okstra 0.101.1 → 0.102.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.
Files changed (40) hide show
  1. package/README.kr.md +5 -5
  2. package/README.md +5 -5
  3. package/docs/for-ai/README.md +2 -3
  4. package/docs/for-ai/skills/{okstra-container.md → okstra-container-build.md} +3 -4
  5. package/docs/for-ai/skills/okstra-inspect.md +1 -2
  6. package/docs/kr/architecture/storage-model.md +1 -2
  7. package/docs/kr/architecture.md +6 -6
  8. package/docs/kr/cli.md +3 -3
  9. package/docs/kr/container.md +1 -1
  10. package/docs/project-structure-overview.md +5 -5
  11. package/docs/superpowers/plans/2026-06-15-internal-skill-resource-migration.md +1 -1
  12. package/docs/superpowers/plans/2026-06-24-cross-project-precondition.md +542 -0
  13. package/docs/superpowers/plans/2026-06-24-decision-drafts-render-gap.md +568 -0
  14. package/docs/superpowers/plans/2026-06-24-manual-user-test-section.md +203 -0
  15. package/docs/superpowers/plans/2026-06-24-okstra-container-build-rename.md +525 -0
  16. package/docs/superpowers/specs/2026-06-24-cross-project-precondition-design.md +129 -0
  17. package/docs/superpowers/specs/2026-06-24-decision-drafts-render-gap-design.md +185 -0
  18. package/docs/superpowers/specs/2026-06-24-manual-user-test-section-design.md +121 -0
  19. package/docs/superpowers/specs/2026-06-24-okstra-container-build-rename-design.md +110 -0
  20. package/package.json +1 -1
  21. package/runtime/BUILD.json +2 -2
  22. package/runtime/agents/workers/report-writer-worker.md +1 -0
  23. package/runtime/prompts/lead/report-writer.md +1 -1
  24. package/runtime/prompts/lead/team-contract.md +2 -2
  25. package/runtime/prompts/profiles/_implementation-deliverable.md +2 -0
  26. package/runtime/prompts/profiles/final-verification.md +4 -3
  27. package/runtime/prompts/profiles/implementation-planning.md +12 -9
  28. package/runtime/python/okstra_ctl/run.py +0 -1
  29. package/runtime/python/okstra_token_usage/paths.py +1 -2
  30. package/runtime/schemas/final-report-v1.0.schema.json +106 -3
  31. package/runtime/skills/{okstra-container → okstra-container-build}/SKILL.md +3 -3
  32. package/runtime/templates/reports/final-report.template.md +63 -2
  33. package/runtime/templates/reports/final-verification-input.template.md +3 -3
  34. package/runtime/templates/reports/i18n/en.json +28 -1
  35. package/runtime/templates/reports/i18n/ko.json +28 -1
  36. package/runtime/templates/worker-prompt-preamble.md +1 -1
  37. package/runtime/validators/validate-run.py +70 -1
  38. package/src/commands/lifecycle/install.mjs +17 -18
  39. package/src/commands/lifecycle/uninstall.mjs +8 -6
  40. package/src/lib/skill-catalog.mjs +10 -9
@@ -54,7 +54,7 @@
54
54
  {{INCLUDE:_clarification-recommendation.md}}
55
55
  - **Evidence note required inside `Statement`**: every clarification row includes `Evidence checked: <path:line>` or `Evidence checked: none — <human-only reason>` in the `Statement` cell. `none` is allowed ONLY when the row's nature is "only a human can answer this" (reporter intent, business priority, organisational decision). A row with `none` that *could* have been answered by the codebase is a defect of this phase, restated from the pre-planning rule above.
56
56
  - Section heading contract (BLOCKING — validator scans for these literal English substrings):
57
- - The final report MUST include section headings containing each of the following exact strings: `Option Candidates`, `Trade-off`, `Recommended Option`, `Stage Map`, `Stage Exit Contract`, `Stage Validation`, `Dependency`, `Validation Checklist`, `Rollback`, `Requirement Coverage`. (Approval is no longer a body section — it is the YAML frontmatter `approved` field.)
57
+ - The final report MUST include section headings containing each of the following exact strings: `Option Candidates`, `Trade-off`, `Recommended Option`, `Stage Map`, `Stage Exit Contract`, `Stage Validation`, `Dependency`, `Cross-Project Dependencies`, `Decision Drafts`, `Validation Checklist`, `Rollback`, `Requirement Coverage`. (Approval is no longer a body section — it is the YAML frontmatter `approved` field.)
58
58
  - Korean translations are allowed in parentheses (e.g. `### Recommended Option (권장 옵션)`), but the English keyword must be present verbatim in the heading line.
59
59
  - The shape and ordering follow `final-report-template.md` sections 5.4 (`Implementation Plan Deliverables`) + 5.5 (`Stage Map`). `validators/validate-run.py` substring-matches the raw report text, so a Korean-only heading fails the gate — the cause of repeated observed failures.
60
60
  - Beyond substring matching, when the Plan Body Verification gate result is `passed` / `passed-with-dissent`, `validators/validate-run.py` runs the **structural** Stage Map validator (`validators/validate-implementation-plan-stages.py`) at the planning boundary — not deferred to the `implementation` entry gate. It enforces: the exact `## 5.5 Stage Map` heading, each `## 5.5.<i> Stage <i>:` section with its four required subsections, the per-stage effective step count (≤8), the `depends-on` DAG, and the per-stage vertical-slice contract (S10). S10 scans for the literal in-section strings `Slice value:`, `Acceptance:`, the three `Test case (success):` / `Test case (boundary):` / `Test case (failure):` lines (S10d), and the Stepwise `action`-cell prefixes `RED:` / `GREEN:` (or a `TDD exemption:` line, which waives both the test-case lines and the RED/GREEN check) — keep these tokens verbatim for the same reason as the heading keywords above.
@@ -88,16 +88,17 @@
88
88
  - **Vertical-slice-first partition rule (1st-class):** the grouping anchor is a **thin end-to-end vertical slice** — one stage delivers a single user-observable increment, crossing whatever layers are needed (data → service → API → UI) to make that one increment work. File/module proximity is demoted to the **intra-slice grouping rule**: within a slice, keep steps touching the same file/directory/module together so the diff, PR, and rollback unit stay cohesive. **Horizontal layer-splitting is forbidden** — never carve "the DB layer" into one stage and "the service layer" into the next; that produces stages that ship no standalone user value. A stage is split ONLY when (a) a real `depends-on` data/contract dependency exists, (b) effective steps would exceed 8, or (c) it is a distinct vertical slice (a different user-value increment). Maximising the number of parallel stages is NOT a reason to split — parallelism is an emergent property of independent stages, never a partitioning goal.
89
89
  - **Project-boundary partition rule (hard boundary):** a *project* boundary is either (a) a different repository / `PROJECT_ROOT`, or (b) a different top-level independently-deployable module within one repo. A stage maps to a single worktree on one repo/branch, so **no stage may contain edits belonging to more than one project** — this is a hard split that overrides the ≤8-step merging allowance; never co-locate two projects' changes in one stage to save a stage. Two cases:
90
90
  - **Same repo, different modules** — put each project/module's increment in its own stage. Their file sets are disjoint, so they default to `depends-on (none)` and run in parallel; add a `depends-on` link ONLY when a real cross-module contract / shared-schema / deploy-order dependency exists.
91
- - **Different repos** — a single okstra task **cannot** span repos: every stage worktree is a `git worktree add` in one repo's main checkout (one `<project-id>`), the run-index / manifests / registry are keyed to that one project, and the edit allowlist only covers that project's tree plus `~/.okstra/worktrees/**`. This is a structural limit, not a style preference. Therefore cross-repo work MUST be split into **a separate okstra run per repo** — never modelled as stages of one task. State, in the Stage Map `Cross-project parallelism:` line, whether those per-repo runs can proceed in parallel. To avoid re-deriving shared analysis, the second repo's run should consume the first run's relevant plan/decision artifacts as brief Source Material (see the cross-repo carry note below).
91
+ - **Different repos** — a single okstra task **cannot** span repos: every stage worktree is a `git worktree add` in one repo's main checkout (one `<project-id>`), the run-index / manifests / registry are keyed to that one project, and the edit allowlist only covers that project's tree plus `~/.okstra/worktrees/**`. This is a structural limit, not a style preference. Therefore cross-repo work MUST be split into **a separate okstra run per repo** — never modelled as stages of one task. State, in the Stage Map `Cross-project parallelism:` line, whether those per-repo runs can proceed in parallel. To avoid re-deriving shared analysis, the second repo's run should consume the first run's relevant plan/decision artifacts as brief Source Material (see the cross-project dependency rows below).
92
92
  - **Parallel-feasibility check (mandatory for every multi-project plan):** disjoint files (S9 below) is necessary but NOT sufficient for parallelism — a cross-project API/contract/schema/deploy-order dependency forces sequencing even when no file overlaps. For each pair of projects, explicitly determine and record (in the `Cross-project parallelism:` line) whether they are independent (run in parallel) or sequenced (and the exact dependency that forces the order).
93
93
  - **Parallel-safety invariant (BLOCKING):** any two stages that are both `depends-on (none)` MUST predict disjoint file sets in their `Stage Exit Contract`. Two parallel `implementation` runs would otherwise edit the same file concurrently. Work touching a shared file must either go in one stage or be ordered with `depends-on`. Enforced by `validators/validate-implementation-plan-stages.py` check S9.
94
- - **Cross-repo carry packet (multi-repo plans only the carry note referenced above):** when the plan identifies work in a repo *other* than this run's project, that work cannot be implemented here (Different-repos rule above). For each other repo, add a top-level report appendix section `## Cross-Repo Carry<repo>` with these three mandatory subsections, written so a reader who has never seen this run can act cold:
95
- - `### Preconditions already covered by this run` — what THIS run's repo delivers that `<repo>`'s work depends on (an endpoint, a published contract, a migration, a package version). For each, give the **observable verification signal** `<repo>`'s run must confirm before/while implementing (PR merged, endpoint live, version published) — NOT a `depends-on` stage link. A cross-repo dependency cannot be a `depends-on`: that gate resolves commits inside one repo's git graph only (`scripts/okstra_ctl/run.py` `_resolve_stage_base_commit`), so it is structurally incapable of pointing at another repo's commit.
96
- - `### Work for <repo> to implement` the self-contained B-portion: its requirements restated as fresh `R-NNN` from `<repo>`'s perspective, the proposed stages/steps, affected files, and any decision drafts. Carry ONLY what `<repo>` still has to build never carry this run's already-`done` stages as if they were `<repo>` stages.
97
- - `### How to start <repo>'s run` the exact handoff: in `<repo>` the user runs `okstra-brief` citing **this report's absolute path as Source Material** (the only sanctioned cross-`<PROJECT_ROOT>` read `okstra-brief` reads outside `<PROJECT_ROOT>/.okstra/**` only when the user explicitly cites the path), then `okstra-run` `<repo>`'s own planning implementation seeded by it.
98
- - **Recognition caveat (write it verbatim into the section):** `<repo>`'s run is structurally independent — its done-set comes only from its OWN `runs/.../consumers.jsonl`, its stage numbers are its own, and `depends-on` resolves against its own git graph. This run's completed stages are therefore NOT auto-recognised as `done` by `<repo>`'s gate (and must not be — they are this repo's work). The carry packet is narrative input that seeds `<repo>`'s planning; `<repo>` re-plans and implements only its own portion, treating this run's deliverables as the external preconditions above. This run MUST NOT write into `<repo>`'s tree or its `.okstra/`; it only emits the carry section in its own report.
94
+ - **Cross-project dependency rows (`crossProjectDependencies` 배열 — 옛 `## Cross-Repo Carry` 부록을 대체):** 타 프로젝트(다른 repo / 다른 top-level 독립 배포 모듈 / published 패키지) 대한 의존은 freeform `## Cross-Repo Carry` 부록이 아니라 **구조 필드 `crossProjectDependencies` `XP-NNN` 행**으로 기록한다. 프로젝트 의존마다 XP 행을 두고, 양방향 중 해당하는 `direction` 을 채운다(렌더는 `### Cross-Project Dependencies` §5.4; 단일 프로젝트 계획은 배열). 필드는 subsection 다음으로 대체한다`requiredWork`(상대가 만들어야 구체 작업) / `verificationSignal`(이 run 관측할 신호) / `linkedWork`(신호 충족 막히는 계획의 stage·step) / `howToStart`(상대 repo 에서의 정확한 handoff).
95
+ - `direction: upstream-precondition` — run 상대의 **선행 작업을 기다림(선행 필수)**: `requiredWork` = 상대가 먼저 구현해야 구체 작업, `verificationSignal` = run 진행 관측해야 신호(PR 머지 / 엔드포인트 live / 버전 publish), `linkedWork` = 신호 충족 막히는 계획의 stage·step, `howToStart` = 상대 repo 에서 `okstra-brief`(**이 보고서의 절대경로를 Source Material 인용** 유일하게 허용된 cross-`<PROJECT_ROOT>` read) → `okstra-run`.
96
+ - `direction: downstream-carry` run 이 상대가 쓸 것을 **만들어 줌(기존 carry)**: `requiredWork` = 상대가 후속 구현할 self-contained B-portion(상대 관점의 신규 `R-NNN`·제안 stage·영향 파일), `verificationSignal` = 상대가 진행 확인할(이 run 인도한) 신호, `linkedWork` = 신호를 인도하는 계획의 stage·step, `howToStart` upstream 동일. run 의 이미 `done` stage 상대 stage 양 넘기지 않는다 — 상대가 아직 만들어야 할 portion 만 담는다.
97
+ - **cross-repo 의존은 `depends-on` 으로 표현 불가:** 그 게이트는 한 repo git graph 내부 커밋만 해소하므로(`scripts/okstra_ctl/run.py` `_resolve_stage_base_commit`) 다른 repo 커밋을 가리킬 수 없다. cross-repo 작업은 stage 아니라 별도 okstra run + XP 행으로 분리한다(Different-repos 규칙). 상대 run 구조적으로 독립이라 run 완료 stage 를 `done` 으로 자동 인식하지 않으며(인식해서도 repo 작업), XP 행은 상대 planning 을 seed 하는 narrative 입력일 뿐이다. 이 run 은 상대 repo 트리·그 `.okstra/` 쓰지 않는다(이 보고서의 XP 행만 emit). 옛 "Recognition caveat" 문구는 렌더 노트(i18n `crossProjectRecognitionNote`)로 이전돼 `### Cross-Project Dependencies` 섹션에 자동 출력된다.
99
98
  - **Stage exit contract is the carry surface:** keep it as narrow as possible. Wider surface = more downstream coupling.
100
99
  - dependency / migration risk assessment (ordering constraints, data backfills, feature-flag prerequisites, repo-internal sequencing)
100
+ - **Cross-Project Dependencies (조건부 필수):** 계획이 다른 프로젝트 / repo / published 패키지의 작업에 의존하면 (a) `dependencyMigrationRisk` 에 `kind: cross-project` DM 행을, (b) `crossProjectDependencies` 에 매칭 `XP-NNN` 행을 둔다. upstream-precondition 행은 `requiredWork`·`verificationSignal`·`howToStart` 가 구체적이어야 한다 — `validators/validate-run.py` 가 DM `cross-project` ⇒ `direction: upstream-precondition` XP 행 ≥1 을, 스키마가 행 필드 비-빈을 강제한다. cross-project 의존은 soft Recommended Next Step 이 아니라 이 구조화된 선행 필수로 기록한다. 단일 프로젝트 계획은 빈 배열.
101
+ - **recommendedNextSteps 정책:** cross-project 선행/후속의 substance 는 `crossProjectDependencies` 에 두고, `§3 Recommended Next Steps` 에는 그 섹션(`§5.4 Cross-Project Dependencies`)을 가리키는 포인터만 둔다 — 이중 기록 금지.
101
102
  - validation checklist (pre / mid / post) — each item is an exact command or observable outcome
102
103
  - rollback strategy — exact revert path (commits, flags, migrations) and the signal that triggers rollback
103
104
  - **Requirement Coverage (mandatory, §5.5.8):** one row per concrete requirement from the task brief / packet. Assign stable IDs `R-001`, `R-002`, ... in source order. Columns: `ID | Source | Requirement | Covered by option / stage / step | Status`. `Source` cites the brief heading or file/line where the requirement came from. `Covered by` must name the specific Option Candidate and Stage/Step that satisfies it, not just "recommended option". `Status` is one of `covered`, `gap`, or `blocked C-NNN`. If any row is `gap` or `blocked C-NNN`, the Plan Body Verification gate MUST NOT be `passed` / `passed-with-dissent`; add a matching `Blocks=approval` row for the blocker and keep `approved: false`.
@@ -111,8 +112,8 @@
111
112
  1. **Hard to reverse** — would changing the decision later cost meaningfully more than deciding now?
112
113
  2. **Surprising without context** — would a future reader, seeing only the code, wonder "why was it built this way?"?
113
114
  3. **Real trade-off** — were there named alternatives, and was one picked for specific reasons?
114
- If **all three** hold, attach a decision draft as a report appendix section titled `Decision Drafts` (one decision per subsection). Each draft uses the `## Context / ## Decision / ## Consequences / ## Alternatives Considered` shape, names the alternatives that were rejected and why, and starts with `## Status: Proposed`. The next decision number is `(max existing in <PROJECT_ROOT>/.okstra/decisions/ + 1)` zero-padded to 4 digits. If any of the three criteria is missing, do NOT raise a decision draft — instead record `skipped adr-candidate: <topic> reason: <criterion that failed>` on one line under `Decision Drafts` so the next reader knows the candidate was evaluated and intentionally dropped.
115
- The drafts are NOT written by this phase. The approved plan's stepwise execution order MUST include the step `Create <PROJECT_ROOT>/.okstra/decisions/<NNNN>-<slug>.md from the decision draft in section X` so the `implementation` run commits the file inside okstra's subtree.
115
+ If **all three** hold, record a decision draft as a `decisionDrafts[]` row (rendered in §5.4 `### Decision Drafts`, one `#### <number>-<slug>` subsection each). Each row carries `number` (= `(max existing in <PROJECT_ROOT>/.okstra/decisions/ + 1)` zero-padded to ≥4 digits), `slug` (kebab-case), `status: Proposed`, and the `context` / `decision` / `consequences` / `alternativesConsidered` fields (`alternativesConsidered` names the rejected alternatives and why). If any of the three criteria is missing, do NOT raise a draft — instead record a `skippedAdrCandidates[]` row (`topic` + `reason: <criterion that failed>`, rendered as a `skipped adr-candidate: … — reason: …` line under the same section) so the next reader knows the candidate was evaluated and intentionally dropped.
116
+ The decision files are NOT written by this phase. The approved plan's stepwise execution order MUST include the step `Create <PROJECT_ROOT>/.okstra/decisions/<NNNN>-<slug>.md from the §5.4 Decision Drafts subsection <number>-<slug>` (materializing the structured fields into the file's `## Status / ## Context / ## Decision / ## Consequences / ## Alternatives Considered` shape) so the `implementation` run commits the file inside okstra's subtree. `validators/validate-run.py` enforces this: a non-empty `decisionDrafts` whose stages carry no stepwise step referencing `.okstra/decisions/` is `contract-violated`.
116
117
  - **Glossary proposals**: if a term or definition should become okstra institutional memory, add the step `Update <PROJECT_ROOT>/.okstra/glossary.md: <term> = <definition>` to the stepwise execution order. Use no other project-memory path.
117
118
  - No-placeholder rule (plan failures — reject any option or step that contains these):
118
119
  - "TBD", "TODO", "implement later", "fill in details", "add appropriate error handling", "handle edge cases", "write tests for the above" without actual test code
@@ -128,3 +129,5 @@
128
129
  6. **Review-rule preflight check** — if a project review rule pack exists, map each relevant rule to the recommended option. Reject the draft if it knowingly creates a violation that the later PR reviewer would flag, unless the plan records a specific rationale and follow-up. In particular, scan for repeated helper stacks across planned files, tests that assert delegation to the same calculator/helper they exercise, public names that hide side effects, domain rules placed in repositories/adapters, and APIs made dead by this change.
129
130
  7. **Plan-body verification reconciliation (BLOCKING for implementation-planning).** Inspect the `### 5.5.9 Plan Body Verification` verdict table. For every plan-item row classified as `majority-disagree → C-<N>`, the corresponding `C-<N>` row MUST exist in `## 1. Clarification Items` with `Kind` chosen per the standard policy and `Blocks=approval`. Do NOT create a parallel `Open Questions` block under the implementation plan body — the unified table is the single home. Conversely, the `Classification` column's `C-<N>` reference and the `## 1. Clarification Items` `ID` column MUST match 1:1; an orphan on either side is a contract violation. For `partial-consensus` and `worker-unique` plan-items, the dissenting opinion lives in §5.5.9 `Dissent log` and is NOT promoted to §5.
130
131
  8. **Stage Map self-check** — for every stage, count the effective rows of its `Stepwise Execution Order` table by hand; reject the draft if any stage exceeds 8. Confirm each stage declares a non-empty `Slice value:` and `Acceptance:` line, the three `Test case (success|boundary|failure):` lines (or carries a `TDD exemption:` line), and that its first step `action` starts with `RED:` with a later `GREEN:` — this is what validator S10 enforces, including S10d on the test-case lines. Read each stage's three test-case lines as a reviewer: reject any that restates the happy path in all three slots, leaves `boundary` blank, or writes `N/A` where a real edge input exists. Walk the `depends-on` graph and confirm it is a DAG (no cycle, no self-reference). For each `depends-on` link, confirm it encodes a real data/contract dependency — do NOT add links to serialise unrelated work, and do NOT split a stage merely to create more parallel stages. **Parallel-safety:** for every pair of `depends-on (none)` stages, confirm their `Stage Exit Contract` predicted file sets are disjoint; if they share a file, merge them or add a `depends-on` link (validator S9 rejects overlap). **Project-boundary:** confirm no stage mixes edits from two projects (different repo/`PROJECT_ROOT` or different top-level deployable module); if any stage does, split it per project. For multi-project plans, confirm each stage's `title` carries its `[<project>]` tag and the `Cross-project parallelism:` line under the table records the parallel-vs-sequenced determination (with the forcing dependency) for every project pair; for cross-repo work, confirm it is split into separate per-repo runs (required — one run structurally cannot touch another repo) rather than crammed into one task's stages.
132
+ 9. **Cross-project dependency check** — 타 repo / 다른 top-level 배포 모듈 / published 패키지에 대한 의존을 빠뜨리지 않았는지 확인한다. `dependencyMigrationRisk` 에 `kind: cross-project` 행이 있으면 매칭되는 `direction: upstream-precondition` `XP-NNN` 행이 `crossProjectDependencies` 에 있고, 그 `requiredWork` 가 추상 표현("상대 작업 완료")이 아니라 상대가 실제로 만들어야 할 구체 작업인지 reviewer 로서 다시 읽는다(validator S 가 존재만 보므로 구체성은 self-review 가 책임짐). cross-repo 작업을 한 task 의 stage 로 욱여넣지 않고 별도 run + XP 행으로 분리했는지, cross-project substance 가 `§3 Recommended Next Steps` 에 중복되지 않고 `§5.4 Cross-Project Dependencies` 에만 있는지 확인한다.
133
+ 10. **Decision-draft materialization check** — `decisionDrafts` 가 비어있지 않으면, 매칭 materialization step(`.okstra/decisions/<NNNN>-<slug>.md` 생성)이 어느 stage 의 stepwise 에 존재하는지, draft 개수와 materialization step 이 1:1 로 대응하는지 reviewer 로서 확인한다. validator 는 step 의 *존재*만 보므로 `<NNNN>-<slug>` 정확성·개수 대응은 self-review 가 책임진다.
@@ -1570,7 +1570,6 @@ def _reserve_final_verification_target(
1570
1570
  f"- **Verification scope:** `{target.scope}`\n"
1571
1571
  f"- **Worktree:** `{target.worktree_path}`\n"
1572
1572
  f"- **Verification base ref:** `{target.base}`\n"
1573
- f"- **Verification head SHA:** `{target.head}`\n"
1574
1573
  f"- **Stages under verification:** {target.stages}\n"
1575
1574
  f"- **Source implementation reports:**\n{reports}\n"
1576
1575
  f"- **Verification diff stat:**\n```\n{diff_stat}\n```"
@@ -7,7 +7,7 @@ from pathlib import Path
7
7
 
8
8
  HOME = Path.home()
9
9
  CLAUDE_PROJECTS = HOME / ".claude" / "projects"
10
- CODEX_SESSIONS = HOME / ".codex" / "sessions"
10
+ CODEX_SESSIONS = HOME / ".agent" / "sessions"
11
11
 
12
12
 
13
13
  def utc_now() -> str:
@@ -45,4 +45,3 @@ def claude_project_dir(cwd: Path, projects_root: Path | None = None) -> Path:
45
45
  # `projects_root` 는 테스트/진단용 주입 시드 — 기본은 실제 ~/.claude/projects.
46
46
  encoded = "-" + str(cwd).strip("/").replace("/", "-")
47
47
  return (projects_root or CLAUDE_PROJECTS) / encoded
48
-
@@ -360,7 +360,10 @@
360
360
  "validationChecklist",
361
361
  "rollbackStrategy",
362
362
  "requirementCoverage",
363
- "planBodyVerification"
363
+ "planBodyVerification",
364
+ "crossProjectDependencies",
365
+ "decisionDrafts",
366
+ "skippedAdrCandidates"
364
367
  ],
365
368
  "additionalProperties": false,
366
369
  "properties": {
@@ -410,7 +413,19 @@
410
413
  "minItems": 1,
411
414
  "items": { "$ref": "#/$defs/ImplementationRequirementCoverageRow" }
412
415
  },
413
- "planBodyVerification": { "$ref": "#/$defs/PlanBodyVerification" }
416
+ "planBodyVerification": { "$ref": "#/$defs/PlanBodyVerification" },
417
+ "crossProjectDependencies": {
418
+ "type": "array",
419
+ "items": { "$ref": "#/$defs/CrossProjectDependency" }
420
+ },
421
+ "decisionDrafts": {
422
+ "type": "array",
423
+ "items": { "$ref": "#/$defs/DecisionDraft" }
424
+ },
425
+ "skippedAdrCandidates": {
426
+ "type": "array",
427
+ "items": { "$ref": "#/$defs/SkippedAdrCandidate" }
428
+ }
414
429
  }
415
430
  },
416
431
 
@@ -526,6 +541,7 @@
526
541
  "validationEvidence",
527
542
  "verifierResults",
528
543
  "rollbackVerification",
544
+ "manualUserTest",
529
545
  "routingRecommendation"
530
546
  ],
531
547
  "additionalProperties": false,
@@ -580,6 +596,29 @@
580
596
  "minItems": 1,
581
597
  "items": { "$ref": "#/$defs/RollbackVerificationRow" }
582
598
  },
599
+ "manualUserTest": {
600
+ "type": "object",
601
+ "additionalProperties": false,
602
+ "required": ["applicable"],
603
+ "properties": {
604
+ "applicable": { "type": "boolean" },
605
+ "exemptionReason": { "type": "string" },
606
+ "items": {
607
+ "type": "array",
608
+ "items": {
609
+ "type": "object",
610
+ "additionalProperties": false,
611
+ "required": ["target", "environmentSetup", "steps", "expectedResult"],
612
+ "properties": {
613
+ "target": { "type": "string" },
614
+ "environmentSetup": { "type": "string" },
615
+ "steps": { "type": "array", "items": { "type": "string" } },
616
+ "expectedResult": { "type": "string" }
617
+ }
618
+ }
619
+ }
620
+ }
621
+ },
583
622
  "routingRecommendation": { "type": "string", "minLength": 1 }
584
623
  }
585
624
  },
@@ -593,6 +632,7 @@
593
632
  "residualRisk",
594
633
  "validationEvidence",
595
634
  "readonlyCommandLog",
635
+ "manualUserTest",
596
636
  "routingRecommendation"
597
637
  ],
598
638
  "additionalProperties": false,
@@ -640,6 +680,29 @@
640
680
  "type": "array",
641
681
  "items": { "$ref": "#/$defs/ReadonlyCommandRow" }
642
682
  },
683
+ "manualUserTest": {
684
+ "type": "object",
685
+ "additionalProperties": false,
686
+ "required": ["applicable"],
687
+ "properties": {
688
+ "applicable": { "type": "boolean" },
689
+ "exemptionReaffirm": { "type": "string" },
690
+ "results": {
691
+ "type": "array",
692
+ "items": {
693
+ "type": "object",
694
+ "additionalProperties": false,
695
+ "required": ["target", "performed", "result", "observed"],
696
+ "properties": {
697
+ "target": { "type": "string" },
698
+ "performed": { "type": "string" },
699
+ "result": { "type": "string" },
700
+ "observed": { "type": "string" }
701
+ }
702
+ }
703
+ }
704
+ }
705
+ },
643
706
  "routingRecommendation": { "type": "string", "minLength": 1 }
644
707
  }
645
708
  },
@@ -1318,7 +1381,7 @@
1318
1381
  "properties": {
1319
1382
  "id": { "type": "string", "pattern": "^DM-\\d{3,}$" },
1320
1383
  "kind": {
1321
- "enum": ["order", "backfill", "flag-precondition", "repo-sequencing", "other"]
1384
+ "enum": ["order", "backfill", "flag-precondition", "repo-sequencing", "cross-project", "other"]
1322
1385
  },
1323
1386
  "item": { "type": "string", "minLength": 1 },
1324
1387
  "impact": { "type": "string", "minLength": 1 },
@@ -1326,6 +1389,46 @@
1326
1389
  }
1327
1390
  },
1328
1391
 
1392
+ "CrossProjectDependency": {
1393
+ "type": "object",
1394
+ "required": ["id", "direction", "project", "requiredWork", "verificationSignal", "linkedWork", "howToStart"],
1395
+ "additionalProperties": false,
1396
+ "properties": {
1397
+ "id": { "type": "string", "pattern": "^XP-\\d{3,}$" },
1398
+ "direction": { "enum": ["upstream-precondition", "downstream-carry"] },
1399
+ "project": { "type": "string", "minLength": 1 },
1400
+ "requiredWork": { "type": "string", "minLength": 1 },
1401
+ "verificationSignal": { "type": "string", "minLength": 1 },
1402
+ "linkedWork": { "type": "string", "minLength": 1 },
1403
+ "howToStart": { "type": "string", "minLength": 1 }
1404
+ }
1405
+ },
1406
+
1407
+ "DecisionDraft": {
1408
+ "type": "object",
1409
+ "required": ["number", "slug", "status", "context", "decision", "consequences", "alternativesConsidered"],
1410
+ "additionalProperties": false,
1411
+ "properties": {
1412
+ "number": { "type": "string", "pattern": "^\\d{4,}$" },
1413
+ "slug": { "type": "string", "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" },
1414
+ "status": { "enum": ["Proposed"] },
1415
+ "context": { "type": "string", "minLength": 1 },
1416
+ "decision": { "type": "string", "minLength": 1 },
1417
+ "consequences": { "type": "string", "minLength": 1 },
1418
+ "alternativesConsidered": { "type": "string", "minLength": 1 }
1419
+ }
1420
+ },
1421
+
1422
+ "SkippedAdrCandidate": {
1423
+ "type": "object",
1424
+ "required": ["topic", "reason"],
1425
+ "additionalProperties": false,
1426
+ "properties": {
1427
+ "topic": { "type": "string", "minLength": 1 },
1428
+ "reason": { "type": "string", "minLength": 1 }
1429
+ }
1430
+ },
1431
+
1329
1432
  "ValidationCheckRow": {
1330
1433
  "type": "object",
1331
1434
  "required": ["id", "phase", "ticketId", "check", "commandOrObservation", "expectedOutcome"],
@@ -1,10 +1,10 @@
1
1
  ---
2
- name: okstra-container
2
+ name: okstra-container-build
3
3
  description: |
4
4
  Use to bring up, inspect, or tear down the okstra user-test container runtime for an implementation task — the docker-compose group okstra deploys from a task's worktree so a human can poke at the running build. Trigger words include "okstra container", "okstra container up", "okstra container down", "컨테이너 띄워", "컨테이너 올려", "컨테이너 내려", "컨테이너 상태", "컨테이너 로그", "유저 테스트 환경", "user test environment", "docker compose 띄워줘", "이 task 컨테이너로 띄워", "watcher 멈춰", "stop watcher", "감시 종료".
5
5
  ---
6
6
 
7
- # OKSTRA Container
7
+ # OKSTRA Container Build
8
8
 
9
9
  Single entry point for the okstra user-test container runtime. okstra provisions a docker-compose group from an `implementation` task's worktree (the `docker-compose.yml` at the worktree root), labels it with the task's run-trace so later sub-commands can find the group, and tails it through a tmux watcher pane. This skill drives that lifecycle. Sub-commands:
10
10
 
@@ -78,7 +78,7 @@ okstra container up --project-root <projectRoot> --task-key <task-key>
78
78
 
79
79
  Parse the stdout JSON and report the provisioned services and the watcher pane. If a service failed its healthcheck, the call surfaces the failing services and the `docker compose ... logs` line to inspect — relay that line; do not invent your own.
80
80
 
81
- After a successful `up`, tell the user how to reach the running build (the compose file's published ports) and that `okstra container status <task-key>` / `okstra container down <task-key>` manage it from here.
81
+ After a successful `up`, tell the user how to reach the running build (the compose file's published ports) and that `okstra container status <task-key>` / `okstra container down <task-key>` manage it from here. For *what to verify* once it is up, point the user to the implementation report's §5.7.9 Manual User Test (Draft) — its steps and expected results are the manual test script for this build.
82
82
 
83
83
  ---
84
84
 
@@ -217,6 +217,22 @@ implementation-option: {{ frontmatter.implementationOption | yaml_scalar }}
217
217
  {% endfor %}
218
218
  {%- endif %}
219
219
 
220
+ ### Cross-Project Dependencies{% if t("sectionAside.crossProjectDependencies") != "Cross-Project Dependencies" %} ({{ t("sectionAside.crossProjectDependencies") }}){% endif %}
221
+
222
+ {% if implementationPlanning.crossProjectDependencies | length == 0 -%}
223
+ {{ t("emptyState.crossProjectDependencies") }}
224
+ {%- else %}
225
+ {% for xp in implementationPlanning.crossProjectDependencies %}
226
+ **{{ xp.id }} — [{{ xp.direction }}] {{ xp.project }}**
227
+
228
+ - {{ t("implementationPlanning.crossProjectFields.requiredWork") }}: {{ xp.requiredWork }}
229
+ - {{ t("implementationPlanning.crossProjectFields.verificationSignal") }}: {{ xp.verificationSignal }}
230
+ - {{ t("implementationPlanning.crossProjectFields.linkedWork") }}: {{ xp.linkedWork }}
231
+ - {{ t("implementationPlanning.crossProjectFields.howToStart") }}: {{ xp.howToStart }}
232
+ {% endfor %}
233
+ {{ t("implementationPlanning.crossProjectRecognitionNote") }}
234
+ {%- endif %}
235
+
220
236
  ### Validation Checklist{% if t("sectionAside.validationChecklist") != "Validation Checklist" %} ({{ t("sectionAside.validationChecklist") }}){% endif %}
221
237
 
222
238
  | ID | Phase | Ticket ID | Check | Command / Observation | Expected outcome |
@@ -241,6 +257,25 @@ implementation-option: {{ frontmatter.implementationOption | yaml_scalar }}
241
257
  | {{ row.id | mdcell }} | `{{ row.source | mdcell }}` | {{ row.requirement | mdcell }} | {{ row.coveredBy | mdcell }} | `{{ row.status | mdcell }}` |
242
258
  {% endfor %}
243
259
 
260
+ ### Decision Drafts{% if t("sectionAside.decisionDrafts") != "Decision Drafts" %} ({{ t("sectionAside.decisionDrafts") }}){% endif %}
261
+
262
+ {% if (implementationPlanning.decisionDrafts | length == 0) and (implementationPlanning.skippedAdrCandidates | length == 0) -%}
263
+ {{ t("emptyState.decisionDrafts") }}
264
+ {%- else %}
265
+ {% for d in implementationPlanning.decisionDrafts %}
266
+ #### {{ d.number }}-{{ d.slug }}
267
+
268
+ - **{{ t("implementationPlanning.decisionDraftFields.status") }}:** {{ d.status }}
269
+ - **{{ t("implementationPlanning.decisionDraftFields.context") }}:** {{ d.context }}
270
+ - **{{ t("implementationPlanning.decisionDraftFields.decision") }}:** {{ d.decision }}
271
+ - **{{ t("implementationPlanning.decisionDraftFields.consequences") }}:** {{ d.consequences }}
272
+ - **{{ t("implementationPlanning.decisionDraftFields.alternativesConsidered") }}:** {{ d.alternativesConsidered }}
273
+ {% endfor %}
274
+ {% for s in implementationPlanning.skippedAdrCandidates %}
275
+ - skipped adr-candidate: {{ s.topic }} — reason: {{ s.reason }}
276
+ {% endfor %}
277
+ {%- endif %}
278
+
244
279
  ## 5.5 Stage Map
245
280
 
246
281
  | stage | title | depends-on | step-count | exit-contract-summary |
@@ -482,7 +517,21 @@ implementation-option: {{ frontmatter.implementationOption | yaml_scalar }}
482
517
  | {{ row.category | mdcell }} | `{{ row.rollbackCommand | mdcell }}` | {{ row.verification | mdcell }} | `{{ row.result | mdcell }}` |
483
518
  {% endfor %}
484
519
 
485
- ### 5.7.9 Routing Recommendation
520
+ ### 5.7.9 Manual User Test (Draft)
521
+
522
+ {% if implementation.manualUserTest.applicable -%}
523
+ {% for item in implementation.manualUserTest.items %}
524
+ - **{{ item.target }}**
525
+ - {{ t("manualUserTest.environmentSetup") }}: {{ item.environmentSetup }}
526
+ - {{ t("manualUserTest.steps") }}:
527
+ {% for step in item.steps %} {{ loop.index }}. {{ step }}
528
+ {% endfor %} - {{ t("manualUserTest.expectedResult") }}: {{ item.expectedResult }}
529
+ {% endfor %}
530
+ {%- else -%}
531
+ - {{ t("manualUserTest.notApplicable") }}: {{ implementation.manualUserTest.exemptionReason }}
532
+ {%- endif %}
533
+
534
+ ### 5.7.10 Routing Recommendation
486
535
 
487
536
  {{ implementation.routingRecommendation }}
488
537
 
@@ -565,7 +614,19 @@ implementation-option: {{ frontmatter.implementationOption | yaml_scalar }}
565
614
  {% endfor %}
566
615
  {%- endif %}
567
616
 
568
- ### 5.8.7 Routing Recommendation
617
+ ### 5.8.7 Manual User Test Results
618
+
619
+ {% if finalVerification.manualUserTest.applicable -%}
620
+ | {{ t("manualUserTest.performed") }} | {{ t("manualUserTest.result") }} | {{ t("manualUserTest.observed") }} |
621
+ |---|---|---|
622
+ {% for row in finalVerification.manualUserTest.results -%}
623
+ | {{ row.target | mdcell }} — {{ row.performed | mdcell }} | `{{ row.result | mdcell }}` | {{ row.observed | mdcell }} |
624
+ {% endfor %}
625
+ {%- else -%}
626
+ - {{ t("manualUserTest.notApplicable") }}: {{ finalVerification.manualUserTest.exemptionReaffirm }}
627
+ {%- endif %}
628
+
629
+ ### 5.8.8 Routing Recommendation
569
630
 
570
631
  {{ finalVerification.routingRecommendation }}
571
632
 
@@ -40,7 +40,7 @@ taskType: "{{FM_TASK_TYPE}}"
40
40
  - Path (project-relative) to the originating `implementation` final-report:
41
41
  - Quoted `Commit list` / `Diff summary` excerpt from the implementation report:
42
42
 
43
- > 보고서 경로가 비거나 누락된 보고서를 가리키면 final-verification 은 status `blocked` 으로 끝내고 `implementation` 또는 `implementation-planning` 으로 라우팅합니다. 검증 대상(worktree/base/head)은 okstra 가 자동 해소하므로 수동 기입이 어긋나 막히는 일은 없습니다.
43
+ > 보고서 경로가 비거나 누락된 보고서를 가리키면 final-verification 은 status `blocked` 으로 끝내고 `implementation` 또는 `implementation-planning` 으로 라우팅합니다. 검증 대상(worktree/base)은 okstra 가 자동 해소하므로 수동 기입이 어긋나 막히는 일은 없습니다.
44
44
 
45
45
  ## Requirement Coverage Source
46
46
 
@@ -55,7 +55,7 @@ taskType: "{{FM_TASK_TYPE}}"
55
55
 
56
56
  - PR or change summary:
57
57
  - Test results:
58
- - Manual verification notes:
58
+ - Manual verification notes (execute the source implementation report's §5.7.9 Manual User Test Draft and record results here):
59
59
  - Related code paths:
60
60
  - Release or rollout notes:
61
61
  - Previous reports in the same task history:
@@ -90,7 +90,7 @@ taskType: "{{FM_TASK_TYPE}}"
90
90
 
91
91
  ## Questions for Analysers
92
92
 
93
- 1. Did your analysis run against the injected `VERIFICATION_TARGET` (base / head SHA / worktree), and does the diff at that target fully cover the stage(s) under verification? (A head you cannot confirm against the injected target is a `tool-failure`, not a silent proceed.)
93
+ 1. Did your analysis run against the injected `VERIFICATION_TARGET` (base ref / worktree), and does the worktree's delivered diff fully cover the stage(s) under verification? (A worktree you cannot confirm against the injected target is a `tool-failure`, not a silent proceed.)
94
94
  2. For each requirement / acceptance criterion, what exact artifact (commit SHA, test output, log line, config value) proves coverage?
95
95
  3. Are there any acceptance blockers?
96
96
  4. What residual risks remain?
@@ -9,6 +9,8 @@
9
9
  "primaryEvidence": "- No primary evidence.",
10
10
  "secondaryEvidence": "- No secondary evidence or alternate interpretations.",
11
11
  "risks": "- No missing information or risks.",
12
+ "crossProjectDependencies": "- No upstream/downstream dependency on another project.",
13
+ "decisionDrafts": "- No decision drafts or skipped ADR candidates.",
12
14
  "dependencyRisk": "- No dependency / migration risks.",
13
15
  "dissent": "- No dissenting opinions.",
14
16
  "outOfPlanEdits": "- No out-of-plan edits.",
@@ -29,6 +31,8 @@
29
31
  "checkMethod": "How to check"
30
32
  },
31
33
  "sectionAside": {
34
+ "crossProjectDependencies": "Cross-Project Dependencies",
35
+ "decisionDrafts": "Decision Drafts",
32
36
  "dependencyRisk": "Dependency / Migration Risk",
33
37
  "validationChecklist": "Validation Checklist",
34
38
  "rollbackStrategy": "Rollback Strategy",
@@ -95,7 +99,21 @@
95
99
  "rationaleLabel": "Rationale (trade-off row / principle)",
96
100
  "rejectedSummaryLabel": "Summary of rejected options",
97
101
  "columnImpact": "Impact",
98
- "columnMitigation": "Mitigation / prerequisite"
102
+ "columnMitigation": "Mitigation / prerequisite",
103
+ "crossProjectFields": {
104
+ "requiredWork": "Required work",
105
+ "verificationSignal": "Verification signal",
106
+ "linkedWork": "Linked work",
107
+ "howToStart": "How to start"
108
+ },
109
+ "crossProjectRecognitionNote": "Note: the other project's run is structurally independent — its done-set, stage numbers, and depends-on all resolve against its own repo, and this run's completed stages are NOT auto-recognized as done there. This section is narrative input that seeds the other run's planning only.",
110
+ "decisionDraftFields": {
111
+ "status": "Status",
112
+ "context": "Context",
113
+ "decision": "Decision",
114
+ "consequences": "Consequences",
115
+ "alternativesConsidered": "Alternatives Considered"
116
+ }
99
117
  },
100
118
  "releaseHandoff": {
101
119
  "auditNote": "Audit trail for the phase that ran git/gh mutating commands.",
@@ -145,6 +163,15 @@
145
163
  "verificationScope": "Verification scope",
146
164
  "stageReportsLabel": "Source implementation reports (per stage)"
147
165
  },
166
+ "manualUserTest": {
167
+ "environmentSetup": "Environment",
168
+ "steps": "Steps",
169
+ "expectedResult": "Expected result",
170
+ "notApplicable": "Manual user test not required",
171
+ "performed": "Performed",
172
+ "result": "Result",
173
+ "observed": "Observed"
174
+ },
148
175
  "index": {
149
176
  "heading": "Index",
150
177
  "sectionsLabel": "Sections",
@@ -9,6 +9,8 @@
9
9
  "primaryEvidence": "- 주 증거 없음.",
10
10
  "secondaryEvidence": "- 보조 증거 또는 대안 해석 없음.",
11
11
  "risks": "- 누락된 정보·위험 없음.",
12
+ "crossProjectDependencies": "- 다른 프로젝트에 대한 선행/후속 의존 없음.",
13
+ "decisionDrafts": "- 결정 기록 초안이나 스킵된 ADR 후보 없음.",
12
14
  "dependencyRisk": "- 의존성·마이그레이션 위험 없음.",
13
15
  "dissent": "- 반대 의견 없음.",
14
16
  "outOfPlanEdits": "- 계획 외 편집 없음.",
@@ -29,6 +31,8 @@
29
31
  "checkMethod": "확인 방법"
30
32
  },
31
33
  "sectionAside": {
34
+ "crossProjectDependencies": "프로젝트 간 의존성",
35
+ "decisionDrafts": "결정 기록 초안",
32
36
  "dependencyRisk": "의존성·마이그레이션 위험",
33
37
  "validationChecklist": "검증 체크리스트",
34
38
  "rollbackStrategy": "롤백 전략",
@@ -95,7 +99,21 @@
95
99
  "rationaleLabel": "근거 (Trade-off 행 / 원칙)",
96
100
  "rejectedSummaryLabel": "채택되지 않은 옵션 요약",
97
101
  "columnImpact": "영향",
98
- "columnMitigation": "완화 / 선행 작업"
102
+ "columnMitigation": "완화 / 선행 작업",
103
+ "crossProjectFields": {
104
+ "requiredWork": "필요 작업",
105
+ "verificationSignal": "검증 신호",
106
+ "linkedWork": "연결된 작업",
107
+ "howToStart": "시작 방법"
108
+ },
109
+ "crossProjectRecognitionNote": "참고: 상대 프로젝트의 run 은 구조적으로 독립이다 — done-set·stage 번호·depends-on 이 모두 자기 repo 기준이며, 이 run 의 완료 stage 가 자동으로 done 으로 인식되지 않는다. 이 섹션은 상대 run 의 planning 을 seed 하는 narrative 입력일 뿐이다.",
110
+ "decisionDraftFields": {
111
+ "status": "상태",
112
+ "context": "맥락",
113
+ "decision": "결정",
114
+ "consequences": "결과",
115
+ "alternativesConsidered": "검토한 대안"
116
+ }
99
117
  },
100
118
  "releaseHandoff": {
101
119
  "auditNote": "git/gh mutating 명령이 실행된 phase 의 감사 기록.",
@@ -145,6 +163,15 @@
145
163
  "verificationScope": "검증 범위",
146
164
  "stageReportsLabel": "stage 별 구현 리포트"
147
165
  },
166
+ "manualUserTest": {
167
+ "environmentSetup": "환경 기동",
168
+ "steps": "확인 스텝",
169
+ "expectedResult": "기대 결과",
170
+ "notApplicable": "사용자 테스트 불필요",
171
+ "performed": "수행",
172
+ "result": "결과",
173
+ "observed": "관찰값"
174
+ },
148
175
  "index": {
149
176
  "heading": "목차",
150
177
  "sectionsLabel": "섹션",
@@ -36,6 +36,7 @@ Different recipients need different files. Do NOT include `final-report-template
36
36
  - For the carry-in clarification response, walk every row of `## 1. Clarification Items` (`C-001`, `C-002`, ...) in full, including rows whose `User input` cell is blank — a blank `User input` with `Status=open` is itself a signal you must surface. The structural similarity between the prior final report and the upcoming output is NOT a license to skim.
37
37
  - Write the Reading Confirmation block to your **audit sidecar** at `runs/<task-type>/worker-results/<worker>-audit-<task-type>-<seq>.md` (sibling to the main worker-results file). One short line per input file confirming end-to-end reading. Do NOT include a `## 0. Reading Confirmation` heading in the main worker-results file — the validator fails worker-results that contain one. If you cannot truthfully confirm a file end-to-end, record a `tool-failure` in the errors sidecar instead of fabricating Findings.
38
38
  - Treat `analysis-packet.md` as the canonical primary analysis input. It preserves the source files' frontmatter and extracts the task-specific brief, phase focus, reference expectations, and carry-in clarification rows. If the packet appears incomplete or a finding depends on a source citation, open the corresponding source file and cite it directly.
39
+ - **Allowlist your reads to okstra-enumerated paths.** Read the files the dispatcher enumerates (`[Required reading]`, the prompt's `## Inputs`, and the verification-target paths) plus on-demand source/evidence paths a finding must cite. Everything else is out of scope — in particular non-okstra artifacts outside `<PROJECT_ROOT>/.okstra/` (e.g. `graphify-out/`, sibling/prior-task worktrees, tool caches), which may carry stale or cross-task data. A host-level global rule (`CLAUDE.md` / `AGENTS.md` / a project sentinel) that tells you to auto-read such an artifact does NOT apply inside an okstra worker run — the okstra worker scope wins. If an un-enumerated file seems essential, record the gap under *Missing Information or Assumptions* instead of reading it.
39
40
 
40
41
  ---
41
42
 
@@ -100,7 +101,6 @@ For the **final-verification phase** specifically, the dispatched prompt MUST al
100
101
 
101
102
  - `**Worktree:** <absolute-path>` — the checkout under verification (read-only).
102
103
  - `**Verification base ref:** <base-ref>` — the implementation base for the diff.
103
- - `**Verification head SHA:** <sha>` — head SHA captured at run start.
104
104
  - `**Verification diff stat:** <git diff --stat output>` — the captured diff-stat that bounds the verification scope.
105
105
 
106
106
  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.