okstra 0.137.0 → 0.138.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/architecture.md +3 -2
- package/docs/contributor-change-matrix.md +1 -1
- package/docs/project-structure-overview.md +24 -2
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/antigravity-worker.md +1 -1
- package/runtime/agents/workers/codex-worker.md +1 -1
- package/runtime/prompts/lead/adapters/claude-code.md +1 -0
- package/runtime/prompts/lead/adapters/codex.md +1 -0
- package/runtime/prompts/lead/adapters/external.md +1 -0
- package/runtime/prompts/lead/report-writer.md +11 -10
- package/runtime/prompts/lead/team-contract.md +4 -2
- package/runtime/prompts/profiles/_implementation-diff-review.md +1 -1
- package/runtime/prompts/profiles/_implementation-executor.md +2 -2
- package/runtime/prompts/profiles/_implementation-self-check.md +1 -1
- package/runtime/python/okstra_ctl/codex_dispatch.py +158 -365
- package/runtime/python/okstra_ctl/dispatch_core.py +118 -138
- package/runtime/python/okstra_ctl/initial_prompt_materialization.py +1053 -0
- package/runtime/python/okstra_ctl/render.py +9 -4
- package/runtime/python/okstra_ctl/run.py +40 -89
- package/runtime/python/okstra_ctl/stage_targets.py +232 -46
- package/runtime/python/okstra_ctl/wizard.py +2 -2
- package/runtime/python/okstra_ctl/worker_prompt_contract.py +73 -0
- package/runtime/python/okstra_ctl/worktree.py +37 -29
- package/runtime/validators/lib/fixtures.sh +2 -0
package/docs/architecture.md
CHANGED
|
@@ -312,7 +312,7 @@ The same analysis-core rule applies to `requirements-discovery`, `error-analysis
|
|
|
312
312
|
|
|
313
313
|
The policy selects one audience preamble: analysis uses `templates/worker-prompt-preamble.md`; executor and verifier use `templates/implementation-worker-preamble.md`; report writing uses `templates/report-writer-prompt-preamble.md`. Every initial audience also reads the shared `templates/worker-error-contract.md`. Only implementation executor/verifier prompts receive `**Coding preflight pack:**`; a report writer never loads implementation coding instructions.
|
|
314
314
|
|
|
315
|
-
`dispatch_core.py
|
|
315
|
+
`initial_prompt_materialization.py` is the sole owner of roster-derived initial prompt rendering, request compatibility checks, contract validation, and immutable publication. `dispatch_core.py` and `codex_dispatch.py` select workers and pass delivery capabilities; Phase 7 `validators/validate-run.py` revalidates the persisted artifacts through the same `worker_prompt_contract`. Report-writer prompts still receive individual common-anchor validation, while `-reverify-r<N>-` prompts keep their separate lightweight convergence contract.
|
|
316
316
|
|
|
317
317
|
Final-verification uses one shared full-core responsibility for every selected initial analysis worker. Provider/model diversity supplies independent observations of the same requirements; it does not split acceptance criteria into disjoint worker scopes. `analysis-packet.md` carries the worker-facing verification procedure, while report-only deliverable and self-review guidance stays with the report writer.
|
|
318
318
|
|
|
@@ -426,6 +426,7 @@ Common constraints:
|
|
|
426
426
|
- **Isolated worktree for pre-implementation non-implementation phases (BLOCKING)**: The first pre-implementation non-implementation phase prepare creates a task-key `git worktree` through `okstra-ctl`. Pre-implementation non-implementation phases reuse the task-key worktree: `requirements-discovery` → `error-analysis` → `implementation-planning` use the same worktree and branch for the same task key. `implementation` does not reuse this task-key worktree; implementation uses a dedicated stage-specific worktree and branch for every stage/run, as described in the next item. The task-key worktree lives at `~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>/` (special characters such as `/` and `:` in segments are normalized to `-`), and the branch is named `<work-category-namespace>/<task-id-segment>` (for example, `feature/dev-9436` or `fix/dev-7311`). The namespace is derived from work_category (`feature`·`improvement`→`feature/`, `bugfix`→`fix/`, `refactor`→`refactor/`, `ops`→`ops/`, unspecified→`task/`). The work_category itself is resolved by `work_categories.resolve_work_category` as **explicit `--work-category` → the classification recorded in `task-manifest.json` → `feature`**, so the `task/` fallback is only reached when a task has no recorded classification at all; a run that omits the flag still inherits the namespace `requirements-discovery` classified. The base ref is the commit selected by the user's `--base-ref` during the first phase's prepare. `~/.okstra/worktrees/registry.json` (guarded by flock) globally manages task-key → path/branch mappings to prevent path and branch collisions during concurrent runs. Configured sync directories are linked from the main worktree as symlinks to provide filesystem continuity across task checkouts (the sync list can be overridden by `worktreeSyncDirs` in `project.json` or the `OKSTRA_WORKTREE_SYNC_DIRS` environment variable; an empty array disables syncing). This sync does not expand the okstra context/write boundary. Provisioning is skipped when the caller is already inside another worktree or project_root is not a Git repository, and the executor works directly from project_root. The worktree is not automatically deleted after a run; it is the authoritative artifact for later phases, PR authoring, and rollback verification. Manual cleanup: `git -C <main-worktree> worktree remove <path>` → `git -C <main-worktree> branch -D <branch>` + remove the registry entry. See the *Task worktree* block in `prompts/profiles/implementation.md` and the *Task worktree (BLOCKING for every task-type)* section in `prompts/lead/okstra-lead-contract.md` for details.
|
|
427
427
|
- **Isolated implementation-stage worktrees (concurrent parallelism)**: The task-key worktree above is the model for `requirements-discovery` through `implementation-planning`. `implementation` tasks use **stage isolation**: **one run = one stage**, and every run receives an isolated worktree at `.../<task-id-segment>/stage-<N>/` (branch `<work-category-namespace>/<task-id-segment>-s<N>`). The registry reserves task keys and **stage keys** (`<task-key>#stage-<N>`) together under flock. The Stage Lifecycle Snapshot reads `done`/`started` entries in `consumers.jsonl`, carry-sidecar backfills, and reserved registry stages together, and removes them from the ready set (occupancy SSOT = registry). Thus, if the user starts two `implementation` runs simultaneously, they proceed on different independent stages without collision. Base selection: independent = common anchor (HEAD fixed at entry to the first stage); single dependency = predecessor's done commit; multiple dependencies = task worktree HEAD only if every predecessor is an ancestor (`git merge-base --is-ancestor`; otherwise `PrepareError`). The cost-aware-design ready-set batch has been retired because each stage needs an isolated branch and reserving two stage keys on one branch creates a branch-uniqueness collision, so it offers no benefit: sequential work uses the next run after a stage is done, and concurrent work uses separate runs, at equivalent cost. Select a stage with `--stage <auto|N>` or the wizard's `stage_pick`. The wizard's `stage_pick` is a multiselect that labels each stage with its state (`mark_done`/`mark_active`/`mark_ready`/`mark_blocked`), topologically sorts the dependency closure of the selection with Kahn's algorithm (`stage_targets.order_stage_closure`), and exports it as the `chain-stages` CSV in render-args. The `okstra-run` SKILL consumes this queue and sequentially executes N single-stage runs in dependency order as an unattended chain, advancing only after checking the Phase 6 `done` row for each stage. This is an orchestration layer only; the **one run = one stage** isolation invariant of the wizard and prepare remains unchanged. Not only worktrees but also **run artifacts (reports, state, worker results, manifests) are isolated per stage under `runs/implementation/stage-<N>/`**, so reports and state from two concurrently running stages do not mix. In contrast, `consumers.jsonl` and the worktree registry remain at the task-type root (`runs/implementation/`) because they are shared coordination sources of truth across stages.
|
|
428
428
|
- **Isolation of single-stage final-verification run artifacts (concurrent parallelism)**: Single-stage `final-verification` (`--stage <N>`) also isolates run artifacts under `runs/final-verification/stage-<N>/`, like implementation, with independent sequences per stage, and appends `-fv-s<N>` to the team name. The `-fv-` delimiter prevents collisions with the same stage's implementation team (`-s<N>`) and with the default whole-task verification name. Thus, final-verification for multiple stages can run concurrently without mixing state, worker results, reports, or teams. It does not create a new worktree; it reuses the corresponding implementation stage worktree from the registry read-only and therefore does not reserve a registry stage key. The `-fv-s<N>` suffix on the `teamName` label is only for audit/display distinction. The actual team is the per-session implicit team (`session-<leadSid>`), so the pre-v2.1.178 hard failure caused by a `TeamCreate` name collision no longer occurs. Whole-task verification (empty stage value) retains the existing flat `runs/final-verification/` structure.
|
|
429
|
+
- **Final-verification target acquisition seam**: `stage_targets.acquire_final_verification_target()` accepts semantic task identity, the approved plan, the normalized Stage Map, and `stage: int | None`; it derives ledger, registry, worktree, Git, and integration facts behind one task-key `worktree_provision_mutex`. Single-stage acquisition is read-only and whole-task acquisition integrates and tears down completed stage worktrees. `run.py` remains the adapter that converts CLI values, builds render-context fields, computes the diff summary, and writes the target snapshot. The container keeps using the locked `resolve_and_integrate_whole_task()` interface; both interfaces share an internal unlocked implementation so the acquisition path never re-enters the non-reentrant task-key mutex.
|
|
429
430
|
- Every phase except `implementation` and `release-handoff` prohibits source-code edits, builds, migrations, deployments, and other state-mutating commands (`final-verification` permits read-only test commands only). `implementation` allows edits/commits only within the approved plan's file list; `git push`, publish, deploy, real migration, and third-party write APIs remain prohibited. `release-handoff` does not modify source code and executes only the commit / push / PR commands selected by the user in the menu (force push, direct push to the base branch, hook bypass, and release publication remain prohibited).
|
|
430
431
|
- Even if the user says something like "continue to the next step," that statement alone does not automatically begin the next phase. The next phase begins only with a new `okstra.sh` execution.
|
|
431
432
|
- **Authority & permissions assumption (shared by every task type and `okstra-schedule-gen`)**: Assume that the user and team have full authority and approval authority for every anticipated action. Do not include external approvals, third-party access, role/IAM permissions, organizational sign-off, legal/security review, vendor coordination, or questions about whether permission is held in routing decisions, missing inputs, clarification questions, risks, dependencies, open questions, or effort/day estimates. Internal okstra phase handoffs such as the `approved:` frontmatter in `implementation-planning` are gates the user can approve immediately and are unaffected. Forbidden `implementation` actions such as `git push`, production deployment, and shared-DB migration also remain prohibited for **safety reasons**, not permission reasons.
|
|
@@ -481,7 +482,7 @@ For mixed or multi-item requests, requirements-discovery splits the request into
|
|
|
481
482
|
|
|
482
483
|
### Worktree preview at the confirm step
|
|
483
484
|
|
|
484
|
-
The okstra-run wizard does not add a separate branch-confirmation step. Instead, the final summary block (`confirmation_block`) immediately before `confirm` shows one `worktree` line indicating "create a new branch/worktree vs reuse the current worktree." The decision is previewed through the side-effect-free `worktree.preview_worktree_decision()`, and `provision_task_worktree` uses the same helper during execution, so preview and reality match. Because `implementation` uses stage isolation, the preview reflects the stage worktree the current run will actually use rather than the task-key directory (`
|
|
485
|
+
The okstra-run wizard does not add a separate branch-confirmation step. Instead, the final summary block (`confirmation_block`) immediately before `confirm` shows one `worktree` line indicating "create a new branch/worktree vs reuse the current worktree." The decision is previewed through the side-effect-free `worktree.preview_worktree_decision()`, and `provision_task_worktree` uses the same helper during execution, so preview and reality match. Because `implementation` uses stage isolation, the preview reflects the stage worktree the current run will actually use rather than the task-key directory (`resolve_stage_worktree_decision`; stage `auto` uses `compute_worktree_path`). `provision_stage_worktree` re-runs that decision at execution time. `final-verification` omits the worktree line because it reuses a stage worktree read-only. `confirm` offers three options: `Proceed`/`Edit`/`Abort`. `Edit` rewinds to any step, including base-ref selection. `Abort` is terminal: state is fixed as `aborted`, subsequent `next_prompt` calls return only `kind: "aborted"`, and `render-args` rejects the request with `ok: false`.
|
|
485
486
|
|
|
486
487
|
|
|
487
488
|
---
|
|
@@ -11,6 +11,6 @@ Use this matrix before changing high-risk repo contracts. Update the source file
|
|
|
11
11
|
| Add phase | `scripts/okstra_ctl/workflow.py`, `prompts/profiles/`, `validators/`, `tests/` | workflow and validation contract tests |
|
|
12
12
|
| Change worker roster | `prompts/profiles/*.md`, `scripts/okstra_ctl/workers.py`, `tests/contract/test_repo_contracts.py` | worker roster contract tests |
|
|
13
13
|
| Change report section | `schemas/final-report-v1.0.schema.json`, `templates/reports/final-report.template.md`, `scripts/okstra_ctl/render_final_report.py`, `validators/validate-run.py` | final-report schema, renderer, and validator tests |
|
|
14
|
-
| Maintain Korean review mirrors | `config/korean-sources.json`, `tools/korean-sources
|
|
14
|
+
| Maintain Korean review mirrors | `config/korean-sources.json`, `tools/korean-sources/` (`lifecycle.mjs` plus its `lifecycle-*.mjs` support modules, CLI/hooks adapters, and shared workflow), `.agents/skills/sync-korean-sources/`, `.claude/skills/sync-korean-sources/` | `tests-js/korean-sources-*.test.mjs` (`lifecycle`, `cli`, `hooks`, and `skill`) |
|
|
15
15
|
|
|
16
16
|
`runtime/` is build output. Never edit it directly; change source files and rebuild the runtime payload instead.
|
|
@@ -230,9 +230,9 @@ Important modules:
|
|
|
230
230
|
|
|
231
231
|
| Module | Role |
|
|
232
232
|
|---|---|
|
|
233
|
-
| `run.py` | `prepare_task_bundle()` single authority and CLI parser; for final-verification it
|
|
233
|
+
| `run.py` | `prepare_task_bundle()` single authority and CLI parser; for final-verification it adapts CLI stage input into `FinalVerificationTargetRequest`, maps the acquired target into render context, and owns `verification-target.md` snapshot/digest materialization before manifests and prompts are rendered |
|
|
234
234
|
| `implementation_stage.py` | `implementation` single-stage run orchestration — read the Stage Lifecycle Snapshot → pick an available Stage Map entry → provision an isolated stage worktree → publish the selected stage as run context (extracted from `run.py`) |
|
|
235
|
-
| `stage_targets.py` | Stage readiness/verification policy SSOT — from the Stage Lifecycle Snapshot (`consumers.jsonl` ledger + carry sidecar backfill + active registry reservation) it decides which stage is runnable, which commit it branches from, and what final-verification checks. `order_stage_closure` topologically sorts (Kahn) the dependency closure of the wizard's multi-selected stage set to produce the unattended `chain-stages` chaining order |
|
|
235
|
+
| `stage_targets.py` | Stage readiness/verification policy SSOT — from the Stage Lifecycle Snapshot (`consumers.jsonl` ledger + carry sidecar backfill + active registry reservation) it decides which stage is runnable, which commit it branches from, and what final-verification checks. `acquire_final_verification_target()` acquires the ledger, registry, worktree, Git, and optional whole-task integration facts behind one task-key mutex and returns a typed target without render-context coupling. `order_stage_closure` topologically sorts (Kahn) the dependency closure of the wizard's multi-selected stage set to produce the unattended `chain-stages` chaining order |
|
|
236
236
|
| `stage_fix_carry.py` | fix-run carry derivation for a re-run on an `implementation` stage whose latest final-report data.json carries verifier `FAIL` verdicts — collects the previous report path, previous run HEAD, failed verifiers, carried blocking findings, and a routing recommendation, which `run.py` renders into the analysis profile through the `{{FIX_RUN_CONTEXT}}` token. A first run, or a re-run after `PASS`, yields no carry and renders the token empty |
|
|
237
237
|
| `stage_reconcile.py` | best-effort git reconciliation shared by the stage prepare flow (delegates to `git_reconcile.auto_reconcile`; advisory — failures are only reported to stderr, the dependency gate stays authoritative) |
|
|
238
238
|
| `design_surfaces.py` | deterministic detection of an `implementation-planning` stage's design surface — matches the stage's file-path tokens/suffixes/patterns and action wording via `SurfaceRule` to derive which design input the stage needs among domain contract, DB/table schema, external interface, transaction/consistency, transformation mapping, lifecycle, rollout/observability, and manual user test, plus its evidence (`TriggerEvidence`). An unmappable structure raises `DesignSurfaceError` |
|
|
@@ -296,6 +296,7 @@ Important modules:
|
|
|
296
296
|
| `report_language.py` | report-writer `**Report Language:**` resolution (`resolve_report_language`) — precedence project config → global config → task-brief inference, shared by both dispatchers so the stamped language does not depend on which dispatch path ran |
|
|
297
297
|
| `worker_prompt_policy.py` | `PromptPlan` generating SSOT — resolves functional audience, equality group, packet-only input, coding-preflight eligibility, required headers, and size limits without consulting provider/model identity |
|
|
298
298
|
| `worker_prompt_contract.py` | deterministic cross-task initial-prompt validator and normalized cross-worker equality SSOT, reused by dispatch adapters and the Phase 7 persisted-artifact validator |
|
|
299
|
+
| `initial_prompt_materialization.py` | sole owner of roster-derived initial prompt rendering, request compatibility checks, contract validation, and immutable create-if-absent publication; exposes `materialize_initial_prompts(InitialPromptMaterializationRequest) -> tuple[Path, ...]` |
|
|
299
300
|
| `convergence_engine.py` | pure `ConvergenceEngine` reducer — seeds Round 0 working state, plans roster-aware rounds, applies structured outcomes and one critic-gap batch, finalizes schema v1.3, and validates replayable state without dispatch or filesystem ownership |
|
|
300
301
|
| `convergence_store.py`, `convergence_migration.py` | atomic JSON persistence plus legacy/new-engine seed decisions; valid terminal finals are reused, while invalid state requires byte-preserving archival before restart |
|
|
301
302
|
| `convergence.py` | `okstra convergence` internal CLI orchestration for `seed`, `plan-round`, `apply-round`, `apply-critic-gaps`, `finalize`, `validate`, and `example`; it composes the reducer, store, and migration policy without duplicating their decisions |
|
|
@@ -411,6 +412,27 @@ The neutral lead lifecycle contract lives at `prompts/lead/okstra-lead-contract.
|
|
|
411
412
|
- `tests/`: pytest modules, layered into per-domain subfolders — `run/` (prepare/dispatch/run-index core), `contract/` (validator, repo/docs contract, phase rules, profile), `report/` (render, convergence, language, template), `inspect/` (recap, error, context-cost, token-usage), `worktree/` (worktree, stage isolation, reconcile, reclaim), `wizard/`, `handoff/`. The shared path SSOT is `tests/_paths.py` (`REPO_ROOT`/`TESTS_DIR`/`FIXTURES`), and the setting that puts `tests/` on the import path is the repo-root `pytest.ini` (`pythonpath = tests`). Fixtures live in `tests/fixtures/`.
|
|
412
413
|
- `tests-e2e/`: `scenario-<id>-<name>.sh` shell scenarios (record-start/reconcile, rerun, task lock, agent install, report view, etc.).
|
|
413
414
|
|
|
415
|
+
### 4.13 `tools/korean-sources/`
|
|
416
|
+
|
|
417
|
+
The maintainer-only Korean review-mirror lifecycle has one stateful public
|
|
418
|
+
boundary: `lifecycle.mjs`. `cli.mjs` and `hooks.mjs` are adapters that call it;
|
|
419
|
+
they do not reconstruct observations or transitions. `config.mjs` and
|
|
420
|
+
`markdown.mjs` remain pure configuration and protected-Markdown validators.
|
|
421
|
+
|
|
422
|
+
| File | Role |
|
|
423
|
+
|---|---|
|
|
424
|
+
| `lifecycle.mjs` | Public lifecycle seam: bootstrap, inspect, evidence transitions, and reviewed-packet application |
|
|
425
|
+
| `lifecycle-store.mjs` | Versioned lifecycle store, canonical JSON IDs, v1 migration, and repository lock |
|
|
426
|
+
| `lifecycle-observation.mjs` | Current source/mirror snapshots, rename detection, and derived change observations |
|
|
427
|
+
| `lifecycle-evidence.mjs` | Decision, direction, review-packet, semantic-confirmation, and approval validation |
|
|
428
|
+
| `lifecycle-application.mjs` | Allowed packet operations, journaled idempotent apply, and completion verification |
|
|
429
|
+
| `lifecycle-index.mjs` | Korean mirror `.project-docs/INDEX.md` row validation and updates |
|
|
430
|
+
|
|
431
|
+
Maintainers follow `tools/korean-sources/workflow.md` through observation,
|
|
432
|
+
conditional direction, review packet, semantic confirmation, conditional
|
|
433
|
+
approval, and apply. The paired local skills only delegate to that workflow;
|
|
434
|
+
they are not published user skills.
|
|
435
|
+
|
|
414
436
|
---
|
|
415
437
|
|
|
416
438
|
## 5. Key runtime modules
|
package/package.json
CHANGED
package/runtime/BUILD.json
CHANGED
|
@@ -137,7 +137,7 @@ This wrapper does NOT invoke MCP tools directly. MCP availability inside the Ant
|
|
|
137
137
|
- The assigned model execution value is canonical for CLI execution. Do not substitute a different Antigravity model unless the task bundle explicitly changes it.
|
|
138
138
|
- Pass the prompt received from Lead directly to agy after persisting the exact prompt to the assigned path.
|
|
139
139
|
- **Executor preflight forwarding check (implementation runs only).** When the lead prompt assigns this dispatch the `Executor` role for an `implementation` run, the persisted prompt body MUST contain the literal heading `Coding-conventions preflight` (the lead appends the body of `prompts/profiles/_coding-conventions-preflight.md` into the dispatch prompt — see `prompts/profiles/_implementation-executor.md` → "Pre-implementation context exploration") — the Antigravity CLI does not share the lead's context, so an unforwarded gate never reaches the process that writes the code. If the heading is absent, return `ANTIGRAVITY_PREFLIGHT_MISSING: executor dispatch prompt lacks the coding-conventions preflight block` instead of invoking the CLI; the lead is responsible for re-dispatching with the block included. This check does NOT apply to verifier or analysis dispatches.
|
|
140
|
-
- **Executor post-write gate forwarding check (implementation runs only).** For the same reason — the Antigravity CLI does not share the lead's context — an `implementation` `Executor` dispatch prompt MUST also carry the two post-write gate bodies the lead appends after the preflight (via `
|
|
140
|
+
- **Executor post-write gate forwarding check (implementation runs only).** For the same reason — the Antigravity CLI does not share the lead's context — an `implementation` `Executor` dispatch prompt MUST also carry the two post-write gate bodies the lead appends after the preflight (via `okstra_ctl.initial_prompt_materialization.materialize_initial_prompts()`): the persisted prompt body MUST contain BOTH the literal heading `Pre-commit diff review sweep` (from `prompts/profiles/_implementation-diff-review.md`) and the literal heading `Implementation self-check` (from `prompts/profiles/_implementation-self-check.md`). If either heading is absent, return `ANTIGRAVITY_POSTWRITE_GATE_MISSING: executor dispatch prompt lacks the post-write diff-review / self-check gate block` instead of invoking the CLI; the lead re-dispatches with both blocks included. This check does NOT apply to verifier or analysis dispatches.
|
|
141
141
|
- Include context (code, diff, file paths) if provided.
|
|
142
142
|
- For long prompts, dispatch through the wrapper with literal absolute paths (plus the worktree path for implementation phase):
|
|
143
143
|
```bash
|
|
@@ -137,7 +137,7 @@ This wrapper does NOT invoke MCP tools directly. MCP availability inside the Cod
|
|
|
137
137
|
- The assigned model execution value is canonical for CLI execution. Do not substitute a different Codex model unless the task bundle explicitly changes it.
|
|
138
138
|
- Pass the prompt received from Lead directly to codex after persisting the exact prompt to the assigned path.
|
|
139
139
|
- **Executor preflight forwarding check (implementation runs only).** When the lead prompt assigns this dispatch the `Executor` role for an `implementation` run, the persisted prompt body MUST contain the literal heading `Coding-conventions preflight` (the lead appends the body of `prompts/profiles/_coding-conventions-preflight.md` into the dispatch prompt — see `prompts/profiles/_implementation-executor.md` → "Pre-implementation context exploration") — the Codex CLI does not share the lead's context, so an unforwarded gate never reaches the process that writes the code. If the heading is absent, return `CODEX_PREFLIGHT_MISSING: executor dispatch prompt lacks the coding-conventions preflight block` instead of invoking the CLI; the lead is responsible for re-dispatching with the block included. This check does NOT apply to verifier or analysis dispatches.
|
|
140
|
-
- **Executor post-write gate forwarding check (implementation runs only).** For the same reason — the Codex CLI does not share the lead's context — an `implementation` `Executor` dispatch prompt MUST also carry the two post-write gate bodies the lead appends after the preflight (via `
|
|
140
|
+
- **Executor post-write gate forwarding check (implementation runs only).** For the same reason — the Codex CLI does not share the lead's context — an `implementation` `Executor` dispatch prompt MUST also carry the two post-write gate bodies the lead appends after the preflight (via `okstra_ctl.initial_prompt_materialization.materialize_initial_prompts()`): the persisted prompt body MUST contain BOTH the literal heading `Pre-commit diff review sweep` (from `prompts/profiles/_implementation-diff-review.md`) and the literal heading `Implementation self-check` (from `prompts/profiles/_implementation-self-check.md`). If either heading is absent, return `CODEX_POSTWRITE_GATE_MISSING: executor dispatch prompt lacks the post-write diff-review / self-check gate block` instead of invoking the CLI; the lead re-dispatches with both blocks included. This check does NOT apply to verifier or analysis dispatches.
|
|
141
141
|
- Include context (code, diff, file paths) if provided.
|
|
142
142
|
- For long prompts, dispatch through the wrapper with literal absolute paths (plus the worktree path for implementation phase):
|
|
143
143
|
```bash
|
|
@@ -12,6 +12,7 @@ This adapter maps the neutral Okstra lead operations to Claude Code host primiti
|
|
|
12
12
|
| `leadRoleLabel` | `Claude lead` |
|
|
13
13
|
| `userPromptMode` | `native-question` |
|
|
14
14
|
| `workerDispatchBackend` | `team` |
|
|
15
|
+
| `initialPromptDeliveryMode` | `lazy-path-reference` |
|
|
15
16
|
| `sessionAccounting` | `claude-jsonl` |
|
|
16
17
|
| `resumeMode` | `session-id` |
|
|
17
18
|
| `teardownMode` | `teammate-shutdown` |
|
|
@@ -12,6 +12,7 @@ This adapter maps the neutral Okstra lead operations to the Codex artifact-first
|
|
|
12
12
|
| `leadRoleLabel` | `Codex lead` |
|
|
13
13
|
| `userPromptMode` | `host-text` |
|
|
14
14
|
| `workerDispatchBackend` | `cli-wrapper` |
|
|
15
|
+
| `initialPromptDeliveryMode` | `eager-include` |
|
|
15
16
|
| `sessionAccounting` | `artifact-only` |
|
|
16
17
|
| `resumeMode` | `artifact-checkpoint` |
|
|
17
18
|
| `teardownMode` | `process-cleanup` |
|
|
@@ -12,6 +12,7 @@ This adapter maps the neutral Okstra lead operations to a generic host using Oks
|
|
|
12
12
|
| `leadRoleLabel` | `Okstra lead` |
|
|
13
13
|
| `userPromptMode` | `host-text` |
|
|
14
14
|
| `workerDispatchBackend` | `tmux-pane` |
|
|
15
|
+
| `initialPromptDeliveryMode` | `lazy-path-reference` |
|
|
15
16
|
| `sessionAccounting` | `artifact-only` |
|
|
16
17
|
| `resumeMode` | `artifact-checkpoint` |
|
|
17
18
|
| `teardownMode` | `pane-teardown` |
|
|
@@ -28,7 +28,7 @@ Two `frontmatter` approval fields are always emitted with their unset default
|
|
|
28
28
|
4. Call `dispatch_worker(report_writer_assignment, prompt)` through the selected adapter.
|
|
29
29
|
5. Call `await_workers([handle])` and verify both the data.json Result Path and worker-results audit path.
|
|
30
30
|
|
|
31
|
-
The assignment's `modelExecutionValue` feeds both adapter dispatch and the prompt header in item
|
|
31
|
+
The assignment's `modelExecutionValue` feeds both adapter dispatch and the prompt header in item 9 below, so the execution model and recorded `**Model:**` header always agree. Missing or unsupported model resolution is a pre-dispatch contract failure; the common contract does not choose a runtime fallback.
|
|
32
32
|
|
|
33
33
|
The prompt MUST include, in this order at the top:
|
|
34
34
|
|
|
@@ -43,19 +43,20 @@ The prompt MUST include, in this order at the top:
|
|
|
43
43
|
- `**Worker Error Contract Path:** <absolute-path>` — selects `templates/worker-error-contract.md`.
|
|
44
44
|
- `**Errors log path:** <absolute-path>` — run-level errors JSONL (`logs/errors-<task-type>-<seq>.jsonl`).
|
|
45
45
|
- `**Errors sidecar path:** <absolute-path>` — this worker's per-run sidecar JSON (`worker-results/report-writer-worker-errors-<task-type>-<seq>.json`).
|
|
46
|
-
8. `**
|
|
47
|
-
9.
|
|
46
|
+
8. `**Prompt Delivery Mode:** <mode>` — the selected adapter's declared `initialPromptDeliveryMode`.
|
|
47
|
+
9. `**Model:** Report writer worker, <modelExecutionValue>` (resolved per Phase 5.5 anchor-header rules)
|
|
48
|
+
10. The full `[Required reading]` clause (see [team-contract](./team-contract.md)) — for Phase 6 it adds two **per-task-type, instruction-set-local** read-only files, both scoped to this run's task-type by `okstra-ctl` at prep time:
|
|
48
49
|
- `<instruction-set>/final-report-schema.json` — a task-type excerpt of the data.json schema (the other task-types' deliverable blocks and their unreachable `$defs` are stripped; ~38% of the full schema is `$defs` alone). This is your authoring aid for the data.json shape — the installed schema, not the excerpt, is what the run is judged against. Do **NOT** pull the full `schemas/final-report-v1.0.schema.json` — it carries all task-types and its `schemas/...` path is not part of the task bundle. (Validation still runs against the full schema post-hoc via the renderer, so the excerpt never relaxes the contract.)
|
|
49
50
|
- `<instruction-set>/final-report-template.md` — the **phase-stripped** template (every other task-type's §5.x deliverable block removed by `render.py`'s `_strip_phase_blocks`, leaving only your run's §5.x). Do **NOT** also pull the full `templates/reports/final-report.template.md` source (it re-adds ~330 lines of other phases' deliverables and is not in the task bundle).
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
11. A one-line MCP pointer instead of the verbatim block (redundant — the brief is already in the report-writer's Required reading, item 10): `**MCP servers:** follow the task brief's "## Available MCP Servers" section (already in your Required reading).`
|
|
52
|
+
12. The convergence classifications (Full/Partial/Contested/Worker-Unique), the round history data (`roundHistory[]`), the `round2SkippedReason` value, and pointers to all worker result files under `worker-results/`. The report-writer worker populates `crossVerification.roundHistory` in the data.json so Section 6 can show which rounds executed, queue sizes, and why Round 2 was (or was not) skipped. The renderer prints the full per-round table only when more than one round ran; single-round or zero-round histories are auto-collapsed to a one-line summary.
|
|
53
|
+
13. `**Report Language:** <en|ko>` — must be either `en` or `ko`; `auto`
|
|
53
54
|
has been resolved by the lead from project.json / global config
|
|
54
55
|
before the dispatch is constructed. The worker copies this verbatim
|
|
55
56
|
into `data.json.meta.reportLanguage`.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
14. For implementation-planning runs: a literal block listing the 12 required English section headings — `Option Candidates`, `Trade-off`, `Recommended Option`, `Stage Map`, `Stepwise Execution Order`, `Dependency`, `Validation Checklist`, `Rollback`, `Requirement Coverage`, `Plan Body Verification`, `Cross-Project Dependencies`, `Decision Drafts`. This list is `PLANNING_REQUIRED_SECTIONS` in `validators/validate-run.py`; that tuple is the SSOT and this block must match it exactly. The writer uses these exact substrings as section headings (Korean translation in parentheses is allowed), and the `Plan Body Verification` section carries its required `Gate result:` line.
|
|
58
|
+
15. An explicit instruction: `You are the author of TWO files: (a) the final-report data.json at <Result Path>, (b) the worker-results audit file at <Audit sidecar path>. After writing the data.json, invoke "okstra render-final-report <Result Path>" through the available execution interface so the markdown sibling is rendered before you return. Do not return the report inline. The validator fails the run when (a)'s schema validation fails, when the rendered markdown is absent, or when (b) is missing.`
|
|
59
|
+
16. The prose budget (dedup contract): `verdictCard.finalConclusion` is the conclusion SSOT — at most 3 sentences. `rationale.*` fields stay within 2 sentences each and reference the verdict card / row IDs instead of restating their prose; `readerSummary` fields are one line each; `summary` stays at 3-5 rows unless the run covers multiple tickets. The schema field descriptions carry the same budgets (`tests/contract/test_report_prose_budget.py` guards both surfaces). Generation time scales with output volume, so exceeding the budget is a cost bug, not extra diligence.
|
|
59
60
|
|
|
60
61
|
**Fix-run incremental authoring (applies when the run's profile carries a "Fix-Run Carry" block).** Do not author the data.json from scratch. Start by copying the previous run's data.json (the `Previous report` path in the Fix-Run Carry block) to this run's Result Path, then update ONLY the blocks the fix run changed: `meta`/`header` (run seq, dates), `executionStatus`, `implementation.verifierResults`, `implementation.validationEvidence`, `implementation.commitList` / `diffSummary`, `crossVerification`, `verdictCard`, `finalVerdict`, and any `evidence` rows the fix touched. Deliverable prose for unchanged sections is carried forward verbatim — do not re-generate it. Then invoke the renderer exactly as in a full run. The schema validation and renderer contract are unchanged, so an incrementally-authored data.json passes the same post-hoc gates. The lead's dispatch prompt MUST include the previous data.json path when the carry block is present.
|
|
61
62
|
|
|
@@ -286,7 +287,7 @@ Skipping this file because "the real report is in `reports/`" is wrong. Both fil
|
|
|
286
287
|
|
|
287
288
|
### Main Body Section
|
|
288
289
|
|
|
289
|
-
Section numbering follows `templates/reports/final-report.template.md` exactly — that file is the documentation SSOT for section names and ordering. For full body structure at authoring time, consult your run's **phase-stripped** `final-report-template.md` (the per-task-type instruction-set copy defined in Phase 6 dispatch item
|
|
290
|
+
Section numbering follows `templates/reports/final-report.template.md` exactly — that file is the documentation SSOT for section names and ordering. For full body structure at authoring time, consult your run's **phase-stripped** `final-report-template.md` (the per-task-type instruction-set copy defined in Phase 6 dispatch item 10); the "copy that block verbatim" references below mean the §-block as it appears in that stripped copy, not a re-read of the full source.
|
|
290
291
|
|
|
291
292
|
**Verdict Card (top-of-report, mandatory).** Render `## Verdict Card` between the report header and the (conditional) Approval block. Its `Verdict Token` / `Direction` / `Next Step` cells MUST byte-match the corresponding cells in `## 7. Final Verdict` and the first item of `## 3. Recommended Next Steps`. Divergence is `contract-violated`.
|
|
292
293
|
|
|
@@ -63,7 +63,9 @@ Only workers selected from `recommendedWorkers` in `task-manifest.json` and `res
|
|
|
63
63
|
|
|
64
64
|
## Worker Prompt Composition
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
`okstra_ctl.initial_prompt_materialization` is the canonical owner of roster-derived initial prompt rendering, validation, and immutable publication. Code-backed `dispatch_worker` mappings leave missing roster prompts to `materialize_initial_prompts()` and pass the selected adapter's declared `initialPromptDeliveryMode`; they do not compose or overwrite those prompts themselves. Native in-process dispatch uses the same headers and the adapter's declared `lazy-path-reference` mode, persists the prompt before dispatch, and remains outside reverify and critic handling.
|
|
67
|
+
|
|
68
|
+
Every worker prompt MUST start with the anchor headers rendered by `okstra_ctl.worker_prompt_headers.worker_prompt_headers()` (the generating SSOT — never hand-author or reorder them). Every persisted initial prompt also carries exactly one non-empty `**Prompt Delivery Mode:** <mode>` header whose value is `eager-include` or `lazy-path-reference`. Redispatch reuses that persisted initial prompt byte-for-byte; it never regenerates or overwrites it. The generated absolute `**Audit sidecar path:**` is derived by `audit_sidecar_rel()` from the canonical worker result path; workers write to that header and never synthesize a `runs/<task-type>/...` destination. Their meaning and extraction rules for workers are documented in the worker preamble §"Anchor headers". Phase-specific extra headers (implementation worktree, final-verification target snapshot, improvement-discovery grilling log) are listed there too.
|
|
67
69
|
|
|
68
70
|
The `**Coding preflight pack:**` anchor is emitted only for the `implementation-executor` and `implementation-verifier` audiences. An implementation report-writer never receives it. A pane display role named `verifier` during `final-verification` is still an initial analysis worker; it neither receives implementation conventions nor becomes a Phase 5.5 reverify dispatch. Reverify is identified by the `-reverify-r<N>-` prompt/result path contract in [convergence](./convergence.md).
|
|
69
71
|
|
|
@@ -73,7 +75,7 @@ The body must include: role name, task type, task key, assigned model, output co
|
|
|
73
75
|
|
|
74
76
|
A `final-verification` prompt may contain exactly one optional `## Run-specific directive` section for a true run delta. It is limited to 40 nonblank lines; the nonblank prompt body excluding common/target anchors is limited to 96 lines. Larger shared material belongs in the instruction set and analysis packet. Before initial dispatch, the selected adapter removes worker-specific header lines (including optional `**Pane role:**`) and requires the remaining normalized analysis bodies to be byte-identical; the semantic `Primary analysis packet` input remains in that comparison.
|
|
75
77
|
|
|
76
|
-
The Phase 7 run validator enforces the same cross-task rule against the persisted prompt paths recorded by the run manifest, dispatch records, and team-state.
|
|
78
|
+
The Phase 7 run validator enforces the same cross-task rule against the persisted prompt paths recorded by the run manifest, dispatch records, and team-state. `initial_prompt_materialization` validates roster-derived prompts before and after publication, while `validators/validate-run.py` revalidates them through `okstra_ctl.worker_prompt_contract.validate_initial_prompt_records()`. The validator resolves each record through `PromptPlan`, requires the delivery-mode header on every non-reverify initial record, applies audience-specific anchors, compares every equality group with at least two prompts, validates report-writer common anchors without adding it to an analysis group, and ignores `-reverify-r<N>-` prompts because they belong to the lightweight convergence protocol. A dispatch-time bypass therefore remains a run-level contract violation.
|
|
77
79
|
|
|
78
80
|
When a worker reads any project-relative path from the prompt, it MUST resolve it against `Project Root` (e.g. `<Project Root>/<Result Path>`) — never use bare relative paths that depend on cwd.
|
|
79
81
|
|
|
@@ -11,7 +11,7 @@ Same delivery paths as the other executor gates (see _implementation-executor.md
|
|
|
11
11
|
- Claude executor reads this file directly after its last Edit / Write.
|
|
12
12
|
- codex / antigravity executor cannot read this path (outside the CLI sandbox),
|
|
13
13
|
so the lead appends this file's body into the persisted executor prompt at
|
|
14
|
-
dispatch time (see
|
|
14
|
+
dispatch time (see `okstra_ctl.initial_prompt_materialization.materialize_initial_prompts()`).
|
|
15
15
|
The `Pre-commit diff review sweep` heading below is the literal string the CLI
|
|
16
16
|
wrapper's "Executor post-write gate forwarding check" greps for in the persisted
|
|
17
17
|
prompt (agents/workers/_cli-wrapper-template.md → Prompt Composition).
|
|
@@ -24,10 +24,10 @@ until Phase 5 ends, then drop from active context for Phase 6/7.
|
|
|
24
24
|
- **CLI executor (BLOCKING when the executor provider is `codex` or `antigravity`):** the executor CLI process does NOT share the lead's context, and it cannot Read this sidecar's directory — that path sits outside the CLI sandbox and the CLI only sees its stdin prompt, so a file reference never reaches it. The lead MUST physically append the **body** of `_coding-conventions-preflight.md` into the persisted executor prompt at dispatch time: Read the file from the same absolute directory you read this sidecar from, then `Write`/`cat` its body into the persisted prompt. Never hand-retype it. Enforcement: the CLI wrapper agents refuse an implementation-Executor dispatch whose persisted prompt lacks the literal heading `Coding-conventions preflight`, returning `<SENTINEL_PREFIX>_PREFLIGHT_MISSING` (see `agents/workers/_cli-wrapper-template.md` → Prompt Composition).
|
|
25
25
|
- **Pre-commit diff review sweep (BLOCKING — runs AFTER the last `Edit` / `Write`, BEFORE the final commit).** The gate body is a single source at `prompts/profiles/_implementation-diff-review.md` (sibling of this sidecar): an exhaustive file×rule sweep of the actual diff against the conventions the preflight loaded, with fix-in-place and a `Coverage:` footer. Do NOT re-type it from memory — deliver it by file so it cannot drift.
|
|
26
26
|
- **Claude executor:** Read `_implementation-diff-review.md` end-to-end after the stage's last edit, run the sweep over `git diff <stage-base>..HEAD`, fix findings in place, and write its `Coverage:` footer to your audit sidecar before committing.
|
|
27
|
-
- **CLI executor (codex / antigravity):** the CLI process cannot Read this path (outside its sandbox). The lead appends this file's body into the persisted executor prompt at dispatch time, between the preflight body and the self-check body (see `
|
|
27
|
+
- **CLI executor (codex / antigravity):** the CLI process cannot Read this path (outside its sandbox). The lead appends this file's body into the persisted executor prompt at dispatch time, between the preflight body and the self-check body (see `okstra_ctl.initial_prompt_materialization.materialize_initial_prompts()`). The head-less executor honours all three gates from the single prompt.
|
|
28
28
|
- **Completion self-check (BLOCKING — runs BEFORE you claim the stage done).** The gate body is a single source at `prompts/profiles/_implementation-self-check.md` (sibling of this sidecar): the completion gate (diff-review Coverage footer present, functions ≤50 lines, conventions applied, truthful names & why-comments, real build/test run, cleanup). Do NOT re-type it from memory — deliver it by file so it cannot drift.
|
|
29
29
|
- **Claude executor:** Read `_implementation-self-check.md` end-to-end before appending the `status:"done"` row, then write the confirming evidence per item to your audit sidecar.
|
|
30
|
-
- **CLI executor (codex / antigravity):** the CLI process cannot Read this path (outside its sandbox). The lead appends this file's body into the persisted executor prompt at dispatch time, immediately after the diff-review body (see `
|
|
30
|
+
- **CLI executor (codex / antigravity):** the CLI process cannot Read this path (outside its sandbox). The lead appends this file's body into the persisted executor prompt at dispatch time, immediately after the diff-review body (see `okstra_ctl.initial_prompt_materialization.materialize_initial_prompts()`). The head-less executor honours all three gates from the single prompt.
|
|
31
31
|
- **Stage discipline transcription (when a preceding stage is `done`):** the lead MUST transcribe the `Stage discipline` rule (from this run's rendered profile — the INCLUDEd `_stage-discipline.md` body) verbatim into the dispatched CLI executor prompt, so a codex/antigravity executor honors the prior-stage behavior-freeze. Declaration-level — no wrapper sentinel.
|
|
32
32
|
- **Non-interactive auto-execution (BLOCKING when the executor provider is `codex` or `antigravity`).** A CLI executor runs head-less (`codex exec` / antigravity equivalent) — there is no human at the keyboard. Skills loaded during the run (tdd, coding-preflight, and others) contain "get user approval", "state your plan to the user and wait", or "ask before proceeding" gates written for interactive sessions; in this run those gates are **already satisfied** by the upstream `implementation-planning` approval (the plan this stage executes was human-approved). The executor MUST NOT stop to request approval, MUST NOT end its turn after only producing a plan, and MUST carry the stage through end-to-end — RED → GREEN → refactor → per-cycle commit → `### Stage Carry Evidence`. The ONLY skill step to skip is the interactive user-approval prompt itself; every other skill rule (TDD discipline, conventions, real-IO isolation) still binds. The lead MUST transcribe this bullet verbatim into the dispatched CLI executor prompt (same reason as the preflight transcription rule above — the CLI process does not share lead context). Stopping early for approval in a head-less run is the observed empty-exit failure (exit 0, no diff): treat it as `contract-violated`.
|
|
33
33
|
- **Mandatory TDD loop**: BEFORE the first `Edit` or `Write` call, the executor MUST apply a red-green-refactor loop for every code change in this run. This is required; skipping it is a `contract-violated` outcome. This governs HOW each step is executed (failing test first → minimal implementation → refactor); it does not override the approved plan's WHAT/file scope.
|
|
@@ -4,7 +4,7 @@ gate runs BEFORE the first Edit/Write; this gate runs BEFORE the executor claims
|
|
|
4
4
|
done. Same delivery paths: Claude executor reads this file directly; codex /
|
|
5
5
|
antigravity executor cannot read it (outside the CLI sandbox), so the lead
|
|
6
6
|
appends this file's body into the persisted executor prompt at dispatch time
|
|
7
|
-
(see
|
|
7
|
+
(see `okstra_ctl.initial_prompt_materialization.materialize_initial_prompts()`).
|
|
8
8
|
-->
|
|
9
9
|
|
|
10
10
|
# Implementation self-check (BLOCKING — before you claim done)
|