Skip to content

Commit be8fcdc

Browse files
committed
feat(launch): execute local engine runs
1 parent 1e168d8 commit be8fcdc

19 files changed

Lines changed: 792 additions & 15 deletions

File tree

docs/codealmanac-launch/next-agent-brief.md

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,23 @@ verification, launch-folder updates, commit, and push.
1010

1111
## Last Completed Slice
1212

13-
Slice 12 added deterministic local commit delivery.
13+
Slice 13 added local engine execution.
1414

1515
Implemented:
1616

17-
- `app.deliveries`
18-
- `app.workflows.local_delivery.deliver(...)`
19-
- native Git delivery adapter for expected-head reads, wiki-only patch
20-
collection, patch application, and commit creation
21-
- moved-head handling: skip delivery and mark the run `stale`
22-
- empty-diff handling: skip delivery and mark the run `succeeded`
23-
- worker workspace path lookup by run id
17+
- `app.workflows.local_engine.execute(...)`
18+
- update-operation prompt at `src/codealmanac/prompts/operations/update.md`
19+
- local engine result helpers for deterministic `docs almanac:` subjects
20+
- normalized run-event recording for harness events
21+
- success path: request artifact -> harness run in worker repo -> result
22+
artifact -> `result_ref` on the control run
23+
- failure path: failed harness or missing prepared request -> failed control
24+
run and failed engine result when possible
2425

2526
Verified:
2627

2728
```text
28-
uv run pytest tests/test_deliveries_service.py tests/test_local_delivery_workflow.py tests/test_git_local_delivery.py tests/test_worker_workspaces_service.py tests/test_architecture.py
29+
uv run pytest tests/test_local_engine_workflow.py tests/test_engine_runs_service.py tests/test_architecture.py
2930
uv run pytest
3031
uv run ruff check .
3132
git diff --check
@@ -38,16 +39,18 @@ Choose the next substantial slice from the launch plan. Good candidates:
3839
- local trigger event recording through Git hooks
3940
- public or hidden setup command that calls `app.local_hooks`
4041
- local run storage bridge from repo-local job files to the control DB
41-
- local model worker execution from prepared `EngineRunRequest`
42+
- local worker orchestration that chains prepare -> engine -> delivery
43+
- prompt restoration / first-build `init` path from
44+
`docs/codealmanac-launch/init-first-build-prompt-restoration.md`
4245

4346
Before coding, write the next slice plan under `docs/plans/`, then implement
4447
the full slice, update this brief, update `progress.md`, send a RelayForge
4548
progress update, commit, and push.
4649

4750
## Known Repo State
4851

49-
The branch is `dev`. At the start of Slice 12 it was clean and even with
50-
`origin/dev`.
52+
The branch is `dev`. At the end of Slice 13 verification it was ready to
53+
commit on top of `origin/dev`.
5154

5255
The local wiki command currently fails on this checkout with:
5356

docs/codealmanac-launch/ownership-map.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Owns:
1616
- local capture storage
1717
- local Git hook dispatchers
1818
- local worker workspace creation
19+
- local engine execution
1920
- deterministic local delivery
2021
- auto-update client behavior
2122

@@ -74,4 +75,3 @@ engine result
7475
```
7576

7677
Both cloud and local workers call this boundary.
77-

docs/codealmanac-launch/progress.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Percentages are planning estimates, not accounting metrics.
88

99
## Latest RelayForge Update
1010

11-
Sent: 2026-07-02 after Slice 12 verification.
11+
Sent: pending after Slice 13 verification.
1212

1313
Route:
1414

@@ -26,7 +26,7 @@ It was not present in `codealmanac/prd` when checked.
2626

2727
| Area | Latest | Previous | Basis |
2828
| --- | ---: | ---: | --- |
29-
| CodeAlmanac backend/local | 58% | 53% | Slice 12 added deterministic local commit delivery from worker repo patches with expected-head checks. |
29+
| CodeAlmanac backend/local | 63% | 58% | Slice 13 added local engine execution from prepared request/source/workspace artifacts through the harness boundary. |
3030
| CodeAlmanac CLI/public UX | 10% | 10% | Hidden trigger command exists; launch public CLI surface is not rebuilt yet. |
3131
| CodeAlmanac-hosted backend/auth/API | 8% | 8% | WorkOS/Doppler setup and hosted rename groundwork exist; public API migration is not implemented yet. |
3232
| Hosted frontend/onboarding | 5% | 5% | Existing frontend is deployed under CodeAlmanac; new onboarding/configuration screens are not implemented yet. |

docs/codealmanac-launch/verification-matrix.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,16 @@ Current evidence:
132132
root.
133133
- `tests/test_architecture.py` proves Git delivery mechanics stay in
134134
`integrations/workspaces/git/delivery.py`, not in the workflow.
135+
- Slice 13 added local engine execution.
136+
- `tests/test_local_engine_workflow.py` proves the workflow reads a prepared
137+
engine request, runs the harness in the worker repo, writes `result.json`,
138+
stores `result_ref`, and records normalized run events.
139+
- `tests/test_local_engine_workflow.py` proves failed harness runs mark the
140+
control run `failed` and write a failed engine result.
141+
- `tests/test_local_engine_workflow.py` proves a missing prepared request fails
142+
the control run without invoking the harness.
143+
- `tests/test_architecture.py` proves local engine execution stays separate
144+
from Git delivery, subprocess mechanics, SQL, and CLI strings.
135145

136146
Commands:
137147

docs/codealmanac-launch/worklog.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,3 +261,23 @@
261261
`uv run pytest tests/test_deliveries_service.py tests/test_local_delivery_workflow.py tests/test_git_local_delivery.py tests/test_worker_workspaces_service.py tests/test_architecture.py`.
262262
- Verified Slice 12 full gate with `uv run pytest` (`407 passed`),
263263
`uv run ruff check .`, and `git diff --check`.
264+
- Sent the Slice 12 RelayForge update and recorded progress as:
265+
CodeAlmanac backend/local 58%, CLI/public UX 10%,
266+
CodeAlmanac-hosted backend/auth/API 8%, hosted frontend/onboarding 5%, and
267+
infra/deploy rename 5%.
268+
- Planned Slice 13 in
269+
`docs/plans/2026-07-02-slice-13-local-engine-execution.md`.
270+
- Added `app.workflows.local_engine.execute(...)`.
271+
- Added `src/codealmanac/workflows/local_engine/` with request/result models,
272+
update prompt rendering, deterministic result helpers, and run-event
273+
recording helpers.
274+
- Added `src/codealmanac/prompts/operations/update.md`.
275+
- Wired local engine execution through the existing harness seam:
276+
`RunHarnessRequest(kind, cwd, prompt, title)`.
277+
- The local engine now reads prepared `request.json`, runs the model in the
278+
worker repo, writes `result.json`, stores `result_ref`, and leaves delivery
279+
to `app.workflows.local_delivery`.
280+
- Verified Slice 13 focused behavior with
281+
`uv run pytest tests/test_local_engine_workflow.py tests/test_engine_runs_service.py tests/test_architecture.py`.
282+
- Verified Slice 13 full gate with `uv run pytest` (`411 passed`),
283+
`uv run ruff check .`, and `git diff --check`.
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Slice 13 Plan: Local Engine Execution
2+
3+
Status: planned.
4+
Date: 2026-07-02.
5+
6+
## Intent
7+
8+
Complete the middle of the local launch pipeline:
9+
10+
```python
11+
prepared = app.workflows.local_runs.prepare_next()
12+
engine = app.workflows.local_engine.execute(run_id, harness)
13+
delivery = app.workflows.local_delivery.deliver(run_id)
14+
```
15+
16+
Slice 13 does not expose a public CLI command. It adds the backend workflow that
17+
cloud and local orchestration can call without going through human CLI strings.
18+
19+
## Product Contract
20+
21+
- The worker receives sources by reference through `sources_path`.
22+
- The model runs inside the prepared worker repo, not the user's active checkout.
23+
- The model may edit only the configured Almanac root.
24+
- The engine writes `~/.codealmanac/runs/<run-id>/result.json`.
25+
- The engine records normalized `run_events` in `~/.codealmanac/control.sqlite`.
26+
- The engine does not commit, merge, open PRs, or deliver changes.
27+
- Delivery remains deterministic and separate.
28+
29+
## Code Shape
30+
31+
```python
32+
result = app.workflows.local_engine.execute(
33+
ExecuteLocalEngineRunRequest(run_id=run.id, harness=HarnessKind.CODEX)
34+
)
35+
```
36+
37+
Ownership:
38+
39+
- `workflows/local_engine/` owns orchestration for executing a prepared engine
40+
request.
41+
- `services/engine_runs/` continues to own request/result artifacts.
42+
- `services/harnesses/` continues to own provider-neutral model execution.
43+
- `workflows/local_delivery/` remains the only local writer to the real
44+
checkout.
45+
46+
## Implementation Scope
47+
48+
Add:
49+
50+
- `src/codealmanac/workflows/local_engine/`
51+
- `requests.py`
52+
- `models.py`
53+
- `prompt.py`
54+
- `service.py`
55+
- `__init__.py`
56+
- `src/codealmanac/prompts/operations/update.md`
57+
- `PromptName.OPERATION_UPDATE`
58+
- `app.workflows.local_engine`
59+
- tests for success, failure, and event/result recording
60+
61+
The workflow should:
62+
63+
1. Read the control run and prepared `EngineRunRequest`.
64+
2. Mark the control run `running`.
65+
3. Render an update prompt with the request JSON as runtime context.
66+
4. Run the requested harness with `cwd=request.repo_path`.
67+
5. Append normalized harness events to `run_events`.
68+
6. Write an `EngineRunResult`.
69+
7. Store `result_ref` on the control run.
70+
8. On harness failure, write a failed engine result, mark the run `failed`, and
71+
append an error event.
72+
73+
## Out Of Scope
74+
75+
- Public CLI command surface.
76+
- Cloud worker execution.
77+
- WorkOS/API/auth changes.
78+
- Delivery changes.
79+
- Parsing a commit subject out of model prose.
80+
81+
## Verification
82+
83+
Focused:
84+
85+
```bash
86+
uv run pytest tests/test_local_engine_workflow.py tests/test_engine_runs_service.py tests/test_architecture.py
87+
```
88+
89+
Full gate:
90+
91+
```bash
92+
uv run pytest
93+
uv run ruff check .
94+
git diff --check
95+
```
96+
97+
## Architecture Notes
98+
99+
The workflow can deterministically derive a commit subject from the harness
100+
summary:
101+
102+
```text
103+
docs almanac: <summary>
104+
```
105+
106+
If no usable summary exists, use:
107+
108+
```text
109+
docs almanac: update wiki
110+
```
111+
112+
The prompt should still instruct the model to produce a concise summary, but
113+
the Python code should not scrape durable fields out of unstructured final
114+
assistant text.

src/codealmanac/app.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
from codealmanac.workflows.lifecycle import LifecycleMutationPolicy
7979
from codealmanac.workflows.local_delivery import LocalDeliveryWorkflow
8080
from codealmanac.workflows.local_delivery.ports import LocalGitDeliveryManager
81+
from codealmanac.workflows.local_engine import LocalEngineWorkflow
8182
from codealmanac.workflows.local_runs import LocalRunPreparationWorkflow
8283
from codealmanac.workflows.page_run import PageRunWorkflow
8384
from codealmanac.workflows.run_queue import RunQueueWorkflow
@@ -92,6 +93,7 @@ class CodeAlmanacWorkflows:
9293
garden: GardenWorkflow
9394
queue: RunQueueWorkflow
9495
local_runs: LocalRunPreparationWorkflow
96+
local_engine: LocalEngineWorkflow
9597
local_delivery: LocalDeliveryWorkflow
9698
sync: SyncWorkflow
9799

@@ -230,6 +232,12 @@ def create_app(
230232
source_bundles,
231233
engine_runs,
232234
)
235+
local_engine = LocalEngineWorkflow(
236+
control,
237+
engine_runs,
238+
harnesses,
239+
prompts,
240+
)
233241
local_delivery = LocalDeliveryWorkflow(
234242
control,
235243
deliveries,
@@ -244,6 +252,7 @@ def create_app(
244252
garden=garden,
245253
queue=queue,
246254
local_runs=local_runs,
255+
local_engine=local_engine,
247256
local_delivery=local_delivery,
248257
sync=sync,
249258
)

src/codealmanac/prompts/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ class PromptName(StrEnum):
77
BASE_SYNTAX = "base/syntax.md"
88
OPERATION_INGEST = "operations/ingest.md"
99
OPERATION_GARDEN = "operations/garden.md"
10+
OPERATION_UPDATE = "operations/update.md"
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Update Operation
2+
3+
Update refreshes the configured Almanac wiki after a finalization event on a
4+
configured branch.
5+
6+
Before editing, read `manual/README.md`, `manual/pages.md`,
7+
`manual/evidence.md`, `manual/style.md`, and `manual/sources.md` under the
8+
configured Almanac root when those files exist.
9+
10+
Use the runtime context as the execution contract. The repository checkout is
11+
already positioned at the expected head SHA. The `sources_path` directory
12+
contains source material by reference. Read `sources_path/manifest.json`, then
13+
read the full session files or other referenced files that are relevant to the
14+
update.
15+
16+
Do not copy source material into the wiki. Distill durable project knowledge:
17+
decisions, flows, invariants, incidents, gotchas, and source-backed changes
18+
that help future agents. Update existing pages when they are the right home.
19+
Create new pages only when the material names a stable concept that deserves
20+
one.
21+
22+
Only edit files under the configured Almanac root. Do not commit, open a pull
23+
request, modify delivery state, or edit files outside the configured Almanac
24+
root. Delivery is handled after this engine run.
25+
26+
End with a concise one-line summary of the wiki change. The commit subject will
27+
be derived from that summary using the configured `docs almanac:` style.

src/codealmanac/services/engine_runs/service.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from codealmanac.core.errors import NotFoundError
22
from codealmanac.services.engine_runs.models import (
3+
EngineRunArtifactPaths,
34
EngineRunRequest,
45
EngineRunResult,
56
PreparedEngineRun,
@@ -16,6 +17,9 @@ class EngineRunsService:
1617
def __init__(self, store: EngineRunsStore):
1718
self.store = store
1819

20+
def paths(self, run_id: str) -> EngineRunArtifactPaths:
21+
return self.store.paths(run_id)
22+
1923
def prepare(self, request: PrepareEngineRunRequest) -> PreparedEngineRun:
2024
paths = self.store.paths(request.run_id)
2125
engine_request = EngineRunRequest(

0 commit comments

Comments
 (0)