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
|
@@ -10,8 +10,8 @@ at Phase 5, BEFORE constructing the verifier worker dispatch prompts.
|
|
|
10
10
|
## Verifier roles (resolved at run-prep time)
|
|
11
11
|
|
|
12
12
|
- **Verifier dispatch labelling.** The core functional role label is `<provider>-verifier` (here, and identically in `final-verification`). Provider, role, and model identity are owned by `prompts/lead/okstra-lead-contract.md` "Model assignments"; the selected runtime adapter owns provider-native dispatch-label mapping (including any `name` / `**Pane role:**` fields) and token-attribution wiring under its "Semantic operation mapping". This functional label is NOT what the run's PROGRESS checkpoints carry: `phase-4-dispatch` / `phase-5-collect` name the roster role team-state records (`Claude worker`, `Codex worker`), because that is the entry the Phase 7 conformance check matches them against.
|
|
13
|
-
- The verifier slots are `Claude verifier` and `Codex verifier`, plus `Antigravity verifier` **only when `antigravity` is in the resolved `--workers` roster**. Every verifier in the resolved roster is dispatched
|
|
14
|
-
- Session isolation — not model-variant divergence — is the primary self-review safeguard: each verifier is a separate CLI invocation with its own context window, so reusing the
|
|
13
|
+
- The verifier slots are `Claude verifier` and `Codex verifier`, plus `Antigravity verifier` **only when `antigravity` is in the resolved `--workers` roster**. Every verifier in the resolved roster is dispatched except the one whose worker ID holds the executor role this run: that ID materializes as the executor on every dispatch (`scripts/okstra_ctl/worker_prompt_policy.py`), so the executor's own provider has no separate verifier session in the current plumbing — a follow-up design item. Independence still holds where it counts: every verdict comes from a fresh CLI session with no shared context, never from the session that wrote the diff. Verifiers MUST NOT call Edit, Write, or any Bash command that mutates files outside the run's artifact directories. If a verifier wants a fix, it records the recommendation in its worker result; it does not apply the fix itself.
|
|
14
|
+
- Session isolation — not model-variant divergence — is the primary self-review safeguard: each verifier is a separate CLI invocation with its own context window, so a verifier reusing the executor's model variant is acceptable. Different model variants (e.g. executor=opus / Claude verifier=sonnet) remain recommended when available.
|
|
15
15
|
- Phase-specific model defaults override the shared defaults: `Claude verifier`=`opus`, `Codex verifier`=`gpt-5.6-sol`, `Antigravity verifier`=`gemini-3.1-pro` (only when present in the roster). The `Executor`'s model is taken from the provider-specific worker model corresponding to `--executor`: claude→`--claude-model` (default `opus`), codex→`--codex-model` (default `gpt-5.6-sol`), antigravity→`--antigravity-model` (default `gemini-3.1-pro`).
|
|
16
16
|
- Verifiers read from the SAME working tree path the Executor used so they observe the exact diff the Executor produced. Verifiers remain strictly read-only there.
|
|
17
17
|
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Change Impact Analysis Profile
|
|
2
2
|
|
|
3
|
+
```yaml
|
|
4
|
+
roles:
|
|
5
|
+
- role: analyser
|
|
6
|
+
count: 2
|
|
7
|
+
optionalCount: 3
|
|
8
|
+
duty: analysis-worker
|
|
9
|
+
minDistinctProviders: 2
|
|
10
|
+
- role: report-writer
|
|
11
|
+
count: 1
|
|
12
|
+
duty: report-writer
|
|
13
|
+
- role: verifier
|
|
14
|
+
count: 0
|
|
15
|
+
duty: reverification-worker
|
|
16
|
+
dynamic: true
|
|
17
|
+
```
|
|
18
|
+
|
|
3
19
|
- Purpose: assess the read-only impact of a proposed change, including preserved behavior, affected dependencies, and constraints that a later planning phase must resolve
|
|
4
20
|
- Required workers:
|
|
5
21
|
- claude
|
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Error Analysis Profile
|
|
2
2
|
|
|
3
|
+
```yaml
|
|
4
|
+
roles:
|
|
5
|
+
- role: analyser
|
|
6
|
+
count: 2
|
|
7
|
+
optionalCount: 3
|
|
8
|
+
duty: diagnosis-worker
|
|
9
|
+
minDistinctProviders: 2
|
|
10
|
+
- role: critic
|
|
11
|
+
count: 0
|
|
12
|
+
optionalCount: 1
|
|
13
|
+
duty: scope-critic
|
|
14
|
+
- role: report-writer
|
|
15
|
+
count: 1
|
|
16
|
+
duty: report-writer
|
|
17
|
+
- role: verifier
|
|
18
|
+
count: 0
|
|
19
|
+
duty: reverification-worker
|
|
20
|
+
dynamic: true
|
|
21
|
+
```
|
|
22
|
+
|
|
3
23
|
- Purpose: analyse reported errors or incidents and identify likely causes, missing evidence, and validation paths
|
|
4
24
|
- Required workers:
|
|
5
25
|
- claude
|
|
@@ -27,7 +47,7 @@
|
|
|
27
47
|
- Structured diagnosis and routing contract:
|
|
28
48
|
- `errorAnalysis` is the source of truth for reproduction status, `EA-NNN` cause candidates, the sharp next diagnostic, and the next route.
|
|
29
49
|
- A route to `implementation-option-selection` requires a credible leading cause referenced by `routing.leadingCauseId` and `begin-option-selection` as the direction. A route back to `error-analysis` requires the sharp next diagnostic and `continue-investigation` as the direction.
|
|
30
|
-
- Structure is enforced by `schemas/final-report-
|
|
50
|
+
- Structure is enforced by `schemas/final-report-v2.0.schema.json` `$defs.ErrorAnalysis`. Cross-field diagnosis and route semantics are enforced by `validators/validate-run.py::_validate_error_analysis_consistency`.
|
|
31
51
|
- Primary focus areas:
|
|
32
52
|
- symptom and trigger clarification
|
|
33
53
|
- root-cause candidates
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Feature Analysis Profile
|
|
2
2
|
|
|
3
|
+
```yaml
|
|
4
|
+
roles:
|
|
5
|
+
- role: analyser
|
|
6
|
+
count: 2
|
|
7
|
+
optionalCount: 3
|
|
8
|
+
duty: analysis-worker
|
|
9
|
+
minDistinctProviders: 2
|
|
10
|
+
- role: report-writer
|
|
11
|
+
count: 1
|
|
12
|
+
duty: report-writer
|
|
13
|
+
- role: verifier
|
|
14
|
+
count: 0
|
|
15
|
+
duty: reverification-worker
|
|
16
|
+
dynamic: true
|
|
17
|
+
```
|
|
18
|
+
|
|
3
19
|
- Purpose: analyse a confirmed feature target's behavior, rules, state changes, external calls, and test coverage scope without designing or changing an implementation
|
|
4
20
|
- Required workers:
|
|
5
21
|
- claude
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Final Verification Profile
|
|
2
2
|
|
|
3
|
+
```yaml
|
|
4
|
+
roles:
|
|
5
|
+
- role: verifier
|
|
6
|
+
count: 2
|
|
7
|
+
optionalCount: 3
|
|
8
|
+
duty: acceptance-verifier
|
|
9
|
+
minDistinctProviders: 2
|
|
10
|
+
- role: critic
|
|
11
|
+
count: 0
|
|
12
|
+
optionalCount: 1
|
|
13
|
+
duty: acceptance-critic
|
|
14
|
+
- role: report-writer
|
|
15
|
+
count: 1
|
|
16
|
+
duty: report-writer
|
|
17
|
+
```
|
|
18
|
+
|
|
3
19
|
- Purpose: analyse completed work and identify remaining defects, omissions, and delivery risk before final acceptance
|
|
4
20
|
- Required workers:
|
|
5
21
|
- claude
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Implementation Option Selection Profile
|
|
2
2
|
|
|
3
|
+
```yaml
|
|
4
|
+
roles:
|
|
5
|
+
- role: designer
|
|
6
|
+
count: 3
|
|
7
|
+
optionalCount: 2
|
|
8
|
+
duty: direction-selection-worker
|
|
9
|
+
minDistinctProviders: 3
|
|
10
|
+
- role: report-writer
|
|
11
|
+
count: 1
|
|
12
|
+
duty: report-writer
|
|
13
|
+
- role: verifier
|
|
14
|
+
count: 0
|
|
15
|
+
duty: reverification-worker
|
|
16
|
+
dynamic: true
|
|
17
|
+
```
|
|
18
|
+
|
|
3
19
|
- Purpose: compare feasible implementation directions before planning, preserving a read-only record of the evidence and trade-offs that selects the direction to plan
|
|
4
20
|
- Required workers:
|
|
5
21
|
- claude
|
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Implementation Planning Profile
|
|
2
2
|
|
|
3
|
+
```yaml
|
|
4
|
+
roles:
|
|
5
|
+
- role: planner
|
|
6
|
+
count: 2
|
|
7
|
+
optionalCount: 3
|
|
8
|
+
duty: planning-worker
|
|
9
|
+
minDistinctProviders: 2
|
|
10
|
+
- role: critic
|
|
11
|
+
count: 0
|
|
12
|
+
optionalCount: 1
|
|
13
|
+
duty: acceptance-critic
|
|
14
|
+
- role: report-writer
|
|
15
|
+
count: 1
|
|
16
|
+
duty: report-writer
|
|
17
|
+
- role: verifier
|
|
18
|
+
count: 0
|
|
19
|
+
duty: reverification-worker
|
|
20
|
+
dynamic: true
|
|
21
|
+
```
|
|
22
|
+
|
|
3
23
|
- Purpose: turn an upstream-selected direction into an executable plan; legacy reruns may retain candidate comparison
|
|
4
24
|
- Required workers:
|
|
5
25
|
- claude
|
|
@@ -58,13 +78,13 @@
|
|
|
58
78
|
- one `endStateCoverage` row per brief end-state id, whose `coveredBy` names the `R-NNN` row that carries it. The two tables are a chain, not duplicates: `endStateCoverage` proves no reporter requirement was dropped, `requirementCoverage` proves each one reaches a stage.
|
|
59
79
|
- Implementation Design Preparation (`implementation-design-prep-v1`, BLOCKING):
|
|
60
80
|
- **Detector SSOT:** the planner MUST run the V1 detector defined by `scripts/okstra_ctl/design_surfaces.py` (`detect_design_surfaces()` over the detector's `RULES`) and MUST NOT invent or copy a second keyword list into the plan or prompt. **Enforced:** `validators/validate-run.py` `_validate_detector_coverage` reruns that detector and compares every `(stage, kind)` plus its trigger evidence.
|
|
61
|
-
- **Exactly-once coverage:** for every detector-produced `(stage, kind)`, the planner MUST write exactly one `designSurfaceCoverage` row on that stage. **Enforced:** `validators/validate-run.py` `_validate_detector_coverage` rejects missing, duplicate, extra-detector-kind, or evidence-mismatched rows; `schemas/final-report-
|
|
62
|
-
- **Disposition:** a row MUST use `inline-contract` only when the stage already states the kind-specific minimum implementation contract; otherwise it MUST use `prep-item` and reference one or more `designPreparation.items`. `not-applicable` is legal only with a concrete rationale consistent with the stage action. **Enforced:** `schemas/final-report-
|
|
63
|
-
- **AI-prepared proposal:** every referenced PREP item MUST record `kind`, `stageRefs`, `need`, evidence-cited `knownFacts`, `openQuestions`, a concrete evidence-backed `aiProposal` (`summary`, `details`, `assumptions`, `evidence`, `confidence`), `humanConfirmation`, explicit `status`, and the safest reversible default available. **Enforced:** `schemas/final-report-
|
|
64
|
-
- **Status choice:** prefer `provisional` with a `workingAssumption`, concrete `guardrails`, `reviewAt`, `ifStillOpen`, and canonical `requestPath`; use `blocked` only for business policy, external authority, a destructive migration decision, or the absence of any safe reversible assumption. **Enforced:** `schemas/final-report-
|
|
81
|
+
- **Exactly-once coverage:** for every detector-produced `(stage, kind)`, the planner MUST write exactly one `designSurfaceCoverage` row on that stage. **Enforced:** `validators/validate-run.py` `_validate_detector_coverage` rejects missing, duplicate, extra-detector-kind, or evidence-mismatched rows; `schemas/final-report-v2.0.schema.json` `$defs.DesignSurfaceCoverage` enforces the row shape.
|
|
82
|
+
- **Disposition:** a row MUST use `inline-contract` only when the stage already states the kind-specific minimum implementation contract; otherwise it MUST use `prep-item` and reference one or more `designPreparation.items`. `not-applicable` is legal only with a concrete rationale consistent with the stage action. **Enforced:** `schemas/final-report-v2.0.schema.json` `$defs.DesignSurfaceCoverage` enforces the disposition-specific fields, and `prompts/lead/plan-body-verification.md` `P-Prep-S<stage>-<kind>` verifies semantic sufficiency.
|
|
83
|
+
- **AI-prepared proposal:** every referenced PREP item MUST record `kind`, `stageRefs`, `need`, evidence-cited `knownFacts`, `openQuestions`, a concrete evidence-backed `aiProposal` (`summary`, `details`, `assumptions`, `evidence`, `confidence`), `humanConfirmation`, explicit `status`, and the safest reversible default available. **Enforced:** `schemas/final-report-v2.0.schema.json` `$defs.DesignPrepItem` / `$defs.DesignPrepProposal` enforce required fields, `validators/validate-run.py` `_validate_prep_references` enforces the bidirectional stage/kind link, and `prompts/lead/plan-body-verification.md` rejects empty or non-implementable proposals.
|
|
84
|
+
- **Status choice:** prefer `provisional` with a `workingAssumption`, concrete `guardrails`, `reviewAt`, `ifStillOpen`, and canonical `requestPath`; use `blocked` only for business policy, external authority, a destructive migration decision, or the absence of any safe reversible assumption. **Enforced:** `schemas/final-report-v2.0.schema.json` `$defs.DesignPrepItem` enforces state-specific fields, `validators/validate-run.py` `_validate_design_prep_states` enforces confirmation/request invariants, and `prompts/lead/plan-body-verification.md` judges whether the disposition is justified. A declared `blocked` status does not by itself fail plan-body verification.
|
|
65
85
|
- **External-reality anchoring (`external-interface` / `transformation-mapping` surfaces):** these two detector kinds are correct only against data whose shape lives *outside this repository* (a third-party response body / external payload format). For such a surface the referenced PREP item's `aiProposal` MUST derive the assumed shape — selectors, field paths, response structure — from a **captured real sample** and cite it in `knownFacts` / `evidence` (source + capture time); a shape invented from internal reasoning and marked `confidence: high` is the disallowed move, because a plan built on an assumed shape yields an implementation whose parser and fixture only ever agree with each other. When the brief supplies no sample and none is capturable at plan time, the item MUST stay `provisional` with a `workingAssumption` that the external shape is unverified against reality, a `guardrails` line forbidding the implementation from presenting a synthetic-fixture green run as reality-verified, and an `ifStillOpen` that routes to user confirmation against real data — it MUST NOT be dispositioned `inline-contract` / settled. **Enforced (semantic):** the surface's presence is machine-checked by `_validate_detector_coverage`; whether its proposal's evidence is genuinely external is judged by the §5.5.9 `P-Prep-S<stage>-<kind>` round (this phase runs it adversarially).
|
|
66
|
-
- **Planner-only test surface:** add `manual-user-test` only when a test prerequisite changes the implementation interface or acceptance contract; the V1 detector never emits it. **Enforced:** `validators/validate-run.py` `_validate_detector_coverage` rejects detector-produced `manual-user-test`, `schemas/final-report-
|
|
67
|
-
- **Trivial task:** when the detector returns no surfaces and no interface/acceptance-changing manual test input exists, `designPreparation` MUST use `mode: no-design-inputs`, an empty `items` array, and a concrete reason tied to the plan. **Enforced:** `schemas/final-report-
|
|
86
|
+
- **Planner-only test surface:** add `manual-user-test` only when a test prerequisite changes the implementation interface or acceptance contract; the V1 detector never emits it. **Enforced:** `validators/validate-run.py` `_validate_detector_coverage` rejects detector-produced `manual-user-test`, `schemas/final-report-v2.0.schema.json` permits its planner-authored shape, and `prompts/lead/plan-body-verification.md` verifies the stage-action rationale.
|
|
87
|
+
- **Trivial task:** when the detector returns no surfaces and no interface/acceptance-changing manual test input exists, `designPreparation` MUST use `mode: no-design-inputs`, an empty `items` array, and a concrete reason tied to the plan. **Enforced:** `schemas/final-report-v2.0.schema.json` `$defs.DesignPreparation` requires the reason and empty array for that mode; `validators/validate-run.py` `_validate_design_prep_contract` validates the marked V1 payload.
|
|
68
88
|
- Approval gate (phase-specific addendum to shared authority rule):
|
|
69
89
|
- The YAML frontmatter `approved: true|false` field is the only authorised approval gate. report-writer always emits `approved: false`. The user clears it either by (a) editing the frontmatter line to `approved: true` directly, or (b) invoking the next phase with `--approve` so the CLI flips the frontmatter on the user's behalf. `okstra_ctl.run._validate_approved_plan` reads this field and refuses entry until it is `true`.
|
|
70
90
|
- Cross-verification mode:
|
|
@@ -103,7 +123,7 @@
|
|
|
103
123
|
- Legacy candidate-comparison requires at least two implementation options. **Each option must include**:
|
|
104
124
|
- **File Structure**: an explicit list of files to create / modify / delete with each file's responsibility (one-line each). Use the form `Create: path — responsibility` / `Modify: path:line-range — change summary` / `Delete: path — reason`. Write every `path` in full and `<PROJECT_ROOT>`-relative — never ellipsis-abbreviated (`…` / `...` / a trailing `/…`); an abbreviated path does not resolve and is rejected by plan-body verification as a kind-b path mismatch.
|
|
105
125
|
- **Two-tier change description.** Each `fileStructure` row carries `summary` **and** optional `details`, and they are not interchangeable:
|
|
106
|
-
- `summary` — one plain-language sentence a reviewer who has never opened this file can follow: what changes and why it is needed. Name behaviour and domain nouns, not identifiers. No function/type/variable names, no call chains, no line numbers, no conditional logic spelled out. **Enforced:** `schemas/final-report-
|
|
126
|
+
- `summary` — one plain-language sentence a reviewer who has never opened this file can follow: what changes and why it is needed. Name behaviour and domain nouns, not identifiers. No function/type/variable names, no call chains, no line numbers, no conditional logic spelled out. **Enforced:** `schemas/final-report-v2.0.schema.json` `$defs.OptionCandidate.fileStructure.items.summary` caps it at 120 characters, so a dense identifier dump fails schema validation.
|
|
107
127
|
- `details` — the technical specifics that used to be crammed into `summary`: exact symbol names, signatures, comparison semantics, line ranges, enum members. Omit the field when there is nothing beyond the summary.
|
|
108
128
|
- Bad `summary` (identifier dump, no readable claim): `Widen the return of retrieveFontFamilyGroupWithFontVersionId to also yield the matched FontFamily (own key and enabled flag) and the matched Font.status.`
|
|
109
129
|
- Good — `summary`: `Carry enough information out of the font lookup to tell whether the matched family is switched off.` / `details`: `Add the matched FontFamily (own key + enabled) and Font.status to the return of retrieveFontFamilyGroupWithFontVersionId. Both are already in scope in the :102-104 loop and dropped at return.`
|
|
@@ -111,12 +131,12 @@
|
|
|
111
131
|
- estimated blast radius (units, configs, deployment manifests, data migrations)
|
|
112
132
|
- trade-off matrix across options (rows = options, columns at minimum: complexity, risk, reversibility, test coverage cost, rollout cost)
|
|
113
133
|
- recommended option with rationale tied to the design principles above
|
|
114
|
-
- `recommendedOption.testSeams` is a mandatory array with one row per boundary a test injects at and replaces: `boundary`, `injectedAs`, and `replacedInTest`. An empty array is legal only with a defensible reason. `schemas/final-report-
|
|
134
|
+
- `recommendedOption.testSeams` is a mandatory array with one row per boundary a test injects at and replaces: `boundary`, `injectedAs`, and `replacedInTest`. An empty array is legal only with a defensible reason. `schemas/final-report-v2.0.schema.json` requires the array and all three row fields; the §5.5.9 `P-Var-*` round rejects a seam whose construction or wiring point is not actually replaceable.
|
|
115
135
|
- Record non-blocking working assumptions inside the Recommended Option. A required answer belongs in a `Blocks=approval` clarification instead. Omit the assumptions only when there are none.
|
|
116
136
|
- The YAML frontmatter carries `implementation-option:` directly under `approved:` so the user can select an Option Candidate after planning.
|
|
117
137
|
- Required deliverable shape (final report, in addition to the standard sections):
|
|
118
138
|
- In the selected-direction branch, `directionRealization` is the sole design payload. Its `fileStructure`, interfaces, blast radius, test seams, assumptions, and invariants concretize the snapshot without introducing another option or recommendation.
|
|
119
|
-
- **Variation-point analysis (`variationPointAnalysis`, mandatory — every plan emits the block, rendered as §5.5.11):** declare `hasMultipleImplementations`, and when it is `true`, one `points[]` row per varying behavior carrying `behavior`, the two or more `implementations` that serve it, `evidence` (a `path:line`, or the sibling task / stage that already implements it), and an `extractionDecision` of `extract` / `interfaceKind` / `coveredBy` (the Stage Map stage that builds the interface) / `rationale`. **A `false` declaration is not an omission — it is a claim**, so it carries a written `noVariationRationale` and an empty `points` array; the two are mutually exclusive, because declared points would be silently dropped from verification under a `false` header. A project whose `.okstra/project.json` sets `architecture.style: hexagonal` extracts a point as a port (`interfaceKind: "port"`), never as a shared helper. **Enforced:** `schemas/final-report-
|
|
139
|
+
- **Variation-point analysis (`variationPointAnalysis`, mandatory — every plan emits the block, rendered as §5.5.11):** declare `hasMultipleImplementations`, and when it is `true`, one `points[]` row per varying behavior carrying `behavior`, the two or more `implementations` that serve it, `evidence` (a `path:line`, or the sibling task / stage that already implements it), and an `extractionDecision` of `extract` / `interfaceKind` / `coveredBy` (the Stage Map stage that builds the interface) / `rationale`. **A `false` declaration is not an omission — it is a claim**, so it carries a written `noVariationRationale` and an empty `points` array; the two are mutually exclusive, because declared points would be silently dropped from verification under a `false` header. A project whose `.okstra/project.json` sets `architecture.style: hexagonal` extracts a point as a port (`interfaceKind: "port"`), never as a shared helper. **Enforced:** `schemas/final-report-v2.0.schema.json` `$defs.VariationPointAnalysis` / `$defs.VariationPoint` make the block required and pin the row shape; `validators/validate-run.py` `_validate_variation_point_analysis` rejects a `false` declaration with no rationale, a `false` declaration carrying points, a `true` declaration with no point, an `extract: true` decision naming no `interfaceKind` or no `coveredBy`, and a hexagonal project extracting as anything but a port; and every point becomes a `P-Var-<N>` plan item judged in §5.5.9 (`prompts/lead/plan-body-verification.md`) — a plan declaring no variation point is still verified, through the lone `P-Var-0`.
|
|
120
140
|
- **Stage Map (mandatory — always emitted, even when N=1):** a table of all stages with `stage | title | depends-on | step-count | exit-contract-summary`. `depends-on` is `(none)` or a comma-separated stage number list. Stages with `depends-on (none)` can be implemented in parallel by two simultaneous `implementation` runs.
|
|
121
141
|
- **Keep the table at exactly 5 columns** — do NOT add a column. `validators/validate-implementation-plan-stages.py` parses `stage | title | depends-on | step-count | exit-contract-summary` and silently skips any row that is not exactly 5 cells, so a 6th column would drop every stage and bypass S2–S11.
|
|
122
142
|
- **Multi-project plans only** (the plan's work spans more than one project — see the Project-boundary partition rule below): prefix each stage's `title` cell with a `[<project>]` tag (e.g. `[okstra] Add X`) so the project each stage belongs to is readable at a glance, and add exactly one line directly under the Stage Map table — `Cross-project parallelism: <which per-project stages run in parallel, which are sequenced, and the cross-project dependency that forces each sequencing>`. Single-project plans omit both the tag and the line.
|
|
@@ -132,6 +152,9 @@
|
|
|
132
152
|
- **Per-stage subsections** (`## 5.5.<i> Stage <i>: <title>` for each `i`), each containing the four required subsections:
|
|
133
153
|
- `### Carry-In` — for `depends-on (none)`: task-brief only. Otherwise: each depended-on stage's static exit contract + runtime sidecar path `runs/<impl-key>/carry/stage-<i>.json` placeholder.
|
|
134
154
|
- `### Stepwise Execution Order` — bite-sized table with `step | action | files | command | outcome | expected`. `outcome` is one word — `PASS` or `FAIL` — and `expected` is the sentence saying what that looks like here; a verdict written inside the sentence is not read as one. The `files` cell lists each touched path in full and `<PROJECT_ROOT>`-relative — never ellipsis-abbreviated (`…` / `...`), which does not resolve and is rejected by plan-body verification as a kind-b path mismatch. **Effective row count ≤ 8** (excluding header / divider / blank). Each step is one cohesive, self-contained change (no lower time bound; it may span several files that change together); for code steps include actual code or diff sketch. **TDD ordering is MUST, not a preference:** the **first** effective step's `action` cell MUST start with the literal `RED:` and describe the failing test(s) that capture this stage's `Acceptance` **and the three declared `Test case (success|boundary|failure)` lines** (`outcome` = `FAIL`) — the RED step encodes the case set, not a single happy-path assertion; at least one later `action` cell MUST start with the literal `GREEN:` and describe the minimal implementation that makes it pass (`outcome` = `PASS`); an optional refactor step starts with `REFACTOR:`. **Exemption:** doc-only / config-only / pure-rename stages with no observable runtime behaviour may omit RED/GREEN by declaring one line `TDD exemption: <reason>` in the stage section (mirrors the executor's per-step exemption in `_implementation-executor.md`). Validator S10c enforces RED-first + GREEN; the `outcome` cell agreeing with its `RED:` / `GREEN:` prefix is a schema conditional (`StageStepRow.allOf`), so a plan whose data.json says otherwise never reaches the validator. S10e rejects a `TDD exemption:` whose reason is not one of doc-only / config-only / pure-rename (both in `validators/validate-implementation-plan-stages.py`).
|
|
155
|
+
- **The `command` cell runs inside an okstra task worktree, not a bare checkout (BLOCKING).** okstra provisions `.okstra`, the configured sync entries (`.project-docs`, `.claude`, …), and — for `implementation` — a nested `stage-<N>/` worktree into the tree the step executes in. Two consequences bind every command you write:
|
|
156
|
+
- **Clean-tree assertions use `okstra worktree-status --check-clean`.** A bare `git status --porcelain` is never empty there, so an assertion built on one fails on okstra's scaffolding rather than on the stage's work. The okstra command asks the same question over source paths only and exits 1 when dirty, so it chains: `okstra worktree-status --check-clean && git tag -f stage-<N>-exit`. Validator S13 rejects the bare form.
|
|
157
|
+
- **Never read an `.okstra/` artifact back out of a git object.** `.okstra/**` is gitignored and never committed — the executor aborts a commit that stages an ignored path and the verifier reports a committed `.okstra` path as a branch defect — so `git cat-file -e <tag>:.okstra/…`, `git show <tag>:.okstra/…`, and every variant of that read can never resolve, at any tag, in any stage. A later stage that needs a QA artifact reads it from the working tree or receives it through the carry sidecar / verifier result; do not design a stage contract around one being reachable from a tag. Validator S12 rejects the read.
|
|
135
158
|
- **Per-stage conformance declaration (mandatory one line, in the stage section — same placement freedom as `TDD exemption:`):** the stage MUST carry exactly one of:
|
|
136
159
|
- `Conformance tests: stage-<N> — <task_root>/qa/scripts/stage-<N>.<ext> (requires=[db|io|http|external,...])` — a Tier3 verification script that proves this stage's upstream requirements (brief / requirements-discovery / error-analysis / improvement-discovery → this stage's `Acceptance`) hold against **real** DB rows, real endpoints, or the real external API — NOT mocks. When you emit this line you MUST also (a) write the script to `<task_root>/qa/scripts/stage-<N>.<ext>` and (b) add a matching entry to `<task_root>/qa/conformance-manifest.json` with fields `stageKey` (= `<task-id>-stage-<N>`), `script`, `runCommand`, `requirementIds`, `requires` (subset of `{db, io, http, external}`), `passContract`, `exemption: null`, `waiver: null`. The script's standard interface: a `main` that exits `0`=PASS / non-zero=FAIL, and whose stdout ends with `QA-RESULT: PASS|FAIL` followed by one `REQ <id>: PASS|FAIL: <reason>` line per requirement. When the verification body is a test spec, author it with the project's own test framework (devDependency) invoked via a discovery override at `<task_root>/qa/scripts/` (jest: `--config <project config> --roots <task_root>/qa/scripts`) — never hand-roll `describe`/`expect` and never widen the project's own test config; for TypeScript specs also write `<task_root>/qa/scripts/tsconfig.json` extending the project tsconfig with the runner's `types` entry so editors resolve the file.
|
|
137
160
|
- `Conformance exemption: <reason>` — only for stages that touch no db/io/http/external surface, or where unit tests fully cover the increment. (If the eventual `implementation` diff actually touches one of those surfaces, `validate-run.py`'s diff-surface cross-check is BLOCKING — an exemption cannot hide a real db/io/http/external change.)
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Implementation Profile
|
|
2
2
|
|
|
3
|
+
```yaml
|
|
4
|
+
roles:
|
|
5
|
+
- role: implementer
|
|
6
|
+
count: 1
|
|
7
|
+
duty: implementation-executor
|
|
8
|
+
- role: verifier
|
|
9
|
+
count: 2
|
|
10
|
+
optionalCount: 1
|
|
11
|
+
duty: implementation-verifier
|
|
12
|
+
minDistinctProviders: 2
|
|
13
|
+
- role: report-writer
|
|
14
|
+
count: 1
|
|
15
|
+
duty: report-writer
|
|
16
|
+
```
|
|
17
|
+
|
|
3
18
|
- Purpose: realise the approved `implementation-planning` deliverable as actual source changes, with cross-model verification, while keeping the run reversible
|
|
4
19
|
- **Run-level fixed cost:** the verifier set, Phase 5.5 convergence, and the Phase 6 report-writer run exactly once per implementation run, over this run's single stage diff — never once per step.
|
|
5
20
|
- **Fix run (profile carries a "Fix-Run Carry" block):** the executor's scope is the carried blocking findings plus the previous routing recommendation — it MUST NOT re-execute plan steps the previous run completed. Verifiers apply the "Fix-run incremental scope" section of `_implementation-verifier.md`; the report writer applies "Fix-run incremental authoring" in `report-writer.md`. The full validation-command re-run is NOT reduced.
|
|
@@ -16,7 +31,8 @@
|
|
|
16
31
|
- Executor model: `{{EXECUTOR_MODEL_DISPLAY}}` (CLI launch value: `{{EXECUTOR_MODEL_EXECUTION_VALUE}}`; host-native launch value: `{{EXECUTOR_HOST_MODEL_VALUE}}`)
|
|
17
32
|
- Executor runner: `{{EXECUTOR_RUNNER}}`
|
|
18
33
|
- Executor dispatch mode: `{{EXECUTOR_DISPATCH_MODE}}`
|
|
19
|
-
- Wherever this profile mentions the `Executor`, it refers to the role bound above.
|
|
34
|
+
- Wherever this profile mentions the `Executor`, it refers to the role bound above. Every analysis provider in the resolved roster **except `{{EXECUTOR_WORKER_ID}}`** is dispatched as a verifier, each in a fresh session with no shared context, so no verdict comes from the session that wrote the diff (`_implementation-verifier.md` owns this rule). The executor's own provider gets **no** second, verifier-role session in the current plumbing: `worker_prompt_policy` materializes that worker ID as the executor on every dispatch, so there is no way to ask for one — treat that as a follow-up design item, never as something to work around from the lead. Verifier dispatches remain strictly read-only.
|
|
35
|
+
- **Dispatch order (BLOCKING).** Executor and verifiers are **two** dispatches, never one batch — a batch holding both makes every verifier observe base HEAD instead of the stage diff. Dispatch the executor alone, settle it with `okstra team await`, then dispatch the verifiers with a `--workers` list that **omits `{{EXECUTOR_WORKER_ID}}`**: that worker ID is materialized as the executor on every dispatch, so a second batch still carrying it is refused again. **Enforcement:** `scripts/okstra_ctl/dispatch_core.py` `_validate_implementation_phase_order` refuses such a batch, in `--dry-run` as well as in a real dispatch.
|
|
20
36
|
{{INCLUDE:_common-contract.md}}
|
|
21
37
|
{{INCLUDE:_stage-discipline.md}}
|
|
22
38
|
- Pre-implementation gate (mandatory — refuse to start if any item fails):
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Improvement Discovery Profile
|
|
2
2
|
|
|
3
|
+
```yaml
|
|
4
|
+
roles:
|
|
5
|
+
- role: analyser
|
|
6
|
+
count: 3
|
|
7
|
+
optionalCount: 2
|
|
8
|
+
duty: discovery-worker
|
|
9
|
+
minDistinctProviders: 3
|
|
10
|
+
- role: report-writer
|
|
11
|
+
count: 1
|
|
12
|
+
duty: report-writer
|
|
13
|
+
- role: verifier
|
|
14
|
+
count: 0
|
|
15
|
+
duty: reverification-worker
|
|
16
|
+
dynamic: true
|
|
17
|
+
```
|
|
18
|
+
|
|
3
19
|
- Purpose: scan a codebase scope through a fixed lens whitelist and surface ranked improvement candidates with multi-worker consensus classification
|
|
4
20
|
- Required workers:
|
|
5
21
|
- claude
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Project Analysis Profile
|
|
2
2
|
|
|
3
|
+
```yaml
|
|
4
|
+
roles:
|
|
5
|
+
- role: analyser
|
|
6
|
+
count: 2
|
|
7
|
+
optionalCount: 3
|
|
8
|
+
duty: analysis-worker
|
|
9
|
+
minDistinctProviders: 2
|
|
10
|
+
- role: report-writer
|
|
11
|
+
count: 1
|
|
12
|
+
duty: report-writer
|
|
13
|
+
- role: verifier
|
|
14
|
+
count: 0
|
|
15
|
+
duty: reverification-worker
|
|
16
|
+
dynamic: true
|
|
17
|
+
```
|
|
18
|
+
|
|
3
19
|
- Purpose: map a bounded project area so later work can navigate components, dependencies, entry points, repositories, and external integrations without changing the source
|
|
4
20
|
- Required workers:
|
|
5
21
|
- claude
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Release Handoff Profile
|
|
2
2
|
|
|
3
|
+
```yaml
|
|
4
|
+
roles: []
|
|
5
|
+
```
|
|
6
|
+
|
|
3
7
|
- Record the handoff shape in `releaseHandoff.handoffScope`: `mode` always, plus `stages`
|
|
4
8
|
and `collectorBranch` in stage-group mode. The report is the only place a reader learns
|
|
5
9
|
which stages shipped — the collector branch name does not say.
|
|
@@ -9,7 +13,7 @@
|
|
|
9
13
|
- Lead-only contract (replaces the shared team contract for this phase):
|
|
10
14
|
- The host-native Okstra lead is the sole agent for this run. No worker dispatch, no teammates, no parallel sub-agents, no convergence loop.
|
|
11
15
|
- The lead drafts the PR title and PR body **inline** by reading the run brief, the cited final-verification report, `git log --oneline <base>..HEAD`, and `git diff <base>..HEAD --stat`. No drafter worker is dispatched.
|
|
12
|
-
- The lead authors the final-report file directly (no `Report writer worker` dispatch). The report still conforms to the standard `templates/reports/final-report.template.md` structure, including the `## 5.6 Release Handoff Deliverables` section.
|
|
16
|
+
- The lead authors the final-report file directly (no `Report writer worker` dispatch). The report still conforms to the standard `templates/reports/final-report-v2.template.md` structure, including the `## 5.6 Release Handoff Deliverables` section.
|
|
13
17
|
- The shared anti-escalation rule from the common contract still applies: do not start any other lifecycle phase from inside this run.
|
|
14
18
|
- The shared "authority & permissions assumption" rule from the common contract still applies: assume the user holds every permission needed; do not block on hypothetical approvals.
|
|
15
19
|
- The shared "MCP read-only" rule still applies if the brief lists MCP servers, though most release-handoff runs do not use MCP.
|
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Requirements Discovery Profile
|
|
2
2
|
|
|
3
|
+
```yaml
|
|
4
|
+
roles:
|
|
5
|
+
- role: analyser
|
|
6
|
+
count: 2
|
|
7
|
+
optionalCount: 3
|
|
8
|
+
duty: analysis-worker
|
|
9
|
+
minDistinctProviders: 2
|
|
10
|
+
- role: critic
|
|
11
|
+
count: 0
|
|
12
|
+
optionalCount: 1
|
|
13
|
+
duty: scope-critic
|
|
14
|
+
- role: report-writer
|
|
15
|
+
count: 1
|
|
16
|
+
duty: report-writer
|
|
17
|
+
- role: verifier
|
|
18
|
+
count: 0
|
|
19
|
+
duty: reverification-worker
|
|
20
|
+
dynamic: true
|
|
21
|
+
```
|
|
22
|
+
|
|
3
23
|
- Purpose: classify the work request, identify missing requirement evidence, and route the task to the safest next lifecycle phase before implementation starts
|
|
4
24
|
- Required workers:
|
|
5
25
|
- claude
|
|
@@ -480,6 +480,22 @@
|
|
|
480
480
|
"no": "아니오 — 단계별로 다시 입력"
|
|
481
481
|
}
|
|
482
482
|
},
|
|
483
|
+
"role_count": {
|
|
484
|
+
"label": "{role} 역할 인스턴스 수를 선택하세요 ({minimum}..{maximum}, 기본 {default})",
|
|
485
|
+
"echo_template": "role-count: {value}",
|
|
486
|
+
"options": {
|
|
487
|
+
"count": "{count}개{default_suffix}",
|
|
488
|
+
"default_suffix": " (기본)"
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
"role_model": {
|
|
492
|
+
"label": "{role} 역할 {ordinal}/{count} 인스턴스의 모델을 선택하세요",
|
|
493
|
+
"echo_template": "role-model: {value}",
|
|
494
|
+
"options": {
|
|
495
|
+
"model": "{model_ref} — {display}{default_suffix}",
|
|
496
|
+
"default_suffix": " (기본 후보)"
|
|
497
|
+
}
|
|
498
|
+
},
|
|
483
499
|
"defaults_or_custom": {
|
|
484
500
|
"label": "역할별 모델 선택 단계입니다 (참여 워커 구성을 바꾸는 게 아닙니다).\n이번 run 에서 모델을 고를 역할:\n{role_models}\n· 기본값으로 진행 — 위 추천 모델을 그대로 쓰고, directive·관련 task 없이 바로 넘어갑니다.\n· 커스터마이즈 — 위 역할별 모델을 직접 고르고, 추가 directive·관련 task 도 지정합니다.\n(추천 값은 runtime 기본값으로 해소됩니다. 분석에 참여하지 않는 역할은 위 목록에 나오지 않습니다 — 예: antigravity 는 implementation 의 executor 로 선택했을 때만 표시됩니다.)",
|
|
485
501
|
"echo_template": "customize: {value}",
|
|
@@ -587,6 +603,8 @@
|
|
|
587
603
|
},
|
|
588
604
|
"confirmation": {
|
|
589
605
|
"header": "선택 확인:",
|
|
606
|
+
"static_role": " static-role : {role}#{ordinal} / {model}",
|
|
607
|
+
"dynamic_role": " dynamic-role : {role} / reuse selected participant model",
|
|
590
608
|
"workers_implementation_default": " workers : (프로필 기본 — executor + verifier 2 + report-writer)",
|
|
591
609
|
"base_ref_stage_isolated": " base-ref : (stage 격리 — 의존 stage 기준으로 run 준비 시점에 자동 해소)",
|
|
592
610
|
"base_ref_reuse_task_dir": " base-ref : (기존 `{task_key}` 디렉터리 재사용 — 최초 base 유지)",
|
|
@@ -39,16 +39,11 @@ def default_worker_dispatch_port(
|
|
|
39
39
|
if provider_registry is not None
|
|
40
40
|
else None
|
|
41
41
|
)
|
|
42
|
-
default_backend = (
|
|
43
|
-
dispatch_core.BACKEND_TMUX_PANE
|
|
44
|
-
if descriptor.launch_mode == "team"
|
|
45
|
-
else dispatch_core.BACKEND_CLI_WRAPPER
|
|
46
|
-
)
|
|
47
42
|
return CliWrapperDispatchPort(
|
|
48
43
|
supported_worker_wrappers=wrappers,
|
|
49
44
|
unsupported_worker_label=f"{descriptor.id} lead",
|
|
50
45
|
required_lead_runtime=descriptor.id,
|
|
51
|
-
default_backend=
|
|
46
|
+
default_backend=dispatch_core.BACKEND_CLI_WRAPPER,
|
|
52
47
|
)
|
|
53
48
|
|
|
54
49
|
|
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
from collections.abc import Mapping
|
|
5
5
|
|
|
6
6
|
from ... import dispatch_core
|
|
7
|
+
from ...domain.worker_exec import WorkerWriteCapability
|
|
7
8
|
from ...ports.worker_dispatch import WorkerDispatchPlan, WorkerDispatchRequest
|
|
8
9
|
|
|
9
10
|
|
|
@@ -17,6 +18,9 @@ class CliWrapperDispatchPort:
|
|
|
17
18
|
default_backend: str = dispatch_core.BACKEND_CLI_WRAPPER,
|
|
18
19
|
cli_wrapper_assignments_only: bool = False,
|
|
19
20
|
default_provider_by_worker_id: Mapping[str, str] | None = None,
|
|
21
|
+
worker_write_capability: WorkerWriteCapability = WorkerWriteCapability(
|
|
22
|
+
"none"
|
|
23
|
+
),
|
|
20
24
|
) -> None:
|
|
21
25
|
self._supported_worker_wrappers = supported_worker_wrappers or {}
|
|
22
26
|
self._unsupported_worker_label = unsupported_worker_label
|
|
@@ -26,6 +30,7 @@ class CliWrapperDispatchPort:
|
|
|
26
30
|
self._default_provider_by_worker_id = dict(
|
|
27
31
|
default_provider_by_worker_id or {}
|
|
28
32
|
)
|
|
33
|
+
self._worker_write_capability = worker_write_capability
|
|
29
34
|
|
|
30
35
|
def build_plan(self, request: WorkerDispatchRequest) -> WorkerDispatchPlan:
|
|
31
36
|
backend_plan = None
|
|
@@ -52,3 +57,6 @@ class CliWrapperDispatchPort:
|
|
|
52
57
|
backend_plan=backend_plan,
|
|
53
58
|
dispatch_mode="render-only",
|
|
54
59
|
)
|
|
60
|
+
|
|
61
|
+
def worker_write_capability(self) -> WorkerWriteCapability:
|
|
62
|
+
return self._worker_write_capability
|
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
from collections.abc import Mapping
|
|
5
5
|
|
|
6
6
|
from ... import dispatch_core
|
|
7
|
+
from ...domain.worker_exec import WorkerWriteCapability
|
|
7
8
|
from ...ports.worker_dispatch import (
|
|
8
9
|
WorkerDispatchPlan,
|
|
9
10
|
WorkerDispatchPort,
|
|
@@ -25,6 +26,9 @@ class CmuxDispatchPort:
|
|
|
25
26
|
required_lead_runtime: str | None = None,
|
|
26
27
|
cli_wrapper_assignments_only: bool = False,
|
|
27
28
|
default_provider_by_worker_id: Mapping[str, str] | None = None,
|
|
29
|
+
worker_write_capability: WorkerWriteCapability = WorkerWriteCapability(
|
|
30
|
+
"none"
|
|
31
|
+
),
|
|
28
32
|
) -> None:
|
|
29
33
|
self._backend_port = CliWrapperDispatchPort(
|
|
30
34
|
supported_worker_wrappers=supported_worker_wrappers,
|
|
@@ -33,6 +37,7 @@ class CmuxDispatchPort:
|
|
|
33
37
|
default_backend=dispatch_core.BACKEND_CMUX_PANE,
|
|
34
38
|
cli_wrapper_assignments_only=cli_wrapper_assignments_only,
|
|
35
39
|
default_provider_by_worker_id=default_provider_by_worker_id,
|
|
40
|
+
worker_write_capability=worker_write_capability,
|
|
36
41
|
)
|
|
37
42
|
|
|
38
43
|
def build_plan(self, request: WorkerDispatchRequest) -> WorkerDispatchPlan:
|
|
@@ -46,6 +51,9 @@ class CmuxDispatchPort:
|
|
|
46
51
|
relay_contract=CMUX_RELAY_CONTRACT,
|
|
47
52
|
)
|
|
48
53
|
|
|
54
|
+
def worker_write_capability(self) -> WorkerWriteCapability:
|
|
55
|
+
return self._backend_port.worker_write_capability()
|
|
56
|
+
|
|
49
57
|
|
|
50
58
|
def dispatch_port_for_terminal_backend(
|
|
51
59
|
terminal_backend: str,
|
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
"""Native host-team dispatch planning."""
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
|
+
from ...domain.worker_exec import WorkerWriteCapability
|
|
4
5
|
from ...ports.worker_dispatch import WorkerDispatchPlan, WorkerDispatchRequest
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
class NativeTeamDispatchPort:
|
|
9
|
+
def __init__(
|
|
10
|
+
self,
|
|
11
|
+
*,
|
|
12
|
+
worker_write_capability: WorkerWriteCapability = WorkerWriteCapability(
|
|
13
|
+
"none"
|
|
14
|
+
),
|
|
15
|
+
) -> None:
|
|
16
|
+
self._worker_write_capability = worker_write_capability
|
|
17
|
+
|
|
8
18
|
def build_plan(self, request: WorkerDispatchRequest) -> WorkerDispatchPlan:
|
|
9
19
|
return WorkerDispatchPlan(
|
|
10
20
|
mode="native-team",
|
|
11
21
|
request=request,
|
|
12
22
|
dispatch_mode="team",
|
|
13
23
|
)
|
|
24
|
+
|
|
25
|
+
def worker_write_capability(self) -> WorkerWriteCapability:
|
|
26
|
+
return self._worker_write_capability
|
|
@@ -60,7 +60,7 @@ def create_adapter(
|
|
|
60
60
|
detector=no_automatic_claim,
|
|
61
61
|
provider_registry=provider_registry,
|
|
62
62
|
host_model_port=host_model_port or NativeExecutionValueHostModelBindingPort(
|
|
63
|
-
DESCRIPTOR.id,
|
|
64
|
-
DESCRIPTOR.native_provider_id,
|
|
63
|
+
host_runtime=DESCRIPTOR.id,
|
|
64
|
+
native_provider=DESCRIPTOR.native_provider_id,
|
|
65
65
|
),
|
|
66
66
|
)
|
|
@@ -15,6 +15,7 @@ from okstra_ctl.adapters.hosts.capability_adapter import (
|
|
|
15
15
|
numbered_interaction_port,
|
|
16
16
|
)
|
|
17
17
|
from okstra_ctl.domain.host import HostClaim, HostDescriptor, HostResolutionContext
|
|
18
|
+
from okstra_ctl.domain.provider import HostModelBinding
|
|
18
19
|
from okstra_ctl.ports.host_model import (
|
|
19
20
|
HostModelBindingError,
|
|
20
21
|
HostModelBindingRequest,
|
|
@@ -42,27 +43,46 @@ DESCRIPTOR = HostDescriptor(
|
|
|
42
43
|
class ClaudeFamilyHostModelBindingPort:
|
|
43
44
|
_FAMILIES = ("fable", "opus", "sonnet", "haiku")
|
|
44
45
|
|
|
45
|
-
def resolve(self, request: HostModelBindingRequest) ->
|
|
46
|
+
def resolve(self, request: HostModelBindingRequest) -> HostModelBinding:
|
|
46
47
|
if request.runner == "cli-wrapper":
|
|
47
|
-
return
|
|
48
|
+
return HostModelBinding(
|
|
49
|
+
runner=request.runner,
|
|
50
|
+
catalog_execution_value=request.model_execution_value,
|
|
51
|
+
resolved_execution_value=request.execution_value,
|
|
52
|
+
host_model_value=None,
|
|
53
|
+
binding_fidelity="exact",
|
|
54
|
+
worker_write_capability=request.worker_write_capability,
|
|
55
|
+
)
|
|
48
56
|
if (
|
|
49
57
|
request.runner != "native-session"
|
|
50
58
|
or request.host_runtime != DESCRIPTOR.id
|
|
51
59
|
or request.provider != DESCRIPTOR.native_provider_id
|
|
52
60
|
):
|
|
53
61
|
raise self._unsupported(request)
|
|
54
|
-
segments = request.
|
|
62
|
+
segments = request.execution_value.lower().split("-")
|
|
55
63
|
matches = [family for family in self._FAMILIES if family in segments]
|
|
56
64
|
if len(matches) != 1:
|
|
57
65
|
raise self._unsupported(request)
|
|
58
|
-
|
|
66
|
+
if request.version_kind == "pinned":
|
|
67
|
+
raise HostModelBindingError(
|
|
68
|
+
"exact binding unavailable: "
|
|
69
|
+
f"host={request.host_runtime!r}, model={request.model_ref!r}"
|
|
70
|
+
)
|
|
71
|
+
return HostModelBinding(
|
|
72
|
+
runner=request.runner,
|
|
73
|
+
catalog_execution_value=request.model_execution_value,
|
|
74
|
+
resolved_execution_value=request.execution_value,
|
|
75
|
+
host_model_value=matches[0],
|
|
76
|
+
binding_fidelity="channel",
|
|
77
|
+
worker_write_capability=request.worker_write_capability,
|
|
78
|
+
)
|
|
59
79
|
|
|
60
80
|
@staticmethod
|
|
61
81
|
def _unsupported(request: HostModelBindingRequest) -> HostModelBindingError:
|
|
62
82
|
return HostModelBindingError(
|
|
63
83
|
"unsupported host model: "
|
|
64
84
|
f"host={request.host_runtime!r}, provider={request.provider!r}, "
|
|
65
|
-
f"model={request.
|
|
85
|
+
f"model={request.execution_value!r}"
|
|
66
86
|
)
|
|
67
87
|
|
|
68
88
|
|
|
@@ -83,7 +83,7 @@ def create_adapter(
|
|
|
83
83
|
provider_registry=provider_registry,
|
|
84
84
|
readiness_probe=_okstra_home_write_checks,
|
|
85
85
|
host_model_port=host_model_port or NativeExecutionValueHostModelBindingPort(
|
|
86
|
-
DESCRIPTOR.id,
|
|
87
|
-
DESCRIPTOR.native_provider_id,
|
|
86
|
+
host_runtime=DESCRIPTOR.id,
|
|
87
|
+
native_provider=DESCRIPTOR.native_provider_id,
|
|
88
88
|
),
|
|
89
89
|
)
|
|
@@ -13,6 +13,7 @@ from okstra_ctl.adapters.hosts.capability_adapter import (
|
|
|
13
13
|
numbered_interaction_port,
|
|
14
14
|
)
|
|
15
15
|
from okstra_ctl.domain.host import HostClaim, HostDescriptor, HostResolutionContext
|
|
16
|
+
from okstra_ctl.ports.host_model import FailClosedHostModelBindingPort
|
|
16
17
|
from okstra_ctl.registry.provider_registry import ProviderRegistry
|
|
17
18
|
|
|
18
19
|
|
|
@@ -70,5 +71,7 @@ def create_adapter(
|
|
|
70
71
|
supported_functions=INTERACTION_FUNCTIONS,
|
|
71
72
|
detector=_detect_tmux,
|
|
72
73
|
provider_registry=provider_registry,
|
|
73
|
-
host_model_port=
|
|
74
|
+
host_model_port=(
|
|
75
|
+
host_model_port or FailClosedHostModelBindingPort(DESCRIPTOR.id)
|
|
76
|
+
),
|
|
74
77
|
)
|