okstra 0.31.0 → 0.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/SKILL.md +3 -3
- package/runtime/agents/workers/report-writer-worker.md +45 -67
- package/runtime/bin/okstra-render-final-report.py +101 -0
- package/runtime/bin/okstra-render-report-views.py +17 -10
- package/runtime/bin/okstra-token-usage.py +3 -1
- package/runtime/python/okstra_ctl/final_report_schema.py +253 -0
- package/runtime/python/okstra_ctl/render_final_report.py +201 -0
- package/runtime/python/okstra_ctl/report_views.py +108 -305
- package/runtime/python/okstra_ctl/wizard.py +16 -5
- package/runtime/python/okstra_token_usage/__init__.py +5 -1
- package/runtime/python/okstra_token_usage/cli.py +66 -36
- package/runtime/python/okstra_token_usage/report.py +148 -65
- package/runtime/python/okstra_vendor/__init__.py +37 -0
- package/runtime/python/okstra_vendor/jinja2/__init__.py +38 -0
- package/runtime/python/okstra_vendor/jinja2/_identifier.py +6 -0
- package/runtime/python/okstra_vendor/jinja2/async_utils.py +99 -0
- package/runtime/python/okstra_vendor/jinja2/bccache.py +408 -0
- package/runtime/python/okstra_vendor/jinja2/compiler.py +1998 -0
- package/runtime/python/okstra_vendor/jinja2/constants.py +20 -0
- package/runtime/python/okstra_vendor/jinja2/debug.py +191 -0
- package/runtime/python/okstra_vendor/jinja2/defaults.py +48 -0
- package/runtime/python/okstra_vendor/jinja2/environment.py +1672 -0
- package/runtime/python/okstra_vendor/jinja2/exceptions.py +166 -0
- package/runtime/python/okstra_vendor/jinja2/ext.py +870 -0
- package/runtime/python/okstra_vendor/jinja2/filters.py +1873 -0
- package/runtime/python/okstra_vendor/jinja2/idtracking.py +318 -0
- package/runtime/python/okstra_vendor/jinja2/lexer.py +868 -0
- package/runtime/python/okstra_vendor/jinja2/loaders.py +693 -0
- package/runtime/python/okstra_vendor/jinja2/meta.py +112 -0
- package/runtime/python/okstra_vendor/jinja2/nativetypes.py +130 -0
- package/runtime/python/okstra_vendor/jinja2/nodes.py +1206 -0
- package/runtime/python/okstra_vendor/jinja2/optimizer.py +48 -0
- package/runtime/python/okstra_vendor/jinja2/parser.py +1049 -0
- package/runtime/python/okstra_vendor/jinja2/py.typed +0 -0
- package/runtime/python/okstra_vendor/jinja2/runtime.py +1062 -0
- package/runtime/python/okstra_vendor/jinja2/sandbox.py +436 -0
- package/runtime/python/okstra_vendor/jinja2/tests.py +256 -0
- package/runtime/python/okstra_vendor/jinja2/utils.py +766 -0
- package/runtime/python/okstra_vendor/jinja2/visitor.py +92 -0
- package/runtime/python/okstra_vendor/markupsafe/__init__.py +396 -0
- package/runtime/python/okstra_vendor/markupsafe/_native.py +8 -0
- package/runtime/python/okstra_vendor/markupsafe/py.typed +0 -0
- package/runtime/schemas/final-report-v1.0.schema.json +1391 -0
- package/runtime/skills/okstra-report-writer/SKILL.md +29 -28
- package/runtime/templates/reports/final-report.template.md +370 -411
- package/runtime/templates/reports/report.css +12 -6
- package/runtime/validators/lib/fixtures.sh +7 -7
- package/runtime/validators/validate-report-views.py +24 -153
- package/runtime/validators/validate-run.py +102 -19
- package/src/install.mjs +20 -1
|
@@ -1,162 +1,160 @@
|
|
|
1
|
+
{# OKSTRA Final Report — Jinja2 template (schemas/final-report-v1.0).
|
|
2
|
+
Consumed by scripts/okstra-render-final-report.py against the JSON
|
|
3
|
+
SSOT at runs/<task-type>/reports/final-report-<task-type>-<seq>.data.json.
|
|
4
|
+
Custom filters: format_int, format_usd, format_duration_ms,
|
|
5
|
+
yaml_scalar, yaml_inline_list (defined in render_final_report.py).
|
|
6
|
+
Token Usage cells render as `--` while tokenUsage.*.totalTokens is
|
|
7
|
+
null in Phase 6; Phase 7 mutates the data.json then re-renders. #}
|
|
1
8
|
---
|
|
2
|
-
title:
|
|
3
|
-
id: {{
|
|
4
|
-
tags: {{
|
|
5
|
-
status:
|
|
6
|
-
aliases: {{
|
|
7
|
-
date: {{
|
|
8
|
-
task-id:
|
|
9
|
-
task-group:
|
|
10
|
-
project-id:
|
|
11
|
-
taskType:
|
|
9
|
+
title: {{ frontmatter.title | yaml_scalar }}
|
|
10
|
+
id: {{ frontmatter.id | yaml_scalar }}
|
|
11
|
+
tags: {{ frontmatter.tags | yaml_inline_list }}
|
|
12
|
+
status: {{ frontmatter.status }}
|
|
13
|
+
aliases: {{ frontmatter.aliases | yaml_inline_list }}
|
|
14
|
+
date: {{ frontmatter.date }}
|
|
15
|
+
task-id: {{ frontmatter.taskId | yaml_scalar }}
|
|
16
|
+
task-group: {{ frontmatter.taskGroup | yaml_scalar }}
|
|
17
|
+
project-id: {{ frontmatter.projectId | yaml_scalar }}
|
|
18
|
+
taskType: {{ frontmatter.taskType | yaml_scalar }}
|
|
19
|
+
workerId: {{ frontmatter.workerId | yaml_scalar }}
|
|
12
20
|
---
|
|
13
21
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"Not applicable") is a contract violation that the validator will catch.
|
|
24
|
-
- Section ordering rule: Verdict Card → Approval Block (planning only) →
|
|
25
|
-
Carry-in (only if non-empty) → Summary/Ticket/Status → Token table →
|
|
26
|
-
§1–§7. The reader's first 30 lines must answer "what was decided" and
|
|
27
|
-
"what do I do next"; deep evidence lives further down.
|
|
28
|
-
-->
|
|
29
|
-
|
|
30
|
-
# {{TASK_KEY}} - Multi-Agent Cross Verification Final Report
|
|
31
|
-
|
|
32
|
-
- Created at: {{RUN_TIMESTAMP_ISO}}
|
|
33
|
-
- Task Key: {{TASK_KEY}}
|
|
34
|
-
- Task Type: {{TASK_TYPE}}
|
|
35
|
-
- Report Owner: `Claude lead`
|
|
36
|
-
- Report Author: `<Report writer worker | Claude lead (release-handoff or recorded-fallback only)>`
|
|
37
|
-
- Lead Model: `{{LEAD_MODEL}}`
|
|
38
|
-
- Okstra Version: `{{OKSTRA_VERSION}}`
|
|
22
|
+
# {{ header.taskKey }} - Multi-Agent Cross Verification Final Report
|
|
23
|
+
|
|
24
|
+
- Created at: {{ header.createdAt }}
|
|
25
|
+
- Task Key: {{ header.taskKey }}
|
|
26
|
+
- Task Type: {{ header.taskType }}
|
|
27
|
+
- Report Owner: `{{ header.reportOwner }}`
|
|
28
|
+
- Report Author: `{{ header.reportAuthor }}`
|
|
29
|
+
- Lead Model: `{{ header.leadModel }}`
|
|
30
|
+
- Okstra Version: `{{ header.okstraVersion }}`
|
|
39
31
|
|
|
40
32
|
## Verdict Card
|
|
41
33
|
|
|
42
|
-
한눈에 보는 결과 카드. 본 표의 모든 값은 `## 2. Final Verdict` 및 `## 6. Recommended Next Steps` 의 권위 있는 값과 정확히 일치해야 합니다.
|
|
34
|
+
한눈에 보는 결과 카드. 본 표의 모든 값은 `## 2. Final Verdict` 및 `## 6. Recommended Next Steps` 의 권위 있는 값과 정확히 일치해야 합니다.
|
|
43
35
|
|
|
44
36
|
| 항목 | 값 |
|
|
45
37
|
|------|----|
|
|
46
|
-
| Final Conclusion |
|
|
47
|
-
| Verdict Token |
|
|
48
|
-
| Direction |
|
|
49
|
-
| Approval Required? |
|
|
50
|
-
| Next Step |
|
|
51
|
-
|
|
52
|
-
<!-- RENDER_IF: task-type == implementation-planning -->
|
|
38
|
+
| Final Conclusion | {{ verdictCard.finalConclusion }} |
|
|
39
|
+
| Verdict Token | `{{ verdictCard.verdictToken }}` |
|
|
40
|
+
| Direction | `{{ verdictCard.direction }}` |
|
|
41
|
+
| Approval Required? | `{% if verdictCard.approvalRequired %}yes — User Approval Request 블록 참조{% else %}no{% endif %}` |
|
|
42
|
+
| Next Step | {{ verdictCard.nextStep }} |
|
|
53
43
|
|
|
44
|
+
{% if header.taskType == 'implementation-planning' %}
|
|
54
45
|
## User Approval Request (사용자 승인 게이트)
|
|
55
46
|
|
|
56
47
|
다음 `implementation` run 은 아래 체크박스가 `[x]` 일 때에만 진입할 수 있습니다 (`okstra_ctl.run._validate_approved_plan` 가 line-anchored 정규식으로 검사). `## 5. Clarification Items` 표에서 `Blocks=approval` 인 모든 행이 `resolved` / `obsolete` 가 된 뒤 승인해 주세요.
|
|
57
48
|
|
|
58
|
-
- 승인 체크박스 (사용자가 직접 편집): `- [ ] Approved`
|
|
49
|
+
- 승인 체크박스 (사용자가 직접 편집): `- [{% if approvalBlock.approved %}x{% else %} {% endif %}] Approved`
|
|
59
50
|
- 승인 후 다음 단계 명령 (수동 편집 방식):
|
|
60
|
-
- Claude Code: `/okstra-run task-key={{
|
|
61
|
-
- 별도 터미널: `scripts/okstra.sh --task-key {{
|
|
51
|
+
- Claude Code: `/okstra-run task-key={{ header.taskKey }} task-type=implementation approved-plan=<이 보고서 경로>`
|
|
52
|
+
- 별도 터미널: `scripts/okstra.sh --task-key {{ header.taskKey }} --task-type implementation --approved-plan <이 보고서 경로>`
|
|
62
53
|
- 승인 + 실행 한 번에 (진입 명령 자체를 승인 의사로):
|
|
63
|
-
- Claude Code: `/okstra-run task-key={{
|
|
64
|
-
- 별도 터미널: `scripts/okstra.sh --task-key {{
|
|
54
|
+
- Claude Code: `/okstra-run task-key={{ header.taskKey }} task-type=implementation approved-plan=<이 보고서 경로> approve`
|
|
55
|
+
- 별도 터미널: `scripts/okstra.sh --task-key {{ header.taskKey }} --task-type implementation --approved-plan <이 보고서 경로> --approve`
|
|
65
56
|
- 보류·거부: 체크박스를 `[ ]` 로 두고 `--approve` 를 사용하지 마세요. 필요 변경은 `## 5.` 표에 `Blocks=approval` 행으로 등록한 뒤 같은 phase 를 재실행합니다.
|
|
66
57
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<!-- RENDER_IF: CLARIFICATION_RESPONSE_RELATIVE_PATH is non-empty
|
|
70
|
-
When empty, DELETE this entire `## 0.` heading and body. The validator
|
|
71
|
-
fails an empty Section 0 stub ("No prior clarification was provided"). -->
|
|
72
|
-
|
|
58
|
+
{% endif %}
|
|
59
|
+
{% if clarificationCarryIn and clarificationCarryIn.sourceFile %}
|
|
73
60
|
## 0. Clarification Response Carried In From Previous Run
|
|
74
61
|
|
|
75
|
-
- Source file: `{{
|
|
62
|
+
- Source file: `{{ clarificationCarryIn.sourceFile }}`
|
|
76
63
|
- 이전 보고서의 `## 5. Clarification Items` 표 매 행(`C-001`, `C-002`, …) 을 새 증거에 비추어 검토하고, 각 행의 `Status` 를 `resolved` 또는 `obsolete` 로 갱신한 뒤 본 run 의 `## 5.` 표에 carry-in 합니다. 해소 근거(파일:라인 / 로그 / 워커 결과) 를 함께 인용합니다.
|
|
77
64
|
|
|
78
|
-
|
|
79
|
-
|
|
65
|
+
{% endif %}
|
|
80
66
|
## Summary of the Problem or Verification Target
|
|
81
67
|
|
|
82
68
|
3~5 개 row 로 핵심 문제·요구사항·검증 대상을 표로 정리합니다. brief, 소스 자료, worker 결과를 근거로 작성합니다.
|
|
83
69
|
|
|
84
70
|
| ID | Ticket ID | 한 줄 요약 | 출처 (brief/source/worker) |
|
|
85
71
|
|----|-----------|------------|----------------------------|
|
|
86
|
-
|
|
72
|
+
{% for row in summary -%}
|
|
73
|
+
| {{ row.id }} | `{{ row.ticketId }}` | {{ row.summary }} | {{ row.source }} |
|
|
74
|
+
{% endfor %}
|
|
87
75
|
|
|
76
|
+
{% if ticketCoverage.omit %}
|
|
77
|
+
{# Ticket Coverage omitted entirely — release-handoff / final-verification #}
|
|
78
|
+
{%- else %}
|
|
88
79
|
## Ticket Coverage
|
|
89
80
|
|
|
90
81
|
본 run 이 다룬 ticket 의 역방향 인덱스. 본문 항목들은 모두 `Ticket ID` 컬럼 또는 `[TICKETID: <id>]` 태그로 ticket 과 묶여 있습니다.
|
|
91
82
|
|
|
92
|
-
|
|
93
|
-
-
|
|
94
|
-
|
|
83
|
+
{% if ticketCoverage.singleTicket -%}
|
|
84
|
+
- Single ticket run: {{ ticketCoverage.singleTicket }}
|
|
85
|
+
{%- else %}
|
|
95
86
|
| Ticket ID | 등장 섹션 | 관련 항목 IDs |
|
|
96
87
|
|-----------|-----------|---------------|
|
|
97
|
-
|
|
88
|
+
{% for row in ticketCoverage.rows -%}
|
|
89
|
+
| `{{ row.ticketId }}` | `{{ row.sections }}` | `{{ row.relatedIds }}` |
|
|
90
|
+
{% endfor %}
|
|
91
|
+
{%- endif %}
|
|
98
92
|
|
|
99
|
-
규칙: `Ticket ID` 는 본문에서 등장한 ticket 키와 정확히 동일 문자열. `Issue / Ticket` 이 비어 폴백된 경우 `Task ID` 값을 prefix 없이 그대로 (예: `8852`). 식별 불가는 `unknown`.
|
|
93
|
+
규칙: `Ticket ID` 는 본문에서 등장한 ticket 키와 정확히 동일 문자열. `Issue / Ticket` 이 비어 폴백된 경우 `Task ID` 값을 prefix 없이 그대로 (예: `8852`). 식별 불가는 `unknown`.
|
|
100
94
|
|
|
95
|
+
{% endif %}
|
|
101
96
|
## Execution Status by Agent
|
|
102
97
|
|
|
103
98
|
각 worker 의 status, 배정 모델, key finding 을 한 표에 모읍니다. worker 산출물을 근거 없는 주장으로 대체하지 않습니다.
|
|
104
99
|
|
|
105
|
-
|
|
100
|
+
| Agent | Role | Model | Status | 처리 토큰 | 환산 토큰 | 비용 (USD) | Duration | Summary of Key Findings |
|
|
101
|
+
|-------|------|-------|--------|-----------|-----------|------------|----------|-------------------------|
|
|
102
|
+
{% for row in executionStatus -%}
|
|
103
|
+
| {{ row.agent }} | {{ row.role }} | {{ row.model }} | {{ row.status }} | {{ row.totalTokens | format_int }}{% if row.cliTotalTokens %} (CLI: {{ row.cliTotalTokens | format_int }}){% endif %} | {{ row.billableTokens | format_int }} | {{ row.costUsd | format_usd }}{% if row.cliCostUsd %} (+ CLI {{ row.cliCostUsd | format_usd }}){% endif %} | {{ row.durationMs | format_duration_ms }} | {{ row.summary }} |
|
|
104
|
+
{% endfor %}
|
|
106
105
|
|
|
107
106
|
## Token Usage Summary
|
|
108
107
|
|
|
109
108
|
| 항목 | 처리 토큰 | 환산 토큰 (input 기준) | 비용 (USD) |
|
|
110
109
|
|------|-----------|------------------------|------------|
|
|
111
|
-
| Lead | `{{
|
|
112
|
-
| Worker 합계 | `{{
|
|
113
|
-
| **전체 합계** | **`{{
|
|
114
|
-
| Codex/Gemini CLI 추가 비용 | | | `{{
|
|
115
|
-
|
|
116
|
-
<!--
|
|
117
|
-
환산식 설명·"읽는 법"·캐시 가중치 등은 `docs/kr/architecture.md#token-accounting`
|
|
118
|
-
및 audit 사이드카에서 참조하세요. 본문 가독성 회복을 위해 인용구는 제거했습니다.
|
|
119
|
-
|
|
120
|
-
placeholders 정책:
|
|
121
|
-
- Phase 6 시점에는 10 개 `{{...}}` 토큰을 verbatim 으로 둡니다.
|
|
122
|
-
- Phase 7 의 `okstra-token-usage.py --substitute-final-report` 가 치환합니다.
|
|
123
|
-
- 임의 값 (`0` / `N/A` / `--` / `not-collected` / `pending`) 으로 대체 금지.
|
|
124
|
-
Validator 가 치환 실패와 임의 값 모두 fail 합니다.
|
|
125
|
-
-->
|
|
110
|
+
| Lead | `{{ tokenUsage.lead.totalTokens | format_int }}` | `{{ tokenUsage.lead.billableTokens | format_int }}` | `{{ tokenUsage.lead.costUsd | format_usd }}` |
|
|
111
|
+
| Worker 합계 | `{{ tokenUsage.worker.totalTokens | format_int }}` | `{{ tokenUsage.worker.billableTokens | format_int }}` | `{{ tokenUsage.worker.costUsd | format_usd }}` |
|
|
112
|
+
| **전체 합계** | **`{{ tokenUsage.grand.totalTokens | format_int }}`** | **`{{ tokenUsage.grand.billableTokens | format_int }}`** | **`{{ tokenUsage.grand.costUsd | format_usd }}`** |
|
|
113
|
+
| Codex/Gemini CLI 추가 비용 | | | `{{ tokenUsage.cli.costUsd | format_usd }}` |
|
|
126
114
|
|
|
127
|
-
|
|
115
|
+
{# Phase 6 시점에는 numeric cells 가 null → 모두 `--` 로 렌더링.
|
|
116
|
+
Phase 7 의 okstra-token-usage.py 가 data.json 의 tokenUsage 를 채우고
|
|
117
|
+
이 renderer 를 재호출하여 최종 markdown 을 다시 생성합니다. #}
|
|
128
118
|
|
|
129
|
-
|
|
119
|
+
## 1. Cross Verification Results
|
|
130
120
|
|
|
131
|
-
|
|
121
|
+
{% if crossVerification.roundHistory and not crossVerification.roundHistory.disabled -%}
|
|
122
|
+
### 1.0 Round History
|
|
132
123
|
|
|
133
124
|
| Round | inputQueueSize | resolvedCount | carriedForwardCount | dispatches (worker:status:durationMs) | skippedWorkers (worker:reason) |
|
|
134
125
|
|-------|----------------|---------------|----------------------|----------------------------------------|---------------------------------|
|
|
135
|
-
|
|
136
|
-
|
|
|
126
|
+
{% for row in crossVerification.roundHistory.rounds -%}
|
|
127
|
+
| {{ row.round }} | {{ row.inputQueueSize }} | {{ row.resolvedCount }} | {{ row.carriedForwardCount }} | {{ row.dispatches }} | {{ row.skippedWorkers }} |
|
|
128
|
+
{% endfor %}
|
|
137
129
|
|
|
138
|
-
- `round2SkippedReason`: `
|
|
139
|
-
- 실행된 round 수가 0 (Round 0 에서 모든 finding 이 곧장 full-consensus) 이면 표 대신 한 줄 — `- Round 0 grouping 에서 모든 finding 이 합의되어 재검증 라운드가 실행되지 않았습니다.`
|
|
130
|
+
- `round2SkippedReason`: `{{ crossVerification.roundHistory.round2SkippedReason }}` ← 값은 `queue-empty | max-rounds-1 | all-reverify-non-result | not-skipped | convergence-disabled | single-analyser-only` 중 하나.
|
|
140
131
|
|
|
132
|
+
{% endif %}
|
|
141
133
|
### 1.1 Consensus
|
|
142
134
|
|
|
135
|
+
{% if crossVerification.consensus | length == 0 -%}
|
|
136
|
+
- 합의 항목 없음.
|
|
137
|
+
{%- else %}
|
|
143
138
|
| ID | Ticket ID | Statement | Source items (worker:item) | Evidence (path:line / log / worker report) |
|
|
144
139
|
|----|-----------|-----------|----------------------------|---------------------------------------------|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
140
|
+
{% for row in crossVerification.consensus -%}
|
|
141
|
+
| {{ row.id }} | `{{ row.ticketId }}` | {{ row.statement }} | {{ row.sourceItems | join(', ') }} | {{ row.evidence }} |
|
|
142
|
+
{% endfor %}
|
|
143
|
+
{%- endif %}
|
|
148
144
|
|
|
149
|
-
`Source items` 규칙: 본 합의 row 가 어느 워커의 어느 항목들에서 합성됐는지를 `<worker>:<item-id>` 페어 콤마-리스트로 적습니다.
|
|
145
|
+
`Source items` 규칙: 본 합의 row 가 어느 워커의 어느 항목들에서 합성됐는지를 `<worker>:<item-id>` 페어 콤마-리스트로 적습니다. 자세한 정책은 `prompts/profiles/_common-contract.md` "Cross-worker traceability" SSOT.
|
|
150
146
|
|
|
151
147
|
### 1.2 Differences
|
|
152
148
|
|
|
149
|
+
{% if crossVerification.differences | length == 0 -%}
|
|
150
|
+
- 유의미한 차이 없음. 1.1 Consensus 가 그대로 유효합니다.
|
|
151
|
+
{%- else %}
|
|
153
152
|
| ID | Ticket ID | Disagreement | Workers (position + item) | Evidence |
|
|
154
153
|
|----|-----------|--------------|---------------------------|----------|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
`Workers (position + item)` 규칙: 1.1 의 `Source items` 와 동일한 `<worker>:<item-id>` 형식이되 워커마다 `(<position>)` 라벨 (`A` / `B` / `-` 등) 을 함께 적어 어느 워커가 어느 입장을 취했는지 표시합니다. 해당 plan item 에 의견을 내지 않은 워커는 `<worker>:--` 로 기록합니다.
|
|
154
|
+
{% for row in crossVerification.differences -%}
|
|
155
|
+
| {{ row.id }} | `{{ row.ticketId }}` | {{ row.disagreement }} | {% for w in row.workersPosition %}{{ w.worker }}:{{ w.itemId }} ({{ w.position }}){% if not loop.last %} / {% endif %}{% endfor %} | {{ row.evidence }} |
|
|
156
|
+
{% endfor %}
|
|
157
|
+
{%- endif %}
|
|
160
158
|
|
|
161
159
|
## 2. Final Verdict
|
|
162
160
|
|
|
@@ -164,469 +162,430 @@ placeholders 정책:
|
|
|
164
162
|
|
|
165
163
|
| 항목 | 값 |
|
|
166
164
|
|------|----|
|
|
167
|
-
| Final Conclusion |
|
|
168
|
-
| Verdict Token |
|
|
169
|
-
| Direction |
|
|
170
|
-
| 근거 요약 |
|
|
171
|
-
| 다음 단계 |
|
|
165
|
+
| Final Conclusion | {{ finalVerdict.finalConclusion }} |
|
|
166
|
+
| Verdict Token | `{{ finalVerdict.verdictToken }}` |
|
|
167
|
+
| Direction | `{{ finalVerdict.direction }}` |
|
|
168
|
+
| 근거 요약 | {{ finalVerdict.rationaleRowIds | join(', ') }} |
|
|
169
|
+
| 다음 단계 | {{ finalVerdict.nextStep }} |
|
|
172
170
|
|
|
173
171
|
## 3. Evidence and Detailed Analysis
|
|
174
172
|
|
|
175
173
|
### 3.1 Primary Evidence
|
|
176
174
|
|
|
175
|
+
{% if evidence.primary | length == 0 -%}
|
|
176
|
+
- 주 증거 없음.
|
|
177
|
+
{%- else %}
|
|
177
178
|
| ID | Ticket ID | Evidence | Source items (worker:item) | Source (path:line / log) |
|
|
178
179
|
|----|-----------|----------|----------------------------|---------------------------|
|
|
179
|
-
|
|
180
|
+
{% for row in evidence.primary -%}
|
|
181
|
+
| {{ row.id }} | `{{ row.ticketId }}` | {{ row.evidence }} | {{ row.sourceItems | join(', ') }} | {{ row.source }} |
|
|
182
|
+
{% endfor %}
|
|
183
|
+
{%- endif %}
|
|
180
184
|
|
|
181
|
-
`Source items` 컬럼 규칙은 §1.1 과
|
|
185
|
+
`Source items` 컬럼 규칙은 §1.1 과 동일.
|
|
182
186
|
|
|
183
187
|
### 3.2 Secondary Evidence or Alternate Interpretations
|
|
184
188
|
|
|
189
|
+
{% if not evidence.secondary or evidence.secondary | length == 0 -%}
|
|
190
|
+
- 보조 증거 또는 대안 해석 없음.
|
|
191
|
+
{%- else %}
|
|
185
192
|
| ID | Ticket ID | Hypothesis or supporting evidence | Source / confidence |
|
|
186
193
|
|----|-----------|-----------------------------------|---------------------|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
194
|
+
{% for row in evidence.secondary -%}
|
|
195
|
+
| {{ row.id }} | `{{ row.ticketId }}` | {{ row.hypothesis }} | {{ row.confidence }} |
|
|
196
|
+
{% endfor %}
|
|
197
|
+
{%- endif %}
|
|
190
198
|
|
|
191
199
|
## 4. Missing Information and Risks
|
|
192
200
|
|
|
201
|
+
{% if missingInformation | length == 0 -%}
|
|
202
|
+
- 누락된 정보·위험 없음.
|
|
203
|
+
{%- else %}
|
|
193
204
|
| ID | Ticket ID | Item | Risk if ignored | Mitigation Owner |
|
|
194
205
|
|----|-----------|------|-----------------|------------------|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
<!-- RENDER_IF: task-type == implementation-planning
|
|
200
|
-
Delete the entire `## 4.5` block + sub-sections otherwise.
|
|
201
|
-
|
|
202
|
-
Validator (validators/validate-run.py PLANNING_REQUIRED_SECTIONS) does
|
|
203
|
-
substring matching for these 9 English keywords in order:
|
|
204
|
-
Option Candidates, Trade-off, Recommended Option,
|
|
205
|
-
Stepwise Execution Order, Dependency, Validation Checklist, Rollback,
|
|
206
|
-
User Approval Request, Plan Body Verification
|
|
207
|
-
The first 7 + 9th live below; "User Approval Request" is satisfied by
|
|
208
|
-
the top-of-report Approval block heading. Do NOT recreate a §4.5.8 stub
|
|
209
|
-
in body — validator now fails reports that contain one. -->
|
|
206
|
+
{% for row in missingInformation -%}
|
|
207
|
+
| {{ row.id }} | `{{ row.ticketId }}` | {{ row.item }} | {{ row.risk }} | {{ row.owner }} |
|
|
208
|
+
{% endfor %}
|
|
209
|
+
{%- endif %}
|
|
210
210
|
|
|
211
|
+
{% if header.taskType == 'implementation-planning' %}
|
|
211
212
|
## 4.5 Implementation Plan Deliverables
|
|
212
213
|
|
|
213
214
|
### 4.5.1 Option Candidates (옵션 후보)
|
|
214
215
|
|
|
215
|
-
|
|
216
|
+
{% for opt in implementationPlanning.optionCandidates %}
|
|
217
|
+
**{{ opt.name }}**
|
|
216
218
|
|
|
217
|
-
-
|
|
219
|
+
- File Structure:
|
|
218
220
|
|
|
219
221
|
| ID | Ticket ID | Action | Path (and line-range) | Change summary |
|
|
220
222
|
|----|-----------|--------|------------------------|----------------|
|
|
221
|
-
|
|
223
|
+
{% for fs in opt.fileStructure -%}
|
|
224
|
+
| {{ fs.id }} | `{{ fs.ticketId }}` | {{ fs.action }} | `{{ fs.path }}` | {{ fs.summary }} |
|
|
225
|
+
{% endfor %}
|
|
226
|
+
|
|
227
|
+
- 영향 인터페이스 / 공개 계약 / 다운스트림 소비자: {{ opt.interfaces }}
|
|
228
|
+
- 폭발 반경 추정: {{ opt.blastRadius }}
|
|
222
229
|
|
|
223
|
-
|
|
224
|
-
- 폭발 반경 추정 (units, configs, deployment manifests, data migrations).
|
|
230
|
+
{% endfor %}
|
|
225
231
|
|
|
226
232
|
### 4.5.2 Trade-off Matrix (트레이드오프 매트릭스)
|
|
227
233
|
|
|
228
234
|
| Option | Complexity | Risk | Reversibility | Test Coverage Cost | Rollout Cost |
|
|
229
235
|
|--------|-----------|------|---------------|--------------------|--------------|
|
|
230
|
-
|
|
236
|
+
{% for row in implementationPlanning.tradeoffMatrix -%}
|
|
237
|
+
| {{ row.option }} | {{ row.complexity }} | {{ row.risk }} | {{ row.reversibility }} | {{ row.testCoverageCost }} | {{ row.rolloutCost }} |
|
|
238
|
+
{% endfor %}
|
|
231
239
|
|
|
232
240
|
### 4.5.3 Recommended Option (권장 옵션)
|
|
233
241
|
|
|
234
242
|
| 항목 | 값 |
|
|
235
243
|
|------|----|
|
|
236
|
-
| Recommended Option |
|
|
237
|
-
| 핵심 이유 |
|
|
238
|
-
| 근거 (Trade-off 행 / 원칙) |
|
|
239
|
-
| 채택되지 않은 옵션 요약 |
|
|
244
|
+
| Recommended Option | {{ implementationPlanning.recommendedOption.name }} |
|
|
245
|
+
| 핵심 이유 | {{ implementationPlanning.recommendedOption.coreReason }} |
|
|
246
|
+
| 근거 (Trade-off 행 / 원칙) | {{ implementationPlanning.recommendedOption.rationale }} |
|
|
247
|
+
| 채택되지 않은 옵션 요약 | {{ implementationPlanning.recommendedOption.rejectedSummary }} |
|
|
240
248
|
|
|
241
249
|
### 4.5.4 Stepwise Execution Order (단계별 실행 순서)
|
|
242
250
|
|
|
243
251
|
| Step | Ticket ID | Action (≤ 5min) | Files | Command / Test | Expected outcome |
|
|
244
252
|
|------|-----------|------------------|-------|----------------|-------------------|
|
|
245
|
-
|
|
253
|
+
{% for row in implementationPlanning.stepwiseExecution -%}
|
|
254
|
+
| {{ row.step }} | `{{ row.ticketId }}` | {{ row.action }} | `{{ row.files }}` | `{{ row.commandOrTest }}` | {{ row.expectedOutcome }} |
|
|
255
|
+
{% endfor %}
|
|
246
256
|
|
|
247
|
-
규칙: 한 step 은 약 2~5 분. 모든 step 은 정확한 파일 경로와 명령어 포함.
|
|
257
|
+
규칙: 한 step 은 약 2~5 분. 모든 step 은 정확한 파일 경로와 명령어 포함.
|
|
248
258
|
|
|
249
259
|
### 4.5.5 Dependency / Migration Risk (의존성·마이그레이션 위험)
|
|
250
260
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
261
|
+
{% if implementationPlanning.dependencyMigrationRisk | length == 0 -%}
|
|
262
|
+
- 의존성·마이그레이션 위험 없음.
|
|
263
|
+
{%- else %}
|
|
264
|
+
| ID | Kind | Item | 영향 | 완화 / 선행 작업 |
|
|
265
|
+
|----|------|------|------|------------------|
|
|
266
|
+
{% for row in implementationPlanning.dependencyMigrationRisk -%}
|
|
267
|
+
| {{ row.id }} | {{ row.kind }} | {{ row.item }} | {{ row.impact }} | {{ row.mitigation }} |
|
|
268
|
+
{% endfor %}
|
|
269
|
+
{%- endif %}
|
|
256
270
|
|
|
257
271
|
### 4.5.6 Validation Checklist (검증 체크리스트)
|
|
258
272
|
|
|
259
273
|
| Phase | Ticket ID | Check | Command / Observation | Expected outcome |
|
|
260
274
|
|-------|-----------|-------|------------------------|-------------------|
|
|
261
|
-
|
|
262
|
-
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
추상적 서술 금지. 모든 row 는 명령어 또는 관찰 가능한 결과를 포함.
|
|
275
|
+
{% for row in implementationPlanning.validationChecklist -%}
|
|
276
|
+
| {{ row.phase }} | `{{ row.ticketId }}` | {{ row.check }} | `{{ row.commandOrObservation }}` | {{ row.expectedOutcome }} |
|
|
277
|
+
{% endfor %}
|
|
266
278
|
|
|
267
279
|
### 4.5.7 Rollback Strategy (롤백 전략)
|
|
268
280
|
|
|
269
|
-
| ID | Step | Action
|
|
270
|
-
|
|
271
|
-
|
|
281
|
+
| ID | Step | Action | Trigger signal | 확인 방법 |
|
|
282
|
+
|----|------|--------|----------------|-----------|
|
|
283
|
+
{% for row in implementationPlanning.rollbackStrategy -%}
|
|
284
|
+
| {{ row.id }} | {{ row.step }} | `{{ row.action }}` | {{ row.triggerSignal }} | `{{ row.verificationMethod }}` |
|
|
285
|
+
{% endfor %}
|
|
272
286
|
|
|
273
287
|
### 4.5.9 Plan Body Verification (계획 본문 검증)
|
|
274
288
|
|
|
275
|
-
Phase 6 에서 report-writer 가 합성한 4.5 본문을 lead 가 plan-item 단위로 워커들에게 다시 던지고
|
|
289
|
+
Phase 6 에서 report-writer 가 합성한 4.5 본문을 lead 가 plan-item 단위로 워커들에게 다시 던지고 평결을 수집한 결과.
|
|
276
290
|
|
|
277
|
-
- **Round count**:
|
|
278
|
-
- **Gate result**:
|
|
279
|
-
- `passed` → 상단 `User Approval Request` 체크박스 라인 렌더.
|
|
280
|
-
- `passed-with-dissent` → 체크박스 렌더 + 반대 의견은 아래 `Dissent log` 에 기록.
|
|
281
|
-
- `blocked-by-disagreement` → 체크박스 라인 **렌더하지 않음**. majority DISAGREE 인 plan item 마다 `## 5.` 에 `Blocks=approval` row 추가.
|
|
282
|
-
- `aborted-non-result` → 워커 dispatch 가 모두 non-result. 체크박스 라인 렌더하지 않음 + `## 5.` 에 "plan-body verification could not run" row.
|
|
291
|
+
- **Round count**: `{{ implementationPlanning.planBodyVerification.roundCount }}`
|
|
292
|
+
- **Gate result**: `{{ implementationPlanning.planBodyVerification.gateResult }}`
|
|
283
293
|
|
|
284
294
|
#### Verdict summary
|
|
285
295
|
|
|
286
|
-
각 plan item 1 행. `Plan item` 열은 `P-Opt-<N>` / `P-Step-<N>` / `P-Dep-<N>` / `P-Val-<N>` / `P-Rb-<N>` prefix. `Section` 열은 4.5 내부 sub-section 번호. 워커별 평결은 아래 `Verdict details` 표로 분리합니다 (워커 수에 비례해 가로 폭이 폭발하던 단일 wide 표를 두 개로 쪼개 시인성을 회복).
|
|
287
|
-
|
|
288
296
|
| Plan item | Ticket ID | Section | Classification |
|
|
289
297
|
|-----------|-----------|---------|----------------|
|
|
290
|
-
|
|
291
|
-
|
|
|
292
|
-
|
|
293
|
-
- `Classification` ∈ `{full-consensus, partial-consensus, worker-unique, majority-disagree → C-<N>}`.
|
|
294
|
-
- `majority-disagree → C-<N>` 의 `C-<N>` 은 `## 5. Clarification Items` 의 row ID 와 1:1 일치해야 합니다.
|
|
298
|
+
{% for row in implementationPlanning.planBodyVerification.verdictSummary -%}
|
|
299
|
+
| {{ row.planItem }} | `{{ row.ticketId }}` | {{ row.section }} | {{ row.classification }} |
|
|
300
|
+
{% endfor %}
|
|
295
301
|
|
|
296
302
|
#### Verdict details
|
|
297
303
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
| P-Opt-1 | codex-worker | AGREE | -- | |
|
|
304
|
-
| P-Step-3 | claude-worker | DISAGREE | a | 참조한 `crates/.../mod.rs:120` 가 없음 |
|
|
305
|
-
| P-Step-3 | codex-worker | DISAGREE | a | 동일 — 파일 path 미존재 |
|
|
306
|
-
| P-Step-3 | gemini-worker | SUPPLEMENT | -- | 대체 step 제안 (Dissent log 참조) |
|
|
304
|
+
| Plan item | Worker | Verdict | Breakage kind | Note |
|
|
305
|
+
|-----------|--------|---------|---------------|------|
|
|
306
|
+
{% for row in implementationPlanning.planBodyVerification.verdictDetails -%}
|
|
307
|
+
| {{ row.planItem }} | {{ row.worker }} | {{ row.verdict }} | {{ row.breakageKind or '--' }} | {{ row.note or '' }} |
|
|
308
|
+
{% endfor %}
|
|
307
309
|
|
|
308
310
|
#### Dissent log
|
|
309
311
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
Delete the entire `## 4.6` block + sub-sections otherwise. -->
|
|
312
|
+
{% if implementationPlanning.planBodyVerification.dissentLog | length == 0 -%}
|
|
313
|
+
- 반대 의견 없음.
|
|
314
|
+
{%- else %}
|
|
315
|
+
{% for row in implementationPlanning.planBodyVerification.dissentLog -%}
|
|
316
|
+
- **{{ row.planItem }}**: `{{ row.workerRole }}` — {{ row.body }}
|
|
317
|
+
{% endfor %}
|
|
318
|
+
{%- endif %}
|
|
318
319
|
|
|
320
|
+
{% endif %}
|
|
321
|
+
{% if header.taskType == 'release-handoff' %}
|
|
319
322
|
## 4.6 Release Handoff Deliverables
|
|
320
323
|
|
|
321
|
-
git/gh mutating 명령이 실행된 phase 의 감사 기록.
|
|
324
|
+
git/gh mutating 명령이 실행된 phase 의 감사 기록.
|
|
322
325
|
|
|
323
|
-
### 4.6.1 Source Verification Report
|
|
326
|
+
### 4.6.1 Source Verification Report
|
|
324
327
|
|
|
325
|
-
- Path (project-relative):
|
|
326
|
-
- Quoted `Verdict Token` row from that report's `## 2.` table
|
|
327
|
-
>
|
|
328
|
-
- 원본 `Verdict Token` 값이 `accepted` 가 아니면 본 run 은 실행되지 않아야 했습니다. self-review 에서 contract-violated 처리하고 routing 을 `final-verification` 으로 되돌립니다.
|
|
328
|
+
- Path (project-relative): `{{ releaseHandoff.sourceVerificationReport.path }}`
|
|
329
|
+
- Quoted `Verdict Token` row from that report's `## 2.` table:
|
|
330
|
+
> {{ releaseHandoff.sourceVerificationReport.verdictTokenQuote }}
|
|
329
331
|
|
|
330
332
|
### 4.6.2 Feature Branch & Working-Tree State (run 시작 시점)
|
|
331
333
|
|
|
332
|
-
- Feature branch
|
|
334
|
+
- Feature branch: `{{ releaseHandoff.featureBranchState.branchName }}`
|
|
333
335
|
- `git status --short` 출력:
|
|
334
336
|
```
|
|
335
|
-
|
|
337
|
+
{{ releaseHandoff.featureBranchState.gitStatusShort }}
|
|
336
338
|
```
|
|
337
|
-
- 기존 PR 존재
|
|
339
|
+
- 기존 PR 존재 여부: `{{ releaseHandoff.featureBranchState.existingPrUrl or '(none)' }}`
|
|
338
340
|
|
|
339
341
|
### 4.6.3 User Selections (메뉴 응답 기록)
|
|
340
342
|
|
|
341
343
|
| 질문 ID | 질문 본문 | 사용자 응답 (원문) | 응답이 가능한 보기 |
|
|
342
344
|
|---------|-----------|--------------------|--------------------|
|
|
343
|
-
| H1 | 어떤 작업을 실행할까요? |
|
|
344
|
-
| H2 | PR base
|
|
345
|
-
| H3 |
|
|
346
|
-
|
|
347
|
-
H1 = `skip` 이거나 H3 = `cancel` 인 경우 4.6.4 ~ 4.6.6 은 빈 결과로 채우고 (mutating 명령 미실행) 4.6.7 routing 만 채웁니다.
|
|
345
|
+
| H1 | 어떤 작업을 실행할까요? | `{{ releaseHandoff.userSelections.h1 }}` | `local only` / `push + PR` / `skip` |
|
|
346
|
+
| H2 | PR base 브랜치 (H1=`push + PR` 인 경우) | `{{ releaseHandoff.userSelections.h2 or '(n/a)' }}` | staging / preprod / prod / main / dev / 사용자 입력 |
|
|
347
|
+
| H3 | PR title/body 초안 처리 | `{{ releaseHandoff.userSelections.h3 }}` | `use as-is` / `edit then proceed` / `cancel` |
|
|
348
348
|
|
|
349
|
-
### 4.6.4 Executed Commands
|
|
350
|
-
|
|
351
|
-
- Mutating commands: 정확한 명령행 / exit code / 한 줄 stdout 요약을 한 행씩 모두 기록 (누락은 contract-violated).
|
|
352
|
-
- Read-only inspection commands: 요약 또는 명령행 목록만으로 충분.
|
|
349
|
+
### 4.6.4 Executed Commands
|
|
353
350
|
|
|
351
|
+
{% if releaseHandoff.executedCommands | length == 0 -%}
|
|
352
|
+
- (mutating 명령 미실행 — H1=`skip` 또는 H3=`cancel`)
|
|
353
|
+
{%- else %}
|
|
354
354
|
| # | command (verbatim) | exit code | stdout/stderr 요약 |
|
|
355
355
|
|---|---------------------|-----------|--------------------|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
-
|
|
379
|
-
|
|
380
|
-
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
### 4.6.
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
356
|
+
{% for row in releaseHandoff.executedCommands -%}
|
|
357
|
+
| {{ row.number }} | `{{ row.command }}` | `{{ row.exitCode }}` | {{ row.outputSummary }} |
|
|
358
|
+
{% endfor %}
|
|
359
|
+
{%- endif %}
|
|
360
|
+
|
|
361
|
+
### 4.6.5 Commit List
|
|
362
|
+
|
|
363
|
+
{% if releaseHandoff.commitList.empty -%}
|
|
364
|
+
- No implementation commits found; release-handoff is blocked.
|
|
365
|
+
{%- else %}
|
|
366
|
+
| Short SHA | Full SHA | Subject | Files |
|
|
367
|
+
|-----------|----------|---------|-------|
|
|
368
|
+
{% for row in releaseHandoff.commitList -%}
|
|
369
|
+
| `{{ row.shortSha }}` | `{{ row.fullSha }}` | {{ row.subject }} | {{ row.files }} |
|
|
370
|
+
{% endfor %}
|
|
371
|
+
{%- endif %}
|
|
372
|
+
|
|
373
|
+
### 4.6.6 Merge Conflict Probe
|
|
374
|
+
|
|
375
|
+
{% if releaseHandoff.mergeConflictProbe.kind == 'not-run' -%}
|
|
376
|
+
- Not run (user picked local only or skip).
|
|
377
|
+
{%- elif releaseHandoff.mergeConflictProbe.kind == 'clean' -%}
|
|
378
|
+
- Clean — no conflicts against {{ releaseHandoff.mergeConflictProbe.baseBranch }} at {{ releaseHandoff.mergeConflictProbe.baseSha }}.
|
|
379
|
+
{%- else -%}
|
|
380
|
+
- Conflicts detected against {{ releaseHandoff.mergeConflictProbe.baseBranch }} at {{ releaseHandoff.mergeConflictProbe.baseSha }}; user chose {{ releaseHandoff.mergeConflictProbe.userChoice }}. Conflicting paths: {{ releaseHandoff.mergeConflictProbe.conflictingPaths | join(', ') }}.
|
|
381
|
+
{%- endif %}
|
|
382
|
+
|
|
383
|
+
### 4.6.7 Pull Request Outcome
|
|
384
|
+
|
|
385
|
+
{% if releaseHandoff.pullRequestOutcome.kind == 'no-action' -%}
|
|
386
|
+
- No PR action requested.
|
|
387
|
+
{%- elif releaseHandoff.pullRequestOutcome.kind == 'created' -%}
|
|
388
|
+
- PR created: {{ releaseHandoff.pullRequestOutcome.url }} — title: {{ releaseHandoff.pullRequestOutcome.title }} (base: {{ releaseHandoff.pullRequestOutcome.baseBranch }})
|
|
389
|
+
{%- elif releaseHandoff.pullRequestOutcome.kind == 'reused' -%}
|
|
390
|
+
- PR reused: {{ releaseHandoff.pullRequestOutcome.url }}
|
|
391
|
+
{%- else -%}
|
|
392
|
+
- PR creation skipped: {{ releaseHandoff.pullRequestOutcome.reason }}
|
|
393
|
+
{%- endif %}
|
|
394
|
+
|
|
395
|
+
### 4.6.8 Routing Recommendation
|
|
396
|
+
|
|
397
|
+
{{ releaseHandoff.routingRecommendation }}
|
|
398
|
+
|
|
399
|
+
{% endif %}
|
|
400
|
+
{% if header.taskType == 'implementation' %}
|
|
394
401
|
## 4.7 Implementation Deliverables
|
|
395
402
|
|
|
396
|
-
|
|
403
|
+
### 4.7.1 Approved Plan Reference
|
|
397
404
|
|
|
398
|
-
|
|
405
|
+
- Plan file (project-relative): `{{ implementation.approvedPlanReference.planFile }}`
|
|
406
|
+
- Approval evidence:
|
|
407
|
+
> {{ implementation.approvedPlanReference.approvalEvidence }}
|
|
408
|
+
- 본 run 의 `EXECUTOR_WORKTREE_PATH`: `{{ implementation.approvedPlanReference.executorWorktreePath }}`
|
|
409
|
+
- 본 run 의 base ref: `{{ implementation.approvedPlanReference.baseRefSha }}`
|
|
399
410
|
|
|
400
|
-
|
|
401
|
-
- Approval evidence (해당 plan 의 정확한 인용 — `- [x] Approved` 마커 + Section 4.5.3 Recommended Option 한 줄):
|
|
402
|
-
> <원문 인용>
|
|
403
|
-
- 본 run 의 `EXECUTOR_WORKTREE_PATH`: `<absolute path>`
|
|
404
|
-
- 본 run 의 base ref (`{{EXECUTOR_WORKTREE_BASE_REF}}`): `<commit SHA>`
|
|
405
|
-
|
|
406
|
-
### 4.7.2 Commit List (생성된 commit)
|
|
411
|
+
### 4.7.2 Commit List
|
|
407
412
|
|
|
413
|
+
{% if implementation.commitList | length == 0 -%}
|
|
414
|
+
- No implementation commits produced; routing recommendation must be back to implementation-planning.
|
|
415
|
+
{%- else %}
|
|
408
416
|
| # | Short SHA | Full SHA | Plan Step | Subject | Files |
|
|
409
417
|
|---|-----------|----------|-----------|---------|-------|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
418
|
+
{% for row in implementation.commitList -%}
|
|
419
|
+
| {{ row.number }} | `{{ row.shortSha }}` | `{{ row.fullSha }}` | {{ row.planStep }} | {{ row.subject }} | {{ row.files }} |
|
|
420
|
+
{% endfor %}
|
|
421
|
+
{%- endif %}
|
|
413
422
|
|
|
414
|
-
### 4.7.3 Diff Summary
|
|
423
|
+
### 4.7.3 Diff Summary
|
|
415
424
|
|
|
416
425
|
```
|
|
417
|
-
|
|
426
|
+
{{ implementation.diffSummary.rawStat }}
|
|
418
427
|
```
|
|
419
428
|
|
|
420
|
-
다음으로 file-by-file 한 줄 요약 표:
|
|
421
|
-
|
|
422
429
|
| File | Action | Lines (+/-) | Plan step / Out-of-plan |
|
|
423
430
|
|------|--------|-------------|--------------------------|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
-
|
|
453
|
-
-
|
|
454
|
-
-
|
|
455
|
-
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
### 4.7.7 Rollback Verification
|
|
460
|
-
|
|
461
|
-
변경 카테고리별로 다른 강도의 확인. 표 1 행 = 1 카테고리.
|
|
431
|
+
{% for row in implementation.diffSummary.files -%}
|
|
432
|
+
| `{{ row.file }}` | {{ row.action }} | `{{ row.lines }}` | {{ row.planStep }} |
|
|
433
|
+
{% endfor %}
|
|
434
|
+
|
|
435
|
+
### 4.7.4 Out-of-plan Edits
|
|
436
|
+
|
|
437
|
+
{% if implementation.outOfPlanEdits | length == 0 -%}
|
|
438
|
+
- 계획 외 편집 없음.
|
|
439
|
+
{%- else %}
|
|
440
|
+
| ID | File | Rationale | Trigger |
|
|
441
|
+
|----|------|-----------|---------|
|
|
442
|
+
{% for row in implementation.outOfPlanEdits -%}
|
|
443
|
+
| {{ row.id }} | `{{ row.file }}` | {{ row.rationale }} | {{ row.trigger }} |
|
|
444
|
+
{% endfor %}
|
|
445
|
+
{%- endif %}
|
|
446
|
+
|
|
447
|
+
### 4.7.5 Validation Evidence
|
|
448
|
+
|
|
449
|
+
| Phase | Command | Exit code | Output tail | TDD evidence |
|
|
450
|
+
|-------|---------|-----------|-------------|--------------|
|
|
451
|
+
{% for row in implementation.validationEvidence -%}
|
|
452
|
+
| {{ row.phase }} | `{{ row.command }}` | `{{ row.exitCode }}` | {{ row.outputTail }} | {{ row.tddEvidence or '--' }} |
|
|
453
|
+
{% endfor %}
|
|
454
|
+
|
|
455
|
+
### 4.7.6 Verifier Results
|
|
456
|
+
|
|
457
|
+
{% for block in implementation.verifierResults %}
|
|
458
|
+
- **{{ block.verifier }}** — Verdict: `{{ block.verdict }}`
|
|
459
|
+
- Read-only command log: {{ block.readOnlyCommandLog }}
|
|
460
|
+
- Independent validation re-run: {{ block.independentValidationRerun }}
|
|
461
|
+
- Style / lint / type-check: {{ block.styleLintTypecheck or '--' }}
|
|
462
|
+
- Declined fix recommendations: {{ block.declinedFixRecommendations or '- 없음.' }}
|
|
463
|
+
- Discrepancy: {{ block.discrepancy or '- 없음.' }}
|
|
464
|
+
{% endfor %}
|
|
465
|
+
|
|
466
|
+
### 4.7.7 Rollback Verification
|
|
462
467
|
|
|
463
468
|
| Category | Rollback command | Verification | Result |
|
|
464
469
|
|----------|-------------------|---------------|--------|
|
|
465
|
-
|
|
466
|
-
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
dry-run 모드가 없는 stateful 변경은 본 항목을 `unable` 로 적고 `## 6.` 의 첫 항목을 `implementation-planning` 재진입으로 권장해야 합니다.
|
|
470
|
-
|
|
471
|
-
### 4.7.8 Routing Recommendation (다음 phase 라우팅)
|
|
472
|
-
|
|
473
|
-
다음 셋 중 하나의 형식으로 한 줄:
|
|
474
|
-
|
|
475
|
-
- `- Routing: final-verification. All plan steps satisfied; rollback verified; verifier consensus <PASS|CONCERNS>.`
|
|
476
|
-
- `- Routing: error-analysis. <한 줄 — 어떤 결함이 추가 분석을 요구하는지>.`
|
|
477
|
-
- `- Routing: implementation-planning. <한 줄 — 왜 새 plan 이 필요한지 (drift / scope-mismatch / stateful-rollback-gap)>.`
|
|
470
|
+
{% for row in implementation.rollbackVerification -%}
|
|
471
|
+
| {{ row.category }} | `{{ row.rollbackCommand }}` | {{ row.verification }} | `{{ row.result }}` |
|
|
472
|
+
{% endfor %}
|
|
478
473
|
|
|
479
|
-
|
|
474
|
+
### 4.7.8 Routing Recommendation
|
|
480
475
|
|
|
481
|
-
|
|
482
|
-
Delete the entire `## 4.8` block + sub-sections otherwise. -->
|
|
476
|
+
{{ implementation.routingRecommendation }}
|
|
483
477
|
|
|
478
|
+
{% endif %}
|
|
479
|
+
{% if header.taskType == 'final-verification' %}
|
|
484
480
|
## 4.8 Final Verification Deliverables
|
|
485
481
|
|
|
486
|
-
|
|
482
|
+
### 4.8.1 Source Implementation Report
|
|
487
483
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
- Path (project-relative): `<runs/implementation/.../reports/final-report-implementation-<seq>.md>`
|
|
484
|
+
- Path (project-relative): `{{ finalVerification.sourceImplementationReport.path }}`
|
|
491
485
|
- 인용된 commit list / diff summary 요약:
|
|
492
|
-
>
|
|
493
|
-
- 검증 대상 worktree path:
|
|
494
|
-
- run 시작 시 capture 한 head/base SHA:
|
|
486
|
+
> {{ finalVerification.sourceImplementationReport.commitListQuote }}
|
|
487
|
+
- 검증 대상 worktree path: `{{ finalVerification.sourceImplementationReport.worktreePath }}`
|
|
488
|
+
- run 시작 시 capture 한 head/base SHA: `{{ finalVerification.sourceImplementationReport.baseHeadSha }}`
|
|
495
489
|
- `git status --short` (run 시작 시점):
|
|
496
490
|
```
|
|
497
|
-
|
|
491
|
+
{{ finalVerification.sourceImplementationReport.gitStatusShort }}
|
|
498
492
|
```
|
|
499
493
|
|
|
500
|
-
### 4.8.2 Acceptance Blockers
|
|
501
|
-
|
|
502
|
-
비어 있으면 표 대신 `- No acceptance blockers found.` 한 줄. 모든 blocker 는 구체적 artifact (file:line, log, exit code, MCP SELECT 결과) 인용 필수 — 증거 없는 blocker 는 4.8.3 residual risk 로 강등.
|
|
503
|
-
|
|
504
|
-
| ID | Severity | Statement | Evidence (path:line / log / exit code) | Recommended follow-up phase |
|
|
505
|
-
|----|----------|-----------|-----------------------------------------|------------------------------|
|
|
506
|
-
| AB-001 | `critical / major / minor` | <한 줄 결함 요약> | `<file>:<line>` 또는 로그 인용 | `error-analysis` / `implementation-planning` |
|
|
494
|
+
### 4.8.2 Acceptance Blockers
|
|
507
495
|
|
|
508
|
-
|
|
496
|
+
{% if finalVerification.acceptanceBlockers | length == 0 -%}
|
|
497
|
+
- No acceptance blockers found.
|
|
498
|
+
{%- else %}
|
|
499
|
+
| ID | Severity | Statement | Evidence | Recommended follow-up phase |
|
|
500
|
+
|----|----------|-----------|----------|------------------------------|
|
|
501
|
+
{% for row in finalVerification.acceptanceBlockers -%}
|
|
502
|
+
| {{ row.id }} | `{{ row.severity }}` | {{ row.statement }} | {{ row.evidence }} | `{{ row.followUpPhase }}` |
|
|
503
|
+
{% endfor %}
|
|
504
|
+
{%- endif %}
|
|
509
505
|
|
|
510
|
-
|
|
506
|
+
### 4.8.3 Residual Risk
|
|
511
507
|
|
|
508
|
+
{% if finalVerification.residualRisk | length == 0 -%}
|
|
509
|
+
- 추적 대상 잔존 위험 없음.
|
|
510
|
+
{%- else %}
|
|
512
511
|
| ID | Item | Mitigation owner | Escalation trigger |
|
|
513
512
|
|----|------|------------------|---------------------|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
513
|
+
{% for row in finalVerification.residualRisk -%}
|
|
514
|
+
| {{ row.id }} | {{ row.item }} | {{ row.owner }} | {{ row.escalationTrigger }} |
|
|
515
|
+
{% endfor %}
|
|
516
|
+
{%- endif %}
|
|
517
517
|
|
|
518
518
|
### 4.8.4 Validation Evidence (요구사항 커버리지)
|
|
519
519
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
520
|
+
| ID | Requirement (plan/brief 인용) | Artifact | Status |
|
|
521
|
+
|----|--------------------------------|----------|--------|
|
|
522
|
+
{% for row in finalVerification.validationEvidence -%}
|
|
523
|
+
| {{ row.id }} | {{ row.requirement }} | `{{ row.artifact }}` | {{ row.status }} |
|
|
524
|
+
{% endfor %}
|
|
525
525
|
|
|
526
|
-
### 4.8.5 Read-only Command Log
|
|
526
|
+
### 4.8.5 Read-only Command Log
|
|
527
527
|
|
|
528
|
-
|
|
528
|
+
| # | Tier | Command (verbatim) | Exit code | Output tail |
|
|
529
|
+
|---|------|---------------------|-----------|-------------|
|
|
530
|
+
{% for row in finalVerification.readonlyCommandLog -%}
|
|
531
|
+
| {{ row.number }} | {{ row.tier }} | `{{ row.command }}` | `{{ row.exitCode }}` | {{ row.outputTail }} |
|
|
532
|
+
{% endfor %}
|
|
529
533
|
|
|
530
|
-
|
|
531
|
-
|---|------|---------------------|-----------|-------------------------|
|
|
532
|
-
| 1 | 1 | `<plan validation cmd>` | `0` | <인용> |
|
|
533
|
-
| 2 | 2 | `cargo clippy --all-targets -- -D warnings` | `0` | <인용> |
|
|
534
|
+
### 4.8.6 Routing Recommendation
|
|
534
535
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
### 4.8.6 Routing Recommendation (다음 phase 라우팅)
|
|
538
|
-
|
|
539
|
-
`## 2. Final Verdict` 의 `Verdict Token` 과 1:1 대응. 다음 셋 중 하나:
|
|
540
|
-
|
|
541
|
-
- `- Routing: release-handoff. Verdict Token = accepted; PR-ready.`
|
|
542
|
-
- `- Routing: release-handoff with conditions. Verdict Token = conditional-accept; conditions listed in 4.8.2 / 4.8.3 must be resolved before push.`
|
|
543
|
-
- `- Routing: error-analysis (or implementation-planning). Verdict Token = blocked; <blocker AB-?> requires <re-analysis | replan>.`
|
|
544
|
-
|
|
545
|
-
<!-- /RENDER_IF (task-type == final-verification) -->
|
|
536
|
+
{{ finalVerification.routingRecommendation }}
|
|
546
537
|
|
|
538
|
+
{% endif %}
|
|
547
539
|
## 5. Clarification Items
|
|
548
540
|
|
|
549
|
-
다음 run 으로 넘어가기 전에 사용자가 답하거나 자료를 첨부해야 하는 항목을 **한 표 안에서** 추적합니다.
|
|
550
|
-
|
|
551
|
-
작성 원칙:
|
|
552
|
-
|
|
553
|
-
- 개발자가 아닌 사람도 한 번 읽고 무엇을 어디서 가져와야 하는지 이해할 수 있게, 줄임말과 내부 용어 대신 풀어 쓴 문장.
|
|
554
|
-
- 한 행은 "왜 필요한지", "무엇을 묻거나 받아야 하는지", "어떤 형태의 답을 기대하는지" 가 모두 드러나야 함.
|
|
555
|
-
- 항목별 ID (`C-001`, `C-002`, …) 는 run 간 유지. 답변된 항목은 다음 run 에서도 삭제하지 말고 `Status` 만 `resolved` / `obsolete` 로 갱신.
|
|
541
|
+
다음 run 으로 넘어가기 전에 사용자가 답하거나 자료를 첨부해야 하는 항목을 **한 표 안에서** 추적합니다.
|
|
556
542
|
|
|
543
|
+
{% if clarificationItems | length == 0 -%}
|
|
544
|
+
- 추가 정보 요청 없음. Section 2 의 최종 판단이 그대로 유효합니다.
|
|
545
|
+
{%- else %}
|
|
557
546
|
답을 채우신 뒤 같은 phase 를 다시 실행:
|
|
558
547
|
|
|
559
|
-
- Claude Code: `/okstra-run resume-clarification task-key={{
|
|
560
|
-
- 별도 터미널: `scripts/okstra.sh --resume-clarification --task-key {{
|
|
548
|
+
- Claude Code: `/okstra-run resume-clarification task-key={{ header.taskKey }}`
|
|
549
|
+
- 별도 터미널: `scripts/okstra.sh --resume-clarification --task-key {{ header.taskKey }}`
|
|
561
550
|
|
|
562
|
-
| ID | Ticket ID | Kind | Statement
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
|
566
|
-
|
|
551
|
+
| ID | Ticket ID | Kind | Statement | Expected form | Blocks | Status | User input |
|
|
552
|
+
|----|-----------|------|-----------|---------------|--------|--------|-----------|
|
|
553
|
+
{% for row in clarificationItems -%}
|
|
554
|
+
| {{ row.id }} | `{{ row.ticketId }}` | `{{ row.kind }}` | {{ row.statement }} | {{ row.expectedForm }} | `{{ row.blocks }}` | {{ row.status }} | {{ row.userInput or '' }} |
|
|
555
|
+
{% endfor %}
|
|
567
556
|
|
|
568
557
|
컬럼 가이드 (전체 정의는 `prompts/profiles/_common-contract.md §Clarification request policy` SSOT 참조):
|
|
569
558
|
|
|
570
559
|
- **`Kind`** ∈ `{material, decision, data-point}`.
|
|
571
|
-
- **`Blocks`** ∈ `{approval, next-phase, none}
|
|
560
|
+
- **`Blocks`** ∈ `{approval, next-phase, none}`.
|
|
572
561
|
- **`Status`** ∈ `{open, answered, resolved, obsolete}`.
|
|
573
|
-
|
|
574
|
-
안티패턴 (validator 가 fail 처리):
|
|
575
|
-
|
|
576
|
-
- 같은 항목을 별도 sub-section (`5.1 추가 자료 요청` / `5.2 사용자 확인 질문` / `4.5.9 Open Questions`) 으로 분리하기 — 본 8-열 표 한 곳으로만 표현합니다.
|
|
577
|
-
- 한 행을 두 개로 쪼개기 — 자료 + yes/no 가 묶인 항목은 `Kind=material`, `Expected form` 에 "파일 경로 + yes/no" 라고 적은 한 행.
|
|
578
|
-
- 사용자가 답하지 않아도 진행 가능한 항목을 `Blocks=approval` 로 표시 — `Blocks=none` / `next-phase` 로 정확히 표시.
|
|
562
|
+
{%- endif %}
|
|
579
563
|
|
|
580
564
|
## 6. Recommended Next Steps
|
|
581
565
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
- Preferred: `/okstra-run resume-clarification task-key={{TASK_KEY}}` / `scripts/okstra.sh --resume-clarification --task-key {{TASK_KEY}}`.
|
|
597
|
-
|
|
598
|
-
Empty-state placeholder (copy verbatim when nothing else applies): `- No further action required. Final verdict in section 2 stands.`
|
|
566
|
+
{% if recommendedNextSteps | length == 0 -%}
|
|
567
|
+
- No further action required. Final verdict in section 2 stands.
|
|
568
|
+
{%- else %}
|
|
569
|
+
{% for step in recommendedNextSteps -%}
|
|
570
|
+
{{ loop.index }}. {{ step.text }}
|
|
571
|
+
{% if step.commands -%}
|
|
572
|
+
{% for cmd in step.commands %}
|
|
573
|
+
- {{ cmd.label }}:
|
|
574
|
+
- Claude Code: `{{ cmd.claudeCode }}`
|
|
575
|
+
- 별도 터미널: `{{ cmd.terminal }}`
|
|
576
|
+
{% endfor -%}
|
|
577
|
+
{%- endif %}
|
|
578
|
+
{% endfor %}
|
|
579
|
+
{%- endif %}
|
|
599
580
|
|
|
600
581
|
## 7. Follow-up Tasks (후속 작업)
|
|
601
582
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
2. **scope-boundary row (선택)** — 본 run 의 구현·검증 범위를 **넘어서는** 작업. lead 가 필요하다고 판단할 때만.
|
|
606
|
-
|
|
607
|
-
phase-continuation row 의무 적용 범위:
|
|
608
|
-
|
|
609
|
-
- `task-type` ∈ {`requirements-discovery`, `implementation-planning`, `error-analysis`, `implementation`, `final-verification`}: **필수**. 다음 phase 가 자명하므로 phase-continuation row 한 개를 반드시 채움.
|
|
610
|
-
- `release-handoff`: 다음 phase 없음 → phase-continuation 생략. scope-boundary row 만 (있다면) 채움.
|
|
611
|
-
|
|
612
|
-
후속 항목 출처(`Origin` 컬럼): `phase-continuation` / `out-of-plan` / `verifier-concern` / `scope-boundary` / `open-question` / `manual` 중 하나.
|
|
613
|
-
|
|
614
|
-
규칙: `Auto-spawn? = yes` 인 row 는 Phase 7 의 `scripts/okstra-spawn-followups.py` 가 자동으로 `tasks/<TASK_GROUP>/<New Task ID>/` 디렉터리 + `task-manifest.json` (status: `todo`) + stub task-brief 를 생성. `no` 는 사람이 처리. `phase-continuation` row 는 항상 `no` — 같은 task-key 를 재사용하여 다음 phase 로 진입하므로 새 task 디렉터리를 만들면 안 됨. `New Task ID` 는 task-group 내 유일한 알파숫자·하이픈 slug(phase-continuation row 의 경우 현재 task-id 를 그대로 사용). 동일 follow-up 이 여러 run 에 등장하면 `New Task ID` 를 동일하게 유지하여 중복 spawn 방지.
|
|
615
|
-
|
|
583
|
+
{% if followUpTasks | length == 0 -%}
|
|
584
|
+
- 후속 작업 없음. 본 run 의 다음 phase 는 §6 (Recommended Next Steps) 참고.
|
|
585
|
+
{%- else %}
|
|
616
586
|
| ID | Ticket ID | Origin | New Task ID | Title | Suggested task-type | Scope (files/areas) | Reason / Why deferred | Priority (P0/P1/P2) | Auto-spawn? |
|
|
617
587
|
|----|-----------|--------|-------------|-------|---------------------|---------------------|------------------------|---------------------|-------------|
|
|
618
|
-
|
|
619
|
-
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
본 섹션이 채워진 경우 Section 6 의 "Follow-up tasks" 항목에 진입 명령(phase-continuation 은 `/okstra-run` 형태, auto-spawn 된 row 는 새 task-key)을 함께 적어 사용자가 즉시 이어갈 수 있게 합니다.
|
|
624
|
-
|
|
625
|
-
## Writing Rules
|
|
626
|
-
|
|
627
|
-
- Markdown. 본문은 한국어. 기술 식별자 (파일 경로, 코드 심볼, 모델명, status 값) 는 원형 유지.
|
|
628
|
-
- 섹션 구조는 brief 가 명시적으로 다른 구조를 요구하지 않는 한 보존.
|
|
629
|
-
- 증거 기반 (speculation 금지). 메타 코멘트 (저장소·세션·이전 메시지 언급) 로 본문 대체 금지.
|
|
630
|
-
- 본 문서는 `Claude lead` 의 최종 합성이지 raw worker dump 가 아닙니다.
|
|
631
|
-
- 표 우선. 같은 모양의 항목을 여러 개 나열할 때 bullet 으로 degrade 금지.
|
|
632
|
-
- Reading Confirmation / 워커 raw output / 환산식 설명 등 audit 자료는 본문이 아닌 사이드카에 둡니다 (`runs/<task-type>/worker-results/<worker>-audit-<task-type>-<seq>.md`).
|
|
588
|
+
{% for row in followUpTasks -%}
|
|
589
|
+
| {{ row.id }} | `{{ row.ticketId }}` | `{{ row.origin }}` | `{{ row.newTaskId }}` | {{ row.title }} | `{{ row.suggestedTaskType }}` | `{{ row.scope }}` | {{ row.reason }} | `{{ row.priority }}` | `{{ row.autoSpawn }}` |
|
|
590
|
+
{% endfor %}
|
|
591
|
+
{%- endif %}
|