okstra 0.186.7 → 0.187.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 +1 -1
- package/dist/cli-registry.d.mts +88 -1
- package/dist/cli-registry.mjs +68 -111
- package/dist/cli-registry.mjs.map +1 -1
- package/dist/commands/execute/render-bundle.mjs +0 -1
- package/dist/commands/execute/render-bundle.mjs.map +1 -1
- package/dist/commands/execute/run.mjs +8 -3
- package/dist/commands/execute/run.mjs.map +1 -1
- package/dist/commands/lifecycle/check-project.mjs +1 -14
- package/dist/commands/lifecycle/check-project.mjs.map +1 -1
- package/dist/commands/lifecycle/config.mjs +38 -40
- package/dist/commands/lifecycle/config.mjs.map +1 -1
- package/dist/commands/lifecycle/doctor.d.mts +22 -7
- package/dist/commands/lifecycle/doctor.mjs +77 -49
- package/dist/commands/lifecycle/doctor.mjs.map +1 -1
- package/dist/commands/lifecycle/install.d.mts +12 -10
- package/dist/commands/lifecycle/install.mjs +104 -39
- package/dist/commands/lifecycle/install.mjs.map +1 -1
- package/dist/commands/lifecycle/paths.mjs +8 -3
- package/dist/commands/lifecycle/paths.mjs.map +1 -1
- package/dist/commands/lifecycle/preflight.mjs +2 -1
- package/dist/commands/lifecycle/preflight.mjs.map +1 -1
- package/dist/commands/lifecycle/setup.mjs +22 -36
- package/dist/commands/lifecycle/setup.mjs.map +1 -1
- package/dist/commands/lifecycle/uninstall.d.mts +4 -2
- package/dist/commands/lifecycle/uninstall.mjs +59 -15
- package/dist/commands/lifecycle/uninstall.mjs.map +1 -1
- package/dist/commands/memory/memory.mjs +7 -1
- package/dist/commands/memory/memory.mjs.map +1 -1
- package/dist/lib/helper-scripts.d.mts +1 -1
- package/dist/lib/helper-scripts.mjs +10 -18
- package/dist/lib/helper-scripts.mjs.map +1 -1
- package/dist/lib/host-config.d.mts +72 -0
- package/dist/lib/host-config.mjs +404 -0
- package/dist/lib/host-config.mjs.map +1 -0
- package/dist/lib/host-registry-client.d.mts +2 -2
- package/dist/lib/host-registry-client.mjs +0 -3
- package/dist/lib/host-registry-client.mjs.map +1 -1
- package/dist/lib/install-assets.d.mts +1 -0
- package/dist/lib/install-assets.mjs +4 -0
- package/dist/lib/install-assets.mjs.map +1 -1
- package/dist/lib/proc.d.mts +2 -0
- package/dist/lib/proc.mjs +12 -0
- package/dist/lib/proc.mjs.map +1 -1
- package/dist/lib/python-command.d.mts +2 -0
- package/dist/lib/python-command.mjs +52 -0
- package/dist/lib/python-command.mjs.map +1 -0
- package/dist/lib/python-helper.d.mts +2 -5
- package/dist/lib/python-helper.mjs +3 -52
- package/dist/lib/python-helper.mjs.map +1 -1
- package/dist/lib/runtime-payload.d.mts +23 -0
- package/dist/lib/runtime-payload.mjs +57 -0
- package/dist/lib/runtime-payload.mjs.map +1 -0
- package/dist/lib/types.d.mts +24 -13
- package/docs/architecture/storage-model.md +21 -5
- package/docs/architecture.md +37 -36
- package/docs/cli.md +55 -76
- package/docs/coding-rules.md +295 -0
- package/docs/container.md +10 -36
- package/docs/contributor-change-matrix.md +1 -1
- package/docs/for-ai/skills/okstra-code-review.md +0 -1
- package/docs/for-ai/skills/okstra-container-build.md +8 -41
- package/docs/for-ai/skills/okstra-inspect.md +4 -4
- package/docs/for-ai/skills/okstra-manager.md +2 -2
- package/docs/for-ai/skills/okstra-rollup.md +0 -1
- package/docs/for-ai/skills/okstra-run.md +3 -3
- package/docs/for-ai/skills/okstra-user-response.md +0 -1
- package/docs/performance-improvement-plan-v2.md +1 -1
- package/docs/project-structure-overview.md +62 -62
- package/docs/task-process/README.md +3 -3
- package/docs/task-process/common-flow.md +1 -1
- package/docs/task-process/error-analysis.md +3 -3
- package/docs/task-process/implementation-planning.md +3 -1
- package/docs/task-process/release-handoff.md +1 -1
- package/package.json +3 -2
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/claude-worker.md +6 -11
- package/runtime/agents/workers/report-writer-worker.md +1 -1
- package/runtime/bin/lib/okstra/cli.sh +4 -0
- package/runtime/bin/lib/okstra/globals.sh +2 -0
- package/runtime/bin/lib/okstra/interactive.sh +26 -173
- package/runtime/bin/lib/okstra/project-resolver.sh +23 -61
- package/runtime/bin/lib/okstra/usage.sh +3 -3
- package/runtime/bin/okstra-compact-reminder.sh +1 -5
- package/runtime/bin/okstra-error-log.py +19 -2
- package/runtime/bin/okstra-import-check.py +26 -0
- package/runtime/bin/okstra-inject-report-index.py +5 -4
- package/runtime/bin/okstra-provider-exec.py +22 -17
- package/runtime/bin/okstra-render-final-report.py +16 -6
- package/runtime/bin/okstra-render-report-views.py +25 -18
- package/runtime/bin/okstra-report-translate.py +30 -18
- package/runtime/bin/okstra-spawn-followups.py +4 -0
- package/runtime/bin/okstra-token-usage.py +3 -0
- package/runtime/bin/okstra.sh +4 -2
- package/runtime/bin/okstra_bootstrap.py +58 -0
- package/runtime/prompts/coding-preflight/overview.md +1 -1
- package/runtime/prompts/duties/planning-worker.md +1 -1
- package/runtime/prompts/launch.template.md +35 -9
- package/runtime/prompts/lead/convergence.md +96 -87
- package/runtime/prompts/lead/okstra-lead-contract.md +63 -12
- package/runtime/prompts/lead/plan-body-verification.md +65 -46
- package/runtime/prompts/lead/report-writer.md +34 -4
- package/runtime/prompts/lead/team-contract.md +4 -1
- package/runtime/prompts/profiles/_clarification-recommendation.md +2 -1
- package/runtime/prompts/profiles/_coding-conventions-preflight.md +1 -1
- package/runtime/prompts/profiles/_common-contract.md +3 -3
- package/runtime/prompts/profiles/_coverage-critic.md +1 -1
- package/runtime/prompts/profiles/_implementation-deliverable.md +2 -2
- package/runtime/prompts/profiles/_implementation-executor.md +3 -1
- package/runtime/prompts/profiles/_implementation-verifier.md +16 -2
- package/runtime/prompts/profiles/error-analysis.md +4 -3
- package/runtime/prompts/profiles/final-verification.md +2 -2
- package/runtime/prompts/profiles/implementation-planning.md +22 -17
- package/runtime/prompts/profiles/implementation.md +3 -2
- package/runtime/prompts/profiles/requirements-discovery.md +2 -1
- package/runtime/prompts/wizard/prompts.ko.json +29 -8
- package/runtime/python/okstra_ctl/__init__.py +6 -27
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +4 -5
- package/runtime/python/okstra_ctl/adapters/hosts/codex/adapter.py +21 -2
- package/runtime/python/okstra_ctl/adapters/hosts/external/adapter.py +3 -12
- package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +40 -22
- package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +14 -21
- package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +37 -20
- package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +86 -14
- package/runtime/python/okstra_ctl/adapters/providers/kimi/adapter.py +12 -12
- package/runtime/python/okstra_ctl/adapters/runtime/cmux.py +4 -7
- package/runtime/python/okstra_ctl/agent/__init__.py +1 -0
- package/runtime/python/okstra_ctl/{agent_activity.py → agent/activity.py} +12 -1
- package/runtime/python/okstra_ctl/{agent_invocation.py → agent/invocation.py} +34 -5
- package/runtime/python/okstra_ctl/agent/prompt_cli/__init__.py +19 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/__main__.py +11 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/cli.py +215 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/dynamic_verifier.py +155 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/emit.py +66 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/inputs.py +138 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/materialize.py +408 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/results.py +197 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/run_identity.py +107 -0
- package/runtime/python/okstra_ctl/analysis_packet.py +47 -4
- package/runtime/python/okstra_ctl/approval_decisions.py +260 -8
- package/runtime/python/okstra_ctl/assignment_resolver.py +0 -12
- package/runtime/python/okstra_ctl/attempt_evidence.py +12 -24
- package/runtime/python/okstra_ctl/blocking_checks.py +251 -0
- package/runtime/python/okstra_ctl/brief_frontmatter.py +0 -7
- package/runtime/python/okstra_ctl/clarification_items/__init__.py +102 -0
- package/runtime/python/okstra_ctl/clarification_items/carry.py +224 -0
- package/runtime/python/okstra_ctl/clarification_items/dispositions.py +135 -0
- package/runtime/python/okstra_ctl/clarification_items/parsing.py +253 -0
- package/runtime/python/okstra_ctl/clarification_items/rows.py +115 -0
- package/runtime/python/okstra_ctl/clarification_items/scan.py +215 -0
- package/runtime/python/okstra_ctl/clarification_items/sidecars.py +211 -0
- package/runtime/python/okstra_ctl/cmux.py +38 -31
- package/runtime/python/okstra_ctl/code_review_target.py +163 -1
- package/runtime/python/okstra_ctl/conformance.py +23 -0
- package/runtime/python/okstra_ctl/container.py +38 -421
- package/runtime/python/okstra_ctl/context_cost.py +16 -2
- package/runtime/python/okstra_ctl/contract_graph_cli.py +7 -0
- package/runtime/python/okstra_ctl/convergence.py +101 -15
- package/runtime/python/okstra_ctl/convergence_critic_prompt.py +345 -0
- package/runtime/python/okstra_ctl/convergence_engine.py +382 -70
- package/runtime/python/okstra_ctl/convergence_store.py +5 -29
- package/runtime/python/okstra_ctl/design_prep.py +108 -12
- package/runtime/python/okstra_ctl/design_snapshot.py +11 -1
- package/runtime/python/okstra_ctl/design_surfaces.py +29 -2
- package/runtime/python/okstra_ctl/dispatch_core.py +102 -25
- package/runtime/python/okstra_ctl/dispatch_state.py +268 -39
- package/runtime/python/okstra_ctl/doctor_cli.py +48 -0
- package/runtime/python/okstra_ctl/domain/worker_exec.py +10 -5
- package/runtime/python/okstra_ctl/domain/worker_presentation.py +21 -1
- package/runtime/python/okstra_ctl/domain/worker_stream.py +52 -21
- package/runtime/python/okstra_ctl/domain/write_policy.py +219 -0
- package/runtime/python/okstra_ctl/entrypoints/hosts.py +9 -2
- package/runtime/python/okstra_ctl/error_log_core.py +1 -1
- package/runtime/python/okstra_ctl/error_report.py +14 -0
- package/runtime/python/okstra_ctl/error_zip.py +18 -2
- package/runtime/python/okstra_ctl/execution_identity.py +100 -7
- package/runtime/python/okstra_ctl/execution_manifest.py +67 -20
- package/runtime/python/okstra_ctl/execution_mutation_audit.py +90 -8
- package/runtime/python/okstra_ctl/final_report_paths.py +17 -0
- package/runtime/python/okstra_ctl/final_report_schema.py +90 -16
- package/runtime/python/okstra_ctl/git_reconcile.py +22 -2
- package/runtime/python/okstra_ctl/handoff.py +24 -1
- package/runtime/python/okstra_ctl/ids.py +6 -16
- package/runtime/python/okstra_ctl/implementation_direction.py +142 -33
- package/runtime/python/okstra_ctl/implementation_options.py +25 -11
- package/runtime/python/okstra_ctl/implementation_outcome.py +5 -2
- package/runtime/python/okstra_ctl/improvement_lenses.py +0 -14
- package/runtime/python/okstra_ctl/incremental_carry.py +69 -8
- package/runtime/python/okstra_ctl/incremental_scope.py +173 -12
- package/runtime/python/okstra_ctl/index.py +2 -2
- package/runtime/python/okstra_ctl/initial_prompt_materialization.py +48 -8
- package/runtime/python/okstra_ctl/interactive_cli.py +223 -0
- package/runtime/python/okstra_ctl/json_boundary.py +10 -0
- package/runtime/python/okstra_ctl/listing.py +0 -91
- package/runtime/python/okstra_ctl/locks.py +5 -19
- package/runtime/python/okstra_ctl/log_report.py +14 -0
- package/runtime/python/okstra_ctl/manager_cli.py +22 -3
- package/runtime/python/okstra_ctl/manager_launch.py +4 -8
- package/runtime/python/okstra_ctl/material.py +2 -2
- package/runtime/python/okstra_ctl/migrate.py +23 -1
- package/runtime/python/okstra_ctl/model_cli.py +19 -5
- package/runtime/python/okstra_ctl/model_discovery.py +46 -47
- package/runtime/python/okstra_ctl/model_io/__init__.py +1 -0
- package/runtime/python/okstra_ctl/model_io/lines.py +163 -0
- package/runtime/python/okstra_ctl/model_io/references.py +370 -0
- package/runtime/python/okstra_ctl/model_io/renderers.py +498 -0
- package/runtime/python/okstra_ctl/model_io_cli.py +30 -945
- package/runtime/python/okstra_ctl/model_pool.py +10 -6
- package/runtime/python/okstra_ctl/models.py +8 -8
- package/runtime/python/okstra_ctl/mutation_recovery.py +5 -63
- package/runtime/python/okstra_ctl/next_phase.py +121 -69
- package/runtime/python/okstra_ctl/pane_reclaim.py +23 -0
- package/runtime/python/okstra_ctl/pane_title.py +11 -8
- package/runtime/python/okstra_ctl/path_hints.py +36 -11
- package/runtime/python/okstra_ctl/paths.py +76 -8
- package/runtime/python/okstra_ctl/plan_items.py +132 -16
- package/runtime/python/okstra_ctl/plan_items_cli.py +486 -36
- package/runtime/python/okstra_ctl/plan_run_root.py +1 -1
- package/runtime/python/okstra_ctl/plan_validate_cli.py +51 -0
- package/runtime/python/okstra_ctl/plan_verify_cli.py +80 -0
- package/runtime/python/okstra_ctl/prepare_error.py +20 -0
- package/runtime/python/okstra_ctl/prior_planning.py +157 -0
- package/runtime/python/okstra_ctl/profile_show.py +18 -1
- package/runtime/python/okstra_ctl/project_setup_cli.py +140 -0
- package/runtime/python/okstra_ctl/recap.py +22 -1
- package/runtime/python/okstra_ctl/reconcile.py +84 -0
- package/runtime/python/okstra_ctl/registry/host_registry.py +18 -1
- package/runtime/python/okstra_ctl/render.py +98 -32
- package/runtime/python/okstra_ctl/render_final_report.py +3 -7
- package/runtime/python/okstra_ctl/report_assembly.py +297 -7
- package/runtime/python/okstra_ctl/report_contract.py +30 -7
- package/runtime/python/okstra_ctl/report_finalize.py +206 -15
- package/runtime/python/okstra_ctl/report_html/common.py +2 -2
- package/runtime/python/okstra_ctl/report_html/render.py +8 -12
- package/runtime/python/okstra_ctl/report_language.py +8 -4
- package/runtime/python/okstra_ctl/report_narrative.py +90 -3
- package/runtime/python/okstra_ctl/report_projections.py +8 -2
- package/runtime/python/okstra_ctl/report_synthesis_packet.py +258 -1
- package/runtime/python/okstra_ctl/report_translation.py +2 -35
- package/runtime/python/okstra_ctl/report_views.py +4 -22
- package/runtime/python/okstra_ctl/resolve_task_key.py +13 -0
- package/runtime/python/okstra_ctl/rollup.py +13 -0
- package/runtime/python/okstra_ctl/run.py +639 -138
- package/runtime/python/okstra_ctl/run_audit.py +13 -0
- package/runtime/python/okstra_ctl/run_index_row.py +0 -12
- package/runtime/python/okstra_ctl/seeding.py +21 -11
- package/runtime/python/okstra_ctl/sequence.py +1 -1
- package/runtime/python/okstra_ctl/session.py +64 -14
- package/runtime/python/okstra_ctl/set_work_status.py +18 -0
- package/runtime/python/okstra_ctl/stage_integrate.py +15 -1
- package/runtime/python/okstra_ctl/stage_ledger.py +1 -1
- package/runtime/python/okstra_ctl/stage_map.py +57 -11
- package/runtime/python/okstra_ctl/stage_map_cli.py +83 -0
- package/runtime/python/okstra_ctl/stage_map_view.py +65 -0
- package/runtime/python/okstra_ctl/stage_targets.py +3 -12
- package/runtime/python/okstra_ctl/task_list_cli.py +138 -0
- package/runtime/python/okstra_ctl/task_show_cli.py +66 -0
- package/runtime/python/okstra_ctl/task_target.py +4 -16
- package/runtime/python/okstra_ctl/team.py +49 -2
- package/runtime/python/okstra_ctl/time_report.py +17 -2
- package/runtime/python/okstra_ctl/usage_report.py +11 -0
- package/runtime/python/okstra_ctl/user_response.py +55 -218
- package/runtime/python/okstra_ctl/user_response_values.py +242 -0
- package/runtime/python/okstra_ctl/validation_contract.py +3 -0
- package/runtime/python/okstra_ctl/verification_target.py +68 -0
- package/runtime/python/okstra_ctl/wizard.py +457 -92
- package/runtime/python/okstra_ctl/worker_artifacts.py +75 -16
- package/runtime/python/okstra_ctl/worker_audit_check.py +22 -0
- package/runtime/python/okstra_ctl/worker_dispatch.py +21 -0
- package/runtime/python/okstra_ctl/worker_liveness.py +33 -0
- package/runtime/python/okstra_ctl/worker_prompt_body.py +15 -2
- package/runtime/python/okstra_ctl/worker_prompt_contract.py +98 -7
- package/runtime/python/okstra_ctl/worker_prompt_headers.py +24 -2
- package/runtime/python/okstra_ctl/worker_prompt_policy.py +18 -3
- package/runtime/python/okstra_ctl/worker_request.py +2 -1
- package/runtime/python/okstra_ctl/worker_runner.py +16 -9
- package/runtime/python/okstra_ctl/worker_state.py +16 -1
- package/runtime/python/okstra_ctl/workflow.py +18 -1
- package/runtime/python/okstra_ctl/worktree/__init__.py +92 -0
- package/runtime/python/okstra_ctl/worktree/cleanliness.py +89 -0
- package/runtime/python/okstra_ctl/worktree/decisions.py +127 -0
- package/runtime/python/okstra_ctl/worktree/git_ops.py +165 -0
- package/runtime/python/okstra_ctl/worktree/linking.py +249 -0
- package/runtime/python/okstra_ctl/worktree/naming.py +91 -0
- package/runtime/python/okstra_ctl/worktree/provision.py +385 -0
- package/runtime/python/okstra_ctl/worktree/sync_config.py +181 -0
- package/runtime/python/okstra_ctl/worktree_cli.py +75 -0
- package/runtime/python/okstra_ctl/worktree_lookup_cli.py +39 -0
- package/runtime/python/okstra_ctl/worktree_registry.py +7 -0
- package/runtime/python/okstra_ctl/worktree_status_cli.py +53 -0
- package/runtime/python/okstra_ctl/write_policy.py +90 -213
- package/runtime/python/okstra_project/__init__.py +0 -4
- package/runtime/python/okstra_project/dirs.py +2 -2
- package/runtime/python/okstra_project/phase_pointer.py +84 -0
- package/runtime/python/okstra_project/slug.py +24 -0
- package/runtime/python/okstra_project/state.py +22 -230
- package/runtime/python/okstra_token_usage/claude.py +9 -1
- package/runtime/python/okstra_token_usage/cli.py +3 -1
- package/runtime/python/okstra_token_usage/collect.py +71 -10
- package/runtime/python/okstra_token_usage/cursor.py +2 -0
- package/runtime/python/okstra_token_usage/grok.py +1 -5
- package/runtime/python/okstra_token_usage/paths.py +26 -0
- package/runtime/python/okstra_token_usage/pricing.py +19 -7
- package/runtime/schemas/convergence-critic-results-v1.0.schema.json +5 -0
- package/runtime/schemas/execution-manifest-v2.schema.json +10 -10
- package/runtime/schemas/final-report-v2.0.schema.json +9 -26
- package/runtime/schemas/final-report-v3.0.schema.json +173 -41
- package/runtime/schemas/report-narrative-v3.0.schema.json +3 -2
- package/runtime/skills/okstra-brief-gen/SKILL.md +35 -2
- package/runtime/skills/okstra-container-build/SKILL.md +16 -47
- package/runtime/skills/okstra-inspect/facets/history.md +1 -1
- package/runtime/skills/okstra-inspect/facets/status.md +7 -6
- package/runtime/skills/okstra-pr-gen/SKILL.md +1 -1
- package/runtime/skills/okstra-run/SKILL.md +7 -5
- package/runtime/templates/report-writer-prompt-preamble.md +1 -1
- package/runtime/templates/reports/brief.template.md +6 -2
- package/runtime/templates/reports/error-analysis-input.template.md +2 -0
- package/runtime/templates/reports/final-verification-input.template.md +2 -0
- package/runtime/templates/reports/implementation-input.template.md +7 -1
- package/runtime/templates/reports/implementation-planning-input.template.md +4 -0
- package/runtime/templates/reports/quick-input.template.md +2 -0
- package/runtime/templates/reports/release-handoff-input.template.md +6 -1
- package/runtime/templates/reports/report.js +20 -3
- package/runtime/templates/reports/schedule.template.md +2 -0
- package/runtime/templates/reports/settings.template.json +0 -10
- package/runtime/templates/reports/task-brief.template.md +3 -0
- package/runtime/templates/reports/user-response.template.md +7 -3
- package/runtime/validators/checks/fixtures-01.py +57 -0
- package/runtime/validators/checks/fixtures-02.py +565 -0
- package/runtime/validators/checks/runners-01.py +108 -0
- package/runtime/validators/checks/validate-assets-01.py +60 -0
- package/runtime/validators/checks/validate-prompt-metadata-01.py +261 -0
- package/runtime/validators/checks/validate-tasks-01.py +46 -0
- package/runtime/validators/checks/validate-tasks-02.py +85 -0
- package/runtime/validators/checks/validate-tasks-03.py +61 -0
- package/runtime/validators/checks/validate-tasks-04.py +118 -0
- package/runtime/validators/forbidden_actions.py +73 -3
- package/runtime/validators/lib/common.sh +5 -0
- package/runtime/validators/lib/fixtures.sh +7 -591
- package/runtime/validators/lib/paths.sh +13 -0
- package/runtime/validators/lib/runners.sh +6 -104
- package/runtime/validators/lib/summary.sh +1 -1
- package/runtime/validators/lib/validate-assets.sh +6 -56
- package/runtime/validators/lib/validate-prompt-metadata.sh +6 -257
- package/runtime/validators/lib/validate-tasks.sh +9 -294
- package/runtime/validators/validate-implementation-plan-stages.py +4 -4
- package/runtime/validators/validate-run.py +1369 -2654
- package/runtime/validators/validate-workflow.sh +56 -16
- package/runtime/validators/validate_improvement_report.py +2 -1
- package/runtime/validators/validate_session_conformance.py +295 -49
- package/dist/commands/execute/agent-prompt.d.mts +0 -1
- package/dist/commands/execute/agent-prompt.mjs +0 -24
- package/dist/commands/execute/agent-prompt.mjs.map +0 -1
- package/dist/commands/execute/codex-dispatch.d.mts +0 -3
- package/dist/commands/execute/codex-dispatch.mjs +0 -6
- package/dist/commands/execute/codex-dispatch.mjs.map +0 -1
- package/dist/commands/execute/codex-run.d.mts +0 -3
- package/dist/commands/execute/codex-run.mjs +0 -62
- package/dist/commands/execute/codex-run.mjs.map +0 -1
- package/dist/commands/execute/convergence.d.mts +0 -1
- package/dist/commands/execute/convergence.mjs +0 -38
- package/dist/commands/execute/convergence.mjs.map +0 -1
- package/dist/commands/execute/error-log.d.mts +0 -1
- package/dist/commands/execute/error-log.mjs +0 -18
- package/dist/commands/execute/error-log.mjs.map +0 -1
- package/dist/commands/execute/git-reconcile.d.mts +0 -1
- package/dist/commands/execute/git-reconcile.mjs +0 -30
- package/dist/commands/execute/git-reconcile.mjs.map +0 -1
- package/dist/commands/execute/handoff.d.mts +0 -1
- package/dist/commands/execute/handoff.mjs +0 -31
- package/dist/commands/execute/handoff.mjs.map +0 -1
- package/dist/commands/execute/incremental-carry.d.mts +0 -1
- package/dist/commands/execute/incremental-carry.mjs +0 -20
- package/dist/commands/execute/incremental-carry.mjs.map +0 -1
- package/dist/commands/execute/incremental-scope.d.mts +0 -1
- package/dist/commands/execute/incremental-scope.mjs +0 -29
- package/dist/commands/execute/incremental-scope.mjs.map +0 -1
- package/dist/commands/execute/integrate-stages.d.mts +0 -1
- package/dist/commands/execute/integrate-stages.mjs +0 -24
- package/dist/commands/execute/integrate-stages.mjs.map +0 -1
- package/dist/commands/execute/pane-title.d.mts +0 -1
- package/dist/commands/execute/pane-title.mjs +0 -20
- package/dist/commands/execute/pane-title.mjs.map +0 -1
- package/dist/commands/execute/plan-items.d.mts +0 -1
- package/dist/commands/execute/plan-items.mjs +0 -9
- package/dist/commands/execute/plan-items.mjs.map +0 -1
- package/dist/commands/execute/plan-validate.d.mts +0 -1
- package/dist/commands/execute/plan-validate.mjs +0 -68
- package/dist/commands/execute/plan-validate.mjs.map +0 -1
- package/dist/commands/execute/plan-verify.d.mts +0 -1
- package/dist/commands/execute/plan-verify.mjs +0 -43
- package/dist/commands/execute/plan-verify.mjs.map +0 -1
- package/dist/commands/execute/spawn-followups.d.mts +0 -1
- package/dist/commands/execute/spawn-followups.mjs +0 -22
- package/dist/commands/execute/spawn-followups.mjs.map +0 -1
- package/dist/commands/execute/team.d.mts +0 -3
- package/dist/commands/execute/team.mjs +0 -66
- package/dist/commands/execute/team.mjs.map +0 -1
- package/dist/commands/execute/token-usage.d.mts +0 -1
- package/dist/commands/execute/token-usage.mjs +0 -19
- package/dist/commands/execute/token-usage.mjs.map +0 -1
- package/dist/commands/execute/worker-audit-check.d.mts +0 -1
- package/dist/commands/execute/worker-audit-check.mjs +0 -34
- package/dist/commands/execute/worker-audit-check.mjs.map +0 -1
- package/dist/commands/execute/worker-dispatch.d.mts +0 -7
- package/dist/commands/execute/worker-dispatch.mjs +0 -64
- package/dist/commands/execute/worker-dispatch.mjs.map +0 -1
- package/dist/commands/execute/worker-state.d.mts +0 -1
- package/dist/commands/execute/worker-state.mjs +0 -28
- package/dist/commands/execute/worker-state.mjs.map +0 -1
- package/dist/commands/execute/worktree-lookup.d.mts +0 -1
- package/dist/commands/execute/worktree-lookup.mjs +0 -92
- package/dist/commands/execute/worktree-lookup.mjs.map +0 -1
- package/dist/commands/execute/worktree-status.d.mts +0 -1
- package/dist/commands/execute/worktree-status.mjs +0 -121
- package/dist/commands/execute/worktree-status.mjs.map +0 -1
- package/dist/commands/inspect/code-review.d.mts +0 -1
- package/dist/commands/inspect/code-review.mjs +0 -32
- package/dist/commands/inspect/code-review.mjs.map +0 -1
- package/dist/commands/inspect/container.d.mts +0 -1
- package/dist/commands/inspect/container.mjs +0 -25
- package/dist/commands/inspect/container.mjs.map +0 -1
- package/dist/commands/inspect/context-cost.d.mts +0 -1
- package/dist/commands/inspect/context-cost.mjs +0 -25
- package/dist/commands/inspect/context-cost.mjs.map +0 -1
- package/dist/commands/inspect/design-prep.d.mts +0 -1
- package/dist/commands/inspect/design-prep.mjs +0 -22
- package/dist/commands/inspect/design-prep.mjs.map +0 -1
- package/dist/commands/inspect/error-report.d.mts +0 -1
- package/dist/commands/inspect/error-report.mjs +0 -25
- package/dist/commands/inspect/error-report.mjs.map +0 -1
- package/dist/commands/inspect/error-zip.d.mts +0 -1
- package/dist/commands/inspect/error-zip.mjs +0 -24
- package/dist/commands/inspect/error-zip.mjs.map +0 -1
- package/dist/commands/inspect/log-report.d.mts +0 -1
- package/dist/commands/inspect/log-report.mjs +0 -26
- package/dist/commands/inspect/log-report.mjs.map +0 -1
- package/dist/commands/inspect/model-io.d.mts +0 -1
- package/dist/commands/inspect/model-io.mjs +0 -25
- package/dist/commands/inspect/model-io.mjs.map +0 -1
- package/dist/commands/inspect/profile-show.d.mts +0 -1
- package/dist/commands/inspect/profile-show.mjs +0 -28
- package/dist/commands/inspect/profile-show.mjs.map +0 -1
- package/dist/commands/inspect/recap.d.mts +0 -1
- package/dist/commands/inspect/recap.mjs +0 -30
- package/dist/commands/inspect/recap.mjs.map +0 -1
- package/dist/commands/inspect/resolve-task-key.d.mts +0 -1
- package/dist/commands/inspect/resolve-task-key.mjs +0 -24
- package/dist/commands/inspect/resolve-task-key.mjs.map +0 -1
- package/dist/commands/inspect/rollup.d.mts +0 -1
- package/dist/commands/inspect/rollup.mjs +0 -25
- package/dist/commands/inspect/rollup.mjs.map +0 -1
- package/dist/commands/inspect/run-audit.d.mts +0 -1
- package/dist/commands/inspect/run-audit.mjs +0 -25
- package/dist/commands/inspect/run-audit.mjs.map +0 -1
- package/dist/commands/inspect/set-work-status.d.mts +0 -1
- package/dist/commands/inspect/set-work-status.mjs +0 -29
- package/dist/commands/inspect/set-work-status.mjs.map +0 -1
- package/dist/commands/inspect/stage-map.d.mts +0 -1
- package/dist/commands/inspect/stage-map.mjs +0 -131
- package/dist/commands/inspect/stage-map.mjs.map +0 -1
- package/dist/commands/inspect/task-list.d.mts +0 -1
- package/dist/commands/inspect/task-list.mjs +0 -149
- package/dist/commands/inspect/task-list.mjs.map +0 -1
- package/dist/commands/inspect/task-show.d.mts +0 -1
- package/dist/commands/inspect/task-show.mjs +0 -108
- package/dist/commands/inspect/task-show.mjs.map +0 -1
- package/dist/commands/inspect/time-report.d.mts +0 -1
- package/dist/commands/inspect/time-report.mjs +0 -24
- package/dist/commands/inspect/time-report.mjs.map +0 -1
- package/dist/commands/inspect/usage-report.d.mts +0 -1
- package/dist/commands/inspect/usage-report.mjs +0 -23
- package/dist/commands/inspect/usage-report.mjs.map +0 -1
- package/dist/commands/inspect/user-response.d.mts +0 -1
- package/dist/commands/inspect/user-response.mjs +0 -35
- package/dist/commands/inspect/user-response.mjs.map +0 -1
- package/dist/commands/inspect/worker-liveness.d.mts +0 -1
- package/dist/commands/inspect/worker-liveness.mjs +0 -45
- package/dist/commands/inspect/worker-liveness.mjs.map +0 -1
- package/dist/commands/lifecycle/contract-check.d.mts +0 -1
- package/dist/commands/lifecycle/contract-check.mjs +0 -18
- package/dist/commands/lifecycle/contract-check.mjs.map +0 -1
- package/dist/commands/lifecycle/migrate.d.mts +0 -1
- package/dist/commands/lifecycle/migrate.mjs +0 -30
- package/dist/commands/lifecycle/migrate.mjs.map +0 -1
- package/dist/commands/lifecycle/model.d.mts +0 -1
- package/dist/commands/lifecycle/model.mjs +0 -22
- package/dist/commands/lifecycle/model.mjs.map +0 -1
- package/dist/commands/manager.d.mts +0 -3
- package/dist/commands/manager.mjs +0 -50
- package/dist/commands/manager.mjs.map +0 -1
- package/dist/commands/report/agent-activity.d.mts +0 -1
- package/dist/commands/report/agent-activity.mjs +0 -20
- package/dist/commands/report/agent-activity.mjs.map +0 -1
- package/dist/commands/report/approval-decision.d.mts +0 -1
- package/dist/commands/report/approval-decision.mjs +0 -21
- package/dist/commands/report/approval-decision.mjs.map +0 -1
- package/dist/commands/report/design-snapshot.d.mts +0 -1
- package/dist/commands/report/design-snapshot.mjs +0 -19
- package/dist/commands/report/design-snapshot.mjs.map +0 -1
- package/dist/commands/report/finalize.d.mts +0 -4
- package/dist/commands/report/finalize.mjs +0 -64
- package/dist/commands/report/finalize.mjs.map +0 -1
- package/dist/commands/report/inject-report-index.d.mts +0 -1
- package/dist/commands/report/inject-report-index.mjs +0 -21
- package/dist/commands/report/inject-report-index.mjs.map +0 -1
- package/dist/commands/report/render-final-report.d.mts +0 -1
- package/dist/commands/report/render-final-report.mjs +0 -23
- package/dist/commands/report/render-final-report.mjs.map +0 -1
- package/dist/commands/report/render-views.d.mts +0 -1
- package/dist/commands/report/render-views.mjs +0 -27
- package/dist/commands/report/render-views.mjs.map +0 -1
- package/dist/commands/report/translate.d.mts +0 -1
- package/dist/commands/report/translate.mjs +0 -33
- package/dist/commands/report/translate.mjs.map +0 -1
- package/runtime/bin/lib/okstra/tmux-pane.sh +0 -40
- package/runtime/bin/lib/okstra-ctl/cmd-batch.sh +0 -59
- package/runtime/bin/lib/okstra-ctl/cmd-list.sh +0 -35
- package/runtime/bin/lib/okstra-ctl/cmd-open.sh +0 -36
- package/runtime/bin/lib/okstra-ctl/cmd-projects.sh +0 -26
- package/runtime/bin/lib/okstra-ctl/cmd-reconcile.sh +0 -29
- package/runtime/bin/lib/okstra-ctl/cmd-reindex.sh +0 -38
- package/runtime/bin/lib/okstra-ctl/cmd-rerun.sh +0 -345
- package/runtime/bin/lib/okstra-ctl/cmd-show.sh +0 -27
- package/runtime/bin/lib/okstra-ctl/cmd-tail.sh +0 -92
- package/runtime/bin/lib/okstra-ctl/main.sh +0 -41
- package/runtime/bin/lib/okstra-ctl/prepare.sh +0 -31
- package/runtime/bin/lib/okstra-ctl/usage.sh +0 -23
- package/runtime/bin/okstra-central.sh +0 -152
- package/runtime/bin/okstra-incremental-carry.py +0 -10
- package/runtime/bin/okstra-incremental-scope.py +0 -10
- package/runtime/bin/okstra-team-reconcile.sh +0 -36
- package/runtime/python/okstra_ctl/agent_prompt_cli.py +0 -1156
- package/runtime/python/okstra_ctl/batch.py +0 -60
- package/runtime/python/okstra_ctl/clarification_items.py +0 -1050
- package/runtime/python/okstra_ctl/container_registry.py +0 -72
- package/runtime/python/okstra_ctl/improvement_assignment.py +0 -61
- package/runtime/python/okstra_ctl/resolver.py +0 -54
- package/runtime/python/okstra_ctl/team_reconcile.py +0 -275
- package/runtime/python/okstra_ctl/tmux.py +0 -134
- package/runtime/python/okstra_ctl/worktree.py +0 -1099
package/docs/architecture.md
CHANGED
|
@@ -18,7 +18,7 @@ Its core capabilities at a glance are:
|
|
|
18
18
|
- **Single python authority**: All prepare wiring—resolving profiles/workers/models, computing paths, rendering, and central record_start—is concentrated in a single function, [`okstra_ctl.run.prepare_task_bundle()`](../scripts/okstra_ctl/run.py). `okstra.sh` and the `okstra-run` skill are thin callers of that same function and do not pass state through environment variables. Task identity, paths, and workflow state are recalculated from authoritative on-disk files every time.
|
|
19
19
|
- **Host-aware handoff**: Claude Code, Codex, Antigravity, Grok, and Kimi can keep their current native session as the lead. The standalone compatibility launcher still starts a new `claude` process by default, while the external adapter uses registered CLI wrappers. Every path consumes the same `prepare_task_bundle` outputs.
|
|
20
20
|
- **Required team contract**: The `Required workers:` block in each phase profile is authoritative for the roster. General analysis phases use Claude/Codex analysers plus a report writer by default, while Antigravity, Grok, and Kimi are included only when allowed by both the profile and `--workers`. Lead-oriented phases such as `release-handoff` have separate rosters.
|
|
21
|
-
- **User-home install + project-local task bundles**: One `npx okstra@latest install` command installs the runtime (`~/.okstra/{lib/python, bin, templates, prompts}`) and installs public skills to `~/.agents/skills/` by default. If `~/.claude` exists, it also installs Claude skills and six worker agent definitions (`~/.claude/agents/*-worker.md`). Only user entry-point skills are exposed in the skill list; lead/support operating contracts are installed as runtime resources under `~/.okstra/prompts/` and are not discoverable as skills. Global conversation memory is stored separately from projects under `~/.okstra/memory-book/`. Task bundles and discovery metadata are stored under `.okstra/` in the target project. **In addition, `<PROJECT_ROOT>/.claude/settings.local.json` is provisioned as a symlink to `~/.okstra/templates/settings.local.json`** (`okstra setup`
|
|
21
|
+
- **User-home install + project-local task bundles**: One `npx okstra@latest install` command installs the runtime (`~/.okstra/{lib/python, bin, templates, prompts}`) and installs public skills to `~/.agents/skills/` by default. If `~/.claude` exists, it also installs Claude skills and six worker agent definitions (`~/.claude/agents/*-worker.md`). Only user entry-point skills are exposed in the skill list; lead/support operating contracts are installed as runtime resources under `~/.okstra/prompts/` and are not discoverable as skills. Global conversation memory is stored separately from projects under `~/.okstra/memory-book/`. Task bundles and discovery metadata are stored under `.okstra/` in the target project. **In addition, `<PROJECT_ROOT>/.claude/settings.local.json` is provisioned as a symlink to `~/.okstra/templates/settings.local.json`** (`okstra setup` and the prepare path manage it idempotently; if a regular file already existed, it is preserved as `.bak.<timestamp>` before replacement).
|
|
22
22
|
- **Resume and clarification**: Supports resuming the same task and responding to follow-up questions from the lead through `--task-key`, `--resume-clarification`, and `--clarification-response`.
|
|
23
23
|
- **Dual-audience derived views and telemetry**: For schema v2, derives the full reading copy Markdown (on demand) and task-specific human-facing HTML independently from the same v2 data.json. Schema v1 and quick Markdown reports keep their compatibility renderer. Worker error sidecars, wrapper log sidecars, and token-usage/cost accounting remain separate audit inputs.
|
|
24
24
|
|
|
@@ -85,7 +85,7 @@ okstra's prepare responsibilities are consolidated in a single Python entry poin
|
|
|
85
85
|
- Resolves task-brief / clarification-response paths (cwd first → PROJECT_ROOT fallback)
|
|
86
86
|
- Computes the stable task root and all paths/sequences inside a per-task mutex (`~/.okstra/.locks/<task-key>.lock`), then persists them to `<run-dir>/manifests/run-context-<seq>.json`
|
|
87
87
|
- Persists user input to `<run-dir>/manifests/run-inputs-<seq>.json`
|
|
88
|
-
- Renders the instruction set (`analysis-profile.md`, `analysis-packet.md`, `analysis-material.md`, `task-brief.md`, `reference-expectations.md`, `final-report-template.md`, `final-report-schema.json`, optional `clarification-response.md`, optional `directive.txt`, final-verification-only `verification-target.md
|
|
88
|
+
- Renders the instruction set (`analysis-profile.md`, `analysis-packet.md`, `analysis-material.md`, `task-brief.md`, `reference-expectations.md`, `final-report-template.md`, `final-report-schema.json`, optional `clarification-response.md`, optional `directive.txt`, final-verification-only `verification-target.md`) and writes the lead prompt to `runs/<task-type>/prompts/lead-execution-prompt-<task-type>-<seq>.md` alongside its `.meta.json` invocation record
|
|
89
89
|
- Updates `task-manifest.json`, `task-index.md`, `run-manifest-*.json`, `history/timeline.json`, and `discovery/{latest-task,task-catalog}.json`
|
|
90
90
|
- Writes a preassigned Claude session ID and `sessions/claude-resume-*.sh` (unless `--render-only` is used)
|
|
91
91
|
- Records record_start in the central indexes (`~/.okstra/{active,recent}.jsonl`, `projects/<id>/{index.jsonl, meta.json}`)
|
|
@@ -126,7 +126,7 @@ Runtime entry points are consolidated in Python packages. Bash and skills only c
|
|
|
126
126
|
- [`okstra_ctl.workflow`](../scripts/okstra_ctl/workflow.py) — phase rules (PHASE_ALLOWED_OUTPUTS / PHASE_FORBIDDEN_ACTIONS).
|
|
127
127
|
- [`okstra_ctl.material`](../scripts/okstra_ctl/material.py) — `analysis-material.md` body + related-tasks builder.
|
|
128
128
|
- [`okstra_ctl.session`](../scripts/okstra_ctl/session.py) · [`okstra_ctl.seeding`](../scripts/okstra_ctl/seeding.py) — Claude session ID / resume command / installation validation / runtime settings.
|
|
129
|
-
- [`okstra_ctl.{ids,index,invocation,jsonl,project_meta,reconcile,
|
|
129
|
+
- [`okstra_ctl.{ids,index,invocation,jsonl,project_meta,reconcile,sequence,backfill,listing,locks}`](../scripts/okstra_ctl/) — existing central-index (`~/.okstra`) modules.
|
|
130
130
|
- [`okstra_project.{resolver,state}`](../scripts/okstra_project/) — PROJECT_ROOT resolution + project.json upsert + task-catalog/manifest reader.
|
|
131
131
|
- [`okstra_ctl.manager_cli`](../scripts/okstra_ctl/manager_cli.py), [`manager_store`](../scripts/okstra_ctl/manager_store.py), [`manager_sync`](../scripts/okstra_ctl/manager_sync.py), [`manager_launch`](../scripts/okstra_ctl/manager_launch.py), [`manager_paths`](../scripts/okstra_ctl/manager_paths.py) — cross-project manager state, one-way project snapshot sync, and child launch packet/context creation for `okstra manager`.
|
|
132
132
|
|
|
@@ -134,7 +134,6 @@ Runtime entry points are consolidated in Python packages. Bash and skills only c
|
|
|
134
134
|
|
|
135
135
|
- [`scripts/okstra.sh`](../scripts/okstra.sh) — standalone compatibility launcher: CLI parsing / interactive prompt / `prepare_task_bundle` invocation / default `exec claude`. In-host Claude Code, Codex, and Antigravity runs use `okstra-run` and keep their current native session.
|
|
136
136
|
- [`scripts/lib/okstra/{cli,globals,interactive,project-resolver,usage}.sh`](../scripts/lib/okstra/) — CLI/interactive support only; contains no artifact-generation logic.
|
|
137
|
-
- [`scripts/okstra-ctl.sh`](../scripts/okstra-ctl.sh) + [`scripts/lib/okstra-ctl/`](../scripts/lib/okstra-ctl/) — central control-center CLI (list / show / open / rerun / reconcile / etc.).
|
|
138
137
|
|
|
139
138
|
### Runtime assets (templates + lead resources)
|
|
140
139
|
|
|
@@ -153,7 +152,7 @@ Runtime entry points are consolidated in Python packages. Bash and skills only c
|
|
|
153
152
|
- [`prompts/lead/okstra-lead-contract.md`](../prompts/lead/okstra-lead-contract.md) is the runtime-neutral lifecycle core: phase boundaries, artifacts, convergence, report ownership, and persistence semantics.
|
|
154
153
|
- `prompts/lead/adapters/claude-code.md`, `prompts/lead/adapters/codex.md`, `prompts/lead/adapters/antigravity.md`, and `prompts/lead/adapters/external.md` map the same semantic operations to one selected host runtime. The generated launch prompt exposes the core path plus exactly one adapter path.
|
|
155
154
|
- `prompts/lead/adapters/cmux.md` is selected by environment rather than by runtime: when the run manifest's `terminalBackend` is `cmux-pane`, every lead runtime resolves to it and dispatches through `okstra team`, because okstra owns the worker panes on that path instead of the host. It overrides only the adapter and the dispatch mode; the lead's agent, role, and session accounting still come from its own runtime.
|
|
156
|
-
- Runtime metadata and role assignments are persisted separately, but the lead provider is derived from the host: Claude Code maps to Claude, Codex maps to Codex, and Antigravity CLI maps to Antigravity. New runs persist `hostRuntime`, `leadAssignment`, and `workerAssignments[]`; each assignment records its provider, model, execution value, and resolved `native-session` or `cli-wrapper` runner. `lead-execution-prompt.md` is canonical
|
|
155
|
+
- Runtime metadata and role assignments are persisted separately, but the lead provider is derived from the host: Claude Code maps to Claude, Codex maps to Codex, and Antigravity CLI maps to Antigravity. New runs persist `hostRuntime`, `leadAssignment`, and `workerAssignments[]`; each assignment records its provider, model, execution value, and resolved `native-session` or `cli-wrapper` runner. `lead-execution-prompt.md` is canonical: one file per run at `runs/<task-type>/prompts/lead-execution-prompt-<task-type>-<seq>.md`. No Claude-named copy is written — `resources.claudeExecutionPromptPath` in the run manifest is a key alias that resolves to that same file for historical consumers.
|
|
157
156
|
- Host and provider registries remain separate: the active registered host owns the native lead session, while non-native providers run through their registered CLI wrappers.
|
|
158
157
|
- [`skills/okstra-setup/SKILL.md`](../skills/okstra-setup/SKILL.md) — **first-run bootstrap**. Runs `okstra install` and creates `project.json`.
|
|
159
158
|
- [`skills/okstra-run/SKILL.md`](../skills/okstra-run/SKILL.md) — host-aware in-session entry point that starts an okstra task in the current registered host session and calls `prepare_task_bundle` directly.
|
|
@@ -272,7 +271,7 @@ The following environment variables are read only as user settings, not for stat
|
|
|
272
271
|
- `OKSTRA_HOME` — overrides the central directory location (default `~/.okstra`).
|
|
273
272
|
- `OKSTRA_DEFAULT_LEAD_MODEL`, `OKSTRA_DEFAULT_CLAUDE_MODEL`, `OKSTRA_DEFAULT_CODEX_MODEL`, `OKSTRA_DEFAULT_ANTIGRAVITY_MODEL`, `OKSTRA_DEFAULT_REPORT_WRITER_MODEL` — model defaults.
|
|
274
273
|
- `OKSTRA_TOOL_NAME`, `OKSTRA_COMMAND_NAME` — display names in usage output.
|
|
275
|
-
- `OKSTRA_RUN_SEQ_OVERRIDE` — run-sequence override forced by
|
|
274
|
+
- `OKSTRA_RUN_SEQ_OVERRIDE` — run-sequence override forced by test hooks (per-process).
|
|
276
275
|
|
|
277
276
|
Other variables such as `PROJECT_ID`, `TASK_GROUP`, `RUN_*`, `FINAL_*`, and `CLAUDE_*` are not exported and do not leak into child processes.
|
|
278
277
|
|
|
@@ -298,12 +297,12 @@ The legacy standalone shell path remains Claude-specific:
|
|
|
298
297
|
|
|
299
298
|
Kimi and Grok implement this same lead contract. Their provider roles remain `lead`, `analyser`, and `critic`; they do not gain executor, verifier, or report-writer roles from being lead-capable hosts.
|
|
300
299
|
|
|
301
|
-
Both modes create identical artifacts (task-manifest, run-manifest, timeline, instruction set, and central-index registration), so
|
|
300
|
+
Both modes create identical artifacts (task-manifest, run-manifest, timeline, instruction set, and central-index registration), so the run-index consumers (`okstra run-audit`, `okstra error-zip`) operate consistently without distinguishing between them.
|
|
302
301
|
- The handed-off native host acts as the Okstra lead, responsible for orchestration and final synthesis.
|
|
303
302
|
- The default worker policy remains Claude + Codex analysis and a Claude report writer. Antigravity, Grok, and Kimi are profile-gated optional assignments; Grok and Kimi are read-only analyser/critic providers.
|
|
304
303
|
- The lead assigns worker responsibilities and makes the final judgment after reading the task bundle.
|
|
305
304
|
- okstra Claude assets installed in the user home (`~/.claude/skills`, `~/.claude/agents`) instruct Claude to dispatch workers through `Agent(name: ...)`; workers automatically join the session's implicit team.
|
|
306
|
-
- **Team lifecycle (Claude Code v2.1.178+)**: v2.1.178 removed the `TeamCreate` / `TeamDelete` tools and the `team_name` parameter from `Agent(...)`. When `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` (seeded into `settings.json` by `okstra install`), one implicit team per session is created automatically at startup. In Phase 3, the lead does not call a team-creation tool. It records only the `teamName` audit label and `teamCreate: { attempted: false, status: "implicit"
|
|
305
|
+
- **Team lifecycle (Claude Code v2.1.178+)**: v2.1.178 removed the `TeamCreate` / `TeamDelete` tools and the `team_name` parameter from `Agent(...)`. When `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` (seeded into `settings.json` by `okstra install`), one implicit team per session is created automatically at startup. In Phase 3, the lead does not call a team-creation tool. It records only the `teamName` audit label and `teamCreate: { attempted: false, status: "implicit" }`, then dispatches workers through `Agent(name: "<role>-worker", run_in_background: true)` (without team_name). Teammates run in-process. At run end, after Phase 7 token accounting, the lead asks whether to clean up worker teammates. If approved, it sends each completed teammate a `SendMessage` shutdown_request. There is no tool for deleting the implicit team; it disappears when the session ends. If the user keeps the teammates, they remain in the FleetView roster and the lead tells the user to remove them through Teams/FleetView. Phase 7 token accounting locates worker sessions by top-level `agentName` or nested `subagents/agent-a<name>-<hash>.jsonl` filenames when `teamCreate.status` is `implicit`/`skipped`/`error`.
|
|
307
306
|
|
|
308
307
|
## Lead prompt contract
|
|
309
308
|
|
|
@@ -322,7 +321,7 @@ The standard `okstra` workflow applies the following team contract consistently
|
|
|
322
321
|
- The current host-native provider owns the synthesis-only lead session: Claude on Claude Code, Codex on Codex.
|
|
323
322
|
- Every selected worker comes from the profile roster and provider capability registry. The default analysis policy remains Claude + Codex + a report writer; Antigravity, Grok, and Kimi are attempted only when the profile and resolved roster include them.
|
|
324
323
|
- `Report writer worker` focuses on report structure and evidence organization, while the host-native lead remains the final synthesis owner. Claude is the default report-writer provider; Codex may be selected explicitly.
|
|
325
|
-
- Model defaults are provider and functional-role policy. Fallbacks include Claude lead/analyser=`opus`, Codex lead/analyser=`gpt-5.6-sol`, Claude report writer=`sonnet`, Antigravity=`gemini-3.1-pro`, Grok analyser=`grok-4.6`, and Kimi analyser=`kimi-
|
|
324
|
+
- Model defaults are provider and functional-role policy. Fallbacks include Claude lead/analyser=`opus`, Codex lead/analyser=`gpt-5.6-sol`, Claude report writer=`sonnet`, Antigravity=`gemini-3.1-pro`, Grok analyser=`grok-4.6`, and Kimi analyser=`kimi-k3`. Selectable catalog models may be assigned to every role.
|
|
326
325
|
- Before the final judgment, each required role in the current run's worker roster must have either a result or an explicit terminal status (`completed`, `timeout`, `error`, `not-run`).
|
|
327
326
|
- Every attempted worker (`completed`, `timeout`, `error`) must have an assigned worker prompt history file under the current run's `prompts/` directory.
|
|
328
327
|
- Worker timing begins at the atomic transition to `in-progress`, which records `workers[].startedAt` in `team-state.json`; prompt creation time is not a dispatch proxy. `okstra worker-state transition` and both dispatch adapters share `dispatch_state.transition_worker_status`, while `okstra worker-liveness --team-state ... --worker ...` reads that timestamp as the launch-grace authority for both probe kinds — the in-process audit sidecar is reused on re-dispatch, so only `startedAt` separates the previous attempt's last heartbeat from this dispatch's silence.
|
|
@@ -352,7 +351,7 @@ The complete artifact lifecycle is: worker results → Round 0 grouping → redu
|
|
|
352
351
|
|
|
353
352
|
Cross-verification does not mean that worker A reviews worker B's entire result. Round 0 records multi-source agreement immediately, and the reducer asks independent analyser instances to vote only on single-source or still-unresolved findings selected in the persisted queue. The report writer is never a voter. It organizes the validated result, while the later plan-body round verifies the consolidated `P-*` plan items rather than reopening the `F-*` finding queue.
|
|
354
353
|
|
|
355
|
-
The lead writes the grouped input, then advances it through the internal admin CLI operations `okstra convergence seed`, `plan-round`, `apply-round`, optional `apply-critic-gaps`, `finalize`, and `validate`. For worker W, each generated dispatch excludes findings originating from W; resolved findings leave the queue permanently. Lightweight reverify receives only its current persisted batch and embedded evidence, not the original analysis packet, profile, brief, or instruction set. Its prompt carries an exact task type and active-phase forbidden-actions block; dispatch validates those phase anchors, and the run validator rejects a recorded phase-boundary violation. Terminal worker non-results and completed per-finding `UNVERIFIABLE` responses become `verification-error`; the engine never fabricates a `DISAGREE` vote. The report writer does not vote and consumes the validated terminal convergence state and every analysis-worker result as read context. Under report contract v3 it writes only the narrative Markdown, a pointer, and its audit sidecar. Approval decisions, activity, execution, convergence, design preparation, and plan-body verification remain in their single-owner inputs. Phase 7 validates those inputs and atomically publishes `data.json` once. The full reading copy is rendered on demand. Newly finalized convergence output is schema v1.
|
|
354
|
+
The lead writes the grouped input, then advances it through the internal admin CLI operations `okstra convergence seed`, `plan-round`, `apply-round`, optional `apply-critic-gaps`, `finalize`, and `validate`. For worker W, each generated dispatch excludes findings originating from W; resolved findings leave the queue permanently. Lightweight reverify receives only its current persisted batch and embedded evidence, not the original analysis packet, profile, brief, or instruction set. Its prompt carries an exact task type and active-phase forbidden-actions block; dispatch validates those phase anchors, and the run validator rejects a recorded phase-boundary violation. Terminal worker non-results and completed per-finding `UNVERIFIABLE` responses become `verification-error`; the engine never fabricates a `DISAGREE` vote. The report writer does not vote and consumes the validated terminal convergence state and every analysis-worker result as read context. Under report contract v3 it writes only the narrative Markdown, a pointer, and its audit sidecar. Approval decisions, activity, execution, convergence, design preparation, and plan-body verification remain in their single-owner inputs. Phase 7 validates those inputs and atomically publishes `data.json` once. The full reading copy is rendered on demand. Newly finalized convergence output is schema v1.4; under the compatibility path, valid historical final schema versions v1.0, v1.1, v1.2, or v1.3 are reused and consumed without rewrite.
|
|
356
355
|
|
|
357
356
|
Coverage critic and plan-body verification remain separate from finding convergence. The critic audits the integrated Round 0 analysis, while implementation-planning's plan-body gate validates the later report draft through its own `P-*` queue and state file. Neither path changes the engine's `F-*` queue.
|
|
358
357
|
|
|
@@ -417,7 +416,7 @@ On the first run, it writes the four fields `projectId`, `projectRoot`, `created
|
|
|
417
416
|
|
|
418
417
|
`reviewRulePacks` (optional, an array of absolute paths, default empty) declares the project's own review rule packs — the review standard a phase reads before it judges a plan or a diff, such as a team's PR-review skill. A pack used to reach a run only when the task brief cited its exact path, so whether the team standard applied depended on who wrote the brief; a declaration here applies to every run in the project, and the two channels are a union. It is read by [`scripts/okstra_project/resolver.py`](../scripts/okstra_project/resolver.py) `resolve_review_rule_packs`, which drops a relative entry — a worker's cwd is a worktree, where a relative path names a different file — and falls back to "none declared" on an unreadable or malformed `project.json`. Three phases consume it: `implementation-planning` (plan away the findings before code exists), the implementation executor's coding-conventions preflight, and the static review passes of the implementation verifier and `final-verification`. **Enforced:** `okstra doctor --phase <phase>` fails the `review rule packs` check when a declared path is not a readable file ([`scripts/okstra_ctl/doctor.py`](../scripts/okstra_ctl/doctor.py) `_review_rule_pack_check`), because a stale path otherwise costs the whole pack in silence. Whether a pack that *does* resolve was actually read stays the phase's own `project-review-rules:` record — no machine check reads a worker's reasoning.
|
|
419
418
|
|
|
420
|
-
The authoritative source for
|
|
419
|
+
The authoritative source for reindex/backfill also changed under the new model. Previously it sourced `examples/projects/*.conf.sh`; it now scans `~/.okstra/projects/<projectId>/meta.json` (the mirror of the project.json information produced by record_start) to restore (projectId, projectRoot) mappings. The `OKSTRA_PROJECT_DEFINITION_DIR_OVERRIDE` environment variable has also been retired.
|
|
421
420
|
|
|
422
421
|
## Artifact-home rule
|
|
423
422
|
|
|
@@ -447,14 +446,14 @@ Selection rules:
|
|
|
447
446
|
|
|
448
447
|
Each task type enforces phase-specific allowed and forbidden actions. A run creates only the artifacts for its own task type and does not advance to the next phase. The next phase always begins with a new `okstra.sh` execution.
|
|
449
448
|
|
|
450
|
-
The fourth column is the `workflow.nextRecommendedPhase` pointer Phase 7 leaves behind. The pointer is an object `{phase, status, rationale}`; `status` is `ready`, `pending`, `blocked`, or `terminal`, and `phase` names a phase only under `ready`. Phase 7 does not decide the route — it projects the pointer from the report's own routing field (`scripts/okstra_ctl/next_phase.py::project`), named per row below. The
|
|
449
|
+
The fourth column is the `workflow.nextRecommendedPhase` pointer Phase 7 leaves behind. The pointer is an object `{phase, status, rationale}`; `status` is `ready`, `pending`, `blocked`, or `terminal`, and `phase` names a phase only under `ready`. Phase 7 does not decide the route — it projects the pointer, `rationale` included, from the report's own routing field (`scripts/okstra_ctl/next_phase.py::project`), named per row below. Nothing else reaches the pointer: the value already in the manifest is the previous run's, and the projection does not consult it. The rule for authoring that field is stated once, in the Phase 6 checklist of [`prompts/lead/report-writer.md`](../prompts/lead/report-writer.md); this table describes the outcome, not the rule.
|
|
451
450
|
|
|
452
451
|
| task type | Purpose | Core artifacts | Next-phase pointer after Phase 7 | Code changes allowed? |
|
|
453
452
|
|---|---|---|---|---|
|
|
454
453
|
| `requirements-discovery` | Classify the request as bugfix, feature, refactor, ops, or improvement, then route it to a safe next phase | work category, routing decision, missing-input list, clarification requests | from `requirementsDiscovery.routing.nextTaskType`: `ready` at `error-analysis` or `implementation-option-selection`; `pending` when the run settles on neither | No |
|
|
455
454
|
| `error-analysis` | Analyze the symptoms, causes, and reproduction gaps of a reported error/incident based on evidence | symptom/trigger summary, root-cause hypotheses, reproduction gap, validation path | from `errorAnalysis.routing.nextTaskType`: `ready` at `implementation-option-selection` after a credible cause, or at `error-analysis` for continued investigation | No |
|
|
456
455
|
| `implementation-option-selection` | Compare or validate implementation directions before detailed planning | up to three ranked directions, per-direction `coveragePercent` and `scopePrecisionPercent`, rejected-candidate audit, separate `DIRECTION SELECTION` response | from the `implementationOptionSelection.routing` string enum: `ready` at `implementation-planning` once a direction is confirmed, `pending` on `pending-direction-selection`, `blocked` on `blocked` | No (strictly read-only; source edits, builds, tests, migrations, and deploys are prohibited) |
|
|
457
|
-
| `implementation-planning` | Expand one selected direction into an executable plan without changing its mechanism or architecture boundary | selected-direction snapshot/reference, direction realization, affected-file list, Stage Map, validation/rollback, exact plan coverage, YAML frontmatter `approved: false`, **§5.5.9 Plan Body Verification**. Existing plans without `planningContract: selected-direction` retain the legacy option-candidate and `implementation-option:` contract | from `implementationPlanning.outcome`: `ready` at `implementation` on `plan-ready` (the plan still needs its separate approval before that run starts), `ready` at `implementation-option-selection` on `direction-invalidated` | No |
|
|
456
|
+
| `implementation-planning` | Expand one selected direction into an executable plan without changing its mechanism or architecture boundary | selected-direction snapshot/reference, direction realization, affected-file list, Stage Map, validation/rollback, exact plan coverage, YAML frontmatter `approved: false`, **§5.5.9 Plan Body Verification**. Existing plans without `planningContract: selected-direction` retain the legacy option-candidate and `implementation-option:` contract | from `implementationPlanning.outcome`: `ready` at `implementation` on `plan-ready` or on a candidate-comparison plan with no `outcome` (the plan still needs its separate approval before that run starts), `ready` at `implementation-option-selection` on `direction-invalidated` | No |
|
|
458
457
|
| `implementation` | Modify source code according to the approved `implementation-planning` final report. **One run executes exactly one stage** (selected with `--stage <auto\|N>`) | commit list, diff summary, out-of-plan edits block, validation/TDD evidence, rollback verification, verifier results (Antigravity/Codex/Claude), `carry/stage-<N>.json` evidence sidecar | from `implementation.routingRecommendation.target`: `ready` at that phase — `final-verification` on a clean stage, otherwise `error-analysis`, `implementation-planning`, or `implementation` | Yes (limited to the approved plan's file list; `git push`/publish/deploy/real migration prohibited) |
|
|
459
458
|
| `final-verification` | Check completed work for residual defects and regression risk, then make a release judgment | acceptance verdict, residual risk, follow-up routing (`error-analysis`/`implementation-option-selection`/`implementation-planning`/`release-handoff`) | from `finalVerification.routingRecommendation.target`: `ready` at that value — `release-handoff` only on an `accepted` verdict, otherwise the phase owning the defect (cause, selected direction, or detailed plan). `release-handoff(stage-group)` is a scope qualifier on the same phase, so it projects to `release-handoff`. `done` becomes `terminal` | No (read-only tests only) |
|
|
460
459
|
| `release-handoff` | Deliver `accepted` changes as a commit, push, or PR according to the user's chosen method | user menu responses (H1 action / H2 PR base / H3 message handling), executed git/gh command log, commit SHA list, PR URL | always `terminal` — the lifecycle ends here and this report has no routing field Phase 7 projects from | Yes—but execute **only the mutating commands selected by the user in the menu**. `git push --force*`, direct push to the base branch, `--no-verify`, `gh release`, and publish/deploy are prohibited. The source code itself must not be changed; package the existing `implementation` diff unchanged. |
|
|
@@ -465,7 +464,7 @@ The fourth column is the `workflow.nextRecommendedPhase` pointer Phase 7 leaves
|
|
|
465
464
|
Common constraints:
|
|
466
465
|
|
|
467
466
|
- Every phase except `implementation` prohibits source-code edits, builds, migrations, deployments, and other state-mutating commands (`final-verification` allows read-only test commands only). `implementation` permits edits/commits only within the file list of the approved plan; `git push`, publish, deploy, real migration, and third-party write APIs remain prohibited.
|
|
468
|
-
- **Isolated worktree for pre-implementation non-implementation phases (BLOCKING)**: The first pre-implementation non-implementation phase prepare creates a task-key `git worktree
|
|
467
|
+
- **Isolated worktree for pre-implementation non-implementation phases (BLOCKING)**: The first pre-implementation non-implementation phase prepare creates a task-key `git worktree`. Pre-implementation non-implementation phases reuse the task-key worktree: `requirements-discovery` → `error-analysis` → `implementation-option-selection` → `implementation-planning` use the same worktree and branch for the same task key. `implementation` does not reuse this task-key worktree; implementation uses a dedicated stage-specific worktree and branch for every stage/run, as described in the next item. The task-key worktree lives at `~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>/` (special characters such as `/` and `:` in segments are normalized to `-`), and the branch is named `<work-category-namespace>/<task-id-segment>` (for example, `feature/dev-9436` or `fix/dev-7311`). The namespace is derived from work_category (`feature`·`improvement`→`feature/`, `bugfix`→`fix/`, `refactor`→`refactor/`, `ops`→`ops/`, unspecified→`task/`). The work_category itself is resolved by `work_categories.resolve_work_category` as **explicit `--work-category` → the classification recorded in `task-manifest.json` → `feature`**, so the `task/` fallback is only reached when a task has no recorded classification at all; a run that omits the flag still inherits the namespace `requirements-discovery` classified. The base ref is the commit selected by the user's `--base-ref` during the first phase's prepare. `~/.okstra/worktrees/registry.json` (guarded by flock) globally manages task-key → path/branch mappings to prevent path and branch collisions during concurrent runs. Configured sync directories are linked from the main worktree as symlinks to provide filesystem continuity across task checkouts (the sync list can be overridden by `worktreeSyncDirs` in `project.json` or the `OKSTRA_WORKTREE_SYNC_DIRS` environment variable; an empty array disables syncing). This sync does not expand the okstra context/write boundary. Provisioning is skipped when the caller is already inside another worktree or project_root is not a Git repository, and the executor works directly from project_root. The worktree is not automatically deleted after a run; it is the authoritative artifact for later phases, PR authoring, and rollback verification. Manual cleanup: `git -C <main-worktree> worktree remove <path>` → `git -C <main-worktree> branch -D <branch>` + remove the registry entry. See the *Task worktree* block in `prompts/profiles/implementation.md` and the *Task worktree (BLOCKING for every task-type)* section in `prompts/lead/okstra-lead-contract.md` for details.
|
|
469
468
|
- **Isolated implementation-stage worktrees (concurrent parallelism)**: The task-key worktree above is the model for `requirements-discovery` through `implementation-planning`. `implementation` tasks use **stage isolation**: **one run = one stage**, and every run receives an isolated worktree at `.../<task-id-segment>/stage-<N>/` (branch `<work-category-namespace>/<task-id-segment>-s<N>`). The registry reserves task keys and **stage keys** (`<task-key>#stage-<N>`) together under flock. The Stage Lifecycle Snapshot reads `done`/`started` entries in `consumers.jsonl`, carry-sidecar backfills, and reserved registry stages together, and removes them from the ready set (occupancy SSOT = registry). Thus, if the user starts two `implementation` runs simultaneously, they proceed on different independent stages without collision. Base selection: independent = common anchor (HEAD fixed at entry to the first stage); single dependency = predecessor's done commit; multiple dependencies = task worktree HEAD only if every predecessor is an ancestor (`git merge-base --is-ancestor`; otherwise `PrepareError`). The cost-aware-design ready-set batch has been retired because each stage needs an isolated branch and reserving two stage keys on one branch creates a branch-uniqueness collision, so it offers no benefit: sequential work uses the next run after a stage is done, and concurrent work uses separate runs, at equivalent cost. Select a stage with `--stage <auto|N>` or the wizard's `stage_pick`. The wizard's `stage_pick` is a multiselect that labels each stage with its state (`mark_done`/`mark_active`/`mark_ready`/`mark_blocked`), topologically sorts the dependency closure of the selection with Kahn's algorithm (`stage_targets.order_stage_closure`), and exports it as the `chain-stages` CSV in render-args. The `okstra-run` SKILL consumes this queue and sequentially executes N single-stage runs in dependency order as an unattended chain, advancing only after checking the Phase 6 `done` row for each stage. This is an orchestration layer only; the **one run = one stage** isolation invariant of the wizard and prepare remains unchanged. Not only worktrees but also **run artifacts (reports, state, worker results, manifests) are isolated per stage under `runs/implementation/stage-<N>/`**, so reports and state from two concurrently running stages do not mix. In contrast, `consumers.jsonl` and the worktree registry remain at the task-type root (`runs/implementation/`) because they are shared coordination sources of truth across stages.
|
|
470
469
|
- **Isolation of single-stage final-verification run artifacts (concurrent parallelism)**: Single-stage `final-verification` (`--stage <N>`) also isolates run artifacts under `runs/final-verification/stage-<N>/`, like implementation, with independent sequences per stage, and appends `-fv-s<N>` to the team name. The `-fv-` delimiter prevents collisions with the same stage's implementation team (`-s<N>`) and with the default whole-task verification name. Thus, final-verification for multiple stages can run concurrently without mixing state, worker results, reports, or teams. It does not create a new worktree; it reuses the corresponding implementation stage worktree from the registry read-only and therefore does not reserve a registry stage key. The `-fv-s<N>` suffix on the `teamName` label is only for audit/display distinction. The actual team is the per-session implicit team (`session-<leadSid>`), so the pre-v2.1.178 hard failure caused by a `TeamCreate` name collision no longer occurs. Whole-task verification (empty stage value) retains the existing flat `runs/final-verification/` structure.
|
|
471
470
|
- **Final-verification target acquisition seam**: `stage_targets.acquire_final_verification_target()` accepts semantic task identity, the approved plan, the normalized Stage Map, and `stage: int | None`; it derives ledger, registry, worktree, Git, and integration facts behind one task-key `worktree_provision_mutex`. Single-stage acquisition is read-only and whole-task acquisition integrates and tears down completed stage worktrees. `run.py` remains the adapter that converts CLI values, builds render-context fields, computes the diff summary, and writes the target snapshot. The container keeps using the locked `resolve_and_integrate_whole_task()` interface; both interfaces share an internal unlocked implementation so the acquisition path never re-enters the non-reentrant task-key mutex.
|
|
@@ -489,7 +488,7 @@ If a bug is discovered in artifacts after a task has completed release-handoff,
|
|
|
489
488
|
- **Entry**: The okstra-run wizard detects reentry into an entry phase for a completed task and confirms it at the `fix_cycle_confirm` step. The CLI uses `--fix-cycle <yes|no>` (when omitted, nothing is recorded). `--fix-cycle yes` opens a cycle only if both guards pass: task type is an entry phase, and the manifest's `workflow.lastCompletedPhase` is `release-handoff`; a violation raises `PrepareError`. A task may have only one open cycle at a time.
|
|
490
489
|
- **Attachment**: While a cycle is open, all runs for the same task attach to it as `run` rows even without a later `--fix-cycle` flag, and `fixCycleId` is recorded in run-manifest and timeline entries.
|
|
491
490
|
- **Closure**: After a release-handoff run attaches to an open cycle and the manifest's `workflow.lastCompletedPhase` becomes `release-handoff`, the next prepare lazily appends a `closed` row.
|
|
492
|
-
- **Consumers (all derived views)**: ① the `## Fix History` section of a later run's analysis-packet ② quotation in Task Continuity Notes from okstra-brief-gen ③ final-report `## 5.10 Fix History`
|
|
491
|
+
- **Consumers (all derived views)**: ① the `## Fix History` section of a later run's analysis-packet ② quotation in Task Continuity Notes from okstra-brief-gen ③ final-report `## 5.10 Fix History` ④ a `fixCycles` summary in task-manifest plus a one-line entry in task-index / task-catalog. All four consumers read only derived views from `fix_cycles.summarize()` / `packet_summary()`.
|
|
493
492
|
|
|
494
493
|
### release-handoff stage-group mode
|
|
495
494
|
|
|
@@ -820,8 +819,7 @@ Checking the following fields first makes it easy to determine the current posit
|
|
|
820
819
|
- `workflow.currentPhaseState`
|
|
821
820
|
- `workflow.phaseStates`
|
|
822
821
|
- `workflow.lastCompletedPhase`
|
|
823
|
-
- `workflow.nextRecommendedPhase` *(object `{phase, status, rationale}`; `status` is `ready` / `pending` / `blocked` / `terminal`.
|
|
824
|
-
- `workflow.nextRecommendedPhaseCorrection` *(present only when Phase 7 validation replaced the authored pointer — `{authored, applied}`, where `authored` is the pointer the lead wrote)*
|
|
822
|
+
- `workflow.nextRecommendedPhase` *(object `{phase, status, rationale}`; `status` is `ready` / `pending` / `blocked` / `terminal`. `phase` is non-empty only under `ready` — a property of the projection, not a constraint the struct enforces: `prepare` lowers a `ready` pointer to `pending` and keeps its `phase`, so a non-`ready` pointer that still names a phase is a normal manifest state. Read `status` to decide whether anything can be launched.)*
|
|
825
823
|
- `workflow.awaitingApproval`
|
|
826
824
|
- `workflow.lastSafeCheckpoint`
|
|
827
825
|
- `phaseOutcome`
|
|
@@ -918,10 +916,10 @@ Errors that occur while provider workers, the report writer, or the Okstra lead
|
|
|
918
916
|
- The `.log` is an execution transcript containing wrapper/CLI output, not the original prompt. `okstra log-report` pairs it with the sibling persisted `.md` prompt and reports `transcriptBytes`, `promptBytes`, and their ratio separately. The compatibility fields `path`, `sizeBytes`, and `totalBytes` continue to mean transcript data, so existing consumers and transcript-size ordering remain stable.
|
|
919
917
|
- **Run-wide cap on the progress copy in the log** (`_LOG_PROGRESS_LINE_CAP` in `scripts/okstra_ctl/worker_runner.py`): workers read their required inputs end-to-end per the Worker Preamble's *Reading rules*, so a single report read can dump 170KB+ into the log and observed sidecars reach 8MB. The runner archives the first 5000 progress lines of the run and replaces the rest with a `[okstra log-cap] N progress line(s) elided` marker, emitted every 500 elided lines so a reader tailing the log can see the run is still producing. The cap is run-wide rather than per-block because a block boundary is a provider's own vocabulary and the shared runner has none; the cost is that a very long run keeps its opening rather than a sample throughout, which the elision notices make visible. **Only the log copy is capped** — never the screen, and never the result stream, because a truncated tool echo costs detail while a truncated answer costs the whole post-mortem.
|
|
920
918
|
- **Progress lands in the worker's own pane, not in a sibling tail pane.** The presentation is passed to the entrypoint as `--presentation live|quiet`; `live` is claimed only by a backend that opened a pane, and the default is `quiet`. Under `live` the runner renders each event into one readable row on the caller's own streams (`→ Bash: …` for a tool call, ` ← ok (N bytes)` for its result, `!! PERMISSION DENIED — <tool>: <reason>` for a refusal); thinking events are dropped. Under `quiet` progress is withheld and only the worker's closing text is printed, which is what a `cli-wrapper` dispatch on a machine with no pane surface needs. `scripts/okstra_ctl/domain/worker_stream.py` owns all three projections (`format_live`, `format_log`, `final_text`) as pure functions over *normalised* events — `Text`, `ToolCall`, `ToolResult`, `Denial`, `Result`. Providers do not share a wire format and this layer may not name one, so each adapter supplies the function that turns its own events into those, declared on `ExecCommand.normalise` beside the stream format it belongs to. Adding a provider whose stream is shaped differently is that one function; a provider that declares `stream-json` without one is failed by `tests/contract/test_provider_execution_contract.py`, which runs the schema each provider claims through its own normaliser and requires rows out.
|
|
921
|
-
- **No okstra pane carries a tag any more, and the tag scan is gone with them.** Two writers disappeared at different times. The wrappers stopped splitting a `tail -F` sibling, so **nothing spawns a trace pane** and `@okstra_trace_run` / `@okstra_status` lost their writer — the operator watches the worker pane itself instead. Then the
|
|
919
|
+
- **No okstra pane carries a tag any more, and the tag scan is gone with them.** Two writers disappeared at different times. The wrappers stopped splitting a `tail -F` sibling, so **nothing spawns a trace pane** and `@okstra_trace_run` / `@okstra_status` lost their writer — the operator watches the worker pane itself instead. Then the pane-tagging dispatch backend was removed, so `@okstra_worker_run` went with it: a worker now gets a cmux surface or a cli-wrapper subprocess, and okstra tags neither. `okstra-trace-cleanup.sh` therefore no longer scans tags at all, and the two modes that existed only for that scan were removed — `--reclaim-completed` (with the `okstra-subagent-reclaim.sh` entry that drove it from `SubagentStop` / `TaskCompleted`) and `--reap` (with its `SessionEnd` entry). Both hooks are gone from `templates/reports/settings.template.json`, which now seeds only the `SessionStart(compact)` reminder.
|
|
922
920
|
- **What cleanup does — okstra's own worker panes**: `okstra team reclaim --project-root <root> --run-manifest <path>` closes the cmux panes this run opened for its workers, and only those whose dispatch has reached a terminal status. The candidates are the `paneId` values recorded in `team-state.workerDispatches[]`, so nothing is discovered by scanning: a title sweep would be worse than nothing, because cmux labels its own agent surfaces with the same glyph the harness uses for a teammate pane and a sweep could close the lead (`team._reclaimable_panes`). A pane the harness opened for its own teammate (`runner: native-session`, which okstra's dispatcher refuses and hands to the host) carries no recorded id and is not okstra's to close. `--dry-run` prints the same `<paneId>\t<kind>` set without closing, which is how the lead counts before it closes. At every worker round boundary — after collecting that round's results and token usage, immediately before the next dispatch — the lead runs the counting pass, reports `PROGRESS: phase-batch-cleanup panes=<n>`, then runs the closing pass. Closing also gives the lead its width back: cmux hands freed width to a neighbour it picks, and that neighbour is not always the lead. See [ADR-0012](../.project-docs/adr/0012-pane-reclaim-scope.md).
|
|
923
921
|
- **Cleanup survives compaction and precedes user gates**: A `SessionStart` hook with matcher `compact` (`okstra-compact-reminder.sh`, seeded in `settings.template.json`) fires after every `/compact` or auto-compaction. It reads `cwd` from the hook's stdin JSON and asks `pane_reclaim.in_flight_run_dirs` for that project's runs that still hold a non-terminal dispatch — the newest `team-state` per run directory decides, because sequences accumulate and an earlier round's `in-progress` rows stay on disk. If one exists it prints a factual reminder naming the run dir and the two-pass `okstra team reclaim` sequence, restoring the boundary/gate obligation that a compaction summary can otherwise drop. The hook never closes a pane itself; the closing stays with the lead, which holds the run manifest. The signal is the run directory rather than `~/.okstra/active.jsonl`: an in-session run is registered `prepared` (because `render-bundle` forces `--render-only`), `prepared` routes to `recent.jsonl` as terminal, and that ledger was measured empty while 310 runs sat in `recent.jsonl` — see [ADR-0011](../.project-docs/adr/0011-in-flight-run-source-of-truth.md). Separately, the lead runs the same two passes immediately before any user approval/clarification/decision gate (`PROGRESS: phase-gate-cleanup panes=<n>`). At every cleanup point the pane close and the task stop (`TaskStop`) are paired — a `TaskStop` alone idles the roster task and closes no pane.
|
|
924
|
-
- **User confirmation at phase end**: At the final step of the run, the lead calls `okstra team teardown --project-root <root> --run-manifest <path> --dry-run` to show the panes this run recorded, then asks once whether to "close all and clean up teammates / keep them." Unlike the round boundary, teardown's set is every recorded pane regardless of status — the run is ending, so none is expected to continue — and it also writes off any dispatch that never reached a terminal status. If approved, the lead runs the same command without `--dry-run`, then
|
|
922
|
+
- **User confirmation at phase end**: At the final step of the run, the lead calls `okstra team teardown --project-root <root> --run-manifest <path> --dry-run` to show the panes this run recorded, then asks once whether to "close all and clean up teammates / keep them." Unlike the round boundary, teardown's set is every recorded pane regardless of status — the run is ending, so none is expected to continue — and it also writes off any dispatch that never reached a terminal status. If approved, the lead runs the same command without `--dry-run`, then sends each completed teammate a `SendMessage` shutdown_request (`TeamDelete` was removed in v2.1.178; the implicit team disappears with the session). A `cli-wrapper` run recorded no pane, so the command safely reports an empty set.
|
|
925
923
|
- Disk accumulation is handled by the `okstra-inspect logs` flow, which offers a read-only inventory and suggests cleanup commands for the user to copy and paste.
|
|
926
924
|
|
|
927
925
|
### Linked-worktree `.git/` write permissions
|
|
@@ -942,7 +940,7 @@ Tokens used in each run are collected from lead/worker session transcripts and w
|
|
|
942
940
|
- CLI execution evidence and token attribution are independent. A wrapper `.status.json` proves `not-started`, `started`, `exited`, `timeout`, or `failed` and supplies the worker's collection window; only a matching transcript with a final token snapshot proves attributable usage. If a wrapper exited successfully but no attributable transcript exists, the worker remains `source: "unavailable"` with `cliExecutionStatus: "exited"` and a reason instead of becoming zero usage or being described as never invoked.
|
|
943
941
|
- Records billable-equivalent token math and USD cost estimates. It applies Anthropic billing ratios (`cache_creation_5m=1.25x`, `cache_creation_1h=2.0x`, `cache_read=0.1x`, `output=5x`). When the transcript provides separate `usage.cache_creation.ephemeral_5m_input_tokens` / `ephemeral_1h_input_tokens` values, they are counted separately.
|
|
944
942
|
- Pricing is centrally managed in `scripts/okstra_token_usage/pricing.py`. Update it when model prices change. Model IDs that fail price matching are exposed to the user in `usageSummary.unmatchedModels`, preventing silent-zero incidents.
|
|
945
|
-
- Project-wide historical usage is exposed through the read-only `okstra usage-report` command (`
|
|
943
|
+
- Project-wide historical usage is exposed through the read-only `okstra usage-report` command (`scripts/okstra_ctl/usage_report.py`) and the `okstra-usage` skill. It defaults to the whole current project's last 30 days and returns run coverage, raw and billable-equivalent tokens, known USD cost, CPU-sum milliseconds, and wall-clock milliseconds grouped by task type. Runs without usable Phase 7 usage are excluded from resource totals and reported through unavailable reason counts rather than treated as zero usage; unmatched model names remain visible when their tokens and time are included but their cost is not. Use `okstra-inspect` for one task's elapsed/context detail and `okstra-rollup` for task-group or project status/report digests.
|
|
946
944
|
- **Incremental scan cache (P6)**: To avoid rescanning session jsonl files, a per-file byte cursor and the extracted usage events before windowing are stored in `$OKSTRA_HOME/cache/token-usage/<transcript-dir>/<sessionId>.json` (`scripts/okstra_token_usage/cursor.py`). The run window (since/until) is reevaluated over events on every invocation, so even if a rerun narrows the window, the total matches a full scan. The cache is derived data; identifier mismatch, truncation, or corruption automatically falls back to a full rescan, and `okstra-token-usage.py --no-cache` forces a bypass.
|
|
947
945
|
- **Phase timeline (P0 instrumentation)**: The collector extracts `PROGRESS: phase-*` checkpoint lines (see "Progress reporting" in prompts/lead/okstra-lead-contract.md) from the lead session jsonl scoped to the run window, and records them in team-state as a `phaseTimeline` block (`{source, phases: [{phase, firstAt, lastAt, markerCount, wallMsToNext}]}`) (`scripts/okstra_token_usage/collect.py :: phase_timeline`). This provides measurement points for per-phase wall-clock time within the run and is consumed by the "Per-run phase breakdown" in the `okstra-inspect` time facet. Runs without markers explicitly report that measurement is unavailable with `phases: []`.
|
|
948
946
|
|
|
@@ -951,13 +949,19 @@ Tokens used in each run are collected from lead/worker session transcripts and w
|
|
|
951
949
|
Entry points that enforce whether phase artifacts may be published:
|
|
952
950
|
|
|
953
951
|
- `validators/validate-workflow.sh` — integrated phase-contract validation.
|
|
954
|
-
- `validators/validate-run.py` —
|
|
952
|
+
- `validators/validate-run.py` — run-level final-report contract, validated from `data.json`. Schema v2 and v3 reports are the only shapes a current run produces, and for those `validate_report` delegates straight to the data.json rules: heading order and human-only fields in the compact reading copy, task deliverables, and cross-field invariants. The Markdown body itself is no longer scanned — the Verdict Card / Index / numbered-section / token-table checks were display-title rules with no consumer (ADR-0024), and they sat behind a `schemaVersion` guard no current run reached. Below the delegation only one branch remains: the report file does not exist. Worker-result audit sidecars and phase-safe execution evidence are still required.
|
|
955
953
|
- `validators/validate-report-views.py` — checks form-control placement in the self-contained HTML view, absence of external URLs, stale source digests, and Response ID parity (`C-*` ↔ HTML).
|
|
956
954
|
- `validators/validate-brief.py` — enforces the brief schema (frontmatter, presence of `Reporter Confirmations`, root parent-id self rule, slug conventions, and so on). `bash validators/validate-brief.sh <brief.md>` is a thin wrapper.
|
|
957
955
|
|
|
958
956
|
Each validator blocks the phase with a `contract-violated` exit code when a contract is breached. Violations are applied when the next phase executes, leaving prior artifacts unchanged.
|
|
959
957
|
|
|
960
|
-
**Blocking failures vs advisories.** `validate-run.py` splits its findings into `validation.failures` and `validation.advisories` (both written to the run manifest and team state, and printed on stdout; advisories also go to stderr one per line). Only `failures` decide `validation.status`, so a run can pass while carrying advisories.
|
|
958
|
+
**Blocking failures vs advisories.** `validate-run.py` splits its findings into `validation.failures` and `validation.advisories` (both written to the run manifest and team state, and printed on stdout; advisories also go to stderr one per line). Only `failures` decide `validation.status`, so a run can pass while carrying advisories.
|
|
959
|
+
|
|
960
|
+
The split is not made by the individual checks. Every check appends to one flat list, and immediately before the status is computed that list is partitioned by an allowlist: `partition()` in [`scripts/okstra_ctl/blocking_checks.py`](../scripts/okstra_ctl/blocking_checks.py), applied at [`validators/validate-run.py`](../validators/validate-run.py) just above `update_validation_metadata`. A failure blocks only if its message contains one of the registered substring fragments; everything else is moved into `validation.advisories`. **Advisory is the default, and a check does not choose its own grade** — a sub-validator that classified its own finding as an error (`worker_audit_ledger.worker_results_audit_findings`, `validate_session_conformance.SessionConformanceResult`) still ends up advisory unless its wording matches a registered fragment.
|
|
961
|
+
|
|
962
|
+
The registration test is a sentence, not a severity feeling: **which consumer outside the validator breaks when this value is wrong?** Registered fragments name one — a renderer with no input (`final-report data.json is missing`), a gate whose result cannot be read (`conformance gate BLOCKING`, `self-mock gate BLOCKING:`), a release path opened on an unverified value (`final-verification report declares`, `` `verdict: FAIL` but `finalVerdict.verdictToken` is ``), a successor stage that cannot be prepared (`implementation run declares stage-`). Where the only reader is the validator itself or the report projection — a cross-reference link, an `Evidence checked:` line, a heading that reads differently — the finding is advisory by construction. ADR-0024 states the same rule from the other side: a display title is never a blocking reason.
|
|
963
|
+
|
|
964
|
+
Fragments are substrings, so an over-broad fragment silently promotes neighbouring checks that happen to share a prefix. Each entry therefore carries a written consumer sentence next to it, and the fragment is chosen from a message string that actually exists. **Enforced:** `tests/contract/test_validate_run_conformance.py::test_every_blocking_fragment_is_producible` reconstructs every string expression in `validators/` and `scripts/okstra_ctl/` from the AST (excluding the allowlist module itself, so the check cannot pass by finding its own copy) and rejects a fragment no validator can emit; `::test_report_bookkeeping_failures_do_not_block` and `::test_a_broken_or_missing_artifact_still_blocks` pin the two sides of the partition.
|
|
961
965
|
|
|
962
966
|
`contractValidation.status=failed` means the run artifact contract failed; it does not necessarily mean the implementation itself is incomplete. An implementation run derives `phaseOutcome.implementation` from `runs/implementation/carry/stage-<N>.json`, `runs/implementation-planning/consumers.jsonl`, and the approved Stage Map together. If every Stage Map stage has pass-grade carry evidence, it can retain the contract failure as audit information while raising `workflow.nextRecommendedPhase.status` to `ready`. It does not choose the phase: the reconciler's fact is that every stage finished, and the destination was already settled by the last stage's report routing, so it leaves `phase` untouched and raises the status only when `phase` is non-empty.
|
|
963
967
|
|
|
@@ -1003,34 +1007,31 @@ Each validator blocks the phase with a `contract-violated` exit code when a cont
|
|
|
1003
1007
|
|
|
1004
1008
|
---
|
|
1005
1009
|
|
|
1006
|
-
##
|
|
1010
|
+
## Run index — operating model / concurrency / environment variables
|
|
1007
1011
|
|
|
1008
1012
|
### Operating model
|
|
1009
1013
|
|
|
1010
1014
|
- At startup, `okstra.sh` invokes the `record_start` hook once to record metadata and the invocation in the indexes.
|
|
1011
|
-
- Finalization
|
|
1012
|
-
-
|
|
1013
|
-
-
|
|
1015
|
+
- **Finalization runs from two live invokers.** `record_start` writes the row when a run begins; nothing in the run's own path writes its end. Two mechanisms close it, and they are different in kind — one *records* a known verdict, the other *infers* one from disk.
|
|
1016
|
+
- [`validators/validate-run.py::record_validation_in_central_index`](../validators/validate-run.py) — fires right after the validator writes team-state / run-manifest / task-manifest, and writes the verdict it just produced onto that one row via [`settle_run_row`](../scripts/okstra_ctl/reconcile.py). The row is matched on `executionManifestPath`, which is unique per run; `runDirRel` is not, because every run-seq of one task-type shares it. Recording rather than inferring is what makes re-validation come out right: `reconcile_recent` skips rows that are already terminal, so a run that failed, got fixed, and passed would otherwise stay `failed` in the index forever.
|
|
1017
|
+
- [`okstra_ctl.run._reconcile_prior_runs`](../scripts/okstra_ctl/run.py) — fires after `record_start` succeeds and sweeps the project's other rows through [`reconcile_home`](../scripts/okstra_ctl/reconcile.py), which infers terminal status from final-report existence plus the run-manifest's `validation.status`. This is the backstop for runs that died before validation and so never reached the validator; those are closed by the 12-hour abort timeout. `reconcile_home` is the only entry point to that inference because `reconcile_active` (promote out of `active.jsonl`) and `reconcile_recent` (refresh a `prepared` row in place) must always run as a pair.
|
|
1018
|
+
- Both are scoped to the run's `projectId`. An unscoped sweep would abort rows belonging to projects the invoking run has nothing to do with. Both are best-effort: a failure prints to stderr and never undoes the prepare or the validation verdict. Neither may be called while holding `central_lock` — both acquire it themselves and `flock` is not reentrant.
|
|
1019
|
+
- Without a live invoker a row stayed `running` forever, and [`run_audit._never_ran`](../scripts/okstra_ctl/run_audit.py) reads such a row as a run that has not produced its report *yet*, skipping the report invariant entirely. `validators/validate-workflow.sh` asserts the settled row end-to-end after its validator step.
|
|
1014
1020
|
- runId format: `<project-id>/<task-group>/<task-id>/<task-type>/r<run-seq>` (for example, `sample-project/payment/fail/error-analysis/r07`). Input supports prefix-substring matching.
|
|
1015
1021
|
|
|
1016
1022
|
### Concurrency control (two-level mutex)
|
|
1017
1023
|
|
|
1018
|
-
|
|
1024
|
+
The run index and the per-task prepare path use two fcntl `LOCK_EX` locks with different scopes. Their responsibilities are separate, so no deadlock occurs even when both are held.
|
|
1019
1025
|
|
|
1020
1026
|
| Lock | Location | Scope | Held during | Purpose |
|
|
1021
1027
|
|---|---|---|---|---|
|
|
1022
|
-
| central lock | `~/.okstra/.lock` | Global (index-wide) | Writes to `active.jsonl`/`recent.jsonl`/`projects/<id>/index.jsonl` by `record_start`;
|
|
1023
|
-
| task lock | `~/.okstra/.locks/<
|
|
1024
|
-
|
|
1025
|
-
Acquisition order is always `task lock` → `central lock` (ctl rerun), or `central lock` alone (record_start, reconcile). The reverse order never occurs.
|
|
1028
|
+
| central lock | `~/.okstra/.lock` | Global (index-wide) | Writes to `active.jsonl`/`recent.jsonl`/`projects/<id>/index.jsonl` by `record_start`; reservation writes | Serializes read-modify-write operations on index jsonl files. Prevents a concurrent record_start append and a reconcile rotation from leaking into each other ([locks.central_lock](../scripts/okstra_ctl/locks.py)). |
|
|
1029
|
+
| task lock | `~/.okstra/.locks/<task-key>.lock` | Per task-key mutex | Sequence prediction and run-context writes during prepare | Prevents simultaneous prepares of the same task from receiving the same run sequence and colliding on manifests/directories. Acquired outside the central lock, so different tasks do not block each other ([run_context.task_mutex](../scripts/okstra_ctl/run_context.py)). |
|
|
1026
1030
|
|
|
1027
|
-
|
|
1031
|
+
Acquisition order is always `task lock` → `central lock` (prepare), or `central lock` alone (record_start). The reverse order never occurs.
|
|
1028
1032
|
|
|
1029
1033
|
### Environment variables
|
|
1030
1034
|
|
|
1031
1035
|
- `OKSTRA_HOME`: overrides the central directory location (default `~/.okstra`).
|
|
1032
|
-
- `OKSTRA_CTL_MAX_SPAWN`: default threshold for concurrent rerun spawns.
|
|
1033
|
-
- `OKSTRA_CTL_SKIP_BACKFILL=1`: skips automatic backfill on first invocation.
|
|
1034
|
-
- `OKSTRA_CTL_SKIP_RECONCILE=1`: skips lazy reconciliation (for tests/debugging).
|
|
1035
1036
|
- `OKSTRA_SKIP_INSTALL_CHECK=1`: skips installation-asset checks in `verify_installation` (for tests; workspace-existence validation remains enabled).
|
|
1036
|
-
- `OKSTRA_RUN_SEQ_OVERRIDE`: forces the run sequence used by okstra.sh
|
|
1037
|
+
- `OKSTRA_RUN_SEQ_OVERRIDE`: forces the run sequence used by okstra.sh (test hooks only).
|