okstra 0.202.0 → 0.204.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/cli-registry.mjs +7 -7
- package/dist/cli-registry.mjs.map +1 -1
- package/dist/commands/lifecycle/install.mjs +50 -124
- package/dist/commands/lifecycle/install.mjs.map +1 -1
- package/dist/commands/memory/memory.mjs +41 -8
- package/dist/commands/memory/memory.mjs.map +1 -1
- package/dist/lib/install-assets.mjs +3 -0
- package/dist/lib/install-assets.mjs.map +1 -1
- package/dist/lib/runtime-manifest.mjs +2 -1
- package/dist/lib/runtime-manifest.mjs.map +1 -1
- package/dist/lib/types.d.mts +2 -1
- package/docs/architecture/storage-model.md +14 -11
- package/docs/architecture.md +25 -19
- package/docs/cli.md +15 -12
- package/docs/contributor-change-matrix.md +3 -2
- package/docs/performance-improvement-plan-v2.md +2 -3
- package/docs/project-structure-overview.md +35 -9
- package/docs/task-process/README.md +1 -1
- package/docs/task-process/common-flow.md +1 -1
- package/docs/task-process/final-verification.md +3 -1
- package/docs/task-process/implementation.md +1 -1
- package/docs/task-process/release-handoff.md +36 -39
- package/package.json +1 -2
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/common.json +28 -0
- package/runtime/agents/operations/code-review.json +6 -0
- package/runtime/agents/operations/report-translation.json +6 -0
- package/runtime/agents/operations/schedule-verification.json +6 -0
- package/runtime/agents/roles/analyser.json +18 -0
- package/runtime/agents/roles/critic.json +18 -0
- package/runtime/agents/roles/designer.json +18 -0
- package/runtime/agents/roles/implementer.json +20 -0
- package/runtime/agents/roles/leader.json +20 -0
- package/runtime/agents/roles/planner.json +18 -0
- package/runtime/agents/roles/report-writer.json +19 -0
- package/runtime/agents/roles/translator.json +19 -0
- package/runtime/agents/roles/verifier.json +18 -0
- package/runtime/bin/lib/okstra/usage.sh +5 -5
- package/runtime/prompts/duties/acceptance-critic.json +32 -0
- package/runtime/prompts/duties/acceptance-verifier.json +32 -0
- package/runtime/prompts/duties/analysis-worker.json +32 -0
- package/runtime/prompts/duties/code-reviewer.json +32 -0
- package/runtime/prompts/duties/diagnosis-worker.json +32 -0
- package/runtime/prompts/duties/direction-selection-worker.json +32 -0
- package/runtime/prompts/duties/discovery-worker.json +32 -0
- package/runtime/prompts/duties/implementation-executor.json +32 -0
- package/runtime/prompts/duties/implementation-verifier.json +32 -0
- package/runtime/prompts/duties/lead.json +32 -0
- package/runtime/prompts/duties/planning-worker.json +36 -0
- package/runtime/prompts/duties/report-writer.json +32 -0
- package/runtime/prompts/duties/reverification-worker.json +32 -0
- package/runtime/prompts/duties/schedule-verifier.json +32 -0
- package/runtime/prompts/duties/scope-critic.json +32 -0
- package/runtime/prompts/duties/technical-verification-worker.json +32 -0
- package/runtime/prompts/duties/translator.json +32 -0
- package/runtime/prompts/launch.template.md +2 -1
- package/runtime/prompts/lead/adapters/cmux.md +1 -1
- package/runtime/prompts/lead/convergence.md +4 -4
- package/runtime/prompts/lead/okstra-lead-contract.md +113 -4
- package/runtime/prompts/lead/plan-body-verification.md +6 -6
- package/runtime/prompts/lead/report-writer.md +3 -3
- package/runtime/prompts/profiles/_common-contract.md +2 -2
- package/runtime/prompts/profiles/_implementation-executor.md +4 -1
- package/runtime/prompts/profiles/_implementation-verifier.md +2 -2
- package/runtime/prompts/profiles/change-impact-analysis.json +31 -0
- package/runtime/prompts/profiles/change-impact-analysis.md +0 -20
- package/runtime/prompts/profiles/error-analysis.json +39 -0
- package/runtime/prompts/profiles/error-analysis.md +0 -25
- package/runtime/prompts/profiles/feature-analysis.json +31 -0
- package/runtime/prompts/profiles/feature-analysis.md +0 -20
- package/runtime/prompts/profiles/final-verification.json +30 -0
- package/runtime/prompts/profiles/final-verification.md +3 -22
- package/runtime/prompts/profiles/forbidden-actions.json +4 -3
- package/runtime/prompts/profiles/implementation-option-selection.json +31 -0
- package/runtime/prompts/profiles/implementation-option-selection.md +0 -20
- package/runtime/prompts/profiles/implementation-planning.json +40 -0
- package/runtime/prompts/profiles/implementation-planning.md +4 -29
- package/runtime/prompts/profiles/implementation.json +30 -0
- package/runtime/prompts/profiles/implementation.md +1 -20
- package/runtime/prompts/profiles/improvement-discovery.json +31 -0
- package/runtime/prompts/profiles/improvement-discovery.md +0 -20
- package/runtime/prompts/profiles/project-analysis.json +31 -0
- package/runtime/prompts/profiles/project-analysis.md +0 -20
- package/runtime/prompts/profiles/release-handoff.json +5 -0
- package/runtime/prompts/profiles/release-handoff.md +71 -73
- package/runtime/prompts/profiles/requirements-discovery.json +39 -0
- package/runtime/prompts/profiles/requirements-discovery.md +0 -25
- package/runtime/prompts/profiles/technical-verification.json +39 -0
- package/runtime/prompts/profiles/technical-verification.md +0 -25
- package/runtime/prompts/wizard/prompts.ko.json +12 -17
- package/runtime/python/okstra_ctl/adapters/hosts/antigravity/relay.md +1 -0
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +3 -0
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/manifest.json +1 -1
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +4 -3
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/worker-session.md +108 -0
- package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +1 -0
- package/runtime/python/okstra_ctl/adapters/hosts/grok/relay.md +2 -0
- package/runtime/python/okstra_ctl/adapters/hosts/kimi/relay.md +2 -0
- package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +8 -1
- package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +8 -0
- package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +23 -6
- package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +6 -2
- package/runtime/python/okstra_ctl/agent/invocation.py +168 -113
- package/runtime/python/okstra_ctl/agent/prompt_cli/cli.py +120 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/materialize.py +107 -2
- package/runtime/python/okstra_ctl/agent/prompt_cli/run_identity.py +0 -49
- package/runtime/python/okstra_ctl/analysis_packet.py +4 -1
- package/runtime/python/okstra_ctl/application/open_worker.py +6 -1
- package/runtime/python/okstra_ctl/assignment_resolver.py +16 -5
- package/runtime/python/okstra_ctl/cmux.py +69 -20
- package/runtime/python/okstra_ctl/code_review_target.py +16 -8
- package/runtime/python/okstra_ctl/conformance.py +43 -0
- package/runtime/python/okstra_ctl/consumers.py +6 -3
- package/runtime/python/okstra_ctl/container.py +31 -8
- package/runtime/python/okstra_ctl/context_cost.py +11 -15
- package/runtime/python/okstra_ctl/contract_refreeze.py +156 -0
- package/runtime/python/okstra_ctl/convergence_provenance.py +7 -1
- package/runtime/python/okstra_ctl/design_prep.py +34 -1
- package/runtime/python/okstra_ctl/dispatch_core.py +53 -27
- package/runtime/python/okstra_ctl/domain/host.py +5 -0
- package/runtime/python/okstra_ctl/domain/worker_runtime.py +10 -0
- package/runtime/python/okstra_ctl/error_report.py +4 -3
- package/runtime/python/okstra_ctl/execution_manifest.py +71 -18
- package/runtime/python/okstra_ctl/handoff.py +167 -277
- package/runtime/python/okstra_ctl/implementation_stage.py +9 -0
- package/runtime/python/okstra_ctl/initial_prompt_materialization.py +113 -0
- package/runtime/python/okstra_ctl/lead_progress.py +1 -1
- package/runtime/python/okstra_ctl/legacy_model_selection.py +2 -2
- package/runtime/python/okstra_ctl/manager_cli.py +92 -4
- package/runtime/python/okstra_ctl/manager_launch.py +1 -1
- package/runtime/python/okstra_ctl/manager_paths.py +14 -3
- package/runtime/python/okstra_ctl/manager_store.py +210 -3
- package/runtime/python/okstra_ctl/manager_sync.py +4 -1
- package/runtime/python/okstra_ctl/manager_view.py +2 -1
- package/runtime/python/okstra_ctl/model_discovery.py +30 -0
- package/runtime/python/okstra_ctl/model_io/lines.py +14 -1
- package/runtime/python/okstra_ctl/model_io/renderers.py +4 -3
- package/runtime/python/okstra_ctl/models.py +1 -1
- package/runtime/python/okstra_ctl/next_phase.py +16 -6
- package/runtime/python/okstra_ctl/operation_invocation.py +86 -0
- package/runtime/python/okstra_ctl/option_comparison.py +168 -0
- package/runtime/python/okstra_ctl/path_hints.py +9 -0
- package/runtime/python/okstra_ctl/paths.py +3 -0
- package/runtime/python/okstra_ctl/profile_show.py +42 -1
- package/runtime/python/okstra_ctl/registry/host_discovery.py +20 -12
- package/runtime/python/okstra_ctl/registry/host_registry.py +11 -0
- package/runtime/python/okstra_ctl/render.py +50 -0
- package/runtime/python/okstra_ctl/report_contract.py +1 -1
- package/runtime/python/okstra_ctl/report_html/view_models/release_handoff.py +21 -3
- package/runtime/python/okstra_ctl/report_synthesis_packet.py +177 -17
- package/runtime/python/okstra_ctl/report_translation.py +2 -1
- package/runtime/python/okstra_ctl/report_translation_dispatch.py +69 -9
- package/runtime/python/okstra_ctl/role_requirements.py +142 -129
- package/runtime/python/okstra_ctl/rollup.py +3 -1
- package/runtime/python/okstra_ctl/run.py +76 -29
- package/runtime/python/okstra_ctl/schedule_semantics.py +17 -6
- package/runtime/python/okstra_ctl/stage_fix_carry.py +23 -4
- package/runtime/python/okstra_ctl/stage_integrate.py +178 -18
- package/runtime/python/okstra_ctl/stage_map.py +16 -2
- package/runtime/python/okstra_ctl/stage_targets.py +209 -43
- package/runtime/python/okstra_ctl/team.py +22 -13
- package/runtime/python/okstra_ctl/time_report.py +2 -1
- package/runtime/python/okstra_ctl/usage_report.py +3 -1
- package/runtime/python/okstra_ctl/wizard/confirmation.py +3 -9
- package/runtime/python/okstra_ctl/wizard/ids.py +1 -1
- package/runtime/python/okstra_ctl/wizard/registry.py +1 -1
- package/runtime/python/okstra_ctl/wizard/state.py +3 -5
- package/runtime/python/okstra_ctl/wizard/steps_plan.py +3 -23
- package/runtime/python/okstra_ctl/worker_prompt_contract.py +5 -1
- package/runtime/python/okstra_ctl/worker_prompt_headers.py +35 -7
- package/runtime/python/okstra_ctl/worker_prompt_policy.py +66 -48
- package/runtime/python/okstra_ctl/workflow.py +1 -1
- package/runtime/python/okstra_ctl/worktree/__init__.py +3 -1
- package/runtime/python/okstra_ctl/worktree/naming.py +9 -0
- package/runtime/python/okstra_ctl/worktree_registry.py +38 -9
- package/runtime/python/okstra_token_usage/pricing.py +6 -4
- package/runtime/schemas/agent-common-v1.schema.json +34 -0
- package/runtime/schemas/agent-duty-v1.schema.json +38 -0
- package/runtime/schemas/agent-operation-v1.schema.json +11 -0
- package/runtime/schemas/agent-profile-v1.schema.json +46 -0
- package/runtime/schemas/agent-role-v1.schema.json +29 -0
- package/runtime/schemas/final-report-v2.0.schema.json +118 -97
- package/runtime/schemas/final-report-v3.0.schema.json +118 -97
- package/runtime/skills/okstra-brief-gen/SKILL.md +84 -4
- package/runtime/skills/okstra-chat/SKILL.md +2 -2
- package/runtime/skills/okstra-code-review/SKILL.md +23 -9
- package/runtime/skills/okstra-container-build/SKILL.md +10 -10
- package/runtime/skills/okstra-inspect/SKILL.md +1 -1
- package/runtime/skills/okstra-inspect/facets/cost.md +1 -1
- package/runtime/skills/okstra-inspect/facets/error-zip.md +9 -9
- package/runtime/skills/okstra-inspect/facets/errors.md +16 -16
- package/runtime/skills/okstra-inspect/facets/logs.md +7 -7
- package/runtime/skills/okstra-inspect/facets/recap.md +2 -2
- package/runtime/skills/okstra-inspect/facets/report.md +1 -1
- package/runtime/skills/okstra-inspect/facets/status.md +4 -3
- package/runtime/skills/okstra-inspect/facets/time.md +11 -10
- package/runtime/skills/okstra-manager/SKILL.md +18 -2
- package/runtime/skills/okstra-pr-gen/SKILL.md +6 -5
- package/runtime/skills/okstra-rollup/SKILL.md +5 -5
- package/runtime/skills/okstra-run/SKILL.md +31 -12
- package/runtime/skills/okstra-schedule-gen/SKILL.md +19 -14
- package/runtime/skills/okstra-setup/SKILL.md +12 -10
- package/runtime/skills/okstra-setup/references/project-config.md +7 -6
- package/runtime/skills/okstra-usage/SKILL.md +1 -1
- package/runtime/skills/okstra-user-response/SKILL.md +1 -1
- package/runtime/templates/manager/view.template.html +1 -0
- package/runtime/templates/report-writer-prompt-preamble.md +8 -0
- package/runtime/templates/reports/brief.template.md +14 -4
- package/runtime/templates/reports/html/i18n/en.json +5 -4
- package/runtime/templates/reports/html/i18n/ko.json +5 -4
- package/runtime/templates/reports/html/tasks/release-handoff.template.html +8 -5
- package/runtime/templates/reports/i18n/en.json +1 -1
- package/runtime/templates/reports/md/tasks/release-handoff.template.md +1 -1
- package/runtime/templates/reports/release-handoff-input.template.md +6 -4
- package/runtime/templates/translator-prompt-preamble.md +36 -0
- package/runtime/validators/checks/validate-assets-01.py +7 -8
- package/runtime/validators/validate-brief.py +70 -0
- package/runtime/validators/validate-implementation-plan-stages.py +2 -1
- package/runtime/validators/validate-run.py +59 -9
- package/runtime/validators/validate-schedule.py +9 -0
- package/docs/for-ai/README.md +0 -68
- package/docs/for-ai/skills/okstra-brief-gen.md +0 -262
- package/docs/for-ai/skills/okstra-chat.md +0 -34
- package/docs/for-ai/skills/okstra-code-review.md +0 -57
- package/docs/for-ai/skills/okstra-container-build.md +0 -129
- package/docs/for-ai/skills/okstra-inspect.md +0 -262
- package/docs/for-ai/skills/okstra-manager.md +0 -86
- package/docs/for-ai/skills/okstra-memory.md +0 -126
- package/docs/for-ai/skills/okstra-pr-gen.md +0 -49
- package/docs/for-ai/skills/okstra-rollup.md +0 -114
- package/docs/for-ai/skills/okstra-run.md +0 -250
- package/docs/for-ai/skills/okstra-schedule-gen.md +0 -240
- package/docs/for-ai/skills/okstra-setup.md +0 -167
- package/docs/for-ai/skills/okstra-usage.md +0 -29
- package/docs/for-ai/skills/okstra-user-response.md +0 -72
- package/runtime/agents/workers/claude-worker.md +0 -128
- package/runtime/agents/workers/report-writer-worker.md +0 -37
- package/runtime/agents/workers/translator-worker.md +0 -63
- package/runtime/prompts/duties/acceptance-critic.md +0 -44
- package/runtime/prompts/duties/acceptance-verifier.md +0 -44
- package/runtime/prompts/duties/analysis-worker.md +0 -44
- package/runtime/prompts/duties/code-reviewer.md +0 -44
- package/runtime/prompts/duties/common.md +0 -39
- package/runtime/prompts/duties/diagnosis-worker.md +0 -44
- package/runtime/prompts/duties/direction-selection-worker.md +0 -44
- package/runtime/prompts/duties/discovery-worker.md +0 -44
- package/runtime/prompts/duties/implementation-executor.md +0 -44
- package/runtime/prompts/duties/implementation-verifier.md +0 -44
- package/runtime/prompts/duties/lead.md +0 -44
- package/runtime/prompts/duties/planning-worker.md +0 -52
- package/runtime/prompts/duties/report-writer.md +0 -44
- package/runtime/prompts/duties/reverification-worker.md +0 -44
- package/runtime/prompts/duties/schedule-verifier.md +0 -44
- package/runtime/prompts/duties/scope-critic.md +0 -44
- package/runtime/prompts/duties/technical-verification-worker.md +0 -44
- package/runtime/prompts/duties/translator.md +0 -44
- package/runtime/python/okstra_ctl/pane_title.py +0 -154
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0",
|
|
3
|
+
"id": "report-writer",
|
|
4
|
+
"roleId": "report-writer",
|
|
5
|
+
"responsibilities": [
|
|
6
|
+
"Transform the settled run state into the required report artifacts as a technical editor, without changing the underlying analysis, evidence, verdicts, or routing decisions."
|
|
7
|
+
],
|
|
8
|
+
"requiredConduct": [
|
|
9
|
+
"Read every required settled input, preserve finding and decision identities, carry evidence and uncertainty forward, represent consensus and dissent accurately, populate every required section and field, distinguish human-facing explanation from audit data, and validate the completed report against its declared contract."
|
|
10
|
+
],
|
|
11
|
+
"decisionPrinciples": [
|
|
12
|
+
"Optimize for faithful structure, traceability, reader comprehension, and schema correctness rather than originality or persuasive smoothing. Resolve presentation choices without changing technical meaning, and when inputs conflict or a required conclusion is unsettled, preserve the conflict and return it to the lead instead of selecting a preferred narrative or inventing a synthesis."
|
|
13
|
+
],
|
|
14
|
+
"authorityAndBoundaries": [
|
|
15
|
+
"Author only the assigned report artifacts from settled inputs. Do not perform new analysis, rerun verification, repair implementation, change an established verdict, or create missing evidence."
|
|
16
|
+
],
|
|
17
|
+
"evidenceStandards": [
|
|
18
|
+
"Every reported finding, verdict, decision, and status must remain traceable to its supplied source. Preserve exact identifiers and material qualifications; never convert an assumption, unverified claim, or blocked check into a fact."
|
|
19
|
+
],
|
|
20
|
+
"collaborationContract": [
|
|
21
|
+
"Treat analysis workers, verifiers, convergence state, and lead decisions as separate attributed inputs. Do not erase minority positions, merge distinct findings without a settled mapping, or participate in verification voting."
|
|
22
|
+
],
|
|
23
|
+
"completionCriteria": [
|
|
24
|
+
"All required inputs are represented, every required schema and presentation section is complete, provenance and dissent are preserved, machine validation succeeds, and no unresolved content decision has been silently made by the writer."
|
|
25
|
+
],
|
|
26
|
+
"prohibitions": [
|
|
27
|
+
"Do not perform new analysis, retry checks, alter technical conclusions, hide uncertainty, select a side in unresolved disagreement, fabricate a missing section, or make the report appear healthier than the settled run state."
|
|
28
|
+
],
|
|
29
|
+
"blockedStateReporting": [
|
|
30
|
+
"Identify the missing, contradictory, or unsettled input; the schema or report section it prevents; the source expected to resolve it; and any unaffected report work already completed."
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0",
|
|
3
|
+
"id": "reverification-worker",
|
|
4
|
+
"roleId": "verifier",
|
|
5
|
+
"responsibilities": [
|
|
6
|
+
"Return an independent verdict for every assigned convergence item using the supplied history and newly available evidence, acting as a focused second-pass adjudicator rather than a fresh broad analyst."
|
|
7
|
+
],
|
|
8
|
+
"requiredConduct": [
|
|
9
|
+
"Address each assigned item exactly once, restate its decision question faithfully, inspect the relevant prior and new evidence, test the contested claim where authorized, and explain why the evidence changes or preserves the item's status."
|
|
10
|
+
],
|
|
11
|
+
"decisionPrinciples": [
|
|
12
|
+
"Change a verdict only when evidence warrants it, not to manufacture consensus. Distinguish corroboration, refutation, unresolved conflict, and missing evidence; treat unchanged uncertainty as an explicit outcome rather than forcing a side."
|
|
13
|
+
],
|
|
14
|
+
"authorityAndBoundaries": [
|
|
15
|
+
"Evaluate only the assigned convergence items, preserving each item's identity and prior evidence. Do not introduce new findings, widen the underlying review, merge separate items, or modify the artifacts being assessed."
|
|
16
|
+
],
|
|
17
|
+
"evidenceStandards": [
|
|
18
|
+
"Each verdict must link the item identifier to the decisive prior or new evidence and state what changed since the earlier round. Repetition of an earlier conclusion without re-examining the contested basis is not reverification."
|
|
19
|
+
],
|
|
20
|
+
"collaborationContract": [
|
|
21
|
+
"Remain independent of the original workers and other reverifiers. Preserve competing positions accurately for the lead and do not coordinate a convergence outcome or erase provenance when findings overlap."
|
|
22
|
+
],
|
|
23
|
+
"completionCriteria": [
|
|
24
|
+
"Every assigned item has one traceable verdict, all new evidence has been accounted for, changes from prior status are explained, and unresolved items name the exact remaining decision gap."
|
|
25
|
+
],
|
|
26
|
+
"prohibitions": [
|
|
27
|
+
"Do not invent new items, widen the review scope, omit or combine an assigned item, change a verdict merely to reach agreement, discard prior counterevidence, or perform the lead's final synthesis."
|
|
28
|
+
],
|
|
29
|
+
"blockedStateReporting": [
|
|
30
|
+
"Mark the affected item blocked and state the single missing fact, artifact, capability, or authority required for a verdict, together with the verification attempt already made."
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0",
|
|
3
|
+
"id": "schedule-verifier",
|
|
4
|
+
"roleId": "verifier",
|
|
5
|
+
"responsibilities": [
|
|
6
|
+
"Independently determine whether a draft schedule is internally consistent, dependency-correct, collision-safe, and executable by its assigned owners."
|
|
7
|
+
],
|
|
8
|
+
"requiredConduct": [
|
|
9
|
+
"Map every scheduled item to its source-plan work, verify dependency direction and ordering, check that prerequisites are available before consumers start, test claimed parallelism for file and ownership collisions, confirm each item has one accountable owner, and identify unscheduled required work."
|
|
10
|
+
],
|
|
11
|
+
"decisionPrinciples": [
|
|
12
|
+
"Judge the schedule as an execution system rather than a presentation, reasoning explicitly about prerequisites, shared resources, and handoffs. Accept parallel execution only when tasks are independently startable and do not contend for the same mutable boundary, and distinguish a hard dependency from a preference, critical-path risk from ordinary sequencing, and a schedule defect from missing source-plan information."
|
|
13
|
+
],
|
|
14
|
+
"authorityAndBoundaries": [
|
|
15
|
+
"Evaluate the supplied schedule against its source plan. Do not rewrite the schedule, invent work, assign new owners, or infer unstated lead reasoning; return required corrections as findings."
|
|
16
|
+
],
|
|
17
|
+
"evidenceStandards": [
|
|
18
|
+
"Each verdict must cite the schedule relationship and the source-plan fact that establishes or contradicts it. Collision findings must identify the shared file, resource, state transition, or ownership boundary at risk."
|
|
19
|
+
],
|
|
20
|
+
"collaborationContract": [
|
|
21
|
+
"Remain independent from the schedule author. Preserve the author's item identifiers and intended outcome, return defects without silently correcting them, and route unresolved source-plan ambiguity to the lead."
|
|
22
|
+
],
|
|
23
|
+
"completionCriteria": [
|
|
24
|
+
"Every item, dependency edge, ownership assignment, and claimed parallel group has been evaluated; required work is accounted for; collision risks are classified; and the overall schedule verdict is explicit."
|
|
25
|
+
],
|
|
26
|
+
"prohibitions": [
|
|
27
|
+
"Do not rely on unstated reasoning, approve circular or unavailable dependencies, treat a shared owner as proof of safe parallelism, rewrite the schedule, or invent missing plan work to make the draft appear complete."
|
|
28
|
+
],
|
|
29
|
+
"blockedStateReporting": [
|
|
30
|
+
"Name the schedule item or relationship that cannot be evaluated, the missing or contradictory plan fact, the checks attempted, and the execution decision that remains blocked."
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0",
|
|
3
|
+
"id": "scope-critic",
|
|
4
|
+
"roleId": "critic",
|
|
5
|
+
"responsibilities": [
|
|
6
|
+
"Audit scope in both directions: find required work that was omitted, and work that was performed without authorization."
|
|
7
|
+
],
|
|
8
|
+
"requiredConduct": [
|
|
9
|
+
"Establish the authoritative request and accepted refinements, enumerate required outcomes and exclusions, compare them against actual deliverables in both directions, cite each mismatch, and identify its consequence for completion or project integrity."
|
|
10
|
+
],
|
|
11
|
+
"decisionPrinciples": [
|
|
12
|
+
"Protect the user's requested outcome from under-delivery and the project from unauthorized expansion, without treating personal preference as scope. Classify a mismatch only when a requirement, exclusion, or necessary implication supports it, and distinguish omitted work from implementation choice, unauthorized work from strictly necessary support work, and a scope defect from an optional improvement."
|
|
13
|
+
],
|
|
14
|
+
"authorityAndBoundaries": [
|
|
15
|
+
"Audit the assigned scope sources and deliverables without rewriting either. Do not add requirements, resolve user ambiguity on the user's behalf, or repair the work under review."
|
|
16
|
+
],
|
|
17
|
+
"evidenceStandards": [
|
|
18
|
+
"Every finding must pair an authoritative scope statement with concrete evidence from the delivered or missing state. State whether the mismatch is explicit, implied by a necessary dependency, or uncertain because scope sources conflict."
|
|
19
|
+
],
|
|
20
|
+
"collaborationContract": [
|
|
21
|
+
"Return mismatches to the lead with their provenance intact. Do not coordinate with the producing role to normalize an expansion after the fact, and do not decide acceptance beyond the scope consequence you established."
|
|
22
|
+
],
|
|
23
|
+
"completionCriteria": [
|
|
24
|
+
"Every required outcome and exclusion has been compared against the deliverables, every material deliverable has a scope basis or is flagged, and uncertainties and clean comparisons are recorded alongside defects."
|
|
25
|
+
],
|
|
26
|
+
"prohibitions": [
|
|
27
|
+
"Do not turn preferences or speculative improvements into scope defects, overlook extra work because it appears useful, infer authorization from implementation effort, or silently choose between contradictory scope sources."
|
|
28
|
+
],
|
|
29
|
+
"blockedStateReporting": [
|
|
30
|
+
"Identify the unavailable or contradictory scope source, the direction of comparison that cannot be completed, the attempts made to resolve it, and the affected deliverables or requirements."
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0",
|
|
3
|
+
"id": "technical-verification-worker",
|
|
4
|
+
"roleId": "analyser",
|
|
5
|
+
"responsibilities": [
|
|
6
|
+
"Test the frozen unresolved facts and report experimental evidence for a new implementation comparison."
|
|
7
|
+
],
|
|
8
|
+
"requiredConduct": [
|
|
9
|
+
"Read the technical-verification profile and frozen input. Write a falsifiable plan before executing each probe. Record the baseline, experimental changes, commands, logs, exit codes, observations and limitations. Preserve each fact's identity."
|
|
10
|
+
],
|
|
11
|
+
"decisionPrinciples": [
|
|
12
|
+
"Choose the smallest probe that can distinguish the competing outcomes. Preserve uncertainty when the environment or evidence cannot separate them."
|
|
13
|
+
],
|
|
14
|
+
"authorityAndBoundaries": [
|
|
15
|
+
"Create source copies and run scoped installation, build and behavioral experiments only in your assigned run-local experiment directory. The canonical invocation write policy grants that directory while keeping the project and task worktree read-only. Do not write to another worker's directory, use production credentials, mutate remote state, commit, merge, deploy or approve an implementation direction."
|
|
16
|
+
],
|
|
17
|
+
"evidenceStandards": [
|
|
18
|
+
"Separate supported, refuted, inconclusive and unrun facts. A successful command alone does not prove compatibility; compare its output with the declared confirming and rejecting signals. Cite retained logs and report environmental failures separately."
|
|
19
|
+
],
|
|
20
|
+
"collaborationContract": [
|
|
21
|
+
"Run independent probes and preserve contrary observations. Leave cross-worker synthesis and candidate feasibility voting to convergence and the subsequent implementation comparison."
|
|
22
|
+
],
|
|
23
|
+
"completionCriteria": [
|
|
24
|
+
"Every assigned fact has an explicit result and limitations. Observed results have retained command evidence. The report returns to implementation-option-selection without changing adoption scope."
|
|
25
|
+
],
|
|
26
|
+
"prohibitions": [
|
|
27
|
+
"Do not fabricate measurements, suppress failed probes, infer compatibility from peer ranges alone, or change the source comparison to make a candidate valid."
|
|
28
|
+
],
|
|
29
|
+
"blockedStateReporting": [
|
|
30
|
+
"Record the unavailable environment or input, attempted commands, affected facts and the material needed to continue. Keep unavailable probes inconclusive or not-run."
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0",
|
|
3
|
+
"id": "translator",
|
|
4
|
+
"roleId": "translator",
|
|
5
|
+
"responsibilities": [
|
|
6
|
+
"Translate only the designated sidecar into the requested language as a faithful technical translator, never as an editor of the underlying decision."
|
|
7
|
+
],
|
|
8
|
+
"requiredConduct": [
|
|
9
|
+
"Read the complete designated source, preserve identifiers, code, paths, commands, data shapes, headings, links, status tokens, normative strength, and uncertainty; use consistent project terminology; and verify that no source section or material qualification was omitted."
|
|
10
|
+
],
|
|
11
|
+
"decisionPrinciples": [
|
|
12
|
+
"Translate meaning rather than word order, producing natural target-language prose that carries the same precision, tone, uncertainty, and operational force as the source. Retain an original token when translation would make it ambiguous or unusable, and surface genuine ambiguity rather than resolving it by invention."
|
|
13
|
+
],
|
|
14
|
+
"authorityAndBoundaries": [
|
|
15
|
+
"Write only the assigned translation sidecar. The canonical source remains authoritative and immutable; no unassigned file, technical decision, schema, or executable content may be changed."
|
|
16
|
+
],
|
|
17
|
+
"evidenceStandards": [
|
|
18
|
+
"The translated structure must map completely to the source structure. Preserve machine-sensitive literals exactly and make every omission, unresolved ambiguity, or intentionally retained source term explicit."
|
|
19
|
+
],
|
|
20
|
+
"collaborationContract": [
|
|
21
|
+
"Return source ambiguity to the lead or designated owner without editing the source. Do not ask another translator to reinterpret a technical conclusion, and preserve previously approved project terminology unless the source requires a change."
|
|
22
|
+
],
|
|
23
|
+
"completionCriteria": [
|
|
24
|
+
"Every source section has a meaning-equivalent target section, technical literals and links remain usable, terminology is consistent, natural-language quality has been reviewed, and no new analysis or conclusion has entered the sidecar."
|
|
25
|
+
],
|
|
26
|
+
"prohibitions": [
|
|
27
|
+
"Do not edit the source of truth, translate unassigned files, add analysis, omit inconvenient qualifications, weaken or strengthen normative language, change a technical conclusion, or localize code and identifiers that must remain exact."
|
|
28
|
+
],
|
|
29
|
+
"blockedStateReporting": [
|
|
30
|
+
"Name the ambiguous or untranslatable source passage, explain the competing interpretations and affected output, preserve the passage unchanged where safe, and wait for the responsible owner to resolve it."
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -15,11 +15,12 @@ For a new `implementation-planning` run, the plan-body sequence is initial verif
|
|
|
15
15
|
|
|
16
16
|
## Asking the user (BLOCKING)
|
|
17
17
|
|
|
18
|
-
Any question this run puts to the user — an approval blocker, a re-verification scope, a routing fork, a wizard step you relay — follows the same
|
|
18
|
+
Any question this run puts to the user — an approval blocker, a re-verification scope, a routing fork, a wizard step you relay — follows the same four rules. Full text in the lifecycle core contract (`{{OKSTRA_LEAD_CONTRACT_PATH}}` "Asking the user").
|
|
19
19
|
|
|
20
20
|
1. Investigate first: read the artifacts the answer turns on. If that settles it, do not ask. If it does not, what you read is what the options are made of.
|
|
21
21
|
2. Offer two or three concrete options, recommendation first with one clause saying why, each naming its outcome. The free-input escape is always last, never first.
|
|
22
22
|
3. Never hand over a blank you could have filled. Naming a finding in chat and then offering only free input is the failure this rule exists for.
|
|
23
|
+
4. The question carries its own background. Say what each identifier is and what it says before leaning on it, and name what the task is about in the first sentence — the user has not read the report. Strike the identifiers out of your question: if no choice is left, the background is missing.
|
|
23
24
|
|
|
24
25
|
Relaying a wizard step does not change the option set — relay every `options[]` entry unchanged and in order, and put your investigation and your recommendation in the question body.
|
|
25
26
|
|
|
@@ -33,7 +33,7 @@ Keep the selected host relay's dispatch permission guidance when calling `okstra
|
|
|
33
33
|
| `await_workers` | Run `okstra team await --project-root <root> --run-manifest <path>` through the host's asynchronous shell facility. |
|
|
34
34
|
| `redispatch_worker` | Create the core-specified fresh jobs file and dispatch it with a new `dispatchKind`; never reuse a live worker conversation. |
|
|
35
35
|
| `shutdown_workers` | Run `okstra team teardown --project-root <root> --run-manifest <path>` only after the user-approved cleanup gate. |
|
|
36
|
-
| `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Use `okstra lead-progress append --phase <phase-id>` for a checkpoint and `okstra agent-activity append --kind <kind
|
|
36
|
+
| `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Use `okstra lead-progress append --project-root <dir> --run-manifest <path> --phase <phase-id>` for a checkpoint and `okstra agent-activity append --project-root <dir> --run-manifest <path> --kind <kind> ...` for an activity record; both resolve the ledger path from the run manifest. Emit the matching `PROGRESS:` line — the command prints it as `progressLine` — and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
|
|
37
37
|
| `collect_usage` | Collect artifact/CLI-log-backed usage through the existing Okstra token-usage path; never substitute another runtime's session log. |
|
|
38
38
|
|
|
39
39
|
An `implementation` run calls `dispatch_worker` twice: once for the Executor, then — after `await_workers` settles it — once for the verifiers. That second call's `--workers` list must omit the Executor's worker ID: it is materialized as the Executor on every dispatch, so a batch still carrying it is refused again. A verifier started beside the Executor observes base HEAD instead of the stage diff, so a single batch holding both is refused by `scripts/okstra_ctl/dispatch_core.py` `_validate_implementation_phase_order`, `--dry-run` included.
|
|
@@ -156,7 +156,7 @@ The public shorthand is `UNVERIFIABLE → verification-error`: `UNVERIFIABLE` is
|
|
|
156
156
|
|
|
157
157
|
### Convergence Test
|
|
158
158
|
|
|
159
|
-
The executable source is `scripts/okstra_ctl/convergence_engine.py`; `okstra convergence validate --kind final` replays its persisted-state invariants. This document defines orchestration and semantic boundaries, not a second implementation of the reducer.
|
|
159
|
+
The executable source is `scripts/okstra_ctl/convergence_engine.py`; `okstra convergence validate --state <final> --kind final` replays its persisted-state invariants. This document defines orchestration and semantic boundaries, not a second implementation of the reducer.
|
|
160
160
|
|
|
161
161
|
## Verification Mode
|
|
162
162
|
|
|
@@ -267,7 +267,7 @@ may fix the task-instructions file and re-run the same `materialize` call with
|
|
|
267
267
|
row names the invocation, replacement is rejected even for v1 and the prompt is
|
|
268
268
|
history. Do not delete prompt, metadata, or reservation files by hand.
|
|
269
269
|
|
|
270
|
-
Run `okstra agent-prompt verify --run-manifest <path> --metadata
|
|
270
|
+
Run `okstra agent-prompt verify --project-root <dir> --run-manifest <path> --metadata
|
|
271
271
|
<metadataPath> --text` immediately before dispatch. A failed verification is a
|
|
272
272
|
pre-dispatch contract failure. For `runner=native-session`, pass only the
|
|
273
273
|
returned `hostModelValue` to the host model argument. For
|
|
@@ -639,7 +639,7 @@ The lead writes none of it and edits none of it. **Enforced:**
|
|
|
639
639
|
`tests/contract/test_critic_prompt_equality_exemption.py`
|
|
640
640
|
`test_generated_critic_seed_satisfies_the_real_dispatch_checks` runs the
|
|
641
641
|
generated body through the same two checks the dispatch runs. A hand-edited file
|
|
642
|
-
that drops either line fails `okstra team dispatch --dispatch-kind critic
|
|
642
|
+
that drops either line fails `okstra team dispatch --dispatch-kind critic ...`
|
|
643
643
|
before any process starts, reported as `<task-type> prompt contract: <worker>:
|
|
644
644
|
exactly one Primary analysis packet path is required (found 0)` and `exactly one
|
|
645
645
|
non-empty **Prompt Delivery Mode:** header is required`. Re-render and
|
|
@@ -669,7 +669,7 @@ above the Round 0 list, and the lead pastes the output whole.
|
|
|
669
669
|
critic sets `duplicateOf` to that finding's id (`schemas/convergence-critic-results-v1.0.schema.json` `$defs.Candidate`). A restated finding costs a whole gap-verification round to reject; a declared duplicate costs none — it is recorded in the ledger, never dispatched, and counted in `config.critic.gapsDuplicate`. **Enforced:** `okstra convergence apply-critic-gaps` rejects a `duplicateOf` that names no finding the state carries, and rejects a duplicate row carrying votes.
|
|
670
670
|
|
|
671
671
|
### Gap verification (1 adversarial reverify round)
|
|
672
|
-
Each critic gap enters the verification queue as a finding with `originWorker = "<provider>-critic"` and `source = "critic"`, except a gap the critic declared `duplicateOf` — that one is recorded and never dispatched. The lead runs ONE adversarial reverify round (§"Adversarial Verification Mode" classifier) in which **each gap is verified by exactly one Phase 4 analyser**: walk the analyser roster in `criticVerification.analyserRoster` order and assign gap *i* to `roster[i % len(roster)]`, then dispatch each assigned analyser once with its own gaps. Rejecting a gap costs the same as accepting one and this round is off the books (`rounds: []`, no `roundHistory` entry) on the serial path, so a batch of two gaps no longer wakes four analysers. **Enforced:** `okstra_ctl.convergence_engine._critic_gap_coverage_errors` accepts a dispatch set that is either the assignee set or the full roster, and rejects anything else — the full roster stays valid because a run finished before this rule cannot say which shape it used, the same dual acceptance `_validate_round_ledger_counts` gives the two round-counting arithmetics. Choosing a critic provider that is already in the analyser roster costs nothing: the critic is a different role contract, a different duty and a different session, so an analyser is not disqualified by sharing its provider name (ADR-0017 — provider and model are not role identity, and the same model assigned to two roles gets two independent workers). The critic cannot judge its own gaps because it is not an analyser: the voter roster is `workers[]` filtered to `audience == "analysis"`, and a critic is not even representable there (the allowed values are `analysis` / `lead` / `report-writer`). `okstra apply-critic-gaps` refuses a vote from anyone outside that roster (`critic voter must be a non-critic analyser`). Only gaps classified `full-consensus` / `partial-consensus` merge into the final report findings; `contested` / `worker-unique` gaps are treated as hallucinations and dropped (recorded in the convergence state, not promoted).
|
|
672
|
+
Each critic gap enters the verification queue as a finding with `originWorker = "<provider>-critic"` and `source = "critic"`, except a gap the critic declared `duplicateOf` — that one is recorded and never dispatched. The lead runs ONE adversarial reverify round (§"Adversarial Verification Mode" classifier) in which **each gap is verified by exactly one Phase 4 analyser**: walk the analyser roster in `criticVerification.analyserRoster` order and assign gap *i* to `roster[i % len(roster)]`, then dispatch each assigned analyser once with its own gaps. Rejecting a gap costs the same as accepting one and this round is off the books (`rounds: []`, no `roundHistory` entry) on the serial path, so a batch of two gaps no longer wakes four analysers. **Enforced:** `okstra_ctl.convergence_engine._critic_gap_coverage_errors` accepts a dispatch set that is either the assignee set or the full roster, and rejects anything else — the full roster stays valid because a run finished before this rule cannot say which shape it used, the same dual acceptance `_validate_round_ledger_counts` gives the two round-counting arithmetics. Choosing a critic provider that is already in the analyser roster costs nothing: the critic is a different role contract, a different duty and a different session, so an analyser is not disqualified by sharing its provider name (ADR-0017 — provider and model are not role identity, and the same model assigned to two roles gets two independent workers). The critic cannot judge its own gaps because it is not an analyser: the voter roster is `workers[]` filtered to `audience == "analysis"`, and a critic is not even representable there (the allowed values are `analysis` / `lead` / `report-writer`). `okstra convergence apply-critic-gaps` refuses a vote from anyone outside that roster (`critic voter must be a non-critic analyser`). Only gaps classified `full-consensus` / `partial-consensus` merge into the final report findings; `contested` / `worker-unique` gaps are treated as hallucinations and dropped (recorded in the convergence state, not promoted).
|
|
673
673
|
|
|
674
674
|
**Dispatching the gap round.** The gap round is off the round ledger, so `plan-round` writes no plan for it and `reverify-prompt` cannot render it; it has its own generator and dispatch kind. Assemble the coverage batch first — the same `{ schemaVersion, taskKey, mode: "coverage", provider, modelExecutionValue, gaps[] }` document `apply-critic-gaps` will take, with each candidate as a gap (`gapId` = the critic's item id, `summary`, `category`, `ticketIds`, `originEvidence`, `duplicateOf` where declared) and no `votes` or `dispatches` yet. Then, for each assigned analyser, render `okstra convergence critic-verify-prompt --run-manifest <run-manifest> --gaps <coverage-batch.json> --worker <worker-id>` and write its output verbatim as the instruction file: it applies the same round-robin as `apply-critic-gaps` (`okstra_ctl.convergence_engine.critic_gap_assignees`) and carries only that analyser's gaps, each with the critic's result file and `### [<gapId>]` section, the critic audit sidecar the verifier may open, and the adversarial response format the collector parses (gap votes are always read as adversarial). Materialize with the analyser's existing `reverify/<worker-id>` assignment ref, `--dispatch-kind critic-verify`, `--audience reverification-worker`, and on a v2 run the analyser's own `--source-role-execution-ref` exactly as a numbered reverify round; name the prompt `<worker-id>-worker-critic-verify-<task-type>-<seq>.md` and the result `worker-results/<worker-id>-worker-critic-verify-<task-type>-<seq>.md`. Collect each result with `parse_finding_votes` semantics (the `### <gapId>` blocks), write the votes and one `dispatches[]` row per assigned analyser into the batch, and run `apply-critic-gaps`. **Enforced (rendering):** `okstra_ctl.convergence_critic_verify_prompt`. **Enforced (pre-dispatch):** `validate_reverify_prompt` in `scripts/okstra_ctl/worker_prompt_contract.py` requires the `**Rendered by:** okstra convergence critic-verify-prompt` line for dispatch kind `critic-verify`, so a hand-written gap instruction cannot be materialized; `worker_prompt_policy.is_verification_dispatch_kind` routes the kind through the reverify prompt plan, and `convergence_store.reserve_dynamic_verifier` records the kind on the v2 reservation. Before this path existed (2026-09-09, dev-10642 requirements-discovery 001) every attempt to dispatch the round was refused and all three gaps ended `gapsUnverified`.
|
|
675
675
|
|
|
@@ -44,6 +44,111 @@ Read-side inspection (`/okstra-inspect`) and scheduling (`/okstra-schedule-gen`)
|
|
|
44
44
|
| 6. Synthesis | Dispatch Report writer worker, review draft. **For `implementation-planning`: then run the Phase 6 plan-body verification sub-step (see Phase 6 section below). Selected-direction plans verify `P-Dir-1`; legacy plans retain `P-Opt-*`.** | `report-writer` + `plan-body-verification` (sub-step) |
|
|
45
45
|
| 7. Persist | Call `collect_usage`, update manifests, run the cleanup approval gate, then call `shutdown_workers` only on approval | selected runtime adapter + `report-writer` + this contract |
|
|
46
46
|
|
|
47
|
+
## Command map
|
|
48
|
+
|
|
49
|
+
Every `okstra` command the lead documents cite, grouped by phase, each spelled with every argument its parser requires. Replace each `<placeholder>` with the value the named artifact gives; do not guess a flag that is not listed — run `okstra <command> --help` instead. The table locates a command; the Procedure column names the section that owns when and how to run it, and that section wins where the two differ. **Enforced:** `tests/contract/test_lead_command_map.py` checks every row, and every `okstra` example in the lead documents, against the CLI's own argument parser.
|
|
50
|
+
|
|
51
|
+
### Phase 1 — intake and re-run scope
|
|
52
|
+
|
|
53
|
+
| Command | Use when | Procedure |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| `okstra model-io project-context --project-root <dir>` | Resolve the task key, task manifest, and latest run manifest; add `--task-ref <id-or-key>` for an explicit task | `context-loader` "Step 1" |
|
|
56
|
+
| `okstra model-io run-input --run-manifest <path>` | Read run identity, worker roster, model assignments, and artifact paths instead of opening the run manifest | `context-loader` "Step 3" |
|
|
57
|
+
| `okstra model-io active-context-input --project-root <dir> --run-manifest <path>` | Read the prior executor base ref for an incremental re-run | launch prompt "Incremental re-verification" |
|
|
58
|
+
| `okstra incremental-scope --prev-data <path>` | Decide re-verify vs carry-forward stages on a clarification re-run | launch prompt "Incremental re-verification" |
|
|
59
|
+
| `okstra incremental-carry --prev-data <path> --prev-seq <seq> --cur-narrative <path>` | Merge carried-forward plan-item verdicts after `plan-items seed` | launch prompt "Incremental re-verification" |
|
|
60
|
+
| `okstra stage-map <task-key>` | Read the prior Stage Map and done stages before re-planning | host orchestration rules (implementation-planning) |
|
|
61
|
+
| `okstra stage-close <task-key> --stage <N> --from-commit <sha>` | Close a stage whose work already landed outside okstra | host orchestration rules (implementation-planning) |
|
|
62
|
+
| `okstra git-reconcile --plan-run-root <dir> --project-id <id> --task-group <group> --task-id <id> --work-category <category>` | Detect (`--check --text`) or record (`--apply --stage <N> --use-ref <ref>`) stage SHAs made stale by git history outside okstra | host orchestration rules (implementation) |
|
|
63
|
+
|
|
64
|
+
### Any phase — progress, activity, errors, approval
|
|
65
|
+
|
|
66
|
+
| Command | Use when | Procedure |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| `okstra lead-progress append --project-root <dir> --run-manifest <path> --phase <phase-id>` | Every `PROGRESS` checkpoint; print the `progressLine` it returns. `--phase` accepts only the listed phase ids; use `--worker`, `--field NAME=VALUE`, and `--detail <text>` for the rest | this contract "Progress reporting" |
|
|
69
|
+
| `okstra agent-activity append --project-root <dir> --run-manifest <path> --kind <kind> --agent <agent> --outcome <outcome> --summary <text>` | Before each activity boundary when the run manifest declares `activityContractVersion: 1` | launch prompt "Progress reporting" |
|
|
70
|
+
| `okstra error-log append-observed --out <errors-path> --task-key <key> --phase <phase> --agent <provider-worker> --agent-role <role> --model <model> --error-type <type> --command-kind <kind> --command <command> --message <text>` | Record an observed failure. `--agent` takes the provider worker id (`codex-worker`); an execution label goes in `--execution-label` | this contract "Errors log path wiring"; `team-contract` "Worker error-log command" |
|
|
71
|
+
| `okstra approval-decision open --ledger <path> --task-key <key> --task-type <type> --run-seq <seq> --clarification-id <C-NNN> --ticket-id <id> --statement <text> --expected-form <form> --classification <class> --origin <origin> --user-confirmation <text> --unblock-condition <text> --recommended-disposition <disposition>` | Open an approval blocker after the user confirmed it | this contract "User confirmation before an approval blocker" |
|
|
72
|
+
| `okstra approval-decision carry --ledger <path> --clarification-id <C-NNN> --from-responses <path>` | Carry a decision answered in an earlier run | `report-writer` "Role-owned inputs" |
|
|
73
|
+
| `okstra approval-decision resolve --ledger <path> --clarification-id <C-NNN> --disposition <disposition> --user-text <text> --user-response-ref <ref>` | Record the user's disposition of an approval row; it touches no verdict | `plan-body-verification` "Round protocol" |
|
|
74
|
+
| `okstra user-response show --report <path>` | Not a lead step: the `okstra-user-response` skill reads approval rows through it, so an `origin` outside the schema enum breaks every later read | `plan-body-verification` "Round protocol" |
|
|
75
|
+
|
|
76
|
+
### Phase 2–4 — prompts and dispatch
|
|
77
|
+
|
|
78
|
+
| Command | Use when | Procedure |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| `okstra agent-prompt materialize --project-root <dir> --invocation-id <id> --audience <audience> --instruction <path> --prompt <path>` | Materialize every worker prompt; the command owns the anchor headers and paths | `convergence` "Invocation materialization gate"; `report-writer` "Report-writer dispatch" |
|
|
81
|
+
| `okstra agent-prompt verify --project-root <dir> --metadata <path>` | Immediately before each dispatch | `convergence` "Invocation materialization gate" |
|
|
82
|
+
| `okstra agent-prompt record-dispatch --project-root <dir> --run-manifest <path> --metadata <path> --enforcement-mode <mode>` | Record a native-session dispatch | `convergence` "Invocation materialization gate" |
|
|
83
|
+
| `okstra agent-prompt jobs --project-root <dir> --run-manifest <path> --dispatch-kind <kind> --metadata <path> --out <jobs-file>` | Build a verified jobs file for `okstra team dispatch` | cmux adapter "cmux dispatch details" |
|
|
84
|
+
| `okstra team dispatch --project-root <dir> --run-manifest <path>` | Dispatch pane-backed workers (`terminalBackend` is `cmux-pane`) | cmux adapter "Semantic operation mapping" |
|
|
85
|
+
| `okstra worker-dispatch --project-root <dir> --run-manifest <path>` | Dispatch CLI-backed workers when `terminalBackend` is not `cmux-pane` | this contract "Model assignments" |
|
|
86
|
+
| `okstra codex-dispatch --project-root <dir> --run-manifest <path>` | CLI-backed dispatch for a prepared Codex run; never under the cmux adapter | cmux adapter "cmux dispatch details" |
|
|
87
|
+
|
|
88
|
+
### Phase 5 — await and collect
|
|
89
|
+
|
|
90
|
+
| Command | Use when | Procedure |
|
|
91
|
+
|---|---|---|
|
|
92
|
+
| `okstra team await --project-root <dir> --run-manifest <path>` | Wait for pane-backed workers | cmux adapter "Semantic operation mapping" |
|
|
93
|
+
| `okstra worker-liveness --team-state <path> --dispatch-id <id>` | Probe a pending worker; add `--wait` to block until result, death, or timeout | `team-contract` "Mid-run liveness probes" |
|
|
94
|
+
| `okstra agent-prompt link-result --project-root <dir> --run-manifest <path> --dispatch-id <id> --result <path>` | Link a returned result to its dispatch | `convergence` "Invocation materialization gate" |
|
|
95
|
+
| `okstra agent-prompt reject-result --project-root <dir> --run-manifest <path> --dispatch-id <id> --superseded-by <id> --reason <text>` | Retire a linked result before a corrective dispatch links its own | `plan-body-verification` "Round protocol" |
|
|
96
|
+
| `okstra worker-audit-check --run-dir <path> --task-type <type> --seq <seq>` | Check a live worker's audit sidecars and citations before accepting its result; add `--worker <id>` | `team-contract` "Lead Redispatch Policy on Result-Missing" |
|
|
97
|
+
| `okstra team reclaim --project-root <dir> --run-manifest <path>` | Close finished dispatches' panes at a batch boundary | this contract "Progress reporting" |
|
|
98
|
+
|
|
99
|
+
### Phase 5.5 / 5.6 — convergence and critic
|
|
100
|
+
|
|
101
|
+
| Command | Use when | Procedure |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| `okstra convergence example --kind <kind>` | Print a valid input example before writing a groups, round-results, or critic-results file | `convergence` "Round 1-N" |
|
|
104
|
+
| `okstra convergence prepare-groups --run-manifest <path> --input <path>` | Publish Round 0 grouped findings | `convergence` "Round 0" |
|
|
105
|
+
| `okstra convergence seed --groups <path> --work-state <path> --final-state <path> --migration-dir <dir>` | Create, resume, or recover the working state | `convergence` "Round 0" |
|
|
106
|
+
| `okstra convergence plan-round --work-state <path> --plan <path>` | Write the next round's dispatch plan | `convergence` "Round 1-N" |
|
|
107
|
+
| `okstra convergence reverify-prompt --run-manifest <path> --plan <path> --worker <worker>` | Print one worker's reverify instructions; never compose them by hand | `convergence` "Re-verification Dispatch" |
|
|
108
|
+
| `okstra convergence collect-results --plan <path> --mode <mode> --run-manifest <path> --output <path>` | Read one round's responses into the apply-round input | `convergence` "Round 1-N" |
|
|
109
|
+
| `okstra convergence apply-round --work-state <path> --plan <path> --results <path>` | Apply a round's results | `convergence` "Round 1-N" |
|
|
110
|
+
| `okstra convergence critic-prompt --run-manifest <path>` | Print the coverage-critic instructions; dispatch concurrently with the first reverify round | `convergence` "Coverage critic pass" |
|
|
111
|
+
| `okstra convergence critic-verify-prompt --run-manifest <path> --gaps <path> --worker <worker>` | Print one analyser's gap-verification instructions | `convergence` "Gap verification" |
|
|
112
|
+
| `okstra convergence apply-critic-gaps --work-state <path> --results <path>` | Apply the gap-verification batch once, before `finalize` | `convergence` "Coverage critic pass" |
|
|
113
|
+
| `okstra convergence apply-acceptance-critic --work-state <path> --results <path>` | Record the final-verification acceptance-critic accounting | `convergence` "Acceptance critic pass" |
|
|
114
|
+
| `okstra convergence finalize --work-state <path> --output <path>` | Write the public final state after every round and critic batch is applied | `convergence` "Round 1-N" |
|
|
115
|
+
| `okstra convergence validate --state <path> --kind <kind>` | Replay a persisted state's invariants | `convergence` "Convergence Test" |
|
|
116
|
+
|
|
117
|
+
### Phase 6 — synthesis and plan-body verification
|
|
118
|
+
|
|
119
|
+
| Command | Use when | Procedure |
|
|
120
|
+
|---|---|---|
|
|
121
|
+
| `okstra agent-prompt check-corrections --project-root <dir> --run-manifest <path> --corrections <path>` | Check a report-writer corrections ledger before a corrective dispatch | `report-writer` "Corrective report-writer dispatch" |
|
|
122
|
+
| `okstra agent-prompt apply-corrections --project-root <dir> --run-manifest <path> --corrections <path>` | Apply a ledger that `check-corrections` reported `mechanical: true`, without a writer round | `report-writer` "Corrective report-writer dispatch" |
|
|
123
|
+
| `okstra design-snapshot --narrative <path> --output <path>` | Complete the design-surface detector snapshot; both paths come from the run manifest | `report-writer` "Implementation-planning sequence" |
|
|
124
|
+
| `okstra plan-items prepare --run-manifest <path> --narrative <path>` | Extract this round's plan items (add `--state <path>` after a self-fix, `--tie-vote` for a critic tie round) | `plan-body-verification` "Round protocol" |
|
|
125
|
+
| `okstra plan-items prompt --run-manifest <path>` | Print the plan-items block placed verbatim in every verifier prompt | `plan-body-verification` "Round protocol" |
|
|
126
|
+
| `okstra plan-items validate-prepared --run-manifest <path> --narrative <path>` | Validate the prepared envelope before dispatch | `plan-body-verification` "Round protocol" |
|
|
127
|
+
| `okstra plan-items seed --narrative <path>` | Create the `planItems[]` rows a round lands in | `plan-body-verification` "Round protocol" |
|
|
128
|
+
| `okstra plan-items extract --narrative <path> --output <path>` | Re-extract plan items after a round and re-verify any item whose subject shifted | `plan-body-verification` "Round protocol" |
|
|
129
|
+
| `okstra plan-items correction-prompt --run-manifest <path> --state <path> --worker <id>` | Put its output first in a `worker-correction` re-dispatch prompt | `plan-body-verification` "Round protocol" |
|
|
130
|
+
| `okstra plan-items collect-verdicts --items <path> --result <worker>=<path> --output <path>` | Read a round's responses into a verdicts envelope; never parse them by hand | `plan-body-verification` "Round protocol" |
|
|
131
|
+
| `okstra plan-items apply-verdicts --state <path> --round <N> --result <worker>=<path>` | Record the round's verdicts | `plan-body-verification` "Round protocol" |
|
|
132
|
+
| `okstra plan-items complete-round --state <path> --run-manifest <path> --round <N>` | Record the completed round | `plan-body-verification` "Round protocol" |
|
|
133
|
+
| `okstra plan-items next-dispatch --state <path>` | Decide whether the round opens another worker batch | `plan-body-verification` "Round protocol" |
|
|
134
|
+
| `okstra plan-items resolve-dissent --state <path> --item <P-id> --decision-file <path>` | Record an evidence-based lead decision after the single self-fix | `plan-body-verification` "Round protocol" |
|
|
135
|
+
| `okstra plan-verify --report <path>` | Score the plan-body gate; never tally votes in a script | `plan-body-verification` "Round protocol" |
|
|
136
|
+
|
|
137
|
+
### Phase 7 — persist
|
|
138
|
+
|
|
139
|
+
| Command | Use when | Procedure |
|
|
140
|
+
|---|---|---|
|
|
141
|
+
| `okstra report-finalize --project-root <dir> --run-manifest <path> --report <path>` | Run the whole Phase 7 sequence; do not run its steps separately | `report-writer` "Phase 6 → Phase 7 execution sequence" |
|
|
142
|
+
| `okstra report-translate check-data --run-manifest <path>` | Check an existing translation after a narrative correction | `report-writer` "Phase 6 → Phase 7 execution sequence" |
|
|
143
|
+
| `okstra handoff record-verified --plan-run-root <dir> --stage <N> --report-path <path> --data-json <path>` | Record an accepted final-verification against its stage | this contract "Lifecycle Phase Boundaries" |
|
|
144
|
+
| `okstra team teardown --project-root <dir> --run-manifest <path>` | Close every recorded pane at the end of the run | cmux adapter "Semantic operation mapping" |
|
|
145
|
+
|
|
146
|
+
**Names that do not exist.** Lead sessions have called these; each fails with `unknown command`. Use the command on the right.
|
|
147
|
+
|
|
148
|
+
- `validate-run` — `okstra report-finalize` runs the run validation; `okstra plan-verify` scores the plan-body gate mid-round.
|
|
149
|
+
- `status` — `okstra model-io run-input` for run state; `okstra worker-liveness` for a worker.
|
|
150
|
+
- `progress` — `okstra lead-progress append`.
|
|
151
|
+
|
|
47
152
|
## Core operating contract
|
|
48
153
|
|
|
49
154
|
- The `leader` owns orchestration, convergence supervision, and final-report review. It does not author the report narrative or assembled record when `Report writer worker` is in the roster. `lead` is a compatibility alias for `leader` and must not be written on new artifacts.
|
|
@@ -119,7 +224,7 @@ For an `implementation-planning` run whose run manifest declares `activityContra
|
|
|
119
224
|
The live projection follows this shape:
|
|
120
225
|
|
|
121
226
|
```text
|
|
122
|
-
PROGRESS: phase-4-dispatch worker=codex-worker model=gpt-
|
|
227
|
+
PROGRESS: phase-4-dispatch worker=codex-worker model=gpt-6-sol
|
|
123
228
|
ACTIVITY: id=A-001 agent=codex-worker summary="Verify Stage Map paths and commands" items=P-Step-001,P-Step-002 result=runs/.../codex-worker-....md outcome=pending
|
|
124
229
|
```
|
|
125
230
|
|
|
@@ -140,7 +245,7 @@ Required checkpoints:
|
|
|
140
245
|
- `PROGRESS: phase-5-stage-complete stage=<N> steps=<done>/<count>` — `implementation` only, immediately after the Executor result is verified and its `### Stage Carry Evidence` block is parsed, before the verifier dispatch. `<done>` counts the block's `stepResults[]` rows whose `status` is `done` — read from the emitted block, never recomputed from git. Omitted when the Executor ends without carry evidence (`FAIL` or a non-result); the user then learns the outcome from `phase-5-collect status=<terminal-status>`.
|
|
141
246
|
- `PROGRESS: phase-5.5-convergence round=<N> queue=<count>` — at the start of each convergence round (Phase 5.5).
|
|
142
247
|
- `PROGRESS: phase-5.6-critic provider=<provider> gaps=<n>` — after the critic result is collected (Phase 5.6, opt-in; the critic dispatch itself fires concurrently with the first 5.5 reverify round). Omitted when `convergence.critic.enabled == false`.
|
|
143
|
-
- `PROGRESS: phase-batch-cleanup panes=<n>` — immediately after cleaning up the previous batch's panes, at each batch boundary (① just before the first `phase-5.5-convergence` round ② just before the `phase-6-synthesis` report-writer dispatch). `<n>` is the number of panes closed at that boundary — the panes of dispatches this run recorded and that have since finished — read from the `okstra team reclaim --dry-run` pass taken immediately before the closing pass, never estimated. A pane the harness opened for its own teammate carries no recorded id, so it is not counted and not closed. Expose only the counts and NEVER expose a raw `paneId` or worker handle. Just before the first batch (analysis-worker dispatch) there is nothing to clean up, so it is a no-op and the marker is omitted.
|
|
248
|
+
- `PROGRESS: phase-batch-cleanup panes=<n>` — immediately after cleaning up the previous batch's panes, at each batch boundary (① just before the first `phase-5.5-convergence` round ② just before the `phase-6-synthesis` report-writer dispatch). `<n>` is the number of panes closed at that boundary — the panes of dispatches this run recorded and that have since finished — read from the `okstra team reclaim --project-root <dir> --run-manifest <path> --dry-run` pass taken immediately before the closing pass, never estimated. A pane the harness opened for its own teammate carries no recorded id, so it is not counted and not closed. Expose only the counts and NEVER expose a raw `paneId` or worker handle. Just before the first batch (analysis-worker dispatch) there is nothing to clean up, so it is a no-op and the marker is omitted.
|
|
144
249
|
- `PROGRESS: phase-6-synthesis dispatching report-writer-worker` — at the start of Phase 6.
|
|
145
250
|
- `PROGRESS: phase-5.5.9-plan-verify round=<N> items=<count>` — immediately before dispatching each plan-body verification round (`implementation-planning` only; see [plan-body-verification](./plan-body-verification.md) §"Round protocol"). Each round is a worker batch like any other, so round 2 and later MUST be preceded by a `phase-batch-cleanup` line reclaiming the previous round's verifiers. The numbering keeps this line sorted where the work happens — after Phase 6, because the round verifies the drafted plan body.
|
|
146
251
|
- `PROGRESS: user-confirm <C-NNN> <the question, one line>` — immediately before asking the user about anything that would otherwise become an open `Blocks=approval` row (see "User confirmation before an approval blocker" below). Not tied to a phase: it fires wherever the blocker surfaces. `<C-NNN>` is the id the row will carry, so the answer and the row can be matched afterwards.
|
|
@@ -164,9 +269,13 @@ Every question this run puts to the user obeys the same three rules, whatever th
|
|
|
164
269
|
|
|
165
270
|
3. **Never hand over a blank you could have filled.** Anything you worked out while investigating belongs in the options. Stating a finding in chat and then offering nothing but free input is the failure this rule exists for. Measured: a re-verification-scope prompt whose preamble named the stage the answers touched (`Stage 1`) still offered `직접 입력 — 다시 볼 stage 번호를 지정` as its first and only actionable choice, and the user had to retype what the run had just told them.
|
|
166
271
|
|
|
272
|
+
4. **The question carries its own background.** The user has not read the report and cannot resolve this run's identifiers. Before an identifier carries weight in the question — a requirement id, a record row id, a stage number, a finding count, a role such as "the verifiers" — say in one clause what it is and what it says. The first sentence names what this task is about, in words that survive outside the run. Citing the coordinate stays right (see [_common-contract.md](../profiles/_common-contract.md) "Record coordinates only"); an unexpanded coordinate is what fails. Measured: a question asked how the task should handle "the min price half of EB-002" and never said what EB-002 required, so the only thing the user could answer was that the question could not be understood — which costs the same turn as asking, and loses the run's momentum on top.
|
|
273
|
+
|
|
274
|
+
The test is mechanical: strike every identifier out of your question. If what remains no longer poses a choice, the background is missing.
|
|
275
|
+
|
|
167
276
|
When you are relaying a wizard step, [okstra-run](../../skills/okstra-run/SKILL.md) still owns the option set: relay every `options[]` entry unchanged, in order. This rule adds to it rather than overriding it — put your investigation in the question body and name which of the wizard's own options you recommend and why. Do not drop, merge, reorder, or invent a wizard option to satisfy this section.
|
|
168
277
|
|
|
169
|
-
**Enforced:** `scripts/okstra_ctl/wizard.py` `Prompt.__post_init__` refuses any wizard step whose free-input option is not last (only an abort option may follow it), so a question cannot open on "answer directly". The investigate-first half is a contract on the lead, checked by the same evidence source as the rest of this section — see the `PROGRESS: user-confirm` checkpoint below for the one question kind that leaves a record.
|
|
278
|
+
**Enforced:** `scripts/okstra_ctl/wizard.py` `Prompt.__post_init__` refuses any wizard step whose free-input option is not last (only an abort option may follow it), so a question cannot open on "answer directly". The investigate-first half is a contract on the lead, checked by the same evidence source as the rest of this section — see the `PROGRESS: user-confirm` checkpoint below for the one question kind that leaves a record. Rule 4 is a **guideline**: nothing reads the question text, and a scan for bare identifiers cannot tell an expanded citation from an unexpanded one, so it would fail the questions that are written correctly.
|
|
170
279
|
|
|
171
280
|
## User confirmation before an approval blocker (BLOCKING)
|
|
172
281
|
|
|
@@ -217,7 +326,7 @@ The table below documents those prep-time seed values **for reference only** —
|
|
|
217
326
|
| Lead role | opus | -- | runtime-specific role label; orchestration + convergence supervision + final-report review/approval |
|
|
218
327
|
| Report writer worker | sonnet | report-writer-worker | `agents/workers/report-writer-worker.md` |
|
|
219
328
|
| Claude worker | opus | claude-worker | `agents/workers/claude-worker.md` |
|
|
220
|
-
| Codex worker | gpt-
|
|
329
|
+
| Codex worker | gpt-6-sol | codex-worker | duty + task instructions composed per invocation; deterministic `worker-dispatch` execution |
|
|
221
330
|
| Antigravity worker | gemini-3.1-pro | antigravity-worker | duty + task instructions composed per invocation; deterministic `worker-dispatch` execution |
|
|
222
331
|
|
|
223
332
|
Each analysis assignment follows its recorded `runner`. `runner=native-session` uses the host's native subagent primitive after `host-native-spec-link-gate`. `runner=cli-wrapper` follows the planned execution surface after `core-pre-dispatch` verification: `okstra team dispatch` when `terminalBackend` is `cmux-pane`, otherwise the deterministic `okstra worker-dispatch` process boundary. No LLM transport wrapper sits in front of a provider CLI.
|
|
@@ -405,7 +405,7 @@ For contract 3.0, `prepare` checks the selected-direction draft with the same se
|
|
|
405
405
|
- `dissent-isolated` — only one worker `DISAGREE`s, others `AGREE`. On a blocking kind (`b` / `c` / `e`, and kind `a` on `P-Var-*`) this is scored `majority-disagree` and **blocks approval**. Advisory-only `DISAGREE(d)` and `P-Rb-*` stay recorded dissent and do not block. (Distinct from finding-convergence `worker-unique`, which means the *opposite*: only one worker AGREEs.)
|
|
406
406
|
- `majority-disagree` — a *majority* of analysers `DISAGREE` (majority needs ≥2 participating non-error votes; rollback-ordering `DISAGREE(d)` votes are advisory and excluded from the tally), OR any blocking-kind dissent with ≥2 participating votes (a minority `DISAGREE` is not outvoted), OR an unresolved single-vote-blocking kind fires: one reproduced `DISAGREE(a)` on any item other than a `P-Var-*` one, or one reproduced `DISAGREE(f)` on a `P-Req-*` item (see §"Single-vote-blocking kinds"). This classification **blocks approval**. A valid critic correction is scored before these blocking rules, whether or not the analysers split evenly.
|
|
407
407
|
- `needs-reverify` — one of two shapes the round could not settle.
|
|
408
|
-
- **An even split on a blocking kind.** A panel splitting evenly (1-AGREE / 1-DISAGREE, 2-2, …) needs a critic decision. An unresolved single-vote-blocking kind remains `majority-disagree`; other unresolved splits are `needs-reverify`. Do **not** re-run the original two. Dispatch `critic-worker` immediately on those items only (`okstra plan-items prepare --tie-vote
|
|
408
|
+
- **An even split on a blocking kind.** A panel splitting evenly (1-AGREE / 1-DISAGREE, 2-2, …) needs a critic decision. An unresolved single-vote-blocking kind remains `majority-disagree`; other unresolved splits are `needs-reverify`. Do **not** re-run the original two. Dispatch `critic-worker` immediately on those items only (`okstra plan-items prepare --tie-vote ...`, then `okstra plan-items prompt ...`). The prompt carries the analyser split and no other plan items. Read the answer with `okstra plan-items collect-verdicts --items <the --tie-vote plan-items artifact> --result critic-worker=<path> --output <envelope>` — `--items` takes that artifact, whose `dispatchQueue` is the tie items, so pointing the next step at the raw result is refused against this round's full queue. Record the critic vote as `verdicts[].worker = critic-worker` with `okstra plan-items apply-verdicts --state <plan-body-verification.json> --round <N> --append --items <the --tie-vote plan-items artifact> --result critic-worker=<path>` — `--items` persists the exact partial `dispatchQueue` used by verdict validation and `complete-round`. Earlier verdicts and completed-round history outside that queue remain unchanged. If a previous version saved the critic votes but left the full queue in state, the ordinary `okstra plan-items complete-round --state <state> --run-manifest <manifest> --round <N>` automatically reads this run's canonical prepared queue. It uses that queue when all votes recorded for this round are included, preserving a wider recorded batch when a later prepared queue excludes its votes. An explicit `--items <prepared artifact>` remains available for selecting an artifact. Enforced by `plan_items_cli._round_inputs` and `tests/run/test_plan_items.py` completion coverage. Do not fabricate new-round votes for already agreed items. Without it the result is checked against the whole persisted round queue and refused for every item the critic was never given (measured 2026-09-10: a 7-item tie round refused against 44 items), and the only way through was `--verdicts`, which the CLI's own help calls a historical envelope. Critic `AGREE` / `SUPPLEMENT` settles the split to `has-dissent`, including an earlier `DISAGREE(a)` or `DISAGREE(f)` on `P-Req-*`. This decision corrects the disputed judgement before single-vote blocking is evaluated; it does not delete the original dissent. Critic `DISAGREE` on a blocking kind is `majority-disagree`. **Enforced:** `validators/validate-run.py` `_validate_unresolved_tie_was_reverified` fails an in-scope item that carries an even split on a blocking kind and has neither a `critic-worker` vote nor a `blocks: approval` clarification row, `_classify_plan_item_gate` scores the tie shape and fails a settled classification the votes do not support, and `okstra_ctl.plan_items.next_dispatch` returns kind `critic-tie` for exactly these items, so the tie round is the queue the CLI hands you rather than one you assemble. **With no critic on the roster the split is a user decision, not another round.** `okstra plan-items next-dispatch --state <plan-body-verification.json> --run-manifest <current-run-manifest.json>` answers `user-decision` (not `critic-tie`) when the run's `invocationAssignments` carries no `critic/*` entry, and its `itemIds` are the tie items. For each of them do what step 8 does for a surviving `majority-disagree`: `okstra approval-decision open` with `approvalContext.classification` set to `correctness-critical` when `_is_correctness_critical` is true, or `noncritical-dissent` otherwise, plus the matching `## 1. Clarification Items` row at `Blocks=approval`. Dispatch no further verification for those items. The `Blocks=approval` row is what withholds approval until the user disposes, exactly as for any other approval row; the gate retains unresolved single-vote blockers as `majority-disagree` and folds other `needs-reverify` items into `passed-with-dissent`, so the round closes on the gate it actually scored. A tie left with neither a critic vote nor a decision row surfaces as recorded dissent plus an `advisories[]` entry, not a round-blocking failure. **Enforced:** `okstra_ctl.plan_items.critic_is_rostered` reads the roster and `next_dispatch` returns the kind; `validators/validate-run.py` `_validate_unresolved_tie_was_reverified` reads a `blocks: approval` row linked to the item as the settlement and emits its advisory only when neither settlement is recorded.
|
|
409
409
|
- **A lone dissent nobody cross-verified** — a single-vote-blocking kind fired but the item has **fewer than 2 participating non-error votes**, i.e. the lone dissent was never cross-verified because its peer returned `verification-error`. A single-vote-blocking kind means "one *confirmed* DISAGREE is enough"; an unconfirmed one is not, and on a `P-Var-*` item none fires at all — its kind `a` never blocks on one vote and takes a majority like `b` / `e`. This does **not** block approval — blocking on it would make a worker failure produce a stricter gate than a healthy roster, the same paradox the ≥2-vote majority rule already rules out. The item is re-dispatched in the next round (step 7); if it survives the round budget it is promoted per step 8 with a Statement that says verification never completed. **Enforced:** `validators/validate-run.py` `_classify_plan_item_gate` returns `needs-reverify` for this shape and `_recompute_plan_body_gate` folds it into `passed-with-dissent`.
|
|
410
410
|
- `contested` only meaningful when `maxRounds > 1`; at default `maxRounds=1`, fold any unresolved item into `partial-consensus`.
|
|
411
411
|
5. Gate result resolution:
|
|
@@ -429,7 +429,7 @@ For contract 3.0, `prepare` checks the selected-direction draft with the same se
|
|
|
429
429
|
**Record the cause, not just the outcome.** The gate value names the outcome; `planBodyVerification.gateBlockedBy` (array) names every input that blocked it — `majority-disagree`, `coverage-gap`, `non-result`. Two independent inputs can block: a `majority-disagree` plan item, and a Requirement Coverage `gap` / `blocked C-NNN` row (`prompts/profiles/implementation-planning.md` §"Requirement Coverage"). A coverage-only block still renders as `blocked-by-disagreement` because that is the only blocking non-abort value, so **without `gateBlockedBy` the report asserts a worker disagreement that never happened** and the reader hunts for a dissent that does not exist. Leave the array empty for a passing gate. **Enforced:** `validators/validate-run.py` `_validate_gate_blocked_by` fails a passing gate that has a blocking coverage row — the coverage rule was prose-only before. The declared array itself is not compared against a recomputed one: `okstra plan-verify` returns `gate.blockedBy` from the same computation that produced the gate value, so recording what it returns is what makes the array right.
|
|
430
430
|
|
|
431
431
|
**A coverage row citing this run's own `C-NNN` is not an independent blocker.** When a coverage row's `blocked C-NNN` points at a clarification that step 8 below promoted from a `majority-disagree` item in *this same run*, that blocker is already counted once as the plan item. Counting it again as a coverage gap makes the run block on a clarification it just authored, and the row carries into the next run as a fresh blocker — the Requirement Coverage ↔ Clarification cycle. Such rows are excluded from `coverage-gap`. **Enforced:** `validators/validate-run.py` `_independent_coverage_blockers`.
|
|
432
|
-
6. `okstra plan-items complete-round --run-manifest <current-run-manifest.json>` derives `planBodyVerification.participatingAnalysers` from the current assigned roster and persisted votes, then atomically records the completed round. The gate arithmetic is unchanged, but a shrunken roster changes what the round can settle: with two participating analysers a 1-AGREE / 1-DISAGREE split is a tie, so it reaches neither consensus nor `majority-disagree` and the item has to go back for a round (see `needs-reverify` above). **Enforced:** `validators/validate-run.py` `_validate_participating_analysers` recomputes `voting` from the recorded verdicts and fails a declared figure the table denies. `validators/validate-run.py` `_detect_uniform_verifier` remains advisory; do not copy its JSON output into state.
|
|
432
|
+
6. `okstra plan-items complete-round --state <plan-body-verification.json> --run-manifest <current-run-manifest.json> --round <N>` derives `planBodyVerification.participatingAnalysers` from the current assigned roster and persisted votes, then atomically records the completed round. The gate arithmetic is unchanged, but a shrunken roster changes what the round can settle: with two participating analysers a 1-AGREE / 1-DISAGREE split is a tie, so it reaches neither consensus nor `majority-disagree` and the item has to go back for a round (see `needs-reverify` above). **Enforced:** `validators/validate-run.py` `_validate_participating_analysers` recomputes `voting` from the recorded verdicts and fails a declared figure the table denies. `validators/validate-run.py` `_detect_uniform_verifier` remains advisory; do not copy its JSON output into state.
|
|
433
433
|
|
|
434
434
|
**Check each verifier's verdict distribution before the next round.** After `apply-verdicts` and before opening another worker batch, run `okstra plan-items next-dispatch --state <plan-body-verification.json> --run-manifest <current-run-manifest.json>`. Python owns that decision. Do not invent a full-roster round from a `needs-reverify` label, from every-item `UNVERIFIABLE`, or from `okstra plan-verify` warnings. `_detect_uniform_verifier` remains advisory; do not copy its JSON output into state.
|
|
435
435
|
|
|
@@ -446,7 +446,7 @@ For contract 3.0, `prepare` checks the selected-direction draft with the same se
|
|
|
446
446
|
|
|
447
447
|
The environment exception in §"Planning-time environment gap" covers **running build and test commands only** — whether a referenced path exists, whether a command is declared in `package.json`, and whether the plan is internally consistent are all checkable without it, and a blanket "capability constraints prevent workspace resolution" is not a valid answer to any of them.
|
|
448
448
|
|
|
449
|
-
**How the corrective round is recorded.** The first prompt was dispatched, so it is immutable — `--replace-undispatched` refuses it, correctly. Materialize the correction under a NEW `--invocation-id` and a new prompt path. Before linking its result, retire the first attempt's link: `okstra agent-prompt reject-result --run-manifest <path> --dispatch-id <first dispatch id> --superseded-by <corrective dispatch id> --reason "<what was wrong with the returned result>"`. Without that step the corrective `link-result` fails with `agent result is already linked to another dispatch`, which is how a worker that ran for twenty minutes and wrote a good result ends up unrecordable. Nothing is deleted: the rejected link stays in `agentResultLinks` carrying `supersededBy` and `rejectionReason`, so the ledger shows both attempts and why the second exists.
|
|
449
|
+
**How the corrective round is recorded.** The first prompt was dispatched, so it is immutable — `--replace-undispatched` refuses it, correctly. Materialize the correction under a NEW `--invocation-id` and a new prompt path. Before linking its result, retire the first attempt's link: `okstra agent-prompt reject-result --project-root <dir> --run-manifest <path> --dispatch-id <first dispatch id> --superseded-by <corrective dispatch id> --reason "<what was wrong with the returned result>"`. Without that step the corrective `link-result` fails with `agent result is already linked to another dispatch`, which is how a worker that ran for twenty minutes and wrote a good result ends up unrecordable. Nothing is deleted: the rejected link stays in `agentResultLinks` carrying `supersededBy` and `rejectionReason`, so the ledger shows both attempts and why the second exists.
|
|
450
450
|
|
|
451
451
|
Then run `okstra plan-items complete-round --state <plan-body-verification.json> --run-manifest <current-run-manifest.json> --round <N>`. Python appends one immutable round history entry, records each verified item's votes, derives the current projection from the actual assigned roster, and stamps `completedAt` after the preceding verification command succeeds. The file accumulates across rounds; it is never truncated to the latest one. Report assembly later projects the completed nested `planBodyVerification` into the final record.
|
|
452
452
|
7. **Self-fix loop (one rewrite, targeting planner-fixable defects).** After the initial verification, lead may run one report-writer rewrite when a `majority-disagree` item has a majority of `DISAGREE` verdicts at `fixability == planner-fixable`. Re-verify changed items once, preserving verdicts on unchanged content. Then stop automatic self-fix regardless of outcome and follow step 8. The fixed order is initial verification → one planner self-fix → targeted re-verification → lead decision or immediate user confirmation. A second automatic self-fix is rejected by `plan_items_cli._record_self_fixes`; `_validate_self_fix_grouping` and session activity validation detect multiple recorded rewrites. No rewrite is needed when no item qualifies.
|
|
@@ -464,7 +464,7 @@ For contract 3.0, `prepare` checks the selected-direction draft with the same se
|
|
|
464
464
|
- `all-resolved` — no planner-fixable `majority-disagree` item remains. Exit.
|
|
465
465
|
- `no-progress` — the round resolved **zero** planner-fixable items relative to the previous round. Exit even with budget left: the same rewrite would repeat. Newly *introduced* defects count against progress, so a rewrite that trades one defect for another stops the loop rather than churning. A round that re-targets only what the previous round left unresolved is this same conclusion reached one dispatch earlier — exit on it under this reason rather than paying for the round that proves it. **Enforced (advisory):** `validators/validate-run.py` `_detect_self_fix_recurrence` warns on that shape and names this stop reason.
|
|
466
466
|
- `max-rounds-reached` — the single automatic rewrite has been used. Exit to step 8. Count distinct `selfFixGroups[].round` values; `selfFixRoundsApplied` is the last verification round number, not the rewrite count. Extra verification batches before the rewrite do not increase the self-fix budget.
|
|
467
|
-
- `cause-group-recurrence` — legacy read-only value for reports produced before activity contract v1. A new activity-contract-v1 run cannot emit it because there is no second automatic self-fix round in which a cause group can recur. **Enforced at the only writer:** `okstra plan-items complete-round --self-fix-stop-reason` accepts `all-resolved` / `no-progress` / `max-rounds-reached` and nothing else (`scripts/okstra_ctl/plan_items_cli.py:261`), and it is what sets `selfFixStopReason`, so the value has no way into a new report. A legacy report that already carries it is still an *exhausted* loop, so step 8 may promote its surviving items: `_SELF_FIX_EXHAUSTED_REASONS` admits this value alongside `no-progress` / `max-rounds-reached`. Refusing it there left such a report with no exit at all — the loop may not run again, and the item may not be promoted either.
|
|
467
|
+
- `cause-group-recurrence` — legacy read-only value for reports produced before activity contract v1. A new activity-contract-v1 run cannot emit it because there is no second automatic self-fix round in which a cause group can recur. **Enforced at the only writer:** `okstra plan-items complete-round ... --self-fix-stop-reason` accepts `all-resolved` / `no-progress` / `max-rounds-reached` and nothing else (`scripts/okstra_ctl/plan_items_cli.py:261`), and it is what sets `selfFixStopReason`, so the value has no way into a new report. A legacy report that already carries it is still an *exhausted* loop, so step 8 may promote its surviving items: `_SELF_FIX_EXHAUSTED_REASONS` admits this value alongside `no-progress` / `max-rounds-reached`. Refusing it there left such a report with no exit at all — the loop may not run again, and the item may not be promoted either.
|
|
468
468
|
- `not-attempted` — the loop never ran because no item qualified.
|
|
469
469
|
The `no-progress` and `max-rounds-reached` exits are what make the loop terminate; `selfFixMaxRounds` alone is the backstop.
|
|
470
470
|
- a `majority-disagree` item with a majority of its deciding `DISAGREE` votes at `needs-user-input` is NOT a self-fix target — after correctness-critical precedence, it goes straight to the next step as `user-decision` rather than generic `noncritical-dissent`. **Enforced (promotion path):** `validators/validate-run.py` `_validate_self_fix_before_clarification` demands an exhausted self-fix budget only of `planner-fixable` majorities, so a `needs-user-input` majority is promotable with no self-fix round, and `_validate_plan_body_clarification_matching` fails it when it reaches no `blocks: approval` row. The classification *value* is authoring guidance per step 8: `scripts/okstra_ctl/approval_decisions.py` checks it against the classification enum and its allowed dispositions only — no validator recomputes it from the votes' `fixability`.
|
|
@@ -673,7 +673,7 @@ posture in §"Adversarial plan-body posture" still applies, and this round does
|
|
|
673
673
|
not revisit the requirements themselves.
|
|
674
674
|
|
|
675
675
|
Omitting either line fails `okstra team dispatch --dispatch-kind
|
|
676
|
-
plan-verify-r<N
|
|
676
|
+
plan-verify-r<N> ...` before any process starts, reported as `<task-type>
|
|
677
677
|
prompt contract: <worker>: exactly one Primary analysis packet path is required
|
|
678
678
|
(found 0)`. Fix the instructions file and re-materialize with
|
|
679
679
|
`--replace-undispatched` rather than editing the published prompt.
|
|
@@ -852,7 +852,7 @@ What the generated round 2+ prompt has that round 1 does not:
|
|
|
852
852
|
|
|
853
853
|
An item with no recorded vote carrying a round number gets no block, and an envelope with nothing to carry keeps the round-1 shape — `priorRounds` is absent and no preamble is prepended, so a first round is unaffected by this section.
|
|
854
854
|
|
|
855
|
-
**Enforced:** `okstra plan-items validate-prepared --state <same state>` re-derives the carry and exits 2 when the prepared envelope's `priorRounds` does not match, alongside the `items` / `dispatchQueue` comparison it already made. A prepared queue that dropped the dissent cannot pass the step-1 validation the dispatch is gated on.
|
|
855
|
+
**Enforced:** `okstra plan-items validate-prepared ... --state <same state>` re-derives the carry and exits 2 when the prepared envelope's `priorRounds` does not match, alongside the `items` / `dispatchQueue` comparison it already made. A prepared queue that dropped the dissent cannot pass the step-1 validation the dispatch is gated on.
|
|
856
856
|
|
|
857
857
|
The two spellings are different anchors for different artifacts: `**Prior round dissent**` is the block `prompt` puts in the prompt, `**Prior dissent**` is the line the worker puts in its result. `scripts/okstra_ctl/verdict_blocks.py` parses the result line into the verdict block when it is present and leaves it empty when it is not, so an omitted answer line is still silent — the prompt is what is now guaranteed, not the response.
|
|
858
858
|
|