okstra 0.125.0 → 0.125.1

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.
@@ -298,7 +298,7 @@ The standard `okstra` workflow applies the following team contract consistently
298
298
  - The main Claude is always the `Claude lead` and operates in synthesis-only mode.
299
299
  - The default required worker roles are `Claude worker`, `Codex worker`, and `Report writer worker`. `Antigravity worker` is optional and is included as required only when explicitly named by `--workers` or the profile's `- Workers:` section.
300
300
  - `Report writer worker` focuses on report structure and evidence organization, but `Claude lead` remains the final synthesis owner.
301
- - The default model contract is computed from central defaults. Fallbacks are `Claude lead`=`opus`, `Claude worker`=`opus`, `Codex worker`=`gpt-5.6-sol`, and `Antigravity worker`=`auto` (when opted in). Without a separate override, `Report writer worker` follows the `Claude lead` model (therefore `opus` by default).
301
+ - The default model contract is computed from central defaults. Fallbacks are `Claude lead`=`opus`, `Claude worker`=`opus`, `Codex worker`=`gpt-5.6-sol`, `Report writer worker`=`sonnet`, and `Antigravity worker`=`auto` (when opted in). `Report writer worker` no longer inherits the `Claude lead` model it resolves from its own catalog `ROLE_DEFAULTS` entry because it does not vote in convergence; `--report-writer-model opus` or `OKSTRA_DEFAULT_REPORT_WRITER_MODEL` restores the previous behavior.
302
302
  - Because `Antigravity worker` is optional, it is attempted only in runs where it is explicitly included.
303
303
  - Before the final judgment, each required role in the current run's worker roster must have either a result or an explicit terminal status (`completed`, `timeout`, `error`, `not-run`).
304
304
  - Every attempted worker (`completed`, `timeout`, `error`) must have an assigned worker prompt history file under the current run's `prompts/` directory.
package/docs/cli.md CHANGED
@@ -383,7 +383,7 @@ The central-default environment variables are:
383
383
  Fallback defaults are:
384
384
 
385
385
  - `Claude lead`: `opus`
386
- - `Report writer worker`: `opus`
386
+ - `Report writer worker`: `sonnet`
387
387
  - `Claude worker`: `opus`
388
388
  - `Codex worker`: `gpt-5.6-sol`
389
389
  - `Antigravity worker`: `auto`
@@ -54,13 +54,14 @@ okstra/
54
54
  │ ├── okstra_vendor/ vendored Jinja2 / MarkupSafe + graphify / networkx (okstra-graphify skill)
55
55
  │ ├── lib/okstra/ Bash helpers for okstra.sh
56
56
  │ └── lib/okstra-ctl/ Bash control-center subcommands
57
- ├── skills/ Claude Code skills (11)
57
+ ├── skills/ Claude Code skills (13); `_fragments/` holds shared marker blocks
58
58
  ├── agents/ lead SKILL.md + worker agent specs
59
59
  ├── prompts/ launch template, phase profiles, wizard prompt JSON
60
60
  ├── schemas/ JSON schema for final-report data.json
61
61
  ├── templates/ report, setup, PR, project-doc templates/assets
62
62
  ├── validators/ run / brief / schedule / view validators
63
63
  ├── tools/build.mjs source → runtime sync
64
+ ├── tools/sync-skill-fragments.mjs expand shared fragment blocks into skills/*/SKILL.md
64
65
  ├── tools/docs_publication/ public-manual publication pipeline (build-time only; not shipped)
65
66
  ├── config/docs-publication.json publication inventory: every tracked Markdown path + classification
66
67
  ├── runtime/ generated install payload; do not edit directly
@@ -220,6 +221,7 @@ Important modules:
220
221
  | `run.py` | `prepare_task_bundle()` single authority and CLI parser |
221
222
  | `implementation_stage.py` | `implementation` single-stage run orchestration — read the Stage Lifecycle Snapshot → pick an available Stage Map entry → provision an isolated stage worktree → publish the selected stage as run context (extracted from `run.py`) |
222
223
  | `stage_targets.py` | Stage readiness/verification policy SSOT — from the Stage Lifecycle Snapshot (`consumers.jsonl` ledger + carry sidecar backfill + active registry reservation) it decides which stage is runnable, which commit it branches from, and what final-verification checks. `order_stage_closure` topologically sorts (Kahn) the dependency closure of the wizard's multi-selected stage set to produce the unattended `chain-stages` chaining order |
224
+ | `stage_fix_carry.py` | fix-run carry derivation for a re-run on an `implementation` stage whose latest final-report data.json carries verifier `FAIL` verdicts — collects the previous report path, previous run HEAD, failed verifiers, carried blocking findings, and a routing recommendation, which `run.py` renders into the analysis profile through the `{{FIX_RUN_CONTEXT}}` token. A first run, or a re-run after `PASS`, yields no carry and renders the token empty |
223
225
  | `stage_reconcile.py` | best-effort git reconciliation shared by the stage prepare flow (delegates to `git_reconcile.auto_reconcile`; advisory — failures are only reported to stderr, the dependency gate stays authoritative) |
224
226
  | `design_surfaces.py` | deterministic detection of an `implementation-planning` stage's design surface — matches the stage's file-path tokens/suffixes/patterns and action wording via `SurfaceRule` to derive which design input the stage needs among domain contract, DB/table schema, external interface, transaction/consistency, transformation mapping, lifecycle, rollout/observability, and manual user test, plus its evidence (`TriggerEvidence`). An unmappable structure raises `DesignSurfaceError` |
225
227
  | `design_prep.py` | fingerprint / materialize / resolve backend for design-preparation requests (CLI: `okstra design-prep <list\|show\|write>`) — computes an assessment fingerprint from the approved planning snapshot's `ASSESSMENT_FIELDS`, idempotently writes an Okstra-owned request under `design-prep-requests/`, and resolves the highest-revision append-only user response under `design-prep-inputs/` whose fingerprint matches as the effective response. Keeps the three authorities (report snapshot / Okstra request / user input) separate and never modifies the report or existing revisions. Sidecar I/O is protected by a directory-fd anchor + flock |
@@ -342,14 +344,16 @@ Optional (v1.0 backward-compatible) top-level keys:
342
344
 
343
345
  ### 4.10 `skills/`
344
346
 
345
- 13 user-facing skills (the only skills `okstra install` copies). The list SSOT is `USER_SKILL_NAMES` in `src/lib/skill-catalog.mjs`; the Claude plugin manifest and the installer both derive from it:
347
+ 13 user-facing skills (the only skills `okstra install` copies). The list SSOT is `USER_SKILL_NAMES` in `src/lib/skill-catalog.mjs`; the Claude plugin manifest and the installer both derive from it.
348
+
349
+ Boilerplate shared by several skills (bash invocation rule, outdated-CLI preflight, python bootstrap note) is kept canonical in `skills/_fragments/*.md` and expanded in place inside each `SKILL.md` between `<!-- BEGIN FRAGMENT: <name> -->` / `<!-- END FRAGMENT: <name> -->` markers by `tools/sync-skill-fragments.mjs` (`--check` fails on drift). Sources stay fully expanded, so `runtime/` and installed copies remain self-contained; the guards are `tests-js/skill-fragments.test.mjs` and `tests/contract/test_prompt_fragment_ownership.py`.
346
350
 
347
351
  | Skill | User-invocable | Role |
348
352
  |---|---:|---|
349
353
  | `okstra-brief-gen` | yes | Produce task brief from ticket/doc/link/conversation |
350
354
  | `okstra-run` | yes | Start/resume okstra task in current Claude Code session |
351
355
  | `okstra-memory` | yes | Store/search/archive global conversation memory under `~/.okstra/memory-book` |
352
- | `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) |
356
+ | `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` |
353
357
  | `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 |
354
358
  | `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) |
355
359
  | `okstra-schedule-gen` | yes | Generate task-group schedule |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okstra",
3
- "version": "0.125.0",
3
+ "version": "0.125.1",
4
4
  "description": "Multi-agent cross-verification orchestrator runtime + Claude Code skills.",
5
5
  "license": "MIT",
6
6
  "author": "devonshin",
@@ -1,5 +1,5 @@
1
1
  {
2
- "package": "0.125.0",
3
- "builtAt": "2026-07-19T16:21:54.855Z",
2
+ "package": "0.125.1",
3
+ "builtAt": "2026-07-20T08:47:14.936Z",
4
4
  "repoRoot": "/home/runner/work/okstra/okstra"
5
5
  }
@@ -254,6 +254,16 @@ mkfifo "$stdout_fifo"
254
254
  tee -a "$log_path" < "$stdout_fifo" &
255
255
  stdout_tee_pid=$!
256
256
 
257
+ # Disable git's fsmonitor for every git command agy runs in this process tree —
258
+ # the main worktree's fsmonitor daemon leaks its IPC socket into task worktrees,
259
+ # so git status/commit here intermittently fail with `fsmonitor_ipc__send_query`
260
+ # errors. GIT_CONFIG_* scopes the override to this process tree without touching
261
+ # the user's repo config. See `okstra-codex-exec.sh` for the full rationale.
262
+ _gc_idx="${GIT_CONFIG_COUNT:-0}"
263
+ export "GIT_CONFIG_KEY_${_gc_idx}=core.fsmonitor"
264
+ export "GIT_CONFIG_VALUE_${_gc_idx}=false"
265
+ export GIT_CONFIG_COUNT="$(( _gc_idx + 1 ))"
266
+
257
267
  agy --print "$(cat "$prompt_path")" --model "$model" "${add_dir_args[@]}" \
258
268
  --print-timeout "$PRINT_TIMEOUT" --dangerously-skip-permissions \
259
269
  2>> "$log_path" \
@@ -328,6 +328,18 @@ mkfifo "$stdout_fifo"
328
328
  tee -a "$log_path" < "$stdout_fifo" &
329
329
  stdout_tee_pid=$!
330
330
 
331
+ # Disable git's fsmonitor for every git command codex runs in this process
332
+ # tree. The main worktree's fsmonitor daemon leaks its IPC socket into task
333
+ # worktrees, so git status/commit here intermittently fail with
334
+ # `fsmonitor_ipc__send_query` errors (workers otherwise recover by hand with
335
+ # `git -c core.fsmonitor=false`). Injecting it via GIT_CONFIG_* scopes the
336
+ # override to this process tree without touching the user's repo config, and
337
+ # appends after any GIT_CONFIG_* the caller already set.
338
+ _gc_idx="${GIT_CONFIG_COUNT:-0}"
339
+ export "GIT_CONFIG_KEY_${_gc_idx}=core.fsmonitor"
340
+ export "GIT_CONFIG_VALUE_${_gc_idx}=false"
341
+ export GIT_CONFIG_COUNT="$(( _gc_idx + 1 ))"
342
+
331
343
  codex exec -C "$project_root" ${extra_args[@]+"${extra_args[@]}"} --model "$model" --sandbox workspace-write -c approval_policy=never - \
332
344
  < "$prompt_path" \
333
345
  2>> "$log_path" \
@@ -43,9 +43,17 @@ Different recipients need different files. Do NOT include `final-report-template
43
43
 
44
44
  ## Error reporting (all workers)
45
45
 
46
- If any tool call you make (Bash, Read, Edit, MCP, etc.) returns a non-zero exit code, raises an exception, or otherwise fails its intended effect, append a single entry to your worker errors sidecar at the absolute path the lead provided as `**Errors sidecar path:** <abs-path>`.
46
+ Record a tool call only when its failure **blocked the step you intended** a test you needed to run did not start, a file you needed to read was missing, a config resolved against the wrong tree, an edit was rejected. When that happens, append a single entry to your worker errors sidecar at the absolute path the lead provided as `**Errors sidecar path:** <abs-path>`.
47
47
 
48
- If the sidecar file does not exist, create it with `{"schemaVersion": 1, "errors": []}` then append.
48
+ A non-zero exit code is NOT by itself a failure to record. Many tools use non-zero to report a normal, expected result. Do **NOT** record an entry when:
49
+
50
+ - a search/probe tool (`rg`, `grep`, `find`, `ls`, `test`, `git check-ignore`) exits non-zero solely because it found **no matches**, and you proceed unaffected;
51
+ - you probe an **optional / expected-absent** path (`graphify-out/`, `.project-docs/`, `.scratch/`, an optional lint config, a review pack) and it is absent — detecting absence was the point of the probe;
52
+ - output was truncated but you re-ran and read the content end-to-end.
53
+
54
+ The test: if the non-zero exit changed nothing about what you could do next, it is a normal result, not a `tool-failure`. When in doubt about whether a failure blocked you, record it — under-recording a real blocker is worse than one noisy entry. These benign non-zero exits are the single largest source of error-log noise; keeping them out is what makes the log a signal.
55
+
56
+ If the sidecar file does not exist and you have a real entry to record, create it with `{"schemaVersion": 1, "errors": []}` then append.
49
57
 
50
58
  ### Entry schema
51
59
 
@@ -109,7 +117,13 @@ For the **improvement-discovery phase** specifically, the dispatched prompt MUST
109
117
 
110
118
  - `**Phase 1.5 Grilling Log:** <absolute-path>` — the lead's Phase 1.5 reflect-back log (`<RUN_DIR>/state/phase-1.5-grilling.md`, written before dispatch). Its `Resolved scope` / `Resolved lenses` blocks are the authoritative scope and lens definition for this run. Read the file at this absolute path; do NOT re-derive it from `<RUN_DIR>`, and do NOT re-interpret the brief's raw `scan-scope` / `priority-lenses`. The presence of this anchor is itself the signal that this is an improvement-discovery run — no separate task-type detection is required.
111
119
 
112
- When a worker reads any project-relative path from the prompt, it MUST resolve it against `Project Root` (e.g. `<Project Root>/<Result Path>`) — never use bare relative paths that depend on cwd.
120
+ ### Path anchoring (BLOCKING the single largest source of worker tool-failures)
121
+
122
+ Every `.okstra/...` path is anchored at `**Project Root:**`, **never** at your cwd. When your run has a worktree (`**Worktree:**` is present), your cwd is that worktree — and the stage/task worktree does **not** contain the project's `.okstra/` directory. So a bare `Read`/`cat .okstra/tasks/...` from cwd resolves inside the worktree and fails "no such file". This is the same trap whether the path came from the prompt, a manifest field, a prior report's citation, or your own reasoning.
123
+
124
+ - Resolve any project-relative path (`.okstra/...`, `<Result Path>`, `<Prompt History Path>`, a prior-report `path:line` citation) against `**Project Root:**`: `<Project Root>/.okstra/...`. Never use the bare relative form.
125
+ - Mutating build/test commands still run from the worktree cwd (`cd <Worktree> && ...`) — but reads of okstra artifacts (`.okstra/**`) always go through `<Project Root>`, even while cwd is the worktree.
126
+ - If a `.okstra/...` read fails "no such file / does not exist in the worktree", do not retry the same relative path — re-anchor it to `<Project Root>` and read the absolute path.
113
127
 
114
128
  ---
115
129