okstra 0.102.2 → 0.102.4
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/README.kr.md +5 -5
- package/README.md +5 -5
- package/docs/kr/architecture/storage-model.md +8 -3
- package/docs/kr/architecture.md +12 -13
- package/docs/kr/cli.md +4 -4
- package/docs/kr/container.md +1 -1
- package/docs/kr/performance-improvement-plan-v2.md +2 -2
- package/docs/project-structure-overview.md +2 -2
- package/package.json +7 -2
- package/runtime/BUILD.json +2 -2
- package/runtime/bin/lib/okstra/interactive.sh +12 -0
- package/runtime/bin/okstra-antigravity-exec.sh +1 -2
- package/runtime/bin/okstra-codex-exec.sh +1 -2
- package/runtime/bin/okstra-render-final-report.py +2 -9
- package/runtime/bin/okstra-spawn-followups.py +4 -6
- package/runtime/bin/okstra-trace-cleanup.sh +24 -4
- package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
- package/runtime/prompts/lead/report-writer.md +1 -1
- package/runtime/prompts/profiles/_common-contract.md +9 -11
- package/runtime/python/okstra_ctl/codex_dispatch.py +6 -13
- package/runtime/python/okstra_ctl/consumers.py +35 -0
- package/runtime/python/okstra_ctl/container.py +4 -6
- package/runtime/python/okstra_ctl/dispatch_core.py +8 -13
- package/runtime/python/okstra_ctl/final_report_paths.py +24 -0
- package/runtime/python/okstra_ctl/handoff.py +2 -1
- package/runtime/python/okstra_ctl/implementation_outcome.py +271 -0
- package/runtime/python/okstra_ctl/implementation_stage.py +7 -11
- package/runtime/python/okstra_ctl/path_hints.py +665 -0
- package/runtime/python/okstra_ctl/render.py +4 -3
- package/runtime/python/okstra_ctl/report_view_artifacts.py +14 -0
- package/runtime/python/okstra_ctl/report_views.py +7 -4
- package/runtime/python/okstra_ctl/run.py +3 -10
- package/runtime/python/okstra_ctl/run_context.py +4 -2
- package/runtime/python/okstra_ctl/stage_targets.py +18 -0
- package/runtime/python/okstra_ctl/wizard.py +37 -26
- package/runtime/python/okstra_ctl/wizard_stage_intent.py +54 -0
- package/runtime/python/okstra_project/state.py +40 -2
- package/runtime/python/okstra_token_usage/report.py +2 -5
- package/runtime/validators/validate-report-views.py +2 -1
- package/runtime/validators/validate-run.py +1 -11
- package/src/commands/lifecycle/install.mjs +5 -5
- package/src/commands/lifecycle/uninstall.mjs +4 -4
- package/docs/superpowers/plans/2026-05-12-ticket-id-in-reports.md +0 -638
- package/docs/superpowers/plans/2026-05-14-convergence-queue-pruning.md +0 -1568
- package/docs/superpowers/plans/2026-05-17-dual-format-final-report.md +0 -167
- package/docs/superpowers/plans/2026-05-20-final-report-language.md +0 -1501
- package/docs/superpowers/plans/2026-05-20-implementation-planning-multi-stage.md +0 -1267
- package/docs/superpowers/plans/2026-05-20-okstra-run-prompt-sot-b1.md +0 -1007
- package/docs/superpowers/plans/2026-05-20-wizard-messages-json-sot.md +0 -720
- package/docs/superpowers/plans/2026-05-20-wizard-prompt-json-sot-a1.md +0 -681
- package/docs/superpowers/plans/2026-05-21-improvement-discovery-task-type.md +0 -1691
- package/docs/superpowers/plans/2026-05-24-implementation-lead-context-slimming.md +0 -1700
- package/docs/superpowers/plans/2026-05-25-okstra-project-root-rename.md +0 -158
- package/docs/superpowers/plans/2026-05-26-wizard-3-option-picker.md +0 -860
- package/docs/superpowers/plans/2026-06-02-final-verification-protocol-hardening.md +0 -326
- package/docs/superpowers/plans/2026-06-02-okstra-run-branch-confirm-step.md +0 -337
- package/docs/superpowers/plans/2026-06-02-okstra-run-phase-pane-cleanup.md +0 -410
- package/docs/superpowers/plans/2026-06-02-requirements-discovery-fanout.md +0 -728
- package/docs/superpowers/plans/2026-06-04-adversarial-implementation-planning.md +0 -294
- package/docs/superpowers/plans/2026-06-04-adversarial-verification.md +0 -570
- package/docs/superpowers/plans/2026-06-04-coverage-critic.md +0 -516
- package/docs/superpowers/plans/2026-06-04-stage-cohesion-planner.md +0 -351
- package/docs/superpowers/plans/2026-06-04-stage-run-batching.md +0 -457
- package/docs/superpowers/plans/2026-06-05-acceptance-critic.md +0 -251
- package/docs/superpowers/plans/2026-06-05-compact-markdown-report-tables.md +0 -323
- package/docs/superpowers/plans/2026-06-05-wizard-batch-prompts.md +0 -559
- package/docs/superpowers/plans/2026-06-06-final-verification-whole-task-gate.md +0 -993
- package/docs/superpowers/plans/2026-06-06-stage-parallel-and-pending-fixes.md +0 -93
- package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p1.md +0 -447
- package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p2.md +0 -289
- package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p3.md +0 -774
- package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p4.md +0 -303
- package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p5-multidep-base.md +0 -387
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase2.md +0 -275
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase3.md +0 -282
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4a.md +0 -147
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4b.md +0 -262
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4c.md +0 -184
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4d.md +0 -88
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4e.md +0 -250
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa.md +0 -409
- package/docs/superpowers/plans/2026-06-09-implementation-run-artifact-stage-isolation.md +0 -320
- package/docs/superpowers/plans/2026-06-10-concurrent-run-team-guard.md +0 -456
- package/docs/superpowers/plans/2026-06-10-git-reconcile-stale-sha-recovery.md +0 -1408
- package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling-PROBE.md +0 -42
- package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling.md +0 -337
- package/docs/superpowers/plans/2026-06-10-p6-token-usage-incremental.md +0 -1029
- package/docs/superpowers/plans/2026-06-10-stage-group-handoff.md +0 -1572
- package/docs/superpowers/plans/2026-06-11-fix-cycle.md +0 -1290
- package/docs/superpowers/plans/2026-06-11-wizard-whole-task-final-verification.md +0 -526
- package/docs/superpowers/plans/2026-06-12-html-plan-approval.md +0 -1000
- package/docs/superpowers/plans/2026-06-13-repo-risk-hardening.md +0 -493
- package/docs/superpowers/plans/2026-06-14-host-runtime-auto-execution.md +0 -1775
- package/docs/superpowers/plans/2026-06-15-coding-preflight-pack-dispatch-path.md +0 -504
- package/docs/superpowers/plans/2026-06-15-internal-skill-migration-final-fixups.md +0 -342
- package/docs/superpowers/plans/2026-06-15-internal-skill-migration-fixups.md +0 -258
- package/docs/superpowers/plans/2026-06-15-internal-skill-migration-remaining-fixups.md +0 -387
- package/docs/superpowers/plans/2026-06-15-internal-skill-resource-migration.md +0 -749
- package/docs/superpowers/plans/2026-06-15-worker-prompt-anchor-final-fixups.md +0 -828
- package/docs/superpowers/plans/2026-06-15-worker-prompt-header-error-contract.md +0 -490
- package/docs/superpowers/plans/2026-06-17-okstra-error-report.md +0 -724
- package/docs/superpowers/plans/2026-06-18-subagent-pane-reclaim.md +0 -483
- package/docs/superpowers/plans/2026-06-19-agent-operating-standard.md +0 -476
- package/docs/superpowers/plans/2026-06-19-okstra-inspect-recap-facet.md +0 -647
- package/docs/superpowers/plans/2026-06-20-error-feedback-loop.md +0 -1019
- package/docs/superpowers/plans/2026-06-20-run-index-row-normalization.md +0 -583
- package/docs/superpowers/plans/2026-06-20-stage-auto-integrate-teardown.md +0 -819
- package/docs/superpowers/plans/2026-06-21-okstra-container-local-user-test.md +0 -714
- package/docs/superpowers/plans/2026-06-21-release-handoff-local-checkout.md +0 -348
- package/docs/superpowers/plans/2026-06-23-implementation-stage-multiselect-chain.md +0 -630
- package/docs/superpowers/plans/2026-06-23-implementation-step-commit-granularity.md +0 -274
- package/docs/superpowers/plans/2026-06-23-phase-batch-cleanup-enforcement.md +0 -409
- package/docs/superpowers/plans/2026-06-24-cross-project-precondition.md +0 -542
- package/docs/superpowers/plans/2026-06-24-decision-drafts-render-gap.md +0 -568
- package/docs/superpowers/plans/2026-06-24-manual-user-test-section.md +0 -203
- package/docs/superpowers/plans/2026-06-24-okstra-container-build-rename.md +0 -525
- package/docs/superpowers/specs/2026-05-12-ticket-id-in-reports-design.md +0 -131
- package/docs/superpowers/specs/2026-05-15-implementation-plan-verification-design.md +0 -254
- package/docs/superpowers/specs/2026-05-20-final-report-language-design.md +0 -383
- package/docs/superpowers/specs/2026-05-20-implementation-planning-multi-stage-design.md +0 -322
- package/docs/superpowers/specs/2026-05-20-okstra-run-prompt-sot-design.md +0 -299
- package/docs/superpowers/specs/2026-05-21-improvement-discovery-task-type-design.md +0 -335
- package/docs/superpowers/specs/2026-06-02-okstra-run-branch-confirm-step-design.md +0 -113
- package/docs/superpowers/specs/2026-06-02-okstra-run-phase-pane-cleanup-design.md +0 -173
- package/docs/superpowers/specs/2026-06-02-requirements-discovery-fanout-design.md +0 -154
- package/docs/superpowers/specs/2026-06-04-adversarial-implementation-planning-design.md +0 -90
- package/docs/superpowers/specs/2026-06-04-adversarial-verification-design.md +0 -176
- package/docs/superpowers/specs/2026-06-04-coverage-critic-design.md +0 -99
- package/docs/superpowers/specs/2026-06-04-stage-splitting-cost-aware-design.md +0 -98
- package/docs/superpowers/specs/2026-06-05-acceptance-critic-design.md +0 -90
- package/docs/superpowers/specs/2026-06-05-compact-markdown-report-tables-design.md +0 -87
- package/docs/superpowers/specs/2026-06-05-wizard-batch-prompts-design.md +0 -121
- package/docs/superpowers/specs/2026-06-06-final-verification-whole-task-gate-design.md +0 -126
- package/docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md +0 -180
- package/docs/superpowers/specs/2026-06-06-vertical-slice-tdd-planning-design.md +0 -179
- package/docs/superpowers/specs/2026-06-07-stage-conformance-qa-design.md +0 -169
- package/docs/superpowers/specs/2026-06-09-executor-model-custom-id-cascade-design.md +0 -66
- package/docs/superpowers/specs/2026-06-09-implementation-run-artifact-stage-isolation-design.md +0 -87
- package/docs/superpowers/specs/2026-06-10-blocking-contract-posthoc-conformance-design.md +0 -168
- package/docs/superpowers/specs/2026-06-10-concurrent-run-team-guard-design.md +0 -107
- package/docs/superpowers/specs/2026-06-10-git-reconcile-stale-sha-recovery-design.md +0 -105
- package/docs/superpowers/specs/2026-06-10-lead-worker-completion-polling-design.md +0 -113
- package/docs/superpowers/specs/2026-06-10-stage-group-handoff-design.md +0 -156
- package/docs/superpowers/specs/2026-06-11-brief-entry-only-handoff-stage-entry-design.md +0 -158
- package/docs/superpowers/specs/2026-06-11-fix-cycle-design.md +0 -94
- package/docs/superpowers/specs/2026-06-11-wizard-whole-task-final-verification-design.md +0 -89
- package/docs/superpowers/specs/2026-06-12-codex-lead-adapter-design.md +0 -358
- package/docs/superpowers/specs/2026-06-12-html-plan-approval-design.md +0 -85
- package/docs/superpowers/specs/2026-06-12-stage-discipline-rule-design.md +0 -108
- package/docs/superpowers/specs/2026-06-13-forbidden-actions-ssot-design.md +0 -134
- package/docs/superpowers/specs/2026-06-13-neutral-tmux-lead-adapter-design.md +0 -284
- package/docs/superpowers/specs/2026-06-14-host-runtime-auto-execution-design.md +0 -404
- package/docs/superpowers/specs/2026-06-17-okstra-error-report-design.md +0 -123
- package/docs/superpowers/specs/2026-06-18-subagent-pane-reclaim-design.md +0 -150
- package/docs/superpowers/specs/2026-06-19-agent-operating-standard-design.md +0 -120
- package/docs/superpowers/specs/2026-06-19-okstra-inspect-recap-facet-design.md +0 -96
- package/docs/superpowers/specs/2026-06-20-error-feedback-loop-design.md +0 -171
- package/docs/superpowers/specs/2026-06-20-run-index-row-normalization-design.md +0 -112
- package/docs/superpowers/specs/2026-06-20-stage-auto-integrate-teardown-design.md +0 -145
- package/docs/superpowers/specs/2026-06-21-okstra-container-local-user-test-design.md +0 -125
- package/docs/superpowers/specs/2026-06-21-release-handoff-local-checkout-design.md +0 -113
- package/docs/superpowers/specs/2026-06-23-implementation-stage-multiselect-chain-design.md +0 -138
- package/docs/superpowers/specs/2026-06-23-implementation-step-commit-granularity-design.md +0 -120
- package/docs/superpowers/specs/2026-06-24-cross-project-precondition-design.md +0 -129
- package/docs/superpowers/specs/2026-06-24-decision-drafts-render-gap-design.md +0 -185
- package/docs/superpowers/specs/2026-06-24-manual-user-test-section-design.md +0 -121
- package/docs/superpowers/specs/2026-06-24-okstra-container-build-rename-design.md +0 -110
|
@@ -1,526 +0,0 @@
|
|
|
1
|
-
# wizard whole-task final-verification 노출 Implementation Plan
|
|
2
|
-
|
|
3
|
-
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
-
|
|
5
|
-
**Goal:** okstra-run 위저드의 final-verification stage picker 에서 "전체 task 검증" 을 명시 항목으로 선택할 수 있게 한다(prepare 계약 무변경, `auto` 토큰 미사용).
|
|
6
|
-
|
|
7
|
-
**Architecture:** 위저드 레이어만 수정한다. picker 가 `consumers.jsonl` 의 done 행을 읽어 stage 별 done 마킹을 붙이고, 전 stage done 일 때만 "전체 task" 항목(내부 sentinel `__whole_task__`)을 노출한다. `render_args` 가 sentinel 을 빈 stage(`""`)로 변환해 prepare 의 기존 whole-task 경로를 탄다. 머지/clean/active 전제는 prepare 의 PrepareError 게이트에 위임한다.
|
|
8
|
-
|
|
9
|
-
**Tech Stack:** Python 3 (`scripts/okstra_ctl/wizard.py`), JSON 프롬프트(`prompts/wizard/prompts.ko.json`), pytest.
|
|
10
|
-
|
|
11
|
-
**Spec:** [2026-06-11-wizard-whole-task-final-verification-design.md](../specs/2026-06-11-wizard-whole-task-final-verification-design.md)
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## File Structure
|
|
16
|
-
|
|
17
|
-
- `scripts/okstra_ctl/wizard.py` — sentinel 상수, done/Stage-Map 헬퍼, picker·submit·render_args·confirmation 수정.
|
|
18
|
-
- `prompts/wizard/prompts.ko.json` — `steps.stage_pick.options` 에 whole-task·done 마킹 라벨 추가.
|
|
19
|
-
- `tests/test_wizard_stage_pick.py` — picker·submit·render_args 회귀 + 신규 케이스.
|
|
20
|
-
- `tests/test_wizard_whole_task_fv.py` — done 헬퍼 + whole-task 노출 게이트 신규 테스트.
|
|
21
|
-
|
|
22
|
-
기존 단독-stage UX(`54b9482`)·prepare·CLI 계약은 건드리지 않는다.
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
## Task 1: sentinel 상수 + done/Stage-Map 헬퍼
|
|
27
|
-
|
|
28
|
-
**Files:**
|
|
29
|
-
- Modify: `scripts/okstra_ctl/wizard.py` (토큰 블록 1354-1360 근처, 헬퍼는 `_stage_auto_allowed` 1778 부근)
|
|
30
|
-
- Test: `tests/test_wizard_whole_task_fv.py` (create)
|
|
31
|
-
|
|
32
|
-
- [ ] **Step 1: 실패 테스트 작성**
|
|
33
|
-
|
|
34
|
-
`tests/test_wizard_whole_task_fv.py`:
|
|
35
|
-
|
|
36
|
-
```python
|
|
37
|
-
import importlib
|
|
38
|
-
import json
|
|
39
|
-
import sys
|
|
40
|
-
from pathlib import Path
|
|
41
|
-
|
|
42
|
-
REPO = Path(__file__).resolve().parents[1]
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def _load_wizard():
|
|
46
|
-
if "okstra_ctl.wizard" in sys.modules:
|
|
47
|
-
return sys.modules["okstra_ctl.wizard"]
|
|
48
|
-
if str(REPO / "scripts") not in sys.path:
|
|
49
|
-
sys.path.insert(0, str(REPO / "scripts"))
|
|
50
|
-
return importlib.import_module("okstra_ctl.wizard")
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def _plan_run(tmp_path: Path, done_stages: list[int]) -> Path:
|
|
54
|
-
"""plan_run_root/reports/plan.md + plan_run_root/consumers.jsonl 를 만들고
|
|
55
|
-
approved plan 경로를 돌려준다. plan_run_root == plan.resolve().parents[1]."""
|
|
56
|
-
run = tmp_path / "run"
|
|
57
|
-
(run / "reports").mkdir(parents=True)
|
|
58
|
-
plan = run / "reports" / "plan.md"
|
|
59
|
-
fixture = (REPO / "tests" / "fixtures" / "plans"
|
|
60
|
-
/ "valid_three_stage_parallel.md").read_text(encoding="utf-8")
|
|
61
|
-
plan.write_text(fixture + "\n- [x] Approved\n", encoding="utf-8")
|
|
62
|
-
rows = [json.dumps({"status": "done", "stage": n,
|
|
63
|
-
"impl_task_key": "k", "head_commit": f"sha{n}"})
|
|
64
|
-
for n in done_stages]
|
|
65
|
-
(run / "consumers.jsonl").write_text(
|
|
66
|
-
("\n".join(rows) + "\n") if rows else "", encoding="utf-8")
|
|
67
|
-
return plan
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def test_done_stage_numbers_reads_consumers(tmp_path):
|
|
71
|
-
wizard = _load_wizard()
|
|
72
|
-
plan = _plan_run(tmp_path, [1, 3])
|
|
73
|
-
state = wizard.WizardState(
|
|
74
|
-
workspace_root=str(REPO), project_root=str(tmp_path),
|
|
75
|
-
project_id="demo", task_type="final-verification",
|
|
76
|
-
approved_plan_path=str(plan))
|
|
77
|
-
assert wizard._done_stage_numbers(state) == {1, 3}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def test_whole_task_allowed_true_when_all_done(tmp_path):
|
|
81
|
-
wizard = _load_wizard()
|
|
82
|
-
plan = _plan_run(tmp_path, [1, 2, 3])
|
|
83
|
-
state = wizard.WizardState(
|
|
84
|
-
workspace_root=str(REPO), project_root=str(tmp_path),
|
|
85
|
-
project_id="demo", task_type="final-verification",
|
|
86
|
-
approved_plan_path=str(plan))
|
|
87
|
-
assert wizard._whole_task_allowed(state) is True
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def test_whole_task_allowed_false_when_partial(tmp_path):
|
|
91
|
-
wizard = _load_wizard()
|
|
92
|
-
plan = _plan_run(tmp_path, [1, 2])
|
|
93
|
-
state = wizard.WizardState(
|
|
94
|
-
workspace_root=str(REPO), project_root=str(tmp_path),
|
|
95
|
-
project_id="demo", task_type="final-verification",
|
|
96
|
-
approved_plan_path=str(plan))
|
|
97
|
-
assert wizard._whole_task_allowed(state) is False
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def test_whole_task_allowed_false_for_implementation(tmp_path):
|
|
101
|
-
wizard = _load_wizard()
|
|
102
|
-
plan = _plan_run(tmp_path, [1, 2, 3])
|
|
103
|
-
state = wizard.WizardState(
|
|
104
|
-
workspace_root=str(REPO), project_root=str(tmp_path),
|
|
105
|
-
project_id="demo", task_type="implementation",
|
|
106
|
-
approved_plan_path=str(plan))
|
|
107
|
-
assert wizard._whole_task_allowed(state) is False
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
- [ ] **Step 2: 테스트 실패 확인**
|
|
111
|
-
|
|
112
|
-
Run: `python3 -m pytest tests/test_wizard_whole_task_fv.py -v`
|
|
113
|
-
Expected: FAIL — `AttributeError: module ... has no attribute '_done_stage_numbers'`
|
|
114
|
-
|
|
115
|
-
- [ ] **Step 3: 최소 구현**
|
|
116
|
-
|
|
117
|
-
`scripts/okstra_ctl/wizard.py` 의 토큰 블록(`_REUSE_LAST_TOKEN = "__reuse_last__"` 등이 있는 1354-1360 근처)에 sentinel 추가:
|
|
118
|
-
|
|
119
|
-
```python
|
|
120
|
-
WHOLE_TASK_STAGE = "__whole_task__"
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
`_stage_auto_allowed` 정의(1778 근처) 바로 아래에 헬퍼 3개 추가:
|
|
124
|
-
|
|
125
|
-
```python
|
|
126
|
-
def _parse_stage_objects(state: WizardState) -> list:
|
|
127
|
-
"""승인 plan 의 Stage Map stage 객체 목록. validator 의 _parse_stage_map 재사용.
|
|
128
|
-
`_build_stage_pick` 과 `_whole_task_allowed` 가 공유한다."""
|
|
129
|
-
import importlib.util as _ilu
|
|
130
|
-
import sys as _sys
|
|
131
|
-
plan_text = Path(state.approved_plan_path).read_text(encoding="utf-8")
|
|
132
|
-
validator_path = (Path(state.workspace_root) / "validators"
|
|
133
|
-
/ "validate-implementation-plan-stages.py")
|
|
134
|
-
spec = _ilu.spec_from_file_location("_ip_stage_v_wizard", str(validator_path))
|
|
135
|
-
if spec is None or spec.loader is None:
|
|
136
|
-
raise WizardError(f"cannot load stage validator at {validator_path}")
|
|
137
|
-
mod = _ilu.module_from_spec(spec)
|
|
138
|
-
_sys.modules["_ip_stage_v_wizard"] = mod
|
|
139
|
-
try:
|
|
140
|
-
spec.loader.exec_module(mod)
|
|
141
|
-
stages, _errs = mod._parse_stage_map(plan_text)
|
|
142
|
-
finally:
|
|
143
|
-
_sys.modules.pop("_ip_stage_v_wizard", None)
|
|
144
|
-
return stages
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def _done_stage_numbers(state: WizardState) -> set:
|
|
148
|
-
"""approved plan 을 소비한 implementation run 들의 consumers.jsonl 에서
|
|
149
|
-
done 처리된 stage 번호 집합. git 호출 없음 — 파일 읽기만(prepare 와 동일 SSOT)."""
|
|
150
|
-
if not state.approved_plan_path:
|
|
151
|
-
return set()
|
|
152
|
-
from .consumers import (read_consumers, backfill_done_from_carry,
|
|
153
|
-
latest_done_by_stage)
|
|
154
|
-
plan_run_root = Path(state.approved_plan_path).resolve().parents[1]
|
|
155
|
-
backfill_done_from_carry(plan_run_root)
|
|
156
|
-
rows = read_consumers(plan_run_root)
|
|
157
|
-
return set(latest_done_by_stage(rows).keys())
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
def _whole_task_allowed(state: WizardState) -> bool:
|
|
161
|
-
"""final-verification 이고 Stage Map 의 모든 stage 가 done 일 때만 True.
|
|
162
|
-
위저드는 done 만 본다 — 머지/clean/active 는 prepare 게이트가 강제한다."""
|
|
163
|
-
if state.task_type != "final-verification":
|
|
164
|
-
return False
|
|
165
|
-
if not state.approved_plan_path:
|
|
166
|
-
return False
|
|
167
|
-
stages = _parse_stage_objects(state)
|
|
168
|
-
if not stages:
|
|
169
|
-
return False
|
|
170
|
-
done = _done_stage_numbers(state)
|
|
171
|
-
return all(s.stage_number in done for s in stages)
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
- [ ] **Step 4: 테스트 통과 확인**
|
|
175
|
-
|
|
176
|
-
Run: `python3 -m pytest tests/test_wizard_whole_task_fv.py -v`
|
|
177
|
-
Expected: 4 PASS
|
|
178
|
-
|
|
179
|
-
- [ ] **Step 5: 커밋**
|
|
180
|
-
|
|
181
|
-
```bash
|
|
182
|
-
git add scripts/okstra_ctl/wizard.py tests/test_wizard_whole_task_fv.py
|
|
183
|
-
git commit -m "feat(wizard): final-verification done/whole-task 헬퍼 추가"
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
---
|
|
187
|
-
|
|
188
|
-
## Task 2: stage picker 에 done 마킹 + 전체 task 항목
|
|
189
|
-
|
|
190
|
-
**Files:**
|
|
191
|
-
- Modify: `scripts/okstra_ctl/wizard.py:1494-1533` (`_build_stage_pick`)
|
|
192
|
-
- Modify: `prompts/wizard/prompts.ko.json` (`steps.stage_pick.options`)
|
|
193
|
-
- Test: `tests/test_wizard_whole_task_fv.py`
|
|
194
|
-
|
|
195
|
-
- [ ] **Step 1: 실패 테스트 추가**
|
|
196
|
-
|
|
197
|
-
`tests/test_wizard_whole_task_fv.py` 끝에 추가(`_plan_run` 헬퍼 재사용):
|
|
198
|
-
|
|
199
|
-
```python
|
|
200
|
-
def test_picker_shows_whole_task_when_all_done(tmp_path):
|
|
201
|
-
wizard = _load_wizard()
|
|
202
|
-
plan = _plan_run(tmp_path, [1, 2, 3])
|
|
203
|
-
state = wizard.WizardState(
|
|
204
|
-
workspace_root=str(REPO), project_root=str(tmp_path),
|
|
205
|
-
project_id="demo", task_type="final-verification",
|
|
206
|
-
approved_plan_path=str(plan))
|
|
207
|
-
prompt = wizard._build_stage_pick(state)
|
|
208
|
-
values = [o.value for o in prompt.options]
|
|
209
|
-
assert wizard.WHOLE_TASK_STAGE in values
|
|
210
|
-
assert "auto" not in values
|
|
211
|
-
assert values == [wizard.WHOLE_TASK_STAGE, "1", "2", "3"]
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
def test_picker_hides_whole_task_when_partial(tmp_path):
|
|
215
|
-
wizard = _load_wizard()
|
|
216
|
-
plan = _plan_run(tmp_path, [1, 2])
|
|
217
|
-
state = wizard.WizardState(
|
|
218
|
-
workspace_root=str(REPO), project_root=str(tmp_path),
|
|
219
|
-
project_id="demo", task_type="final-verification",
|
|
220
|
-
approved_plan_path=str(plan))
|
|
221
|
-
prompt = wizard._build_stage_pick(state)
|
|
222
|
-
values = [o.value for o in prompt.options]
|
|
223
|
-
assert wizard.WHOLE_TASK_STAGE not in values
|
|
224
|
-
# stage 3 미완 마킹이 라벨에 보인다
|
|
225
|
-
label_3 = next(o.label for o in prompt.options if o.value == "3")
|
|
226
|
-
assert "미완" in label_3
|
|
227
|
-
label_1 = next(o.label for o in prompt.options if o.value == "1")
|
|
228
|
-
assert "done" in label_1
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
- [ ] **Step 2: 테스트 실패 확인**
|
|
232
|
-
|
|
233
|
-
Run: `python3 -m pytest tests/test_wizard_whole_task_fv.py -k picker -v`
|
|
234
|
-
Expected: FAIL — whole-task 항목이 없고 done 마킹이 없음
|
|
235
|
-
|
|
236
|
-
- [ ] **Step 3: 구현**
|
|
237
|
-
|
|
238
|
-
`prompts/wizard/prompts.ko.json` 의 `steps.stage_pick.options` 를 다음으로 교체:
|
|
239
|
-
|
|
240
|
-
```json
|
|
241
|
-
"options": {
|
|
242
|
-
"auto": "auto (다음 미완료 stage)",
|
|
243
|
-
"whole_task": "전체 task 검증 (모든 stage)",
|
|
244
|
-
"done_mark": "[done]",
|
|
245
|
-
"undone_mark": "[미완]"
|
|
246
|
-
}
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
`scripts/okstra_ctl/wizard.py` 의 `_build_stage_pick` 본문을 교체(파싱은 `_parse_stage_objects` 로 위임):
|
|
250
|
-
|
|
251
|
-
```python
|
|
252
|
-
def _build_stage_pick(state: WizardState) -> Prompt:
|
|
253
|
-
"""Parse the Stage Map from the approved plan and build the stage picker."""
|
|
254
|
-
t = _p(state.workspace_root, "stage_pick")
|
|
255
|
-
stages = _parse_stage_objects(state)
|
|
256
|
-
is_fv = state.task_type == "final-verification"
|
|
257
|
-
label = (
|
|
258
|
-
t.get("label_final_verification", t["label"])
|
|
259
|
-
if is_fv else t["label"]
|
|
260
|
-
)
|
|
261
|
-
done = _done_stage_numbers(state) if is_fv else set()
|
|
262
|
-
options = []
|
|
263
|
-
if _stage_auto_allowed(state):
|
|
264
|
-
options.append(_opt("auto", t["options"]["auto"]))
|
|
265
|
-
if is_fv and stages and all(s.stage_number in done for s in stages):
|
|
266
|
-
options.append(_opt(
|
|
267
|
-
WHOLE_TASK_STAGE,
|
|
268
|
-
t["options"].get("whole_task", "전체 task 검증 (모든 stage)"),
|
|
269
|
-
))
|
|
270
|
-
for s in stages:
|
|
271
|
-
depends = ",".join(map(str, s.depends_on)) or "(none)"
|
|
272
|
-
suffix = ""
|
|
273
|
-
if is_fv:
|
|
274
|
-
mark = (t["options"].get("done_mark", "[done]")
|
|
275
|
-
if s.stage_number in done
|
|
276
|
-
else t["options"].get("undone_mark", "[미완]"))
|
|
277
|
-
suffix = f" {mark}"
|
|
278
|
-
options.append(_opt(
|
|
279
|
-
str(s.stage_number),
|
|
280
|
-
f"{s.stage_number}: {s.title} "
|
|
281
|
-
f"[depends-on: {depends} | steps: {s.step_count}]{suffix}",
|
|
282
|
-
))
|
|
283
|
-
return Prompt(
|
|
284
|
-
step=S_STAGE_PICK, kind="pick",
|
|
285
|
-
label=label,
|
|
286
|
-
options=options,
|
|
287
|
-
echo_template=t["echo_template"],
|
|
288
|
-
)
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
- [ ] **Step 4: 테스트 통과 + 기존 picker 회귀 확인**
|
|
292
|
-
|
|
293
|
-
Run: `python3 -m pytest tests/test_wizard_whole_task_fv.py tests/test_wizard_stage_pick.py -v`
|
|
294
|
-
Expected: 신규 picker 2 PASS + `test_final_verification_stage_pick_excludes_auto`(이제 stage 별 라벨에 `[미완]` 가 붙지만 value 는 `["1","2","3"]` 유지) 포함 기존 전부 PASS
|
|
295
|
-
|
|
296
|
-
> 주의: `test_final_verification_stage_pick_excludes_auto` 는 done 행이 없는 plan 을 쓰므로 whole-task 항목이 안 뜨고 `values == ["1","2","3"]` 가 유지된다. 라벨 문자열은 검사하지 않으므로 마킹 추가와 무관하다.
|
|
297
|
-
|
|
298
|
-
- [ ] **Step 5: 커밋**
|
|
299
|
-
|
|
300
|
-
```bash
|
|
301
|
-
git add scripts/okstra_ctl/wizard.py prompts/wizard/prompts.ko.json tests/test_wizard_whole_task_fv.py
|
|
302
|
-
git commit -m "feat(wizard): final-verification picker 에 done 마킹 + 전체 task 항목"
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
---
|
|
306
|
-
|
|
307
|
-
## Task 3: submit 이 전체 task sentinel 수용
|
|
308
|
-
|
|
309
|
-
**Files:**
|
|
310
|
-
- Modify: `scripts/okstra_ctl/wizard.py:1536-1552` (`_submit_stage_pick`)
|
|
311
|
-
- Test: `tests/test_wizard_whole_task_fv.py`
|
|
312
|
-
|
|
313
|
-
- [ ] **Step 1: 실패 테스트 추가**
|
|
314
|
-
|
|
315
|
-
```python
|
|
316
|
-
def test_submit_accepts_whole_task_for_fv(tmp_path):
|
|
317
|
-
wizard = _load_wizard()
|
|
318
|
-
state = wizard.WizardState(
|
|
319
|
-
workspace_root=str(REPO), project_root=str(tmp_path),
|
|
320
|
-
project_id="demo", task_type="final-verification")
|
|
321
|
-
result = wizard._submit_stage_pick(state, wizard.WHOLE_TASK_STAGE)
|
|
322
|
-
assert state.selected_stage == wizard.WHOLE_TASK_STAGE
|
|
323
|
-
assert result == f"stage: {wizard.WHOLE_TASK_STAGE}"
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
def test_submit_rejects_whole_task_for_implementation(tmp_path):
|
|
327
|
-
wizard = _load_wizard()
|
|
328
|
-
state = wizard.WizardState(
|
|
329
|
-
workspace_root=str(REPO), project_root=str(tmp_path),
|
|
330
|
-
project_id="demo", task_type="implementation")
|
|
331
|
-
try:
|
|
332
|
-
wizard._submit_stage_pick(state, wizard.WHOLE_TASK_STAGE)
|
|
333
|
-
assert False, "expected WizardError"
|
|
334
|
-
except wizard.WizardError as exc:
|
|
335
|
-
assert "final-verification" in str(exc)
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
- [ ] **Step 2: 테스트 실패 확인**
|
|
339
|
-
|
|
340
|
-
Run: `python3 -m pytest tests/test_wizard_whole_task_fv.py -k submit -v`
|
|
341
|
-
Expected: FAIL — sentinel 이 `int()` 분기로 빠져 "stage number" 에러
|
|
342
|
-
|
|
343
|
-
- [ ] **Step 3: 구현**
|
|
344
|
-
|
|
345
|
-
`_submit_stage_pick` 을 교체:
|
|
346
|
-
|
|
347
|
-
```python
|
|
348
|
-
def _submit_stage_pick(state: WizardState, answer: str) -> Optional[str]:
|
|
349
|
-
if not answer:
|
|
350
|
-
raise WizardError("value required")
|
|
351
|
-
if answer == "auto":
|
|
352
|
-
if not _stage_auto_allowed(state):
|
|
353
|
-
raise WizardError(
|
|
354
|
-
"final-verification requires an explicit stage number"
|
|
355
|
-
)
|
|
356
|
-
elif answer == WHOLE_TASK_STAGE:
|
|
357
|
-
if state.task_type != "final-verification":
|
|
358
|
-
raise WizardError(
|
|
359
|
-
"whole-task verification is only valid for final-verification"
|
|
360
|
-
)
|
|
361
|
-
else:
|
|
362
|
-
try:
|
|
363
|
-
int(answer)
|
|
364
|
-
except ValueError:
|
|
365
|
-
raise WizardError(
|
|
366
|
-
f"answer must be 'auto', whole-task, or a stage number, "
|
|
367
|
-
f"got {answer!r}"
|
|
368
|
-
)
|
|
369
|
-
state.selected_stage = answer
|
|
370
|
-
return f"stage: {answer}"
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
- [ ] **Step 4: 테스트 통과 + 기존 submit 회귀 확인**
|
|
374
|
-
|
|
375
|
-
Run: `python3 -m pytest tests/test_wizard_whole_task_fv.py tests/test_wizard_stage_pick.py -k submit -v`
|
|
376
|
-
Expected: 신규 2 + 기존 submit 케이스 전부 PASS
|
|
377
|
-
|
|
378
|
-
- [ ] **Step 5: 커밋**
|
|
379
|
-
|
|
380
|
-
```bash
|
|
381
|
-
git add scripts/okstra_ctl/wizard.py tests/test_wizard_whole_task_fv.py
|
|
382
|
-
git commit -m "feat(wizard): _submit_stage_pick 이 전체 task sentinel 수용"
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
---
|
|
386
|
-
|
|
387
|
-
## Task 4: render_args 빈 stage 변환 + confirmation 라벨
|
|
388
|
-
|
|
389
|
-
**Files:**
|
|
390
|
-
- Modify: `scripts/okstra_ctl/wizard.py:2792-2806` (`render_args` stage 결정부)
|
|
391
|
-
- Modify: `scripts/okstra_ctl/wizard.py:2872-2878` (`confirmation_block` stage 표기부)
|
|
392
|
-
- Test: `tests/test_wizard_whole_task_fv.py`
|
|
393
|
-
|
|
394
|
-
- [ ] **Step 1: 실패 테스트 추가**
|
|
395
|
-
|
|
396
|
-
```python
|
|
397
|
-
def test_render_args_whole_task_emits_empty_stage(tmp_path):
|
|
398
|
-
wizard = _load_wizard()
|
|
399
|
-
plan = _plan_run(tmp_path, [1, 2, 3])
|
|
400
|
-
state = wizard.WizardState(
|
|
401
|
-
workspace_root=str(REPO), project_root=str(tmp_path),
|
|
402
|
-
project_id="demo", task_type="final-verification",
|
|
403
|
-
approved_plan_path=str(plan),
|
|
404
|
-
selected_stage=wizard.WHOLE_TASK_STAGE)
|
|
405
|
-
args = wizard.render_args(state)
|
|
406
|
-
assert args["stage"] == ""
|
|
407
|
-
assert args["base-ref"] == "" # final-verification 은 base 자동 해소
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
def test_render_args_single_stage_fv_keeps_number(tmp_path):
|
|
411
|
-
wizard = _load_wizard()
|
|
412
|
-
plan = _plan_run(tmp_path, [2])
|
|
413
|
-
state = wizard.WizardState(
|
|
414
|
-
workspace_root=str(REPO), project_root=str(tmp_path),
|
|
415
|
-
project_id="demo", task_type="final-verification",
|
|
416
|
-
approved_plan_path=str(plan), selected_stage="2")
|
|
417
|
-
args = wizard.render_args(state)
|
|
418
|
-
assert args["stage"] == "2"
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
def test_confirmation_block_labels_whole_task(tmp_path):
|
|
422
|
-
wizard = _load_wizard()
|
|
423
|
-
plan = _plan_run(tmp_path, [1, 2, 3])
|
|
424
|
-
state = wizard.WizardState(
|
|
425
|
-
workspace_root=str(REPO), project_root=str(tmp_path),
|
|
426
|
-
project_id="demo", task_group="g", task_id="t",
|
|
427
|
-
task_type="final-verification", approved_plan_path=str(plan),
|
|
428
|
-
selected_stage=wizard.WHOLE_TASK_STAGE)
|
|
429
|
-
block = wizard.confirmation_block(state)
|
|
430
|
-
assert "전체 task" in block
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
- [ ] **Step 2: 테스트 실패 확인**
|
|
434
|
-
|
|
435
|
-
Run: `python3 -m pytest tests/test_wizard_whole_task_fv.py -k "render_args or confirmation" -v`
|
|
436
|
-
Expected: FAIL — sentinel 이 그대로 stage 로 새거나 `WizardError`("requires an explicit stage number")
|
|
437
|
-
|
|
438
|
-
- [ ] **Step 3: 구현**
|
|
439
|
-
|
|
440
|
-
`render_args` 의 stage 결정 블록(현재 `elif state.task_type == "final-verification":` 분기, 2799-2804)을 교체:
|
|
441
|
-
|
|
442
|
-
```python
|
|
443
|
-
if state.task_type == "implementation":
|
|
444
|
-
stage = state.selected_stage or "auto"
|
|
445
|
-
elif state.task_type == "final-verification":
|
|
446
|
-
if state.selected_stage == WHOLE_TASK_STAGE:
|
|
447
|
-
stage = "" # prepare 가 빈 stage 를 whole-task 로 해석
|
|
448
|
-
elif not state.selected_stage or state.selected_stage == "auto":
|
|
449
|
-
raise WizardError(
|
|
450
|
-
"final-verification requires an explicit stage number"
|
|
451
|
-
)
|
|
452
|
-
else:
|
|
453
|
-
stage = state.selected_stage
|
|
454
|
-
else:
|
|
455
|
-
stage = ""
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
`confirmation_block` 의 stage 표기 블록(2874-2878)을 교체:
|
|
459
|
-
|
|
460
|
-
```python
|
|
461
|
-
stage = (
|
|
462
|
-
"전체 task"
|
|
463
|
-
if state.selected_stage == WHOLE_TASK_STAGE
|
|
464
|
-
else (state.selected_stage
|
|
465
|
-
or ("auto" if state.task_type == "implementation"
|
|
466
|
-
else "(not selected)"))
|
|
467
|
-
)
|
|
468
|
-
```
|
|
469
|
-
|
|
470
|
-
- [ ] **Step 4: 테스트 통과 + render_args 회귀 확인**
|
|
471
|
-
|
|
472
|
-
Run: `python3 -m pytest tests/test_wizard_whole_task_fv.py tests/test_wizard_stage_pick.py -k "render_args or confirmation" -v`
|
|
473
|
-
Expected: 신규 3 + 기존 render_args 케이스(`test_render_args_includes_stage_for_implementation` 등) 전부 PASS
|
|
474
|
-
|
|
475
|
-
- [ ] **Step 5: 커밋**
|
|
476
|
-
|
|
477
|
-
```bash
|
|
478
|
-
git add scripts/okstra_ctl/wizard.py tests/test_wizard_whole_task_fv.py
|
|
479
|
-
git commit -m "feat(wizard): render_args 가 전체 task sentinel 을 빈 stage 로 변환"
|
|
480
|
-
```
|
|
481
|
-
|
|
482
|
-
---
|
|
483
|
-
|
|
484
|
-
## Task 5: 통합 검증 + CHANGES 기록
|
|
485
|
-
|
|
486
|
-
**Files:**
|
|
487
|
-
- Modify: `CHANGES.md`
|
|
488
|
-
- Test: 전체 위저드 스위트
|
|
489
|
-
|
|
490
|
-
- [ ] **Step 1: 전체 위저드 테스트**
|
|
491
|
-
|
|
492
|
-
Run: `python3 -m pytest tests/test_wizard_whole_task_fv.py tests/test_wizard_stage_pick.py tests/test_wizard_final_verification_stage.py tests/test_okstra_ctl_wizard.py -v`
|
|
493
|
-
Expected: 전부 PASS (whole-task 경로에서도 base-ref/branch-confirm 생략이 유지되는지 `test_okstra_ctl_wizard.py` 가 커버)
|
|
494
|
-
|
|
495
|
-
- [ ] **Step 2: build 후 runtime sync 확인**
|
|
496
|
-
|
|
497
|
-
Run: `npm run build && node bin/okstra --version`
|
|
498
|
-
Expected: 빌드 성공, 버전 출력. `runtime/` 에 prompts.ko.json·wizard.py 변경분이 반영됨(직접 편집 금지, 빌드로만).
|
|
499
|
-
|
|
500
|
-
- [ ] **Step 3: CHANGES.md 항목 추가**
|
|
501
|
-
|
|
502
|
-
`CHANGES.md` 의 최상단 날짜 섹션(`## 2026-06-11`, 없으면 생성)에 추가:
|
|
503
|
-
|
|
504
|
-
```markdown
|
|
505
|
-
### feat(wizard): final-verification 위저드에서 전체 task 검증 선택 지원
|
|
506
|
-
|
|
507
|
-
- **배경**: `54b9482` 이후 okstra-run 위저드의 `final-verification` 은 명시 stage 만 선택 가능해, 모든 stage 를 머지한 뒤 한 번 도는 전체-task 검증을 CLI `--stage auto` 로만 할 수 있었다.
|
|
508
|
-
- **해결**: stage picker 에 stage 별 done 마킹을 표시하고, 모든 stage 가 done 이면 "전체 task 검증" 항목을 노출한다. 선택 시 prepare 에 빈 stage 를 넘겨 기존 전체-task 경로를 탄다(`auto` 토큰 미사용, prepare 계약 무변경). 머지/clean 미충족은 prepare 의 기존 PrepareError 가 안내한다.
|
|
509
|
-
- 사용자 영향: 다음 release + `npx -y okstra@latest install` 후, 모든 stage 가 done 이면 위저드에서 "전체 task 검증" 을 골라 task 전체를 한 번에 검증할 수 있다.
|
|
510
|
-
```
|
|
511
|
-
|
|
512
|
-
- [ ] **Step 4: 커밋**
|
|
513
|
-
|
|
514
|
-
```bash
|
|
515
|
-
git add CHANGES.md runtime/
|
|
516
|
-
git commit -m "docs(changes): wizard 전체 task final-verification 지원 기록 + runtime 빌드"
|
|
517
|
-
```
|
|
518
|
-
|
|
519
|
-
---
|
|
520
|
-
|
|
521
|
-
## Self-Review 결과
|
|
522
|
-
|
|
523
|
-
- **Spec coverage**: §3 노출(Task 2) · §4 done 데이터원(Task 1) · §5 빈 stage emit(Task 4) · §6 게이트 함수(Task 2~4) · §7 프롬프트(Task 2) · §8 테스트(Task 1~5) — 전부 매핑됨.
|
|
524
|
-
- **Placeholder**: 모든 코드 스텝에 실제 본문 포함, TODO 없음.
|
|
525
|
-
- **Type/이름 일관성**: `WHOLE_TASK_STAGE` sentinel 이 Task 1 정의 → 2·3·4 에서 동일 이름 사용. `_parse_stage_objects`/`_done_stage_numbers`/`_whole_task_allowed` 시그니처 일관.
|
|
526
|
-
- **회귀**: 각 Task Step 4 가 기존 `test_wizard_stage_pick.py` 를 함께 돌려 단독-stage UX 불변을 확인.
|