okstra 0.24.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/claude-worker.md +1 -1
- package/runtime/agents/workers/codex-worker.md +1 -1
- package/runtime/agents/workers/gemini-worker.md +1 -1
- package/runtime/agents/workers/report-writer-worker.md +1 -1
- package/runtime/prompts/launch.template.md +1 -1
- package/runtime/prompts/profiles/_common-contract.md +8 -5
- package/runtime/prompts/profiles/error-analysis.md +1 -1
- package/runtime/prompts/profiles/final-verification.md +1 -1
- package/runtime/prompts/profiles/implementation-planning.md +3 -3
- package/runtime/prompts/profiles/implementation.md +1 -1
- package/runtime/prompts/profiles/requirements-discovery.md +1 -1
- package/runtime/python/okstra_ctl/clarification_items.py +190 -0
- package/runtime/python/okstra_ctl/run.py +18 -1
- package/runtime/python/okstra_ctl/workflow.py +1 -1
- package/runtime/skills/okstra-report-writer/SKILL.md +2 -2
- package/runtime/skills/okstra-team-contract/SKILL.md +9 -7
- package/runtime/templates/reports/final-report.template.md +49 -49
package/package.json
CHANGED
package/runtime/BUILD.json
CHANGED
|
@@ -57,7 +57,7 @@ Unlike the Codex / Gemini workers, you are an in-process Claude subagent — you
|
|
|
57
57
|
Before producing any output, you MUST read every input file enumerated in the `[Required reading]` block of the lead's prompt from the very first character to the very last character. This includes the task brief, analysis profile, analysis material (if present), reference expectations, the carry-in clarification response (if present), and the final report template.
|
|
58
58
|
|
|
59
59
|
- Use a single `Read` call per file with no `offset` and no `limit`. If a file is genuinely too large for one read, page through it with explicit `offset` / `limit` calls that together cover the entire file, and record the page boundaries in your Findings.
|
|
60
|
-
- For the carry-in clarification response, walk every row of
|
|
60
|
+
- For the carry-in clarification response, walk every row of `## 5. 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, not skip. Skimming these rows is the most common failure mode here; the fact that the file you will eventually contribute to has a structurally similar section 5 is NOT a license to skim. If the prior report uses the deprecated `4.5.9 Open Questions` / `5.1` / `5.2` layout with `OQ-*` / `A*` / `Q*` IDs, walk all three blocks the same way (legacy carry-in transitional rule).
|
|
61
61
|
- Before listing any Findings, state one sentence per input file confirming you read it end-to-end (e.g. "Read task-brief.md end-to-end (147 lines)."). If you cannot truthfully say this for a file, record a `tool-failure` in the errors sidecar instead of fabricating Findings.
|
|
62
62
|
- Do not skip a file because its name suggests its content is already familiar from a prior run. Each file is canonical for the current run only.
|
|
63
63
|
|
|
@@ -125,7 +125,7 @@ This wrapper does NOT invoke MCP tools directly. MCP availability inside the Cod
|
|
|
125
125
|
Before producing any output, you MUST ensure the underlying Codex CLI run reads every input file enumerated in the `[Required reading]` block of the lead's prompt from the very first character to the very last character. This includes the task brief, analysis profile, analysis material (if present), reference expectations, the carry-in clarification response (if present), and the final report template.
|
|
126
126
|
|
|
127
127
|
- The lead's prompt body, which you persist verbatim and feed into Codex via stdin, already contains the explicit list of files and the end-to-end reading rule. Do not strip or summarize that block before passing it to the CLI.
|
|
128
|
-
- For the carry-in clarification response, the CLI must walk every row of
|
|
128
|
+
- For the carry-in clarification response, the CLI must walk every row of `## 5. 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 fact that the prior run's final report and the upcoming output share section 5 structure is NOT a license to skim. If the prior report uses the deprecated `4.5.9 Open Questions` / `5.1` / `5.2` layout with `OQ-*` / `A*` / `Q*` IDs, walk all three blocks the same way (legacy carry-in transitional rule).
|
|
129
129
|
- The Codex output you return MUST begin with one sentence per input file confirming end-to-end reading (e.g. "Read task-brief.md end-to-end (147 lines)."). If any file was skipped, record a `tool-failure` in the errors sidecar instead of fabricating Findings.
|
|
130
130
|
|
|
131
131
|
## Worker Output Structure
|
|
@@ -125,7 +125,7 @@ This wrapper does NOT invoke MCP tools directly. MCP availability inside the Gem
|
|
|
125
125
|
Before producing any output, you MUST ensure the underlying Gemini CLI run reads every input file enumerated in the `[Required reading]` block of the lead's prompt from the very first character to the very last character. This includes the task brief, analysis profile, analysis material (if present), reference expectations, the carry-in clarification response (if present), and the final report template.
|
|
126
126
|
|
|
127
127
|
- The lead's prompt body, which you persist verbatim and feed into Gemini via stdin, already contains the explicit list of files and the end-to-end reading rule. Do not strip or summarize that block before passing it to the CLI.
|
|
128
|
-
- For the carry-in clarification response, the CLI must walk every row of
|
|
128
|
+
- For the carry-in clarification response, the CLI must walk every row of `## 5. 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 the most common reason this step gets skipped — do not repeat that. If the prior report uses the deprecated `4.5.9 Open Questions` / `5.1` / `5.2` layout with `OQ-*` / `A*` / `Q*` IDs, walk all three blocks the same way (legacy carry-in transitional rule).
|
|
129
129
|
- The Gemini output you return MUST begin with one sentence per input file confirming end-to-end reading (e.g. "Read task-brief.md end-to-end (147 lines)."). If any file was skipped, record a `tool-failure` in the errors sidecar instead of fabricating Findings.
|
|
130
130
|
|
|
131
131
|
## Worker Output Structure
|
|
@@ -46,7 +46,7 @@ If you find yourself thinking "I'll just return the report inline and let lead s
|
|
|
46
46
|
Before writing the final report, you MUST read every input file enumerated in the `[Required reading]` block of the lead's prompt from the very first character to the very last character. This always includes `final-report-template.md` and every analysis worker's result file under `worker-results/`, plus the convergence output under `state/convergence-<task-type>-<seq>.json` (if present).
|
|
47
47
|
|
|
48
48
|
- Use a single `Read` call per file with no `offset` and no `limit`. If a file is too large for one read, page through it with explicit `offset` / `limit` calls covering the full file.
|
|
49
|
-
- For the carry-in `clarification-response.md` (if present), walk every row of
|
|
49
|
+
- For the carry-in `clarification-response.md` (if present), walk every row of `## 5. Clarification Items` (`C-001`, `C-002`, ...) including rows whose `User input` cell is blank — a blank cell with `Status=open` is itself a signal you must surface in section 0. The fact that the file you write has a structurally similar section 5 is NOT an excuse to skim. If the prior report uses the deprecated `4.5.9 Open Questions` / `5.1` / `5.2` layout with `OQ-*` / `A*` / `Q*` IDs, walk all three blocks the same way (legacy carry-in transitional rule).
|
|
50
50
|
- Open every analysis-worker result file under `worker-results/` end-to-end. Do not summarize them from convergence output alone — convergence captures classifications, not full evidence.
|
|
51
51
|
- Before writing, state one sentence per input file confirming end-to-end reading. If you cannot truthfully say this for a file, record a `tool-failure` in the errors sidecar instead of fabricating the report.
|
|
52
52
|
- When the convergence-state file is present, read it fully and reproduce the `roundHistory[]` array, `round2SkippedReason`, and `finalClassificationCounts` in the final report's Section 1 Round History sub-table. Do not derive these values from worker results alone — they live in `state/convergence-<task-type>-<seq>.json`.
|
|
@@ -85,4 +85,4 @@ Invoke the `okstra` skill now. Read the manifests below for all task metadata, p
|
|
|
85
85
|
|
|
86
86
|
- Source path: `{{CLARIFICATION_RESPONSE_RELATIVE_PATH}}`
|
|
87
87
|
- If the source path above is empty, no prior clarification response was attached to this run.
|
|
88
|
-
- If the source path is set, a copy is staged at `{{INSTRUCTION_SET_RELATIVE_PATH}}/clarification-response.md`. Read it before running workers; reconcile each `
|
|
88
|
+
- If the source path is set, a copy is staged at `{{INSTRUCTION_SET_RELATIVE_PATH}}/clarification-response.md`. Read it before running workers; reconcile each `C-*` row in section 5 (`## 5. Clarification Items`) of the prior report against new evidence and record the outcome in section 0 of this run's final report. If the prior report uses the deprecated `4.5.9 Open Questions` / `5.1` / `5.2` layout with `OQ-*` / `A*` / `Q*` IDs, follow the legacy-carry-in mapping rule in `final-report-template.md` section 0.
|
|
@@ -15,7 +15,7 @@ profile document.
|
|
|
15
15
|
- the read-only MCP servers declared in the task brief's `## Available MCP Servers` section may be queried as a read-only cross-check; that section is the canonical source of which servers and tools exist for this run, and any MCP-derived finding MUST cite server, table, and the SELECT used. MCP MUST NEVER be used as a write path — schema/data mutations go through repository migration files reviewed by humans.
|
|
16
16
|
- Authority & permissions assumption (HARD RULE — applies to every okstra task-type):
|
|
17
17
|
- **Assume the user (and their team) holds full authority and every permission required for the anticipated, in-flight, or follow-up work.** Treat external approvals, third-party access grants, role/IAM permissions, organisational sign-off, legal/compliance review, vendor coordination, and "verify access exists" steps as already satisfied unless the task brief explicitly states otherwise.
|
|
18
|
-
- Do NOT add such items to routing decisions, missing-materials lists, clarification questions, option trade-offs, dependency/migration risk, validation checklists, rollout plans, acceptance blockers, residual risks, release recommendations, `
|
|
18
|
+
- Do NOT add such items to routing decisions, missing-materials lists, clarification questions, option trade-offs, dependency/migration risk, validation checklists, rollout plans, acceptance blockers, residual risks, release recommendations, the `## 5. Clarification Items` table, or any day/effort estimate. They are not legitimate sources of schedule extension.
|
|
19
19
|
- Internal okstra phase handoffs (e.g. the `User Approval Request` block in `implementation-planning`) are unaffected — those are the user themselves approving and proceed without external coordination.
|
|
20
20
|
- This rule does NOT relax any phase-specific Forbidden actions list; safety rules in the per-profile document remain in force regardless of the user's authority.
|
|
21
21
|
- Anti-escalation rule (shared):
|
|
@@ -32,8 +32,11 @@ profile document.
|
|
|
32
32
|
- On `아니오` / `n` / `keep` → leave the panes intact; remind the user that they will be cleaned up automatically when Claude `/exit` fires the `SessionEnd` hook.
|
|
33
33
|
- The question MUST be a clean yes/no — do NOT offer "close some / keep some" partial answers, do NOT propose alternatives like "close only codex panes". The whole-set decision keeps the wrap-up predictable.
|
|
34
34
|
- This step is mandatory for every phase (`requirements-discovery`, `error-analysis`, `implementation-planning`, `implementation`, `final-verification`, `release-handoff`). It is silent-skipped when `$TMUX_PANE` is unset (lead running outside tmux); the lead MUST NOT fabricate a synthetic pane list in that case.
|
|
35
|
-
- Clarification request policy (shared — applies whenever a profile uses `## 5. Clarification
|
|
36
|
-
- section 5
|
|
37
|
-
-
|
|
35
|
+
- Clarification request policy (shared — applies whenever a profile uses `## 5. Clarification Items`):
|
|
36
|
+
- section 5 is a **single unified table** per `final-report-template.md`. Every clarification item — whether the user must attach a file, choose between options, or supply a single number/path — is one row of that table. Do not split it into sub-sections, do not create a parallel table elsewhere in the report, and do not duplicate the same item into `## 4.5.8 User Approval Request` or any other section.
|
|
37
|
+
- each row's `Kind` column picks one of `{material, decision, data-point}`: `material` for files / snapshots / logs / screenshots the user must attach (the `User input` cell will hold a path or URL); `decision` for choices and yes/no confirmations only the user can make; `data-point` for a single number, ID, date, or short string the user can answer inline. Items that mix "yes/no + file path if yes" are one row of `Kind=material` with the combined expectation written into `Expected form`.
|
|
38
|
+
- each row's `Blocks` column picks one of `{approval, next-phase, none}`. `approval` is reserved for items that gate the `implementation-planning` User Approval Request — never use `approval` outside that task-type. `next-phase` blocks the next run from starting cleanly. `none` is informational/audit-only.
|
|
39
|
+
- write every entry in full, descriptive sentences that a non-developer can act on without further context. Avoid abbreviations and internal jargon. The `Statement` cell must state *what* is needed, *why* the answer / attachment changes the next step, and (for `material`) *where* the user can find it and *where* to place it. The `Expected form` cell must state the shape of the answer (예/아니오, 보기 중 하나, 숫자/날짜, 파일 경로, 짧은 서술 등); supply concrete option choices when applicable.
|
|
38
40
|
- the same `final-report.md` file is the canonical artifact carried into the next run; the user appends answers inline before rerunning. The preferred turn-around is `scripts/okstra.sh --resume-clarification --task-key <project-id>:<task-group>:<task-id>` (opens the latest report in `$EDITOR`, then auto-reruns the same phase with `--clarification-response` carry-in). The lower-level form `--clarification-response <path>` remains available for scripted runs.
|
|
39
|
-
- if a clarification response was carried in for this run,
|
|
41
|
+
- if a clarification response was carried in for this run, walk every `C-*` row of the prior report's `## 5. Clarification Items` table in section 0 of this report, reconcile each one against new evidence, and update its `Status` to `resolved` or `obsolete` before issuing the next decision/verdict.
|
|
42
|
+
- transitional rule for legacy carry-in (one release cycle): if the prior report uses the deprecated `4.5.9 Open Questions` / `5.1 Additional Materials` / `5.2 Questions for the User` layout, follow the mapping described in section 0 of `final-report-template.md` — collapse `OQ-*` / `A*` / `Q*` into `C-*` rows in this run's new section 5 (legacy ID preserved in the Statement for traceability).
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
- uncertainty boundaries
|
|
21
21
|
- practical next diagnostic steps
|
|
22
22
|
- Clarification request policy (phase-specific addenda — shared policy is in `_common-contract.md`):
|
|
23
|
-
- if any blocking uncertainty remains at the time of writing the final report, populate `## 5. Clarification
|
|
23
|
+
- if any blocking uncertainty remains at the time of writing the final report, populate `## 5. Clarification Items` in `final-report-template.md` (a single unified table; `Blocks=next-phase` for items the next run cannot start without)
|
|
24
24
|
- prefer plain Korean over abbreviations (e.g. write "초당 평균 요청 수" instead of "QPS", "재현 절차" instead of "repro")
|
|
25
25
|
- Non-goals:
|
|
26
26
|
- implementation details unless they are necessary to validate the cause
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
- **Two-tier command lookup (shared with `implementation`):** when this phase performs its own independent re-validation, the command source is exactly the same two tiers `implementation` verifiers use — Tier 1 is the originating task brief / approved plan's `validation` set, Tier 2 is `<PROJECT_ROOT>/.project-docs/okstra/project.json` under `qaCommands`. Auto-detecting tools from manifest files is forbidden; missing tiers are recorded as `qa-command not configured: <category>` and do NOT trigger a guess. The `cmd` deny-list (`--fix`, `--write`, ` -w`, ` -u`, `--snapshot-update`, `INSTA_UPDATE=<not-no>`, `cargo update`, `npm install` without `ci`, etc.) is enforced identically. NOTE: runtime fail-fast validation (`okstra_ctl.qa_commands.validate_qa_commands`) only fires at `--task-type implementation` run-prep, so this phase MUST self-check each `qaCommands` entry against the deny-list before executing it — if a denied token is present, skip the command and record it as a `Read-only command log` line `qa-command rejected (denied token: <token>): <label>`.
|
|
35
35
|
- **Routing recommendation**: brief note on the next safe phase (`done`, `error-analysis`, `implementation-planning`) tied to the verdict and blocker list.
|
|
36
36
|
- Clarification request policy (phase-specific addendum — shared policy is in `_common-contract.md`):
|
|
37
|
-
- populate
|
|
37
|
+
- populate `## 5. Clarification Items` only when a blocker hinges on information only the user can supply (deployment intent, intended target environment, business-rule interpretation); use `Blocks=next-phase` for items that gate continuing to release-handoff
|
|
38
38
|
- Self-review pass before finalising the report (`Claude lead` runs this; do not delegate to a generic subagent):
|
|
39
39
|
1. **Verdict precision** — section 2 includes `Verdict Token` with one of the three allowed verdict tokens; `conditional-accept` lists every condition as an actionable item.
|
|
40
40
|
2. **Blocker traceability** — every blocker cites a concrete artifact (file:line, log excerpt, test exit code, MCP SELECT). Blockers without evidence are demoted to residual risk or removed.
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
- read the task brief, related-task briefs, and any cited spec / design doc end-to-end
|
|
13
13
|
- inspect the current state of every file the task names (or the closest matching files if names are stale) — record current responsibilities, public interfaces, and known coupling points
|
|
14
14
|
- skim recent commits touching those files (`git log -- <path>`) to surface in-flight work or contested areas
|
|
15
|
-
- flag any requirement that is ambiguous, contradictory, or missing success criteria —
|
|
15
|
+
- flag any requirement that is ambiguous, contradictory, or missing success criteria — register each one as a row in the report's `## 5. Clarification Items` table with `Blocks=approval` instead of guessing
|
|
16
16
|
- Primary focus areas:
|
|
17
17
|
- requirement gaps
|
|
18
18
|
- affected components and boundaries
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
- validation checklist (pre / mid / post) — each item is an exact command or observable outcome
|
|
58
58
|
- rollback strategy — exact revert path (commits, flags, migrations) and the signal that triggers rollback
|
|
59
59
|
- explicit `User Approval Request (사용자 승인 게이트)` block placed at the **top of the report** with a single canonical checkbox marker `- [ ] Approved` (user toggles to `- [x] Approved` to authorise the next `implementation` run). Section `4.5.8` is retained only as a back-pointer to this top block for validator/key-substring compatibility — it must NOT carry an independent marker.
|
|
60
|
-
-
|
|
60
|
+
- every ambiguity flagged during pre-planning that the user must resolve before approval registered as a `Blocks=approval` row in the `## 5. Clarification Items` table (do NOT create a separate `Open Questions` block under `4.5.x` — the unified table is the single home)
|
|
61
61
|
- No-placeholder rule (plan failures — reject any option or step that contains these):
|
|
62
62
|
- "TBD", "TODO", "implement later", "fill in details", "add appropriate error handling", "handle edge cases", "write tests for the above" without actual test code
|
|
63
63
|
- "similar to Option/Task N" without repeating the concrete content (readers may consume sections out of order)
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
1. **Spec coverage** — for every requirement in the task brief, point to the option(s) and step(s) that satisfy it. List gaps explicitly.
|
|
68
68
|
2. **Placeholder scan** — search the report for the patterns in the No-placeholder rule above and fix inline.
|
|
69
69
|
3. **Internal consistency** — option file lists, trade-off matrix, and recommended step list must agree on file paths, names, and signatures. A symbol called `clearLayers()` in the matrix and `clearFullLayers()` in the steps is a bug.
|
|
70
|
-
4. **Ambiguity check** — any requirement that could be read two ways must be made explicit or moved to `
|
|
70
|
+
4. **Ambiguity check** — any requirement that could be read two ways must be made explicit or moved to the `## 5. Clarification Items` table as a `Blocks=approval` row.
|
|
71
71
|
5. **Scope check** — if the recommended plan now spans multiple independent subsystems, recommend splitting into separate planning runs rather than shipping an oversized plan.
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
- **Feature-flag-gated changes**: confirm the off-switch path was exercised in this run's validation evidence (i.e. one of the validation commands ran with the flag off and succeeded). A plan that ships a flag without exercising the off-path does NOT satisfy this requirement.
|
|
129
129
|
- **Schema migrations, config-format changes, or any change with persisted state**: a **dry-run of the rollback step is mandatory**, not preferred. Record the exact rollback command and its captured exit code / stdout. If the migration tool offers no dry-run mode (`--dry-run`, `--plan`, equivalent), the executor MUST refuse to claim rollback verification and instead end the run with a routing recommendation back to `implementation-planning` for a safer rollback strategy. Skipping this step on a stateful change is treated as a `contract-violated` outcome by `final-verification`.
|
|
130
130
|
- **Routing recommendation for `final-verification`**: brief note on whether the changes are ready for final-verification phase or need a new error-analysis / planning loop first.
|
|
131
|
-
- **Follow-up tasks (Section 7 of the final report)**: every item discovered during this run that was *not* delivered MUST appear in the final report's `## 7. Follow-up Tasks (후속 작업)` table with a concrete `Origin`, `New Task ID`, `Suggested task-type`, `Scope`, and `Reason / Why deferred`. Sources include: out-of-scope discoveries that the executor consciously chose not to fold into this run, verifier concerns the executor declined to fix in-place, scope-boundary items from the approved plan that turned out to need their own ticket, and any
|
|
131
|
+
- **Follow-up tasks (Section 7 of the final report)**: every item discovered during this run that was *not* delivered MUST appear in the final report's `## 7. Follow-up Tasks (후속 작업)` table with a concrete `Origin`, `New Task ID`, `Suggested task-type`, `Scope`, and `Reason / Why deferred`. Sources include: out-of-scope discoveries that the executor consciously chose not to fold into this run, verifier concerns the executor declined to fix in-place, scope-boundary items from the approved plan that turned out to need their own ticket, and any unresolved `## 5. Clarification Items` row carried over from the approved plan (`Status` ∈ `{open, answered}` at approval time). An empty section is acceptable but only when expressed as the single line `- 후속 작업 없음.` — silence is treated as a contract violation. Rows with `Auto-spawn? = yes` will be materialised by `scripts/okstra-spawn-followups.py` in Phase 7; rows with `Auto-spawn? = no` MUST also appear in `Section 6. Recommended Next Steps` so the user knows to act manually.
|
|
132
132
|
- Self-review pass before finalising the report (`Claude lead` runs this; do not delegate to a generic subagent):
|
|
133
133
|
1. **Plan coverage** — every step in the approved plan's recommended option must point to a commit (or an explicit `Skipped: <reason>` entry). List gaps.
|
|
134
134
|
2. **Evidence completeness** — every `Validation evidence` and `TDD evidence` claim has the actual command line and exit code? No paraphrased "tests pass" without output?
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
- uncertainty boundaries and missing inputs
|
|
20
20
|
- next recommended phase and safe resume guidance
|
|
21
21
|
- Clarification request policy (phase-specific addenda — shared policy is in `_common-contract.md`):
|
|
22
|
-
- if any blocking input is missing at the time of writing the final report, populate `## 5. Clarification
|
|
22
|
+
- if any blocking input is missing at the time of writing the final report, populate `## 5. Clarification Items` in `final-report-template.md` (a single unified table; `Blocks=next-phase` for items the next run cannot start without)
|
|
23
23
|
- prefer concrete questions whose answers map directly to a routing decision (`bugfix` vs `feature`, `error-analysis` vs `implementation-planning`, etc.). State each option in plain language with one sentence describing what choosing it would mean for the next phase.
|
|
24
24
|
- Non-goals:
|
|
25
25
|
- full implementation design unless it is required to decide the next phase
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"""Parse the ``## 5. Clarification Items`` table from a final-report markdown.
|
|
2
|
+
|
|
3
|
+
The unified §5 table (introduced when §4.5.9 / §5.1 / §5.2 collapsed into a
|
|
4
|
+
single section) is the canonical home for every clarification an
|
|
5
|
+
implementation-planning run owes the user — decisions, file attachments,
|
|
6
|
+
single data points. Each row carries a ``Blocks`` column whose value picks
|
|
7
|
+
one of ``{approval, next-phase, none}``. Rows with ``Blocks=approval`` are
|
|
8
|
+
the approval gate: they MUST resolve before the user marks the report
|
|
9
|
+
``Approved`` and starts the next ``implementation`` run.
|
|
10
|
+
|
|
11
|
+
This module exposes one read function for that gate so both
|
|
12
|
+
``_validate_approved_plan`` (pre-implementation run-prep) and any later
|
|
13
|
+
validator can share the same parsing logic.
|
|
14
|
+
|
|
15
|
+
Legacy compatibility: reports written before the §5 unification used
|
|
16
|
+
``4.5.9 Open Questions`` + ``5.1 Additional Materials`` + ``5.2 Questions
|
|
17
|
+
for the User`` and lacked a ``Blocks`` column. Those reports cannot be
|
|
18
|
+
gate-checked by Blocks; the parser returns ``None`` to signal "schema
|
|
19
|
+
absent, skip check" rather than fabricating a verdict.
|
|
20
|
+
"""
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import re
|
|
24
|
+
from dataclasses import dataclass
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
from typing import Optional
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
SECTION_HEADING_PATTERN = re.compile(r"^##\s+5\.\s+Clarification Items\s*$", re.MULTILINE)
|
|
30
|
+
NEXT_TOP_LEVEL_HEADING_PATTERN = re.compile(r"^##\s+(?!5\.)", re.MULTILINE)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True)
|
|
34
|
+
class ClarificationItem:
|
|
35
|
+
"""One row of the §5 table.
|
|
36
|
+
|
|
37
|
+
``raw_*`` fields preserve the exact cell text (after backtick stripping)
|
|
38
|
+
for diagnostics; canonical lowercased versions live in ``blocks`` /
|
|
39
|
+
``status`` for predicate use.
|
|
40
|
+
"""
|
|
41
|
+
row_id: str
|
|
42
|
+
kind: str # "material" | "decision" | "data-point" | other
|
|
43
|
+
blocks: str # canonical lowercase: "approval" | "next-phase" | "none" | other
|
|
44
|
+
status: str # canonical lowercase: "open" | "answered" | "resolved" | "obsolete" | other
|
|
45
|
+
raw_blocks: str
|
|
46
|
+
raw_status: str
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _strip_backticks(cell: str) -> str:
|
|
50
|
+
s = cell.strip()
|
|
51
|
+
if s.startswith("`") and s.endswith("`") and len(s) >= 2:
|
|
52
|
+
s = s[1:-1].strip()
|
|
53
|
+
return s
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _split_pipe_row(line: str) -> list[str]:
|
|
57
|
+
"""Split a markdown pipe-table row into cells (strip outer pipes + cell whitespace)."""
|
|
58
|
+
stripped = line.strip()
|
|
59
|
+
if stripped.startswith("|"):
|
|
60
|
+
stripped = stripped[1:]
|
|
61
|
+
if stripped.endswith("|"):
|
|
62
|
+
stripped = stripped[:-1]
|
|
63
|
+
return [_strip_backticks(c) for c in stripped.split("|")]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _is_separator_row(line: str) -> bool:
|
|
67
|
+
"""Detect ``|---|---|---|`` divider lines that separate header from body."""
|
|
68
|
+
stripped = line.strip()
|
|
69
|
+
if not stripped.startswith("|"):
|
|
70
|
+
return False
|
|
71
|
+
inner = stripped.strip("|").strip()
|
|
72
|
+
# A separator cell is dashes optionally framed by colons; anything else
|
|
73
|
+
# (real text) means this is a data row, not a separator.
|
|
74
|
+
for cell in inner.split("|"):
|
|
75
|
+
if not re.fullmatch(r"\s*:?-{2,}:?\s*", cell):
|
|
76
|
+
return False
|
|
77
|
+
return True
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _section_5_slice(report_text: str) -> Optional[str]:
|
|
81
|
+
"""Return the substring spanning the §5 section (heading exclusive of the
|
|
82
|
+
next ``##`` heading), or None if §5 is absent."""
|
|
83
|
+
start_match = SECTION_HEADING_PATTERN.search(report_text)
|
|
84
|
+
if not start_match:
|
|
85
|
+
return None
|
|
86
|
+
rest = report_text[start_match.end():]
|
|
87
|
+
end_match = NEXT_TOP_LEVEL_HEADING_PATTERN.search(rest)
|
|
88
|
+
return rest[: end_match.start()] if end_match else rest
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def parse_clarification_items(report_text: str) -> Optional[list[ClarificationItem]]:
|
|
92
|
+
"""Return the list of §5 rows. ``None`` means "no unified §5 table
|
|
93
|
+
detected" (legacy report or missing section) — caller must NOT treat
|
|
94
|
+
that as "table is empty".
|
|
95
|
+
|
|
96
|
+
An empty list ``[]`` means "table exists but has no data rows" (e.g.,
|
|
97
|
+
just the ``- 추가 정보 요청 없음.`` placeholder); that IS a confident
|
|
98
|
+
"no approval-blocking items".
|
|
99
|
+
"""
|
|
100
|
+
section = _section_5_slice(report_text)
|
|
101
|
+
if section is None:
|
|
102
|
+
return None
|
|
103
|
+
|
|
104
|
+
lines = section.splitlines()
|
|
105
|
+
# Locate the header row containing both `Blocks` and `Status` columns.
|
|
106
|
+
# We scan for the first table-shaped header line that includes both
|
|
107
|
+
# column names (case-insensitive); anything else (legacy 5.1 / 5.2
|
|
108
|
+
# tables, intro tables) is rejected.
|
|
109
|
+
header_idx = -1
|
|
110
|
+
headers: list[str] = []
|
|
111
|
+
for idx, line in enumerate(lines):
|
|
112
|
+
if not line.lstrip().startswith("|"):
|
|
113
|
+
continue
|
|
114
|
+
cells = [c.lower() for c in _split_pipe_row(line)]
|
|
115
|
+
if "blocks" in cells and "status" in cells:
|
|
116
|
+
header_idx = idx
|
|
117
|
+
headers = cells
|
|
118
|
+
break
|
|
119
|
+
if header_idx < 0:
|
|
120
|
+
# Section heading present but no Blocks/Status header — legacy
|
|
121
|
+
# layout or schema not yet adopted.
|
|
122
|
+
return None
|
|
123
|
+
|
|
124
|
+
blocks_col = headers.index("blocks")
|
|
125
|
+
status_col = headers.index("status")
|
|
126
|
+
id_col = headers.index("id") if "id" in headers else 0
|
|
127
|
+
kind_col = headers.index("kind") if "kind" in headers else None
|
|
128
|
+
|
|
129
|
+
items: list[ClarificationItem] = []
|
|
130
|
+
body_started = False
|
|
131
|
+
for line in lines[header_idx + 1:]:
|
|
132
|
+
if not line.lstrip().startswith("|"):
|
|
133
|
+
if body_started:
|
|
134
|
+
break
|
|
135
|
+
continue
|
|
136
|
+
if _is_separator_row(line):
|
|
137
|
+
body_started = True
|
|
138
|
+
continue
|
|
139
|
+
if not body_started:
|
|
140
|
+
# A second header (unlikely) or a malformed row before the
|
|
141
|
+
# separator — skip.
|
|
142
|
+
continue
|
|
143
|
+
cells = _split_pipe_row(line)
|
|
144
|
+
if max(blocks_col, status_col, id_col) >= len(cells):
|
|
145
|
+
# malformed row; skip rather than crash
|
|
146
|
+
continue
|
|
147
|
+
raw_blocks = cells[blocks_col]
|
|
148
|
+
raw_status = cells[status_col]
|
|
149
|
+
row_id = cells[id_col]
|
|
150
|
+
kind = cells[kind_col] if kind_col is not None and kind_col < len(cells) else ""
|
|
151
|
+
# Treat template-placeholder rows (e.g. literal ``C-001`` with
|
|
152
|
+
# angle-bracket sample text) as still-real rows but caller can
|
|
153
|
+
# filter on raw_id == "C-001" if needed.
|
|
154
|
+
items.append(
|
|
155
|
+
ClarificationItem(
|
|
156
|
+
row_id=row_id,
|
|
157
|
+
kind=kind.lower(),
|
|
158
|
+
blocks=raw_blocks.lower(),
|
|
159
|
+
status=raw_status.lower(),
|
|
160
|
+
raw_blocks=raw_blocks,
|
|
161
|
+
raw_status=raw_status,
|
|
162
|
+
)
|
|
163
|
+
)
|
|
164
|
+
return items
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
UNRESOLVED_STATUSES = {"open", "answered"}
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def unresolved_approval_blockers(report_text: str) -> Optional[list[ClarificationItem]]:
|
|
171
|
+
"""Return rows that gate the User Approval Request — ``Blocks=approval``
|
|
172
|
+
AND ``Status`` in ``{open, answered}``.
|
|
173
|
+
|
|
174
|
+
``None`` propagates the "schema absent" signal from
|
|
175
|
+
``parse_clarification_items``: caller may decide to soft-pass legacy
|
|
176
|
+
reports and only enforce on the new-format §5.
|
|
177
|
+
"""
|
|
178
|
+
items = parse_clarification_items(report_text)
|
|
179
|
+
if items is None:
|
|
180
|
+
return None
|
|
181
|
+
return [
|
|
182
|
+
it for it in items
|
|
183
|
+
if it.blocks == "approval" and it.status in UNRESOLVED_STATUSES
|
|
184
|
+
]
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def unresolved_approval_blockers_in_file(path: Path) -> Optional[list[ClarificationItem]]:
|
|
188
|
+
return unresolved_approval_blockers(
|
|
189
|
+
Path(path).read_text(encoding="utf-8", errors="replace")
|
|
190
|
+
)
|
|
@@ -24,6 +24,7 @@ from datetime import datetime, timezone
|
|
|
24
24
|
from pathlib import Path
|
|
25
25
|
|
|
26
26
|
from okstra_project import upsert_project_json
|
|
27
|
+
from .clarification_items import unresolved_approval_blockers
|
|
27
28
|
from .qa_commands import format_errors as _format_qa_errors, validate_qa_commands
|
|
28
29
|
from .material import (
|
|
29
30
|
build_analysis_material,
|
|
@@ -131,7 +132,8 @@ def _validate_approved_plan(path: str) -> None:
|
|
|
131
132
|
p = Path(path)
|
|
132
133
|
if not p.is_file():
|
|
133
134
|
raise PrepareError(f"approved plan file not found: {path}")
|
|
134
|
-
|
|
135
|
+
body = p.read_text(encoding="utf-8", errors="replace")
|
|
136
|
+
if not APPROVED_PLAN_PATTERN.search(body):
|
|
135
137
|
raise PrepareError(
|
|
136
138
|
f"approved plan has no recognised user-approval marker: {path}\n"
|
|
137
139
|
' canonical form (single line, top-of-report block): "- [x] Approved"\n'
|
|
@@ -140,6 +142,21 @@ def _validate_approved_plan(path: str) -> None:
|
|
|
140
142
|
" shortcut: re-run okstra with --approve to have the CLI itself "
|
|
141
143
|
"record the approval marker on this file."
|
|
142
144
|
)
|
|
145
|
+
# The approval marker is set. Cross-check the §5 Clarification Items
|
|
146
|
+
# table: any row with Blocks=approval that is still open/answered
|
|
147
|
+
# invalidates the approval. Legacy reports (no unified §5 with a
|
|
148
|
+
# Blocks column) return None — soft-pass to preserve compatibility
|
|
149
|
+
# during the transitional release.
|
|
150
|
+
blockers = unresolved_approval_blockers(body)
|
|
151
|
+
if blockers:
|
|
152
|
+
lines = [
|
|
153
|
+
f"approved plan marker is set but §5 has {len(blockers)} unresolved "
|
|
154
|
+
f"`Blocks=approval` row(s); resolve them or mark them obsolete before approving:",
|
|
155
|
+
]
|
|
156
|
+
for b in blockers:
|
|
157
|
+
lines.append(f" - {b.row_id} (Status={b.raw_status})")
|
|
158
|
+
lines.append(f" file: {path}")
|
|
159
|
+
raise PrepareError("\n".join(lines))
|
|
143
160
|
|
|
144
161
|
|
|
145
162
|
# `- [ ] Approved` 라인을 정확히 한 번만 매치한다. 좌측 leading whitespace 와
|
|
@@ -68,7 +68,7 @@ PHASE_RULES: dict[str, dict[str, str]] = {
|
|
|
68
68
|
" - trade-off matrix across options (complexity, risk, reversibility, test cost, rollout cost) and recommended option with rationale tied to isolation / single-responsibility / YAGNI principles\n"
|
|
69
69
|
" - bite-sized stepwise execution order for the recommended option (each step ~2-5 min, exact file paths and commands, TDD ordering when applicable, no placeholders)\n"
|
|
70
70
|
" - dependency / migration risk assessment, validation checklist (pre / mid / post with exact commands), rollback strategy with revert path and trigger signal\n"
|
|
71
|
-
" - `Open Questions` block
|
|
71
|
+
" - every unresolved ambiguity registered as a `Blocks=approval` row in the `## 5. Clarification Items` table (do NOT create a separate `Open Questions` block under `4.5.x` — the unified table is the single home)\n"
|
|
72
72
|
" - explicit `User Approval Request` block awaiting human approval\n"
|
|
73
73
|
" - self-review confirmation (spec coverage, placeholder scan, internal consistency, ambiguity, scope)"
|
|
74
74
|
),
|
|
@@ -224,7 +224,7 @@ Skipping this file because "the real report is in `reports/`" is wrong. Both fil
|
|
|
224
224
|
|
|
225
225
|
Section numbering matches `okstra-final-report.template.md`. Section 0 is the carry-in reconciliation that runs first when a clarification response was provided; sections 1–7 follow the template's main body order.
|
|
226
226
|
|
|
227
|
-
0. **Clarification Response Carried In** - if `{{CLARIFICATION_RESPONSE_RELATIVE_PATH}}` is non-empty, read `instruction-set/clarification-response.md`,
|
|
227
|
+
0. **Clarification Response Carried In** - if `{{CLARIFICATION_RESPONSE_RELATIVE_PATH}}` is non-empty, read `instruction-set/clarification-response.md`, walk every `C-*` row of the prior report's `## 5. Clarification Items` table, reconcile each one against new evidence, and record the outcome (`resolved`/`obsolete`) plus the citation in this section before drafting the verdict. If the prior report uses the deprecated `4.5.9 Open Questions` / `5.1` / `5.2` layout with `OQ-*`/`A*`/`Q*` IDs, follow the legacy-carry-in mapping rule in `final-report-template.md` section 0.
|
|
228
228
|
1. **Problem or Verification Summary** - Key summary based on the brief and data (3–5 bullet points)
|
|
229
229
|
2. **Cross Verification Results** (Use 4 categories when convergence is enabled, per `okstra-convergence`)
|
|
230
230
|
- Round History sub-table (convergence-enabled runs only): one row per executed round with columns `Round | inputQueueSize | resolvedCount | carriedForwardCount | dispatches (worker:status:durationMs) | skippedWorkers (worker:reason)`. Add a one-line note immediately under the table with `round2SkippedReason: <value>` (always present, even when `"not-skipped"`). Pull all values verbatim from `convergence-<task-type>-<seq>.json`.
|
|
@@ -239,7 +239,7 @@ Section numbering matches `okstra-final-report.template.md`. Section 0 is the ca
|
|
|
239
239
|
- If explicit expected values are present in `reference-expectations.md`, specify whether they match or differ from the expected values in config files / deployment manifests
|
|
240
240
|
- Supporting evidence or alternative interpretations
|
|
241
241
|
5. **Missing Information and Risks** - Uncertain/I don't know items
|
|
242
|
-
6. **Clarification
|
|
242
|
+
6. **Clarification Items** - single unified table (`C-001`, `C-002`, ...) the user fills inline before reruns. Columns: `ID`, `Ticket ID`, `Kind` (`material` / `decision` / `data-point`), `Statement`, `Expected form`, `Blocks` (`approval` / `next-phase` / `none`), `Status`, `User input`. Replaces the legacy `4.5.9 Open Questions` / `5.1` / `5.2` triple; never create those sub-sections — same item appearing in two places is the failure mode this table prevents.
|
|
243
243
|
- Required for `task-type` `error-analysis` and `requirements-discovery` whenever blocking uncertainty remains
|
|
244
244
|
- Optional for other task-types; explicitly state "no clarification needed" when none
|
|
245
245
|
- Follow the table format from `final-report-template.md` exactly (columns: Question ID, Blocking, Why this matters, Question, Expected answer shape, Status, Answer)
|
|
@@ -127,13 +127,15 @@ Reading rules:
|
|
|
127
127
|
large for one read; if you must page, you MUST cover the entire file
|
|
128
128
|
before moving on, and you MUST state the page boundaries you used in your
|
|
129
129
|
Findings section.
|
|
130
|
-
- For the carry-in clarification response, read sub-section 0
|
|
131
|
-
5.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
130
|
+
- For the carry-in clarification response, read sub-section 0 and every
|
|
131
|
+
row of `## 5. Clarification Items` (`C-001`, `C-002`, ...) in full,
|
|
132
|
+
including rows whose `User input` cell is blank. The fact that you
|
|
133
|
+
will write your output into a file with a structurally similar
|
|
134
|
+
section 5 is NOT an excuse to skim — the prior `C-*` rows carry
|
|
135
|
+
context you cannot reconstruct from the new run alone. If the prior
|
|
136
|
+
report uses the deprecated `4.5.9 Open Questions` / `5.1` / `5.2`
|
|
137
|
+
layout with `OQ-*` / `A*` / `Q*` IDs, walk all three blocks the
|
|
138
|
+
same way (legacy carry-in transitional rule).
|
|
137
139
|
- Before writing any Findings, state in one sentence per file that you
|
|
138
140
|
read it end-to-end. Example: "Read task-brief.md end-to-end (147 lines)."
|
|
139
141
|
If you cannot truthfully say this for a file, do not produce Findings —
|
|
@@ -24,7 +24,7 @@ taskType: "{{FM_TASK_TYPE}}"
|
|
|
24
24
|
|
|
25
25
|
> **이 블록은 `task-type` = `implementation-planning` 결과에서만 의미를 가집니다.** 다른 task-type의 보고서에서는 이 섹션 전체를 삭제하세요.
|
|
26
26
|
>
|
|
27
|
-
> 다음 `implementation` run은 아래 체크박스가 `[x]`로 표시되어 있을 때에만 진입할 수 있습니다 (`okstra_ctl.run._validate_approved_plan` 가 이 마커를 line-anchored 정규식으로 검사하여 통과/거부합니다). 본문(`Sections 1`–`4.5`)을 끝까지 읽고,
|
|
27
|
+
> 다음 `implementation` run은 아래 체크박스가 `[x]`로 표시되어 있을 때에만 진입할 수 있습니다 (`okstra_ctl.run._validate_approved_plan` 가 이 마커를 line-anchored 정규식으로 검사하여 통과/거부합니다). 본문(`Sections 1`–`4.5`)을 끝까지 읽고, `## 5. Clarification Items` 표에서 `Blocks=approval` 인 모든 행이 `Status` 가 `resolved` 또는 `obsolete` 인지 확인한 뒤 승인해 주세요. 한 행이라도 `open`/`answered` 로 남아 있으면 `Approved` 마커를 새기지 마십시오 — 향후 `validate-run.py` 가 이 정합성을 자동 검사할 예정입니다.
|
|
28
28
|
|
|
29
29
|
- 승인 여부 (사용자가 직접 편집): `- [ ] Approved` ← 승인하려면 `[ ]` 를 `[x]` 로 변경하여 저장하세요.
|
|
30
30
|
- 승인 후 다음 단계 명령어 (방법 A — 수동 편집):
|
|
@@ -34,13 +34,13 @@ taskType: "{{FM_TASK_TYPE}}"
|
|
|
34
34
|
- Claude Code 세션 안: `/okstra-run task-key={{TASK_KEY}} task-type=implementation approved-plan=<이 보고서 경로> approve`
|
|
35
35
|
- 별도 터미널: `scripts/okstra.sh --task-key {{TASK_KEY}} --task-type implementation --approved-plan <이 보고서 경로> --approve`
|
|
36
36
|
- 방법 B 는 `--approve` 입력 행위 자체를 승인 의사로 모델링합니다. 런타임이 본 블록의 체크박스를 자동으로 `[x]` 로 바꾸고, 본 섹션 하단에 `승인 일시 (CLI ack): <ISO8601>` audit 라인을 한 줄 덧붙입니다.
|
|
37
|
-
- 승인을 보류하거나 거부하려면 체크박스는 `[ ]` 로 두고 `--approve` 도 사용하지 마세요. 필요한 변경 사항은
|
|
37
|
+
- 승인을 보류하거나 거부하려면 체크박스는 `[ ]` 로 두고 `--approve` 도 사용하지 마세요. 필요한 변경 사항은 `## 5. Clarification Items` 표에 한 행으로 기록한 뒤 (`Blocks=approval` 로 표시) 같은 phase 를 재실행해 주세요.
|
|
38
38
|
|
|
39
39
|
## 0. Clarification Response Carried In From Previous Run
|
|
40
40
|
- Source file: `{{CLARIFICATION_RESPONSE_RELATIVE_PATH}}`
|
|
41
41
|
- If the source path is empty, write `- No prior clarification response was provided for this run.` and skip the rest of this section.
|
|
42
|
-
- If the source path is set, walk
|
|
43
|
-
-
|
|
42
|
+
- If the source path is set, walk every row of the prior report's `## 5. Clarification Items` table (`C-001`, `C-002`, ...). For each row, summarize how its `User input` (or its absence) was used by this run's evidence, cite the new evidence (file path, line number, log excerpt, worker finding) that resolves or refutes the prior answer, and update the row's `Status` to `resolved` or `obsolete` when carrying it into this run's section 5.
|
|
43
|
+
- Transitional rule (legacy carry-in only): if the prior report uses the deprecated `4.5.9 Open Questions` / `5.1 Additional Materials` / `5.2 Questions for the User` layout with `OQ-*` / `A*` / `Q*` IDs, walk every row of all three blocks. Map each legacy row into a single `C-*` row in this run's new `## 5. Clarification Items` table — assign `Kind = material` for prior `A*`, `Kind = decision` for prior `Q*` and prior `OQ*`, and `Blocks = approval` only for items the prior report flagged as gating the implementation-planning approval (default: `next-phase`). Keep the legacy ID in the new row's Statement column for traceability (e.g. `"[legacy OQ-003] ..."`).
|
|
44
44
|
|
|
45
45
|
## Summary of the Problem or Verification Target
|
|
46
46
|
|
|
@@ -223,14 +223,7 @@ revert 경로와 롤백 트리거 신호를 표로 정리합니다. 추상적
|
|
|
223
223
|
### 4.5.8 User Approval Request (사용자 승인 요청 — 본 보고서 상단 참조)
|
|
224
224
|
- 실제 승인 게이트는 본 보고서 **상단 `User Approval Request (사용자 승인 게이트)` 블록**에 있습니다. 이 하위 섹션은 validator가 요구하는 영문 키워드(`User Approval Request`)와 본문 구조 일관성을 위해 남겨 둡니다.
|
|
225
225
|
- 본 섹션에는 승인 결정에 영향을 주는 *플랜 측 보충 메모*만 적습니다(예: 위험을 줄이기 위한 사전 작업, 승인 전 사용자가 확인해 두어야 할 사항). 승인 마커는 본 섹션이 아니라 상단 블록의 체크박스로만 부여합니다.
|
|
226
|
-
|
|
227
|
-
### 4.5.9 Open Questions
|
|
228
|
-
|
|
229
|
-
pre-planning에서 발견된 모호점을 표로 남깁니다. 사용자가 승인 전에 해소해야 할 질문 목록입니다. 없을 시: `- Open question 없음.` 한 줄.
|
|
230
|
-
|
|
231
|
-
| ID | Ticket ID | 질문 | Blocking (예/아니오) | 기대 답 형태 | Status |
|
|
232
|
-
|----|-----------|------|----------------------|--------------|--------|
|
|
233
|
-
| OQ-001 | `<TICKET-or-fallback>` | <질문 본문> | 예 | <예/아니오 / 선택 / 자유서술> | open |
|
|
226
|
+
- 사용자가 답하거나 자료를 첨부해야만 승인이 가능한 항목은 **이 섹션에 적지 않습니다** — `## 5. Clarification Items` 표에 한 행으로 등록하고 `Blocks=approval` 로 표시하세요. 같은 항목을 두 위치에 적으면 sync 가 깨집니다.
|
|
234
227
|
|
|
235
228
|
## 4.6 Release Handoff Deliverables (release-handoff runs only)
|
|
236
229
|
|
|
@@ -287,49 +280,56 @@ H1 이 `skip` 이거나 H3 가 `cancel` 인 경우, 본 섹션 다음의 4.6.4 ~
|
|
|
287
280
|
- 단, H1=`skip` 또는 H3=`cancel` 로 종료된 경우 사용자가 추후 재진입해 다시 release-handoff 를 실행할 수 있는지 한 줄로 명시합니다.
|
|
288
281
|
- 형식 예시: `- Routing: done. PR <url> opened against <base>; no follow-up required.`
|
|
289
282
|
|
|
290
|
-
## 5. Clarification
|
|
283
|
+
## 5. Clarification Items
|
|
284
|
+
|
|
285
|
+
이 섹션은 다음 run 으로 넘어가기 전에 사용자가 답하거나 자료를 첨부해야 하는 항목을 **한 표 안에서** 추적합니다. `task-type`이 `error-analysis` 또는 `requirements-discovery` 이고 지금까지의 증거만으로 확신 있는 최종 판단이 어려울 때는 반드시 채웁니다. 그 외의 `task-type`에서는 lead 가 필요하다고 판단할 때만 채우고, 그렇지 않다면 `- 추가 정보 요청 없음. Section 2의 최종 판단이 그대로 유효합니다.` 한 줄만 남깁니다.
|
|
291
286
|
|
|
292
|
-
이
|
|
287
|
+
이 표가 도입되기 전에는 `4.5.9 Open Questions` / `5.1 추가 자료 요청` / `5.2 사용자 확인 질문` 세 자리에 같은 항목이 중복으로 적히는 문제가 있었습니다. 그 세 위치는 더 이상 사용하지 않으며, 모든 항목은 본 표의 한 행으로 표현합니다. 표 외부에 같은 항목을 다시 적지 마세요 (sync 가 깨집니다).
|
|
293
288
|
|
|
294
289
|
작성 원칙:
|
|
295
290
|
|
|
296
291
|
- 개발자가 아닌 사람도 한 번 읽고 무엇을 어디서 가져와야 하는지 이해할 수 있게, 줄임말과 내부 용어 대신 풀어 쓴 문장으로 작성합니다. (예: "QPS" 대신 "초당 평균 요청 수", "AC 미정" 대신 "합격 기준이 아직 정의되지 않았습니다")
|
|
297
|
-
- 한
|
|
298
|
-
-
|
|
299
|
-
|
|
300
|
-
-
|
|
301
|
-
- `open`: 요청했지만 아직 받지 못했습니다.
|
|
302
|
-
- `answered`: 사용자가 아래 답변 칸을 채워 두었습니다(다음 run의 lead가 검증해야 합니다).
|
|
303
|
-
- `resolved`: 다음 run에서 lead가 답변을 받아 검증을 마쳤습니다.
|
|
304
|
-
- `obsolete`: 이후 분석 결과로 더 이상 필요 없어진 항목입니다.
|
|
305
|
-
|
|
306
|
-
이 보고서에 답을 채우신 뒤에는 한 줄로 같은 phase를 다시 실행하실 수 있습니다(자동으로 `$EDITOR`가 이 파일을 열고, 저장하면 같은 phase가 `--clarification-response`로 carry-in 되어 재실행됩니다).
|
|
292
|
+
- 한 행은 "왜 필요한지", "무엇을 묻거나 받아야 하는지", "어떤 형태의 답을 기대하는지"가 모두 분명히 드러나야 합니다. 한 줄짜리 단답형 질문은 피하고, 필요한 배경을 1~2 문장으로 함께 적습니다.
|
|
293
|
+
- run 사이에 일관된 추적이 가능하도록 항목별 ID (`C-001`, `C-002`, ...) 는 한 번 부여한 뒤 다음 run 에서도 유지합니다. 이미 답변된 항목은 다음 run 에서도 삭제하지 말고 `Status`만 `resolved` 또는 `obsolete` 로 갱신합니다.
|
|
294
|
+
|
|
295
|
+
이 보고서에 답을 채우신 뒤에는 한 줄로 같은 phase 를 다시 실행하실 수 있습니다 (자동으로 `$EDITOR` 가 이 파일을 열고, 저장하면 같은 phase 가 `--clarification-response` 로 carry-in 되어 재실행됩니다).
|
|
307
296
|
- Claude Code 세션 안: `/okstra-run resume-clarification task-key={{TASK_KEY}}`
|
|
308
297
|
- 별도 터미널: `scripts/okstra.sh --resume-clarification --task-key {{TASK_KEY}}`
|
|
309
298
|
|
|
310
|
-
스크립트로 자동화하실 때는 셸 형식 `scripts/okstra.sh --task-key {{TASK_KEY}} --task-type {{TASK_TYPE}} --clarification-response <이 파일
|
|
311
|
-
|
|
312
|
-
### 5.1
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
|
317
|
-
|
|
318
|
-
|
|
|
319
|
-
|
|
320
|
-
### 5.2
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
-
|
|
327
|
-
-
|
|
328
|
-
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
299
|
+
스크립트로 자동화하실 때는 셸 형식 `scripts/okstra.sh --task-key {{TASK_KEY}} --task-type {{TASK_TYPE}} --clarification-response <이 파일 경로>` 도 그대로 사용하실 수 있습니다. Node `okstra` admin CLI 는 `--task-key`/`--task-type`/`--resume-clarification` 을 받지 않으므로 위 두 진입점 중 하나를 사용하세요.
|
|
300
|
+
|
|
301
|
+
### 5.1 Clarification Items table
|
|
302
|
+
|
|
303
|
+
| ID | Ticket ID | Kind | Statement (무엇이 필요한지 + 왜) | Expected form (답·자료의 모양) | Blocks | Status | User input (사용자가 다음 run 전에 채움) |
|
|
304
|
+
|----|-----------|------|----------------------------------|-------------------------------|--------|--------|------------------------------------------|
|
|
305
|
+
| C-001 | `<TICKET-or-fallback>` | `decision` | <예: "지난 주 새벽에 보고된 결제 실패가 일회성 사고였는지, 아니면 같은 증상이 다시 발생한 적이 있는지 알려주십시오. 이 결정에 따라 다음 run 의 task-type 이 `error-analysis` 로 갈지 `requirements-discovery` 로 갈지가 갈립니다."> | <예: "(a) 일회성·재발 없음, (b) 재발 있음 — 가장 최근 시각 YYYY-MM-DD HH:MM, 영향 사용자 수 약 N명"> | `next-phase` | open | <빈칸으로 두고 다음 run 전에 사용자가 채움> |
|
|
306
|
+
| C-002 | `<TICKET-or-fallback>` | `material` | <예: "오류가 처음 보고된 시각 전후 30분 동안의 worker 로그가 필요합니다. 어떤 task 가 실패했고 그때 큐에 무엇이 쌓여 있었는지를 함께 확인해야 root cause 가설을 좁힐 수 있기 때문입니다. Datadog `service:worker env:prod` 필터, 시각 범위 2026-04-30 09:30~10:30 KST. `.project-docs/tasks/8852/logs/worker-2026-04-30.log` 로 저장해 주십시오."> | <예: "위 경로의 .log 파일 (gzip 압축 가능)"> | `next-phase` | open | |
|
|
307
|
+
| C-003 | `<TICKET-or-fallback>` | `data-point` | <예: "본 배치 시작 직전 `common.FontManualClassifiers` 의 `prediction=0` / `prediction=1` 행 수가 필요합니다. acceptance #5 의 동일성 검증 ground truth 입니다."> | <예: "두 정수 (prediction=0 count, prediction=1 count) 를 한 줄로"> | `approval` | open | |
|
|
308
|
+
|
|
309
|
+
### 5.2 컬럼 가이드
|
|
310
|
+
|
|
311
|
+
- **`Kind`** ∈ `{material, decision, data-point}`:
|
|
312
|
+
- `material` — 파일 / 스냅샷 / 로그 / 스크린샷 등 사용자가 따로 **첨부 또는 경로 공유** 해야 하는 자료.
|
|
313
|
+
- `decision` — 사용자가 선택지 중 하나를 고르거나 (a/b/c 보기, yes/no) 짧게 자유서술로 결정해 주셔야 진행 가능한 의사결정.
|
|
314
|
+
- `data-point` — 숫자 / ID / 날짜 / 짧은 문자열처럼 사용자가 명령 한 번으로 뽑아 **inline 으로** 답해 주실 수 있는 사실 확인.
|
|
315
|
+
- **`Statement`**: 무엇을 묻거나 받아야 하는지 + 왜 필요한지 + (material 의 경우) 어디서 가져오는지·어디에 두면 되는지를 1~3 문장으로. 자료 출처가 길면 본 셀에 풀어 적고 `Expected form` 셀은 짧게 유지합니다.
|
|
316
|
+
- **`Expected form`**: 답 / 자료의 모양 — 예/아니오, 보기 a/b/c, 정수, 날짜, 파일 경로, URL 등. 가능하면 정확한 보기 또는 예시 한 줄.
|
|
317
|
+
- **`Blocks`** ∈ `{approval, next-phase, none}`:
|
|
318
|
+
- `approval` — `implementation-planning` 의 User Approval Request 통과를 막는 항목. 모두 `resolved`/`obsolete` 가 되어야 상단 체크박스를 `[x]` 로 바꿀 수 있습니다.
|
|
319
|
+
- `next-phase` — 승인 게이트가 아니더라도 다음 run 진입에 답이 필요한 항목.
|
|
320
|
+
- `none` — informational. 답이 없어도 다음 phase 는 진행 가능하지만 audit 기록을 위해 남깁니다.
|
|
321
|
+
- **`Status`** ∈ `{open, answered, resolved, obsolete}`:
|
|
322
|
+
- `open` — 요청했지만 아직 받지 못함.
|
|
323
|
+
- `answered` — 사용자가 `User input` 칸을 채워 두었음 (다음 run 의 lead 가 검증해야 함).
|
|
324
|
+
- `resolved` — 다음 run 에서 lead 가 답변·자료를 받아 검증을 마침.
|
|
325
|
+
- `obsolete` — 이후 분석 결과로 더 이상 필요 없어진 항목.
|
|
326
|
+
- **`User input`**: 사용자가 직접 채우는 칸. `material` 이면 첨부 파일 경로 / URL / 메모, `decision` 이면 선택 또는 짧은 서술, `data-point` 이면 inline 값.
|
|
327
|
+
|
|
328
|
+
작성 안티패턴 (자동 거절):
|
|
329
|
+
|
|
330
|
+
- 같은 항목을 `## 4.5.8 User Approval Request` 보충 메모와 본 표에 동시 등록 — `Blocks=approval` 행 하나로 충분합니다.
|
|
331
|
+
- 한 행을 두 개로 나눠 "자료 요청 행" 과 "관련 질문 행" 으로 쪼개기 — 자료 + yes/no 가 묶인 항목은 `Kind=material`, `Expected form` 에 "파일 경로 + yes/no" 라고 적은 한 행으로 처리합니다.
|
|
332
|
+
- 사용자가 답하지 않아도 진행 가능한 항목을 `Blocks=approval` 로 표시 — `Blocks=none` 또는 `next-phase` 로 정확히 표시하세요. 잘못 표시하면 사용자가 불필요하게 게이트에 걸립니다.
|
|
333
333
|
|
|
334
334
|
## 6. Recommended Next Steps
|
|
335
335
|
|
|
@@ -346,7 +346,7 @@ When concrete actions exist, list them as a numbered list using the rules below.
|
|
|
346
346
|
- 별도 터미널: `scripts/okstra.sh --task-key {{TASK_KEY}} --task-type <next-phase>`
|
|
347
347
|
2. **Additional verification needed before implementation or release.** List read-only checks (test commands, log queries, dashboard URLs) that the user should run before moving to the next phase. No state-mutating commands here.
|
|
348
348
|
3. **Follow-up tasks or related tasks if needed.** Reference them by `task-key` when they already exist; otherwise describe the new brief to draft.
|
|
349
|
-
4. **If section 5 has any `
|
|
349
|
+
4. **If section 5 has any rows with `Status` in `{open, answered}`**, the highest-priority next step MUST be the clarification turn-around. Show both forms:
|
|
350
350
|
- Preferred (interactive) — opens this file in `$EDITOR`, then auto-reruns the same phase with `--clarification-response` carry-in:
|
|
351
351
|
- Claude Code 세션 안: `/okstra-run resume-clarification task-key={{TASK_KEY}}`
|
|
352
352
|
- 별도 터미널: `scripts/okstra.sh --resume-clarification --task-key {{TASK_KEY}}`
|
|
@@ -370,7 +370,7 @@ Empty-state placeholder, copy verbatim when nothing else applies:
|
|
|
370
370
|
- `out-of-plan` — 구현 중 발견됐으나 본 plan의 file list / step 범위를 벗어나 처리하지 못한 항목 (Out-of-plan edits 블록에 기록되지 않고 미처리로 남은 것).
|
|
371
371
|
- `verifier-concern` — verifier가 PASS는 줬으나 후속 개선 권고로 남긴 항목.
|
|
372
372
|
- `scope-boundary` — `implementation-planning`의 `4.5.5 Dependency / Migration Risk` 또는 task-brief `Out of Scope` 에서 의도적으로 제외했으나, 본 run 결과에 비추어 별도 ticket이 필요한 항목.
|
|
373
|
-
- `open-question` —
|
|
373
|
+
- `open-question` — `## 5. Clarification Items` 에서 분리한 후속 작업 (사용자 답을 그대로 닫지 않고 별도 task 로 진행해야 하는 경우).
|
|
374
374
|
- `manual` — lead가 추가로 식별한 follow-up.
|
|
375
375
|
|
|
376
376
|
규칙:
|