okstra 0.173.0 → 0.175.1
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 +18 -9
- package/bin/okstra +8 -4
- package/dist/cli-registry.d.mts +16 -0
- package/dist/cli-registry.mjs +560 -0
- package/dist/cli-registry.mjs.map +1 -0
- package/dist/commands/execute/agent-prompt.d.mts +1 -0
- package/{src → dist}/commands/execute/agent-prompt.mjs +10 -11
- package/dist/commands/execute/agent-prompt.mjs.map +1 -0
- package/dist/commands/execute/codex-dispatch.d.mts +3 -0
- package/dist/commands/execute/codex-dispatch.mjs +6 -0
- package/dist/commands/execute/codex-dispatch.mjs.map +1 -0
- package/dist/commands/execute/codex-run.d.mts +3 -0
- package/{src → dist}/commands/execute/codex-run.mjs +30 -37
- package/dist/commands/execute/codex-run.mjs.map +1 -0
- package/dist/commands/execute/convergence.d.mts +1 -0
- package/{src → dist}/commands/execute/convergence.mjs +15 -16
- package/dist/commands/execute/convergence.mjs.map +1 -0
- package/dist/commands/execute/error-log.d.mts +1 -0
- package/{src → dist}/commands/execute/error-log.mjs +2 -3
- package/dist/commands/execute/error-log.mjs.map +1 -0
- package/dist/commands/execute/git-reconcile.d.mts +1 -0
- package/{src → dist}/commands/execute/git-reconcile.mjs +10 -11
- package/dist/commands/execute/git-reconcile.mjs.map +1 -0
- package/dist/commands/execute/handoff.d.mts +1 -0
- package/{src → dist}/commands/execute/handoff.mjs +10 -11
- package/dist/commands/execute/handoff.mjs.map +1 -0
- package/dist/commands/execute/incremental-carry.d.mts +1 -0
- package/{src → dist}/commands/execute/incremental-carry.mjs +2 -3
- package/dist/commands/execute/incremental-carry.mjs.map +1 -0
- package/dist/commands/execute/incremental-scope.d.mts +1 -0
- package/{src → dist}/commands/execute/incremental-scope.mjs +2 -3
- package/dist/commands/execute/incremental-scope.mjs.map +1 -0
- package/dist/commands/execute/integrate-stages.d.mts +1 -0
- package/{src → dist}/commands/execute/integrate-stages.mjs +10 -11
- package/dist/commands/execute/integrate-stages.mjs.map +1 -0
- package/dist/commands/execute/pane-title.d.mts +1 -0
- package/dist/commands/execute/pane-title.mjs +20 -0
- package/dist/commands/execute/pane-title.mjs.map +1 -0
- package/dist/commands/execute/plan-items.d.mts +1 -0
- package/dist/commands/execute/plan-items.mjs +9 -0
- package/dist/commands/execute/plan-items.mjs.map +1 -0
- package/dist/commands/execute/plan-validate.d.mts +1 -0
- package/dist/commands/execute/plan-validate.mjs +68 -0
- package/dist/commands/execute/plan-validate.mjs.map +1 -0
- package/dist/commands/execute/plan-verify.d.mts +1 -0
- package/{src → dist}/commands/execute/plan-verify.mjs +13 -16
- package/dist/commands/execute/plan-verify.mjs.map +1 -0
- package/dist/commands/execute/render-bundle.d.mts +3 -0
- package/{src → dist}/commands/execute/render-bundle.mjs +65 -61
- package/dist/commands/execute/render-bundle.mjs.map +1 -0
- package/dist/commands/execute/run.d.mts +24 -0
- package/dist/commands/execute/run.mjs +196 -0
- package/dist/commands/execute/run.mjs.map +1 -0
- package/dist/commands/execute/spawn-followups.d.mts +1 -0
- package/{src → dist}/commands/execute/spawn-followups.mjs +6 -7
- package/dist/commands/execute/spawn-followups.mjs.map +1 -0
- package/dist/commands/execute/team.d.mts +3 -0
- package/dist/commands/execute/team.mjs +56 -0
- package/dist/commands/execute/team.mjs.map +1 -0
- package/dist/commands/execute/token-usage.d.mts +1 -0
- package/{src → dist}/commands/execute/token-usage.mjs +2 -3
- package/dist/commands/execute/token-usage.mjs.map +1 -0
- package/dist/commands/execute/wizard.d.mts +8 -0
- package/dist/commands/execute/wizard.mjs +191 -0
- package/dist/commands/execute/wizard.mjs.map +1 -0
- package/dist/commands/execute/worker-audit-check.d.mts +1 -0
- package/{src → dist}/commands/execute/worker-audit-check.mjs +11 -12
- package/dist/commands/execute/worker-audit-check.mjs.map +1 -0
- package/dist/commands/execute/worker-dispatch.d.mts +7 -0
- package/{src → dist}/commands/execute/worker-dispatch.mjs +34 -46
- package/dist/commands/execute/worker-dispatch.mjs.map +1 -0
- package/dist/commands/execute/worker-state.d.mts +1 -0
- package/{src → dist}/commands/execute/worker-state.mjs +15 -16
- package/dist/commands/execute/worker-state.mjs.map +1 -0
- package/dist/commands/execute/worktree-lookup.d.mts +1 -0
- package/{src → dist}/commands/execute/worktree-lookup.mjs +38 -37
- package/dist/commands/execute/worktree-lookup.mjs.map +1 -0
- package/dist/commands/execute/worktree-status.d.mts +1 -0
- package/dist/commands/execute/worktree-status.mjs +115 -0
- package/dist/commands/execute/worktree-status.mjs.map +1 -0
- package/dist/commands/inspect/code-review.d.mts +1 -0
- package/{src → dist}/commands/inspect/code-review.mjs +16 -19
- package/dist/commands/inspect/code-review.mjs.map +1 -0
- package/dist/commands/inspect/container.d.mts +1 -0
- package/{src → dist}/commands/inspect/container.mjs +11 -13
- package/dist/commands/inspect/container.mjs.map +1 -0
- package/dist/commands/inspect/context-cost.d.mts +1 -0
- package/{src → dist}/commands/inspect/context-cost.mjs +11 -13
- package/dist/commands/inspect/context-cost.mjs.map +1 -0
- package/dist/commands/inspect/design-prep.d.mts +1 -0
- package/{src → dist}/commands/inspect/design-prep.mjs +10 -11
- package/dist/commands/inspect/design-prep.mjs.map +1 -0
- package/dist/commands/inspect/error-report.d.mts +1 -0
- package/{src → dist}/commands/inspect/error-report.mjs +11 -13
- package/dist/commands/inspect/error-report.mjs.map +1 -0
- package/dist/commands/inspect/error-zip.d.mts +1 -0
- package/{src → dist}/commands/inspect/error-zip.mjs +11 -12
- package/dist/commands/inspect/error-zip.mjs.map +1 -0
- package/dist/commands/inspect/log-report.d.mts +1 -0
- package/{src → dist}/commands/inspect/log-report.mjs +11 -13
- package/dist/commands/inspect/log-report.mjs.map +1 -0
- package/dist/commands/inspect/profile-show.d.mts +1 -0
- package/{src → dist}/commands/inspect/profile-show.mjs +10 -11
- package/dist/commands/inspect/profile-show.mjs.map +1 -0
- package/dist/commands/inspect/recap.d.mts +1 -0
- package/{src → dist}/commands/inspect/recap.mjs +11 -13
- package/dist/commands/inspect/recap.mjs.map +1 -0
- package/dist/commands/inspect/resolve-task-key.d.mts +1 -0
- package/{src → dist}/commands/inspect/resolve-task-key.mjs +11 -13
- package/dist/commands/inspect/resolve-task-key.mjs.map +1 -0
- package/dist/commands/inspect/rollup.d.mts +1 -0
- package/{src → dist}/commands/inspect/rollup.mjs +11 -13
- package/dist/commands/inspect/rollup.mjs.map +1 -0
- package/dist/commands/inspect/run-audit.d.mts +1 -0
- package/{src → dist}/commands/inspect/run-audit.mjs +11 -12
- package/dist/commands/inspect/run-audit.mjs.map +1 -0
- package/dist/commands/inspect/set-work-status.d.mts +1 -0
- package/{src → dist}/commands/inspect/set-work-status.mjs +11 -13
- package/dist/commands/inspect/set-work-status.mjs.map +1 -0
- package/dist/commands/inspect/stage-map.d.mts +1 -0
- package/dist/commands/inspect/stage-map.mjs +110 -0
- package/dist/commands/inspect/stage-map.mjs.map +1 -0
- package/dist/commands/inspect/task-list.d.mts +1 -0
- package/dist/commands/inspect/task-list.mjs +103 -0
- package/dist/commands/inspect/task-list.mjs.map +1 -0
- package/dist/commands/inspect/task-show.d.mts +1 -0
- package/dist/commands/inspect/task-show.mjs +108 -0
- package/dist/commands/inspect/task-show.mjs.map +1 -0
- package/dist/commands/inspect/time-report.d.mts +1 -0
- package/{src → dist}/commands/inspect/time-report.mjs +11 -13
- package/dist/commands/inspect/time-report.mjs.map +1 -0
- package/dist/commands/inspect/usage-report.d.mts +1 -0
- package/{src → dist}/commands/inspect/usage-report.mjs +11 -13
- package/dist/commands/inspect/usage-report.mjs.map +1 -0
- package/dist/commands/inspect/user-response.d.mts +1 -0
- package/{src → dist}/commands/inspect/user-response.mjs +10 -11
- package/dist/commands/inspect/user-response.mjs.map +1 -0
- package/dist/commands/inspect/worker-liveness.d.mts +1 -0
- package/{src → dist}/commands/inspect/worker-liveness.mjs +11 -13
- package/dist/commands/inspect/worker-liveness.mjs.map +1 -0
- package/dist/commands/lifecycle/check-project.d.mts +21 -0
- package/dist/commands/lifecycle/check-project.mjs +175 -0
- package/dist/commands/lifecycle/check-project.mjs.map +1 -0
- package/dist/commands/lifecycle/config.d.mts +1 -0
- package/dist/commands/lifecycle/config.mjs +369 -0
- package/dist/commands/lifecycle/config.mjs.map +1 -0
- package/dist/commands/lifecycle/doctor.d.mts +10 -0
- package/dist/commands/lifecycle/doctor.mjs +317 -0
- package/dist/commands/lifecycle/doctor.mjs.map +1 -0
- package/dist/commands/lifecycle/install.d.mts +17 -0
- package/dist/commands/lifecycle/install.mjs +1077 -0
- package/dist/commands/lifecycle/install.mjs.map +1 -0
- package/dist/commands/lifecycle/migrate.d.mts +1 -0
- package/{src → dist}/commands/lifecycle/migrate.mjs +10 -11
- package/dist/commands/lifecycle/migrate.mjs.map +1 -0
- package/dist/commands/lifecycle/model.d.mts +1 -0
- package/dist/commands/lifecycle/model.mjs +22 -0
- package/dist/commands/lifecycle/model.mjs.map +1 -0
- package/dist/commands/lifecycle/paths.d.mts +1 -0
- package/dist/commands/lifecycle/paths.mjs +102 -0
- package/dist/commands/lifecycle/paths.mjs.map +1 -0
- package/dist/commands/lifecycle/preflight.d.mts +1 -0
- package/dist/commands/lifecycle/preflight.mjs +124 -0
- package/dist/commands/lifecycle/preflight.mjs.map +1 -0
- package/dist/commands/lifecycle/setup.d.mts +1 -0
- package/dist/commands/lifecycle/setup.mjs +297 -0
- package/dist/commands/lifecycle/setup.mjs.map +1 -0
- package/dist/commands/lifecycle/uninstall.d.mts +4 -0
- package/dist/commands/lifecycle/uninstall.mjs +262 -0
- package/dist/commands/lifecycle/uninstall.mjs.map +1 -0
- package/dist/commands/manager.d.mts +3 -0
- package/{src → dist}/commands/manager.mjs +25 -32
- package/dist/commands/manager.mjs.map +1 -0
- package/dist/commands/memory/memory.d.mts +1 -0
- package/dist/commands/memory/memory.mjs +569 -0
- package/dist/commands/memory/memory.mjs.map +1 -0
- package/dist/commands/pr/pr.d.mts +33 -0
- package/dist/commands/pr/pr.mjs +296 -0
- package/dist/commands/pr/pr.mjs.map +1 -0
- package/dist/commands/report/agent-activity.d.mts +1 -0
- package/{src → dist}/commands/report/agent-activity.mjs +11 -12
- package/dist/commands/report/agent-activity.mjs.map +1 -0
- package/dist/commands/report/finalize.d.mts +4 -0
- package/dist/commands/report/finalize.mjs +64 -0
- package/dist/commands/report/finalize.mjs.map +1 -0
- package/dist/commands/report/inject-report-index.d.mts +1 -0
- package/{src → dist}/commands/report/inject-report-index.mjs +6 -7
- package/dist/commands/report/inject-report-index.mjs.map +1 -0
- package/dist/commands/report/render-final-report.d.mts +1 -0
- package/{src → dist}/commands/report/render-final-report.mjs +6 -7
- package/dist/commands/report/render-final-report.mjs.map +1 -0
- package/dist/commands/report/render-views.d.mts +1 -0
- package/{src → dist}/commands/report/render-views.mjs +6 -7
- package/dist/commands/report/render-views.mjs.map +1 -0
- package/dist/commands/report/translate.d.mts +1 -0
- package/{src → dist}/commands/report/translate.mjs +6 -7
- package/dist/commands/report/translate.mjs.map +1 -0
- package/dist/lib/helper-scripts.d.mts +3 -0
- package/{src → dist}/lib/helper-scripts.mjs +11 -14
- package/dist/lib/helper-scripts.mjs.map +1 -0
- package/dist/lib/host-registry-client.d.mts +25 -0
- package/dist/lib/host-registry-client.mjs +152 -0
- package/dist/lib/host-registry-client.mjs.map +1 -0
- package/dist/lib/install-assets.d.mts +8 -0
- package/{src → dist}/lib/install-assets.mjs +17 -20
- package/dist/lib/install-assets.mjs.map +1 -0
- package/dist/lib/okstra-dirs.d.mts +4 -0
- package/{src → dist}/lib/okstra-dirs.mjs +3 -6
- package/dist/lib/okstra-dirs.mjs.map +1 -0
- package/dist/lib/paths.d.mts +4 -0
- package/dist/lib/paths.mjs +78 -0
- package/dist/lib/paths.mjs.map +1 -0
- package/dist/lib/proc.d.mts +3 -0
- package/dist/lib/proc.mjs +31 -0
- package/dist/lib/proc.mjs.map +1 -0
- package/dist/lib/python-helper.d.mts +8 -0
- package/dist/lib/python-helper.mjs +123 -0
- package/dist/lib/python-helper.mjs.map +1 -0
- package/dist/lib/runtime-manifest.d.mts +7 -0
- package/dist/lib/runtime-manifest.mjs +73 -0
- package/dist/lib/runtime-manifest.mjs.map +1 -0
- package/dist/lib/skill-catalog.d.mts +4 -0
- package/dist/lib/skill-catalog.mjs +50 -0
- package/dist/lib/skill-catalog.mjs.map +1 -0
- package/dist/lib/types.d.mts +129 -0
- package/dist/lib/types.mjs +2 -0
- package/dist/lib/types.mjs.map +1 -0
- package/dist/lib/version.d.mts +2 -0
- package/dist/lib/version.mjs +27 -0
- package/dist/lib/version.mjs.map +1 -0
- package/docs/architecture/storage-model.md +17 -3
- package/docs/architecture.md +12 -22
- package/docs/cli.md +29 -8
- package/docs/container.md +1 -1
- package/docs/contributor-change-matrix.md +3 -3
- package/docs/project-structure-overview.md +29 -20
- package/docs/task-process/README.md +3 -1
- package/docs/task-process/implementation-planning.md +2 -2
- package/docs/task-process/implementation.md +1 -1
- package/package.json +11 -5
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/claude-worker.md +3 -2
- package/runtime/agents/workers/report-writer-worker.md +3 -1
- package/runtime/agents/workers/translator-worker.md +3 -1
- package/runtime/bin/lib/okstra/cli.sh +12 -0
- package/runtime/bin/lib/okstra/globals.sh +4 -1
- package/runtime/bin/lib/okstra/usage.sh +4 -4
- package/runtime/bin/okstra-error-log.py +27 -0
- package/runtime/bin/okstra-provider-exec.py +245 -16
- package/runtime/bin/okstra-trace-cleanup.sh +58 -129
- package/runtime/bin/okstra.sh +10 -0
- package/runtime/prompts/lead/adapters/cmux.md +2 -0
- package/runtime/prompts/lead/convergence.md +27 -18
- package/runtime/prompts/lead/okstra-lead-contract.md +4 -2
- package/runtime/prompts/lead/plan-body-verification.md +13 -6
- package/runtime/prompts/lead/report-writer.md +6 -6
- package/runtime/prompts/lead/team-contract.md +1 -1
- package/runtime/prompts/profiles/_common-contract.md +2 -2
- package/runtime/prompts/profiles/_implementation-executor.md +2 -0
- package/runtime/prompts/profiles/_implementation-verifier.md +2 -2
- package/runtime/prompts/profiles/change-impact-analysis.md +16 -0
- package/runtime/prompts/profiles/error-analysis.md +21 -1
- package/runtime/prompts/profiles/feature-analysis.md +16 -0
- package/runtime/prompts/profiles/final-verification.md +16 -0
- package/runtime/prompts/profiles/implementation-option-selection.md +16 -0
- package/runtime/prompts/profiles/implementation-planning.md +32 -9
- package/runtime/prompts/profiles/implementation.md +17 -1
- package/runtime/prompts/profiles/improvement-discovery.md +16 -0
- package/runtime/prompts/profiles/project-analysis.md +16 -0
- package/runtime/prompts/profiles/release-handoff.md +5 -1
- package/runtime/prompts/profiles/requirements-discovery.md +20 -0
- package/runtime/prompts/wizard/prompts.ko.json +18 -0
- package/runtime/python/okstra_ctl/adapters/dispatch/__init__.py +1 -6
- package/runtime/python/okstra_ctl/adapters/dispatch/cli_wrapper.py +8 -0
- package/runtime/python/okstra_ctl/adapters/dispatch/cmux.py +8 -0
- package/runtime/python/okstra_ctl/adapters/dispatch/native_team.py +13 -0
- package/runtime/python/okstra_ctl/adapters/hosts/antigravity/adapter.py +2 -2
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +25 -5
- package/runtime/python/okstra_ctl/adapters/hosts/codex/adapter.py +2 -2
- package/runtime/python/okstra_ctl/adapters/hosts/external/adapter.py +4 -1
- package/runtime/python/okstra_ctl/adapters/hosts/external/relay.md +4 -4
- package/runtime/python/okstra_ctl/adapters/hosts/grok/adapter.py +2 -2
- package/runtime/python/okstra_ctl/adapters/hosts/kimi/adapter.py +2 -2
- package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +79 -11
- package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +100 -25
- package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +59 -14
- package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +55 -9
- package/runtime/python/okstra_ctl/adapters/providers/kimi/adapter.py +51 -12
- package/runtime/python/okstra_ctl/agent_activity.py +5 -1
- package/runtime/python/okstra_ctl/agent_invocation.py +608 -14
- package/runtime/python/okstra_ctl/agent_prompt_cli.py +249 -50
- package/runtime/python/okstra_ctl/application/resolve_assignment.py +53 -12
- package/runtime/python/okstra_ctl/assignment_environment.py +102 -0
- package/runtime/python/okstra_ctl/assignment_resolver.py +790 -0
- package/runtime/python/okstra_ctl/attempt_evidence.py +342 -0
- package/runtime/python/okstra_ctl/conformance.py +68 -0
- package/runtime/python/okstra_ctl/convergence.py +409 -3
- package/runtime/python/okstra_ctl/convergence_engine.py +248 -15
- package/runtime/python/okstra_ctl/convergence_store.py +170 -1
- package/runtime/python/okstra_ctl/dispatch_core.py +1181 -102
- package/runtime/python/okstra_ctl/dispatch_state.py +835 -22
- package/runtime/python/okstra_ctl/doctor.py +16 -2
- package/runtime/python/okstra_ctl/domain/host.py +32 -1
- package/runtime/python/okstra_ctl/domain/provider.py +212 -6
- package/runtime/python/okstra_ctl/domain/role.py +125 -0
- package/runtime/python/okstra_ctl/domain/wizard/interaction.py +13 -0
- package/runtime/python/okstra_ctl/domain/worker_exec.py +39 -1
- package/runtime/python/okstra_ctl/domain/worker_role.py +13 -3
- package/runtime/python/okstra_ctl/domain/worker_stream.py +24 -0
- package/runtime/python/okstra_ctl/error_log_write.py +9 -0
- package/runtime/python/okstra_ctl/error_report.py +21 -1
- package/runtime/python/okstra_ctl/execution_identity.py +529 -0
- package/runtime/python/okstra_ctl/execution_manifest.py +1281 -0
- package/runtime/python/okstra_ctl/execution_mutation_audit.py +619 -0
- package/runtime/python/okstra_ctl/final_report_schema.py +5 -4
- package/runtime/python/okstra_ctl/index.py +6 -2
- package/runtime/python/okstra_ctl/initial_prompt_materialization.py +43 -3
- package/runtime/python/okstra_ctl/legacy_model_selection.py +490 -0
- package/runtime/python/okstra_ctl/model_cli.py +278 -0
- package/runtime/python/okstra_ctl/model_defaults.py +46 -0
- package/runtime/python/okstra_ctl/model_discovery.py +26 -7
- package/runtime/python/okstra_ctl/model_pool.py +501 -0
- package/runtime/python/okstra_ctl/models.py +47 -27
- package/runtime/python/okstra_ctl/mutation_recovery.py +293 -0
- package/runtime/python/okstra_ctl/pane_reclaim.py +13 -22
- package/runtime/python/okstra_ctl/pane_title.py +151 -0
- package/runtime/python/okstra_ctl/ports/host_model.py +48 -17
- package/runtime/python/okstra_ctl/ports/worker_dispatch.py +4 -0
- package/runtime/python/okstra_ctl/registry/provider_registry.py +8 -4
- package/runtime/python/okstra_ctl/render.py +78 -10
- package/runtime/python/okstra_ctl/render_final_report.py +34 -19
- package/runtime/python/okstra_ctl/report_contract.py +39 -1
- package/runtime/python/okstra_ctl/report_finalize.py +84 -9
- package/runtime/python/okstra_ctl/report_html/render.py +1 -0
- package/runtime/python/okstra_ctl/role_requirements.py +217 -0
- package/runtime/python/okstra_ctl/run.py +1250 -260
- package/runtime/python/okstra_ctl/run_index_row.py +7 -1
- package/runtime/python/okstra_ctl/schema_excerpt.py +1 -1
- package/runtime/python/okstra_ctl/scope_provenance.py +1 -1
- package/runtime/python/okstra_ctl/session.py +69 -12
- package/runtime/python/okstra_ctl/team.py +51 -25
- package/runtime/python/okstra_ctl/time_report.py +38 -4
- package/runtime/python/okstra_ctl/tmux.py +19 -149
- package/runtime/python/okstra_ctl/usage_identity.py +86 -0
- package/runtime/python/okstra_ctl/usage_report.py +15 -3
- package/runtime/python/okstra_ctl/wizard.py +1253 -62
- package/runtime/python/okstra_ctl/worker_audit_ledger.py +68 -65
- package/runtime/python/okstra_ctl/worker_request.py +9 -1
- package/runtime/python/okstra_ctl/worker_runner.py +130 -5
- package/runtime/python/okstra_ctl/workers.py +7 -5
- package/runtime/python/okstra_ctl/worktree.py +69 -3
- package/runtime/python/okstra_ctl/write_policy.py +571 -0
- package/runtime/python/okstra_token_usage/cli.py +1 -1
- package/runtime/python/okstra_token_usage/collect.py +66 -6
- package/runtime/schemas/convergence-groups-v2.0.schema.json +128 -0
- package/runtime/schemas/execution-manifest-v2.schema.json +340 -0
- package/runtime/schemas/final-report-v2.0.schema.json +25 -0
- package/runtime/skills/okstra-run/SKILL.md +9 -9
- package/runtime/skills/okstra-setup/references/project-config.md +11 -0
- package/runtime/templates/report-writer-prompt-preamble.md +2 -0
- package/runtime/templates/reports/final-report-v2.template.md +7 -1
- package/runtime/templates/reports/html/base.template.html +21 -0
- package/runtime/templates/reports/html/i18n/en.json +4 -0
- package/runtime/templates/reports/html/i18n/ko.json +4 -0
- package/runtime/templates/reports/settings.template.json +0 -24
- package/runtime/templates/worker-prompt-preamble.md +6 -2
- package/runtime/validators/lib/fixtures.sh +98 -33
- package/runtime/validators/validate-implementation-plan-stages.py +63 -3
- package/runtime/validators/validate-run.py +443 -508
- package/runtime/validators/validate_session_conformance.py +26 -8
- package/runtime/bin/okstra-subagent-reclaim.sh +0 -26
- package/runtime/schemas/final-report-v1.0.schema.json +0 -6366
- package/runtime/templates/reports/final-report.template.md +0 -1258
- package/src/cli-registry.mjs +0 -532
- package/src/commands/execute/codex-dispatch.mjs +0 -10
- package/src/commands/execute/plan-items.mjs +0 -9
- package/src/commands/execute/plan-validate.mjs +0 -68
- package/src/commands/execute/run.mjs +0 -208
- package/src/commands/execute/team.mjs +0 -63
- package/src/commands/execute/wizard.mjs +0 -167
- package/src/commands/inspect/stage-map.mjs +0 -98
- package/src/commands/inspect/task-list.mjs +0 -97
- package/src/commands/inspect/task-show.mjs +0 -100
- package/src/commands/lifecycle/check-project.mjs +0 -187
- package/src/commands/lifecycle/config.mjs +0 -385
- package/src/commands/lifecycle/doctor.mjs +0 -308
- package/src/commands/lifecycle/install.mjs +0 -1172
- package/src/commands/lifecycle/paths.mjs +0 -104
- package/src/commands/lifecycle/preflight.mjs +0 -125
- package/src/commands/lifecycle/setup.mjs +0 -333
- package/src/commands/lifecycle/uninstall.mjs +0 -279
- package/src/commands/memory/memory.mjs +0 -524
- package/src/commands/pr/pr.mjs +0 -261
- package/src/commands/report/finalize.mjs +0 -64
- package/src/lib/host-registry-client.mjs +0 -176
- package/src/lib/paths.mjs +0 -86
- package/src/lib/proc.mjs +0 -31
- package/src/lib/python-helper.mjs +0 -142
- package/src/lib/runtime-manifest.mjs +0 -70
- package/src/lib/skill-catalog.mjs +0 -53
- package/src/lib/version.mjs +0 -20
- /package/{src → dist}/commands/pr/default.md +0 -0
|
@@ -1,45 +1,45 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
#
|
|
3
|
-
# okstra-trace-cleanup.sh — close
|
|
3
|
+
# okstra-trace-cleanup.sh — close the harness-owned worker panes of an okstra run.
|
|
4
4
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
5
|
+
# The panes this closes are the teammate panes the HARNESS splits for dispatched
|
|
6
|
+
# worker agents. okstra does not create them and cannot tag them, so they are
|
|
7
|
+
# found by a title allowlist scoped to the lead's window. They accumulate until
|
|
8
|
+
# the pane budget runs out, and `shutdown_request` only idles the agent without
|
|
9
|
+
# freeing its pane — this script is the only thing that closes them, which is why
|
|
10
|
+
# the lead calls it at every round boundary and before every user gate.
|
|
10
11
|
#
|
|
11
|
-
#
|
|
12
|
-
# `@okstra_trace_run` / `@okstra_status`. Those wrappers are now four-line
|
|
13
|
-
# entrypoints and worker progress renders into the worker's own pane, so
|
|
14
|
-
# NOTHING SPAWNS A TRACE PANE and neither tag has a writer left. The trace
|
|
15
|
-
# paths below still run and simply match nothing; `--reclaim-completed`, which
|
|
16
|
-
# keys on `@okstra_status`, is inert for the same reason. Kept rather than
|
|
17
|
-
# deleted because the hooks that call this script are already seeded on user
|
|
18
|
-
# machines — retiring the trace machinery is a deliberate follow-up.
|
|
12
|
+
# Two tag-driven paths used to live here and both are gone:
|
|
19
13
|
#
|
|
20
|
-
#
|
|
14
|
+
# - Worker-compute panes of the `tmux-pane` dispatch backend, tagged
|
|
15
|
+
# `@okstra_worker_run`. That backend was removed — a worker now gets a cmux
|
|
16
|
+
# surface or a cli-wrapper subprocess, and neither is a tmux pane okstra owns.
|
|
17
|
+
# - Trace panes, tagged `@okstra_trace_run` / `@okstra_status`, which the
|
|
18
|
+
# provider wrappers used to split as `tail -F` siblings. The wrappers became
|
|
19
|
+
# four-line entrypoints and worker progress renders into the worker's own
|
|
20
|
+
# pane, so nothing had spawned a trace pane for some time.
|
|
21
21
|
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
# by a title allowlist scoped to the LEAD's WINDOW. The
|
|
28
|
-
# lead pane is read from `<RUN_DIR>/state/lead-pane.id`
|
|
29
|
-
# (recorded once by the lead in its own foreground pane —
|
|
30
|
-
# reliable even though Claude Code's Bash tool strips
|
|
31
|
-
# `$TMUX`/`$TMUX_PANE`); it scopes the title scan and is
|
|
32
|
-
# NEVER killed. Window scope keeps a second lead running
|
|
33
|
-
# in another window of the same session out of range.
|
|
22
|
+
# With both writers gone the tag scan matched nothing, so it was removed along
|
|
23
|
+
# with the two modes that existed only to drive it (`--reap`, which the SessionEnd
|
|
24
|
+
# hook called, and `--reclaim-completed`, which `okstra-subagent-reclaim.sh` drove
|
|
25
|
+
# from SubagentStop / TaskCompleted). Those hooks are gone from the seeded
|
|
26
|
+
# settings too.
|
|
34
27
|
#
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
# worker
|
|
28
|
+
# Invocation:
|
|
29
|
+
#
|
|
30
|
+
# --run-dir <RUN_DIR> Closes the run's worker-agent panes (`claude-worker` /
|
|
31
|
+
# `codex-worker` / `antigravity-worker` /
|
|
32
|
+
# `report-writer-worker` and the FleetView teammate
|
|
33
|
+
# prefixes), scoped to the LEAD's WINDOW. The lead pane is
|
|
34
|
+
# read from `<RUN_DIR>/state/lead-pane.id` (recorded once
|
|
35
|
+
# by the lead in its own foreground pane — reliable even
|
|
36
|
+
# though Claude Code's Bash tool strips `$TMUX` /
|
|
37
|
+
# `$TMUX_PANE`); it scopes the scan and is NEVER killed.
|
|
38
|
+
# Window scope keeps a second lead running in another
|
|
39
|
+
# window of the same session out of range.
|
|
40
40
|
#
|
|
41
41
|
# `--list` (alias `--dry-run`) prints `<pane_id>\t<pane_title>` per pane instead
|
|
42
|
-
# of killing
|
|
42
|
+
# of killing.
|
|
43
43
|
#
|
|
44
44
|
# `--keep <substr>` (repeatable) spares any pane whose current title contains
|
|
45
45
|
# <substr>, in both the kill and the list set. Used to preserve an in-flight
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
|
|
51
51
|
set -u
|
|
52
52
|
|
|
53
|
-
#
|
|
53
|
+
# Caller-pane resolution helper (okstra_resolve_caller_pane) — see
|
|
54
54
|
# lib/okstra/tmux-pane.sh. Used as the lead-pane fallback below so a missing /
|
|
55
55
|
# stale lead-pane.id resolves to the pane THIS process actually runs in (via
|
|
56
56
|
# ancestor-PID ↔ tmux pane_pid matching), never a foreign active-client pane.
|
|
@@ -58,43 +58,26 @@ set -u
|
|
|
58
58
|
_clean_script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
59
59
|
[ -r "$_clean_script_dir/lib/okstra/tmux-pane.sh" ] && . "$_clean_script_dir/lib/okstra/tmux-pane.sh"
|
|
60
60
|
|
|
61
|
-
# --reclaim-completed shells out to `python3 -m okstra_ctl.pane_reclaim`. The
|
|
62
|
-
# package is a bin-sibling in the repo layout (scripts/okstra_ctl) and under
|
|
63
|
-
# $OKSTRA_HOME/lib/python in the installed layout. Put both on PYTHONPATH so the
|
|
64
|
-
# import resolves regardless of where this script runs from.
|
|
65
|
-
_okstra_home="${OKSTRA_HOME:-$HOME/.okstra}"
|
|
66
|
-
export PYTHONPATH="${_clean_script_dir}:${_okstra_home}/lib/python${PYTHONPATH:+:$PYTHONPATH}"
|
|
67
|
-
|
|
68
61
|
MODE="kill" # kill | list
|
|
69
|
-
RECLAIM=0 # 1: trace pane 은 @okstra_status 가 완료(exited)일 때만 회수 (--reclaim-completed)
|
|
70
|
-
REAP=0
|
|
71
62
|
run_dir=""
|
|
72
63
|
KEEP_PATTERNS=() # --keep <substr>: panes whose title contains substr are spared from kill/list
|
|
73
64
|
while [[ $# -gt 0 ]]; do
|
|
74
65
|
case "$1" in
|
|
75
|
-
--list|--dry-run)
|
|
76
|
-
--reclaim-completed) RECLAIM=1 ;;
|
|
77
|
-
--reap) REAP=1 ;;
|
|
66
|
+
--list|--dry-run) MODE="list" ;;
|
|
78
67
|
--run-dir) shift; run_dir="${1-}" ;;
|
|
79
68
|
--run-dir=*) run_dir="${1#--run-dir=}" ;;
|
|
80
69
|
--keep) shift; KEEP_PATTERNS+=("${1-}") ;;
|
|
81
70
|
--keep=*) KEEP_PATTERNS+=("${1#--keep=}") ;;
|
|
82
71
|
-h|--help)
|
|
83
72
|
cat <<'USAGE'
|
|
84
|
-
usage: okstra-trace-cleanup.sh
|
|
73
|
+
usage: okstra-trace-cleanup.sh --run-dir <RUN_DIR> [--list] [--keep <substr>]...
|
|
85
74
|
|
|
86
|
-
--run-dir okstra run directory; closes that run's
|
|
87
|
-
--list
|
|
75
|
+
--run-dir okstra run directory; closes that run's worker-agent panes.
|
|
76
|
+
--list print "<pane_id>\t<pane_title>" per pane; no kill.
|
|
88
77
|
--dry-run alias for --list.
|
|
89
78
|
--keep <substr> exclude any pane whose title contains <substr> from the
|
|
90
79
|
kill/list set (repeatable). Used to spare an in-flight
|
|
91
80
|
report-writer at a round boundary.
|
|
92
|
-
--reclaim-completed with --run-dir: restrict trace panes to those whose
|
|
93
|
-
@okstra_status sidecar is terminal (stage=exited); in-flight
|
|
94
|
-
and teammate panes are preserved. Skips the title-allowlist
|
|
95
|
-
teammate scan. Combinable with --list.
|
|
96
|
-
--reap close every okstra trace pane under $CLAUDE_PROJECT_DIR/.okstra
|
|
97
|
-
(SessionEnd hook; no single run-dir applies).
|
|
98
81
|
USAGE
|
|
99
82
|
exit 0 ;;
|
|
100
83
|
*)
|
|
@@ -104,29 +87,16 @@ USAGE
|
|
|
104
87
|
shift
|
|
105
88
|
done
|
|
106
89
|
|
|
107
|
-
if [[
|
|
108
|
-
printf 'okstra-trace-cleanup.sh: --run-dir <RUN_DIR>
|
|
90
|
+
if [[ -z "$run_dir" ]]; then
|
|
91
|
+
printf 'okstra-trace-cleanup.sh: --run-dir <RUN_DIR> is required\n' >&2
|
|
109
92
|
exit 2
|
|
110
93
|
fi
|
|
111
94
|
|
|
112
|
-
#
|
|
113
|
-
#
|
|
114
|
-
# — else a symlinked component (e.g. macOS /tmp -> /private/tmp) makes the
|
|
115
|
-
# compare miss. Fall back to the literal value if the dir does not resolve.
|
|
116
|
-
_resolve() { (cd "$1" 2>/dev/null && pwd -P) || printf '%s' "$1"; }
|
|
117
|
-
[[ -n "$run_dir" ]] && run_dir="$(_resolve "$run_dir")"
|
|
118
|
-
project_dir=""
|
|
119
|
-
[[ -n "${CLAUDE_PROJECT_DIR:-}" ]] && project_dir="$(_resolve "$CLAUDE_PROJECT_DIR")"
|
|
120
|
-
|
|
121
|
-
# Lead pane. For a run, prefer the value the lead recorded in its own foreground
|
|
122
|
-
# pane; fall back to the active-pane probe. Rejected if the recorded pane is
|
|
123
|
-
# gone. For --reap there is no run state — probe the active pane, used only to
|
|
124
|
-
# avoid killing whatever pane the reap runs from.
|
|
95
|
+
# Lead pane. Prefer the value the lead recorded in its own foreground pane; fall
|
|
96
|
+
# back to the active-pane probe. Rejected if the recorded pane is gone.
|
|
125
97
|
lead_pane=""
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
[[ -r "$lead_pane_file" ]] && lead_pane="$(head -n1 "$lead_pane_file" 2>/dev/null || true)"
|
|
129
|
-
fi
|
|
98
|
+
lead_pane_file="$run_dir/state/lead-pane.id"
|
|
99
|
+
[[ -r "$lead_pane_file" ]] && lead_pane="$(head -n1 "$lead_pane_file" 2>/dev/null || true)"
|
|
130
100
|
if [[ -z "$lead_pane" ]] || ! tmux display-message -p -t "$lead_pane" '#{pane_id}' >/dev/null 2>&1; then
|
|
131
101
|
if type okstra_resolve_caller_pane >/dev/null 2>&1; then
|
|
132
102
|
lead_pane="$(okstra_resolve_caller_pane 2>/dev/null || true)"
|
|
@@ -135,17 +105,6 @@ if [[ -z "$lead_pane" ]] || ! tmux display-message -p -t "$lead_pane" '#{pane_id
|
|
|
135
105
|
fi
|
|
136
106
|
fi
|
|
137
107
|
|
|
138
|
-
# Does a trace pane's tag belong to the set we are closing?
|
|
139
|
-
_tag_in_scope() {
|
|
140
|
-
local tag="$1"
|
|
141
|
-
if [[ "$REAP" -eq 1 ]]; then
|
|
142
|
-
[[ -z "$tag" ]] && return 1
|
|
143
|
-
[[ -n "$project_dir" ]] && { [[ "$tag" == "$project_dir/"* ]]; return; }
|
|
144
|
-
return 0 # no project scope available → reap every tagged trace pane
|
|
145
|
-
fi
|
|
146
|
-
[[ "$tag" == "$run_dir" ]]
|
|
147
|
-
}
|
|
148
|
-
|
|
149
108
|
_title_in_okstra_scope() {
|
|
150
109
|
local title="$1"
|
|
151
110
|
case "$title" in
|
|
@@ -168,7 +127,6 @@ _title_in_okstra_scope() {
|
|
|
168
127
|
}
|
|
169
128
|
|
|
170
129
|
# A collected pane whose current title contains any --keep substring is spared.
|
|
171
|
-
# Applied at the final emit so both the tag scan and the title scan honour it.
|
|
172
130
|
_keep_excluded() {
|
|
173
131
|
local pid="$1" title pat
|
|
174
132
|
(( ${#KEEP_PATTERNS[@]} )) || return 1
|
|
@@ -181,54 +139,25 @@ _keep_excluded() {
|
|
|
181
139
|
|
|
182
140
|
collect_okstra_panes() {
|
|
183
141
|
local -a panes=()
|
|
184
|
-
local pid
|
|
185
|
-
|
|
186
|
-
#
|
|
187
|
-
#
|
|
188
|
-
#
|
|
189
|
-
#
|
|
190
|
-
#
|
|
191
|
-
#
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
while IFS=$'\t' read -r pid trace_tag worker_tag status_tag; do
|
|
195
|
-
trace_tag="${trace_tag#x}"; worker_tag="${worker_tag#x}"; status_tag="${status_tag#x}"
|
|
142
|
+
local pid title
|
|
143
|
+
|
|
144
|
+
# Title-allowlisted worker-agent panes in the lead's WINDOW. `list-panes -t
|
|
145
|
+
# <pane>` (no `-s`, no `-a`) resolves the window containing that pane and lists
|
|
146
|
+
# only that window's panes. Split-pane teammates always land in the lead's
|
|
147
|
+
# window, so this catches all of THIS run's worker panes while a second okstra
|
|
148
|
+
# lead in another window of the same tmux session is left untouched. Skipped
|
|
149
|
+
# when the lead pane is unknown.
|
|
150
|
+
[[ -n "$lead_pane" ]] || return 0
|
|
151
|
+
while IFS=$'\t' read -r pid title; do
|
|
196
152
|
[[ -n "$pid" ]] || continue
|
|
197
153
|
[[ "$pid" == "$lead_pane" ]] && continue
|
|
198
|
-
if
|
|
199
|
-
if [[ "$RECLAIM" -eq 1 ]]; then
|
|
200
|
-
# reclaim 모드: 완료(stage=exited)된 worker 의 pane 만. status 태그가
|
|
201
|
-
# 없거나(teammate/비-wrapper pane) 미완료면 보존.
|
|
202
|
-
[[ -n "$status_tag" ]] || continue
|
|
203
|
-
python3 -m okstra_ctl.pane_reclaim "$status_tag" || continue
|
|
204
|
-
fi
|
|
154
|
+
if _title_in_okstra_scope "$title"; then
|
|
205
155
|
panes+=("$pid")
|
|
206
156
|
fi
|
|
207
|
-
done < <(tmux list-panes -
|
|
208
|
-
-F '#{pane_id}'$'\t''
|
|
209
|
-
2>/dev/null || true)
|
|
210
|
-
# (2) Title-allowlisted worker-agent panes in the lead's WINDOW. Only for a
|
|
211
|
-
# run (reap leaves these harness-owned panes to the harness). `list-panes -t
|
|
212
|
-
# <pane>` (no `-s`, no `-a`) resolves the window containing that pane and
|
|
213
|
-
# lists only that window's panes. Split-pane teammates always land in the
|
|
214
|
-
# lead's window, so this catches all of THIS run's worker panes while a second
|
|
215
|
-
# okstra lead in another window of the same tmux session — whose in-flight
|
|
216
|
-
# worker panes are untagged and title-only — is left untouched. Skipped when
|
|
217
|
-
# the lead pane is unknown. reclaim 모드는 teammate pane 을 회수하지 않으므로
|
|
218
|
-
# (완료 판정 불가, trace-only) 이 스캔을 건너뛴다.
|
|
219
|
-
if [[ "$REAP" -eq 0 && "$RECLAIM" -eq 0 && -n "$lead_pane" ]]; then
|
|
220
|
-
while IFS=$'\t' read -r pid title; do
|
|
221
|
-
[[ -n "$pid" ]] || continue
|
|
222
|
-
[[ "$pid" == "$lead_pane" ]] && continue
|
|
223
|
-
if _title_in_okstra_scope "$title"; then
|
|
224
|
-
panes+=("$pid")
|
|
225
|
-
fi
|
|
226
|
-
done < <(tmux list-panes -t "$lead_pane" \
|
|
227
|
-
-F '#{pane_id}'$'\t''#{pane_title}' 2>/dev/null || true)
|
|
228
|
-
fi
|
|
157
|
+
done < <(tmux list-panes -t "$lead_pane" \
|
|
158
|
+
-F '#{pane_id}'$'\t''#{pane_title}' 2>/dev/null || true)
|
|
229
159
|
|
|
230
|
-
#
|
|
231
|
-
# Then drop any pane a --keep pattern spares (in-flight report-writer).
|
|
160
|
+
# Drop any pane a --keep pattern spares (in-flight report-writer).
|
|
232
161
|
if (( ${#panes[@]} )); then
|
|
233
162
|
printf '%s\n' "${panes[@]}" | awk 'NF && !seen[$0]++' | while IFS= read -r _pid; do
|
|
234
163
|
_keep_excluded "$_pid" && continue
|
package/runtime/bin/okstra.sh
CHANGED
|
@@ -222,6 +222,16 @@ PY_ARGS=(
|
|
|
222
222
|
[[ -n "${DIRECTIVE-}" ]] && PY_ARGS+=(--directive "$DIRECTIVE")
|
|
223
223
|
[[ -n "${FIX_CYCLE-}" ]] && PY_ARGS+=(--fix-cycle "$FIX_CYCLE")
|
|
224
224
|
[[ -n "${WORKERS_OVERRIDE-}" ]] && PY_ARGS+=(--workers "$WORKERS_OVERRIDE")
|
|
225
|
+
for role_count in "${ROLE_COUNTS[@]-}"; do
|
|
226
|
+
[[ -z "$role_count" ]] && continue
|
|
227
|
+
PY_ARGS+=(--role-count "$role_count")
|
|
228
|
+
done
|
|
229
|
+
for role_model in "${ROLE_MODELS[@]-}"; do
|
|
230
|
+
[[ -z "$role_model" ]] && continue
|
|
231
|
+
PY_ARGS+=(--role-model "$role_model")
|
|
232
|
+
done
|
|
233
|
+
[[ -n "${HOST_SESSION_CONTEXT_JSON-}" ]] && \
|
|
234
|
+
PY_ARGS+=(--host-session-context-json "$HOST_SESSION_CONTEXT_JSON")
|
|
225
235
|
[[ -n "${LEAD_PROVIDER_OVERRIDE-}" ]] && PY_ARGS+=(--lead-provider "$LEAD_PROVIDER_OVERRIDE")
|
|
226
236
|
[[ -n "${LEAD_MODEL_OVERRIDE-}" ]] && PY_ARGS+=(--lead-model "$LEAD_MODEL_OVERRIDE")
|
|
227
237
|
[[ -n "${CLAUDE_MODEL_OVERRIDE-}" ]] && PY_ARGS+=(--claude-model "$CLAUDE_MODEL_OVERRIDE")
|
|
@@ -34,6 +34,8 @@ It overrides only the worker-dispatch portion of the selected host relay, not th
|
|
|
34
34
|
| `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Emit the matching `PROGRESS:` line and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
|
|
35
35
|
| `collect_usage` | Collect artifact/CLI-log-backed usage through the existing Okstra token-usage path; never substitute another runtime's session log. |
|
|
36
36
|
|
|
37
|
+
An `implementation` run calls `dispatch_worker` twice: once for the Executor, then — after `await_workers` settles it — once for the verifiers. That second call's `--workers` list must omit the Executor's worker ID: it is materialized as the Executor on every dispatch, so a batch still carrying it is refused again. A verifier started beside the Executor observes base HEAD instead of the stage diff, so a single batch holding both is refused by `scripts/okstra_ctl/dispatch_core.py` `_validate_implementation_phase_order`, `--dry-run` included.
|
|
38
|
+
|
|
37
39
|
## Pane placement is not yours to compute
|
|
38
40
|
|
|
39
41
|
Okstra creates, sizes, labels, and closes every worker pane. Do not issue terminal-multiplexer commands of any kind — not to place a worker, not to resize the lead, not to reclaim a finished round. Pane geometry depends on the display, and a lead that recomputes it per run gets it wrong differently on every host.
|
|
@@ -84,7 +84,7 @@ Read the worker result files generated in Phase 4/5 and extract individual findi
|
|
|
84
84
|
- Same semantics but disjoint ticket sets → separate groups (do NOT over-merge across tickets).
|
|
85
85
|
- Only one worker confirms a finding → one single-source group.
|
|
86
86
|
4. When grouping is ambiguous, prefer splitting over merging (avoid over-merging). Semantic matching, ticket-set equality, and evidence interpretation remain lead judgments; the engine does not perform fuzzy matching or decide whether evidence is credible.
|
|
87
|
-
5. Write `runs/<task-type>/state/convergence-groups-<task-type>-<seq>.json`. Each group carries its `ticketIds`, `originWorker`, `originEvidence`, `discoveredBy`, and every `<worker>:<item-id>` source in `sourceItems`. For analysis sidetracks where ticket tagging is not required, `ticketIds: []` is the canonical value; never synthesize `"unknown"` or another placeholder. `scripts/okstra_ctl/convergence_engine.py` and
|
|
87
|
+
5. Write `runs/<task-type>/state/convergence-groups-<task-type>-<seq>.json`. Each group carries its `ticketIds`, `originWorker`, `originEvidence`, `discoveredBy`, and every `<worker>:<item-id>` source in `sourceItems`. For analysis sidetracks where ticket tagging is not required, `ticketIds: []` is the canonical value; never synthesize `"unknown"` or another placeholder. `scripts/okstra_ctl/convergence_engine.py` and the version-selected convergence-groups schema enforce the required array field and reject non-string or blank entries while allowing the empty array. When a live command or external read produced reproducible evidence, also include `evidenceArtifacts[]` with its `.okstra/` path, SHA-256 digest, command, and environment. The field is optional because historical or inaccessible evidence may not have a captured artifact. The lead and verifier MUST NOT infer live or external evidence from wording or keyword matching; they use the finding's explicit claim, provenance, and supplied artifacts. Include the resolved worker roster in order with functional `audience` values; do not derive scope from provider or model identity. In a v2 run, set top-level `schemaVersion: "2.0"`, `executionIdentityVersion: 2`, and `runManifestPath` to the current run manifest's exact canonical project-relative path. Write the groups artifact under that same resolved run directory's `state/` directory. Every v2 worker row also carries the paired `participantRef` and `sourceRoleExecutionRef` from that run manifest's canonical role state. Set `sourceRoleExecutionRef` to the selected source `RoleExecution` row's `roleExecutionRef`, not that row's `sourceRoleExecutionRef` field; a static source row has null in the latter field. Copy `participantRef` from that same selected row. Never derive those references from the worker name, provider, model, or execution label. A legacy v1 document keeps `schemaVersion: "1.0"` and omits `executionIdentityVersion`, `runManifestPath`, and both worker reference fields. The `audience` enum is a convergence role, not a phase label: every finding-producing worker uses `analysis` and selects an `analyser`, `designer`, `planner`, or `verifier` source role. Only the report author uses `report-writer`, paired with a `report-writer` source role. There is no `implementation-verifier` audience here; map an implementation verifier to `analysis`.
|
|
88
88
|
6. Do not write a queue or classification in this grouped-input artifact. `okstra convergence seed` classifies Round 0 by mode:
|
|
89
89
|
- Collaborative mode: multi-source groups become `full-consensus` immediately; only single-source groups enter the working queue.
|
|
90
90
|
- Adversarial mode: every finding enters the working queue regardless of source count. Semantic grouping merges provenance only; it does not decide a finding is reliable.
|
|
@@ -106,8 +106,8 @@ convergence-<task-type>-<seq>.json
|
|
|
106
106
|
|
|
107
107
|
Follow this protocol exactly:
|
|
108
108
|
|
|
109
|
-
0.
|
|
110
|
-
1. Run `okstra convergence seed --groups <groups> --work-state <work> --final-state <final> --migration-dir <state/migrations
|
|
109
|
+
0. Version-selected schemas describe what the reducer reads: `schemas/convergence-groups-v1.0.schema.json` accepts only legacy groups, `schemas/convergence-groups-v2.0.schema.json` accepts only explicit v2 execution identity, and `schemas/convergence-round-results-v1.0.schema.json` feeds step 4's `apply-round --results`. `schemas/convergence-critic-results-v1.0.schema.json` is a fourth shape but **not** a reducer input — it describes the critic worker's own result document. Step 6's `apply-critic-gaps --results` takes the coverage batch you assemble from those candidates plus each analyser's vote (`{schemaVersion, taskKey, mode, provider, modelExecutionValue, dispatches[], gaps[]}`, spelled out in §"Coverage critic pass" §"State"); feeding the critic document straight in is rejected, by design. `okstra convergence example --kind <groups|round-results|critic-results>` prints a deterministic valid v1 instance of each and writes only JSON to stdout.
|
|
110
|
+
1. Run `okstra convergence seed --groups <groups> --run-manifest <current-run-manifest> --work-state <work> --final-state <final> --migration-dir <state/migrations>` for a v2 worker roster. `--run-manifest` must be the exact current manifest named by the groups document's `runManifestPath`; a previous run from the same task is not interchangeable. Omit the flag for a legacy v1 roster. A `reuse-final` action means validate the existing final and continue to Phase 6. `create-work`, `resume-work`, and `restart-round0` continue with planning.
|
|
111
111
|
2. Run `okstra convergence plan-round --work-state <work> --plan <round-plan>`. This is read-only with respect to the working state.
|
|
112
112
|
3. When the plan action is `dispatch`, create exactly one reverify prompt for each `dispatches[]` row and dispatch it through the selected runtime adapter. Its findings are exactly that row's `findingIds`.
|
|
113
113
|
4. Convert parsed verdicts and every terminal dispatch outcome into `convergence-round-<N>-results-<task-type>-<seq>.json`; then run `okstra convergence apply-round --work-state <work> --plan <round-plan> --results <round-results>`.
|
|
@@ -228,21 +228,30 @@ Design intent: one `counter-evidence` refute denies a claim consensus (it cannot
|
|
|
228
228
|
|
|
229
229
|
For every finding reverify row and critic-gap verification row, first write a
|
|
230
230
|
call-specific task-instructions file under the current run's `state/`
|
|
231
|
-
directory.
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
231
|
+
directory. For a v2 run, take `participantRef` and
|
|
232
|
+
`sourceRoleExecutionRef` from the canonical round-plan dispatch row or the
|
|
233
|
+
matching canonical working-state worker row. That stored reference is the
|
|
234
|
+
selected source `RoleExecution` row's `roleExecutionRef`, not that row's
|
|
235
|
+
`sourceRoleExecutionRef` field. Then run `okstra agent-prompt
|
|
236
|
+
materialize` with `--audience
|
|
237
|
+
reverification-worker`, `--assignment-ref reverify/<workerId>`,
|
|
238
|
+
`--source-role-execution-ref
|
|
239
|
+
<sourceRoleExecutionRef>`, the exact `--worker-id`, `--dispatch-kind
|
|
240
|
+
reverify-r<N>`, and the authorized prompt/result/audit paths. Do not derive the
|
|
241
|
+
source role execution from `workerId`, provider, model, or execution-label
|
|
242
|
+
text. A legacy v1 run omits `--source-role-execution-ref`; the materializer
|
|
243
|
+
keeps its legacy read-only identity resolution for that schema version. The
|
|
244
|
+
returned `promptPath` is the only body that may be dispatched; do not append
|
|
245
|
+
role prose or reconstruct model headers after materialization.
|
|
246
|
+
|
|
247
|
+
If the dispatch gate then rejects that prompt, preserve its prompt, metadata,
|
|
248
|
+
reservation, and append-only Invocation bytes. A v2 reverify correction uses a
|
|
249
|
+
fresh `--invocation-id` and fresh prompt/metadata path; the materializer rejects
|
|
250
|
+
`--replace-undispatched` for this dynamic identity path. A legacy v1 correction
|
|
251
|
+
may fix the task-instructions file and re-run the same `materialize` call with
|
|
252
|
+
`--replace-undispatched` while keeping the `--invocation-id`. Once any dispatch
|
|
253
|
+
row names the invocation, replacement is rejected even for v1 and the prompt is
|
|
254
|
+
history. Do not delete prompt, metadata, or reservation files by hand.
|
|
246
255
|
|
|
247
256
|
Run `okstra agent-prompt verify --run-manifest <path> --metadata
|
|
248
257
|
<metadataPath> --json` immediately before dispatch. A failed verification is a
|
|
@@ -44,7 +44,9 @@ Read-side inspection (`/okstra-inspect`) and scheduling (`/okstra-schedule-gen`)
|
|
|
44
44
|
|
|
45
45
|
## Core operating contract
|
|
46
46
|
|
|
47
|
-
- The `
|
|
47
|
+
- The `leader` owns orchestration, convergence supervision, and final-report review/approval. It does not author the final-report file when `Report writer worker` is in the roster. `lead` is a compatibility alias for `leader` and must not be written on new artifacts.
|
|
48
|
+
- Dispatch consumes stored role executions, not provider-named worker IDs. Canonical roles are `leader`, `analyser`, `critic`, `designer`, `planner`, `implementer`, `verifier`, `report-writer`, and `translator`. `executor` is a compatibility alias for `implementer`.
|
|
49
|
+
- Pane titles and operational rows use the stored `executionLabel`. Do not rebuild that label from a provider name or model string.
|
|
48
50
|
- Standard worker roles remain `Claude worker`, `Codex worker`, `Antigravity worker`, and `Report writer worker`; these are provider/functional-role identities, not lead-runtime primitives.
|
|
49
51
|
- `Report writer worker`, when in the roster, is the **author** of the final-report file. Lead reviews the draft and may request a revision via a follow-up dispatch, but MUST NOT write the report itself as a "shortcut". The only legal lead-authored fallback is when a Report writer worker dispatch was actually attempted and recorded a terminal status of `error`/`timeout`/`not-run` with an explicit reason in team-state — see [report-writer](./report-writer.md) "Lead-authored fallback".
|
|
50
52
|
- "Session resume", "team is no longer alive", and similar are NOT valid reasons to skip Report writer worker dispatch — see [report-writer](./report-writer.md) "Resume-safe dispatch".
|
|
@@ -181,7 +183,7 @@ For `--task-type implementation` runs, the task bundle additionally pins one of
|
|
|
181
183
|
- `instruction-set/analysis-profile.md` — top "Executor binding" block (provider, display name, model, runner, and dispatch mode)
|
|
182
184
|
- `runs/implementation/manifests/run-manifest-*.json` — `teamContract.executor` object (the same binding plus `appliesTo: "implementation"`)
|
|
183
185
|
|
|
184
|
-
Lead MUST dispatch Edit/Write-bearing work only through that executor binding: use the host primitive with `hostModelValue` for `runner=native-session`, or `okstra worker-dispatch` with `modelExecutionValue` for `runner=cli-wrapper`. The other
|
|
186
|
+
Lead MUST dispatch Edit/Write-bearing work only through that executor binding: use the host primitive with `hostModelValue` for `runner=native-session`, or `okstra worker-dispatch` with `modelExecutionValue` for `runner=cli-wrapper`. The other providers in the roster still run as read-only verifiers in the same run; the executor's own provider does not, because its worker ID materializes as the executor on every dispatch — so the diff is reviewed context-isolated by the remaining verifiers. Session isolation is the primary self-review safeguard — a verifier reusing the executor's model variant is acceptable in a distinct session. A different model variant (e.g. executor=opus / Claude verifier=sonnet) is recommended but not mandatory.
|
|
185
187
|
|
|
186
188
|
Executor is chosen at run-prep time via `--executor <claude|codex|antigravity>` (or `OKSTRA_DEFAULT_EXECUTOR`, fallback `claude`); the model used by the executor is taken from the corresponding worker model flag (`--claude-model` / `--codex-model` / `--antigravity-model`). For CLI-backed executors, the underlying file mutation happens inside the executor CLI's own auto-edit mode (e.g. `codex exec --sandbox workspace-write`), not through the lead runtime's `write_artifact` operation.
|
|
187
189
|
|
|
@@ -53,7 +53,7 @@ The shared Majority definition and the auto-disable rule (fewer than 2 analyser
|
|
|
53
53
|
|
|
54
54
|
## Plan-item extraction (Round 0 equivalent)
|
|
55
55
|
|
|
56
|
-
From the report-writer's draft of `## 5.4 Implementation Plan Deliverables`, the lead creates the verification queue only through this sequence (see also `templates/reports/final-report.template.md` §5.5.9):
|
|
56
|
+
From the report-writer's draft of `## 5.4 Implementation Plan Deliverables`, the lead creates the verification queue only through this sequence (see also `templates/reports/final-report-v2.template.md` §5.5.9):
|
|
57
57
|
|
|
58
58
|
```text
|
|
59
59
|
okstra plan-items extract --data <data.json> --output <state>/plan-items-....json
|
|
@@ -124,7 +124,7 @@ The verdict tokens `AGREE` / `DISAGREE` / `SUPPLEMENT` are reused, but their mea
|
|
|
124
124
|
`P-Prep-S<stage>-<kind>` applies the same verdict tokens and adds these disposition checks:
|
|
125
125
|
|
|
126
126
|
- `inline-contract`: AGREE only when the contract contains the kind-specific fields needed to implement the stage; a label or generic prose is insufficient.
|
|
127
|
-
- `prep-item`: AGREE only when every referenced PREP item has a concrete `aiProposal`, correct `stageRefs`/`kind`, and state-specific safeguards required by `schemas/final-report-
|
|
127
|
+
- `prep-item`: AGREE only when every referenced PREP item has a concrete `aiProposal`, correct `stageRefs`/`kind`, and state-specific safeguards required by `schemas/final-report-v2.0.schema.json`.
|
|
128
128
|
- `not-applicable`: AGREE only when the rationale is consistent with the stage action; otherwise DISAGREE with `fixability` (`planner-fixable` when the plan can supply the missing contract, `needs-user-input` only for genuinely external facts).
|
|
129
129
|
- A declared `blocked` item is not itself a plan-body failure. Missing or duplicate coverage, an empty proposal, a mismatched reference, or an unjustified disposition is a failure and receives `DISAGREE(<kind>)` with `fixability`.
|
|
130
130
|
|
|
@@ -202,7 +202,14 @@ Before each verifier call, write one task-instructions file under the current
|
|
|
202
202
|
run's `state/` directory and run `okstra agent-prompt materialize` with
|
|
203
203
|
`--audience reverification-worker`,
|
|
204
204
|
`--assignment-ref reverify/<workerId>`, the exact `--worker-id`, and
|
|
205
|
-
`--dispatch-kind reverify-r<N>`.
|
|
205
|
+
`--dispatch-kind reverify-r<N>`. For a v2 run, select the verifier's canonical
|
|
206
|
+
source `RoleExecution` row from the run manifest's static role state. Use its
|
|
207
|
+
`participantRef`, and set `sourceRoleExecutionRef` to the selected source
|
|
208
|
+
`RoleExecution` row's `roleExecutionRef`, not that row's
|
|
209
|
+
`sourceRoleExecutionRef` field. Pass `--source-role-execution-ref
|
|
210
|
+
<sourceRoleExecutionRef>`. Do not derive that reference from `workerId`,
|
|
211
|
+
provider, model, or execution-label text. A legacy v1 run omits this flag. Run
|
|
212
|
+
`okstra agent-prompt verify` against the
|
|
206
213
|
returned `metadataPath` before dispatch and use the returned `promptPath`
|
|
207
214
|
without modification. Native-session calls use only `hostModelValue`; before
|
|
208
215
|
the host primitive, run `okstra agent-prompt record-dispatch` with the project
|
|
@@ -254,7 +261,7 @@ round before any host or provider process starts.
|
|
|
254
261
|
|
|
255
262
|
**How the corrective round is recorded.** The first prompt was dispatched, so it is immutable — `--replace-undispatched` refuses it, correctly. Materialize the correction under a NEW `--invocation-id` and a new prompt path. Before linking its result, retire the first attempt's link: `okstra agent-prompt reject-result --run-manifest <path> --dispatch-id <first dispatch id> --superseded-by <corrective dispatch id> --reason "<what was wrong with the returned result>"`. Without that step the corrective `link-result` fails with `agent result is already linked to another dispatch`, which is how a worker that ran for twenty minutes and wrote a good result ends up unrecordable. Nothing is deleted: the rejected link stays in `agentResultLinks` carrying `supersededBy` and `rejectionReason`, so the ledger shows both attempts and why the second exists.
|
|
256
263
|
|
|
257
|
-
Then lead writes `runs/<task-type>/state/plan-body-verification-<task-type>-<seq>.json` (schema below), **appending this round** — one new `roundHistory[]` entry plus this round's votes on each verified item's `planItems[].rounds[]`. The file accumulates across rounds; it is never truncated to the latest one. After `okstra plan-verify` exits 0, lead sets that new round's `completedAt` to the current ISO 8601 UTC time exactly once; a prior round's `completedAt` is immutable. Lead then populates `### 5.5.9 Plan Body Verification` in the final report's data.json (`implementationPlanning.planBodyVerification`, schema `schemas/final-report-
|
|
264
|
+
Then lead writes `runs/<task-type>/state/plan-body-verification-<task-type>-<seq>.json` (schema below), **appending this round** — one new `roundHistory[]` entry plus this round's votes on each verified item's `planItems[].rounds[]`. The file accumulates across rounds; it is never truncated to the latest one. After `okstra plan-verify` exits 0, lead sets that new round's `completedAt` to the current ISO 8601 UTC time exactly once; a prior round's `completedAt` is immutable. Lead then populates `### 5.5.9 Plan Body Verification` in the final report's data.json (`implementationPlanning.planBodyVerification`, schema `schemas/final-report-v2.0.schema.json`; template at `templates/reports/final-report-v2.template.md`). The §5.5.9 body is **grouped by plan item**: `planItems[]`, each carrying its `id`, its plain-language `subject` (rendered as the item heading), an optional `sourceSection`, an optional `clarificationId` (the `C-<N>` this item blocks on when `majority-disagree`), and a `verdicts[]` list (`worker / verdict / breakageKind / note`) — one verdict row per worker under that item. The renderer prints three fixed legends (gate values, verdict tokens, breakage kinds a–f) so the reader can decode every cell without opening this spec. The older flat `#### Verdict details` table (`Plan item / Worker / …`, one row per plan-item × worker pair) is superseded by the grouped layout — it hid *what* each vote was about behind a bare `P-*` ID; the subject heading is the fix. The validator's `Plan Body Verification` + `Gate result:` substring checks still gate this section.
|
|
258
265
|
7. **Self-fix loop (one rewrite, targeting planner-fixable defects).** After round 1, lead may run one report-writer rewrite when at least one `majority-disagree` item has a majority of its `DISAGREE` verdicts at `fixability == planner-fixable`. The targeted re-verification after that rewrite is round 2. After round 2, stop automatic self-fix regardless of outcome. Classify every remaining item as `user-decision`, `noncritical-dissent`, or `correctness-critical`. A second automatic self-fix is a contract violation. The fixed order is initial verification → one planner self-fix → targeted re-verification → user gate.
|
|
259
266
|
- **Group the targets by cause before instructing (BLOCKING).** Blocked items are usually several derivatives of one defect — one constant declared twice, one responsibility given two owners — and the coverage rows that cite them fail as a consequence, not independently. Lead MUST partition this round's targets into cause groups and instruct each group as **"remove this cause"**, naming the derivatives it accounts for. **Handing report-writer a bare item list is forbidden**: patched one at a time, each correction leaves the sibling sections still asserting the old value, so the next round re-finds the same family and the budget drains without converging. Record the partition in `planBodyVerification.selfFixGroups[]` (`round`, `causeSummary`, `itemIds`). One group per item is a legitimate outcome only when the items genuinely share no cause — recorded that way, it is a visible diagnosis rather than a skipped one. **Enforced:** `validators/validate-run.py` `_validate_self_fix_grouping` requires the partition, ties `selfFixRoundsApplied` to the highest recorded round, and fails any corrected item that belongs to no group.
|
|
260
267
|
- lead instructs report-writer to rewrite the items in each cause group (NOT a full draft regeneration; procedure in [report-writer](./report-writer.md) §"Self-fix rewrite").
|
|
@@ -268,9 +275,9 @@ round before any host or provider process starts.
|
|
|
268
275
|
- **Round completion.** A round is complete only after the renderer has run on the corrected data.json, lead has appended the round to the state file per step 6, lead has reconciled instructed groups against applied corrections — every `itemIds` entry either carries a `selfFixNote` or is still recorded as broken — **`okstra plan-verify --report <report>` exits 0** (step 5), and lead has then set that round's immutable `completedAt`. A round left with a non-zero exit carries its defect into the next round's inputs, which is how a mis-scored gate survives a whole self-fix budget. A round that was instructed but never rendered has not happened, and counting it inflates the budget that gates promotion. The state-file append is not optional bookkeeping: the next re-verification overwrites data.json's `planItems[].verdicts`, so a round that never reached `roundHistory[]` leaves no record anywhere of what it blocked on — which is the whole reason this file exists. **Enforced:** `validators/validate-run.py` `_validate_plan_body_state_rounds` requires one `roundHistory[]` entry per round `1..roundCount`, each carrying its own `gateResult` and cited by at least one item's `rounds[]`, and requires the file's `selfFixRoundsApplied` to match the report's. For a resolved correctness-critical user response, `_validate_target_round_causality` additionally requires the cited round's `completedAt` to be after every linked canonical `user-decision-required` event and no later than every linked canonical `user-decision-evaluated` event.
|
|
269
276
|
- **Loop termination.** Lead — not the report-writer worker — records the round count in `planBodyVerification.selfFixRoundsApplied` at each round's end, and why the loop stopped in `planBodyVerification.selfFixStopReason`. The count must equal the highest `round` in `selfFixGroups[]`, so it is derivable from recorded work rather than self-reported. A user-directed correction does not consume the automatic self-fix limit, and a verification failure after that correction does not restart the automatic loop:
|
|
270
277
|
- `all-resolved` — no planner-fixable `majority-disagree` item remains. Exit.
|
|
271
|
-
- `no-progress` — the round resolved **zero** planner-fixable items relative to the previous round. Exit even with budget left: the same rewrite would repeat. Newly *introduced* defects count against progress, so a rewrite that trades one defect for another stops the loop rather than churning.
|
|
278
|
+
- `no-progress` — the round resolved **zero** planner-fixable items relative to the previous round. Exit even with budget left: the same rewrite would repeat. Newly *introduced* defects count against progress, so a rewrite that trades one defect for another stops the loop rather than churning. A round that re-targets only what the previous round left unresolved is this same conclusion reached one dispatch earlier — exit on it under this reason rather than paying for the round that proves it. **Enforced (advisory):** `validators/validate-run.py` `_detect_self_fix_recurrence` warns on that shape and names this stop reason.
|
|
272
279
|
- `max-rounds-reached` — `selfFixRoundsApplied == selfFixMaxRounds`. Exit.
|
|
273
|
-
- `cause-group-recurrence` — legacy read-only value for reports produced before activity contract v1. A new activity-contract-v1 run MUST NOT emit it because there is no second automatic self-fix round in which a cause group can recur. **Enforced:** `validators/validate-run.py` `_validate_activity_contract_plan_limits`.
|
|
280
|
+
- `cause-group-recurrence` — legacy read-only value for reports produced before activity contract v1. A new activity-contract-v1 run MUST NOT emit it because there is no second automatic self-fix round in which a cause group can recur. **Enforced:** `validators/validate-run.py` `_validate_activity_contract_plan_limits`. A legacy report that already carries it is still an *exhausted* loop, so step 8 may promote its surviving items: `_SELF_FIX_EXHAUSTED_REASONS` admits this value alongside `no-progress` / `max-rounds-reached`. Refusing it there left such a report with no exit at all — the loop may not run again, and the item may not be promoted either.
|
|
274
281
|
- `not-attempted` — the loop never ran because no item qualified.
|
|
275
282
|
The `no-progress` and `max-rounds-reached` exits are what make the loop terminate; `selfFixMaxRounds` alone is the backstop.
|
|
276
283
|
- a `majority-disagree` item with a majority of its deciding `DISAGREE` votes at `needs-user-input` is NOT a self-fix target — after correctness-critical precedence, it goes straight to the next step as `user-decision` rather than generic `noncritical-dissent`. **Enforced:** `validators/validate-run.py` `_expected_approval_classification`.
|
|
@@ -261,17 +261,17 @@ For those v1 reports, the final report must contain section headings whose **lin
|
|
|
261
261
|
| 7 | `Validation Checklist` | `### Validation Checklist (Korean gloss)` |
|
|
262
262
|
| 8 | `Rollback` | `### Rollback Strategy (Korean gloss)` |
|
|
263
263
|
| 9 | `Requirement Coverage` | `### Requirement Coverage (Korean gloss)` |
|
|
264
|
-
| 10 | `Plan Body Verification` + `Gate result:` | `### Plan Body Verification (Korean gloss)` containing a `Gate result:` line — copy `templates/reports/final-report.template.md §5.5.9` verbatim. Validator checks both substrings. |
|
|
264
|
+
| 10 | `Plan Body Verification` + `Gate result:` | `### Plan Body Verification (Korean gloss)` containing a `Gate result:` line — copy `templates/reports/final-report-v2.template.md §5.5.9` verbatim. Validator checks both substrings. |
|
|
265
265
|
| 11 | `Cross-Project Dependencies` | `### Cross-Project Dependencies (Korean gloss)` — `_(none)_` when the plan is single-project. |
|
|
266
266
|
| 12 | `Decision Drafts` | `### Decision Drafts (Korean gloss)` |
|
|
267
267
|
|
|
268
268
|
**Never author a `User Approval Request` section.** The approval gate moved to the YAML frontmatter `approved: true|false` field, and `validators/validate-run.py` fails any report containing a `## User Approval Request` block or a `### 5.5.8 User Approval Request` stub. This paragraph replaces an earlier row that listed the heading as required — following it produced a report the validator rejected.
|
|
269
269
|
|
|
270
|
-
`Implementation Design Preparation` is NOT in the substring list: `templates/reports/final-report.template.md` §5.5.10 renders that heading from `implementationPlanning.designPreparation`, so it is enforced by the schema + renderer rather than by a heading scan.
|
|
270
|
+
`Implementation Design Preparation` is NOT in the substring list: `templates/reports/final-report-v2.template.md` §5.5.10 renders that heading from `implementationPlanning.designPreparation`, so it is enforced by the schema + renderer rather than by a heading scan.
|
|
271
271
|
|
|
272
272
|
The English keyword is mandatory and the body of each section is written in English, like everything else you author — see "Writing Guidelines" below. For non-`implementation-planning` runs, omit this entire block — these headings are NOT validator-checked for other task-types.
|
|
273
273
|
|
|
274
|
-
The final-report template `templates/reports/final-report.template.md` Section 5.5 already encodes this contract — copy that block verbatim and fill in.
|
|
274
|
+
The final-report template `templates/reports/final-report-v2.template.md` Section 5.5 already encodes this contract — copy that block verbatim and fill in.
|
|
275
275
|
|
|
276
276
|
### Self-fix rewrite (plan-body self-fix round)
|
|
277
277
|
|
|
@@ -305,7 +305,7 @@ When the run's `task-type` is `final-verification`, the report's `## 7. Final Ve
|
|
|
305
305
|
|
|
306
306
|
For every other task-type, set the `Verdict Token` cell to `not-applicable`. Do NOT omit the row — the template renders it for all task-types and downstream tooling expects the field to exist.
|
|
307
307
|
|
|
308
|
-
The final-report template `templates/reports/final-report.template.md` Section 7 already encodes this contract — copy that block verbatim and fill in.
|
|
308
|
+
The final-report template `templates/reports/final-report-v2.template.md` Section 7 already encodes this contract — copy that block verbatim and fill in.
|
|
309
309
|
|
|
310
310
|
### Release-handoff section contract (release-handoff runs only)
|
|
311
311
|
|
|
@@ -313,7 +313,7 @@ When the run's `task-type` is `release-handoff`, the final report MUST include S
|
|
|
313
313
|
|
|
314
314
|
**Single-lead authorship (release-handoff only):** release-handoff has no worker roster. The lead authors the final-report file directly — there is no `Report writer worker` dispatch to perform in Phase 6, no resume-safe dispatch concern, and no mandatory worker-results file for a report-writer role. The rest of this contract's dispatch / resume / fallback machinery applies ONLY when `Report writer worker` is in the roster (i.e. every task-type other than `release-handoff`).
|
|
315
315
|
|
|
316
|
-
The final-report template `templates/reports/final-report.template.md` Section 5.6 already encodes this contract — copy that block verbatim and fill in. For non-`release-handoff` runs, omit Section 5.6 entirely.
|
|
316
|
+
The final-report template `templates/reports/final-report-v2.template.md` Section 5.6 already encodes this contract — copy that block verbatim and fill in. For non-`release-handoff` runs, omit Section 5.6 entirely.
|
|
317
317
|
|
|
318
318
|
### Mandatory worker-result pointer and audit sidecar (BLOCKING)
|
|
319
319
|
|
|
@@ -337,7 +337,7 @@ The selected report-writer preamble defines that audit shape. **Enforced:** `val
|
|
|
337
337
|
|
|
338
338
|
### Main Body Section
|
|
339
339
|
|
|
340
|
-
Section numbering follows `templates/reports/final-report.template.md` exactly — that file is the documentation SSOT for section names and ordering. For full body structure at authoring time, consult your run's **phase-stripped** `final-report-template.md` (the per-task-type instruction-set copy defined in Phase 6 dispatch item 10); the "copy that block verbatim" references below mean the §-block as it appears in that stripped copy, not a re-read of the full source.
|
|
340
|
+
Section numbering follows `templates/reports/final-report-v2.template.md` exactly — that file is the documentation SSOT for section names and ordering. For full body structure at authoring time, consult your run's **phase-stripped** `final-report-template.md` (the per-task-type instruction-set copy defined in Phase 6 dispatch item 10); the "copy that block verbatim" references below mean the §-block as it appears in that stripped copy, not a re-read of the full source.
|
|
341
341
|
|
|
342
342
|
**Verdict Card (top-of-report, mandatory).** Render `## Verdict Card` between the report header and the (conditional) Approval block. Its `Verdict Token` and `Direction` cells MUST byte-match the corresponding cells in `## 7. Final Verdict`. Its `Next Step`, the final-verdict next step, and the first item of `## 3. Recommended Next Steps` MUST name the same route target, though the actionable command and prose need not be byte-identical. Divergence is `contract-violated`.
|
|
343
343
|
|
|
@@ -164,7 +164,7 @@ After each worker attempt returns (regardless of role), Lead MUST verify the can
|
|
|
164
164
|
- The result file exists but its audit sidecar does not, at `runs/<task-type>/worker-results/<worker>-audit-<task-type>-<seq>.md`. Workers write both in the same step, so a result without a sidecar means the Reading Confirmation block — the only evidence the worker read its inputs — was never produced. `validate-run.py` fails the run on this at Phase 7 either way (`validate_worker_results_audit`); checking it here spends the existing one-retry budget while the role can still be re-dispatched, instead of surfacing hours later when the worker session is gone.
|
|
165
165
|
- `okstra worker-audit-check --run-dir <runs/<task-type>/> --task-type <t> --seq <n> --worker <id>` exits 2 on a backticked `path:line` citation in the worker's result that has no matching Evidence read row in its audit sidecar. Run it the moment you collect each result. Phase 7 enforces the same rules from the same implementation (`okstra_ctl.worker_audit_ledger`), but by then the worker session is gone and the only remaining moves are editing the result yourself — which destroys the audit chain the ledger exists to provide — or ending the run `contract-violated`. While the session is alive, `SendMessage` to the worker so it corrects its own citation; that costs about a minute against a re-dispatch or a failed run.
|
|
166
166
|
|
|
167
|
-
The same audit check parses command evidence from canonical rows such as `- Evidence command: {"command":"npm run check","cwd":"<project-root>","exitCode":0,"outputSummary":"all checks passed"}`. Workers record only commands that produced or verified a conclusion, not exploratory `rg`, `ls`, or file-opening commands.
|
|
167
|
+
The same audit check parses command evidence from canonical rows such as `- Evidence command: {"command":"npm run check","cwd":"<project-root>","exitCode":0,"outputSummary":"all checks passed"}`. Workers record only commands that produced or verified a conclusion, not exploratory `rg`, `ls`, or file-opening commands. A malformed row is a contract failure returned by `okstra_ctl.worker_audit_ledger`; send the failure to the worker while its session is still available. Nothing scans these rows for secrets, so a row is never refused for how a setting is named — `AUTH_MODE=off` and `TOKEN_TTL=60` record verbatim. Do not tell a worker to drop or paraphrase a row on those grounds: a worker that cannot record the command it ran has no way to satisfy the evidence ledger that demands it.
|
|
168
168
|
|
|
169
169
|
**One-retry policy:**
|
|
170
170
|
|
|
@@ -12,7 +12,7 @@ profile document.
|
|
|
12
12
|
- **Phase 5.5 (convergence — peer review by workers)**: workers peer-review each other's findings across up to `effectiveMaxRounds` rounds; the lead mediates but does not vote. See `prompts/lead/convergence.md` for the round protocol (replay of findings, `AGREE` / `DISAGREE` / `SUPPLEMENT` verdicts), queue invariants, and final classification (`full-consensus` / `partial-consensus` / `contested` / `worker-unique`). For `requirements-discovery`, `error-analysis`, `implementation-option-selection`, `implementation-planning`, `project-analysis`, `feature-analysis`, and `change-impact-analysis` this phase runs in **adversarial mode** (`convergence.adversarial=true`): verifiers try to refute each finding against its cited evidence and the burden of proof sits on the claim — see that skill's §"Adversarial Verification Mode".
|
|
13
13
|
- Do NOT conclude "no peer review happens" from the roster alone — every profile that lists ≥2 analyser workers runs convergence by default (`convergence.enabled=true` in `task-manifest.json`).
|
|
14
14
|
- For a new `implementation-planning` run, the plan-body sequence is initial verification → one planner self-fix → targeted re-verification → user gate. The initial verification is round 1, the targeted re-verification is round 2, and a second automatic self-fix is a contract violation. A user-directed correction does not consume the automatic self-fix limit, and a verification failure after that correction does not restart the automatic loop.
|
|
15
|
-
- **provider-unavailable fallback (tolerance).** A worker dispatch can fail to produce a result for two distinct reasons, and both take the same recovery path. (1) **Pane budget:** the dispatch is rejected with `no room for another tmux split` (or an equivalent teammate-pane creation failure). (2) **Sandbox CLI-start failure
|
|
15
|
+
- **provider-unavailable fallback (tolerance).** A worker dispatch can fail to produce a result for two distinct reasons, and both take the same recovery path. (1) **Pane budget:** the dispatch is rejected with `no room for another tmux split` (or an equivalent teammate-pane creation failure) — this is the harness running out of room for its own teammate panes, not okstra placing a worker. (2) **Sandbox CLI-start failure:** an external CLI worker wrapper exits non-zero within seconds with empty stdout and its live-log shows `operation not permitted`. In either case the lead spends the one shared retry budget through the assignment's recorded runner. If the provider is still unavailable, record that terminal status and continue only under the convergence quorum rules; never replace it silently with a fixed provider or count a substitute as the original provider's vote. Completed external-CLI workers hold no pane of their own; the harness teammate panes are reclaimed by the selected runtime adapter's resource lifecycle. (This is a prompt instruction, not a code-enforced gate.)
|
|
16
16
|
- Dual-audience final-report contract (shared):
|
|
17
17
|
- data.json is the sole authored report artifact. AI handoff Markdown and human HTML are independently derived from it; neither derived artifact is the other's source.
|
|
18
18
|
- User-facing information belongs in `humanSummary` and the selected task block's `userNarrative`; it must not exist only in Markdown. The HTML human main body explains the result with those fields plus task facts.
|
|
@@ -69,7 +69,7 @@ profile document.
|
|
|
69
69
|
- `origin` — who raised it. `worker-finding` (an analyser or verifier reached it on its own evidence), `material-gap` (neither the brief nor the codebase answers it), or `lead-directed` (the lead's own judgment, **including anything the lead instructed a worker to raise**). A lead that seeds its conclusion into a worker prompt and then reports the worker's agreement as an independent finding has mislabelled the row; that shape is what let one run block on a question its own lead had authored.
|
|
70
70
|
- `userConfirmation` — what happened before the row was written. `asked-and-answered`, `asked-awaiting` (asked, no answer yet), or `deferred-no-interactive-session` (this run had no user to ask). Record an answer in `userInput` and move `status` to `answered`.
|
|
71
71
|
- Neither field is required once `status` is `answered` / `resolved` — the record lives in `userInput` by then.
|
|
72
|
-
- **Legacy canonical column schema (must match `templates/reports/final-report.template.md` §1 exactly):** every `## 1. Clarification Items` table has exactly these 4 columns, in this order:
|
|
72
|
+
- **Legacy canonical column schema (must match `templates/reports/final-report-v2.template.md` §1 exactly):** every `## 1. Clarification Items` table has exactly these 4 columns, in this order:
|
|
73
73
|
`| <record-meta> | Statement | Expected form | User input |` (the first header is the i18n `columns.recordMeta` label — `Record`).
|
|
74
74
|
The five short fields (ID, Ticket ID, Kind, Blocks, Status) are stacked inside the single record-meta cell, one per line separated by `<br>`, in this fixed order (mirrors the §2.1 Primary-Evidence meta column):
|
|
75
75
|
|
|
@@ -94,6 +94,8 @@ persisted prompt lacks the heading `Coding-conventions preflight`
|
|
|
94
94
|
- **local git operations only**: `git add`, `git commit`. Prefer small commits keyed to plan steps.
|
|
95
95
|
- **Explicit-path staging only (BLOCKING).** Stage exactly the files a plan step touches by naming each path — `git add <path1> <path2>`. Never use the bulk forms `git add .`, `git add -A`, `git add -u`, or `git add --all`: they sweep in unrelated edits, stray build output, and editor scratch files. Never use `git add -f` (force) under any circumstance — `-f` is the *only* way a `.gitignore`d path reaches a commit, and a forced ignored file is always a defect. If `git add <path>` reports the path is ignored, that file does not belong in the commit; do not override it — leave it untracked.
|
|
96
96
|
- **No ignored / okstra files in commits (BLOCKING).** Before every `git commit`, run `git diff --cached --name-only` and pipe the staged paths through `git check-ignore --stdin --no-index`; abort the commit if it reports **any** match — a staged path that `.gitignore` excludes means a bulk-add or `-f` leaked it in. The check explicitly covers `.okstra/` (and `.project-docs/` when the legacy symlink is present): `.okstra/**` is gitignored, and force-staging it onto the stage branch is the one way these verification artifacts reach the upstream PR. Conformance/qa evidence belongs in the carry sidecar and verifier result — committing it is never correct, even when a step's instructions seem to ask for it.
|
|
97
|
+
- **Clean-tree checks use `okstra worktree-status --check-clean` (BLOCKING).** The worktree you execute in carries okstra's own provisioning — `.okstra`, the synced entries (`.project-docs`, `.claude`, …), and the nested `stage-<N>/` worktree — so `git status --porcelain` is never empty here and its emptiness proves nothing about your stage. Use `okstra worktree-status --check-clean`: it asks the same question over source paths only and exits 1 when dirty, so it chains as an assertion. This applies to a check you write yourself AND to one you inherit: when a plan step's `command` cell asserts cleanliness with a bare `git status`, run the okstra command in its place and record the substitution in `Out-of-plan edits` — the step's intent was a clean stage, not a literal empty status.
|
|
98
|
+
- **Never read an `.okstra/` artifact from a git object (BLOCKING).** `.okstra/**` is gitignored and never committed (see the staging rules above), so `git cat-file -e <tag>:.okstra/…`, `git show <tag>:.okstra/…`, and every variant of that read fail by construction — the answer is never "commit it after all". When a plan step's command depends on such a read, the step is unsatisfiable as written: read the artifact from the working tree instead, record the deviation, and carry the artifact forward through the stage carry sidecar.
|
|
97
99
|
- **Commit message format (mandatory)**: every commit message MUST follow Conventional Commits — `<type>(<scope>): <subject>` for the first line, optional body separated by a blank line, optional footer. Constraints:
|
|
98
100
|
- `<type>` MUST be one of: `feat` / `fix` / `perf` / `revert` / `deps` / `docs` / `refactor` / `build` / `ci` / `chore` / `test`. When the repo is `release-please`-managed, this aligns the commit with a configured changelog section.
|
|
99
101
|
- `<scope>` SHOULD be the plan step identifier or the primary module touched (e.g. `feat(report-writer): ...`). Omit the parentheses only when no meaningful scope applies.
|