okstra 0.174.0 → 0.176.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +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/{src → dist}/commands/execute/team.mjs +29 -36
- 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/{src → dist}/commands/execute/worktree-status.mjs +52 -46
- 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/{src → dist}/commands/report/finalize.mjs +25 -32
- 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 +6 -2
- package/docs/architecture.md +29 -20
- package/docs/cli.md +40 -16
- package/docs/contributor-change-matrix.md +2 -2
- package/docs/for-ai/skills/okstra-inspect.md +2 -3
- package/docs/for-ai/skills/okstra-rollup.md +1 -0
- package/docs/project-structure-overview.md +72 -62
- package/docs/task-process/README.md +12 -8
- package/docs/task-process/common-flow.md +13 -16
- package/docs/task-process/error-analysis.md +9 -10
- package/docs/task-process/final-verification.md +7 -7
- package/docs/task-process/implementation-planning.md +9 -9
- package/docs/task-process/implementation.md +6 -6
- package/docs/task-process/release-handoff.md +8 -7
- package/docs/task-process/requirements-discovery.md +8 -8
- package/package.json +11 -5
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/claude-worker.md +2 -1
- 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 +3 -0
- package/runtime/bin/lib/okstra/interactive.sh +12 -6
- package/runtime/bin/lib/okstra/usage.sh +7 -6
- package/runtime/bin/okstra-error-log.py +27 -0
- package/runtime/bin/okstra-provider-exec.py +217 -5
- package/runtime/bin/okstra-spawn-followups.py +4 -2
- package/runtime/bin/okstra.sh +10 -0
- package/runtime/prompts/launch.template.md +2 -2
- package/runtime/prompts/lead/context-loader.md +1 -2
- package/runtime/prompts/lead/convergence.md +27 -18
- package/runtime/prompts/lead/okstra-lead-contract.md +6 -5
- package/runtime/prompts/lead/plan-body-verification.md +10 -3
- package/runtime/prompts/lead/report-writer.md +15 -1
- package/runtime/prompts/lead/team-contract.md +17 -13
- package/runtime/prompts/profiles/_implementation-deliverable.md +1 -1
- package/runtime/prompts/profiles/_implementation-executor.md +0 -3
- package/runtime/prompts/profiles/_implementation-verifier.md +3 -7
- package/runtime/prompts/profiles/change-impact-analysis.md +20 -0
- package/runtime/prompts/profiles/error-analysis.md +27 -1
- package/runtime/prompts/profiles/feature-analysis.md +20 -0
- package/runtime/prompts/profiles/final-verification.md +20 -1
- package/runtime/prompts/profiles/implementation-option-selection.md +20 -0
- package/runtime/prompts/profiles/implementation-planning.md +26 -0
- package/runtime/prompts/profiles/implementation.md +19 -0
- package/runtime/prompts/profiles/improvement-discovery.md +21 -1
- package/runtime/prompts/profiles/project-analysis.md +20 -0
- package/runtime/prompts/profiles/release-handoff.md +4 -0
- package/runtime/prompts/profiles/requirements-discovery.md +27 -1
- package/runtime/prompts/wizard/prompts.ko.json +35 -0
- 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/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 +95 -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/adapters/runtime/__init__.py +1 -0
- package/runtime/python/okstra_ctl/adapters/runtime/assembly.py +27 -0
- package/runtime/python/okstra_ctl/adapters/runtime/cli_wrapper.py +49 -0
- package/runtime/python/okstra_ctl/adapters/runtime/cmux.py +74 -0
- 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/open_worker.py +29 -0
- 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/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 +1204 -155
- package/runtime/python/okstra_ctl/dispatch_state.py +696 -11
- package/runtime/python/okstra_ctl/doctor.py +14 -0
- package/runtime/python/okstra_ctl/domain/host.py +34 -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 +18 -0
- package/runtime/python/okstra_ctl/domain/worker_exec.py +34 -1
- package/runtime/python/okstra_ctl/domain/worker_role.py +13 -3
- package/runtime/python/okstra_ctl/domain/worker_runtime.py +44 -0
- 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/implementation_outcome.py +21 -5
- 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 +578 -0
- package/runtime/python/okstra_ctl/manager_sync.py +4 -1
- 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/next_phase.py +236 -0
- 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/ports/worker_runtime.py +26 -0
- package/runtime/python/okstra_ctl/recap.py +4 -1
- package/runtime/python/okstra_ctl/registry/provider_registry.py +8 -4
- package/runtime/python/okstra_ctl/render.py +124 -57
- package/runtime/python/okstra_ctl/render_final_report.py +19 -0
- package/runtime/python/okstra_ctl/report_contract.py +39 -0
- package/runtime/python/okstra_ctl/report_finalize.py +16 -0
- package/runtime/python/okstra_ctl/report_html/render.py +1 -0
- package/runtime/python/okstra_ctl/role_requirements.py +210 -0
- package/runtime/python/okstra_ctl/rollup.py +4 -1
- package/runtime/python/okstra_ctl/run.py +1210 -258
- package/runtime/python/okstra_ctl/run_index_row.py +7 -1
- package/runtime/python/okstra_ctl/stage_fix_carry.py +17 -1
- package/runtime/python/okstra_ctl/team.py +14 -18
- package/runtime/python/okstra_ctl/time_report.py +38 -4
- 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 +1449 -66
- package/runtime/python/okstra_ctl/worker_audit_ledger.py +68 -65
- package/runtime/python/okstra_ctl/worker_prompt_body.py +18 -2
- package/runtime/python/okstra_ctl/worker_prompt_contract.py +40 -9
- package/runtime/python/okstra_ctl/worker_prompt_headers.py +16 -1
- package/runtime/python/okstra_ctl/worker_request.py +7 -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/workflow.py +18 -32
- package/runtime/python/okstra_ctl/worktree.py +3 -3
- package/runtime/python/okstra_ctl/worktree_registry.py +5 -4
- package/runtime/python/okstra_ctl/write_policy.py +571 -0
- package/runtime/python/okstra_project/state.py +54 -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 +68 -5
- package/runtime/skills/okstra-inspect/facets/recap.md +2 -0
- package/runtime/skills/okstra-inspect/facets/report.md +1 -1
- package/runtime/skills/okstra-inspect/facets/status.md +15 -13
- package/runtime/skills/okstra-rollup/SKILL.md +1 -0
- package/runtime/skills/okstra-run/SKILL.md +14 -14
- package/runtime/templates/implementation-worker-preamble.md +3 -18
- package/runtime/templates/project-docs/task-index.template.md +0 -1
- 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/html/macros/forms.html +5 -4
- package/runtime/templates/reports/html/tasks/final-verification.template.html +1 -1
- package/runtime/templates/reports/html/tasks/implementation.template.html +1 -1
- package/runtime/templates/worker-prompt-preamble.md +6 -35
- package/runtime/validators/lib/fixtures.sh +49 -16
- package/runtime/validators/validate-run.py +486 -134
- package/runtime/validators/validate_session_conformance.py +25 -7
- package/src/cli-registry.mjs +0 -539
- 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/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 -1170
- 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/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
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
4
|
import argparse
|
|
5
|
+
from dataclasses import replace
|
|
5
6
|
from datetime import datetime, timezone
|
|
7
|
+
import hashlib
|
|
6
8
|
import json
|
|
7
9
|
import os
|
|
8
10
|
from pathlib import Path
|
|
@@ -21,24 +23,33 @@ from .agent_invocation import (
|
|
|
21
23
|
AgentModelAssignment,
|
|
22
24
|
PreparedAgentInvocation,
|
|
23
25
|
agent_model_assignment_from_payload,
|
|
26
|
+
compose_agent_prompt,
|
|
27
|
+
compose_unbound_run_prompt,
|
|
24
28
|
digest_duty_catalog,
|
|
29
|
+
invocation_execution_identity_from_manifest,
|
|
25
30
|
materialize_standalone_result,
|
|
26
31
|
prepare_agent_invocation,
|
|
27
32
|
publish_standalone_completion,
|
|
28
33
|
verify_standalone_completion,
|
|
29
34
|
verify_agent_invocation,
|
|
35
|
+
v2_role_assignment_authority_errors,
|
|
30
36
|
)
|
|
31
|
-
from .
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
from .convergence_store import (
|
|
38
|
+
DYNAMIC_VERIFIER_SOURCE_ROLES,
|
|
39
|
+
reserve_dynamic_verifier,
|
|
40
|
+
)
|
|
41
|
+
from .assignment_environment import load_assignment_context
|
|
42
|
+
from .assignment_resolver import AssignmentContext, resolve_dispatch_assignment
|
|
34
43
|
from .path_hints import hydrate_active_run_context
|
|
35
|
-
from .ports.host_model import HostModelBindingRequest
|
|
36
|
-
from .registry.host_registry import default_host_registry
|
|
37
|
-
from .registry.provider_registry import default_provider_registry
|
|
38
44
|
from .worker_prompt_headers import WorkerPromptHeaderError, worker_prompt_headers
|
|
45
|
+
from .worker_artifact_paths import audit_sidecar_rel
|
|
46
|
+
from .wrapper_status import status_path_for_prompt
|
|
39
47
|
from .worker_prompt_policy import resolve_prompt_plan_for_manifest
|
|
40
48
|
from .dispatch_state import (
|
|
49
|
+
BACKEND_CLI_WRAPPER,
|
|
50
|
+
BACKEND_CMUX_PANE,
|
|
41
51
|
DispatchError,
|
|
52
|
+
detect_terminal_backend,
|
|
42
53
|
link_agent_dispatch_result,
|
|
43
54
|
record_verified_agent_dispatch,
|
|
44
55
|
reject_agent_dispatch_result,
|
|
@@ -65,9 +76,14 @@ def _parser() -> argparse.ArgumentParser:
|
|
|
65
76
|
materialize.add_argument("--worker-id")
|
|
66
77
|
materialize.add_argument("--dispatch-kind")
|
|
67
78
|
materialize.add_argument("--assignment-ref")
|
|
79
|
+
materialize.add_argument("--source-role-execution-ref")
|
|
68
80
|
materialize.add_argument("--result")
|
|
69
81
|
materialize.add_argument("--audit-source")
|
|
70
82
|
materialize.add_argument("--host-runtime")
|
|
83
|
+
materialize.add_argument(
|
|
84
|
+
"--terminal-backend",
|
|
85
|
+
choices=(BACKEND_CLI_WRAPPER, BACKEND_CMUX_PANE),
|
|
86
|
+
)
|
|
71
87
|
materialize.add_argument("--provider")
|
|
72
88
|
materialize.add_argument("--model-role")
|
|
73
89
|
materialize.add_argument("--model", default="")
|
|
@@ -314,7 +330,19 @@ def _materialize_run(
|
|
|
314
330
|
raise AgentPromptCliError(
|
|
315
331
|
f"assignment reference is missing from run manifest: {args.assignment_ref}"
|
|
316
332
|
)
|
|
317
|
-
|
|
333
|
+
assignment_payload = assignments[args.assignment_ref]
|
|
334
|
+
assignment = agent_model_assignment_from_payload(assignment_payload)
|
|
335
|
+
dynamic_source = _dynamic_verifier_source(args, manifest)
|
|
336
|
+
identity = (
|
|
337
|
+
None
|
|
338
|
+
if dynamic_source is not None
|
|
339
|
+
else invocation_execution_identity_from_manifest(
|
|
340
|
+
manifest,
|
|
341
|
+
assignment=assignment,
|
|
342
|
+
assignment_ref=args.assignment_ref,
|
|
343
|
+
duty_id=args.audience,
|
|
344
|
+
)
|
|
345
|
+
)
|
|
318
346
|
duty_root = _project_manifest_path(
|
|
319
347
|
project_root,
|
|
320
348
|
contract.get("dutyRootPath"),
|
|
@@ -345,9 +373,9 @@ def _materialize_run(
|
|
|
345
373
|
manifest=manifest,
|
|
346
374
|
active_context=active_context,
|
|
347
375
|
))
|
|
348
|
-
|
|
376
|
+
request = AgentInvocationRequest(
|
|
349
377
|
invocation_id=args.invocation_id,
|
|
350
|
-
worker_id=args.worker_id,
|
|
378
|
+
worker_id=args.worker_id if identity is None else None,
|
|
351
379
|
audience=args.audience,
|
|
352
380
|
assignment_ref=args.assignment_ref,
|
|
353
381
|
purpose=None,
|
|
@@ -366,8 +394,186 @@ def _materialize_run(
|
|
|
366
394
|
prompt_path=prompt_path,
|
|
367
395
|
metadata_path=prompt_path.with_name(prompt_path.name + ".meta.json"),
|
|
368
396
|
dispatch_kind=args.dispatch_kind,
|
|
397
|
+
participant_ref=identity.participant_ref if identity is not None else None,
|
|
398
|
+
role_execution_ref=(
|
|
399
|
+
identity.role_execution_ref if identity is not None else None
|
|
400
|
+
),
|
|
401
|
+
duty_id=identity.duty_id if identity is not None else None,
|
|
402
|
+
invocation_ref=args.invocation_id if identity is not None else None,
|
|
403
|
+
attempt=1,
|
|
369
404
|
replace_undispatched=args.replace_undispatched,
|
|
370
|
-
)
|
|
405
|
+
)
|
|
406
|
+
if dynamic_source is not None:
|
|
407
|
+
request = _reserve_dynamic_verifier_request(
|
|
408
|
+
request,
|
|
409
|
+
args=args,
|
|
410
|
+
manifest=manifest,
|
|
411
|
+
manifest_path=manifest_path,
|
|
412
|
+
source_role_execution_ref=dynamic_source,
|
|
413
|
+
artifact_paths=_dynamic_verifier_artifact_paths(
|
|
414
|
+
project_root,
|
|
415
|
+
prompt_path,
|
|
416
|
+
result_path,
|
|
417
|
+
audit_source_path,
|
|
418
|
+
audit_rel,
|
|
419
|
+
active_context,
|
|
420
|
+
args.worker_id,
|
|
421
|
+
),
|
|
422
|
+
)
|
|
423
|
+
return prepare_agent_invocation(request)
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
def _reserve_dynamic_verifier_request(
|
|
427
|
+
request: AgentInvocationRequest,
|
|
428
|
+
*,
|
|
429
|
+
args: argparse.Namespace,
|
|
430
|
+
manifest: Mapping[str, Any],
|
|
431
|
+
manifest_path: Path,
|
|
432
|
+
source_role_execution_ref: str,
|
|
433
|
+
artifact_paths: tuple[Path, ...],
|
|
434
|
+
) -> AgentInvocationRequest:
|
|
435
|
+
_validate_dynamic_source_assignment(
|
|
436
|
+
manifest,
|
|
437
|
+
source_role_execution_ref,
|
|
438
|
+
request.assignment,
|
|
439
|
+
)
|
|
440
|
+
prompt_bytes = compose_unbound_run_prompt(request)
|
|
441
|
+
verifier, invocation = reserve_dynamic_verifier(
|
|
442
|
+
manifest_path,
|
|
443
|
+
source_role_execution_ref=source_role_execution_ref,
|
|
444
|
+
duty_id=args.audience,
|
|
445
|
+
round_number=_reverify_round(args.dispatch_kind),
|
|
446
|
+
task_key=_required_manifest_string(manifest, "taskKey"),
|
|
447
|
+
input_digest="sha256:" + hashlib.sha256(prompt_bytes).hexdigest(),
|
|
448
|
+
invocation_ref=args.invocation_id,
|
|
449
|
+
artifact_paths=artifact_paths,
|
|
450
|
+
)
|
|
451
|
+
bound = replace(
|
|
452
|
+
request,
|
|
453
|
+
worker_id=None,
|
|
454
|
+
participant_ref=verifier.participant_ref,
|
|
455
|
+
role_execution_ref=verifier.role_execution_ref,
|
|
456
|
+
duty_id=args.audience,
|
|
457
|
+
invocation_ref=invocation.invocation_ref,
|
|
458
|
+
)
|
|
459
|
+
if compose_agent_prompt(bound).encode("utf-8") != prompt_bytes:
|
|
460
|
+
raise AgentPromptCliError(
|
|
461
|
+
"dynamic verifier identity changed immutable prompt bytes"
|
|
462
|
+
)
|
|
463
|
+
return bound
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
def _dynamic_verifier_artifact_paths(
|
|
467
|
+
project_root: Path,
|
|
468
|
+
prompt_path: Path,
|
|
469
|
+
result_path: Path,
|
|
470
|
+
audit_source_path: Path,
|
|
471
|
+
audit_rel: str,
|
|
472
|
+
active_context: Mapping[str, Any],
|
|
473
|
+
worker_id: str,
|
|
474
|
+
) -> tuple[Path, ...]:
|
|
475
|
+
paths = {
|
|
476
|
+
result_path,
|
|
477
|
+
audit_source_path,
|
|
478
|
+
project_root / audit_sidecar_rel(audit_rel),
|
|
479
|
+
status_path_for_prompt(prompt_path),
|
|
480
|
+
prompt_path.with_suffix(prompt_path.suffix + ".log"),
|
|
481
|
+
}
|
|
482
|
+
error_logs = active_context.get("errorLogs")
|
|
483
|
+
sidecars = error_logs.get("sidecarsByWorkerId") if isinstance(error_logs, Mapping) else None
|
|
484
|
+
value = sidecars.get(worker_id) if isinstance(sidecars, Mapping) else None
|
|
485
|
+
if isinstance(value, str) and value:
|
|
486
|
+
path = Path(value)
|
|
487
|
+
paths.add(path if path.is_absolute() else project_root / path)
|
|
488
|
+
return tuple(sorted(paths, key=str))
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
def _dynamic_verifier_source(
|
|
492
|
+
args: argparse.Namespace,
|
|
493
|
+
manifest: Mapping[str, Any],
|
|
494
|
+
) -> str | None:
|
|
495
|
+
is_v2 = (
|
|
496
|
+
manifest.get("schemaVersion") == "2.0"
|
|
497
|
+
and manifest.get("executionIdentityVersion") == 2
|
|
498
|
+
)
|
|
499
|
+
is_reverify = (
|
|
500
|
+
args.assignment_ref.startswith("reverify/")
|
|
501
|
+
and args.audience == "reverification-worker"
|
|
502
|
+
)
|
|
503
|
+
source = args.source_role_execution_ref
|
|
504
|
+
if is_v2 and is_reverify:
|
|
505
|
+
if args.replace_undispatched:
|
|
506
|
+
raise AgentPromptCliError(
|
|
507
|
+
"v2 dynamic verifier prompts are append-only; use a fresh "
|
|
508
|
+
"invocation ID and prompt path"
|
|
509
|
+
)
|
|
510
|
+
if not source:
|
|
511
|
+
raise AgentPromptCliError(
|
|
512
|
+
"v2 reverify materialization requires "
|
|
513
|
+
"--source-role-execution-ref"
|
|
514
|
+
)
|
|
515
|
+
return source
|
|
516
|
+
if source:
|
|
517
|
+
raise AgentPromptCliError(
|
|
518
|
+
"--source-role-execution-ref is allowed only for v2 reverify"
|
|
519
|
+
)
|
|
520
|
+
return None
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
def _reverify_round(dispatch_kind: str) -> int:
|
|
524
|
+
prefix = "reverify-r"
|
|
525
|
+
value = dispatch_kind.removeprefix(prefix)
|
|
526
|
+
if not dispatch_kind.startswith(prefix) or not value.isdigit() or int(value) < 1:
|
|
527
|
+
raise AgentPromptCliError(
|
|
528
|
+
"dynamic verifier dispatch kind must be reverify-r<N>"
|
|
529
|
+
)
|
|
530
|
+
return int(value)
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
def _validate_dynamic_source_assignment(
|
|
534
|
+
manifest: Mapping[str, Any],
|
|
535
|
+
source_role_execution_ref: str,
|
|
536
|
+
assignment: AgentModelAssignment,
|
|
537
|
+
) -> None:
|
|
538
|
+
rows = manifest.get("roleExecutions")
|
|
539
|
+
source = next(
|
|
540
|
+
(
|
|
541
|
+
row
|
|
542
|
+
for row in rows
|
|
543
|
+
if isinstance(row, Mapping)
|
|
544
|
+
and row.get("roleExecutionRef") == source_role_execution_ref
|
|
545
|
+
),
|
|
546
|
+
None,
|
|
547
|
+
) if isinstance(rows, list) else None
|
|
548
|
+
if source is None:
|
|
549
|
+
raise AgentPromptCliError(
|
|
550
|
+
f"source role execution is unknown: {source_role_execution_ref}"
|
|
551
|
+
)
|
|
552
|
+
if source.get("role") not in DYNAMIC_VERIFIER_SOURCE_ROLES:
|
|
553
|
+
raise AgentPromptCliError(
|
|
554
|
+
"dynamic verifier source role is not eligible for re-verification"
|
|
555
|
+
)
|
|
556
|
+
errors = v2_role_assignment_authority_errors(
|
|
557
|
+
manifest,
|
|
558
|
+
role_execution_ref=source_role_execution_ref,
|
|
559
|
+
participant_ref=str(source.get("participantRef") or ""),
|
|
560
|
+
assignment=assignment,
|
|
561
|
+
)
|
|
562
|
+
if errors:
|
|
563
|
+
raise AgentPromptCliError(
|
|
564
|
+
"dynamic verifier source does not match the selected assignment: "
|
|
565
|
+
+ "; ".join(errors)
|
|
566
|
+
)
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
def _required_manifest_string(
|
|
570
|
+
manifest: Mapping[str, Any],
|
|
571
|
+
key: str,
|
|
572
|
+
) -> str:
|
|
573
|
+
value = manifest.get(key)
|
|
574
|
+
if not isinstance(value, str) or not value.strip():
|
|
575
|
+
raise AgentPromptCliError(f"run manifest has no {key}")
|
|
576
|
+
return value
|
|
371
577
|
|
|
372
578
|
|
|
373
579
|
def _validate_run_identity(
|
|
@@ -437,6 +643,7 @@ def _materialize_standalone(
|
|
|
437
643
|
"assignment-ref": args.assignment_ref,
|
|
438
644
|
"result": args.result,
|
|
439
645
|
"audit-source": args.audit_source,
|
|
646
|
+
"source-role-execution-ref": args.source_role_execution_ref,
|
|
440
647
|
}
|
|
441
648
|
present = [name for name, value in forbidden.items() if value]
|
|
442
649
|
if present:
|
|
@@ -459,8 +666,14 @@ def _materialize_standalone(
|
|
|
459
666
|
expected_prompt = root / f"{args.invocation_id}.prompt.md"
|
|
460
667
|
instruction_path = _exact_path(args.instruction, expected_instruction, True, "instruction")
|
|
461
668
|
prompt_path = _exact_path(args.prompt, expected_prompt, False, "prompt")
|
|
462
|
-
|
|
669
|
+
assignment_context = load_assignment_context(
|
|
463
670
|
host_runtime=args.host_runtime,
|
|
671
|
+
terminal_backend=args.terminal_backend or detect_terminal_backend(),
|
|
672
|
+
execution_provider_ids=(args.provider,),
|
|
673
|
+
include_native_provider=False,
|
|
674
|
+
)
|
|
675
|
+
assignment = _standalone_assignment(
|
|
676
|
+
context=assignment_context,
|
|
464
677
|
provider=args.provider,
|
|
465
678
|
model_role=args.model_role,
|
|
466
679
|
model=args.model,
|
|
@@ -488,54 +701,40 @@ def _materialize_standalone(
|
|
|
488
701
|
prompt_path=prompt_path,
|
|
489
702
|
metadata_path=prompt_path.with_name(prompt_path.name + ".meta.json"),
|
|
490
703
|
dispatch_kind="standalone",
|
|
704
|
+
participant_ref=None,
|
|
705
|
+
role_execution_ref=None,
|
|
706
|
+
duty_id=None,
|
|
707
|
+
invocation_ref=None,
|
|
708
|
+
attempt=1,
|
|
491
709
|
))
|
|
492
710
|
|
|
493
711
|
|
|
494
712
|
def _standalone_assignment(
|
|
495
|
-
*,
|
|
713
|
+
*,
|
|
714
|
+
context: AssignmentContext,
|
|
715
|
+
provider: str,
|
|
716
|
+
model_role: str,
|
|
717
|
+
model: str,
|
|
496
718
|
) -> AgentModelAssignment:
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
if not default_model:
|
|
501
|
-
raise AgentPromptCliError(
|
|
502
|
-
f"provider {provider!r} has no default model for role {model_role!r}"
|
|
503
|
-
)
|
|
504
|
-
metadata = resolve_model_metadata(
|
|
505
|
-
provider=provider,
|
|
506
|
-
raw_value=model,
|
|
507
|
-
default_display=default_model,
|
|
508
|
-
default_execution=default_model,
|
|
509
|
-
)
|
|
510
|
-
host_adapter = default_host_registry(provider_registry).resolve(host_runtime)
|
|
511
|
-
runner = resolve_assignment_runner(
|
|
512
|
-
host=host_adapter.descriptor,
|
|
513
|
-
provider=provider_spec,
|
|
514
|
-
role=model_role,
|
|
515
|
-
).runner
|
|
516
|
-
execution = (
|
|
517
|
-
normalize_execution_for_dispatch(
|
|
518
|
-
provider=provider,
|
|
519
|
-
execution=metadata.execution,
|
|
520
|
-
role=model_role,
|
|
521
|
-
)
|
|
522
|
-
if runner == "cli-wrapper"
|
|
523
|
-
else metadata.execution
|
|
524
|
-
)
|
|
525
|
-
host_model = host_adapter.host_model().resolve(HostModelBindingRequest(
|
|
719
|
+
host_runtime = context.environment.host_descriptor.id
|
|
720
|
+
resolved = resolve_dispatch_assignment(
|
|
721
|
+
context=context,
|
|
526
722
|
host_runtime=host_runtime,
|
|
723
|
+
role=model_role,
|
|
724
|
+
duty_id=model_role,
|
|
527
725
|
provider=provider,
|
|
528
|
-
model=
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
726
|
+
model=model,
|
|
727
|
+
)
|
|
728
|
+
binding = resolved.binding
|
|
729
|
+
if binding is None:
|
|
730
|
+
raise AgentPromptCliError("standalone assignment requires a model binding")
|
|
532
731
|
return AgentModelAssignment(
|
|
533
|
-
provider=
|
|
534
|
-
model=
|
|
535
|
-
model_execution_value=
|
|
536
|
-
runner=runner,
|
|
732
|
+
provider=resolved.provider_id,
|
|
733
|
+
model=resolved.display_name,
|
|
734
|
+
model_execution_value=binding.resolved_execution_value,
|
|
735
|
+
runner=binding.runner,
|
|
537
736
|
host_runtime=host_runtime,
|
|
538
|
-
host_model_value=
|
|
737
|
+
host_model_value=binding.host_model_value,
|
|
539
738
|
)
|
|
540
739
|
|
|
541
740
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Choose an execution surface from an injected port chain."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from collections.abc import Callable, Sequence
|
|
5
|
+
|
|
6
|
+
from ..domain.worker_runtime import (
|
|
7
|
+
EnvironmentBlocked,
|
|
8
|
+
RuntimeHandle,
|
|
9
|
+
SurfaceUnavailable,
|
|
10
|
+
WorkerSpawnRequest,
|
|
11
|
+
)
|
|
12
|
+
from ..ports.worker_runtime import WorkerRuntimePort
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def open_worker(
|
|
16
|
+
chain: Sequence[WorkerRuntimePort],
|
|
17
|
+
request_for: Callable[[str], WorkerSpawnRequest],
|
|
18
|
+
) -> RuntimeHandle:
|
|
19
|
+
last_unavailable: SurfaceUnavailable | None = None
|
|
20
|
+
for port in chain:
|
|
21
|
+
try:
|
|
22
|
+
return port.spawn(request_for(port.surface))
|
|
23
|
+
except EnvironmentBlocked:
|
|
24
|
+
raise
|
|
25
|
+
except SurfaceUnavailable as exc:
|
|
26
|
+
last_unavailable = exc
|
|
27
|
+
if last_unavailable is None:
|
|
28
|
+
raise SurfaceUnavailable("runtime chain is empty")
|
|
29
|
+
raise last_unavailable
|
|
@@ -25,7 +25,7 @@ def resolve_assignment_runner(
|
|
|
25
25
|
role: str,
|
|
26
26
|
requested_runner: str = "",
|
|
27
27
|
) -> RunnerResolution:
|
|
28
|
-
if
|
|
28
|
+
if not provider.supports_role(role):
|
|
29
29
|
raise ProviderUnavailable(
|
|
30
30
|
f"provider {provider.provider!r} does not support role {role!r}"
|
|
31
31
|
)
|
|
@@ -66,20 +66,33 @@ def resolve_lead_provider(
|
|
|
66
66
|
provider_registry,
|
|
67
67
|
) -> LeadProviderAssignment:
|
|
68
68
|
host = host_registry.resolve(host_id).descriptor
|
|
69
|
+
provider_id = resolve_lead_provider_id(
|
|
70
|
+
host=host,
|
|
71
|
+
requested_provider=requested_provider,
|
|
72
|
+
)
|
|
73
|
+
provider = provider_registry.resolve(provider_id)
|
|
74
|
+
return resolve_lead_provider_from_specs(
|
|
75
|
+
host=host,
|
|
76
|
+
requested_provider=requested_provider,
|
|
77
|
+
provider=provider,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def resolve_lead_provider_from_specs(
|
|
82
|
+
*,
|
|
83
|
+
host: HostDescriptor,
|
|
84
|
+
requested_provider: str,
|
|
85
|
+
provider: ProviderSpec,
|
|
86
|
+
) -> LeadProviderAssignment:
|
|
87
|
+
"""Resolve a lead from already loaded host and provider facts."""
|
|
69
88
|
requested = (requested_provider or "").strip().lower()
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
"provider with lead capability"
|
|
74
|
-
)
|
|
75
|
-
if host.native_provider_id and requested not in {"", host.native_provider_id}:
|
|
89
|
+
_validate_lead_provider_request(host, requested)
|
|
90
|
+
provider_id = requested or host.native_provider_id
|
|
91
|
+
if provider.provider != provider_id:
|
|
76
92
|
raise HostCapabilityMismatch(
|
|
77
|
-
f"{
|
|
78
|
-
f"{
|
|
79
|
-
f"{requested!r} must be selected as a worker instead"
|
|
93
|
+
f"provider fact {provider.provider!r} does not match requested "
|
|
94
|
+
f"lead provider {provider_id!r}"
|
|
80
95
|
)
|
|
81
|
-
provider_id = requested or host.native_provider_id
|
|
82
|
-
provider = provider_registry.resolve(provider_id)
|
|
83
96
|
resolution = resolve_assignment_runner(
|
|
84
97
|
host=host,
|
|
85
98
|
provider=provider,
|
|
@@ -91,3 +104,31 @@ def resolve_lead_provider(
|
|
|
91
104
|
wrapper=resolution.wrapper,
|
|
92
105
|
reason=resolution.reason,
|
|
93
106
|
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def resolve_lead_provider_id(
|
|
110
|
+
*,
|
|
111
|
+
host: HostDescriptor,
|
|
112
|
+
requested_provider: str,
|
|
113
|
+
) -> str:
|
|
114
|
+
"""Validate lead-provider selection and return its canonical id."""
|
|
115
|
+
requested = (requested_provider or "").strip().lower()
|
|
116
|
+
_validate_lead_provider_request(host, requested)
|
|
117
|
+
return requested or host.native_provider_id
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _validate_lead_provider_request(
|
|
121
|
+
host: HostDescriptor,
|
|
122
|
+
requested: str,
|
|
123
|
+
) -> None:
|
|
124
|
+
if not requested and not host.native_provider_id:
|
|
125
|
+
raise HostCapabilityMismatch(
|
|
126
|
+
f"host {host.id!r} has no native lead provider; select an explicit "
|
|
127
|
+
"provider with lead capability"
|
|
128
|
+
)
|
|
129
|
+
if host.native_provider_id and requested not in {"", host.native_provider_id}:
|
|
130
|
+
raise HostCapabilityMismatch(
|
|
131
|
+
f"{host.agent_label.removesuffix(' CLI')} host requires provider "
|
|
132
|
+
f"{host.native_provider_id!r} for the in-session lead; provider "
|
|
133
|
+
f"{requested!r} must be selected as a worker instead"
|
|
134
|
+
)
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""Load ambient adapter facts once, outside deterministic assignment logic."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from collections.abc import Iterable
|
|
5
|
+
|
|
6
|
+
from .assignment_resolver import (
|
|
7
|
+
AssignmentContext,
|
|
8
|
+
AssignmentEnvironment,
|
|
9
|
+
TerminalBackend,
|
|
10
|
+
)
|
|
11
|
+
from .domain.provider import ExecutionNormalization, UnknownProviderError
|
|
12
|
+
from .domain.role import ROLE_DEFINITIONS
|
|
13
|
+
from .domain.worker_exec import WorkerWriteCapability
|
|
14
|
+
from .model_pool import ModelPool
|
|
15
|
+
from .registry.host_registry import default_host_registry
|
|
16
|
+
from .registry.provider_registry import default_provider_registry
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def load_assignment_context(
|
|
20
|
+
*,
|
|
21
|
+
host_runtime: str,
|
|
22
|
+
terminal_backend: TerminalBackend,
|
|
23
|
+
execution_provider_ids: Iterable[str] | None = None,
|
|
24
|
+
include_native_provider: bool = True,
|
|
25
|
+
) -> AssignmentContext:
|
|
26
|
+
"""Snapshot provider, host, terminal, and execution inputs for one caller."""
|
|
27
|
+
provider_registry = default_provider_registry()
|
|
28
|
+
pool = ModelPool.from_registry(provider_registry)
|
|
29
|
+
adapter = default_host_registry(provider_registry).resolve(host_runtime)
|
|
30
|
+
worker_port = adapter.worker_dispatch()
|
|
31
|
+
capability_reader = getattr(worker_port, "worker_write_capability", None)
|
|
32
|
+
native_capability = (
|
|
33
|
+
capability_reader()
|
|
34
|
+
if callable(capability_reader)
|
|
35
|
+
else WorkerWriteCapability("none")
|
|
36
|
+
)
|
|
37
|
+
roles = tuple(row.id for row in ROLE_DEFINITIONS)
|
|
38
|
+
if execution_provider_ids is None:
|
|
39
|
+
provider_ids = provider_registry.ids()
|
|
40
|
+
else:
|
|
41
|
+
requested = [
|
|
42
|
+
provider.strip().lower() for provider in execution_provider_ids
|
|
43
|
+
]
|
|
44
|
+
if include_native_provider:
|
|
45
|
+
requested.insert(0, adapter.descriptor.native_provider_id)
|
|
46
|
+
requested_ids = dict.fromkeys(requested)
|
|
47
|
+
selected_ids = []
|
|
48
|
+
for provider_id in requested_ids:
|
|
49
|
+
if not provider_id:
|
|
50
|
+
continue
|
|
51
|
+
try:
|
|
52
|
+
provider_registry.resolve(provider_id)
|
|
53
|
+
except UnknownProviderError:
|
|
54
|
+
continue
|
|
55
|
+
selected_ids.append(provider_id)
|
|
56
|
+
provider_ids = tuple(selected_ids)
|
|
57
|
+
execution_resolutions = {}
|
|
58
|
+
for provider_id in provider_ids:
|
|
59
|
+
provider = provider_registry.resolve(provider_id)
|
|
60
|
+
models_by_id = {
|
|
61
|
+
model.model_id: model for model in provider.models.values()
|
|
62
|
+
}
|
|
63
|
+
models = tuple(models_by_id.values())
|
|
64
|
+
normalizer = provider.execution_normalizer
|
|
65
|
+
if normalizer is None:
|
|
66
|
+
rows = {
|
|
67
|
+
(model.model_id, role): ExecutionNormalization(
|
|
68
|
+
model.execution_value
|
|
69
|
+
)
|
|
70
|
+
for model in models
|
|
71
|
+
for role in roles
|
|
72
|
+
}
|
|
73
|
+
else:
|
|
74
|
+
try:
|
|
75
|
+
rows = normalizer.snapshot(models, roles)
|
|
76
|
+
except Exception as exc:
|
|
77
|
+
rows = {
|
|
78
|
+
(model.model_id, role): ExecutionNormalization(None, str(exc))
|
|
79
|
+
for model in models
|
|
80
|
+
for role in roles
|
|
81
|
+
}
|
|
82
|
+
for model in models:
|
|
83
|
+
for role in roles:
|
|
84
|
+
key = (model.model_id, role)
|
|
85
|
+
outcome = rows.get(key)
|
|
86
|
+
if outcome is None:
|
|
87
|
+
outcome = ExecutionNormalization(
|
|
88
|
+
None,
|
|
89
|
+
f"provider {provider_id!r} did not snapshot model "
|
|
90
|
+
f"{model.model_id!r} for role {role!r}",
|
|
91
|
+
)
|
|
92
|
+
execution_resolutions[(f"{provider_id}/{model.model_id}", role)] = (
|
|
93
|
+
outcome
|
|
94
|
+
)
|
|
95
|
+
environment = AssignmentEnvironment(
|
|
96
|
+
host_descriptor=adapter.descriptor,
|
|
97
|
+
host_model_port=adapter.host_model(),
|
|
98
|
+
native_worker_write_capability=native_capability,
|
|
99
|
+
terminal_backend=terminal_backend,
|
|
100
|
+
execution_resolutions=execution_resolutions,
|
|
101
|
+
)
|
|
102
|
+
return AssignmentContext(pool=pool, environment=environment)
|