okstra 0.158.1 → 0.160.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/docs/architecture/storage-model.md +2 -0
- package/docs/architecture.md +1 -1
- package/docs/cli.md +8 -3
- package/docs/for-ai/README.md +2 -2
- package/docs/for-ai/skills/okstra-inspect.md +3 -0
- package/docs/for-ai/skills/okstra-run.md +2 -1
- package/docs/for-ai/skills/okstra-user-response.md +5 -5
- package/docs/project-structure-overview.md +5 -1
- package/docs/task-process/implementation.md +28 -0
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/report-writer-worker.md +1 -1
- package/runtime/bin/okstra-claude-exec.sh +4 -1
- package/runtime/prompts/host-orchestration/README.md +18 -0
- package/runtime/prompts/host-orchestration/implementation.md +57 -0
- package/runtime/prompts/launch.template.md +10 -1
- package/runtime/prompts/lead/adapters/claude-code.md +1 -1
- package/runtime/prompts/lead/context-loader.md +5 -2
- package/runtime/prompts/lead/convergence.md +3 -1
- package/runtime/prompts/lead/plan-body-verification.md +21 -2
- package/runtime/prompts/lead/report-writer.md +1 -1
- package/runtime/prompts/lead/team-contract.md +2 -1
- package/runtime/prompts/profiles/_clarification-recommendation.md +11 -1
- package/runtime/prompts/profiles/_common-contract.md +3 -1
- package/runtime/prompts/profiles/implementation-planning.md +2 -0
- package/runtime/prompts/profiles/requirements-discovery.md +1 -1
- package/runtime/prompts/wizard/prompts.ko.json +3 -0
- package/runtime/python/okstra_ctl/clarification_items.py +9 -0
- package/runtime/python/okstra_ctl/codex_dispatch.py +6 -6
- package/runtime/python/okstra_ctl/convergence.py +168 -11
- package/runtime/python/okstra_ctl/dispatch_core.py +4 -2
- package/runtime/python/okstra_ctl/error_issue.py +640 -0
- package/runtime/python/okstra_ctl/error_report.py +56 -0
- package/runtime/python/okstra_ctl/error_zip.py +23 -10
- package/runtime/python/okstra_ctl/incremental_scope.py +159 -19
- package/runtime/python/okstra_ctl/initial_prompt_materialization.py +18 -5
- package/runtime/python/okstra_ctl/issue_signals.py +186 -0
- package/runtime/python/okstra_ctl/paths.py +38 -0
- package/runtime/python/okstra_ctl/plan_items_cli.py +167 -3
- package/runtime/python/okstra_ctl/profile_show.py +134 -0
- package/runtime/python/okstra_ctl/recap.py +63 -0
- package/runtime/python/okstra_ctl/render_final_report.py +11 -62
- package/runtime/python/okstra_ctl/report_html/filters.py +6 -1
- package/runtime/python/okstra_ctl/report_html/render.py +9 -8
- package/runtime/python/okstra_ctl/report_html/run_usage.py +110 -0
- package/runtime/python/okstra_ctl/report_html/view_models/error_analysis.py +69 -16
- package/runtime/python/okstra_ctl/report_html/visualizations.py +107 -14
- package/runtime/python/okstra_ctl/report_translation.py +4 -0
- package/runtime/python/okstra_ctl/report_views.py +7 -3
- package/runtime/python/okstra_ctl/run.py +41 -2
- package/runtime/python/okstra_ctl/run_audit.py +477 -0
- package/runtime/python/okstra_ctl/usage_cells.py +47 -0
- package/runtime/python/okstra_ctl/user_response.py +25 -10
- package/runtime/python/okstra_ctl/verdict_blocks.py +183 -0
- package/runtime/python/okstra_ctl/wizard.py +64 -10
- package/runtime/python/okstra_ctl/worker_audit_check.py +44 -0
- package/runtime/python/okstra_ctl/worker_audit_ledger.py +207 -0
- package/runtime/python/okstra_ctl/worker_heartbeat.py +9 -3
- package/runtime/python/okstra_ctl/worker_liveness.py +81 -9
- package/runtime/schemas/final-report-v1.0.schema.json +14 -0
- package/runtime/schemas/final-report-v2.0.schema.json +56 -2
- package/runtime/skills/okstra-inspect/SKILL.md +3 -1
- package/runtime/skills/okstra-inspect/facets/error-issue.md +77 -0
- package/runtime/skills/okstra-inspect/facets/run-audit.md +34 -0
- package/runtime/skills/okstra-run/SKILL.md +28 -10
- package/runtime/skills/okstra-user-response/SKILL.md +18 -18
- package/runtime/templates/reports/final-report.template.md +4 -0
- package/runtime/templates/reports/html/assets/base.css +14 -1
- package/runtime/templates/reports/html/base.template.html +42 -0
- package/runtime/templates/reports/html/i18n/en.json +30 -1
- package/runtime/templates/reports/html/i18n/ko.json +30 -1
- package/runtime/templates/reports/html/macros/forms.html +15 -0
- package/runtime/templates/reports/html/macros/visualizations.html +3 -2
- package/runtime/templates/reports/html/tasks/implementation-planning.template.html +1 -0
- package/runtime/templates/reports/i18n/en.json +2 -0
- package/runtime/validators/validate-run.py +331 -208
- package/runtime/validators/validate_session_conformance.py +102 -32
- package/src/cli-registry.mjs +34 -0
- package/src/commands/execute/incremental-scope.mjs +10 -0
- package/src/commands/execute/worker-audit-check.mjs +35 -0
- package/src/commands/inspect/error-issue.mjs +27 -0
- package/src/commands/inspect/profile-show.mjs +29 -0
- package/src/commands/inspect/run-audit.mjs +26 -0
package/README.md
CHANGED
|
@@ -181,7 +181,7 @@ Use these slash commands inside a Claude Code session:
|
|
|
181
181
|
| `/okstra-brief-gen` | Convert a ticket, requirements document, link, or conversation into an `okstra-run` task brief |
|
|
182
182
|
| `/okstra-run` | Start a new task or continue an existing task's next phase |
|
|
183
183
|
| `/okstra-memory` | Store, search, and archive global conversation memory in `~/.okstra/memory-book` |
|
|
184
|
-
| `/okstra-inspect` | Unified read side. Subcommands: `status` (phase/state and workStatus updates), `history` (past tasks, reruns, resumes), `report` (find/read final reports), `time` (elapsed-time breakdown), `logs` (wrapper log sidecar inventory and cleanup suggestions), `cost` (task bundle context/read cost), `errors` (aggregate run error logs into a report), `error-zip` (collect cross-project error logs into an anonymized zip and summarize clusters), and `recap` (run-to-run before/after summary plus free-form Q&A over a task's `.okstra` artifacts) |
|
|
184
|
+
| `/okstra-inspect` | Unified read side. Subcommands: `status` (phase/state and workStatus updates), `history` (past tasks, reruns, resumes), `report` (find/read final reports), `time` (elapsed-time breakdown), `logs` (wrapper log sidecar inventory and cleanup suggestions), `cost` (task bundle context/read cost), `errors` (aggregate run error logs into a report), `error-zip` (collect cross-project error logs into an anonymized zip and summarize clusters), `run-audit` (check every run's artifacts against progress invariants, catching runs that ended wrong without ever logging a failure), `error-issue` (turn those anomalies into GitHub issue candidates and, after explicit approval, file them on the okstra repo), and `recap` (run-to-run before/after summary plus free-form Q&A over a task's `.okstra` artifacts) |
|
|
185
185
|
| `/okstra-rollup` | Aggregate every task run in a task group or project, including per-task run counts, duration, errors, group totals, and a cross-task report digest |
|
|
186
186
|
| `/okstra-usage` | Show the current project's recent run coverage, raw and billable-equivalent tokens, known USD cost, CPU time, and wall-clock time grouped by task type (default: last 30 days) |
|
|
187
187
|
| `/okstra-schedule-gen` | Invoke as `/okstra-schedule-gen [task-group]` to generate a work schedule for an entire task group. Each non-done task is resolved through the source-aware `stage-map` response; your unfinished-stage choices are captured in a temporary selection contract, and only the same draft that passes deterministic selection validation followed by independent narrative verification is published |
|
|
@@ -17,6 +17,8 @@ The task manifest, task index, instruction set, runs, and history are collected
|
|
|
17
17
|
- `instruction-set/`
|
|
18
18
|
- `analysis-profile.md`, `analysis-packet.md`, `analysis-material.md`, `reference-expectations.md`, `task-brief.md`
|
|
19
19
|
- `verification-target.md` for final verification and optional `directive.txt`
|
|
20
|
+
- `host-orchestration-rules.md`, the staged copy of the host orchestration rules for this task type, when the run has one
|
|
21
|
+
- `clarification-response.md`, the user's carried-in clarification answers, when the run has any
|
|
20
22
|
- `final-report-schema.json`, `final-report-template.md`
|
|
21
23
|
- canonical `lead-execution-prompt.md` plus the `claude-execution-prompt.md` compatibility alias
|
|
22
24
|
- `runs/<task-type>/`
|
package/docs/architecture.md
CHANGED
|
@@ -770,7 +770,7 @@ The Phase 7 `render-views` step accepts either a final-report data.json or its M
|
|
|
770
770
|
- **Human summary**: `humanSummary` is the sole v2 top-level human summary contract. It is not copied into AI Markdown. Each task view decides how to present it together with the task deliverable instead of sharing a generic dashboard body.
|
|
771
771
|
- **Audit isolation**: worker execution, convergence, and token/cost material remain available for traceability but are subordinate to the user's findings and decisions. They never replace the task analysis narrative.
|
|
772
772
|
- **Schema v1 compatibility**: existing v1 data and quick Markdown reports keep the legacy conditional renderer, including `readerSummary`, reader modes, and the original Markdown-parsing path.
|
|
773
|
-
- **`C-*` select option order**:
|
|
773
|
+
- **`C-*` select option order (schema v1)**: the legacy renderer parses `Expected form`, puts the `Recommended:` answer **first**, and relabels the `Alternatives:` items consecutively as `(a)`, `(b)`, and so on (the original character labels are not retained). Schema v2 parses nothing here — a `Kind=decision` row carries `options[]`, and the presentation order is the array order with the `role: recommended` entry first.
|
|
774
774
|
|
|
775
775
|
Entry points:
|
|
776
776
|
|
package/docs/cli.md
CHANGED
|
@@ -720,20 +720,24 @@ The `okstra` Node CLI (`bin/okstra`) provides both installer/admin commands and
|
|
|
720
720
|
| `okstra preflight [--runtime <name>] [--cwd <dir>] [--json]` | Single skill-preflight call combining `ensure-installed`, with silent reinstall when stale, `check-project`, and host-specific `runtimeReadiness` into one JSON response. A `claude-code` host checks project workspace trust; `codex`, `antigravity`, and `external` hosts return ready without reading Claude Code state. Step 0 of every project-scoped skill converges on this command |
|
|
721
721
|
| `okstra convergence seed --groups <path> --work-state <path> --final-state <path> --migration-dir <dir> [--restart-from-round0]` | Create, resume, reuse, or explicitly recover deterministic convergence state |
|
|
722
722
|
| `okstra convergence plan-round --work-state <path> --plan <path>` | Persist the next roster-aware dispatch plan without mutating working state |
|
|
723
|
+
| `okstra convergence collect-results --plan <round-plan.json> --mode <adversarial\|collaborative> --result <worker>=<path>… --dispatch <worker>=<status>:<durationMs>… --output <round-results.json>` | Read one round's worker responses into the `apply-round --results` shape. `--mode` picks the verdict vocabulary — the adversarial prompt answers `REFUTED` / `SURVIVES` / `SURVIVES-WITH-CAVEAT` / `UNVERIFIABLE`, which this maps to `disagree` / `agree` / `supplement` / `unverifiable`, and copies `**Basis**` into `disagreeBasis`. `--dispatch` supplies the terminal status and duration, which live in the dispatch rather than the response; a worker that never returned gets a `--dispatch` and no `--result`. Exits 2 on a dispatched finding with no verdict, a verdict for a finding the plan did not dispatch to that worker, a planned worker with no recorded outcome, or a vote with no explanation |
|
|
723
724
|
| `okstra convergence apply-round --work-state <path> --plan <path> --results <path>` | Validate one complete structured result set and atomically reduce it into working state |
|
|
724
725
|
| `okstra convergence apply-critic-gaps --work-state <path> --results <path>` | Apply one verified coverage-critic batch after the main queue reaches a terminal state |
|
|
725
726
|
| `okstra convergence finalize --work-state <path> --output <path>` | Materialize the terminal schema v1.3 convergence state |
|
|
726
727
|
| `okstra convergence validate --state <path> --kind <working\|final>` | Validate replayable working state or a terminal final state |
|
|
727
|
-
| `okstra convergence example --kind <groups\|round-results\|critic-results>` | Print one deterministic valid input example as JSON. `groups`
|
|
728
|
+
| `okstra convergence example --kind <groups\|round-results\|critic-results\|coverage-batch>` | Print one deterministic valid input example as JSON. Each kind feeds one command: `groups` → `seed --groups`, `round-results` → `apply-round --results`, `coverage-batch` → `apply-critic-gaps --results`. `critic-results` feeds nothing — it is the critic worker's own result document, and feeding it to `apply-critic-gaps` is rejected by design; that reducer takes the coverage batch the lead assembles from those candidates plus each analyser's vote, which is what `--kind coverage-batch` prints |
|
|
728
729
|
| `okstra plan-items extract --data <data.json> --output <items.json>` | Deterministically extract the complete implementation-planning `P-*` queue from report-writer data.json |
|
|
729
730
|
| `okstra plan-items validate --data <data.json> --items <items.json>` | Require the persisted `P-*` queue to match a fresh deterministic extraction exactly |
|
|
731
|
+
| `okstra plan-items collect-verdicts --result <worker-id>=<path>… --items <items.json> --output <verdicts.json>` | Read one plan-verify round's worker responses into a verdicts envelope, using the `### <item-id>` / `**Verdict**` block shape fixed by `prompts/lead/plan-body-verification.md`. Exits 2 on an assigned item the worker left unanswered, a verdict for an item outside the persisted queue, a `DISAGREE` with no breakage kind, or a `DISAGREE` without a fixability value — every failure mode a per-round regex drops silently |
|
|
732
|
+
| `okstra plan-items apply-verdicts --data <data.json> --verdicts <verdicts.json>` | Overwrite `implementationPlanning.planBodyVerification.planItems[].verdicts` with that envelope. Overwrites rather than merges, because the contract records one round at a time and a merged table lets the previous round's votes keep voting. Exits 2 when the report carries no row for an incoming item |
|
|
730
733
|
| `okstra config <get\|set\|unset\|show> [key] [value] [--scope project\|global\|all]` | Manage persistent settings such as `pr-template-path` with atomic JSON writes |
|
|
731
734
|
| `okstra memory <add\|list\|search\|show\|archive>` | Manage global conversation memory in `~/.okstra/memory-book`, a user-home store separate from project `.okstra/` and the CLI basis of the `save this in okstra` natural-language skill |
|
|
732
735
|
| `okstra manager <init\|discover-projects\|new\|task>` | Public CLI for grouping cross-project okstra tasks into manager-owned context. `new project`, `new task-group`, and `new task` create manager plans; `task assign`, `task note`, `task sync`, `task status`, and `task run` manage per-project assignments and snapshots. `new project --project-root` accepts only existing directories and performs setup-equivalent registration only if `.okstra/project.json` is absent. Public documentation uses the full `project-id:task-group:task-id` child task key; when child task IDs differ within the same manager task, select the exact child with `--child-task-id`. `task run` does not execute the child lead directly; it returns `prepared` launch metadata/event and a child launch-context packet as JSON |
|
|
733
736
|
| `okstra rollup [--task-group <group>] [--project-root <dir>] [--cwd <dir>]` | Read-only backend for the okstra-rollup skill. For every catalog task, or one task group, it emits JSON with per-task run counts, raw duration in ms, error counts, latest report paths, group totals, and status/category/phase distributions. Omitting `--task-group` targets the whole project catalog. The caller skill formats raw ms as HH:MM:SS and synthesizes report prose. Use the `okstra inspect` family for a single-task drill-down |
|
|
734
737
|
| `okstra usage-report [--days <positive-int>] [--project-root <dir>] [--cwd <dir>] [--json]` | Read-only backend for the okstra-usage skill. Defaults to the whole current project's last 30 days and emits task-type run coverage, raw/billable tokens, known USD cost, CPU-sum milliseconds, wall-clock milliseconds, unavailable reason counts, and unmatched pricing models |
|
|
735
738
|
| `okstra worker-state transition --team-state <path> --worker <id> --status <in-progress\|completed\|timeout\|error\|not-run> [--reason <text>] [--model <execution-value>]` | Atomically update one persisted worker row. `in-progress` records the authoritative `startedAt` and clears `endedAt`; terminal states record `endedAt`; `timeout`, `error`, and `not-run` require a reason. Dispatch adapters use this same transition path, so CLI-backed and in-process orchestration share the status timestamp contract |
|
|
736
|
-
| `okstra worker-liveness [--team-state <path> --worker <id>]… [--max-idle <seconds>] [--launch-grace <seconds>] [--json]` | Judge whether pending workers are still alive so the lead's poll ends a stalled wait early instead of paying the full deadline. The selector repeats; each `--team-state` must have a paired `--worker`. The worker row's `livenessMode` picks the probe: `audit-heartbeat` reads its `auditSidecarPath` and reports `stalled` when the `- PROGRESS:` heartbeat is past the idle budget; `wrapper-status` reads its `promptPath` and reports `did-not-launch` when neither the wrapper `.log` nor `.status.json` appears. Both graces start at the persisted `startedAt`, never at an artifact mtime — the audit sidecar is reused on re-dispatch, so a heartbeat older than this dispatch counts as no signal yet rather than a stall. Healthy probes report `live`. It only judges—it never kills or re-dispatches. Exit 1 on an unhealthy verdict, so a poll loop can branch without parsing JSON. The heartbeat line shape and budget come from the `okstra_ctl.worker_heartbeat` SSOT shared with the Phase 7 audit (`validators/validate_session_conformance.py`) |
|
|
739
|
+
| `okstra worker-liveness [--team-state <path> --worker <id>]… [--max-idle <seconds>] [--launch-grace <seconds>] [--stall-confirm <seconds>] [--json]` | Judge whether pending workers are still alive so the lead's poll ends a stalled wait early instead of paying the full deadline. The selector repeats; each `--team-state` must have a paired `--worker`. The worker row's `livenessMode` picks the probe: `audit-heartbeat` reads its `auditSidecarPath` and reports `stalled` when the `- PROGRESS:` heartbeat is past the idle budget; `wrapper-status` reads its `promptPath` and reports `did-not-launch` when neither the wrapper `.log` nor `.status.json` appears. Both graces start at the persisted `startedAt`, never at an artifact mtime — the audit sidecar is reused on re-dispatch, so a heartbeat older than this dispatch counts as no signal yet rather than a stall. A heartbeat budget breach is confirmed before it is reported: the probe re-reads the sidecar after `--stall-confirm` seconds (default: half that stage's budget; `0` disables) and reports `stalled` only when the newest heartbeat has not advanced, so a worker inside one long uninterruptible tool call is not judged dead for being slow. Healthy probes report `live`. It only judges—it never kills or re-dispatches. Exit 1 on an unhealthy verdict, so a poll loop can branch without parsing JSON. The heartbeat line shape and budget come from the `okstra_ctl.worker_heartbeat` SSOT shared with the Phase 7 audit (`validators/validate_session_conformance.py`) |
|
|
740
|
+
| `okstra worker-audit-check --run-dir <runs/<task-type>/> --task-type <type> --seq <nnn> [--worker <id>]` | Apply the Phase 7 worker audit-sidecar rules mid-run, while the worker session is still alive. For each of this run's `worker-results/<worker>-<task-type>-<seq>.md` it checks that the file carries no `## 0. Reading Confirmation` heading, that the matching audit sidecar exists, and — for prompts carrying the required-v1 evidence-ledger marker — that every backticked `path:line` citation has an Evidence read row in that sidecar. `--worker` scopes it to the role that just returned. Emits `{ok, failures[]}` and exits 2 when `failures[]` is non-empty. The rules come from the `okstra_ctl.worker_audit_ledger` SSOT shared with `validate-run.py`, so an early pass and the Phase 7 pass cannot disagree. Run it right after collecting a result: the same failure at Phase 7 leaves only a retroactive edit, which breaks the audit chain, or a failed run |
|
|
737
741
|
| `okstra log-report [--project-root <dir>] [--cwd <dir>] [--top <N>] [--json]` | Read-only inventory of wrapper transcript `.log` files and their sibling prompt `.md` files. Each ranked entry preserves `path` / `sizeBytes` for compatibility and also reports `transcriptPath`, `transcriptBytes`, `promptPath`, `promptBytes`, and `transcriptToPromptRatio`; totals distinguish prompt bytes from transcript bytes and count paired files. Ranking remains transcript-size descending |
|
|
738
742
|
| `okstra recap <assemble\|record\|note> <task-root\|task-key> …` | Backend for the okstra-inspect `recap` facet. `assemble` is read-only and prints a JSON summary of phase transitions across a task's runs. `record --kind <summary\|qa> --mode <artifact\|code> --answer <text> [--question <text>] [--citation <path:line> …]` appends one line to `<task-root>/recap/recap-log.jsonl` and never mutates other artifacts. `note --kind <verification-evidence\|decision-draft\|analysis-note> --slug <topic> --purpose <text> --scope-note <text> (--body <markdown>\|--body-file <path>)` writes an agent-authored note to `<task-root>/notes/` and prints its path plus the `--clarification-response` argument for feeding it into a later run |
|
|
739
743
|
| `okstra user-response <list\|show\|write> …` | Backend for the `/okstra-user-response` skill: answer a task's open clarification questions in-session and write the response sidecar. `list --home <dir> --project <id> [--limit <n>]` finds reports with open questions; `show --report <md>` reads one report's questions; `write --report <md> --answers <json> [--approval <json>] [--task-key <key>]` writes the sidecar. Each answer carries a `disposition` of `answer` or `reframe`; a `reframe` is carried into the next run as a re-scoped brief. JSON output; exit 0 ok / 1 error |
|
|
@@ -742,13 +746,14 @@ The `okstra` Node CLI (`bin/okstra`) provides both installer/admin commands and
|
|
|
742
746
|
| `okstra task-list [--project-root <path>]` | Combine `list_project_tasks` and `read_latest_task` into JSON containing the task catalog and latest task |
|
|
743
747
|
| `okstra task-show <task-key> [--project-root <path>]` | Summarize workflow, phase, status, and artifacts from the Task Read-Side Snapshot |
|
|
744
748
|
| `okstra stage-map <task-key> [--cwd <dir>\|--project <dir>]` | Dump the task's implementation-planning Stage Map as JSON: `{ ok, taskKey, taskRoot, state, sourcePlanPath, stages:[{stage_number,title,depends_on,step_count}], doneStages:[int] }`. `state` is `ready` for one resolved source and `missing` when no Stage Map exists; corrupt or conflicting sources return structured non-zero errors instead of silently selecting another report. `doneStages` is read from the implementation-planning stage consumer state (with carry recovery). This is the read-side source `/okstra-schedule-gen [task-group]` uses to derive selectable unfinished stages and their completed dependency closure |
|
|
745
|
-
| `okstra incremental-scope <args…>` | Decide re-verify vs carry-forward scope for an `implementation-planning` clarification re-run. Thin shim into `scripts/okstra_ctl/incremental_scope.py` (deterministic pure function): it reads the dependency graph from the prior run `data.json`'s `implementationPlanning.stageMap` and returns `mode:"incremental"` only when the base-ref SHA is unchanged and the affected stages' `downstream_stage_closure` covers at most half of all stages; otherwise it signals a full re-run. Used to bound the cost of a clarification re-run |
|
|
749
|
+
| `okstra incremental-scope <args…>` | Decide re-verify vs carry-forward scope for an `implementation-planning` clarification re-run. Thin shim into `scripts/okstra_ctl/incremental_scope.py` (deterministic pure function): it reads the dependency graph from the prior run `data.json`'s `implementationPlanning.stageMap` and returns `mode:"incremental"` only when the base-ref SHA is unchanged and the affected stages' `downstream_stage_closure` covers at most half of all stages; otherwise it signals a full re-run. Used to bound the cost of a clarification re-run. `--preview --prev-data <path> --answered-clarifications <csv>` runs the link half alone — no base SHA, no side effects — and prints `{wouldForceFull, unlinkedIds, reason}`, so the cost of the next re-run is visible before `render-bundle` fixes a base commit |
|
|
746
750
|
| `okstra incremental-carry <args…>` | Merge carried-forward plan-item verdicts into an incremental re-run. Thin shim into `scripts/okstra_ctl/incremental_carry.py`: it takes the prior run's plan-item verdicts that the current run does not re-verify and merges them into the current `data.json` tagged with `carriedForwardFromSeq`. A `schemaVersion` drift raises `CarryError` and exits non-zero to force a full fallback. Runs after `incremental-scope` returns `mode:"incremental"` |
|
|
747
751
|
| `okstra code-review target --task-key <k> --stage <N> [--project-root <dir>] [--cwd <dir>] [--json]` / `okstra code-review target --branch <name> [--base <ref>] [--date <YYYY-MM-DD>] [--project-root <dir>] [--cwd <dir>] [--json]` | Resolve what a code review reads and where its result file goes. Output is always JSON, so `--json` only makes that explicit. `--project-root` and `--cwd` are shared pre-dispatch arguments and apply to both modes; `--cwd` is only consulted when `--project-root` is absent. Both modes return `{ ok, projectRoot, mode, worktreePath, branch, baseCommit, headCommit, reviewPath, round }`; stage mode additionally returns `taskKey`, `taskRoot`, and `stage`. Stage mode takes the diff base from the `base_ref` recorded on that stage's worktree-registry row when it was provisioned — not from a rule re-applied at review time — and names the result `.okstra/tasks/<task-group>/<task-id>/code-reviews/stage-<NN>.md`, where a re-review of the same stage becomes `-r2`, `-r3`, … (the `round` field). Only a legacy row provisioned before `base_ref` was recorded falls back to re-deriving the base through `stage_targets`, and a failure there is reported as `stage_base_unresolved`. `worktreePath` comes back empty whenever the stage worktree is not usable as a live checkout — the registry row is no longer `active` (whole-task final-verification released it), the row never carried a path, or the recorded directory is gone — and the review then reads the `branch` ref instead. Branch mode uses `--base` when given, otherwise the merge-base with the default branch (`refs/remotes/origin/HEAD`, else `main`/`master`), and names the result `.project-docs/code-reviews/<branch>/<YYYY-MM-DD>-<NN>.md`, where `<NN>` (the `round` field) is the next sequence number for that date — the highest already on disk plus one. Read-only: it resolves paths and creates no directory and no file, so the review directory does not exist until the caller writes the report. Backend for the okstra-code-review skill |
|
|
748
752
|
| `okstra set-work-status <token> <todo\|in-progress\|blocked\|done> [--note <text>] [--task-group <g>] [--project-root <dir>]` | Update user-managed `workStatus` in task-manifest.json, along with `workStatusUpdatedAt` and, when `--note` is supplied, `workStatusNote`. `<token>` is a full task key or bare task ID. It uses the manifest renderer's serialization rules and returns `stage:"ambiguous"` plus `matches[]` when ambiguous |
|
|
749
753
|
| `okstra worktree-lookup <task-key>` | Return the `worktree_registry.lookup` result: reserved path, branch, base ref, and current status |
|
|
750
754
|
| `okstra plan-validate <plan-path>` | Run `_validate_approved_plan` and report frontmatter `approved` recognition plus unresolved Blocks=approval rows |
|
|
751
755
|
| `okstra render-bundle <args…> [--stage <auto\|N>] [--stages <csv>]` | Thin shim over `prepare_task_bundle(render_only=True)` with the same signature as `python3 -m okstra_ctl.run --render-only`. `--stage` is for `implementation` and `final-verification`: for implementation, `auto` (default) selects the earliest incomplete stage with satisfied dependencies, while `<N>` forces a stage; for final-verification, `<N>` verifies one stage with artifacts under `runs/final-verification/stage-<N>/` and a `-fv-s<N>` team suffix, while an empty value performs whole-task verification with the flat layout. The separate `--stages <csv>` channel is for `release-handoff`: stage-group mode bundles the listed stage numbers into one PR, while an empty value selects whole-task mode. Preparation enforces eligibility—`done` + accepted `verified` + not yet `pr`—and automatically creates an input document that cites verification reports |
|
|
756
|
+
| `okstra profile show <task-type> [--resolved]` | Print a phase profile. `--resolved` expands its `{{INCLUDE:}}` targets and appends the lazy-read sidecars named in the profile body — transitively, because sidecars name sidecars of their own (`_implementation-executor.md` points at the coding-conventions preflight, the diff-review sweep, and the completion self-check). That matters because a profile is assembled from three places, so grepping only the top-level file returns false negatives: `grep clarification prompts/profiles/implementation.md` finds nothing while the assembled profile has many hits. One grep over this output answers whether a task-type covers a rule. The sidecar list is read from the profile body, never hard-coded, so a newly added sidecar is picked up without a code change. Read-only: it writes no manifest and registers no run, which is what separates it from `render-bundle` — `render-bundle` answers the same question but records a run in `recent.jsonl`, so it cannot be used to look something up. Exits 2 for an unknown task-type |
|
|
752
757
|
| `okstra codex-run <args…>` | Codex lead-adapter dry-run entry point. Accepts the same arguments as `render-bundle` but owns `--render-only --lead-runtime codex`. It prepares the task bundle and prints the prompt for the Codex lead without dispatching workers |
|
|
753
758
|
| `okstra codex-dispatch --project-root <dir> --run-manifest <path> [--workers <csv>]` | Read a Codex-host run manifest and dispatch every requested `runner=cli-wrapper` assignment through its registered provider wrapper. Native Codex rows remain in-session. The persisted report-writer assignment needs no Codex-specific opt-in; successful report completion triggers token substitution, HTML rendering, follow-up generation, and validation |
|
|
754
759
|
| `okstra team dispatch --project-root <dir> --run-manifest <path> [--workers <csv>] [--jobs-file <path>] [--dry-run]` / `okstra team await --project-root <dir> --run-manifest <path> [--json]` / `okstra team teardown --project-root <dir> --run-manifest <path> [--dry-run] [--json]` | Read a `leadRuntime=external` run manifest and dispatch, await, or tear down tmux-pane workers. If a tmux pane cannot be created, gracefully degrade to the CLI wrapper and record the fallback in `workerDispatches[].degradedFrom` |
|
package/docs/for-ai/README.md
CHANGED
|
@@ -20,7 +20,7 @@ This directory is a compressed manual for an AI to quickly select and precisely
|
|
|
20
20
|
| Turn requirements, tickets, links, a codebase scan, or an error-zip into an okstra input brief | `okstra-brief-gen` | [`skills/okstra-brief-gen.md`](skills/okstra-brief-gen.md) |
|
|
21
21
|
| Start an okstra run or execute the next phase in the current Claude Code session | `okstra-run` | [`skills/okstra-run.md`](skills/okstra-run.md) |
|
|
22
22
|
| Manage okstra tasks across multiple projects — bundling, assignment, sync snapshots, child launch packets | `okstra-manager` | [`skills/okstra-manager.md`](skills/okstra-manager.md) |
|
|
23
|
-
| Check status, history, report, time, logs, cost, errors, error-zip, recap | `okstra-inspect` | [`skills/okstra-inspect.md`](skills/okstra-inspect.md) |
|
|
23
|
+
| Check status, history, report, time, logs, cost, errors, error-zip, run-audit, error-issue, recap | `okstra-inspect` | [`skills/okstra-inspect.md`](skills/okstra-inspect.md) |
|
|
24
24
|
| Collect and aggregate the results of multiple task runs across a task-group (or the whole project) into a synthesized summary | `okstra-rollup` | [`skills/okstra-rollup.md`](skills/okstra-rollup.md) |
|
|
25
25
|
| Project-wide recent run coverage, tokens, known cost, CPU, and wall-clock usage by task type | `okstra-usage` | [`skills/okstra-usage.md`](skills/okstra-usage.md) |
|
|
26
26
|
| Generate a client-facing work schedule for a whole task-group | `okstra-schedule-gen` | [`skills/okstra-schedule-gen.md`](skills/okstra-schedule-gen.md) |
|
|
@@ -38,7 +38,7 @@ This directory is a compressed manual for an AI to quickly select and precisely
|
|
|
38
38
|
4. Project artifacts go under `<PROJECT_ROOT>/.okstra/` by default. The exception is `okstra-memory`, which uses the global user memory `~/.okstra/memory-book/`.
|
|
39
39
|
5. `runtime/` is build output. When fixing a source skill or template, edit the source under `skills/`, `templates/`, `validators/`, `scripts/`, `src/` and apply it via a build.
|
|
40
40
|
6. Do not guess the contents of a tracker, URL, file, report, log, zip, template, or validator. Use only what you have confirmed by reading or running with a tool.
|
|
41
|
-
7. Read-side skills also produce some artifacts. `okstra-inspect errors` produces an error report Markdown,
|
|
41
|
+
7. Read-side skills also produce some artifacts. `okstra-inspect errors` produces an error report Markdown, `okstra-inspect error-zip` produces an anonymized zip, and `okstra-inspect error-issue` produces a plan file and — only after the user approves in that session — GitHub issues on a public repo. Even in these cases, keep the CLI stdout JSON as the source of truth.
|
|
42
42
|
|
|
43
43
|
## The Order the AI Reads In
|
|
44
44
|
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
- `status.4`: writes the user-requested `workStatus` into `task-manifest.json`.
|
|
19
19
|
- `errors`, `error-zip`, `recap record`: produce report/zip/log artifacts from the information read.
|
|
20
|
+
- `error-issue submit`: the only sub-command that writes outside this machine. It files GitHub issues on a public repo and runs only after an explicit user approval in the same session.
|
|
20
21
|
|
|
21
22
|
## sub-command list
|
|
22
23
|
|
|
@@ -30,6 +31,8 @@
|
|
|
30
31
|
| `cost` | estimate task bundle context/read cost | read |
|
|
31
32
|
| `errors` | aggregate task error logs into a timestamped markdown report | generates report |
|
|
32
33
|
| `error-zip` | build an anonymized zip of cross-project error logs | generates zip |
|
|
34
|
+
| `run-audit` | check every run's artifacts against progress invariants — catches a run that ended wrong without ever logging a failure | read |
|
|
35
|
+
| `error-issue` | turn cross-project anomalies into GitHub issue candidates (`plan`), then file the approved ones (`submit`) | writes a plan file; `submit` creates/comments GitHub issues after user approval |
|
|
33
36
|
| `recap` | summarize a task's before/after runs and record Q&A | appends `recap-log.jsonl` |
|
|
34
37
|
|
|
35
38
|
## Preflight
|
|
@@ -160,7 +160,8 @@ verbatim reason. Neither the AI lead nor a worker creates a self-exemption.
|
|
|
160
160
|
The resulting blocking/advisory policy is enforced by
|
|
161
161
|
`scripts/okstra_ctl/conformance.py::decide_conformance_gate` and
|
|
162
162
|
`validators/validate-run.py::_validate_conformance`; the picker restriction is
|
|
163
|
-
defined by `
|
|
163
|
+
defined by `prompts/host-orchestration/implementation.md` Step 5.1 (the
|
|
164
|
+
`okstra-run` skill body carries a generated copy).
|
|
164
165
|
|
|
165
166
|
When chosen, add it to `render-bundle` only.
|
|
166
167
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
`okstra-user-response` answers the **unresolved clarification questions** an okstra run left behind (the open `C-*` rows under the final report's `## 1. Clarification Items`) **in-session**, and records those answers as a `runs/<type>/user-responses/` sidecar. The next `/okstra-run` auto-attaches this sidecar via `--clarification-response`.
|
|
12
12
|
|
|
13
|
-
**Core principle — the skill never picks an answer for the user.** It builds the option board — background, a self-contained question,
|
|
13
|
+
**Core principle — the skill never picks an answer for the user.** It builds the option board — background, a self-contained question, the report's options with their impact, `Enter directly` — and the user alone picks from it; every `value` is what the user chose or typed. It does not call `write` until the user has explicitly confirmed (`confirmed`).
|
|
14
14
|
|
|
15
15
|
**Second principle — one question at a time.** Never batch two clarification items into one question, and never dump the whole open list at the user.
|
|
16
16
|
|
|
@@ -21,7 +21,7 @@ Distinguish it from starting a run (`okstra-run`), inspecting a finished task (`
|
|
|
21
21
|
| Sub-command | What it does |
|
|
22
22
|
|---|---|
|
|
23
23
|
| `list` | List tasks that still have approval-open clarification (newest report first) |
|
|
24
|
-
| `show` | Expand one report's open `C-*` rows (statement +
|
|
24
|
+
| `show` | Expand one report's open `C-*` rows (statement + options + contextRefs) |
|
|
25
25
|
| `write` | Record the collected answers (+ optional approval) as a `user-responses/` sidecar |
|
|
26
26
|
|
|
27
27
|
## Preflight
|
|
@@ -37,11 +37,11 @@ okstra preflight --runtime claude-code --json
|
|
|
37
37
|
## Flow
|
|
38
38
|
|
|
39
39
|
1. **list**: `okstra user-response list --home <home> --project <projectId> --limit 3` → an array of `{taskKey, taskType, seq, reportPath, reportMtime, openBlockerCount, openApprovalCount, unreadable}` (`openBlockerCount` = open rows with `Blocks` in `{approval, next-phase}`; `openApprovalCount` = the `approval`-only subset). If the array is empty, stop with "no open clarification". A 3-option picker (top recommendations + the final option always "Enter directly" for pasting a `reportPath`/`task-key` directly). `unreadable:true` is a §1 format drift — flag it with `⚠` and do not proceed (do not fabricate rows).
|
|
40
|
-
2. **show (data fetch, not a presentation step)**: `okstra user-response show --report <reportPath>` → `rows[]`
|
|
40
|
+
2. **show (data fetch, not a presentation step)**: `okstra user-response show --report <reportPath>` → `rows[]` of `{id, kind, blocks, status, statement, expectedForm, options, contextRefs, resolvedRefs}`. Each `options[]` entry is `{role, answer, rationale, scopeImpact, addedWork, directionChange}`; `resolvedRefs` carries the `definition` of internal tokens such as `RB-002`/`§4.7`. A schema-v1 report has nowhere to record impact, so those three fields arrive empty. Do not print `rows` at the user and **do not paste the raw `statement` as the question** — announce only `<N> open items — I'll go through them one at a time.`
|
|
41
41
|
3. **ask, one item at a time**: iterate the rows in report order, **one item per `AskUserQuestion` call**, headed `[n/N] C-014 — blocks: approval gate`. Per item:
|
|
42
42
|
- **Background first**, in the message text above the picker, 3–6 lines: (a) *Situation* — what the run was doing when it stopped here; (b) *What is undecided* — the fork, internal tokens expanded inline from `resolvedRefs[].definition`, plus what is stuck (`approval` → the approval gate stays shut and `implementation` cannot start; `next-phase` → the next phase cannot begin); (c) *What changes with your answer*. Source it from `resolvedRefs[].definition`, else **Read** the `§`/`path:line` in `contextRefs[]`; **never invent it** — say the report is silent instead. Close with `Source: C-014 — "<raw statement>"`.
|
|
43
|
-
- **Picker:
|
|
44
|
-
- **Transcribe**:
|
|
43
|
+
- **Picker: the row's `options[]` plus `Enter directly`** — slots follow array order, the `role: recommended` entry first with its label suffixed `(Recommended)`, `Enter directly` always last. Each `label` is the option's `answer`; each `description` is `<rationale> — Scope: <scopeImpact> · Added work: <addedWork> · Direction: <directionChange>`, in that fixed order. Never fold the three axes into one phrase. An empty axis is written `not stated in the report` — never inferred. More than three entries: keep the recommended one plus the two alternatives whose `scopeImpact` differs most, and say how many were left out. Never mark anything but `recommended` as recommended.
|
|
44
|
+
- **Transcribe**: an `options[]` pick → `value` = that option's `answer` text, `disposition:"answer"`; `Enter directly` → the user's utterance verbatim, `disposition:"answer"`; free text asking for a re-ask → `disposition:"reframe"` (does not satisfy the approval gate). A question back from the user records nothing — **Read** the ref, explain, re-ask the same item with the same options. Echo `[n/N] C-014 → answer: …` and move on. Each item's JSON: `{id, kind, value, rationale?, disposition}`.
|
|
45
45
|
4. **echo → confirmed gate**: before `write`, echo the whole collection (each `id`·`disposition`·`value`·`rationale`·approval) as-is and get explicit confirmation. Never `write` before `confirmed`. On any change, re-echo and re-confirm.
|
|
46
46
|
5. **approval (optional)**: only when the approval-blocking items are **all filled with an answer** and the user explicitly approved, `--approval '{"approved":true,"implementationOption":"<selected option>"}'`. If any item is unfilled/reframe, do not approve and say the gate is still open.
|
|
47
47
|
6. **write**: `okstra user-response write --report <reportPath> --answers '<json>' [--approval '<json>'] --task-key <taskKey>` → report the returned `{sidecar:<path>}`. (When a same-named sidecar exists, the same `id` is overwritten with the new value and merged.)
|
|
@@ -175,11 +175,14 @@ Runtime/install asset changes follow this checklist:
|
|
|
175
175
|
| `resolve-task-key` | `src/commands/inspect/resolve-task-key.mjs` | Resolve a bare task-id to candidate task-keys from the project catalog |
|
|
176
176
|
| `set-work-status` | `src/commands/inspect/set-work-status.mjs` | Set a task's user-managed `workStatus` in task-manifest.json (Python: `okstra_ctl.set_work_status`) |
|
|
177
177
|
| `time-report`, `log-report`, `error-report`, `error-zip` | `src/commands/inspect/*.mjs` | Read-side task runtime, wrapper log, and error aggregation helpers |
|
|
178
|
+
| `run-audit`, `error-issue` | `src/commands/inspect/run-audit.mjs`, `src/commands/inspect/error-issue.mjs` | Anomaly detection and issue filing — `run-audit` checks run artifacts against progress invariants (read-only), `error-issue plan/submit` turns anomalies into GitHub issue candidates and files the approved ones (Python: `okstra_ctl.run_audit`, `okstra_ctl.error_issue`) |
|
|
178
179
|
| `worker-liveness` | `src/commands/inspect/worker-liveness.mjs` | Report whether pending workers are still alive, so the lead's poll ends a stalled wait early instead of paying the deadline (Python: `okstra_ctl.worker_liveness`) |
|
|
180
|
+
| `worker-audit-check` | `src/commands/execute/worker-audit-check.mjs` | Apply the Phase 7 worker audit-sidecar rules while the worker session is still alive, so it can fix its own citations (Python: `okstra_ctl.worker_audit_check`, rules in `okstra_ctl.worker_audit_ledger`) |
|
|
179
181
|
| `context-cost` | `src/commands/inspect/context-cost.mjs` | Estimate task bundle file/read context cost |
|
|
180
182
|
| `worktree-lookup` | `src/commands/execute/worktree-lookup.mjs` | Look up a task-key's registered worktree |
|
|
181
183
|
| `plan-validate` | `src/commands/execute/plan-validate.mjs` | Check approved-plan approval marker |
|
|
182
184
|
| `render-bundle` | `src/commands/execute/render-bundle.mjs` | Preview `prepare_task_bundle(render_only=True)` |
|
|
185
|
+
| `profile` | `src/commands/inspect/profile-show.mjs` | Print a phase profile with `{{INCLUDE:}}` expanded and its lazy-read sidecars appended transitively, so one grep answers whether a task-type covers a rule — a top-level grep alone returns false negatives (Python: `okstra_ctl.profile_show`). Read-only, unlike `render-bundle` |
|
|
183
186
|
| `run` | `src/commands/execute/run.mjs` | Host-aware execution front door (`auto` → Claude/Codex/Antigravity/external path selection) |
|
|
184
187
|
| `codex-run`, `codex-dispatch` | `src/commands/execute/codex-*.mjs` | Codex lead dry-run bundle preparation and CLI-backed worker dispatch |
|
|
185
188
|
| `team` | `src/commands/execute/team.mjs` | External lead tmux-pane worker dispatch / await / teardown |
|
|
@@ -268,6 +271,7 @@ Important modules:
|
|
|
268
271
|
| `index.py`, `jsonl.py`, `reconcile.py`, `listing.py`, `batch.py`, `backfill.py` | `~/.okstra` run index and history operations |
|
|
269
272
|
| `run_index_row.py` | single reference point for creating / slimming / hydrating a `~/.okstra` run-index row — runId SSOT, preserves projectId raw |
|
|
270
273
|
| `error_report.py`, `error_log_core.py`, `error_zip.py` | backend for the okstra-inspect errors/error-zip facets — `error_log_core` is the read-only core that globs/parses/aggregates `errors-*.jsonl`, `error_report` renders the errors facet, and `error_zip` collects cross-project run directories, allowlist-anonymizes, aggregates clusters, and produces a zip |
|
|
274
|
+
| `run_audit.py`, `issue_signals.py`, `error_issue.py` | backend for the okstra-inspect run-audit/error-issue facets — `run_audit` reads run-manifest / final-report / team-state artifacts and reports invariant violations (read-only, never the lead's self-report); `issue_signals` computes the verdict signals from pre-anonymization records and classifies a cluster as okstra-defect / environment-policy / target-code; `error_issue` applies the quantitative gate, fingerprints clusters, matches existing issues via `gh`, renders the outbound body, and enforces the last-gate allowlist that keeps target identity out of a public repo |
|
|
271
275
|
| `worker_heartbeat.py`, `worker_liveness.py` | `worker_heartbeat` is the single definition of the `- PROGRESS:` heartbeat line shape and its 5-minute (+60s grace) cadence budget, shared by the Phase 7 audit (`validators/validate_session_conformance.py`) and the live probe; `worker_liveness` backs `okstra worker-liveness`, resolving each pending worker from its team-state row (`livenessMode` picks the artifact, `startedAt` anchors the grace) and reporting `stalled` (heartbeat past the budget, or none yet for this dispatch past the grace) or `did-not-launch` (no wrapper `.log`/`.status.json` past the launch grace) |
|
|
272
276
|
| `log_report.py`, `time_report.py` | read-side backend for the okstra-inspect logs/time facets (`okstra log-report` pairs each wrapper transcript `.log` with its sibling prompt `.md` and reports both byte counts without changing legacy transcript-size fields; `okstra time-report` is per-task time aggregation) |
|
|
273
277
|
| `rollup.py` | read-side backend for the okstra-rollup skill — fans the catalog out per task-group (or the whole project) and deterministically aggregates each task's run count, elapsed time (raw ms), error count, and latest report path, plus group-level totals/status, category, and phase distribution. Reuses the `time_report`/`error_log_core` functions and delegates report-body synthesis to the skill |
|
|
@@ -403,7 +407,7 @@ Boilerplate shared by several skills (bash invocation rule, outdated-CLI preflig
|
|
|
403
407
|
| `okstra-brief-gen` | yes | Produce task brief from ticket/doc/link/conversation |
|
|
404
408
|
| `okstra-run` | yes | Start/resume an okstra task in the current Claude Code, Codex, or Antigravity host session |
|
|
405
409
|
| `okstra-memory` | yes | Store/search/archive global conversation memory under `~/.okstra/memory-book` |
|
|
406
|
-
| `okstra-inspect` | yes | Unified read-side — sub-commands `status` (lifecycle + workStatus), `history` (past runs / re-run / resume), `report` (find final-report), `time` (elapsed-time breakdown), `logs` (wrapper log inventory + cleanup), `cost` (task bundle context/read cost), `errors` (error-log aggregation), `error-zip` (anonymized cross-project error bundle), `recap` (cross-run phase recap). `SKILL.md` is a thin core (preflight + dispatch table + shared rules) and each sub-command body lives in `skills/okstra-inspect/facets/<sub-command>.md`, lazily read only after dispatch resolves; the 1:1 match between dispatch rows and facet files is enforced by `tests/contract/test_okstra_inspect_facets.py` |
|
|
410
|
+
| `okstra-inspect` | yes | Unified read-side — sub-commands `status` (lifecycle + workStatus), `history` (past runs / re-run / resume), `report` (find final-report), `time` (elapsed-time breakdown), `logs` (wrapper log inventory + cleanup), `cost` (task bundle context/read cost), `errors` (error-log aggregation), `error-zip` (anonymized cross-project error bundle), `run-audit` (progress-invariant audit over run artifacts), `error-issue` (anomaly → GitHub issue candidates, filed only after explicit approval), `recap` (cross-run phase recap). `SKILL.md` is a thin core (preflight + dispatch table + shared rules) and each sub-command body lives in `skills/okstra-inspect/facets/<sub-command>.md`, lazily read only after dispatch resolves; the 1:1 match between dispatch rows and facet files is enforced by `tests/contract/test_okstra_inspect_facets.py` |
|
|
407
411
|
| `okstra-rollup` | yes | Cross-task roll-up — aggregate runs/time/errors across a task-group (or whole project) and synthesize a digest from the report files |
|
|
408
412
|
| `okstra-usage` | yes | Read-only project usage snapshot — aggregate recent run coverage, tokens, known cost, CPU, and wall-clock time by task type (default: 30 days) |
|
|
409
413
|
| `okstra-schedule-gen` | yes | Generate task-group schedule |
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
- [1. Purpose](#1-purpose)
|
|
6
6
|
- [2. okstra-run wizard flow](#2-okstra-run-wizard-flow)
|
|
7
|
+
- [Carry-in](#carry-in)
|
|
7
8
|
- [3. runtime gate](#3-runtime-gate)
|
|
8
9
|
- [3.1 design-preparation preflight](#31-design-preparation-preflight)
|
|
9
10
|
- [4. executor and verifier](#4-executor-and-verifier)
|
|
@@ -43,6 +44,33 @@ flowchart TD
|
|
|
43
44
|
|
|
44
45
|
The current okstra-run wizard path does not expose `--approve` that directly flips the approval checkbox. The plan file must already have a recognized approval marker.
|
|
45
46
|
|
|
47
|
+
## Carry-in
|
|
48
|
+
|
|
49
|
+
Three facts about what reaches an implementation run from its approved plan, gathered
|
|
50
|
+
here because they were previously readable only by tracing the runtime sources.
|
|
51
|
+
|
|
52
|
+
- **What is attached automatically.** The user's answers to the approved plan's `## 1.
|
|
53
|
+
Clarification Items` rows — the `user-response-*.md` sidecars under
|
|
54
|
+
`runs/implementation-planning/user-responses/`, a sibling of the directory holding the
|
|
55
|
+
plan itself — are collected into `instruction-set/clarification-response.md`. Those
|
|
56
|
+
sidecars are written by the user, not by the report renderer: the report HTML's `Export
|
|
57
|
+
user response` button downloads a file the user then saves there, and `okstra
|
|
58
|
+
user-response write` writes one directly. The renderer at most pre-creates that
|
|
59
|
+
directory empty so the user does not have to; it never puts a sidecar in it.
|
|
60
|
+
The plan document is *not* copied: it reaches the run as the `--approved-plan` path and
|
|
61
|
+
the executor re-reads it there. An explicit `--clarification-response` wins when given;
|
|
62
|
+
the automatic attachment is the fallback for an implementation run that supplies none
|
|
63
|
+
(`scripts/okstra_ctl/run.py`, the `implementation` carry-in branch).
|
|
64
|
+
- **Who reads it, and when.** The executor, before its first edit
|
|
65
|
+
(`prompts/profiles/_implementation-executor.md`). A CLI executor (codex/antigravity)
|
|
66
|
+
cannot reach that path from inside its sandbox, so the lead transcribes the file's body
|
|
67
|
+
into the dispatched executor prompt — a path reference alone never arrives.
|
|
68
|
+
- **What happens when an answer contradicts the plan.** Each answer is an authoritative
|
|
69
|
+
refinement of its matching row's scope, but an answer that contradicts the approved plan
|
|
70
|
+
or expands scope beyond it is a re-plan trigger: it routes to a new
|
|
71
|
+
`implementation-planning` run rather than being absorbed silently mid-run. Quietly
|
|
72
|
+
widening scope inside an implementation run is what this branch exists to prevent.
|
|
73
|
+
|
|
46
74
|
## 3. runtime gate
|
|
47
75
|
|
|
48
76
|
```mermaid
|
package/package.json
CHANGED
package/runtime/BUILD.json
CHANGED
|
@@ -102,7 +102,7 @@ Rules (the schema enforces most of these — they are listed here so you know *w
|
|
|
102
102
|
- Read the exact permitted header values from the task bundle schema excerpt. In the current v2 contract, `header.reportOwner` is `"Okstra lead"` and `header.reportAuthor` is `"Report writer worker"`. Set author to `"Okstra lead"` only for `release-handoff` runs (single-lead by design) or a recorded report-writer dispatch failure fallback. A legacy v1 excerpt may retain its historical compatibility values; follow that excerpt rather than inferring ownership from the provider.
|
|
103
103
|
- **Source items (worker:item) preservation.** Every `consensus[].sourceItems`, `differences[].workersPosition[].itemId`, and `evidence.primary[].sourceItems` entry MUST carry the worker:item-id pair (e.g. `claude:F-001`, `codex:1.1`, `antigravity:F-3`, or `lead:mcp-1` for lead-only evidence). The schema enforces this via the `SourceItem` regex; bare worker-name lists no longer parse.
|
|
104
104
|
- **Verdict Card consistency.** `verdictCard.verdictToken` and `verdictCard.direction` MUST byte-match `finalVerdict.verdictToken` / `.direction`; `validators/validate-run.py` diffs both and fails the run on divergence. `verdictCard.nextStep` names the same action as `finalVerdict.nextStep` and `recommendedNextSteps[0].text` but is written as the actionable command the reader runs (e.g. `/okstra-run task-key=… task-type=release-handoff`) where the other two are prose — it is deliberately not a byte copy. Duplicating the compared values across `verdictCard` and `finalVerdict` is intentional so the validator can diff them.
|
|
105
|
-
- **Error-analysis diagnosis and routing.** When `header.taskType` is `error-analysis`, populate the required `errorAnalysis` object. Copy `errorAnalysis.symptomVerbatim` byte-for-byte from the symptom stated in the brief's `Source Material`; do not paraphrase it. Every `causeCandidates[]` row includes the full `supportingEvidence`, `falsifyingEvidenceChecked`, `confidence`, and `disproveWith` fields. Route `errorAnalysis.routing.nextTaskType=implementation-planning` with `direction=begin-planning`, or route `errorAnalysis.routing.nextTaskType=error-analysis` with `direction=continue-investigation`; no other pairing is valid. `verdictCard.nextStep`, `finalVerdict.nextStep`, the first `recommendedNextSteps` action and command, and the unique `followUpTasks` row whose `origin` is `phase-continuation` MUST all point to the same `errorAnalysis.routing.nextTaskType` target. The schema enforces only the presence of a `phase-continuation` row. Phase validation MUST enforce exact target agreement and uniqueness through `validators/validate-run.py::_validate_error_analysis_consistency`; until that check is implemented and executed, those semantics are contract requirements rather than enforced guarantees.
|
|
105
|
+
- **Error-analysis diagnosis and routing.** When `header.taskType` is `error-analysis`, populate the required `errorAnalysis` object. Copy `errorAnalysis.symptomVerbatim` byte-for-byte from the symptom stated in the brief's `Source Material`; do not paraphrase it. Every `causeCandidates[]` row includes the full `supportingEvidence`, `falsifyingEvidenceChecked`, `confidence`, and `disproveWith` fields. When a candidate is a step in a propagation chain rather than a competing explanation — the analysis calls it a downstream step, a second stage, or a consequence of another candidate — set its `downstreamOf` to the ids of the candidates immediately upstream of it; leave the field absent for a candidate that stands on its own. Every id listed MUST be another candidate in the same report, no row may name itself, and the links MUST NOT form a cycle; `validators/validate-run.py::_validate_cause_chain` rejects all three. This is the only place the chain is machine-readable — prose calling a candidate "the second step of the chain" while `downstreamOf` is absent leaves the report's figure claiming the candidates are alternatives. Route `errorAnalysis.routing.nextTaskType=implementation-planning` with `direction=begin-planning`, or route `errorAnalysis.routing.nextTaskType=error-analysis` with `direction=continue-investigation`; no other pairing is valid. `verdictCard.nextStep`, `finalVerdict.nextStep`, the first `recommendedNextSteps` action and command, and the unique `followUpTasks` row whose `origin` is `phase-continuation` MUST all point to the same `errorAnalysis.routing.nextTaskType` target. The schema enforces only the presence of a `phase-continuation` row. Phase validation MUST enforce exact target agreement and uniqueness through `validators/validate-run.py::_validate_error_analysis_consistency`; until that check is implemented and executed, those semantics are contract requirements rather than enforced guarantees.
|
|
106
106
|
- **Human narrative.** Populate required `humanSummary` and the selected task block's `userNarrative`. Human-visible analysis facts must not exist only in Markdown; HTML is derived independently and can use only data.json. Keep worker discussion and audit details in `crossVerification`, `executionStatus`, and `tokenUsage`, outside the human narrative fields.
|
|
107
107
|
- **External QA advisory.** A Tier 3 entry requiring `db`, `http`, or
|
|
108
108
|
`external` may be non-PASS without changing approval or final verdict. Render
|
|
@@ -114,7 +114,10 @@ stdout_tee_pid=$!
|
|
|
114
114
|
tee -a "$log_path" < "$stderr_fifo" >&2 &
|
|
115
115
|
stderr_tee_pid=$!
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
# `--verbose` is mandatory, not cosmetic: Claude Code rejects `--print` combined
|
|
118
|
+
# with `--output-format=stream-json` without it ("requires --verbose") and exits
|
|
119
|
+
# 1 in under a second, so every CLI-wrapper claude worker dies before starting.
|
|
120
|
+
claude -p --model "$model" ${extra_args[@]+"${extra_args[@]}"} --output-format=stream-json --verbose \
|
|
118
121
|
< "$prompt_path" \
|
|
119
122
|
> "$stdout_fifo" \
|
|
120
123
|
2> "$stderr_fifo" &
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Host orchestration rules
|
|
2
|
+
|
|
3
|
+
One file per task-type whose host orchestration carries gates. A task-type with
|
|
4
|
+
no gates has no file here, and its runs get no
|
|
5
|
+
`instruction-set/host-orchestration-rules.md`.
|
|
6
|
+
|
|
7
|
+
Each file is the single source for two generated surfaces:
|
|
8
|
+
|
|
9
|
+
- `skills/okstra-run/SKILL.md` — a `<!-- BEGIN FRAGMENT: host-orchestration-<task-type> -->`
|
|
10
|
+
block, synced by `tools/sync-skill-fragments.mjs` (`--check` fails on drift).
|
|
11
|
+
- `<run>/instruction-set/host-orchestration-rules.md` — written by
|
|
12
|
+
`scripts/okstra_ctl/run.py` at prepare time.
|
|
13
|
+
|
|
14
|
+
The second surface exists because a rule that lives only in the conversation is
|
|
15
|
+
one compaction away from gone: a DEV-10400 run operated for five turns on a
|
|
16
|
+
skill body truncated mid-Step-5 and nothing signalled the loss. On disk, the
|
|
17
|
+
rules survive compaction and `validators/validate_session_conformance.py` can
|
|
18
|
+
check after the fact that they were read.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
## Host orchestration rules — implementation
|
|
2
|
+
|
|
3
|
+
These are the rules the **host orchestrator** follows around an `implementation`
|
|
4
|
+
run: when to offer a conformance waiver, what a concurrent-run marker means, how
|
|
5
|
+
to recover a stale stage SHA, and what the chaining queue does when the next
|
|
6
|
+
stage is not ready. They are not lead phase rules — the lead's rules live in
|
|
7
|
+
`prompts/profiles/`.
|
|
8
|
+
|
|
9
|
+
This file is the single source. Two surfaces are generated from it: the
|
|
10
|
+
`okstra-run` skill body (marker block, synced by `tools/sync-skill-fragments.mjs`)
|
|
11
|
+
and each run's `instruction-set/host-orchestration-rules.md`. Edit here.
|
|
12
|
+
|
|
13
|
+
### Step 5.1 (implementation only): blocking local conformance waiver offer
|
|
14
|
+
|
|
15
|
+
`render-bundle` accepts an optional `--qa-waiver "<stageKey>:<reason>"` flag (implementation only). It records a **user-acknowledged** waiver into the task-level conformance manifest entry (`entry.waiver`), letting the run proceed when an `io`-only Tier 3 conformance script genuinely cannot run. The waiver records the user's reason **verbatim**.
|
|
16
|
+
|
|
17
|
+
Inspect the selected manifest entry's `requires`. If it contains `db`, `http`,
|
|
18
|
+
or `external`, it is external-advisory: Do not offer a waiver and continue so
|
|
19
|
+
the verifier can attempt automatic startup/execution. A non-PASS outcome will
|
|
20
|
+
become a user-owned follow-up. If `requires=[]`, fail closed as declaration or
|
|
21
|
+
contract trouble: Do not offer a waiver for `requires=[]`. Offer the existing
|
|
22
|
+
waiver picker only when `requires=[io]` and that local command genuinely cannot run.
|
|
23
|
+
|
|
24
|
+
This is **never** a lead/worker self-exemption — only the user may waive. After classification confirms `requires=[io]`, surface it as a 3-option recommendation picker (per the run-prompt recommendation rule):
|
|
25
|
+
|
|
26
|
+
1. (recommended) Run the conformance script — no waiver.
|
|
27
|
+
2. Waive this stage — ask the user for the exact `<stageKey>` and reason, then pass `--qa-waiver "<stageKey>:<reason>"` to `render-bundle` (reason = the user's words, unedited).
|
|
28
|
+
3. Enter directly — the user types the full `<stageKey>:<reason>` value.
|
|
29
|
+
|
|
30
|
+
When the user picks a waiver, append `--qa-waiver "<stageKey>:<reason>"` to the `render-bundle` invocation above. Omit the flag entirely otherwise (do **not** pass `--qa-waiver ""`). A malformed value or unknown `<stageKey>` aborts `render-bundle` with a `PrepareError`.
|
|
31
|
+
|
|
32
|
+
### Concurrent-run detection branch (concurrent-run)
|
|
33
|
+
|
|
34
|
+
If `render-bundle` stdout carries an `okstra concurrent-run stages: <stages>` label line (another implementation run on the same task-key is occupying `<stages>`), the launch prompt has already been rendered with the "Concurrent-run marker" gate. If this line is absent it is not a concurrent run, so skip this branch. If present, before dispatch present a 3-option recommendation picker to the user (run-prompt recommendation rule: 1–2 recommendations + Enter directly; this picker is authored by the skill, so it is unconstrained by the wizard `options[]` rule):
|
|
35
|
+
|
|
36
|
+
1. (recommended) Proceed as-is — use the already-rendered bundle. Each session uses its own implicit team, so concurrent runs have no team conflict and split-pane works fine.
|
|
37
|
+
2. Wait — hold the dispatch for now. The stage worktree·run-context are preserved, so after the other occupying run finishes, resuming the same stage takes the normal team path. Print the resume command (`okstra-inspect` history → resume) to the user.
|
|
38
|
+
3. Enter directly.
|
|
39
|
+
|
|
40
|
+
### Stale git SHA recovery (git-reconcile gate)
|
|
41
|
+
|
|
42
|
+
If `render-bundle` fails with a `PrepareError` containing `Recorded stage SHAs no longer match the git history`, the git history changed outside okstra (rebase / squash / review-feedback amend / branch deletion). Never fix the registry/consumers by hand; recover in this order:
|
|
43
|
+
|
|
44
|
+
1. Run the `okstra git-reconcile … --check --json` command printed in the error message verbatim to get the stale report. (Items whose content-identity is proven by patch-id were already auto-reconciled by prepare, so only confirm items remain here.)
|
|
45
|
+
2. For each confirm item, present a 3-option picker to the user:
|
|
46
|
+
- **Re-record to the `stage-<N>` branch's current tip (recommended)** — when an intended change such as review feedback lives on that branch.
|
|
47
|
+
- **Enter a different ref directly** — the user names a commit/branch/tag.
|
|
48
|
+
- **Abort** — stop the run without recovering.
|
|
49
|
+
3. Run `okstra git-reconcile … --apply --stage <N> --use-ref <ref>` with the chosen ref, then retry the failed `render-bundle` with the same arguments.
|
|
50
|
+
|
|
51
|
+
If the anchor (`implementation_base_commit`) is reported unresolvable, run the same command's `--reset-anchor <ref>` after user confirmation. Correcting a confirm item without the picker is forbidden — the runtime also rejects a confirm correction without `--use-ref`.
|
|
52
|
+
|
|
53
|
+
### Next stage not yet ready — normal termination (not an exception gate)
|
|
54
|
+
Because of the dependency closure, the chain queue **may include a stage that another implementation run has occupied as started/reserved.** That stage's `render-bundle` is rejected with `--stage N already in progress or reserved by another run` (StageTargetError). This is **not** an exception gate needing human judgment but a "next stage not yet ready" situation. On this rejection, **terminate the chain normally** and report the remaining queue to the user (e.g. `remaining queue: stage 4, 5 — resume with okstra-run after occupancy is released`). This is a different branch from the exception gate below (data corruption·concurrent-occupancy conflict confirmation).
|
|
55
|
+
|
|
56
|
+
### Exception gate during chaining
|
|
57
|
+
If `render-bundle` raises Step 5's concurrent-run conflict detection (concurrent-run branch) or git stale-SHA reconciliation (git-reconcile branch), **stop the chain at that stage** and present the gate to the user exactly as Step 5 prescribes. Once the user resolves the gate, resume the chain in place (continue with the remaining queue). Data corruption·concurrent-occupancy conflicts are confirmed by a human — this is the safety boundary of unattended chaining. (Unlike the "not ready" rejection above, these two branches do not discard the queue; they wait for user resolution.)
|
|
@@ -80,10 +80,19 @@ Emit one `PROGRESS: <phase-id> <verb-phrase>` line as plain user-facing text at
|
|
|
80
80
|
- Codex worker and Antigravity worker run external CLIs; they can only use these MCP servers if their own CLI configs mirror them. If not, instruct the worker to record `MCP not available in this CLI` in its `Missing Information or Assumptions` block rather than guessing or shell-falling-back.
|
|
81
81
|
- MCP queries are evidence-grade. Cite server, table, and the SELECT used in worker output. MCP must NOT be used as a write path in any phase, including `implementation`.
|
|
82
82
|
|
|
83
|
+
## Host Orchestration Rules
|
|
84
|
+
|
|
85
|
+
- Path: `{{HOST_ORCHESTRATION_RULES_RELATIVE_PATH}}`
|
|
86
|
+
- If the path above is empty, this task-type carries no host orchestration gates and there is nothing to read.
|
|
87
|
+
- If it is set, that file is the durable copy of the rules the host follows *around* the run — the conformance waiver offer, the concurrent-run branch, the stale-SHA recovery order, and what the chaining queue does when the next stage is not ready. Read it once during intake, then re-read it whenever you are about to act on one of those gates and again after any compaction. It is on disk precisely because the conversation copy does not survive compaction: a prior run operated for five turns on a truncated copy and nothing signalled the loss.
|
|
88
|
+
- **Enforced:** for an `implementation` run, `validators/validate_session_conformance.py` fails the run when its conformance evidence source records no read of this file inside the run window. Artifact-accounted adapters record the read the way they record the implementation sidecar reads.
|
|
89
|
+
- Acting on any of those gates without having read this file is how a run offers the user a waiver it should not have offered, or edits a registry it must not touch by hand.
|
|
90
|
+
|
|
83
91
|
## Clarification Response Carried In
|
|
84
92
|
|
|
85
93
|
- Source path: `{{CLARIFICATION_RESPONSE_RELATIVE_PATH}}`
|
|
86
94
|
- If the source path above is empty, no prior clarification response was attached to this run.
|
|
95
|
+
- When this task's earlier runs recorded `contract-violation` or `tool-failure` errors, a digest is staged at `{{INSTRUCTION_SET_RELATIVE_PATH}}/prior-run-errors.md`. Read it before dispatching workers and act on it — adjust the roster or pre-check the result of a worker that broke its contract, raise the budget for a tool that timed out. These are not findings about the work; they are traps that already fired on this task. The file is absent when nothing actionable was recorded, so its absence is not something to report.
|
|
87
96
|
- If the source path is set, a copy is staged at `{{INSTRUCTION_SET_RELATIVE_PATH}}/clarification-response.md`. Read it before running workers; reconcile each `C-*` row in section 1 (`## 1. Clarification Items`) of the prior report against new evidence and record the outcome in the conditional `## 0. Clarification Response Carried In From Previous Run` section of this run's final report (render that heading only when carry-in is non-empty — the validator fails empty Section 0 stubs).
|
|
88
97
|
- When a `## <C-id>` block carries `- Disposition: reframe`, it is not an answer but a request to re-question — the user is asking you to redefine this item. Do not treat it as answered; reconstruct the question itself in a fresh `## 1` Clarification Item, and never let a `reframe` item satisfy the approval gate.
|
|
89
98
|
|
|
@@ -91,7 +100,7 @@ Emit one `PROGRESS: <phase-id> <verb-phrase>` line as plain user-facing text at
|
|
|
91
100
|
|
|
92
101
|
The **default is full re-verification**. Only narrow this re-run to the impacted stages when the deterministic `okstra incremental-scope` CLI returns `mode == "incremental"`; on any doubt, stay full. This procedure fires ONLY when this run's task-type is `implementation-planning` AND a prior final report exists for this task-key (its data.json at `runs/implementation-planning/reports/final-report-implementation-planning-<prev-seq>.data.json`, where `<prev-seq>` is the most recent prior implementation-planning run's seq). For every other task-type, ignore this block and re-verify normally. This branches on the CLI's `mode` output only — it does NOT re-implement the safety logic in the prompt.
|
|
93
102
|
|
|
94
|
-
1. **List the answered clarifications (a fact, not a judgement).** Collect the `C-NNN` ids you reconciled as answered in §1, and the IDs of any PREP items changed by the carried response. Pass the ids through `--answered-clarifications`; the CLI resolves which Stage Map stages each one touches by reading the prior run's own links — the `P-*` plan item that carried that `clarificationId`, and the requirement-coverage row
|
|
103
|
+
1. **List the answered clarifications (a fact, not a judgement).** Collect the `C-NNN` ids you reconciled as answered in §1, and the IDs of any PREP items changed by the carried response. Pass the ids through `--answered-clarifications`; the CLI resolves which Stage Map stages each one touches by reading the prior run's own links — the `P-*` plan item that carried that `clarificationId`, and the requirement-coverage row blocked on `C-NNN` in either its `status` or its `approvalDisposition` (a `documented-deviation` row records the block in the latter). Do NOT map answers to stage numbers yourself.
|
|
95
104
|
- An id that traces to no stage in the prior report makes the CLI return `mode == "full"` for the whole re-run. That is the intended outcome: an answer whose blast radius the prior report never recorded must not narrow anything.
|
|
96
105
|
- **Structural change is your call, and you declare it.** When an answer overturns the selected Option, restructures the stages, or changes the recommended approach, pass `--full-reason "<what changes and how>"`. It forces `mode == "full"` regardless of every other input — the back-trace resolves stages, it cannot judge whether the plan's shape survived. Do NOT express this by leaving the CSVs empty: that produces the same `no impacted stages resolved` reason as a re-run that simply failed to map anything, and the two become indistinguishable in the record. `--impacted` remains available for stage numbers you resolved yourself.
|
|
97
106
|
- Pass ONLY stage numbers that appear in that Stage Map when you do use `--impacted`. Never invent or guess a stage number — a number absent from the graph must never enter `--impacted` (it would leak into `reverify_stages`).
|
|
@@ -64,7 +64,7 @@ This adapter maps the neutral Okstra lead operations to Claude Code host primiti
|
|
|
64
64
|
- Follow the core Result Path + terminal-status completion contract. The Claude adapter's wake mechanism is one `Bash(run_in_background: true)` poll covering every pending Result Path, not foreground sleep or an idle-notification dependency. A spawn acknowledgement is never completion.
|
|
65
65
|
- The background poll uses a per-worker deadline of twice the expected duration: 20 minutes for `requirements-discovery`, 30 for `error-analysis`, 40 for `implementation-planning`, 40 for `implementation`, and 20 for `final-verification`. On timeout, record terminal status and apply the core's single shared retry budget.
|
|
66
66
|
- Each in-process worker heartbeat audit sidecar must update at least every five minutes while its result is pending. A missing or stale heartbeat consumes the same one-retry budget; after the second silent hang, record `timeout`. The result file remains the authoritative completion signal.
|
|
67
|
-
- **The background poll checks liveness, not only Result Paths.** Result Paths change once, at the very end, so polling them alone pays the full deadline for a worker that died at minute three. Each poll iteration MUST also run, in the same background shell, one `okstra worker-liveness` call covering every pending worker — one paired `--team-state <path> --worker <id>` per worker, in-process and CLI-wrapper alike. The probe reads that worker row's `livenessMode` to pick the artifact and its `startedAt` as the grace anchor; never pass an artifact path yourself and never infer the transport from provider or filename. It exits non-zero when a worker is `stalled` (heartbeat older than the cadence budget) or `did-not-launch`; either verdict ends the wait for that worker immediately and spends the core's one-retry budget, rather than waiting out the deadline. The command reports only — it never kills or re-dispatches. It shares its heartbeat budget with the Phase 7 audit (`okstra_ctl.worker_heartbeat`), so a worker the live probe passes cannot fail the post-hoc one for cadence.
|
|
67
|
+
- **The background poll checks liveness, not only Result Paths.** Result Paths change once, at the very end, so polling them alone pays the full deadline for a worker that died at minute three. Each poll iteration MUST also run, in the same background shell, one `okstra worker-liveness` call covering every pending worker — one paired `--team-state <path> --worker <id>` per worker, in-process and CLI-wrapper alike. The probe reads that worker row's `livenessMode` to pick the artifact and its `startedAt` as the grace anchor; never pass an artifact path yourself and never infer the transport from provider or filename. It exits non-zero when a worker is `stalled` (heartbeat older than the cadence budget) or `did-not-launch`; either verdict ends the wait for that worker immediately and spends the core's one-retry budget, rather than waiting out the deadline. The command reports only — it never kills or re-dispatches. It shares its heartbeat budget with the Phase 7 audit (`okstra_ctl.worker_heartbeat`), so a worker the live probe passes cannot fail the post-hoc one for cadence. A `stalled` verdict is confirmed before it is returned — the probe waits half the stage's budget and re-reads, so a worker that is merely slow gets to prove it by appending its next heartbeat. Budget that confirmation window into the poll iteration; it is the price of not spending the one-retry budget on a live worker.
|
|
68
68
|
- The Claude Code harness blocks long foreground sleeps and shorter-sleep circumvention loops. Keep the result poll in a single background shell and let wrapper agents use their documented `BashOutput` loop.
|
|
69
69
|
- On approved cleanup, reconcile the current live session roster before sending shutdown requests. Never target the lead session.
|
|
70
70
|
- Collect usage before teardown. Resume through the recorded Claude session id and keep all run artifacts authoritative.
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
| `workflow.awaitingApproval` | Approval wait marker |
|
|
51
51
|
| `workflow.routingStatus` | Routing decision status |
|
|
52
52
|
| `workflow.lastSafeCheckpoint` | Safe resume checkpoint metadata |
|
|
53
|
-
| `instructionSetPath` | Path to the `instruction-set/` **directory** containing `analysis-packet.md`, `analysis-profile.md`, `analysis-material.md`, `reference-expectations.md`, `task-brief.md`, `final-report-template.md` (see Step 4). Not a single-file path. |
|
|
53
|
+
| `instructionSetPath` | Path to the `instruction-set/` **directory** containing `analysis-packet.md`, `analysis-profile.md`, `analysis-material.md`, `reference-expectations.md`, `task-brief.md`, `final-report-template.md`, and — only for task types whose host orchestration carries gates — `host-orchestration-rules.md` (see Step 4). Not a single-file path. |
|
|
54
54
|
| `referenceExpectationsPath` | config/deployment expectation artifact path |
|
|
55
55
|
| `latestRunPath` | latest run path |
|
|
56
56
|
| `latestRunStatus` | latest run status |
|
|
@@ -76,7 +76,8 @@ After identifying the task root in `task-manifest.json`, derive all paths accord
|
|
|
76
76
|
│ ├── analysis-material.md (analysis materials)
|
|
77
77
|
│ ├── reference-expectations.md (config/deployment expected values)
|
|
78
78
|
│ ├── task-brief.md (task brief)
|
|
79
|
-
│
|
|
79
|
+
│ ├── final-report-template.md (Final Report Template)
|
|
80
|
+
│ └── host-orchestration-rules.md (host gate rules; present only for task types whose host orchestration carries gates)
|
|
80
81
|
├── runs/
|
|
81
82
|
│ └── <task-type>/ (Run scope isolated per task-type, e.g. error-analysis)
|
|
82
83
|
│ ├── manifests/ (run-manifest-<task-type>-<seq>.json)
|
|
@@ -116,6 +117,7 @@ After verifying `task-manifest.json`, read only the compact intake files needed
|
|
|
116
117
|
1. `instruction-set/analysis-profile.md` (analysis guide by task type)
|
|
117
118
|
2. `instruction-set/analysis-packet.md` (primary compact input for analysis workers)
|
|
118
119
|
3. `runs/<task-type>/state/active-run-context-<task-type>-<seq>.json` if present (compact current-run path/worker snapshot)
|
|
120
|
+
4. `instruction-set/host-orchestration-rules.md` when the launch prompt's Host Orchestration Rules path is set. Read it here even though no gate has fired yet — the gates it governs fire around `render-bundle`, so waiting for one means reading it too late, and this is the copy that survives compaction. **Enforced:** Phase 7 conformance fails an `implementation` run whose evidence source records no read of it.
|
|
119
121
|
|
|
120
122
|
Read source files lazily:
|
|
121
123
|
|
|
@@ -123,6 +125,7 @@ Read source files lazily:
|
|
|
123
125
|
- `instruction-set/analysis-material.md` only when packet content is insufficient or a source citation needs verification.
|
|
124
126
|
- `instruction-set/reference-expectations.md` for report-writer synthesis or when packet expectation extract is insufficient.
|
|
125
127
|
- `instruction-set/final-report-template.md` only for report-writer authoring.
|
|
128
|
+
- `instruction-set/host-orchestration-rules.md` — already read at Step 4; re-read it whenever you are about to act on a host gate — the conformance waiver offer, the concurrent-run branch, stale-SHA recovery, the chaining queue — and again after any compaction. Absent file means this task type carries no host gates.
|
|
126
129
|
|
|
127
130
|
### Brief Reporter-Confirmation Precondition (BLOCKING)
|
|
128
131
|
|
|
@@ -409,7 +409,9 @@ re-read the task brief, instruction-set, or report template.
|
|
|
409
409
|
...
|
|
410
410
|
```
|
|
411
411
|
|
|
412
|
-
When persisting votes, map SURVIVES→`agree`, SURVIVES-WITH-CAVEAT→`supplement`, REFUTED→`disagree`, and UNVERIFIABLE→`
|
|
412
|
+
When persisting votes, map SURVIVES→`agree`, SURVIVES-WITH-CAVEAT→`supplement`, REFUTED→`disagree`, and UNVERIFIABLE→`unverifiable`; copy the stated Basis into `votes.<worker>.disagreeBasis` (null for non-REFUTED verdicts). Every vote requires a non-empty `explanation`.
|
|
413
|
+
|
|
414
|
+
UNVERIFIABLE is **not** `verification-error`. A verifier that opened the evidence and could not check it participated in the round; a `verification-error` is a verifier that failed to answer. The classifier counts only non-error votes, so folding the two shrinks the participating roster without saying so — a round where one analyser answers UNVERIFIABLE throughout would read as a two-way cross-check while reporting three voters. **Enforced:** `okstra convergence collect-results` applies this mapping (`okstra_ctl.verdict_blocks.ADVERSARIAL_VERDICTS`); do not transcribe votes by hand.
|
|
413
415
|
|
|
414
416
|
### Full Re-analysis Re-verification Prompt
|
|
415
417
|
|