okstra 0.201.3 → 0.204.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/README.md +3 -3
- package/dist/cli-registry.mjs +7 -7
- package/dist/cli-registry.mjs.map +1 -1
- package/dist/commands/lifecycle/install.mjs +50 -124
- package/dist/commands/lifecycle/install.mjs.map +1 -1
- package/dist/commands/lifecycle/setup.mjs +15 -0
- package/dist/commands/lifecycle/setup.mjs.map +1 -1
- package/dist/commands/memory/memory.mjs +41 -8
- package/dist/commands/memory/memory.mjs.map +1 -1
- package/dist/lib/citation-guidance.d.mts +21 -0
- package/dist/lib/citation-guidance.mjs +79 -0
- package/dist/lib/citation-guidance.mjs.map +1 -0
- package/dist/lib/install-assets.mjs +3 -0
- package/dist/lib/install-assets.mjs.map +1 -1
- package/dist/lib/runtime-manifest.mjs +2 -1
- package/dist/lib/runtime-manifest.mjs.map +1 -1
- package/dist/lib/types.d.mts +2 -1
- package/docs/architecture/storage-model.md +17 -10
- package/docs/architecture.md +26 -20
- package/docs/cli.md +16 -13
- package/docs/contributor-change-matrix.md +3 -2
- package/docs/performance-improvement-plan-v2.md +2 -3
- package/docs/project-structure-overview.md +38 -9
- package/docs/task-process/README.md +1 -1
- package/docs/task-process/common-flow.md +1 -1
- package/docs/task-process/final-verification.md +3 -1
- package/docs/task-process/implementation.md +1 -1
- package/docs/task-process/release-handoff.md +36 -39
- package/package.json +1 -2
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/common.json +28 -0
- package/runtime/agents/operations/code-review.json +6 -0
- package/runtime/agents/operations/report-translation.json +6 -0
- package/runtime/agents/operations/schedule-verification.json +6 -0
- package/runtime/agents/roles/analyser.json +18 -0
- package/runtime/agents/roles/critic.json +18 -0
- package/runtime/agents/roles/designer.json +18 -0
- package/runtime/agents/roles/implementer.json +20 -0
- package/runtime/agents/roles/leader.json +20 -0
- package/runtime/agents/roles/planner.json +18 -0
- package/runtime/agents/roles/report-writer.json +19 -0
- package/runtime/agents/roles/translator.json +19 -0
- package/runtime/agents/roles/verifier.json +18 -0
- package/runtime/bin/lib/okstra/usage.sh +5 -5
- package/runtime/prompts/duties/acceptance-critic.json +32 -0
- package/runtime/prompts/duties/acceptance-verifier.json +32 -0
- package/runtime/prompts/duties/analysis-worker.json +32 -0
- package/runtime/prompts/duties/code-reviewer.json +32 -0
- package/runtime/prompts/duties/diagnosis-worker.json +32 -0
- package/runtime/prompts/duties/direction-selection-worker.json +32 -0
- package/runtime/prompts/duties/discovery-worker.json +32 -0
- package/runtime/prompts/duties/implementation-executor.json +32 -0
- package/runtime/prompts/duties/implementation-verifier.json +32 -0
- package/runtime/prompts/duties/lead.json +32 -0
- package/runtime/prompts/duties/planning-worker.json +36 -0
- package/runtime/prompts/duties/report-writer.json +32 -0
- package/runtime/prompts/duties/reverification-worker.json +32 -0
- package/runtime/prompts/duties/schedule-verifier.json +32 -0
- package/runtime/prompts/duties/scope-critic.json +32 -0
- package/runtime/prompts/duties/technical-verification-worker.json +32 -0
- package/runtime/prompts/duties/translator.json +32 -0
- package/runtime/prompts/launch.template.md +3 -2
- package/runtime/prompts/lead/adapters/cmux.md +1 -1
- package/runtime/prompts/lead/convergence.md +4 -4
- package/runtime/prompts/lead/okstra-lead-contract.md +115 -6
- package/runtime/prompts/lead/plan-body-verification.md +6 -6
- package/runtime/prompts/lead/report-writer.md +3 -3
- package/runtime/prompts/profiles/_common-contract.md +2 -2
- package/runtime/prompts/profiles/_implementation-executor.md +4 -1
- package/runtime/prompts/profiles/_implementation-verifier.md +3 -3
- package/runtime/prompts/profiles/change-impact-analysis.json +31 -0
- package/runtime/prompts/profiles/change-impact-analysis.md +0 -20
- package/runtime/prompts/profiles/error-analysis.json +39 -0
- package/runtime/prompts/profiles/error-analysis.md +0 -25
- package/runtime/prompts/profiles/feature-analysis.json +31 -0
- package/runtime/prompts/profiles/feature-analysis.md +0 -20
- package/runtime/prompts/profiles/final-verification.json +30 -0
- package/runtime/prompts/profiles/final-verification.md +3 -22
- package/runtime/prompts/profiles/forbidden-actions.json +4 -3
- package/runtime/prompts/profiles/implementation-option-selection.json +31 -0
- package/runtime/prompts/profiles/implementation-option-selection.md +0 -20
- package/runtime/prompts/profiles/implementation-planning.json +40 -0
- package/runtime/prompts/profiles/implementation-planning.md +6 -29
- package/runtime/prompts/profiles/implementation.json +30 -0
- package/runtime/prompts/profiles/implementation.md +1 -20
- package/runtime/prompts/profiles/improvement-discovery.json +31 -0
- package/runtime/prompts/profiles/improvement-discovery.md +0 -20
- package/runtime/prompts/profiles/project-analysis.json +31 -0
- package/runtime/prompts/profiles/project-analysis.md +0 -20
- package/runtime/prompts/profiles/release-handoff.json +5 -0
- package/runtime/prompts/profiles/release-handoff.md +71 -73
- package/runtime/prompts/profiles/requirements-discovery.json +39 -0
- package/runtime/prompts/profiles/requirements-discovery.md +0 -25
- package/runtime/prompts/profiles/technical-verification.json +39 -0
- package/runtime/prompts/profiles/technical-verification.md +0 -25
- package/runtime/prompts/wizard/prompts.ko.json +12 -17
- package/runtime/python/okstra_ctl/adapters/hosts/antigravity/relay.md +1 -0
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +3 -0
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/manifest.json +1 -1
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +4 -3
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/worker-session.md +108 -0
- package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +1 -0
- package/runtime/python/okstra_ctl/adapters/hosts/grok/relay.md +2 -0
- package/runtime/python/okstra_ctl/adapters/hosts/kimi/relay.md +2 -0
- package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +8 -1
- package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +8 -0
- package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +23 -6
- package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +6 -2
- package/runtime/python/okstra_ctl/agent/invocation.py +168 -113
- package/runtime/python/okstra_ctl/agent/prompt_cli/cli.py +120 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/materialize.py +107 -2
- package/runtime/python/okstra_ctl/agent/prompt_cli/run_identity.py +0 -49
- package/runtime/python/okstra_ctl/analysis_packet.py +4 -1
- package/runtime/python/okstra_ctl/application/open_worker.py +6 -1
- package/runtime/python/okstra_ctl/assignment_resolver.py +16 -5
- package/runtime/python/okstra_ctl/cmux.py +69 -20
- package/runtime/python/okstra_ctl/code_review_target.py +16 -8
- package/runtime/python/okstra_ctl/conformance.py +43 -0
- package/runtime/python/okstra_ctl/consumers.py +6 -3
- package/runtime/python/okstra_ctl/container.py +31 -8
- package/runtime/python/okstra_ctl/context_cost.py +11 -15
- package/runtime/python/okstra_ctl/contract_refreeze.py +156 -0
- package/runtime/python/okstra_ctl/convergence_critic_prompt.py +4 -6
- package/runtime/python/okstra_ctl/convergence_provenance.py +81 -18
- package/runtime/python/okstra_ctl/design_prep.py +34 -1
- package/runtime/python/okstra_ctl/dispatch_core.py +53 -27
- package/runtime/python/okstra_ctl/domain/host.py +5 -0
- package/runtime/python/okstra_ctl/domain/worker_runtime.py +10 -0
- package/runtime/python/okstra_ctl/error_report.py +4 -3
- package/runtime/python/okstra_ctl/execution_manifest.py +71 -18
- package/runtime/python/okstra_ctl/execution_mutation_audit.py +21 -21
- package/runtime/python/okstra_ctl/handoff.py +167 -277
- package/runtime/python/okstra_ctl/implementation_stage.py +9 -0
- package/runtime/python/okstra_ctl/initial_prompt_materialization.py +113 -0
- package/runtime/python/okstra_ctl/lead_progress.py +1 -1
- package/runtime/python/okstra_ctl/legacy_model_selection.py +2 -2
- package/runtime/python/okstra_ctl/manager_cli.py +175 -14
- package/runtime/python/okstra_ctl/manager_launch.py +41 -19
- package/runtime/python/okstra_ctl/manager_paths.py +22 -3
- package/runtime/python/okstra_ctl/manager_split.py +474 -0
- package/runtime/python/okstra_ctl/manager_store.py +331 -21
- package/runtime/python/okstra_ctl/manager_sync.py +37 -16
- package/runtime/python/okstra_ctl/manager_view.py +217 -0
- package/runtime/python/okstra_ctl/model_discovery.py +30 -0
- package/runtime/python/okstra_ctl/model_io/lines.py +14 -1
- package/runtime/python/okstra_ctl/model_io/renderers.py +4 -3
- package/runtime/python/okstra_ctl/models.py +1 -1
- package/runtime/python/okstra_ctl/next_phase.py +16 -6
- package/runtime/python/okstra_ctl/operation_invocation.py +86 -0
- package/runtime/python/okstra_ctl/option_comparison.py +168 -0
- package/runtime/python/okstra_ctl/path_hints.py +9 -0
- package/runtime/python/okstra_ctl/paths.py +3 -0
- package/runtime/python/okstra_ctl/plan_items_cli.py +6 -1
- package/runtime/python/okstra_ctl/profile_show.py +42 -1
- package/runtime/python/okstra_ctl/qa_commands.py +15 -0
- package/runtime/python/okstra_ctl/registry/host_discovery.py +20 -12
- package/runtime/python/okstra_ctl/registry/host_registry.py +11 -0
- package/runtime/python/okstra_ctl/render.py +50 -0
- package/runtime/python/okstra_ctl/report_contract.py +1 -1
- package/runtime/python/okstra_ctl/report_finalize.py +13 -6
- package/runtime/python/okstra_ctl/report_html/view_models/final_verification.py +2 -21
- package/runtime/python/okstra_ctl/report_html/view_models/release_handoff.py +21 -3
- package/runtime/python/okstra_ctl/report_html/visualizations.py +0 -5
- package/runtime/python/okstra_ctl/report_synthesis_packet.py +177 -17
- package/runtime/python/okstra_ctl/report_translation.py +2 -1
- package/runtime/python/okstra_ctl/report_translation_dispatch.py +69 -9
- package/runtime/python/okstra_ctl/role_requirements.py +142 -129
- package/runtime/python/okstra_ctl/rollup.py +3 -1
- package/runtime/python/okstra_ctl/run.py +76 -29
- package/runtime/python/okstra_ctl/schedule_semantics.py +17 -6
- package/runtime/python/okstra_ctl/stage_fix_carry.py +23 -4
- package/runtime/python/okstra_ctl/stage_integrate.py +178 -18
- package/runtime/python/okstra_ctl/stage_map.py +16 -2
- package/runtime/python/okstra_ctl/stage_targets.py +209 -43
- package/runtime/python/okstra_ctl/team.py +22 -13
- package/runtime/python/okstra_ctl/time_report.py +2 -1
- package/runtime/python/okstra_ctl/usage_report.py +3 -1
- package/runtime/python/okstra_ctl/verification_target.py +13 -2
- package/runtime/python/okstra_ctl/wizard/confirmation.py +3 -9
- package/runtime/python/okstra_ctl/wizard/ids.py +1 -1
- package/runtime/python/okstra_ctl/wizard/registry.py +1 -1
- package/runtime/python/okstra_ctl/wizard/state.py +3 -5
- package/runtime/python/okstra_ctl/wizard/steps_plan.py +3 -23
- package/runtime/python/okstra_ctl/worker_prompt_contract.py +5 -1
- package/runtime/python/okstra_ctl/worker_prompt_headers.py +35 -7
- package/runtime/python/okstra_ctl/worker_prompt_policy.py +66 -48
- package/runtime/python/okstra_ctl/workflow.py +1 -1
- package/runtime/python/okstra_ctl/worktree/__init__.py +3 -1
- package/runtime/python/okstra_ctl/worktree/naming.py +9 -0
- package/runtime/python/okstra_ctl/worktree_registry.py +38 -9
- package/runtime/python/okstra_token_usage/pricing.py +6 -4
- package/runtime/schemas/agent-common-v1.schema.json +34 -0
- package/runtime/schemas/agent-duty-v1.schema.json +38 -0
- package/runtime/schemas/agent-operation-v1.schema.json +11 -0
- package/runtime/schemas/agent-profile-v1.schema.json +46 -0
- package/runtime/schemas/agent-role-v1.schema.json +29 -0
- package/runtime/schemas/final-report-v2.0.schema.json +118 -97
- package/runtime/schemas/final-report-v3.0.schema.json +118 -97
- package/runtime/skills/okstra-brief-gen/SKILL.md +84 -4
- package/runtime/skills/okstra-chat/SKILL.md +2 -2
- package/runtime/skills/okstra-code-review/SKILL.md +23 -9
- package/runtime/skills/okstra-container-build/SKILL.md +10 -10
- package/runtime/skills/okstra-inspect/SKILL.md +1 -1
- package/runtime/skills/okstra-inspect/facets/cost.md +1 -1
- package/runtime/skills/okstra-inspect/facets/error-zip.md +9 -9
- package/runtime/skills/okstra-inspect/facets/errors.md +16 -16
- package/runtime/skills/okstra-inspect/facets/logs.md +7 -7
- package/runtime/skills/okstra-inspect/facets/recap.md +2 -2
- package/runtime/skills/okstra-inspect/facets/report.md +1 -1
- package/runtime/skills/okstra-inspect/facets/status.md +4 -3
- package/runtime/skills/okstra-inspect/facets/time.md +11 -10
- package/runtime/skills/okstra-manager/SKILL.md +70 -5
- package/runtime/skills/okstra-pr-gen/SKILL.md +6 -5
- package/runtime/skills/okstra-rollup/SKILL.md +5 -5
- package/runtime/skills/okstra-run/SKILL.md +32 -13
- package/runtime/skills/okstra-schedule-gen/SKILL.md +19 -14
- package/runtime/skills/okstra-setup/SKILL.md +21 -10
- package/runtime/skills/okstra-setup/references/project-config.md +7 -6
- package/runtime/skills/okstra-usage/SKILL.md +1 -1
- package/runtime/skills/okstra-user-response/SKILL.md +1 -1
- package/runtime/templates/manager/view.template.html +109 -0
- package/runtime/templates/report-writer-prompt-preamble.md +8 -0
- package/runtime/templates/reports/brief.template.md +14 -4
- package/runtime/templates/reports/html/i18n/en.json +7 -4
- package/runtime/templates/reports/html/i18n/ko.json +7 -4
- package/runtime/templates/reports/html/tasks/final-verification.template.html +2 -2
- package/runtime/templates/reports/html/tasks/release-handoff.template.html +8 -5
- package/runtime/templates/reports/i18n/en.json +1 -1
- package/runtime/templates/reports/md/tasks/release-handoff.template.md +1 -1
- package/runtime/templates/reports/release-handoff-input.template.md +6 -4
- package/runtime/templates/translator-prompt-preamble.md +36 -0
- package/runtime/validators/checks/validate-assets-01.py +7 -8
- package/runtime/validators/validate-brief.py +77 -2
- package/runtime/validators/validate-implementation-plan-stages.py +2 -1
- package/runtime/validators/validate-run.py +59 -9
- package/runtime/validators/validate-schedule.py +9 -0
- package/docs/for-ai/README.md +0 -68
- package/docs/for-ai/skills/okstra-brief-gen.md +0 -262
- package/docs/for-ai/skills/okstra-chat.md +0 -34
- package/docs/for-ai/skills/okstra-code-review.md +0 -57
- package/docs/for-ai/skills/okstra-container-build.md +0 -129
- package/docs/for-ai/skills/okstra-inspect.md +0 -262
- package/docs/for-ai/skills/okstra-manager.md +0 -69
- package/docs/for-ai/skills/okstra-memory.md +0 -126
- package/docs/for-ai/skills/okstra-pr-gen.md +0 -49
- package/docs/for-ai/skills/okstra-rollup.md +0 -114
- package/docs/for-ai/skills/okstra-run.md +0 -250
- package/docs/for-ai/skills/okstra-schedule-gen.md +0 -240
- package/docs/for-ai/skills/okstra-setup.md +0 -158
- package/docs/for-ai/skills/okstra-usage.md +0 -29
- package/docs/for-ai/skills/okstra-user-response.md +0 -72
- package/runtime/agents/workers/claude-worker.md +0 -128
- package/runtime/agents/workers/report-writer-worker.md +0 -37
- package/runtime/agents/workers/translator-worker.md +0 -63
- package/runtime/prompts/duties/acceptance-critic.md +0 -44
- package/runtime/prompts/duties/acceptance-verifier.md +0 -44
- package/runtime/prompts/duties/analysis-worker.md +0 -44
- package/runtime/prompts/duties/code-reviewer.md +0 -44
- package/runtime/prompts/duties/common.md +0 -39
- package/runtime/prompts/duties/diagnosis-worker.md +0 -44
- package/runtime/prompts/duties/direction-selection-worker.md +0 -44
- package/runtime/prompts/duties/discovery-worker.md +0 -44
- package/runtime/prompts/duties/implementation-executor.md +0 -44
- package/runtime/prompts/duties/implementation-verifier.md +0 -44
- package/runtime/prompts/duties/lead.md +0 -44
- package/runtime/prompts/duties/planning-worker.md +0 -52
- package/runtime/prompts/duties/report-writer.md +0 -44
- package/runtime/prompts/duties/reverification-worker.md +0 -44
- package/runtime/prompts/duties/schedule-verifier.md +0 -44
- package/runtime/prompts/duties/scope-critic.md +0 -44
- package/runtime/prompts/duties/technical-verification-worker.md +0 -44
- package/runtime/prompts/duties/translator.md +0 -44
- package/runtime/python/okstra_ctl/pane_title.py +0 -154
package/docs/architecture.md
CHANGED
|
@@ -18,7 +18,7 @@ Its core capabilities at a glance are:
|
|
|
18
18
|
- **Single python authority**: All prepare wiring—resolving profiles/workers/models, computing paths, rendering, and central record_start—is concentrated in a single function, [`okstra_ctl.run.prepare_task_bundle()`](../scripts/okstra_ctl/run.py). `okstra.sh` and the `okstra-run` skill are thin callers of that same function and do not pass state through environment variables. Task identity, paths, and workflow state are recalculated from authoritative on-disk files every time.
|
|
19
19
|
- **Host-aware handoff**: Claude Code, Codex, Antigravity, Grok, and Kimi can keep their current native session as the lead. The standalone compatibility launcher still starts a new `claude` process by default, while the external adapter uses registered CLI wrappers. Every path consumes the same `prepare_task_bundle` outputs.
|
|
20
20
|
- **Required team contract**: The `Required workers:` block in each phase profile is authoritative for the roster. General analysis phases use Claude/Codex analysers plus a report writer by default, while Antigravity, Grok, and Kimi are included only when allowed by both the profile and `--workers`. Lead-oriented phases such as `release-handoff` have separate rosters.
|
|
21
|
-
- **User-home install + project-local task bundles**: One `npx okstra@latest install` command installs the runtime (`~/.okstra/{lib/python, bin, templates, prompts}`) and installs public skills to `~/.agents/skills/` by default. If `~/.claude` exists, it also installs Claude skills and
|
|
21
|
+
- **User-home install + project-local task bundles**: One `npx okstra@latest install` command installs the runtime (`~/.okstra/{lib/python, bin, templates, prompts}`) and installs public skills to `~/.agents/skills/` by default. If `~/.claude` exists, it also installs Claude skills. The nine role contracts, the common contract and the non-run operation contracts install to `~/.okstra/agents/`; nothing is written to a host-global agent discovery path, so okstra roles are not exposed to runs that do not use okstra (ADR-0017). Only user entry-point skills are exposed in the skill list; lead/support operating contracts are installed as runtime resources under `~/.okstra/prompts/` and are not discoverable as skills. Global conversation memory is stored separately from projects under `~/.okstra/memory-book/`. Task bundles and discovery metadata are stored under `.okstra/` in the target project. **In addition, `<PROJECT_ROOT>/.claude/settings.local.json` is provisioned as a symlink to `~/.okstra/templates/settings.local.json`** (`okstra setup` and the prepare path manage it idempotently; if a regular file already existed, it is preserved as `.bak.<timestamp>` before replacement).
|
|
22
22
|
- **Resume and clarification**: Supports resuming the same task and responding to follow-up questions from the lead through `--task-key`, `--resume-clarification`, and `--clarification-response`.
|
|
23
23
|
- **Dual-audience derived views and telemetry**: For schema v2, derives the full reading copy Markdown (on demand) and task-specific human-facing HTML independently from the same v2 data.json. Schema v1 and quick Markdown reports keep their compatibility renderer. Worker error sidecars, wrapper log sidecars, and token-usage/cost accounting remain separate audit inputs.
|
|
24
24
|
|
|
@@ -78,7 +78,7 @@ Where `README.md` is the quick entry point, this document is the detailed refere
|
|
|
78
78
|
|
|
79
79
|
okstra's prepare responsibilities are consolidated in a single Python entry point, [`okstra_ctl.run.prepare_task_bundle`](../scripts/okstra_ctl/run.py). This function performs the following as one transaction:
|
|
80
80
|
|
|
81
|
-
- Verifies that okstra installation assets exist (`~/.agents/skills/okstra-*`, optional `~/.claude/skills/okstra
|
|
81
|
+
- Verifies that okstra installation assets exist (`~/.agents/skills/okstra-*`, optional `~/.claude/skills/okstra-*`, `~/.okstra/agents/...`, `~/.okstra/bin/...`)
|
|
82
82
|
- Self-registers `<PROJECT_ROOT>/.okstra/project.json` (or verifies that the projectId matches)
|
|
83
83
|
- Loads task type → `prompts/profiles/<task-type>.md` and extracts recommended workers
|
|
84
84
|
- Normalizes user worker/model overrides through the provider registry (Claude, Codex, Antigravity, Grok, Kimi, and report-writer-capable providers)
|
|
@@ -128,7 +128,7 @@ Runtime entry points are consolidated in Python packages. Bash and skills only c
|
|
|
128
128
|
- [`okstra_ctl.session`](../scripts/okstra_ctl/session.py) · [`okstra_ctl.seeding`](../scripts/okstra_ctl/seeding.py) — Claude session ID / resume command / installation validation / runtime settings.
|
|
129
129
|
- [`okstra_ctl.{ids,index,invocation,jsonl,project_meta,reconcile,sequence,backfill,listing,locks}`](../scripts/okstra_ctl/) — existing central-index (`~/.okstra`) modules.
|
|
130
130
|
- [`okstra_project.{resolver,state}`](../scripts/okstra_project/) — PROJECT_ROOT resolution + project.json upsert + task-catalog/manifest reader.
|
|
131
|
-
- [`okstra_ctl.manager_cli`](../scripts/okstra_ctl/manager_cli.py), [`manager_store`](../scripts/okstra_ctl/manager_store.py), [`manager_sync`](../scripts/okstra_ctl/manager_sync.py), [`manager_launch`](../scripts/okstra_ctl/manager_launch.py), [`manager_paths`](../scripts/okstra_ctl/manager_paths.py) — cross-project manager state, one-way project snapshot sync,
|
|
131
|
+
- [`okstra_ctl.manager_cli`](../scripts/okstra_ctl/manager_cli.py), [`manager_store`](../scripts/okstra_ctl/manager_store.py), [`manager_sync`](../scripts/okstra_ctl/manager_sync.py), [`manager_launch`](../scripts/okstra_ctl/manager_launch.py), [`manager_paths`](../scripts/okstra_ctl/manager_paths.py), [`manager_view`](../scripts/okstra_ctl/manager_view.py), [`manager_split`](../scripts/okstra_ctl/manager_split.py) — cross-project manager state, one-way project snapshot sync, child launch packet/context creation, the HTML overview page, and tracker split into per-project scoped briefs for `okstra manager`.
|
|
132
132
|
|
|
133
133
|
### Bash entry points (thin)
|
|
134
134
|
|
|
@@ -150,7 +150,7 @@ Runtime entry points are consolidated in Python packages. Bash and skills only c
|
|
|
150
150
|
### Skills (`skills/`) and lead resources (`prompts/`)
|
|
151
151
|
|
|
152
152
|
- [`prompts/lead/okstra-lead-contract.md`](../prompts/lead/okstra-lead-contract.md) is the runtime-neutral lifecycle core: phase boundaries, artifacts, convergence, report ownership, and persistence semantics.
|
|
153
|
-
- `
|
|
153
|
+
- Each registered host adapter carries its relay contract beside its code — `scripts/okstra_ctl/adapters/hosts/<host>/relay.md` for `claude-code`, `codex`, `antigravity`, `external`, `grok`, and `kimi` — and it maps the same semantic operations to one selected host runtime. The generated launch prompt exposes the core path plus exactly one adapter path.
|
|
154
154
|
- `prompts/lead/adapters/cmux.md` is selected by environment rather than by runtime: when the run manifest's `terminalBackend` is `cmux-pane`, every lead runtime resolves to it and dispatches through `okstra team`, because okstra owns the worker panes on that path instead of the host. It overrides only the adapter and the dispatch mode; the lead's agent, role, and session accounting still come from its own runtime.
|
|
155
155
|
- Runtime metadata and role assignments are persisted separately, but the lead provider is derived from the host: Claude Code maps to Claude, Codex maps to Codex, and Antigravity CLI maps to Antigravity. New runs persist `hostRuntime`, `leadAssignment`, and `workerAssignments[]`; each assignment records its provider, model, execution value, and resolved `native-session` or `cli-wrapper` runner. `lead-execution-prompt.md` is canonical: one file per run at `runs/<task-type>/prompts/lead-execution-prompt-<task-type>-<seq>.md`. No Claude-named copy is written — `resources.claudeExecutionPromptPath` in the run manifest is a key alias that resolves to that same file for historical consumers.
|
|
156
156
|
- Host and provider registries remain separate: the active registered host owns the native lead session, while non-native providers run through their registered CLI wrappers.
|
|
@@ -301,7 +301,7 @@ Both modes create identical artifacts (task-manifest, run-manifest, timeline, in
|
|
|
301
301
|
- The handed-off native host acts as the Okstra lead, responsible for orchestration and final synthesis.
|
|
302
302
|
- The default worker policy remains Claude + Codex analysis and a Claude report writer. Antigravity, Grok, and Kimi are profile-gated optional assignments; Grok and Kimi are read-only analyser/critic providers.
|
|
303
303
|
- The lead assigns worker responsibilities and makes the final judgment after reading the task bundle.
|
|
304
|
-
- okstra Claude
|
|
304
|
+
- okstra Claude skills installed in the user home (`~/.claude/skills`) instruct Claude to dispatch workers through `Agent(name: ...)` with no `subagent_type`: okstra registers no agent definitions, so a native worker is a general-purpose session carrying the frozen prompt. Workers automatically join the session's implicit team.
|
|
305
305
|
- **Team lifecycle (Claude Code v2.1.178+)**: v2.1.178 removed the `TeamCreate` / `TeamDelete` tools and the `team_name` parameter from `Agent(...)`. When `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` (seeded into `settings.json` by `okstra install`), one implicit team per session is created automatically at startup. In Phase 3, the lead does not call a team-creation tool. It records only the `teamName` audit label and `teamCreate: { attempted: false, status: "implicit" }`, then dispatches workers through `Agent(name: "<role>-worker", run_in_background: true)` (without team_name). Teammates run in-process. At run end, after Phase 7 token accounting, the lead asks whether to clean up worker teammates. If approved, it sends each completed teammate a `SendMessage` shutdown_request. There is no tool for deleting the implicit team; it disappears when the session ends. If the user keeps the teammates, they remain in the FleetView roster and the lead tells the user to remove them through Teams/FleetView. Phase 7 token accounting locates worker sessions by top-level `agentName` or nested `subagents/agent-a<name>-<hash>.jsonl` filenames when `teamCreate.status` is `implicit`/`skipped`/`error`.
|
|
306
306
|
|
|
307
307
|
## Lead prompt contract
|
|
@@ -321,7 +321,7 @@ The standard `okstra` workflow applies the following team contract consistently
|
|
|
321
321
|
- The current host-native provider owns the synthesis-only lead session: Claude on Claude Code, Codex on Codex.
|
|
322
322
|
- Every selected worker comes from the profile roster and provider capability registry. The default analysis policy remains Claude + Codex + a report writer; Antigravity, Grok, and Kimi are attempted only when the profile and resolved roster include them.
|
|
323
323
|
- `Report writer worker` focuses on report structure and evidence organization, while the host-native lead remains the final synthesis owner. Claude is the default report-writer provider; Codex may be selected explicitly.
|
|
324
|
-
- Model defaults are provider and functional-role policy. Fallbacks include Claude lead/analyser=`opus`, Codex lead/analyser=`gpt-
|
|
324
|
+
- Model defaults are provider and functional-role policy. Fallbacks include Claude lead/analyser=`opus`, Codex lead/analyser=`gpt-6-sol`, Claude report writer=`sonnet`, Antigravity=`gemini-3.1-pro`, Grok analyser=`grok-4.7`, and Kimi analyser=`kimi-k3`. Selectable catalog models may be assigned to every role.
|
|
325
325
|
- Before the final judgment, each required role in the current run's worker roster must have either a result or an explicit terminal status (`completed`, `timeout`, `error`, `not-run`).
|
|
326
326
|
- Every attempted worker (`completed`, `timeout`, `error`) must have an assigned worker prompt history file under the current run's `prompts/` directory.
|
|
327
327
|
- Worker timing begins at the atomic transition to `in-progress`, which records `workers[].startedAt` in `team-state.json`; prompt creation time is not a dispatch proxy. `okstra worker-state transition` and both dispatch adapters share `dispatch_state.transition_worker_status`, while `okstra worker-liveness --team-state ... --worker ...` reads that timestamp as the launch-grace authority for both probe kinds — the in-process audit sidecar is reused on re-dispatch, so only `startedAt` separates the previous attempt's last heartbeat from this dispatch's silence.
|
|
@@ -333,7 +333,7 @@ The standard `okstra` workflow applies the following team contract consistently
|
|
|
333
333
|
|
|
334
334
|
The same analysis-core rule applies to `requirements-discovery`, `error-analysis`, `implementation-option-selection`, `implementation-planning`, `improvement-discovery`, and `final-verification`: every selected initial analyser receives the same normalized semantic body and independently covers the whole common scope. In `implementation`, the implementation executor is excluded from verifier equality; all selected implementation verifiers form their own equality group. If the roster contains one verifier, individual header rules still apply, while one verifier makes normalized equality a deliberate no-op. Report-writer and reverify prompts are excluded from analysis equality groups because they author or adjudicate existing findings instead of producing an initial independent analysis.
|
|
335
335
|
|
|
336
|
-
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.
|
|
336
|
+
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`; translation uses `templates/translator-prompt-preamble.md`. Every initial audience also reads the shared `templates/worker-error-contract.md`. A `runner=native-session` worker additionally receives `**Host Session Contract Path:**`, the host-owned contract for running inside the lead's session (working directory, shell invocation, MCP call shape, and when to return). A host declares it with `workerSessionContract` in its adapter manifest; a CLI-wrapper worker runs as its own process and never receives it. See ADR-0026. Only implementation executor/verifier prompts receive `**Coding preflight pack:**`; a report writer never loads implementation coding instructions.
|
|
337
337
|
|
|
338
338
|
`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.
|
|
339
339
|
|
|
@@ -452,10 +452,10 @@ The fourth column is the `workflow.nextRecommendedPhase` pointer Phase 7 leaves
|
|
|
452
452
|
|---|---|---|---|---|
|
|
453
453
|
| `requirements-discovery` | Classify the request as bugfix, feature, refactor, ops, or improvement, then route it to a safe next phase | work category, routing decision, missing-input list, clarification requests | from `requirementsDiscovery.routing.nextTaskType`: `ready` at `error-analysis` or `implementation-option-selection`; `pending` when the run settles on neither | No |
|
|
454
454
|
| `error-analysis` | Analyze the symptoms, causes, and reproduction gaps of a reported error/incident based on evidence | symptom/trigger summary, root-cause hypotheses, reproduction gap, validation path | from `errorAnalysis.routing.nextTaskType`: `ready` at `implementation-option-selection` after a credible cause, or at `error-analysis` for continued investigation | No |
|
|
455
|
-
| `implementation-option-selection` | Compare or validate implementation directions before detailed planning | up to three ranked directions, per-direction `coveragePercent` and `scopePrecisionPercent`, rejected-candidate audit, separate `DIRECTION SELECTION` response | from the `implementationOptionSelection.routing` string enum: `ready` at `implementation-planning` both for a confirmed direction and for `pending-direction-selection` with ranked candidates (the planning wizard's `selected_direction_pick`
|
|
455
|
+
| `implementation-option-selection` | Compare or validate implementation directions before detailed planning | up to three ranked directions, per-direction `coveragePercent` and `scopePrecisionPercent`, rejected-candidate audit, separate `DIRECTION SELECTION` response | from the `implementationOptionSelection.routing` string enum: `ready` at `implementation-planning` both for a confirmed direction and for `pending-direction-selection` with ranked candidates (the user picks the direction in the HTML report's `DIRECTION SELECTION` Export and saves it under `user-responses/`; the planning wizard's `selected_direction_pick` then picks that report; the rationale names the candidates and that path), `pending` when no candidate was ranked, `blocked` on `blocked` | No (strictly read-only; source edits, builds, tests, migrations, and deploys are prohibited) |
|
|
456
456
|
| `implementation-planning` | Expand one selected direction into an executable plan without changing its mechanism or architecture boundary | selected-direction snapshot/reference, direction realization, affected-file list, Stage Map, validation/rollback, exact plan coverage, YAML frontmatter `approved: false`, **§5.5.9 Plan Body Verification**. Existing plans without `planningContract: selected-direction` retain the legacy option-candidate and `implementation-option:` contract | from `implementationPlanning.outcome`: `ready` at `implementation` on `plan-ready` or on a candidate-comparison plan with no `outcome` (the plan still needs its separate approval before that run starts), `ready` at `implementation-option-selection` on `direction-invalidated` | No |
|
|
457
457
|
| `implementation` | Modify source code according to the approved `implementation-planning` final report. **One run executes exactly one stage** (selected with `--stage <auto\|N>`) | commit list, diff summary, out-of-plan edits block, validation/TDD evidence, rollback verification, verifier results (Antigravity/Codex/Claude), `carry/stage-<N>.json` evidence sidecar | from `implementation.routingRecommendation.target`: `ready` at that phase — `final-verification` on a clean stage, otherwise `error-analysis`, `implementation-planning`, or `implementation` | Yes (limited to the approved plan's file list; `git push`/publish/deploy/real migration prohibited) |
|
|
458
|
-
| `final-verification` | Check completed work for residual defects and regression risk, then make a release judgment | acceptance verdict, residual risk, follow-up routing (`error-analysis`/`implementation-option-selection`/`implementation-planning`/`release-handoff`) | from `finalVerification.routingRecommendation.target`: `ready` at that value — `release-handoff` only on an `accepted` verdict, otherwise the phase owning the defect (cause, selected direction, or detailed plan). `release-handoff(stage-group)` is a scope qualifier on the same phase, so it projects to `release-handoff
|
|
458
|
+
| `final-verification` | Check completed work for residual defects and regression risk, then make a release judgment | acceptance verdict, residual risk, follow-up routing (`error-analysis`/`implementation-option-selection`/`implementation-planning`/`release-handoff`/`final-verification`) | from `finalVerification.routingRecommendation.target`: `ready` at that value — `release-handoff` only on an `accepted` verdict, otherwise the phase owning the defect (cause, selected direction, or detailed plan). `release-handoff(stage-group)` is a scope qualifier on the same phase, so it projects to `release-handoff`; either verification scope may route there, since a handoff opens one PR per stage. `final-verification` re-runs this phase on the same head, and is for a run whose every remaining blocker is an environment or configuration fault this report already diagnosed. `done` becomes `terminal` | No (read-only tests only) |
|
|
459
459
|
| `release-handoff` | Deliver `accepted` changes as a commit, push, or PR according to the user's chosen method | user menu responses (H1 action / H2 PR base / H3 message handling), executed git/gh command log, commit SHA list, PR URL | always `terminal` — the lifecycle ends here and this report has no routing field Phase 7 projects from | Yes—but execute **only the mutating commands selected by the user in the menu**. `git push --force*`, direct push to the base branch, `--no-verify`, `gh release`, and publish/deploy are prohibited. The source code itself must not be changed; package the existing `implementation` diff unchanged. |
|
|
460
460
|
| `project-analysis` | Map the current project structure and feature index | components, dependencies, entry points, data stores, external systems, feature index | always `pending` with no phase — a sidetrack settles no route | No (strictly read-only; tests are also prohibited) |
|
|
461
461
|
| `feature-analysis` | Trace one confirmed existing feature | flows, domain rules, state changes, external interactions, test coverage | always `pending` with no phase — a sidetrack settles no route | No (strictly read-only; tests are also prohibited) |
|
|
@@ -464,8 +464,8 @@ The fourth column is the `workflow.nextRecommendedPhase` pointer Phase 7 leaves
|
|
|
464
464
|
Common constraints:
|
|
465
465
|
|
|
466
466
|
- Every phase except `implementation` prohibits source-code edits, builds, migrations, deployments, and other state-mutating commands (`final-verification` allows read-only test commands only). `implementation` permits edits/commits only within the file list of the approved plan; `git push`, publish, deploy, real migration, and third-party write APIs remain prohibited.
|
|
467
|
-
- **Isolated worktree for pre-implementation non-implementation phases (BLOCKING)**: The first pre-implementation non-implementation phase prepare creates a task-key `git worktree`. Pre-implementation non-implementation phases reuse the task-key worktree: `requirements-discovery` → `error-analysis` → `implementation-option-selection` → `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)
|
|
468
|
-
- **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 =
|
|
467
|
+
- **Isolated worktree for pre-implementation non-implementation phases (BLOCKING)**: The first pre-implementation non-implementation phase prepare creates a task-key `git worktree`. Pre-implementation non-implementation phases reuse the task-key worktree: `requirements-discovery` → `error-analysis` → `implementation-option-selection` → `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) manages task-key → path/branch mappings across concurrent runs on the machine. Worktree paths are unique machine-wide; branch names are unique per project id, because a branch only exists inside that project's repository and the same name in another project is a different branch. A real collision inside one repository is caught before the registry, by the branch-existence check in provisioning. 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.
|
|
468
|
+
- **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 = the predecessors' own commits: the one that already contains the others when there is one, otherwise a branch merging exactly them (`stage_integrate.ensure_stage_merge_branch`, the same primitive release-handoff uses as a PR base). The task branch is not involved, and a predecessor that has not been merged anywhere no longer blocks the stage. 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.
|
|
469
469
|
- **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.
|
|
470
470
|
- **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.
|
|
471
471
|
- 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).
|
|
@@ -490,20 +490,26 @@ If a bug is discovered in artifacts after a task has completed release-handoff,
|
|
|
490
490
|
- **Closure**: After a release-handoff run attaches to an open cycle and the manifest's `workflow.lastCompletedPhase` becomes `release-handoff`, the next prepare lazily appends a `closed` row.
|
|
491
491
|
- **Consumers (all derived views)**: ① the `## Fix History` section of a later run's analysis-packet ② quotation in Task Continuity Notes from okstra-brief-gen ③ final-report `## 5.10 Fix History` ④ a `fixCycles` summary in task-manifest plus a one-line entry in task-index / task-catalog. All four consumers read only derived views from `fix_cycles.summarize()` / `packet_summary()`.
|
|
492
492
|
|
|
493
|
-
### release-handoff stage
|
|
493
|
+
### release-handoff: one stage, one PR
|
|
494
494
|
|
|
495
|
-
`release-handoff`
|
|
495
|
+
`release-handoff` ships stages, not tasks. Each selected stage becomes its own pull request whose head is that stage's stack branch (`<work-category-namespace>/<task-id-segment>-s<N>`), so the PR diff is exactly that stage's commits and nothing is squashed or collected into a bundle branch.
|
|
496
496
|
|
|
497
|
-
|
|
498
|
-
- **stage-group**: Selects some stages that received `accepted` in single-stage final-verification and combines them into one PR on a collector branch. This allows a PR to be opened for a verified stage group without waiting for the entire task to finish.
|
|
497
|
+
The PR base follows the stage's `depends-on`, after dropping predecessors already merged into the chosen release base:
|
|
499
498
|
|
|
500
|
-
|
|
499
|
+
| live predecessors | base | branch created |
|
|
500
|
+
|---|---|---|
|
|
501
|
+
| none | the release base the user picked (`main`, `preprod`, …) | no |
|
|
502
|
+
| one | that stage's branch — a stacked PR | no |
|
|
503
|
+
| several | a branch merging their recorded `done.head_commit`s, named `<work-category-namespace>/<task-id-segment>-g<n1>-<n2>` | yes, by `pr-plan` |
|
|
501
504
|
|
|
502
|
-
|
|
505
|
+
A merge-base branch is a base only, never a PR head, and it is the one place this phase may create commits. Because the PRs are a stack, they must be merged in ascending stage order with a merge commit or rebase-merge; squashing one replaces the commits the next PR's base points at.
|
|
503
506
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
+
Entry is based on **task ID**, without a brief. Briefs are inputs to entry phases; for release-handoff, prepare determines eligibility from the approved plan's Stage Map + Stage Lifecycle Snapshot, then automatically creates an input document (`<task_root>/release-handoff-input.md`) that cites the verification reports. Stage selection comes from the okstra-run wizard's `handoff_stage_pick` multiselect or CLI `--stages <csv>`; an empty selection takes every eligible stage, and the result is exposed to the lead as `HANDOFF_STAGES` in run-context.
|
|
508
|
+
|
|
509
|
+
The interaction order is: **Q1 action → Q2 select release base → pr-plan (head/base per stage) → conflict probe per stage → draft every PR → push and open them in stage order**.
|
|
510
|
+
|
|
511
|
+
- The Stage Lifecycle Snapshot is the source of truth for eligibility. The Snapshot reads `verified` entries (which stages were accepted in single-stage final-verification), `pr` entries (which stages already have a PR), and done rows in `consumers.jsonl`, then computes stages that are `verified` but not yet covered by a `pr` as candidates.
|
|
512
|
+
- Enforcement is implemented in the Python module `okstra_ctl.handoff`, not merely declared (`okstra handoff <subcommand>`). It has five subcommands: `eligible` (query eligible stages) / `pr-plan` (resolve each stage's head and base, creating a merge-base branch when one is needed) / `record-verified` (record a `verified` row) / `record-pr` (record one `pr` row per stage) / `local-checkout` (hand one stage's branch to the main worktree). The merge a `merge-base` branch needs is an explicit exception to the isolation spec's non-goal that "okstra does not merge automatically."
|
|
507
513
|
|
|
508
514
|
### improvement-discovery (sidetrack entry-point)
|
|
509
515
|
|
package/docs/cli.md
CHANGED
|
@@ -500,9 +500,9 @@ The Codex worker (`--workers codex`, `--codex-model`) and Codex lead runtime are
|
|
|
500
500
|
|
|
501
501
|
> Every `--*-model` flag accepts only aliases registered in the provider mappings in `scripts/okstra_ctl/models.py`. An unregistered value is immediately rejected with `UnknownModelError`, preventing a contract violation where the manifest's `modelExecutionValue` differs from the actual execution value. Allowed values:
|
|
502
502
|
> - Claude (`--lead-model` / `--claude-model` / `--report-writer-model`): `fable`, `fable-5-1`, `claude-fable-5-1`, `fable-5`, `claude-fable-5`, `opus`, `opus-5`, `claude-opus-5`, `sonnet`, `sonnet-5`, `claude-sonnet-5`, `haiku`, `haiku-4-5`, `claude-haiku-4-5`
|
|
503
|
-
> - Codex (`--codex-model`): `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna
|
|
504
|
-
> - Antigravity (`--antigravity-model`): `gemini-3.1-pro` (default), `gemini-3.
|
|
505
|
-
> - Grok (`--worker-model grok=<model>`): `grok-4.
|
|
503
|
+
> - Codex (`--codex-model`): `gpt-6-astra`, `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna` — the newest generation this account actually serves per tier. `gpt-6-sol` and `gpt-6-luna` stay in the catalog (a ChatGPT-account login is refused with HTTP 400 for them, measured 2026-09-23) together with `gpt-5.4-mini` and `codex-auto-review`, so past runs still price and an account that does serve them can still be pinned explicitly, but they are not offered. Codex slugs are gated at dispatch against the provider catalog the CLI caches in `~/.codex/models_cache.json`; a slug that catalog does not list is rejected rather than renamed.
|
|
504
|
+
> - Antigravity (`--antigravity-model`): `gemini-3.1-pro` (default), `gemini-3.8-flash`, and their space-separated aliases. The antigravity worker uses the `agy` CLI to run Gemini-family models, so model IDs retain the `gemini-*` form.
|
|
505
|
+
> - Grok (`--worker-model grok=<model>`): `grok-4.7`
|
|
506
506
|
> - Kimi (`--worker-model kimi=<model>`): `kimi-k3`, `k3`, `k3-256k` and their registered display aliases
|
|
507
507
|
>
|
|
508
508
|
> Not every registered alias is offered for selection. A model whose `ModelSpec` sets `selectable=False` stays in the catalog — so served-model attestation and historical pricing still resolve it — but it is hidden from the wizard's role-model picker, from `okstra model list`, and from `--role-model`. `okstra model list` still prints them, marked `selectable: no` with the reason. Currently hidden: `claude/fable-5-1`, `claude/fable-5`, `claude/opus-5`, `claude/sonnet-5`, `claude/haiku-4-5`, `claude/haiku-4-5-20251001` (each one the pinned twin of a channel entry that already appears; `claude/fable-5` is the previous served id, kept for attestation and pricing), `kimi/k3` (same model as `kimi/kimi-k3`), `codex/gpt-5.4-mini`, `codex/codex-auto-review`, `grok/grok-build-0.1`, `kimi/k3-256k`.
|
|
@@ -571,11 +571,11 @@ The central-default environment variables are:
|
|
|
571
571
|
Fallback defaults are:
|
|
572
572
|
|
|
573
573
|
- Claude Code lead: `opus`
|
|
574
|
-
- Codex lead: `gpt-
|
|
574
|
+
- Codex lead: `gpt-6-sol`
|
|
575
575
|
- Antigravity lead: `gemini-3.1-pro`
|
|
576
576
|
- `Report writer worker`: `sonnet`
|
|
577
577
|
- `Claude worker`: `opus`
|
|
578
|
-
- `Codex worker`: `gpt-
|
|
578
|
+
- `Codex worker`: `gpt-6-sol`
|
|
579
579
|
- `Antigravity worker`: `gemini-3.1-pro`
|
|
580
580
|
- Implementation executor: `claude`, so the default is `Claude executor`.
|
|
581
581
|
|
|
@@ -585,12 +585,12 @@ Selects the provider that performs the Executor role for `--task-type implementa
|
|
|
585
585
|
|
|
586
586
|
- Default: `OKSTRA_DEFAULT_EXECUTOR` → fallback `claude`.
|
|
587
587
|
- The Executor is the **only worker allowed to mutate project files** in this run. The other providers are dispatched as strict read-only verifiers in the same run.
|
|
588
|
-
- The Executor reuses the provider's worker model flag. With `--executor codex`, its model comes from `--codex-model`, default `gpt-
|
|
588
|
+
- The Executor reuses the provider's worker model flag. With `--executor codex`, its model comes from `--codex-model`, default `gpt-6-sol`; with `--executor antigravity`, it comes from `--antigravity-model`, default `gemini-3.1-pro`. With `--executor grok`, its model comes from `--worker-model grok=`, default `grok-4.7`.
|
|
589
589
|
- All three Claude, Codex, and Antigravity verifiers are always dispatched regardless of the Executor provider. Even the verifier using the same provider runs in a separate CLI session with isolated context, preserving the self-review safeguard.
|
|
590
590
|
- Codex and Antigravity mutate files through each CLI's auto-edit mode, for example `codex exec --sandbox danger-full-access`, without passing through Claude-side Edit/Write tools. Mutations occur in the task worktree described below. Every `okstra-<provider>-exec.sh` entrypoint receives the worktree path as its fourth positional argument and adds it to the worker's write scope, which each provider is told as repeated `--add-dir` (Codex names the project root with `-C` and skips the repeat). No provider CLI enforces a sandbox boundary: the write scope tells a worker where its work belongs, and the run checks afterwards that it stayed there.
|
|
591
591
|
- **Claude Executor cwd handling**: Claude's Bash tool has no per-call cwd argument and inherits the lead session cwd. To run cwd-sensitive toolchains such as `cargo`, `npm`, `pnpm`, `bun`, `pytest`, `make`, or `go` inside the worktree, prefix the invocation with `cd {{EXECUTOR_WORKTREE_PATH}} && <cmd>`. Keep `cd` as the leading token in a single Bash call so Claude Code permission auto-allow works; do not wrap it in `bash -lc "..."` or `bash -c "..."`, which hides `cd` and causes a permission prompt on every call. Prefer a tool's working-directory option—such as `git -C <path>`, `cargo --manifest-path`, or `pytest --rootdir`—over a `cd && ` chain. Edit/Write/Read tools already use absolute paths and need no cwd handling. This rule applies only to the Claude Executor; the Codex and Antigravity wrappers inject cwd.
|
|
592
|
-
- **Task worktree (automatic isolation for every task type)**: During the first phase's preparation for any task type, prepare creates a `git worktree` at `~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>/` and branches `<work-category-namespace>/<task-id-segment>` from the resolved commit of the user-selected `--base-ref`, for example `feature/dev-9436` or `fix/dev-7311`. Later phases for the same task key reuse the path and branch and record status `reused`; no new `git worktree add` occurs during run preparation. Special characters such as `/` and `:` in every segment are normalized to `-`, and `~/.okstra/worktrees/registry.json`
|
|
593
|
-
- **`implementation` stage isolation (concurrent parallelism)**: The task-key worktree above applies only from `requirements-discovery` through `implementation-planning`. Each `implementation` run executes in a **stage-specific isolated worktree** at `~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>--stage-<N>/` (a sibling of the task worktree — a nested layout made the task tree's prettier/tsc read the stage tree as source; whole-task `final-verification` prepare moves any remaining nested stage worktree out with `git worktree move` and updates the registry), on branch `<work-category-namespace>/<task-id-segment>-s<N>`. The registry atomically reserves a stage key, `<task-key>#stage-<N>`, under flock. `_resolve_effective_stages` excludes `started` rows in `consumers.jsonl` and reserved stages. Stage selection, worktree creation, and registry reservation all happen in one critical section protected by the task-key provisioning mutex at `~/.okstra/.locks/worktree-provision/`, so concurrent `implementation` runs safely select different ready stages: **one run = one stage**. A stage worktree's base depends on its dependency shape: independent (`depends-on (none)`) uses the common anchor fixed once at first stage entry; a single dependency (`depends-on X`) uses the predecessor stage's completed `head_commit`; multiple dependencies (`depends-on X,Y…`) use
|
|
592
|
+
- **Task worktree (automatic isolation for every task type)**: During the first phase's preparation for any task type, prepare creates a `git worktree` at `~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>/` and branches `<work-category-namespace>/<task-id-segment>` from the resolved commit of the user-selected `--base-ref`, for example `feature/dev-9436` or `fix/dev-7311`. Later phases for the same task key reuse the path and branch and record status `reused`; no new `git worktree add` occurs during run preparation. Special characters such as `/` and `:` in every segment are normalized to `-`, and `~/.okstra/worktrees/registry.json` manages task-key-to-path/branch mappings under flock — paths machine-wide, branch names within one project id. Executor edits, writes, builds, tests, and commits—and verifier reads—run in this worktree. If the caller is already in another worktree or project_root is not a Git repository, provisioning is skipped and records `skipped-in-worktree` or `skipped-not-git`. Path or branch collisions fail immediately with `PrepareError`. Worktrees are not deleted after a run; remove one manually with `git worktree remove`, then `git branch -D`, then delete the registry entry. **The implementation stage isolation below is the exception.**
|
|
593
|
+
- **`implementation` stage isolation (concurrent parallelism)**: The task-key worktree above applies only from `requirements-discovery` through `implementation-planning`. Each `implementation` run executes in a **stage-specific isolated worktree** at `~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>--stage-<N>/` (a sibling of the task worktree — a nested layout made the task tree's prettier/tsc read the stage tree as source; whole-task `final-verification` prepare moves any remaining nested stage worktree out with `git worktree move` and updates the registry), on branch `<work-category-namespace>/<task-id-segment>-s<N>`. The registry atomically reserves a stage key, `<task-key>#stage-<N>`, under flock. `_resolve_effective_stages` excludes `started` rows in `consumers.jsonl` and reserved stages. Stage selection, worktree creation, and registry reservation all happen in one critical section protected by the task-key provisioning mutex at `~/.okstra/.locks/worktree-provision/`, so concurrent `implementation` runs safely select different ready stages: **one run = one stage**. A stage worktree's base depends on its dependency shape: independent (`depends-on (none)`) uses the common anchor fixed once at first stage entry; a single dependency (`depends-on X`) uses the predecessor stage's completed `head_commit`; multiple dependencies (`depends-on X,Y…`) use a base holding exactly those predecessors — the predecessor commit that already contains the others, or else a branch merging them (`<work-category-namespace>/<task-id-segment>-g<n1>-<n2>`, built by `stage_integrate.ensure_stage_merge_branch` and reused as that stage's PR base in release-handoff). The branch is advanced when a predecessor's done commit moves, and only a predecessor commit missing from the repository fails the run. Select the stage with `--stage <auto|N>` for `okstra.sh`/`render-bundle`, or with the okstra-run wizard's `stage_pick` step. If `project_root` is not a Git repository or is a nested worktree, stage isolation also degrades to flat operation.
|
|
594
594
|
- **Single-stage `final-verification` artifact isolation**: `--task-type final-verification --stage <N>` reuses the implementation stage worktree read-only from the registry. Run artifacts are isolated per stage under `runs/final-verification/stage-<N>/`, and the team name receives a `-fv-s<N>` suffix. Concurrent final-verification runs for different stages do not collide in state, worker results, or team names. For concurrent verification of the same stage, `teamName` is only an audit label and each session has its own implicit team, so the sessions can coexist without a TeamCreate/name collision. This statement is limited to per-session team identity and does not claim safety for shared mutable state. Whole-task verification with an empty stage keeps the flat `runs/final-verification/` layout.
|
|
595
595
|
|
|
596
596
|
Example:
|
|
@@ -819,11 +819,11 @@ The `okstra` Node CLI (`bin/okstra`) provides both installer/admin commands and
|
|
|
819
819
|
| `okstra paths [--field <name>\|--shell]` | Print package, runtime, home, bin, Python path, and version locations |
|
|
820
820
|
| `okstra install [--runtime claude-code\|codex\|antigravity\|external\|all] [--refresh\|--dry-run\|--link <repo>]` | Install or update the runtime, templates, skills, and agents. The default runtime is `auto`; skill targets are not runtimes. `~/.agents/skills/` is always created, and Claude skills and agents are also installed when `~/.claude` exists |
|
|
821
821
|
| `okstra ensure-installed [--runtime claude-code\|codex\|antigravity\|external\|all] [-q]` | Check installation state and reinstall stale assets for the same runtime. Default `auto` continues without a host signal and checks drift in the Agent skill target and any existing Claude target |
|
|
822
|
-
| `okstra uninstall [--purge -y]` | Remove installed assets. By default, removes
|
|
822
|
+
| `okstra uninstall [--purge -y]` | Remove installed assets. By default, removes the installed trees under `~/.okstra` (including `agents/`), the skill targets recorded in `installed-skills.json`, and any host agent files `installed-agents.json` proves a past install owned, while preserving user data |
|
|
823
823
|
| `okstra doctor [--runtime claude-code\|codex\|antigravity\|external\|all] [--phase <phase>] [--json]` | Diagnose the runtime, Python imports, skill/agent installation, and model-pool state. The JSON `modelPool` object reports pool errors, default errors, binding precision, observed model, max write boundary, and invocation downgrade reason. It never sends an inference call. The `codex`, `antigravity`, and `external` runtimes omit Claude skill checks. `--phase` adds readiness checks for `implementation`, `final-verification`, `release-handoff`, or `improvement-discovery` |
|
|
824
824
|
| `okstra model list [--role <role>] [--host <host>] [--json]` | List catalog models for a host and optional role. Unselectable exact bindings report `exact binding unavailable`. No inference call |
|
|
825
825
|
| `okstra model default set\|unset <role> ... --scope project\|global [--cwd <dir>]` | Atomically write or remove `modelDefaults` for one canonical role |
|
|
826
|
-
| `okstra setup --project-id <id>` | Create or update `.okstra/project.json` in the current project |
|
|
826
|
+
| `okstra setup --project-id <id>` | Create or update `.okstra/project.json` in the current project. When `<PROJECT_ROOT>/CLAUDE.md` or `AGENTS.md` already exists, it also appends — or refreshes in place — an okstra-managed block between `<!-- okstra:citation-guidance:begin -->` / `end` telling agents not to cite okstra-internal references (report section numbers, `C-NNN` ids, run/stage ids, `.okstra/...` paths) outside an okstra report. Neither file is created, and a failure is a warning, not an error |
|
|
827
827
|
| `okstra check-project [--json]` | Verify that the current project is registered |
|
|
828
828
|
| `okstra preflight [--runtime <name>] [--cwd <dir>] [--machine]` | Single skill-preflight call combining `ensure-installed`, with silent reinstall when stale, `check-project`, and host-specific `runtimeReadiness`. It defaults to a fixed text projection. `--machine` returns the automation JSON contract, and `--json` is a deprecated one-release alias. A `claude-code` host checks project workspace trust. A `codex` current-session host verifies write access to `~/.okstra/worktrees/registry.lock`; a sandbox denial blocks before the wizard with the `switch-codex-to-full-access-and-rerun` action. `antigravity` and `external` hosts return ready without reading Claude Code state. Step 0 of every project-scoped skill converges on this command |
|
|
829
829
|
| `okstra convergence seed --groups <path> --work-state <path> --final-state <path> --migration-dir <dir> [--restart-from-round0]` | Create, resume, reuse, or explicitly recover deterministic convergence state |
|
|
@@ -856,7 +856,7 @@ The `okstra` Node CLI (`bin/okstra`) provides both installer/admin commands and
|
|
|
856
856
|
| `okstra model-io active-context-input --project-root <dir> --run-manifest <path>` | Resolve the prior implementation-planning active context only through the current project and run authority, then emit fixed fields such as the executor base ref. Caller-supplied active-context paths are not accepted. |
|
|
857
857
|
| `okstra report-translate <source\|write\|check-data> --run-manifest <path> …` | Resolve the report data and translation sidecar from the run manifest. `source` emits a source digest with the fixed translation queue; `write` requires that digest and rejects a stale report; `check-data` verifies the derived sidecar. Models never choose the data or sidecar path. |
|
|
858
858
|
| `okstra convergence prepare-groups --run-manifest <path> --input <grouping.md>` | Parse fixed grouping Markdown, validate distinct per-worker evidence and group semantics against the run authority, then publish the schema-valid groups artifact at the run-owned path. |
|
|
859
|
-
| `okstra manager <init\|discover-projects\|new\|task> [--json]` | Public CLI for grouping cross-project okstra tasks into manager-owned context. The default is purpose-specific fixed text for model use; `--json` preserves the machine contract and exit codes. `new project --project-root` accepts only existing directories and performs setup-equivalent registration only if `.okstra/project.json` is absent. |
|
|
859
|
+
| `okstra manager <init\|discover-projects\|new\|task\|list\|remove\|view> [--json]` | Public CLI for grouping cross-project okstra tasks into manager-owned context. The default is purpose-specific fixed text for model use; `--json` preserves the machine contract and exit codes. `new project --project-root` accepts only existing directories and performs setup-equivalent registration only if `.okstra/project.json` is absent. `list managers`, `list projects --manager-id <id>` and `list tasks --manager-id <id>` enumerate manager state; `view --manager-id <id>` writes `~/.okstra/managers/<id>/view/index.html` and prints its path and `file://` URL. `task split --plan <json>` writes one validated brief with a `## Project Scope` section into each project an issue is assigned to and registers those children; `task run` then passes `--task-brief`. `list task-groups` lists groups including empty ones; `task update` edits a task's objective, common brief or progress mode; `remove project`, `remove task`, `remove task-group` and `task remove-child` print their targets and delete manager files only with `--confirm`, and `remove project` keeps the project's children marked unlinked. |
|
|
860
860
|
| `okstra rollup [--task-group <group>] [--project-root <dir>] [--cwd <dir>] [--text\|--json]` | Read-only backend for the okstra-rollup skill. `--text` emits ordered fixed labels for model use. The default and `--json` preserve the full machine JSON contract and exit codes. Omitting `--task-group` targets the whole project catalog. |
|
|
861
861
|
| `okstra usage-report [--days <positive-int>] [--project-root <dir>] [--cwd <dir>] [--text\|--json]` | Read-only backend for the okstra-usage skill. `--text` emits ordered fixed labels for model use. The default and `--json` preserve the full machine JSON contract and exit codes. Defaults to the current project's last 30 days. |
|
|
862
862
|
| `okstra worker-state transition --team-state <path> --worker <id> --status <in-progress\|completed\|timeout\|error\|not-run> [--reason <text>] [--model <execution-value>]` | Atomically update one persisted worker row. `in-progress` records the authoritative `startedAt` and clears `endedAt`; terminal states record `endedAt`; `timeout`, `error`, and `not-run` require a reason. Dispatch adapters use this same transition path, so CLI-backed and in-process orchestration share the status timestamp contract |
|
|
@@ -866,6 +866,7 @@ The `okstra` Node CLI (`bin/okstra`) provides both installer/admin commands and
|
|
|
866
866
|
| `okstra log-report [--project-root <dir>] [--cwd <dir>] [--top <N>] [--json]` | Read-only inventory of wrapper transcript `.log` files and their sibling prompt `.md` files. Each ranked entry preserves `path` / `sizeBytes` for compatibility and also reports `transcriptPath`, `transcriptBytes`, `promptPath`, `promptBytes`, and `transcriptToPromptRatio`; totals distinguish prompt bytes from transcript bytes and count paired files. Ranking remains transcript-size descending |
|
|
867
867
|
| `okstra recap <assemble\|record\|note> (<task-root\|task-key> \| --task-group <group>) …` | Backend for the okstra-inspect `recap` facet. `assemble` is read-only: for a task it prints a JSON summary of phase transitions across its runs; with `--task-group` it prints the group's start order (briefs in ordinal order, each `done` / `in progress` / `not started` from the catalog's task-manifests, memory entries only for tasks the catalog does not know) and every recorded task's latest conclusion from `group-context.md`'s Task Memory. `okstra model-io recap-input --task-group <group>` is the fixed-text projection of the same join. `record --kind <summary\|qa> --mode <artifact\|code> --answer <text> [--question <text>] [--citation <path:line> …]` appends one line to `<task-root>/recap/recap-log.jsonl`, or with `--task-group` to `.okstra/tasks/<group>/.recap/recap-log.jsonl`, and never mutates other artifacts. `note` is task-only. `note --kind <verification-evidence\|decision-draft\|analysis-note> --slug <topic> --purpose <text> --scope-note <text> (--body <markdown>\|--body-file <path>)` writes an agent-authored note to `<task-root>/notes/` and prints its path plus the `--clarification-response` argument for feeding it into a later run |
|
|
868
868
|
| `okstra user-response <list-view\|show-view\|begin\|answer\|plan-decision\|legacy-report-authoring\|finalize> …` | Backend for the `/okstra-user-response` skill. `list-view` and `show-view --report <md\|data.json> --project-root <dir>` are fixed-text model views; `show-view` validates that the report belongs to the explicit project root and prints each open row's why-asked line, linked plan items, and cited `path:line` artifacts so the skill can read them before asking. The legacy `list` and `show` JSON reads retain their automation-compatible fields. `begin --report <md\|data.json> --task-key <key>` returns an opaque transaction id. A predefined clarification choice uses `answer --transaction <id> --clarification-id <C-NNN> --kind <kind> --option-number <N>`; Python resolves the answer, disposition, reach, and scope effects from the validated report. Direct input instead uses `--disposition <answer\|reframe> --value-file <md> [--rationale-file <md>]`. Every value, rationale, and reason file must be a regular file under `<PROJECT_ROOT>/.okstra/tmp/user-response/`; external paths and symbolic links are rejected. `plan-decision` accepts `approved`, `revision-requested`, or `rejected`, validates any `--implementation-option` against the report candidates, and requires `--reason-file` for the latter two statuses. `legacy-report-authoring` is restricted to report contract 2.0. `finalize` validates the complete existing sidecar before a lossless merge, uses compare-and-swap under a run-local lock, and atomically publishes only the user-owned sidecar; exit 0 ok / 1 error. |
|
|
869
|
+
| `okstra option-comparison --report <data.json\|md>` | Read-only backend for the okstra-run comparison material. Prints one implementation-option-selection report's comparison facts as JSON: `criteria` (the eight evaluation criteria and their weights), `workers` (voting analysts in first-seen order), and per ranked direction `scores`, `scoreRationales`, the recorded `weightedScore` (publication already checks it against the recalculated value), `coverage` (verdict, counts, requirement ids), `safetyBlockers` and `unresolvedFeasibilityFacts` counts, and `votes` per worker (verdict, rationale, counterevidence); plus the report's `narrative` texts and `nextStep`, which is the next-phase pointer rationale. Exits 2 when the record has no `implementationOptionSelection` block or ranks no direction. |
|
|
869
870
|
| `okstra pr <template\|branches\|gen> … [--json]` | Backend for the okstra-pr-gen skill. Git-only—no project registration required. `template list\|show <name\|default>\|add --name <name> (--content <text>\|--file <path>)\|path` manages PR body templates under `~/.okstra/template/pr/` (bundled fallback `src/commands/pr/default.md`); `branches` recommends a base branch; `gen --base <ref> [--template <name\|default>]` emits fixed `Base`, `Current branch`, `Template name`, `Commits`, `Diff stat`, and `Template` sections by default. `--json` preserves the machine bundle for automation. |
|
|
870
871
|
| `okstra migrate [--apply] [--cwd <dir>] [--quiet]` | One-time migration of the project artifact root from `.project-docs/okstra/` to `.okstra/`. It is a dry run by default; `--apply` performs the move with `git mv` in a Git worktree, removes an empty `.project-docs/`, and synchronizes the `<PROJECT>/CLAUDE.md` import line, `.gitignore`, the project's rows in `~/.okstra/{recent,active}.jsonl`, and `~/.okstra/worktrees/registry.json`. It exits 1 if `.okstra/` already exists or the legacy directory is absent. Scheduled for removal by the end of v0.x |
|
|
871
872
|
| `okstra task-list [--project-root <path>]` | Combine `list_project_tasks` and `read_latest_task` into JSON containing the task catalog and latest task |
|
|
@@ -879,14 +880,16 @@ The `okstra` Node CLI (`bin/okstra`) provides both installer/admin commands and
|
|
|
879
880
|
| `okstra worktree-lookup <project-id> <task-group> <task-id>` | Return the `worktree_registry.lookup` result: reserved path, branch, base ref, and current status |
|
|
880
881
|
| `okstra worktree-status [--path <dir>] [--check-clean]` | Answer "is this worktree clean?" over source paths only, excluding what okstra provisioned there — `.okstra`, the configured sync entries (`.project-docs`, `.claude`, …), and any nested stage worktree. A bare `git status --porcelain` in a task worktree is never empty for that reason, so a plan step asserting a clean tree with one fails on okstra's scaffolding instead of on the stage's own work; this is the same gate `handoff` and stage integration use. Output is JSON `{ ok, path, clean, entries, excluded }` where `entries` holds the `git status --short` rows that made it dirty. Exit code is 0 regardless unless `--check-clean` is given, which exits 1 on a dirty tree so it can stand as a shell assertion (`okstra worktree-status --check-clean`). okstra writes `stage-<N>-exit` itself when it settles the stage, so a plan step must not tag. A path outside a git work tree exits 2 rather than reporting a clean tree |
|
|
881
882
|
| `okstra plan-validate <plan-path>` | Run `_validate_approved_plan` and report frontmatter `approved` recognition plus unresolved Blocks=approval rows |
|
|
882
|
-
| `okstra render-bundle <args…> [--stage <auto\|N>] [--stages <csv>]` | Thin shim over `prepare_task_bundle(render_only=True)` with the same signature as `python3 -m okstra_ctl.run --render-only`. `--stage` is for `implementation` and `final-verification`: for implementation, `auto` (default) selects the earliest incomplete stage with satisfied dependencies, while `<N>` forces a stage; for final-verification, `<N>` verifies one stage with artifacts under `runs/final-verification/stage-<N>/` and a `-fv-s<N>` team suffix, while an empty value performs whole-task verification with the flat layout. The separate `--stages <csv>` channel is for `release-handoff`:
|
|
883
|
+
| `okstra render-bundle <args…> [--stage <auto\|N>] [--stages <csv>]` | Thin shim over `prepare_task_bundle(render_only=True)` with the same signature as `python3 -m okstra_ctl.run --render-only`. `--stage` is for `implementation` and `final-verification`: for implementation, `auto` (default) selects the earliest incomplete stage with satisfied dependencies, while `<N>` forces a stage; for final-verification, `<N>` verifies one stage with artifacts under `runs/final-verification/stage-<N>/` and a `-fv-s<N>` team suffix, while an empty value performs whole-task verification with the flat layout. The separate `--stages <csv>` channel is for `release-handoff`: it names the stages to open a PR for, one PR per stage, and an empty value takes every eligible stage. Preparation enforces eligibility—`done` + accepted `verified` + not yet `pr`—and automatically creates an input document that cites verification reports |
|
|
883
884
|
| `okstra profile show <task-type> [--resolved]` | Print a phase profile. `--resolved` expands its `{{INCLUDE:}}` targets and appends the lazy-read sidecars named in the profile body — transitively, because sidecars name sidecars of their own (`_implementation-executor.md` points at the coding-conventions preflight, the diff-review sweep, and the completion self-check). That matters because a profile is assembled from three places, so grepping only the top-level file returns false negatives: `grep clarification prompts/profiles/implementation.md` finds nothing while the assembled profile has many hits. One grep over this output answers whether a task-type covers a rule. The sidecar list is read from the profile body, never hard-coded, so a newly added sidecar is picked up without a code change. Read-only: it writes no manifest and registers no run, which is what separates it from `render-bundle` — `render-bundle` answers the same question but records a run in `recent.jsonl`, so it cannot be used to look something up. Exits 2 for an unknown task-type |
|
|
884
885
|
| `okstra codex-run <args…>` | Codex lead-adapter dry-run entry point. Accepts the same arguments as `render-bundle` but owns `--render-only --lead-runtime codex`. It prepares the task bundle and prints the prompt for the Codex lead without dispatching workers |
|
|
885
886
|
| `okstra worker-dispatch --project-root <dir> --run-manifest <path> [--workers <csv>] [--dry-run]` | Provider-neutral deterministic dispatcher for `runner=cli-wrapper` assignments. It verifies each adjacent invocation specification against the immutable run manifest immediately before process creation and records `core-pre-dispatch`; native-session rows stay with the host. The default selects CLI analysis assignments only. Phase 6 uses explicit `--workers report-writer`, and a mixed analysis/report batch is rejected. `--dry-run` performs the same verification and resolution without starting a provider process. |
|
|
886
887
|
| `okstra codex-dispatch --project-root <dir> --run-manifest <path> [--workers <csv>] [--dry-run]` | Compatibility alias for `okstra worker-dispatch`; it no longer selects a Codex-only transport-agent path. |
|
|
888
|
+
| `okstra agent-prompt resolve-operation --operation <id> [--json]` | Print what a non-run operation runs: its duty, its canonical role, the worker count, and one slot line per worker carrying that slot's provider and model reference. The operation contract (`agents/operations/<id>.json`) owns the duty and the count; the models come from the same project/global/bundled default chain a run uses, one distinct model per slot. A machine with fewer distinct models than the contract requires fails here rather than dispatching a short roster. The default output is fixed text because a skill body must not instruct a model to parse okstra-owned JSON; `--json` is for programmatic callers. |
|
|
887
889
|
| `okstra agent-prompt jobs --project-root <dir> --run-manifest <path> --dispatch-kind <kind> --metadata <path> [--metadata <path>] --out <path> [--json]` | Generate an immutable v2 jobs file from verified invocation metadata. Reads canonical identity, role, five digests, and actual result anchors; validates the full batch through the dispatch consumer before publishing. Rejects mixed runs or dispatch kinds, duplicate attempts, and translator input (use canonical `worker-dispatch --workers translator`). Reuses identical output; preserves differing output and requests a new `--out` path. Does not launch workers. |
|
|
888
890
|
| `okstra agent-prompt materialize\|check-corrections\|apply-corrections\|verify\|record-dispatch\|link-result\|reject-result\|abandon-attempt\|materialize-result\|complete\|verify-completion` | Internal invocation-contract CLI. `materialize` composes model assignment, functional duty, and task instructions; `verify` rejects identity, path, snapshot, assignment, source, or digest drift. Every run-branch report-writer prompt gets its `## Output` section (narrative, pointer record, reading audit) rendered by okstra, and an instruction body that writes a `## Output` or `## Corrections` heading is refused. A corrective report-writer round — the narrative at `reportNarrativePath` already exists and its structure parses, value defects included — must pass `--corrections <ledger>` (`schemas/report-writer-corrections-v1.0.schema.json`: `replace` / `remove` / `add` / `move` / `rewrite` entries keyed by the validator's field-path grammar, `baseNarrativePath` naming a preserved copy of the attempt, and optional `baseNarrativeSha256` binding that version): the ledger is applied to that base and checked against the writer-owned schema and the task's semantic validator before dispatch, every defect is reported at once, and okstra renders the prompt's `## Corrections` section from it; a report-writer materialization without a ledger over such a narrative is refused before any prompt is written, while a narrative whose structure does not parse (line grammar, unknown top-level field) is re-authored without one. `check-corrections --run-manifest <path> --corrections <ledger> [--json]` runs the same check without materializing (exit 1 lists the defects; `mechanical: true` means every entry is a validated `replace`, `remove`, `add`, or `move`, including derived planning step counts). `apply-corrections` with the same arguments applies such a mechanical ledger without a writer round: it writes the corrected narrative to `reportNarrativePath` and records a `lead-correction-applied` activity row (`evidenceRefs` = ledger path + correction ids) through the run's activity contract; `--rewrite-results <file>` also accepts hash-bound replacement values for exactly the requested rewrite ids. Correction-only materialization sends those target fields, evidence, and constraints instead of the initial instructions and complete synthesis packet; the runtime merges the submitted values and checks the complete narrative before writing. It refuses unresolved `rewrite` entries or any defect, a stale live narrative, a base that is the live narrative, a run without `activityContractVersion` 1, and a ledger already applied. An empty ledger can preflight the initial writer result and derive `stageMap[].stepCount` from matching execution rows without another writer call. Run-backed calls resolve `assignmentRef` from the manifest, enforce `authorizedPaths`, and reject real-path or symbolic-link escape. `record-dispatch` records a verified host-native specification before dispatch and `link-result` binds the accepted result; one result path belongs to one dispatch, so a corrective round retires the first attempt with `reject-result --dispatch-id <first> --superseded-by <corrective> --reason <text>` before the new link is accepted — the rejected row stays in `agentResultLinks` carrying `supersededBy` and `rejectionReason` rather than being deleted. The corrective dispatch is a new invocation: an invocation whose last attempt finished with a mutation takes no further attempt (`execution_manifest._validate_next_attempt` lets only `failed-no-mutation` be followed), so a retry attempt of the rejected invocation itself is refused by the manifest, and `reject-result` does not make it possible. `abandon-attempt --invocation-ref <ref> --reason <text>` closes a started attempt whose worker died without producing a result — the one case neither `link-result` (which needs the result file) nor the dispatch-failure path covers — so a retry can follow it instead of the run having to be re-rendered. It refuses any attempt whose `writePolicy.sourcePolicy.mode` is not `source-readonly`: closing an attempt records `failed-no-mutation`, which is true by policy for a read-only worker and a guess for a mutating one. Standalone calls are identified by `(purpose, invocationId)` under `.okstra/agent-invocations/<purpose>/`; they publish a canonical result envelope and publish the completion marker last. Consumers use only the `returnedBody` from `verify-completion`. Metadata contains exactly `catalogDigest`, `assignmentDigest`, `dutyDigest`, `instructionDigest`, and `promptDigest`; JSON inputs use UTF-8, sorted keys, compact separators, and no non-finite values, while duty files use versioned sorted-name/byte framing. Instruction sources use `{kind: project\|runtime, path: <relative POSIX path>}` and never persist an installed absolute runtime path. A published prompt is immutable, so re-running `materialize` with an edited instruction file fails as `existing_invocation_conflict`; `--replace-undispatched` is the one exit, for a call that failed a pre-dispatch gate and therefore ran nowhere — it covers a differing prompt and a differing metadata alike, since the two are published together and describe one call. It republishes prompt and metadata together, and it is verified rather than trusted — a row in `agentDispatches` or `workerDispatches` naming this `invocationId` refuses the replacement and names the dispatch that used it. |
|
|
889
|
-
| `okstra
|
|
891
|
+
| `okstra agent-prompt refreeze-contracts --project-root <dir> --run-manifest <path> [--json]` | Re-freeze one run's duty contract snapshot in the installed format and stamp `agentContract.catalogDigest` and `contractFormatVersion` on its run manifest. A run freezes its contracts at prepare time and pins their digest; installing a release that changed the contract format leaves that digest unmatchable, so the run can materialize no further prompt and `materialize` stops with the format message naming this command. It replaces the frozen directory's contents (no file of the old format is kept), touches no prompt, result or ledger, and reports `changed: false` when the run is already on the installed format. User-invoked recovery only — nothing runs it automatically, because a run's contracts are frozen on purpose. |
|
|
892
|
+
| `okstra team dispatch --project-root <dir> --run-manifest <path> [--workers <csv>] [--jobs-file <path>] [--dry-run]` / `okstra team await --project-root <dir> --run-manifest <path> [--json]` / `okstra team teardown --project-root <dir> --run-manifest <path> [--dry-run] [--json]` | Read a `leadRuntime=external` run manifest and dispatch, await, or tear down pane-backed workers. Default dispatch excludes report writer; Phase 6 selects it explicitly, and mixed analysis/report jobs are rejected. If a pane cannot be opened, gracefully degrade to the CLI wrapper, print a `DEGRADED <role>: cmux-pane -> cli-wrapper (<why>)` line, and record the fallback in `workerDispatches[].degradedFrom` with the reason in `degradedReason`. A degraded worker is not waited for inside the dispatch — it settles through `okstra team await` like a pane worker, so the round still runs concurrently |
|
|
890
893
|
| `okstra agent-activity append --project-root <dir> --run-manifest <path> --kind <kind> --agent <assigned-id> (--summary <text>\|--summary-file <markdown>) --outcome <outcome> [--plan-item-id <current-id>]… [--command <text> --command-cwd <dir> --command-exit-code <n> --command-output-file <markdown>] [--request-ref <returned-ref>]` | Append one structured activity after checking the agent against this run's role assignments and every plan item against its current convergence state. Python returns an `activityRequestRef`; supply only that returned value with `--request-ref` to retry idempotently. A new call without it remains a distinct activity even with identical contents. Legacy JSON command records remain automation compatibility only. |
|
|
891
894
|
| `okstra agent-activity project --project-root <dir> --run-manifest <path> --data <data.json>` | Project this run's canonical activity events into `agentActivity[]`. The command preserves event order, rejects duplicate or decreasing activity IDs, and replaces no other report field. A historical manifest without `activityContractVersion: 1` returns an empty projection and leaves data.json unchanged. Normal Phase 7 execution reaches this behavior through `report-finalize`; use the standalone command only for diagnostics. |
|
|
892
895
|
| `okstra lead-progress append --project-root <dir> --run-manifest <path> --phase <phase-id> [--worker <role>] [--field NAME=VALUE]… [--detail <text>]` | Append one `PROGRESS:` checkpoint to the run's `leadEventsPath` and print the line to emit to the user as `progressLine`. The checkpoint is what `validate_session_conformance.py` reads, and on a host whose adapter declares `sessionAccounting: artifact-only` the ledger is the only place it can read one — a conversation line alone is not retained there. `--phase` accepts the phase ids the lead contract's "Progress reporting (BLOCKING)" list defines; the fixed-prose checkpoints render their contract wording without `--detail`. `--worker` is resolved against team-state and rewritten to the roster `workers[].role` the per-worker checks match, so a phase-specific functional label still lands on the right worker; a name that matches no roster row is written through with a note on stderr. |
|
|
@@ -6,8 +6,9 @@ Use this matrix before changing high-risk repo contracts. Update the source file
|
|
|
6
6
|
|---|---|---|
|
|
7
7
|
| Add CLI flag | `src/`, `scripts/okstra_ctl/run.py`, `docs/cli.md`, `prompts/wizard/` | JS CLI tests and pytest CLI contracts |
|
|
8
8
|
| Add Node subcommand | `src/cli-registry.mts`, `src/commands/`, `docs/cli.md`, `docs/project-structure-overview.md` | `tests-js/cli-registry.test.mjs` plus command-specific JS/Python tests |
|
|
9
|
-
| Add public skill | `src/lib/skill-catalog.mts`, `.claude-plugin/plugin.json`, `skills/<name>/SKILL.md`, `docs/
|
|
10
|
-
| Change manager contract | `scripts/okstra_ctl/manager_*.py`, `skills/okstra-manager/SKILL.md`, `docs/
|
|
9
|
+
| Add public skill | `src/lib/skill-catalog.mts`, `.claude-plugin/plugin.json`, `skills/<name>/SKILL.md`, `docs/skills/<name>.md`, `docs/skills/README.md`, `docs/project-structure-overview.md`, `README.md` | `tests-js/skill-catalog.test.mjs`, `tests/contract/test_docs_runtime_contract.py` |
|
|
10
|
+
| Change manager contract | `scripts/okstra_ctl/manager_*.py`, `skills/okstra-manager/SKILL.md`, `docs/skills/okstra-manager.md`, `docs/cli.md`, `docs/architecture/storage-model.md` | `tests-js/cli-wrapper-contract.test.mjs`, `tests/test_okstra_manager_*.py` |
|
|
11
|
+
| Change a skill's behaviour | `skills/<name>/SKILL.md`, `docs/skills/<name>.md` (every Guarantees row names its enforcement or says `unenforced`) | `tests/contract/test_skill_specs.py` |
|
|
11
12
|
| Add phase | `scripts/okstra_ctl/workflow.py`, `prompts/profiles/`, `validators/`, `tests/` | workflow and validation contract tests |
|
|
12
13
|
| Change worker roster | `prompts/profiles/*.md`, `scripts/okstra_ctl/workers.py`, `tests/contract/test_repo_contracts.py` | worker roster contract tests |
|
|
13
14
|
| Change report section | `schemas/final-report-v2.0.schema.json`, `templates/reports/final-report-v2.template.md`, `scripts/okstra_ctl/render_final_report.py`, `validators/validate-run.py` | final-report schema, renderer, and validator tests |
|
|
@@ -227,13 +227,12 @@ Goals:
|
|
|
227
227
|
|
|
228
228
|
Cautions:
|
|
229
229
|
|
|
230
|
-
-
|
|
230
|
+
- Superseded (2026-08-13, `cf9fcfe`): the shared CLI-wrapper template and the per-provider worker parameter files this item planned to edit were removed. Worker prompts are now composed by `okstra agent-prompt materialize`, so shared worker text belongs in the materializer's inputs, not in a wrapper template.
|
|
231
231
|
- Merely moving text into a separate file can increase cost if the runtime does not inline it and the worker must read another file.
|
|
232
232
|
|
|
233
233
|
Change targets:
|
|
234
234
|
|
|
235
|
-
- `
|
|
236
|
-
- `agents/workers/antigravity-worker.params.json`
|
|
235
|
+
- `scripts/okstra_ctl/agent/prompt_cli/materialize.py` (replaces the removed per-provider worker parameter files)
|
|
237
236
|
- `prompts/lead/team-contract.md`
|
|
238
237
|
- Install/build packaging
|
|
239
238
|
|
|
@@ -138,8 +138,8 @@ Runtime/install asset changes follow this checklist:
|
|
|
138
138
|
- `runtime/templates/*` → `~/.okstra/templates/`
|
|
139
139
|
- `runtime/skills/<name>` (the fourteen user-facing skills only) → `~/.agents/skills` always, plus `~/.claude/skills` when `~/.claude` exists
|
|
140
140
|
- `runtime/prompts/*` → `~/.okstra/prompts/` (lead contracts under `prompts/lead/`, coding-preflight pack under `prompts/coding-preflight/`)
|
|
141
|
-
- the
|
|
142
|
-
- install manifests → `~/.okstra/installed-skills.json` (target-aware), `~/.okstra/installed-agents.json`
|
|
141
|
+
- `runtime/agents/*` → `~/.okstra/agents/` (the common contract, the nine role contracts under `agents/roles/`, and the non-run operation contracts under `agents/operations/`). Nothing is written to a host-global agent discovery path such as `~/.claude/agents/`; agent definitions a previous version installed there are removed only when the prior install manifest proves okstra owned them (ADR-0017)
|
|
142
|
+
- install manifests → `~/.okstra/installed-skills.json` (target-aware), `~/.okstra/installed-agents.json` (now only the record of host files to reclaim)
|
|
143
143
|
- version stamp → `~/.okstra/version`
|
|
144
144
|
|
|
145
145
|
`--link <repo>` mode is for development and symlinks installed files back to repo sources.
|
|
@@ -166,7 +166,7 @@ The Module column below is where the command's behaviour lives — a `src/` modu
|
|
|
166
166
|
| `install`, `ensure-installed` | `src/commands/lifecycle/install.mts` | Install or refresh runtime, skills, agents, templates |
|
|
167
167
|
| `uninstall` | `src/commands/lifecycle/uninstall.mts` | Remove managed runtime/skills/agents, optionally purge data |
|
|
168
168
|
| `doctor` | `src/commands/lifecycle/doctor.mts` | Diagnose runtime and Python imports |
|
|
169
|
-
| `setup` | `src/commands/lifecycle/setup.mts` | Create/update `<PROJECT_ROOT>/.okstra/project.json` |
|
|
169
|
+
| `setup` | `src/commands/lifecycle/setup.mts` | Create/update `<PROJECT_ROOT>/.okstra/project.json`; also appends/refreshes the okstra citation-guidance block in an existing `CLAUDE.md` / `AGENTS.md` via `src/lib/citation-guidance.mts` (neither file is created) |
|
|
170
170
|
| `check-project` | `src/commands/lifecycle/check-project.mts` | Verify project registration |
|
|
171
171
|
| `preflight` | `src/commands/lifecycle/preflight.mts` | One-call skill preflight: ensure-installed + check-project + host-specific runtime readiness (single JSON) |
|
|
172
172
|
| `config` | `src/commands/lifecycle/config.mts` | Read/write project/global settings such as PR template path |
|
|
@@ -327,10 +327,13 @@ Important modules:
|
|
|
327
327
|
| `plan_run_root.py` | shared helper deriving `approved_plan_path` → `plan_run_root` and back-tracing the task-key |
|
|
328
328
|
| `manager_cli.py` | `okstra manager` Python entrypoint — purpose-specific fixed text by default, machine JSON with `--json` |
|
|
329
329
|
| `manager_paths.py` | Manager state path SSOT under `~/.okstra/managers/<manager-id>/`; slug fallback uses `u-<sha1-prefix>` when a safe segment would be empty |
|
|
330
|
-
| `manager_store.py` | Manager-owned state mutation — project membership, task planning, assignment, directives, event append |
|
|
330
|
+
| `manager_store.py` | Manager-owned state mutation — project membership, task planning, assignment, directives, event append — plus the `list managers/projects/task-groups/tasks` readers, `task update`, and the `remove project/task/task-group` and `task remove-child` operations |
|
|
331
331
|
| `manager_sync.py` | One-way child project `.okstra` snapshot reader; corrupt child state becomes row-level `error` so other children continue |
|
|
332
332
|
| `manager_launch.py` | Child launch packet and manager child context renderer; records `prepared` launch metadata/events without changing project-local task state |
|
|
333
|
+
| `manager_view.py` | `okstra manager view` — renders one manager's projects, tasks, child summaries, directives and events into `view/index.html` from `templates/manager/view.template.html`; reads manager-owned files only |
|
|
334
|
+
| `manager_split.py` | `okstra manager task split` — validates a tracker split plan, renders one brief per (issue, project) with a `## Project Scope` section, checks each with `validators/validate-brief.py` before writing, and registers the children |
|
|
333
335
|
| `agent/invocation.py` | Deep invocation-contract module — composes model assignment, common/functional duty, and task instructions; publishes immutable prompt/metadata pairs; verifies five digests; owns standalone result/completion envelopes |
|
|
336
|
+
| `agent/evidence_recovery.py` | Issues a same-model, same-role evidence-recovery invocation over a terminal-state attempt — verifies the source invocation metadata and existing result, then republishes a suffixed prompt/metadata/result triple (`-evidence-recovery-<attempt>`) that preserves the original model assignment while confining the child to preserving the earlier result's evidence rather than re-running the completed work (`prepare_evidence_recovery`, driven from `dispatch_core`) |
|
|
334
337
|
| `agent/prompt_cli/` | CLI boundary for run-backed and standalone materialization/verification plus host-native dispatch and result-link records. `inputs` resolves the path arguments this model-facing surface cannot trust and `emit` writes the result; above them `run_identity` refuses a role the run never issued and `dynamic_verifier` reserves a re-verification slot only after that role qualifies; `materialize` authors the specification (every report-writer prompt gets the okstra-rendered `## Output`; with `--corrections` it runs the ledger check in `corrections` and prepends `## Corrections`; without one it refuses a corrective dispatch over a parsing narrative), `results` links what came back, and `cli` is the argparse surface with the command's canonical USAGE epilog (`check-corrections` runs the ledger check without materializing; `apply-corrections` writes a mechanical ledger to the narrative and records the `lead-correction-applied` activity row via `corrections.run_corrections_apply`) |
|
|
335
338
|
| `dispatch_state.py` | Provider-neutral `WorkerJob`, invocation metadata validation, immutable host-native dispatch/result-link recording, and shared team-state mutation helpers |
|
|
336
339
|
| `dispatch_core.py` | Backend-neutral worker dispatch core — verifies invocation metadata immediately before worker execution, then records and collects code-owned process/pane attempts shared by every lead runtime |
|
|
@@ -380,6 +383,31 @@ Important modules:
|
|
|
380
383
|
| `json_boundary.py` | strict JSON persistence boundaries for okstra-owned artifacts — a sealed `ExternalJsonSource` (validated producer + path) is the only way owned JSON is read, and `JsonBoundaryError` names artifact / reason / path when a write cannot satisfy its contract; the SSOT that keeps the model out of internal JSON key/path authorship |
|
|
381
384
|
| `fixed_text.py` | shared scalar-line format for the model-facing fixed-text projections — `scalar` neutralises complex values and control characters (backticks escaped for the code span `line` wraps it in), `block` projects a prose body outside any code span with its backticks intact, `line` renders one static-labelled Markdown list row, and `value_lines` losslessly flattens a JSON-shaped value into fixed name/order/value rows |
|
|
382
385
|
| `model_io_cli.py`, `model_io/` | renders purpose-scoped fixed Markdown input from okstra-owned JSON for the model boundary — resolves the current run/project through the run manifest (`validated_run_authority`, `canonical_run_state_artifact`) and emits only each command's allow-listed fields in fixed order instead of expanding arbitrary nested objects. `model_io_cli.py` is the argparse surface only; inside the package, `references` resolves paths and reads JSON, `lines` turns an already-read mapping into fixed Markdown and opens nothing, and `renderers` composes the two into one function per command |
|
|
386
|
+
| `assignment_environment.py` | loads ambient host-adapter facts once, outside the deterministic assignment logic; read by `run.py`, `dispatch_core.py`, the wizard's role step, and `agent-prompt materialize` |
|
|
387
|
+
| `execution_identity.py` | provider-neutral execution identity value objects — participant assignment, role execution, invocation, attempt, execution manifest — and their versioned readers |
|
|
388
|
+
| `attempt_evidence.py` | atomic attempt-evidence seals and the orchestrator-owned host event streams written around each worker attempt |
|
|
389
|
+
| `execution_mutation_audit.py` | batch-scoped source and Git mutation audit for worker invocations (snapshots taken around a dispatch batch) |
|
|
390
|
+
| `mutation_recovery.py` | recovery decisions after a sealed or unsealed implementer attempt that mutated source |
|
|
391
|
+
| `write_policy.py` | canonical invocation write policy — which paths an invocation may write — and the enforcement the runner truthfully reports; read by the provider wrapper, `worker_request.py`, `dispatch_core.py`, and report assembly |
|
|
392
|
+
| `role_requirements.py` | parses the canonical role requirements that phase profiles declare |
|
|
393
|
+
| `model_defaults.py` | pure replacement of role-model default scopes |
|
|
394
|
+
| `legacy_model_selection.py` | normalises canonical role selections and legacy provider CLI flags into one selection |
|
|
395
|
+
| `validation_contract.py` | the validation contract version pinned at prepare time (`CURRENT_VALIDATION_CONTRACT_VERSION`) |
|
|
396
|
+
| `usage_identity.py` | projects usage rows from stored execution-identity refs; shared by usage-report, time-report, error-report, and the token collector |
|
|
397
|
+
| `user_response_values.py` | value types and parsers of the `user-responses/` sidecar |
|
|
398
|
+
| `stage_map_view.py` | read-side Stage Map view behind `okstra stage-map` |
|
|
399
|
+
| `lead_progress.py` | `okstra lead-progress append` — records the lead's `PROGRESS:` checkpoints in the lead-events ledger |
|
|
400
|
+
| `plan_verify_cli.py` | `okstra plan-verify` entry point |
|
|
401
|
+
| `doctor_cli.py` | diagnostic projection that `okstra doctor` (`src/commands/lifecycle/doctor.mts`) calls |
|
|
402
|
+
| `worktree_cli.py` | handlers behind `okstra worktree-lookup` and `okstra worktree-status` |
|
|
403
|
+
| `interactive_cli.py` | lookup helpers for the `okstra.sh` interactive input path (`scripts/lib/okstra/interactive.sh`) |
|
|
404
|
+
| `brief_frontmatter.py` | shared lightweight parser for a brief's frontmatter; read by `run.py`, direct completion, the task-group context, the wizard's brief suggestions, and the improvement-report validator |
|
|
405
|
+
| `convergence_provenance.py` | Round-0 grouping provenance — checks that every source item a group cites exists in the canonical worker result; shared by the convergence engine, the critic prompts, and `validate-run.py` |
|
|
406
|
+
| `verdict_blocks.py` | parser for the worker verdict block that plan-body verification and convergence re-verification share |
|
|
407
|
+
| `worker_artifacts.py` | the roster worker-id vocabulary and the artifact paths derived from it |
|
|
408
|
+
| `worker_state.py` | `okstra worker-state transition` — the authoritative status transitions of one persisted team-state |
|
|
409
|
+
| `usage_cells.py` | how a token, cost, or duration figure reads in a report cell; shared by the Markdown and HTML report renderers |
|
|
410
|
+
| `report_contract.py` | single registry of the public final-report task contracts, read by prepare, rendering, approval decisions, and the report synthesis packet |
|
|
383
411
|
|
|
384
412
|
> `i18n.py` (the final-report i18n dictionary loader + Jinja2 lookup) is an intentionally undocumented internal helper — it is a render helper that users and contributors do not need to know about in the canonical docs, so it is excluded from the module map.
|
|
385
413
|
|
|
@@ -430,6 +458,8 @@ Token/cost accounting:
|
|
|
430
458
|
| `templates/worker-prompt-preamble.md` | Initial analysis audience procedure and output contract |
|
|
431
459
|
| `templates/implementation-worker-preamble.md` | Shared implementation executor/verifier procedure, including coding-preflight and worktree rules |
|
|
432
460
|
| `templates/report-writer-prompt-preamble.md` | Report-writer input and authoring procedure without analysis or implementation instructions |
|
|
461
|
+
| `templates/translator-prompt-preamble.md` | Translator output ownership and translation conduct, delivered to every provider regardless of host |
|
|
462
|
+
| `scripts/okstra_ctl/adapters/hosts/claude-code/worker-session.md` | Rules that hold because a worker runs inside the lead's Claude Code session; delivered to `runner=native-session` prompts only |
|
|
433
463
|
| `templates/worker-error-contract.md` | Audience-neutral error-path, sidecar schema, and write protocol shared by every initial worker |
|
|
434
464
|
|
|
435
465
|
### 4.8 `schemas/`
|
|
@@ -487,11 +517,11 @@ Boilerplate shared by several skills (bash invocation rule, outdated-CLI preflig
|
|
|
487
517
|
|
|
488
518
|
| File | Role |
|
|
489
519
|
|---|---|
|
|
490
|
-
| `agents/
|
|
491
|
-
| `agents/
|
|
492
|
-
| `agents/
|
|
520
|
+
| `agents/common.json` | The contract every okstra LLM call carries, ahead of role and duty |
|
|
521
|
+
| `agents/roles/<role>.json` | One of the nine canonical roles: identity, responsibilities, required capabilities, prohibitions |
|
|
522
|
+
| `agents/operations/<operation>.json` | A non-run operation's duty and worker count (`okstra agent-prompt resolve-operation`) |
|
|
493
523
|
|
|
494
|
-
These
|
|
524
|
+
These are provider-neutral contracts rendered into every dispatch prompt, not host agent definitions: okstra registers nothing in a host-global discovery path (ADR-0017). Non-native providers execute through the deterministic `worker-dispatch` process boundary. The neutral lead lifecycle contract lives at `prompts/lead/okstra-lead-contract.md`. Executable host strategies and their relay contracts live together under `scripts/okstra_ctl/adapters/hosts/<host-id>/`; `prompts/lead/adapters/cmux.md` remains the environment-selected cmux worker-backend contract. Lead resources are installed under `~/.okstra/prompts/lead/`, while executable host adapters are installed under `~/.okstra/lib/python/okstra_ctl/adapters/hosts/`. They are runtime resources, not agent skills.
|
|
495
525
|
|
|
496
526
|
### 4.12 `tests/` and `tests-e2e/`
|
|
497
527
|
|
|
@@ -586,7 +616,6 @@ Both Markdown and HTML are derived, not authoring sources. The schema is the con
|
|
|
586
616
|
- `scripts/okstra_ctl/domain/role.py` — canonical roles and duty mapping.
|
|
587
617
|
- `scripts/okstra_ctl/model_pool.py` — unified catalog lookup.
|
|
588
618
|
- `scripts/okstra_ctl/model_cli.py` — `okstra model list` and atomic `modelDefaults` writes. No inference call.
|
|
589
|
-
- `scripts/okstra_ctl/pane_title.py` — pane titles from stored `executionLabel`.
|
|
590
619
|
- `scripts/okstra_ctl/doctor.py` — `model_pool_diagnostics()` for `okstra doctor --json`.
|
|
591
620
|
|
|
592
621
|
---
|
|
@@ -55,7 +55,7 @@ Launch selection is role slots and model refs, not a provider roster. The wizard
|
|
|
55
55
|
| okstra-run skill procedure | [`skills/okstra-run/SKILL.md`](../../skills/okstra-run/SKILL.md) |
|
|
56
56
|
| wizard state machine | [`scripts/okstra_ctl/wizard/`](../../scripts/okstra_ctl/wizard/) |
|
|
57
57
|
| wizard prompt text | [`prompts/wizard/prompts.ko.json`](../../prompts/wizard/prompts.ko.json) |
|
|
58
|
-
| render-bundle Node shim | [`src/commands/execute/render-bundle.
|
|
58
|
+
| render-bundle Node shim | [`src/commands/execute/render-bundle.mts`](../../src/commands/execute/render-bundle.mts) |
|
|
59
59
|
| single entrypoint for bundle creation | [`scripts/okstra_ctl/run.py`](../../scripts/okstra_ctl/run.py) |
|
|
60
60
|
| implementation stage selection/provisioning | [`scripts/okstra_ctl/implementation_stage.py`](../../scripts/okstra_ctl/implementation_stage.py) |
|
|
61
61
|
| Stage Lifecycle Snapshot + stage target/base/verification policy | [`scripts/okstra_ctl/stage_targets.py`](../../scripts/okstra_ctl/stage_targets.py) |
|
|
@@ -95,7 +95,7 @@ sequenceDiagram
|
|
|
95
95
|
Skill->>FS: read lead-execution-prompt.md
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
The Node shim for `render-bundle` is [`src/commands/execute/render-bundle.
|
|
98
|
+
The Node shim for `render-bundle` is [`src/commands/execute/render-bundle.mts`](../../src/commands/execute/render-bundle.mts). This shim attaches the `--workspace-root`, `--render-only`, and runtime resolution arguments directly. As a result, on the okstra-run path the initial run status starts at `prepared` and the task status starts at `ready-for-lead`.
|
|
99
99
|
|
|
100
100
|
## 5. Okstra lead phase 1-7
|
|
101
101
|
|
|
@@ -118,10 +118,12 @@ flowchart TD
|
|
|
118
118
|
|
|
119
119
|
`## 7. Final Verdict` must contain exactly one `Verdict Token` field, and its value is one of the following three.
|
|
120
120
|
|
|
121
|
-
- `accepted`: a state that becomes a
|
|
121
|
+
- `accepted`: a state that becomes a release-handoff candidate — whole-task for every stage it covers, single-stage for that one stage's PR
|
|
122
122
|
- `conditional-accept`: all conditions must be stated explicitly, and when a condition is a gate it blocks the next phase
|
|
123
123
|
- `blocked`: a state that has acceptance blockers and cannot proceed to release-handoff
|
|
124
124
|
|
|
125
|
+
A blocked or conditional run routes to the phase that owns the defect. When every remaining blocker is an environment or configuration fault this report already diagnosed - a `qaCommands` entry naming a path that no longer exists, a missing credential, a stale fixture - the target is `final-verification` itself: repair the configuration and re-verify the same head, rather than spending a root-cause phase on a cause that is already known.
|
|
126
|
+
|
|
125
127
|
Vague phrasings such as "looks good" or "mostly ready" are not allowed.
|
|
126
128
|
|
|
127
129
|
## 6. Deliverables
|
|
@@ -170,7 +170,7 @@ flowchart LR
|
|
|
170
170
|
|
|
171
171
|
Stage selection is `auto` or a number. If `--stage` comes from another task-type, it is a `PrepareError`. The runtime reads `done`/`started` of `consumers.jsonl`, carry sidecar backfill, and the active stage-key of the registry together in the Stage Lifecycle Snapshot, and excludes occupied stages. The Snapshot is not a new stored file but a read-side view of `stage_targets.py`.
|
|
172
172
|
|
|
173
|
-
The stage worktree base is decided by dependency shape. An independent stage uses the task-key worktree HEAD fixed at first implementation entry as its anchor, and a single-dependency stage branches from the predecessor stage's done `head_commit`. A multi-dependency stage branches from the task-
|
|
173
|
+
The stage worktree base is decided by dependency shape. An independent stage uses the task-key worktree HEAD fixed at first implementation entry as its anchor, and a single-dependency stage branches from the predecessor stage's done `head_commit`. A multi-dependency stage branches from a commit holding exactly its predecessors: the predecessor commit that already contains the others, or else an integration branch merging them (`<work-category-namespace>/<task-id-segment>-g<n1>-<n2>`). okstra creates that branch itself, so a predecessor that has not been merged into the task branch no longer blocks the stage; release-handoff later reuses the same branch as that stage's PR base.
|
|
174
174
|
|
|
175
175
|
## 6. Deliverables
|
|
176
176
|
|