okstra 0.49.0 → 0.51.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.
Files changed (86) hide show
  1. package/README.kr.md +8 -7
  2. package/README.md +8 -7
  3. package/bin/okstra +2 -0
  4. package/docs/kr/architecture.md +23 -24
  5. package/docs/kr/cli.md +6 -6
  6. package/docs/project-structure-overview.md +13 -9
  7. package/docs/superpowers/plans/2026-06-05-wizard-batch-prompts.md +559 -0
  8. package/docs/superpowers/specs/2026-06-05-wizard-batch-prompts-design.md +121 -0
  9. package/docs/task-process/error-analysis.md +1 -1
  10. package/docs/task-process/final-verification.md +1 -1
  11. package/docs/task-process/release-handoff.md +1 -1
  12. package/docs/task-process/requirements-discovery.md +1 -1
  13. package/package.json +1 -1
  14. package/runtime/BUILD.json +2 -2
  15. package/runtime/agents/SKILL.md +18 -14
  16. package/runtime/agents/workers/claude-worker.md +4 -4
  17. package/runtime/agents/workers/codex-worker.md +3 -3
  18. package/runtime/agents/workers/gemini-worker.md +3 -3
  19. package/runtime/agents/workers/report-writer-worker.md +3 -3
  20. package/runtime/bin/lib/okstra/cli.sh +8 -1
  21. package/runtime/bin/lib/okstra/globals.sh +3 -0
  22. package/runtime/bin/lib/okstra/interactive.sh +14 -12
  23. package/runtime/bin/lib/okstra/usage.sh +6 -0
  24. package/runtime/bin/okstra-render-report-views.py +1 -1
  25. package/runtime/bin/okstra-team-reconcile.sh +28 -0
  26. package/runtime/bin/okstra.sh +2 -0
  27. package/runtime/prompts/launch.template.md +4 -2
  28. package/runtime/prompts/profiles/_common-contract.md +15 -15
  29. package/runtime/prompts/profiles/_implementation-deliverable.md +1 -1
  30. package/runtime/prompts/profiles/_implementation-executor.md +3 -3
  31. package/runtime/prompts/profiles/_implementation-verifier.md +2 -2
  32. package/runtime/prompts/profiles/error-analysis.md +1 -1
  33. package/runtime/prompts/profiles/final-verification.md +2 -2
  34. package/runtime/prompts/profiles/implementation-planning.md +10 -9
  35. package/runtime/prompts/profiles/implementation.md +1 -1
  36. package/runtime/prompts/profiles/improvement-discovery.md +5 -5
  37. package/runtime/prompts/profiles/release-handoff.md +2 -2
  38. package/runtime/prompts/profiles/requirements-discovery.md +2 -2
  39. package/runtime/python/okstra_ctl/analysis_packet.py +259 -0
  40. package/runtime/python/okstra_ctl/clarification_items.py +11 -11
  41. package/runtime/python/okstra_ctl/context_cost.py +308 -0
  42. package/runtime/python/okstra_ctl/migrate.py +2 -12
  43. package/runtime/python/okstra_ctl/paths.py +22 -0
  44. package/runtime/python/okstra_ctl/render.py +285 -126
  45. package/runtime/python/okstra_ctl/render_final_report.py +32 -1
  46. package/runtime/python/okstra_ctl/report_views.py +12 -12
  47. package/runtime/python/okstra_ctl/run.py +510 -248
  48. package/runtime/python/okstra_ctl/sequence.py +2 -5
  49. package/runtime/python/okstra_ctl/team_reconcile.py +131 -0
  50. package/runtime/python/okstra_ctl/wizard.py +219 -136
  51. package/runtime/python/okstra_ctl/workflow.py +1 -1
  52. package/runtime/python/okstra_ctl/worktree.py +13 -5
  53. package/runtime/schemas/final-report-v1.0.schema.json +4 -0
  54. package/runtime/skills/okstra-brief/SKILL.md +1 -1
  55. package/runtime/skills/okstra-coding-preflight/SKILL.md +69 -0
  56. package/runtime/skills/okstra-coding-preflight/architecture/hexagonal.md +116 -0
  57. package/runtime/skills/okstra-coding-preflight/clean-code.md +254 -0
  58. package/runtime/skills/okstra-coding-preflight/languages/java.md +64 -0
  59. package/runtime/skills/okstra-coding-preflight/languages/javascript-typescript.md +87 -0
  60. package/runtime/skills/okstra-coding-preflight/languages/kotlin.md +69 -0
  61. package/runtime/skills/okstra-coding-preflight/languages/nodejs.md +66 -0
  62. package/runtime/skills/okstra-coding-preflight/languages/python.md +179 -0
  63. package/runtime/skills/okstra-coding-preflight/languages/rust.md +105 -0
  64. package/runtime/skills/okstra-coding-preflight/languages/sql.md +68 -0
  65. package/runtime/skills/okstra-context-loader/SKILL.md +12 -6
  66. package/runtime/skills/okstra-convergence/SKILL.md +8 -8
  67. package/runtime/skills/okstra-inspect/SKILL.md +100 -1
  68. package/runtime/skills/okstra-report-writer/SKILL.md +27 -23
  69. package/runtime/skills/okstra-run/SKILL.md +3 -1
  70. package/runtime/skills/okstra-team-contract/SKILL.md +8 -5
  71. package/runtime/templates/reports/final-report.template.md +188 -187
  72. package/runtime/templates/reports/i18n/en.json +4 -4
  73. package/runtime/templates/reports/i18n/ko.json +4 -4
  74. package/runtime/templates/reports/implementation-planning-input.template.md +1 -1
  75. package/runtime/templates/reports/release-handoff-input.template.md +1 -1
  76. package/runtime/templates/reports/user-response.template.md +1 -1
  77. package/runtime/templates/worker-prompt-preamble.md +4 -4
  78. package/runtime/validators/lib/fixtures.sh +2 -2
  79. package/runtime/validators/validate-implementation-plan-stages.py +9 -9
  80. package/runtime/validators/validate-report-views.py +10 -10
  81. package/runtime/validators/validate-run.py +36 -36
  82. package/runtime/validators/validate_improvement_report.py +8 -8
  83. package/src/_python-helper.mjs +3 -3
  84. package/src/context-cost.mjs +27 -0
  85. package/src/install.mjs +1 -0
  86. package/src/uninstall.mjs +1 -0
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: okstra-inspect
3
3
  description: |
4
- Use for any read-side okstra inspection or status mutation. Single skill dispatches by sub-command to five facets — status, history, report, time, logs. Trigger words include "okstra status", "task status", "current phase", "next phase", "okstra status set", "okstra mark", "<task-id> done|in-progress|진행중|완료", "okstra history", "past runs", "re-run", "resume", "list tasks", "find report", "show report for", "read the okstra report", "continue from report", "작업 시간", "소요 시간", "time summary", "duration", "elapsed", "얼마나 걸렸", "시간 분석", "okstra logs", "로그 현황", "로그 파일", "log files", "log size", "log status", "로그 정리", "log cleanup".
4
+ Use for any read-side okstra inspection or status mutation. Single skill dispatches by sub-command to six facets — status, history, report, time, logs, cost. Trigger words include "okstra status", "task status", "current phase", "next phase", "okstra status set", "okstra mark", "<task-id> done|in-progress|진행중|완료", "okstra history", "past runs", "re-run", "resume", "list tasks", "find report", "show report for", "read the okstra report", "continue from report", "작업 시간", "소요 시간", "time summary", "duration", "elapsed", "얼마나 걸렸", "시간 분석", "okstra logs", "로그 현황", "로그 파일", "log size", "log status", "로그 정리", "log cleanup", "okstra context-cost", "context cost", "context-cost", "컨텍스트 비용", "읽기 비용", "산출물 비용".
5
5
  ---
6
6
 
7
7
  # OKSTRA Inspect
@@ -15,6 +15,7 @@ Single read-side entry point for okstra runtime inspection plus the one write-si
15
15
  | `report` | Resolve final-report path for a task-key. Optionally read it. |
16
16
  | `time` | Per-task-type and per-worker duration breakdown for a task. |
17
17
  | `logs` | Inventory codex/gemini wrapper `.log` sidecars; emit cleanup commands. |
18
+ | `cost` | Estimate file/read context cost for a task bundle. |
18
19
 
19
20
  ## Step 0: Verify okstra runtime + project setup (shared)
20
21
 
@@ -467,6 +468,104 @@ Never write `claude (claude)` — the parenthesized agent is shown only when it
467
468
 
468
469
  ---
469
470
 
471
+ ## cost
472
+
473
+ Trigger phrases: "okstra context-cost", "context cost", "context-cost", "컨텍스트 비용", "읽기 비용", "산출물 비용", "task bundle cost", "agent read cost".
474
+
475
+ Read-only estimate of how much file/context surface a prepared task bundle asks the lead, analysis workers, and report-writer to absorb. This sub-command does **not** mutate task artifacts.
476
+
477
+ ### cost.1 — Resolve target
478
+
479
+ Accepted target forms:
480
+
481
+ 1. Full task-key: `<project-id>:<task-group>:<task-id>`.
482
+ 2. Task id only, e.g. `DEV-9184`.
483
+ 3. Task root path, e.g. `<projectRoot>/.okstra/tasks/<group>/<task-id>`.
484
+
485
+ If the user gives a task root path, run `okstra context-cost <absolute-or-user-provided-path>` directly.
486
+
487
+ If the user gives a full task-key, run:
488
+
489
+ ```bash
490
+ okstra context-cost <task-key> --project-root <projectRoot>
491
+ ```
492
+
493
+ If the user gives only a task id:
494
+
495
+ 1. Read `.okstra/discovery/task-catalog.json`.
496
+ 2. Match `taskId` case-insensitively.
497
+ 3. Single match → use its `taskKey`.
498
+ 4. Multiple matches → list candidates and ask the user to retry with a full task-key.
499
+ 5. No match → report that the task cannot be found.
500
+
501
+ If the user asks generally ("컨텍스트 비용 보여줘") and does not name a task:
502
+
503
+ 1. Read `.okstra/discovery/task-catalog.json`.
504
+ 2. If exactly one task exists, use it.
505
+ 3. If multiple tasks exist, show the latest 10 by `updatedAt` and ask which task to measure. Do not guess.
506
+
507
+ ### cost.2 — Run estimator
508
+
509
+ Use the CLI output as the source of truth:
510
+
511
+ ```bash
512
+ okstra context-cost <resolved-target> --project-root <projectRoot>
513
+ ```
514
+
515
+ Do not re-count files manually unless the CLI fails and the user explicitly asks for manual fallback.
516
+
517
+ ### cost.3 — Summarize output
518
+
519
+ Parse the JSON and report these fields:
520
+
521
+ | Field | Source |
522
+ |---|---|
523
+ | Task bundle | `totals.taskFileCount`, `totals.taskBytes` |
524
+ | Current run | `totals.currentRunFileCount`, `totals.currentRunBytes`, `currentRunPath` |
525
+ | Legacy timestamp artifacts | `totals.legacyTimestampFileCount` |
526
+ | Instruction set | `instructionSet.fileCount`, `instructionSet.bytes`, `instructionSet.analysisPacketBytes`, `instructionSet.legacyTaskPacketBytes` |
527
+ | Lead Phase 1 | `leadPhase1.mode`, `leadPhase1.fileCount`, `leadPhase1.bytes` |
528
+ | Analysis worker | `analysisWorker.mode`, `analysisWorker.fileCount`, `analysisWorker.bytesPerWorker`, `analysisWorker.legacyFullContractBytesPerWorker`, `analysisWorker.estimatedPacketModeBytesPerWorker`, `analysisWorker.estimatedReductionPercent` |
529
+ | Report writer | `reportWriter.fileCount`, `reportWriter.bytes` |
530
+
531
+ Format bytes as both raw bytes and rounded KB/MB where useful. Use `analysisWorker.estimatedReductionPercent` for the worker-input reduction. Do not recompute it from `bytesPerWorker` when `analysisWorker.mode == "analysis-packet-primary"` because `bytesPerWorker` is already the packet-primary cost.
532
+
533
+ ### cost.4 — Output template
534
+
535
+ ```markdown
536
+ ## okstra Context Cost — <task-key>
537
+
538
+ | Surface | Files | Size |
539
+ |---|---:|---:|
540
+ | Task bundle | <N> | <bytes> (<human>) |
541
+ | Current run | <N> | <bytes> (<human>) |
542
+ | Instruction set | <N> | <bytes> (<human>) |
543
+ | Lead Phase 1 (`<mode>`) | <N> | <bytes> (<human>) |
544
+ | Analysis worker / worker (`<mode>`) | <N> | <bytes> (<human>) |
545
+ | Report writer synthesis | <N> | <bytes> (<human>) |
546
+
547
+ - Current run: `<currentRunPath-or-->`
548
+ - Legacy timestamp artifacts: `<N>`
549
+ - Legacy full worker contract: `<legacyFullContractBytesPerWorker>` bytes (`<human>`) per analysis worker
550
+ - Packet estimate: `<estimatedPacketModeBytesPerWorker>` bytes (`<human>`) per analysis worker
551
+ - Estimated worker-input reduction: `<percent>%`
552
+
553
+ ### Reading
554
+
555
+ <One or two Korean sentences explaining the main bottleneck and the next likely optimization target.>
556
+ ```
557
+
558
+ Interpretation rules:
559
+
560
+ - `leadPhase1.mode == "active-run-context"` means the compact lead intake file is present and should be treated as the primary lead read surface.
561
+ - `leadPhase1.mode == "legacy-five-file"` means this task was prepared before active-run-context, or the manifest does not reference it.
562
+ - `analysisWorker.mode == "analysis-packet-primary"` means new workers should read `analysis-packet.md` first and open full source inputs only for evidence checks or missing detail.
563
+ - If `analysisWorker.mode == "full-input-contract"` and `estimatedReductionPercent` is low, the next target is worker prompt/input contract slimming.
564
+ - If `reportWriter.bytes` dominates, the next target is a compact `synthesis-input` artifact.
565
+ - If `legacyTimestampFileCount` is high, recommend current-view/cold-artifact separation or retention cleanup, not destructive deletion by default.
566
+
567
+ ---
568
+
470
569
  ## logs
471
570
 
472
571
  Trigger phrases: "okstra logs", "로그 현황", "로그 파일", "log files", "log size", "log status", "로그 정리", "log cleanup".
@@ -12,6 +12,8 @@ The final-report **data.json** (JSON SSOT) at `runs/<task-type>/reports/final-re
12
12
 
13
13
  The data.json schema is `schemas/final-report-v1.0.schema.json`. The renderer + the run-validator both consume that schema, so a data.json that validates is guaranteed to render into a markdown that passes the contract checks.
14
14
 
15
+ Two `frontmatter` approval fields are always emitted with their unset default — never pre-fill them: `frontmatter.approved` is emitted as `false`, and `frontmatter.implementationOption` is emitted as an empty string `""`. The user later flips `approved` to `true` (via `--approve` or manual edit) and fills `implementationOption` with the chosen Option Candidate name (via `--implementation-option <name>` or manual edit) to authorise and scope the next `implementation` run.
16
+
15
17
  If you are reading this skill **as the report-writer-worker subagent**, YOU are the one calling the `Write` tool against the data.json path AND invoking the renderer via `Bash`. Do not return either artifact inline — the files on disk are the canonical record.
16
18
 
17
19
  If you are reading this skill **as Claude lead**, your job in Phase 6 is to (a) prepare the report-writer prompt, (b) dispatch the Report writer worker per the Phase 6 dispatch template in SKILL.md, (c) review both files in Phase 7. Do not call `Write` against either path yourself when Report writer worker is in the roster.
@@ -33,11 +35,13 @@ Agent(
33
35
  name: "report-writer",
34
36
  subagent_type: "report-writer-worker",
35
37
  team_name: "okstra-<task-key>", # omit if team is not alive — see Resume-safe dispatch
36
- model: "opus",
38
+ model: "<family token of Report writer worker's modelExecutionValue>", # opus/sonnet/haiku — NOT hardcoded; see below
37
39
  mode: "auto"
38
40
  )
39
41
  ```
40
42
 
43
+ The `model:` parameter is **derived from the Report writer worker's `modelExecutionValue`** in `task-manifest.json`, mapped to an Agent family token (`opus` / `sonnet` / `haiku`) per [okstra-team-contract](../okstra-team-contract/SKILL.md) "Model Assignment Rules" #3–#4. Do NOT hardcode it — the report-writer-worker definition is `model: inherit`, so without this explicit parameter the worker silently runs on the lead's model instead of its assignment. The same `modelExecutionValue` feeds the prompt header in item 6 below, so the spawn model and the recorded `**Model:**` header always agree.
44
+
41
45
  The prompt MUST include, in this order at the top:
42
46
 
43
47
  1. `**Project Root:** <absolute-path>`
@@ -48,9 +52,9 @@ The prompt MUST include, in this order at the top:
48
52
  6. `**Model:** Report writer worker, <modelExecutionValue>` (resolved per Phase 5.5 anchor-header rules)
49
53
  7. The full `[Required reading]` clause (see [okstra-team-contract](../okstra-team-contract/SKILL.md)) — for Phase 6 it adds two **per-task-type, instruction-set-local** read-only files, both scoped to this run's task-type by `okstra-ctl` at prep time:
50
54
  - `<instruction-set>/final-report-schema.json` — a task-type excerpt of the data.json schema (the other task-types' deliverable blocks and their unreachable `$defs` are stripped; ~38% of the full schema is `$defs` alone). This is your authoring contract for the data.json shape. Do **NOT** pull the full `schemas/final-report-v1.0.schema.json` — it carries all task-types and its `schemas/...` path is not part of the task bundle. (Validation still runs against the full schema post-hoc via the renderer, so the excerpt never relaxes the contract.)
51
- - `<instruction-set>/final-report-template.md` — the **phase-stripped** template (every other task-type's §4.x deliverable block removed by `render.py`'s `_strip_phase_blocks`, leaving only your run's §4.x). Do **NOT** also pull the full `templates/reports/final-report.template.md` source (it re-adds ~330 lines of other phases' deliverables and is not in the task bundle).
55
+ - `<instruction-set>/final-report-template.md` — the **phase-stripped** template (every other task-type's §5.x deliverable block removed by `render.py`'s `_strip_phase_blocks`, leaving only your run's §5.x). Do **NOT** also pull the full `templates/reports/final-report.template.md` source (it re-adds ~330 lines of other phases' deliverables and is not in the task bundle).
52
56
  8. A one-line MCP pointer instead of the verbatim block — `**MCP servers:** follow the task brief's "## Available MCP Servers" section (already in your Required reading).` The brief is already in the report-writer's Required reading (item 7), so the verbatim block is redundant.
53
- 9. The convergence classifications (Full/Partial/Contested/Worker-Unique), the round history data (`roundHistory[]`), the `round2SkippedReason` value, and pointers to all worker result files under `worker-results/`. The report-writer worker populates `crossVerification.roundHistory` in the data.json so Section 1 can show which rounds executed, queue sizes, and why Round 2 was (or was not) skipped. The renderer prints the full per-round table only when more than one round ran; single-round or zero-round histories are auto-collapsed to a one-line summary.
57
+ 9. The convergence classifications (Full/Partial/Contested/Worker-Unique), the round history data (`roundHistory[]`), the `round2SkippedReason` value, and pointers to all worker result files under `worker-results/`. The report-writer worker populates `crossVerification.roundHistory` in the data.json so Section 6 can show which rounds executed, queue sizes, and why Round 2 was (or was not) skipped. The renderer prints the full per-round table only when more than one round ran; single-round or zero-round histories are auto-collapsed to a one-line summary.
54
58
  10. `**Report Language:** <en|ko>` — must be either `en` or `ko`; `auto`
55
59
  has been resolved by the lead from project.json / global config
56
60
  before the dispatch is constructed. The worker copies this verbatim
@@ -78,9 +82,9 @@ Speculative reasons such as "session resume constraint", "team object no longer
78
82
 
79
83
  ## Phase 6 → Phase 7 execution sequence (BLOCKING order)
80
84
 
81
- The four steps below MUST execute in this exact order. Reordering them is the recurring root cause of reports shipping with `--` token cells (Phase 7 not run yet), Section 6 missing follow-up entries, or Section 7 rows never spawning.
85
+ The four steps below MUST execute in this exact order. Reordering them is the recurring root cause of reports shipping with `--` token cells (Phase 7 not run yet), Section 3 missing follow-up entries, or Section 4 rows never spawning.
82
86
 
83
- 1. **Phase 6 — Report writer worker drafts the final-report data.json** at `runs/<task-type>/reports/final-report-<task-type>-<seq>.data.json`, then invokes `scripts/okstra-render-final-report.py` to produce the sibling markdown. Token Usage cells in the data.json are `null` at this point (renderer emits `--` for nulls); Section 6 lists prioritized actions but does NOT yet include auto-spawned follow-ups (they don't exist yet).
87
+ 1. **Phase 6 — Report writer worker drafts the final-report data.json** at `runs/<task-type>/reports/final-report-<task-type>-<seq>.data.json`, then invokes `scripts/okstra-render-final-report.py` to produce the sibling markdown. Token Usage cells in the data.json are `null` at this point (renderer emits `--` for nulls); Section 3 lists prioritized actions but does NOT yet include auto-spawned follow-ups (they don't exist yet).
84
88
  2. **Phase 7 step 1 — Token-usage collector with `--substitute-data`** (BLOCKING). One invocation aggregates `leadUsage` / `workers[].usage` / `usageSummary` into team-state AND populates `tokenUsage` + `executionStatus[].totalTokens` etc. in the data.json AND re-invokes the renderer so the sibling markdown carries the real numbers. Skipping the flag ships a markdown full of `--` cells.
85
89
 
86
90
  ```bash
@@ -103,7 +107,7 @@ The four steps below MUST execute in this exact order. Reordering them is the re
103
107
  - When the report has **no** `C-*` clarification rows, the html carries no interactive forms (it would only duplicate the MD), so the renderer prints `html: skipped (...)` and writes nothing. This is the expected state for clarification-free runs — `validators/validate-report-views.py` treats "no C-* rows + no html" as a pass, not a missing artifact.
104
108
 
105
109
  Must run AFTER step 1 (so token placeholders are substituted in any rendered html) and BEFORE step 2 (so the html artifact, when generated, exists for the validator step that checks it).
106
- 4. **Phase 7 step 2 — Follow-up task spawner** (BLOCKING when Section 7 is non-empty). Turns the report's `## 7. Follow-up Tasks (후속 작업)` rows into `tasks/<task-group>/<new-task-id>/` stubs.
110
+ 4. **Phase 7 step 2 — Follow-up task spawner** (BLOCKING when Section 4 is non-empty). Turns the report's `## 4. Follow-up Tasks (후속 작업)` rows into `tasks/<task-group>/<new-task-id>/` stubs.
107
111
 
108
112
  ```bash
109
113
  python3 scripts/okstra-spawn-followups.py \
@@ -115,11 +119,11 @@ The four steps below MUST execute in this exact order. Reordering them is the re
115
119
 
116
120
  Behaviour contract:
117
121
  - Idempotent: rows whose target dir exists are reported as `existing` and skipped. Reruns of the same parent task are safe.
118
- - Rows with `autoSpawn != "yes"` are reported as `skipped` and never written; surface them in Section 6 if manual action is still needed.
122
+ - Rows with `autoSpawn != "yes"` are reported as `skipped` and never written; surface them in Section 3 if manual action is still needed.
119
123
  - Rows whose `origin` is `phase-continuation` are reported as `skipped (no new task dir)` and never spawn — they advance the same task-key via `/okstra-run` instead.
120
124
  - An invalid `origin`, `suggestedTaskType`, missing `title`, missing `reason`, or missing `newTaskId` exits `1`. (Schema validation in Phase 6 catches most of these before the spawner runs.)
121
125
  - **Canonical spawn rule (single source of truth):** the spawner runs when `task-type` ∈ {`implementation`, `final-verification`, `release-handoff`}, OR when `followUpTasks` is non-empty for any other task-type. For the listed task-types `followUpTasks` must be present (schema enforces the phase-continuation row for non-terminal task-types); an empty array is permitted only for `release-handoff`. Missing arrays are no-ops (exit `0`). All other references to this rule (including the Persistence Checklist) defer to this statement.
122
- 5. **Phase 7 step 3 — Update Section 6** after the spawner. The report-writer MUST append one row per newly spawned task-key with its entry command:
126
+ 5. **Phase 7 step 3 — Update Section 3** after the spawner. The report-writer MUST append one row per newly spawned task-key with its entry command:
123
127
 
124
128
  ```
125
129
  - Follow-up: `<task-group>/<new-task-id>` — Claude Code 세션 안 `/okstra-run task-key=<task-group>/<new-task-id> task-type=<suggested>` / 별도 터미널 `scripts/okstra.sh --task-key <task-group>/<new-task-id> --task-type <suggested>`
@@ -215,16 +219,16 @@ When the run's `task-type` is `implementation-planning`, the final report MUST c
215
219
  | 5 | `Dependency` | `### Dependency / Migration Risk (의존성·마이그레이션 위험)` |
216
220
  | 6 | `Validation Checklist` | `### Validation Checklist (검증 체크리스트)` |
217
221
  | 7 | `Rollback` | `### Rollback Strategy (롤백 전략)` |
218
- | 8 | `User Approval Request` | Satisfied by the top-of-report `## User Approval Request (사용자 승인 게이트)` block. Do NOT recreate a `### 4.5.8 User Approval Request` body stub — the validator now fails reports that contain one. |
219
- | 9 | `Plan Body Verification` + `Gate result:` | `### Plan Body Verification (계획 본문 검증)` containing a `Gate result:` line — copy `templates/reports/final-report.template.md §4.5.9` verbatim. Validator checks both substrings. |
222
+ | 8 | `User Approval Request` | Satisfied by the top-of-report `## User Approval Request (사용자 승인 게이트)` block. Do NOT recreate a `### 5.5.8 User Approval Request` body stub — the validator now fails reports that contain one. |
223
+ | 9 | `Plan Body Verification` + `Gate result:` | `### Plan Body Verification (계획 본문 검증)` containing a `Gate result:` line — copy `templates/reports/final-report.template.md §5.5.9` verbatim. Validator checks both substrings. |
220
224
 
221
225
  The Korean translation in parentheses is optional but the English keyword is mandatory. The body of each section is written in the Report Language per the writing rules below. For non-`implementation-planning` runs, omit this entire block — these headings are NOT validator-checked for other task-types.
222
226
 
223
- The final-report template `templates/reports/final-report.template.md` Section 4.5 already encodes this contract — copy that block verbatim and fill in.
227
+ The final-report template `templates/reports/final-report.template.md` Section 5.5 already encodes this contract — copy that block verbatim and fill in.
224
228
 
225
229
  ### Final-verification verdict token contract (BLOCKING)
226
230
 
227
- When the run's `task-type` is `final-verification`, the report's `## 2. Final Verdict` table MUST contain a `Verdict Token` row whose value is **exactly one of** the literal strings below. The `release-handoff` profile reads this row as its entry gate; any other value blocks the next phase.
231
+ When the run's `task-type` is `final-verification`, the report's `## 7. Final Verdict` table MUST contain a `Verdict Token` row whose value is **exactly one of** the literal strings below. The `release-handoff` profile reads this row as its entry gate; any other value blocks the next phase.
228
232
 
229
233
  | # | Required substring | Meaning |
230
234
  |---|--------------------|---------|
@@ -234,15 +238,15 @@ When the run's `task-type` is `final-verification`, the report's `## 2. Final Ve
234
238
 
235
239
  For every other task-type, set the `Verdict Token` cell to `not-applicable`. Do NOT omit the row — the template renders it for all task-types and downstream tooling expects the field to exist.
236
240
 
237
- The final-report template `templates/reports/final-report.template.md` Section 2 already encodes this contract — copy that block verbatim and fill in.
241
+ The final-report template `templates/reports/final-report.template.md` Section 7 already encodes this contract — copy that block verbatim and fill in.
238
242
 
239
243
  ### Release-handoff section contract (release-handoff runs only)
240
244
 
241
- When the run's `task-type` is `release-handoff`, the final report MUST include Section `## 4.6 Release Handoff Deliverables` with all eight sub-sections (`4.6.1` Source Verification Report, `4.6.2` Feature Branch & Working-Tree State, `4.6.3` User Selections, `4.6.4` Executed Commands, `4.6.5` Commit List, `4.6.6` Merge Conflict Probe, `4.6.7` Pull Request Outcome, `4.6.8` Routing Recommendation). Every entry is dictated by the lead's recorded git/gh command log and the user's verbatim answers to the H1/H2/H3 menu prompts. H1 choices are `local only`, `push + PR`, or `skip`; release-handoff records existing implementation commits and MUST NOT create new commits. If the user picked `skip` (H1) or `cancel` (H3), keep 4.6.3 populated but leave 4.6.4–4.6.6 explicitly empty per the template's empty-state lines.
245
+ When the run's `task-type` is `release-handoff`, the final report MUST include Section `## 5.6 Release Handoff Deliverables` with all eight sub-sections (`5.6.1` Source Verification Report, `5.6.2` Feature Branch & Working-Tree State, `5.6.3` User Selections, `5.6.4` Executed Commands, `5.6.5` Commit List, `5.6.6` Merge Conflict Probe, `5.6.7` Pull Request Outcome, `5.6.8` Routing Recommendation). Every entry is dictated by the lead's recorded git/gh command log and the user's verbatim answers to the H1/H2/H3 menu prompts. H1 choices are `local only`, `push + PR`, or `skip`; release-handoff records existing implementation commits and MUST NOT create new commits. If the user picked `skip` (H1) or `cancel` (H3), keep 5.6.3 populated but leave 5.6.4–5.6.6 explicitly empty per the template's empty-state lines.
242
246
 
243
247
  **Single-lead authorship (release-handoff only):** release-handoff has no worker roster (no `Report writer worker`, no `Claude worker` drafter). The Claude lead authors the final-report file directly — there is no `Report writer worker` dispatch to perform in Phase 6, no resume-safe dispatch concern, and no mandatory worker-results file for a report-writer role. The rest of this skill's dispatch / resume / fallback machinery applies ONLY when `Report writer worker` is in the roster (i.e. every task-type other than `release-handoff`).
244
248
 
245
- The final-report template `templates/reports/final-report.template.md` Section 4.6 already encodes this contract — copy that block verbatim and fill in. For non-`release-handoff` runs, omit Section 4.6 entirely.
249
+ The final-report template `templates/reports/final-report.template.md` Section 5.6 already encodes this contract — copy that block verbatim and fill in. For non-`release-handoff` runs, omit Section 5.6 entirely.
246
250
 
247
251
  ### Mandatory worker-results file (BLOCKING)
248
252
 
@@ -260,16 +264,16 @@ Skipping this file because "the real report is in `reports/`" is wrong. Both fil
260
264
 
261
265
  ### Main Body Section
262
266
 
263
- Section numbering follows `templates/reports/final-report.template.md` exactly — that file is the documentation SSOT for section names and ordering. For full body structure at authoring time, consult your run's **phase-stripped** `final-report-template.md` (the instruction-set copy of the same template, with other task-types' §4.x deliverable blocks removed); the "copy that block verbatim" references below mean the §-block as it appears in that stripped copy, not a re-read of the full source.
267
+ Section numbering follows `templates/reports/final-report.template.md` exactly — that file is the documentation SSOT for section names and ordering. For full body structure at authoring time, consult your run's **phase-stripped** `final-report-template.md` (the instruction-set copy of the same template, with other task-types' §5.x deliverable blocks removed); the "copy that block verbatim" references below mean the §-block as it appears in that stripped copy, not a re-read of the full source.
264
268
 
265
- **Verdict Card (top-of-report, mandatory).** Render `## Verdict Card` between the report header and the (conditional) Approval block. Its `Verdict Token` / `Direction` / `Next Step` cells MUST byte-match the corresponding cells in `## 2. Final Verdict` and the first item of `## 6.`. Divergence is `contract-violated`.
269
+ **Verdict Card (top-of-report, mandatory).** Render `## Verdict Card` between the report header and the (conditional) Approval block. Its `Verdict Token` / `Direction` / `Next Step` cells MUST byte-match the corresponding cells in `## 7. Final Verdict` and the first item of `## 6.`. Divergence is `contract-violated`.
266
270
 
267
- 0. **Clarification Response Carried In** — render this `## 0.` heading ONLY when `{{CLARIFICATION_RESPONSE_RELATIVE_PATH}}` is non-empty. Walk every `C-*` row of the prior report's `## 5. Clarification Items` table, reconcile against new evidence, and record the outcome (`resolved` / `obsolete`) with citation before drafting the verdict. When no carry-in path was provided, OMIT the `## 0.` heading entirely — the validator fails an empty Section 0 stub.
271
+ 0. **Clarification Response Carried In** — render this `## 0.` heading ONLY when `{{CLARIFICATION_RESPONSE_RELATIVE_PATH}}` is non-empty. Walk every `C-*` row of the prior report's `## 1. Clarification Items` table, reconcile against new evidence, and record the outcome (`resolved` / `obsolete`) with citation before drafting the verdict. When no carry-in path was provided, OMIT the `## 0.` heading entirely — the validator fails an empty Section 0 stub.
268
272
  1. **Cross Verification Results** — 4 categories (Full / Partial / Contested / Worker-Unique) when convergence is enabled, per `okstra-convergence`. Prepend the Round History sub-table (columns: `Round | inputQueueSize | resolvedCount | carriedForwardCount | dispatches | skippedWorkers`) plus a `round2SkippedReason: <value>` note, pulled verbatim from `convergence-<task-type>-<seq>.json`. Empty contested list renders as `- 합의 미달 항목 없음.`. Convergence-disabled runs use the legacy Consensus/Differences format and omit the round table.
269
273
  2. **Final Verdict** — `Direction` ∈ `continue-investigation` / `begin-implementation` / `approve` / `reject` / `hold`. **Verdict Token** is `not-applicable` for every task-type except `final-verification` — see "Final-verification verdict token contract" below for that case.
270
274
  3. **Evidence and Detailed Analysis** — primary evidence rows (file path, line, snippet); secondary evidence / alternate interpretations. If `reference-expectations.md` lists explicit expected values, record match/gap per row.
271
- 4. **Missing Information and Risks** — uncertain / "I don't know" items. `implementation-planning` adds §4.5 (see heading contract below); `release-handoff` adds §4.6.
272
- 5. **Clarification Items** — single unified `C-*` table; column schema, ID convention, and rerun behaviour are owned by `_common-contract.md §Clarification request policy` (8-column SSOT). The deprecated `4.5.9 Open Questions` / `5.1 추가 자료 요청` / `5.2 사용자 확인 질문` sub-sections are removed; the validator fails reports that reintroduce them.
275
+ 4. **Missing Information and Risks** — uncertain / "I don't know" items. `implementation-planning` adds §5.5 (see heading contract below); `release-handoff` adds §5.6.
276
+ 5. **Clarification Items** — single unified `C-*` table; column schema, ID convention, and rerun behaviour are owned by `_common-contract.md §Clarification request policy` (8-column SSOT). The deprecated `5.5.9 Open Questions` / `1.1 추가 자료 요청` / `1.2 사용자 확인 질문` sub-sections are removed; the validator fails reports that reintroduce them.
273
277
  6. **Recommended Next Steps** — prioritized actions. After Phase 7's follow-up spawner runs, append a row per newly created task-key (see "Phase 6 → Phase 7 execution sequence" above).
274
278
  7. **Follow-up Tasks** — auto-spawn-eligible table. Each row drives `okstra-spawn-followups.py`; see template §7 for the row schema.
275
279
 
@@ -281,8 +285,8 @@ Section numbering follows `templates/reports/final-report.template.md` exactly
281
285
  empty-states, token summary, column headers, release-handoff labels)
282
286
  are i18n-rendered by `okstra-render-final-report.py` from
283
287
  `templates/reports/i18n/<lang>.json`; do not translate those — focus
284
- on the prose you author (Section 1 categories, Section 3 evidence
285
- narratives, Section 4 risks, Section 6 recommendations, etc.).
288
+ on the prose you author (Section 6 categories, Section 2 evidence
289
+ narratives, Section 5 risks, Section 3 recommendations, etc.).
286
290
  Code identifiers, file paths, model names, status tokens, and the
287
291
  validator-checked English substrings (`Option Candidates`,
288
292
  `Verdict Token`, `accepted`/`conditional-accept`/`blocked`, etc.)
@@ -296,7 +300,7 @@ Section numbering follows `templates/reports/final-report.template.md` exactly
296
300
  - Write the actual analysis text instead of a meta-description
297
301
  - Do not make unfounded assertions
298
302
  - Include findings from all four categories. Do not omit "contested" or "worker-unique" findings
299
- - Include the convergence round history sub-table (Section 1) so the reader can audit which rounds executed and what `round2SkippedReason` indicates (e.g. `"not-skipped"` when Round 2 ran, or one of the three skip reasons). Pull values verbatim from `convergence-<task-type>-<seq>.json`; do NOT recompute.
303
+ - Include the convergence round history sub-table (Section 6) so the reader can audit which rounds executed and what `round2SkippedReason` indicates (e.g. `"not-skipped"` when Round 2 ran, or one of the three skip reasons). Pull values verbatim from `convergence-<task-type>-<seq>.json`; do NOT recompute.
300
304
  - For each finding, include a brief summary of votes per worker across executed rounds. `verification-error` votes are listed as such — never as `DISAGREE`.
301
305
  - The report writer worker does not participate in the re-verification vote. It is responsible only for drafting the final report
302
306
 
@@ -42,6 +42,7 @@ The wizard tells you *which UI to use* via `kind` (and the optional `multi` flag
42
42
 
43
43
  - `kind: "pick"` + `multi: false` (default) → render `AskUserQuestion` with `label`, `options[].label`, and `multiSelect: false`. Use the chosen `options[].value` (single string) as the answer.
44
44
  - `kind: "pick"` + `multi: true` → render `AskUserQuestion` with `label`, `options[].label`, and `multiSelect: true`. Join the chosen `options[].value` entries with `,` into a single CSV string and submit that as `--answer "csv,values"`. If the user selects nothing, still submit `--answer ""` — the wizard will reply `ok: false` and re-prompt the same step (do not skip the call).
45
+ - `kind: "pick_group"` → render a SINGLE `AskUserQuestion` whose questions array maps 1:1 to the wizard's `questions[]`. For each entry use `questions[].label`, `questions[].options[].label`, and `multiSelect: questions[].multi`. Collect the user's chosen `options[].value` per tab, build a JSON object keyed by each `questions[].step`, and submit it as a single literal `--answer '{"lead_model":"opus","claude_model":"default",...}'`. A tab the user leaves at its default still gets its `"default"`/`""` value in the JSON. Never split a `pick_group` into multiple `AskUserQuestion` calls — the wizard already capped it at 4 tabs and emits any remainder as the next prompt.
45
46
  - `kind: "text"` → write `label` as a plain text message and consume the user's NEXT message as the answer.
46
47
  - `kind: "done"` → input collection finished; move to Step 5.
47
48
 
@@ -96,6 +97,7 @@ Repeat until `next.kind == "done"`:
96
97
  1. **Render** the prompt according to `kind` (and `multi` for pick):
97
98
  - `pick` + `multi: false` → `AskUserQuestion` with `multiSelect: false`, `label`, and `options`. The user's chosen option's `value` is the answer string.
98
99
  - `pick` + `multi: true` → `AskUserQuestion` with `multiSelect: true`, `label`, and `options`. Join the selected `value`s with `,` into a single literal CSV string (e.g. `"claude,codex,gemini"`) and submit it as a single `--answer "claude,codex,gemini"`. Empty selection submits `--answer ""` and the wizard re-prompts.
100
+ - `pick_group` → one `AskUserQuestion` with one question per `questions[]` entry (tab). Map each tab's selected `value` back by `questions[].step`, assemble a JSON object, and submit it as a single literal `--answer '<json>'`.
99
101
  - `text` → plain text message containing `label`. Consume the user's next reply verbatim as the answer string (empty reply = empty string).
100
102
  2. **Submit** the answer — call `okstra wizard step` with the literal state-file path from Step 2 and the literal user answer (no shell variables, no `$(...)`):
101
103
  ```bash
@@ -184,7 +186,7 @@ You can delete the literal state-file path after this point — its job is done.
184
186
 
185
187
  ## Step 6: Take over as Claude lead
186
188
 
187
- Read `<INSTRUCTION_SET_PATH>/claude-execution-prompt.md` verbatim and enter `Claude lead` mode. The lead prompt itself enumerates every other instruction-set file to load (`analysis-profile.md`, `analysis-material.md`, `reference-expectations.md`, `final-report-template.md`, the run manifest, the team-state artifact, etc.) — follow its order, do not preempt it.
189
+ Read `<INSTRUCTION_SET_PATH>/claude-execution-prompt.md` verbatim and enter `Claude lead` mode. The lead prompt now points to compact intake artifacts first (`active-run-context`, `analysis-profile.md`, and `analysis-packet.md`); full source files such as `analysis-material.md`, `reference-expectations.md`, and `final-report-template.md` are lazy/fallback inputs. Follow the rendered prompt order, do not preempt it.
188
190
 
189
191
  Then proceed through the phases exactly as the lead prompt directs (Phase 1 context → Phase 2+ worker dispatch → final synthesis → final report).
190
192
 
@@ -37,6 +37,9 @@ okstra tasks are always operated using the `Claude lead` + required worker team
37
37
 
38
38
  1. `resultContract.requiredWorkerRoles` in `task-manifest.json` (and the lead model metadata) is the canonical source. There is no role-level fallback — a missing assignment is a manifest defect, not a license to invent one.
39
39
  2. If `modelExecutionValue` differs from `model`, use `modelExecutionValue` during execution.
40
+ 3. **Spawn-time enforcement for in-process Claude subagents (BLOCKING).** `Claude worker` and `Report writer worker` are in-process Claude subagents whose agent definitions declare `model: inherit` (`agents/workers/claude-worker.md`, `agents/workers/report-writer-worker.md`). `inherit` follows the **lead's** runtime model, NOT the role's assignment — so an opus assignment silently runs on a sonnet lead. To make the assignment binding (not merely declared), lead MUST pass an explicit `model:` parameter on every `Agent(...)` dispatch for these two roles, derived from that role's `modelExecutionValue`. The dispatch `model:` parameter overrides the `inherit` frontmatter; the frontmatter remains only as the fallback when no parameter is supplied. Omitting `model:` on a Claude-side dispatch is a contract violation that reproduces the assigned-vs-actual model deviation.
41
+ 4. **`modelExecutionValue` → Agent `model:` family token.** The Agent tool's `model` parameter accepts family tokens only — `opus` / `sonnet` / `haiku` (an exact version such as `claude-opus-4-7` is NOT a valid value). Map by prefix: a `modelExecutionValue` of `opus*` / `claude-opus*` → `"opus"`, `sonnet*` / `claude-sonnet*` → `"sonnet"`, `haiku*` / `claude-haiku*` → `"haiku"`. This enforces the assignment at **family granularity** (opus vs sonnet vs haiku); the exact version within a family is still inherited from the lead session and cannot be pinned via this parameter.
42
+ 5. **Codex / Gemini wrappers are out of scope for the Agent `model:` rule.** `Codex worker` / `Gemini worker` subagents are Claude wrappers that shell out to an external CLI; the role's `modelExecutionValue` is already applied via the CLI's own `--model <modelExecutionValue>` argument (see `agents/workers/_cli-wrapper-template.md`). The Agent `model:` parameter for these wrappers would only set the wrapper's own orchestration model, not the external CLI's model — leave it at `inherit` and do NOT map it from `modelExecutionValue`.
40
43
 
41
44
  ### Dynamic Worker Role Determination
42
45
 
@@ -91,7 +94,7 @@ Send byte-identical dispatch prompts to every analysis worker (Claude / Codex /
91
94
  The lead does NOT inline `[Required reading]` or `[Error reporting]` blocks into worker prompts. Both contracts live in a single canonical file at `~/.okstra/templates/worker-prompt-preamble.md` (source: `templates/worker-prompt-preamble.md`). The lead injects the path via the `**Worker Preamble Path:**` anchor header (header #5 above) and each worker Reads that file end-to-end before producing output.
92
95
 
93
96
  What the lead MUST still do per dispatch:
94
- - Inject the input file enumeration into the dispatch prompt body via an `## Inputs` section (or any heading the recipient agent expects), listing the actual project-relative paths derived from the run's `instruction-set/` and the carry-in clarification response if any. The preamble describes the rules; the lead provides the specific paths for THIS run.
97
+ - Inject the input file enumeration into the dispatch prompt body via an `## Inputs` section (or any heading the recipient agent expects), listing the actual project-relative primary inputs derived from the run's `instruction-set/`. For analysis workers, list `analysis-packet.md` as the required primary input and list task-brief / analysis-profile / analysis-material / reference-expectations / clarification-response as source/fallback paths only when useful. The preamble describes the rules; the lead provides the specific paths for THIS run.
95
98
  - Inject the absolute `**Errors log path:**` and `**Errors sidecar path:**` headers (#6 and #7 above) — workers cannot synthesize these paths.
96
99
  - Omit the preamble pointer for reverify dispatches (Phase 5.5 lightweight mode) — see [okstra-convergence](../okstra-convergence/SKILL.md) "Reverify prompt: required-reading suppression".
97
100
 
@@ -99,8 +102,8 @@ Audience-scoped file enumeration (BLOCKING — performance optimization):
99
102
 
100
103
  | Recipient | Files the lead lists under `## Inputs` |
101
104
  |---|---|
102
- | Claude / Codex / Gemini analysis workers | task-brief, analysis-profile, analysis-material (if present), reference-expectations, clarification-response (if carry-in) |
103
- | Report writer worker (Phase 6) | all of the above **plus** the instruction-set-local `final-report-template.md` (phase-stripped) and `final-report-schema.json` (per-task-type excerpt) — NOT the full `templates/reports/...` / `schemas/...` sources |
105
+ | Claude / Codex / Gemini analysis workers | `analysis-packet.md` as primary input; source/fallback paths may be listed below it but are not automatic first-read files |
106
+ | Report writer worker (Phase 6) | task-brief, analysis-profile, analysis-material, reference-expectations, clarification-response (if carry-in), **plus** the instruction-set-local `final-report-template.md` (phase-stripped) and `final-report-schema.json` (per-task-type excerpt) — NOT the full `templates/reports/...` / `schemas/...` sources |
104
107
  | Reverify dispatches | none — the lead provides only the items to reverify |
105
108
 
106
109
  Asymmetry note: `claude-worker` runs in-process and the Agent SDK auto-loads its agent definition; lead's dispatch prompt body for claude-worker can therefore be shorter than for codex/gemini. The Worker Preamble pointer is still emitted for all three so the contract source is identical regardless of dispatch path.
@@ -147,7 +150,7 @@ After each worker subagent returns (regardless of role), Lead MUST verify the ca
147
150
 
148
151
  ### Result Frontmatter (mandatory, precedes Section 1)
149
152
 
150
- Every worker result file MUST begin with a YAML frontmatter block. The values are sourced from the corresponding fields of the input files' frontmatter (e.g. `analysis-material.md`, `task-brief.md`) copy them verbatim; do NOT regenerate them. Only `workerId` and `title` are worker-specific.
153
+ Every worker result file MUST begin with a YAML frontmatter block. For analysis workers, values are sourced from `analysis-packet.md` frontmatter; fall back to `analysis-material.md` or `task-brief.md` only if the packet is missing a field. Report-writer can use `analysis-material.md` / `task-brief.md` as before. Copy values verbatim; do NOT regenerate them. Only `workerId` and `title` are worker-specific.
151
154
 
152
155
  ```yaml
153
156
  ---
@@ -213,7 +216,7 @@ Every item in sections 1–5 MUST be tagged with the ticket(s) it relates to. Th
213
216
 
214
217
  - **Table-form items**: include a `Ticket ID` column. The column is placed immediately after the row-ID column (e.g. after `F-001`, `M-001`).
215
218
  - **Bullet / numbered-list items**: prepend `[TICKETID: <id>]` to the item title, immediately after the row ID and before the body text. Example: `- F-001 [TICKETID: TICKET-123] — <summary> (path:line)`.
216
- - **Section headers in the final report** (e.g. `### 4.5.3 Recommended Option`): append `[TICKETID: <id>]` to the header when the section is scoped to a specific ticket. Headers that span all tickets in the run omit the tag.
219
+ - **Section headers in the final report** (e.g. `### 5.5.3 Recommended Option`): append `[TICKETID: <id>]` to the header when the section is scoped to a specific ticket. Headers that span all tickets in the run omit the tag.
217
220
 
218
221
  Ticket ID fill rule (in order):
219
222