okstra 0.159.0 → 0.161.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 +2 -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/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/adapters/cmux.md +67 -0
- 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/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/cmux.py +531 -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 +76 -7
- package/runtime/python/okstra_ctl/dispatch_state.py +16 -0
- 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/lead_runtime.py +30 -2
- 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.py +7 -2
- package/runtime/python/okstra_ctl/render_final_report.py +7 -22
- 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 +54 -3
- package/runtime/python/okstra_ctl/run_audit.py +477 -0
- package/runtime/python/okstra_ctl/team.py +50 -11
- 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 +51 -1
- 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/i18n/en.json +5 -1
- package/runtime/templates/reports/html/i18n/ko.json +5 -1
- package/runtime/templates/reports/html/macros/forms.html +15 -0
- 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 +267 -208
- package/runtime/validators/validate-workflow.sh +6 -0
- package/runtime/validators/validate_session_conformance.py +135 -31
- 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
|
@@ -147,6 +147,7 @@ Runtime entry points are consolidated in Python packages. Bash and skills only c
|
|
|
147
147
|
|
|
148
148
|
- [`prompts/lead/okstra-lead-contract.md`](../prompts/lead/okstra-lead-contract.md) is the runtime-neutral lifecycle core: phase boundaries, artifacts, convergence, report ownership, and persistence semantics.
|
|
149
149
|
- `prompts/lead/adapters/claude-code.md`, `prompts/lead/adapters/codex.md`, `prompts/lead/adapters/antigravity.md`, and `prompts/lead/adapters/external.md` map the same semantic operations to one selected host runtime. The generated launch prompt exposes the core path plus exactly one adapter path.
|
|
150
|
+
- `prompts/lead/adapters/cmux.md` is selected by environment rather than by runtime: when the run manifest's `terminalBackend` is `cmux-pane`, every lead runtime resolves to it and dispatches through `okstra team`, because okstra owns the worker panes on that path instead of the host. It overrides only the adapter and the dispatch mode; the lead's agent, role, and session accounting still come from its own runtime.
|
|
150
151
|
- Runtime metadata and role assignments are persisted separately, but the lead provider is derived from the host: Claude Code maps to Claude, Codex maps to Codex, and Antigravity CLI maps to Antigravity. New runs persist `hostRuntime`, `leadAssignment`, and `workerAssignments[]`; each assignment records its provider, model, execution value, and resolved `native-session` or `cli-wrapper` runner. `lead-execution-prompt.md` is canonical, while `claude-execution-prompt.md` is a byte-identical compatibility alias for historical consumers.
|
|
151
152
|
- Provider registry and front-door separation are implemented: the active Claude Code, Codex, or Antigravity host owns the native lead session, while non-host providers run through their registered CLI wrappers.
|
|
152
153
|
- [`skills/okstra-setup/SKILL.md`](../skills/okstra-setup/SKILL.md) — **first-run bootstrap**. Runs `okstra install` and creates `project.json`.
|
|
@@ -770,7 +771,7 @@ The Phase 7 `render-views` step accepts either a final-report data.json or its M
|
|
|
770
771
|
- **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
772
|
- **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
773
|
- **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**:
|
|
774
|
+
- **`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
775
|
|
|
775
776
|
Entry points:
|
|
776
777
|
|
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
|
@@ -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.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# cmux Lead Runtime Adapter
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
|
|
5
|
+
This adapter maps the neutral Okstra lead operations to a cmux session, where Okstra owns the worker panes regardless of which model is leading. Read it only when the rendered launch prompt selects it; the run manifest's `terminalBackend` is `cmux-pane` for exactly those runs.
|
|
6
|
+
|
|
7
|
+
It replaces the per-runtime adapter, not the lead contract. Your own runtime still decides how you read files, ask the user, and record your session — this file only decides how workers are started, awaited, and reclaimed.
|
|
8
|
+
|
|
9
|
+
## Capability declaration
|
|
10
|
+
|
|
11
|
+
| Field | Value |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `runtime` | environment-selected — any lead runtime resolves to this adapter under cmux |
|
|
14
|
+
| `leadRoleLabel` | `Okstra lead` |
|
|
15
|
+
| `userPromptMode` | `host-text` |
|
|
16
|
+
| `workerDispatchBackend` | `cmux-pane` |
|
|
17
|
+
| `initialPromptDeliveryMode` | `lazy-path-reference` |
|
|
18
|
+
| `sessionAccounting` | unchanged — keep your own runtime's accounting |
|
|
19
|
+
| `resumeMode` | `artifact-checkpoint` |
|
|
20
|
+
| `teardownMode` | `pane-teardown` |
|
|
21
|
+
| `leadEventSource` | `lead-events-jsonl` |
|
|
22
|
+
|
|
23
|
+
## Semantic operation mapping
|
|
24
|
+
|
|
25
|
+
| Operation | Mapping |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `read_artifacts` | Read the manifest-provided paths through the current host's file or shell interface. |
|
|
28
|
+
| `write_artifact` | Write only core-authorized `.okstra/` artifacts and preserve their schemas. |
|
|
29
|
+
| `prompt_user` | Ask through the host text/question interface and require an explicit approval or clarification response. |
|
|
30
|
+
| `dispatch_worker` | Run `okstra team dispatch --project-root <root> --run-manifest <path>`; use `--dry-run` first when the core requires a dispatch preview. |
|
|
31
|
+
| `await_workers` | Run `okstra team await --project-root <root> --run-manifest <path>` through the host's asynchronous shell facility. |
|
|
32
|
+
| `redispatch_worker` | Create the core-specified fresh jobs file and dispatch it with a new `dispatchKind`; never reuse a live worker conversation. |
|
|
33
|
+
| `shutdown_workers` | Run `okstra team teardown --project-root <root> --run-manifest <path>` only after the user-approved cleanup gate. |
|
|
34
|
+
| `record_lead_event` | Append the required structured event to the manifest-provided `leadEventsPath`; emit the matching user-facing `PROGRESS:` line. |
|
|
35
|
+
| `collect_usage` | Collect artifact/CLI-log-backed usage through the existing Okstra token-usage path; never substitute another runtime's session log. |
|
|
36
|
+
|
|
37
|
+
## Pane placement is not yours to compute
|
|
38
|
+
|
|
39
|
+
Okstra creates, sizes, labels, and closes every worker pane. Do not issue terminal-multiplexer commands of any kind — not to place a worker, not to resize the lead, not to reclaim a finished round. Pane geometry depends on the display, and a lead that recomputes it per run gets it wrong differently on every host.
|
|
40
|
+
|
|
41
|
+
Concretely: you never choose a split direction, a pane width, a surface id, or a title. `okstra team dispatch` does all of it and records what it created.
|
|
42
|
+
|
|
43
|
+
## Watching a worker is not the same as judging it
|
|
44
|
+
|
|
45
|
+
Workers run beside you, so you can read their screens. That is a diagnostic channel and nothing more.
|
|
46
|
+
|
|
47
|
+
- A worker is finished when its dispatch record reaches a terminal status and its required Result Paths exist. Nothing you see on a screen changes that verdict.
|
|
48
|
+
- Never parse a pane's contents into a result. Terminal output is a rendered grid — wrapped to the pane's width, with history truncated — so a path or a number read off it may be silently incomplete.
|
|
49
|
+
- Never send input to a running worker. Workers are one-shot sessions whose prompt is already delivered; retries and re-verification always create a fresh session, and interrupting a live worker contaminates exactly the context that rule protects.
|
|
50
|
+
|
|
51
|
+
Use the screen to tell "still working" from "stuck", and to see at a glance which worker failed. Use the artifacts for everything else.
|
|
52
|
+
|
|
53
|
+
## cmux dispatch details
|
|
54
|
+
|
|
55
|
+
- For convergence reverify, consume the persisted round plan exactly. This adapter may map and transport each returned batch, but it cannot change batch membership and does not classify findings or branch on task type, provider, or model identity.
|
|
56
|
+
- Do not invoke Claude Code team tools or `okstra codex-dispatch`. Under cmux every lead dispatches through `okstra team`, including a Claude Code lead.
|
|
57
|
+
- Worker completion is valid only from `workerDispatches[]`, terminal status sidecars, and required Result Paths. Pane creation alone is not completion.
|
|
58
|
+
- Reverify uses a fresh jobs file at `runs/<task-type>/state/reverify-jobs-r<N>-<task-type>-<seq>.json`, sets `dispatchKind: "reverify-r<N>"`, and dispatches with `okstra team dispatch --project-root <root> --run-manifest <path> --dispatch-kind reverify-r<N> --jobs-file <jobs-file>`.
|
|
59
|
+
- Report-writer uses a fresh one-job jobs file with `dispatchKind: "report-writer"` and the same schema, then dispatches through `okstra team dispatch --project-root <root> --run-manifest <path> --jobs-file <jobs-file>`.
|
|
60
|
+
- Every reverify or report-writer jobs file carries `workerId`, `provider`, `role`, `modelExecutionValue`, `promptPath`, `resultPath`, `workerResultPath`, and `completionPaths`. For reverify, set `role` to `worker-reverify-r<N>` for the pane title. The report-writer completion paths include both data.json and the worker-results audit file.
|
|
61
|
+
- After either dispatch, run `okstra team await --project-root <root> --run-manifest <path>` before evaluating terminal status or completion paths.
|
|
62
|
+
|
|
63
|
+
## Completion, cleanup, and resume
|
|
64
|
+
|
|
65
|
+
- Await through `okstra team await`; raw Result Path polling is forbidden for this backend.
|
|
66
|
+
- Reclaim each round's panes at the round boundary through `okstra team teardown`, before the next round's dispatch. Finished workers leave their panes behind on purpose — the screen survives the process so you can still read a failure — so an unreclaimed round keeps shrinking the space the next one gets.
|
|
67
|
+
- Resume from run artifacts and lead-events checkpoints. After usage collection, persistence, and the core user-approval gate, run `okstra team teardown --project-root <root> --run-manifest <path>` and tear down only Okstra-owned panes recorded for the run.
|
|
@@ -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
|
|