okstra 0.212.0 → 0.212.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okstra",
3
- "version": "0.212.0",
3
+ "version": "0.212.1",
4
4
  "description": "Host-aware multi-provider cross-verification orchestrator runtime and agent skills.",
5
5
  "license": "MIT",
6
6
  "author": "devonshin",
@@ -1,5 +1,5 @@
1
1
  {
2
- "package": "0.212.0",
3
- "builtAt": "2026-10-06T04:03:51.341Z",
2
+ "package": "0.212.1",
3
+ "builtAt": "2026-10-06T05:50:20.444Z",
4
4
  "repoRoot": "/home/runner/work/okstra/okstra"
5
5
  }
@@ -387,6 +387,14 @@ def backfill_done_from_carry(plan_run_root: Path) -> int:
387
387
  for stage, status in last_lifecycle_status_by_stage(existing).items()
388
388
  if status in _LEAD_SETTLED_STATUSES
389
389
  }
390
+ # 원장에 이미 기록된 head 의 carry 는 리드가 판정을 마친 증거다. stage 를 다시
391
+ # 열고 fix run 이 `started` 를 붙이면 마지막 상태가 settled 가 아니게 되지만,
392
+ # 그 옛 carry 로 done 을 다시 만들면 철회된 head 가 살아난다(dev-11126 stage 1).
393
+ ruled_heads = {
394
+ (r.get("stage"), str(r.get("head_commit") or ""))
395
+ for r in existing
396
+ if r.get("status") in _LEAD_SETTLED_STATUSES and r.get("head_commit")
397
+ }
390
398
  key_by_stage: Dict[Any, str] = {}
391
399
  fallback_key = ""
392
400
  for r in existing:
@@ -409,7 +417,7 @@ def backfill_done_from_carry(plan_run_root: Path) -> int:
409
417
  if not _carry_is_complete(carry):
410
418
  continue
411
419
  head = carry_head_commit(carry)
412
- if not head:
420
+ if not head or (stage, head) in ruled_heads:
413
421
  continue
414
422
  impl_key = key_by_stage.get(stage) or carry.get("impl_task_key") or fallback_key
415
423
  if not impl_key:
@@ -63,7 +63,7 @@ are collected and convergence finished. Phase 1-5 do not need it.
63
63
  - Parse the executor's `### Stage Carry Evidence` JSON block. If absent or unparsable, end with status `contract-violated` and route to a follow-up `error-analysis`.
64
64
  - The `### Stage Carry Evidence` JSON may include `designPrepEvidence[]`. Emit a row only when this stage produced concrete evidence that refines an effective PREP item: `itemId`, the injected `assessmentFingerprint`, `resolution`, and non-empty `evidence[]` are required; `overrides` is optional and only records observed, non-authoritative refinements. Carry evidence never represents user approval. Downstream resolution accepts it only from transitive dependency stages with the matching fingerprint.
65
65
  - **A `FAIL` synthesised verdict withholds the two writes below.** They are what marks the stage `done`, so performing them on a stage whose verifier found a blocking defect stacks the next stage on a confirmed regression. When the synthesised verdict is `FAIL`: write NO carry sidecar, and append a `status:"failed"` row in place of the `done` row — same `okstra_ctl.consumers.append_consumer` call, carrying `report_path` and the SHA of HEAD. That row is terminal *without* completion: dependent stages stay blocked because this stage is not done, while its worktree-registry occupancy is released so a fix run can re-enter the same stage number — `--stage <N>` reuses the preserved worktree and branch instead of provisioning a new one. State the reason in the report's `Stage sidecar evidence` section as `withheld`. **Enforced:** `validators/validate-run.py` `_validate_stage_carry_sidecar_exists` accepts a missing carry file only when that field is non-empty, so silently skipping the sidecar still fails the run.
66
- - On a non-`FAIL` verdict, for this run's single stage: write its JSON verbatim to `runs/<impl-task-key>/carry/stage-<N>.json`. Refuse to overwrite an existing file (one stage = one sidecar; a fix run re-entering after a `failed` row writes the first one, because a withheld stage never wrote it).
66
+ - On a non-`FAIL` verdict, for this run's single stage: write its JSON verbatim to `runs/<impl-task-key>/carry/stage-<N>.json`. Refuse to overwrite an existing file (one stage = one sidecar; a fix run re-entering after a `failed` row writes the first one, because a withheld stage never wrote it). A stage reopened after a `done` row (see "Reopening a settled stage" below) still has the sidecar of the run that first settled it, naming a head the stage has since moved past: move it unchanged to `runs/<impl-task-key>/carry/superseded/stage-<N>-from-<that run's task-type>-<seq>.json` before writing the new one, and name both paths in `Stage sidecar evidence`. Do not rename it inside `carry/`: the readers glob `carry/stage-*.json` (`okstra_ctl.stage_map`, `okstra_ctl.consumers.backfill_done_from_carry`), so a renamed file there is read again as a live sidecar. A reopened stage whose run ends `FAIL` writes nothing and leaves the old file where it is.
67
67
  - On a non-`FAIL` verdict, for this run's single stage: append a `status:"done"` row to `runs/<plan-task-key>/consumers.jsonl` with `completed_at`, `carry_path`, `report_path` (this run's final-report path relative to the run root), and the SHA of HEAD. Append it with `okstra_ctl.consumers.append_consumer` (NOT a raw filesystem write) — that call honours the consumers lock AND releases this stage's worktree-registry occupancy, so later runs stop seeing a finished stage as a concurrent run. `report_path` lets `final-verification` cite each stage's originating report when assembling its Source Implementation Report list.
68
68
  - **Reopening a settled stage.** Appending a `status:"failed"` row after a `done` one withdraws that stage: `--stage N` accepts it again, its dependents stop resolving a base from the withdrawn head, and whole-task final-verification blocks until it is settled again. Use the same `okstra_ctl.consumers.append_consumer` call with a `reason`, and re-run the stage rather than repairing the tree outside okstra — a stage reverted outside the ledger leaves the recorded `head_commit` and the carry sidecar naming a tree that no longer exists, and the next stage branches from it.
69
69
  - The verifier round, Phase 5.5 convergence, and this Phase 6 report run **once per run** over this stage's diff — NOT per step.