okstra 0.102.2 → 0.102.3
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 +1 -1
- package/docs/kr/architecture.md +7 -11
- 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/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 +4 -12
- 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 +4 -12
- 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_stage.py +7 -11
- 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/stage_targets.py +18 -0
- package/runtime/python/okstra_ctl/wizard.py +24 -25
- package/runtime/python/okstra_ctl/wizard_stage_intent.py +54 -0
- 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,282 +0,0 @@
|
|
|
1
|
-
# Stage Conformance QA — Phase 3 (validate-run 게이트) 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:** `validators/validate-run.py` 가 implementation/final-verification 리포트에 대해 run 의 `qa/` 디렉터리(conformance 매니페스트 + 결과 사이드카)를 읽어 Phase 2 의 `evaluate_conformance` 로 게이트를 적용한다. BLOCKING verdict 는 run 검증 실패로 만든다 — DEV-9184 의 "정적 OK, 미검증 → silent pass" 를 실제 FAIL 로 전환하는 강제 지점.
|
|
6
|
-
|
|
7
|
-
**Architecture:** Phase 1(매니페스트 검증) + Phase 2(게이트 판정)의 순수 함수를 validate-run 에 wiring 한다. **매니페스트가 없으면 게이트는 inert**(early return) — 따라서 매니페스트를 생성하는 prompt 측(Phase 4)이 없어도 안전하게 단독 출하된다. SSOT: [`docs/superpowers/specs/2026-06-07-stage-conformance-qa-design.md`](../specs/2026-06-07-stage-conformance-qa-design.md) §6.
|
|
8
|
-
|
|
9
|
-
**Tech Stack:** Python 3 (stdlib + pytest). validate-run.py 는 importlib 로 로드되는 standalone 스크립트.
|
|
10
|
-
|
|
11
|
-
**전제:** Phase 1·2 완료 — `scripts/okstra_ctl/conformance.py` 에 `validate_conformance_manifest`, `evaluate_conformance`, `qa_result_from_dict`, `ConformanceVerdict` 존재.
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## 결과 사이드카 계약 (이 Phase 에서 확정)
|
|
16
|
-
|
|
17
|
-
- 매니페스트: `<run_dir>/qa/conformance-manifest.json` (run_dir = `report_path.parent.parent`, 기존 `validate_worker_results_audit` 의 `report_path.parent.parent / "worker-results"` 패턴과 동형).
|
|
18
|
-
- 결과 사이드카(Phase 4 의 verifier 가 작성): `<run_dir>/qa/result-<stageKey>.json` = `{"stageKey","overall","ranAt","requirements"}`. 파일 부재 → 미실행(None) → BLOCKING.
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## Task 1: conformance 게이트 함수 + 결과 로더
|
|
23
|
-
|
|
24
|
-
**Files:**
|
|
25
|
-
- Modify: `validators/validate-run.py`
|
|
26
|
-
- Test: `tests/test_validate_run_conformance.py` (신규)
|
|
27
|
-
|
|
28
|
-
- [ ] **Step 1: 실패 테스트 작성**
|
|
29
|
-
|
|
30
|
-
```python
|
|
31
|
-
# tests/test_validate_run_conformance.py
|
|
32
|
-
from __future__ import annotations
|
|
33
|
-
|
|
34
|
-
import importlib.util
|
|
35
|
-
import json
|
|
36
|
-
from pathlib import Path
|
|
37
|
-
|
|
38
|
-
REPO_ROOT = Path(__file__).resolve().parent.parent
|
|
39
|
-
VALIDATOR_PATH = REPO_ROOT / "validators" / "validate-run.py"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def _load_validator():
|
|
43
|
-
spec = importlib.util.spec_from_file_location("validate_run", VALIDATOR_PATH)
|
|
44
|
-
module = importlib.util.module_from_spec(spec)
|
|
45
|
-
assert spec.loader is not None
|
|
46
|
-
spec.loader.exec_module(module)
|
|
47
|
-
return module
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def _make_run(tmp_path: Path, entries, results):
|
|
51
|
-
run_dir = tmp_path / "runs" / "implementation"
|
|
52
|
-
(run_dir / "reports").mkdir(parents=True)
|
|
53
|
-
qa = run_dir / "qa"
|
|
54
|
-
qa.mkdir()
|
|
55
|
-
(qa / "conformance-manifest.json").write_text(json.dumps({"entries": entries}))
|
|
56
|
-
for key, overall in results.items():
|
|
57
|
-
(qa / f"result-{key}.json").write_text(
|
|
58
|
-
json.dumps({"stageKey": key, "overall": overall, "requirements": {}})
|
|
59
|
-
)
|
|
60
|
-
report = run_dir / "reports" / "final-report-implementation-001.md"
|
|
61
|
-
report.write_text("# fixture\n")
|
|
62
|
-
return report
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def _entry(key, **over):
|
|
66
|
-
base = {"stageKey": key, "script": f"qa/{key}.ts", "runCommand": f"run {key}",
|
|
67
|
-
"requirementIds": ["R-001"], "requires": ["db"],
|
|
68
|
-
"passContract": "exit 0 = PASS", "exemption": None, "waiver": None}
|
|
69
|
-
base.update(over)
|
|
70
|
-
return base
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def test_no_manifest_is_inert(tmp_path):
|
|
74
|
-
v = _load_validator()
|
|
75
|
-
run_dir = tmp_path / "runs" / "implementation"
|
|
76
|
-
(run_dir / "reports").mkdir(parents=True)
|
|
77
|
-
report = run_dir / "reports" / "final-report-implementation-001.md"
|
|
78
|
-
report.write_text("# fixture\n")
|
|
79
|
-
failures: list[str] = []
|
|
80
|
-
v._validate_conformance(report, failures)
|
|
81
|
-
assert failures == []
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
def test_passing_result_no_failure(tmp_path):
|
|
85
|
-
v = _load_validator()
|
|
86
|
-
report = _make_run(tmp_path, [_entry("t-stage-1")], {"t-stage-1": "PASS"})
|
|
87
|
-
failures: list[str] = []
|
|
88
|
-
v._validate_conformance(report, failures)
|
|
89
|
-
assert failures == []
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def test_missing_result_is_blocking(tmp_path):
|
|
93
|
-
v = _load_validator()
|
|
94
|
-
report = _make_run(tmp_path, [_entry("t-stage-1")], {}) # no result file
|
|
95
|
-
failures: list[str] = []
|
|
96
|
-
v._validate_conformance(report, failures)
|
|
97
|
-
assert any("BLOCKING" in f and "t-stage-1" in f for f in failures)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def test_failing_result_is_blocking(tmp_path):
|
|
101
|
-
v = _load_validator()
|
|
102
|
-
report = _make_run(tmp_path, [_entry("t-stage-1")], {"t-stage-1": "FAIL"})
|
|
103
|
-
failures: list[str] = []
|
|
104
|
-
v._validate_conformance(report, failures)
|
|
105
|
-
assert any("BLOCKING" in f for f in failures)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
def test_exemption_passes(tmp_path):
|
|
109
|
-
v = _load_validator()
|
|
110
|
-
entry = _entry("t-stage-1", exemption={"reason": "doc", "declaredAt": "2026-06-07"})
|
|
111
|
-
report = _make_run(tmp_path, [entry], {})
|
|
112
|
-
failures: list[str] = []
|
|
113
|
-
v._validate_conformance(report, failures)
|
|
114
|
-
assert failures == []
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
def test_waiver_passes_but_records_conditional(tmp_path):
|
|
118
|
-
v = _load_validator()
|
|
119
|
-
entry = _entry("t-stage-1", waiver={"acknowledgedBy": "user", "reason": "replica down",
|
|
120
|
-
"at": "2026-06-07", "scope": ["db"]})
|
|
121
|
-
report = _make_run(tmp_path, [entry], {})
|
|
122
|
-
failures: list[str] = []
|
|
123
|
-
v._validate_conformance(report, failures)
|
|
124
|
-
assert failures == [] # waiver = ok (conditional, not a failure)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
def test_malformed_manifest_reported(tmp_path):
|
|
128
|
-
v = _load_validator()
|
|
129
|
-
report = _make_run(tmp_path, [{"stageKey": ""}], {}) # invalid entry
|
|
130
|
-
failures: list[str] = []
|
|
131
|
-
v._validate_conformance(report, failures)
|
|
132
|
-
assert any("conformance manifest" in f for f in failures)
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
- [ ] **Step 2: 실패 확인**
|
|
136
|
-
|
|
137
|
-
Run: `python3 -m pytest tests/test_validate_run_conformance.py -q`
|
|
138
|
-
Expected: FAIL — `module 'validate_run' has no attribute '_validate_conformance'`
|
|
139
|
-
|
|
140
|
-
- [ ] **Step 3: 구현 추가**
|
|
141
|
-
|
|
142
|
-
`validators/validate-run.py` 상단의 `from okstra_project.dirs import tasks_root as _okstra_tasks_root` (line 33 부근) 다음에 import 추가:
|
|
143
|
-
|
|
144
|
-
```python
|
|
145
|
-
from okstra_ctl.conformance import ( # noqa: E402
|
|
146
|
-
evaluate_conformance,
|
|
147
|
-
qa_result_from_dict,
|
|
148
|
-
validate_conformance_manifest,
|
|
149
|
-
)
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
`validate_report` 함수 정의 바로 앞(`def validate_report(` 위)에 두 함수 추가:
|
|
153
|
-
|
|
154
|
-
```python
|
|
155
|
-
def _load_conformance_results(qa_dir: Path, manifest: dict) -> dict:
|
|
156
|
-
"""매니페스트 각 entry 에 대응하는 `result-<stageKey>.json` 을 로드.
|
|
157
|
-
파일 부재/파손은 키를 비워 둬 미실행(None→BLOCKING)으로 흐르게 한다."""
|
|
158
|
-
results: dict = {}
|
|
159
|
-
for entry in manifest.get("entries", []):
|
|
160
|
-
key = entry.get("stageKey") if isinstance(entry, dict) else None
|
|
161
|
-
if not isinstance(key, str) or not key:
|
|
162
|
-
continue
|
|
163
|
-
sidecar = qa_dir / f"result-{key}.json"
|
|
164
|
-
if not sidecar.is_file():
|
|
165
|
-
continue
|
|
166
|
-
try:
|
|
167
|
-
results[key] = qa_result_from_dict(json.loads(sidecar.read_text()))
|
|
168
|
-
except (OSError, json.JSONDecodeError):
|
|
169
|
-
results[key] = qa_result_from_dict(None) # → MISSING → BLOCKING
|
|
170
|
-
return results
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
def _validate_conformance(report_path: Path, failures: list[str]) -> None:
|
|
174
|
-
"""Tier 3 conformance 게이트(implementation / final-verification).
|
|
175
|
-
|
|
176
|
-
`<run_dir>/qa/conformance-manifest.json` 이 없으면 inert(선언된 conformance
|
|
177
|
-
가 없다는 뜻 — 선언을 강제하는 것은 planning 계약(Phase 4)의 몫). 매니페스트가
|
|
178
|
-
있으면 결과 사이드카와 함께 evaluate_conformance 로 판정하고 BLOCKING verdict
|
|
179
|
-
를 run 검증 실패로 승격한다. WAIVED(conditional)/EXEMPT 는 통과시킨다.
|
|
180
|
-
"""
|
|
181
|
-
qa_dir = report_path.parent.parent / "qa"
|
|
182
|
-
manifest_path = qa_dir / "conformance-manifest.json"
|
|
183
|
-
if not manifest_path.is_file():
|
|
184
|
-
return
|
|
185
|
-
try:
|
|
186
|
-
manifest = json.loads(manifest_path.read_text())
|
|
187
|
-
except (OSError, json.JSONDecodeError) as exc:
|
|
188
|
-
failures.append(f"conformance manifest unreadable at {manifest_path}: {exc}")
|
|
189
|
-
return
|
|
190
|
-
schema_errors = validate_conformance_manifest(manifest)
|
|
191
|
-
if schema_errors:
|
|
192
|
-
failures.extend(f"conformance manifest: {e}" for e in schema_errors)
|
|
193
|
-
return
|
|
194
|
-
results = _load_conformance_results(qa_dir, manifest)
|
|
195
|
-
for verdict in evaluate_conformance(manifest, results):
|
|
196
|
-
if not verdict.ok:
|
|
197
|
-
failures.append(
|
|
198
|
-
f"conformance gate BLOCKING for stage {verdict.stage_key}: "
|
|
199
|
-
f"{verdict.message}. Run the stage's conformance script (or declare "
|
|
200
|
-
f"an exemption / user waiver) — see "
|
|
201
|
-
f"docs/superpowers/specs/2026-06-07-stage-conformance-qa-design.md."
|
|
202
|
-
)
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
- [ ] **Step 4: 통과 확인**
|
|
206
|
-
|
|
207
|
-
Run: `python3 -m pytest tests/test_validate_run_conformance.py -q`
|
|
208
|
-
Expected: PASS (7 passed)
|
|
209
|
-
|
|
210
|
-
- [ ] **Step 5: 커밋**
|
|
211
|
-
|
|
212
|
-
```bash
|
|
213
|
-
git add validators/validate-run.py tests/test_validate_run_conformance.py
|
|
214
|
-
git commit -m "feat(validators): conformance Tier3 게이트 함수(_validate_conformance)"
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
## Task 2: 메인 dispatch 에 게이트 wiring
|
|
218
|
-
|
|
219
|
-
**Files:**
|
|
220
|
-
- Modify: `validators/validate-run.py`
|
|
221
|
-
|
|
222
|
-
- [ ] **Step 1: dispatch 에 호출 추가**
|
|
223
|
-
|
|
224
|
-
`validate-run.py` 의 메인 dispatch 에서 `validate_worker_results_audit` 호출 블록 다음, `if task_type == "improvement-discovery":` 앞에 추가:
|
|
225
|
-
|
|
226
|
-
```python
|
|
227
|
-
if task_type in ("implementation", "final-verification"):
|
|
228
|
-
_validate_conformance(report_path, failures)
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
(찾을 앵커 — 현재 코드:)
|
|
232
|
-
|
|
233
|
-
```python
|
|
234
|
-
if task_type:
|
|
235
|
-
validate_worker_results_audit(report_path, task_type, failures)
|
|
236
|
-
if task_type == "improvement-discovery":
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
- [ ] **Step 2: 기존 스위트 회귀 + workflow validator 확인**
|
|
240
|
-
|
|
241
|
-
Run: `python3 -m pytest tests/ -q`
|
|
242
|
-
Expected: 전부 통과(신규 7 포함, 회귀 없음). validate-workflow 의 final-verification fixture 는 `qa/` 디렉터리가 없으므로 게이트는 inert → 영향 없음.
|
|
243
|
-
|
|
244
|
-
Run: `bash validators/validate-workflow.sh`
|
|
245
|
-
Expected: 마지막에 PASS (게이트 inert).
|
|
246
|
-
|
|
247
|
-
- [ ] **Step 3: 코드 확인(수동)**
|
|
248
|
-
|
|
249
|
-
`grep -n "_validate_conformance" validators/validate-run.py` → 정의 1 + 호출 1 = 2건.
|
|
250
|
-
|
|
251
|
-
- [ ] **Step 4: 커밋**
|
|
252
|
-
|
|
253
|
-
```bash
|
|
254
|
-
git add validators/validate-run.py
|
|
255
|
-
git commit -m "feat(validators): implementation/final-verification 에 conformance 게이트 연결"
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
---
|
|
259
|
-
|
|
260
|
-
## Phase 3 Self-Review 체크
|
|
261
|
-
|
|
262
|
-
- [ ] 매니페스트 부재 시 inert(early return) 확인 — 기존 run 들이 깨지지 않는가?
|
|
263
|
-
- [ ] BLOCKING(미실행/MISSING/FAIL) → failures 추가, EXEMPT/WAIVED → 통과가 spec §6/§7 과 일치하는가?
|
|
264
|
-
- [ ] run_dir 해석(`report_path.parent.parent`)이 기존 `validate_worker_results_audit` 와 동형인가?
|
|
265
|
-
- [ ] 전체 pytest + workflow validator 통과(회귀 없음)?
|
|
266
|
-
|
|
267
|
-
---
|
|
268
|
-
|
|
269
|
-
## Phase 4 로 넘길 항목 + ⚠️ 미해결 설계 갬
|
|
270
|
-
|
|
271
|
-
본 게이트는 매니페스트/결과가 존재할 때만 작동한다. 그것을 **생성·실행**하는 다음 작업들은 Phase 4 이며, 일부는 **계획 전 설계 확정이 필요**하다(추측 금지):
|
|
272
|
-
|
|
273
|
-
1. **verifier 실행(prompt)**: `_implementation-verifier.md` 에 Tier 3 추가 — 각 entry 의 `runCommand` 실행 → `parse_qa_result` → `<run_dir>/qa/result-<stageKey>.json` 작성. (env/secret 접근, replica DB, mutation 가드 포함)
|
|
274
|
-
2. **planning 생성(prompt)**: `implementation-planning.md` 가 stage 별 스크립트 + `conformance-manifest.json` + `Conformance exemption:` 라인 산출.
|
|
275
|
-
3. **final-verification(prompt)**: 전 stage 합집합 실행.
|
|
276
|
-
4. **우회 UX**: `--qa-waiver <stageKey>:"<reason>"` CLI(okstra.sh/cli.sh) + wizard picker → `run.py` 가 매니페스트 entry 의 `waiver` 채움.
|
|
277
|
-
5. **env**: `project.json.qaEnv`(replicaDbDsn/appBaseUrl/envFile).
|
|
278
|
-
|
|
279
|
-
**⚠️ 설계 확정 필요(Phase 4 계획 전 brainstorm 보강 권장):**
|
|
280
|
-
- **매니페스트의 교차-phase 위치**: planning 이 만든 매니페스트/스크립트가 implementation run, 이어서 final-verification run 으로 어떻게 전달되는가? (task-key worktree vs stage worktree vs instruction-set 복사) — stage worktree isolation 과 정합해야 함.
|
|
281
|
-
- **"diff 가 surface 를 건드렸는데 매니페스트 entry 자체가 없음"** (planning 누락) 강제: 본 게이트는 선언된 entry 만 강제한다. 누락 탐지는 planning 계약 + diff-surface 휴리스틱이 필요(spec §7.1 선언형 면제 surface 교차검증과 함께).
|
|
282
|
-
- **env/secret 운영 모델**: replica DB·실행 env 를 누가 어떻게 주입하는가.
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
# Stage Conformance QA — Phase 4a (위치 SSOT + 게이트 task-level 전환) 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:** conformance 산출물의 단일 출처를 task-level `<task_root>/qa/` 로 확정한다 — `paths.py` 에 `TASK_QA_PATH` 토큰을 추가하고, Phase 3 게이트(`_validate_conformance`)가 run-level 대신 task-level `qa/` 를 읽도록 고친다(Phase 3 의 final-verification 잠복 결함 해소).
|
|
6
|
-
|
|
7
|
-
**Architecture:** 순수 경로/검증 변경. SSOT: [`docs/superpowers/specs/2026-06-07-stage-conformance-qa-design.md`](../specs/2026-06-07-stage-conformance-qa-design.md) §12.1.
|
|
8
|
-
|
|
9
|
-
**Tech Stack:** Python 3 (stdlib + pytest).
|
|
10
|
-
|
|
11
|
-
**전제:** Phase 1~3 완료. `validators/validate-run.py` 에 `_validate_conformance` 존재, `tests/test_validate_run_conformance.py` 존재.
|
|
12
|
-
|
|
13
|
-
**경로 사실(확정):** report_path = `task_root/runs/<task-type>/reports/final-report-*.md`. 따라서 `run_dir = report_path.parent.parent`(=`runs/<task-type>`), `task_root = run_dir.parent.parent`, `qa_dir = task_root / "qa"`. (`report_path.parent.parent.parent` 는 `runs/` 이므로 잘못 — 한 단계 더 올라가야 함.)
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## Task 1: `paths.py` 에 TASK_QA_PATH 토큰 추가
|
|
18
|
-
|
|
19
|
-
**Files:**
|
|
20
|
-
- Modify: `scripts/okstra_ctl/paths.py`
|
|
21
|
-
- Test: `tests/test_task_path_ssot.py`
|
|
22
|
-
|
|
23
|
-
- [ ] **Step 1: 실패 테스트 추가**
|
|
24
|
-
|
|
25
|
-
`tests/test_task_path_ssot.py` 끝에 추가:
|
|
26
|
-
|
|
27
|
-
```python
|
|
28
|
-
def test_task_qa_path_under_task_root():
|
|
29
|
-
root = Path("/tmp/proj")
|
|
30
|
-
ctx = compute_run_paths(
|
|
31
|
-
workspace_root=Path("/ws"),
|
|
32
|
-
project_root=root,
|
|
33
|
-
project_id="p",
|
|
34
|
-
task_group="My Group",
|
|
35
|
-
task_id="Task ID 01",
|
|
36
|
-
task_type="implementation",
|
|
37
|
-
run_seq_override=1,
|
|
38
|
-
)
|
|
39
|
-
assert ctx["TASK_QA_PATH"] == str(Path(ctx["TASK_ROOT"]) / "qa")
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
- [ ] **Step 2: 실패 확인**
|
|
43
|
-
|
|
44
|
-
Run: `python3 -m pytest tests/test_task_path_ssot.py -q`
|
|
45
|
-
Expected: FAIL — `KeyError: 'TASK_QA_PATH'`
|
|
46
|
-
|
|
47
|
-
- [ ] **Step 3: 구현**
|
|
48
|
-
|
|
49
|
-
`scripts/okstra_ctl/paths.py` 의 `analysis_packet = instruction_set / "analysis-packet.md"` (line 119 부근) 다음 줄에 추가:
|
|
50
|
-
|
|
51
|
-
```python
|
|
52
|
-
task_qa = task_root / "qa"
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
같은 함수의 `abs_paths` 딕셔너리에서 `"ANALYSIS_PACKET_PATH": str(analysis_packet),` 다음 줄에 추가:
|
|
56
|
-
|
|
57
|
-
```python
|
|
58
|
-
"TASK_QA_PATH": str(task_qa),
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
- [ ] **Step 4: 통과 확인**
|
|
62
|
-
|
|
63
|
-
Run: `python3 -m pytest tests/test_task_path_ssot.py -q`
|
|
64
|
-
Expected: PASS
|
|
65
|
-
|
|
66
|
-
- [ ] **Step 5: 커밋**
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
git add scripts/okstra_ctl/paths.py tests/test_task_path_ssot.py
|
|
70
|
-
git commit -m "feat(okstra_ctl/paths): conformance task-level qa 경로 토큰(TASK_QA_PATH)"
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## Task 2: 게이트를 task-level `qa/` 로 전환
|
|
74
|
-
|
|
75
|
-
**Files:**
|
|
76
|
-
- Modify: `validators/validate-run.py`
|
|
77
|
-
- Test: `tests/test_validate_run_conformance.py`
|
|
78
|
-
|
|
79
|
-
- [ ] **Step 1: 테스트 fixture 를 task-level 로 갱신(먼저 실패 유도)**
|
|
80
|
-
|
|
81
|
-
`tests/test_validate_run_conformance.py` 의 `_make_run` 에서 qa 디렉터리를 task_root(=`tmp_path`) 아래로 옮긴다. 현재:
|
|
82
|
-
|
|
83
|
-
```python
|
|
84
|
-
run_dir = tmp_path / "runs" / "implementation"
|
|
85
|
-
(run_dir / "reports").mkdir(parents=True)
|
|
86
|
-
qa = run_dir / "qa"
|
|
87
|
-
qa.mkdir()
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
로 바꾼다:
|
|
91
|
-
|
|
92
|
-
```python
|
|
93
|
-
run_dir = tmp_path / "runs" / "implementation"
|
|
94
|
-
(run_dir / "reports").mkdir(parents=True)
|
|
95
|
-
qa = tmp_path / "qa" # task-level: <task_root>/qa (task_root = tmp_path)
|
|
96
|
-
qa.mkdir()
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
(`test_no_manifest_is_inert` 는 qa 를 만들지 않으므로 그대로 inert — 변경 불필요.)
|
|
100
|
-
|
|
101
|
-
- [ ] **Step 2: 실패 확인**
|
|
102
|
-
|
|
103
|
-
Run: `python3 -m pytest tests/test_validate_run_conformance.py -q`
|
|
104
|
-
Expected: FAIL — 게이트가 아직 run-level(`run_dir/qa`)을 읽어 매니페스트를 못 찾고 inert 처리 → `test_missing_result_is_blocking`/`test_failing_result_is_blocking`/`test_malformed_manifest_reported` 가 기대 실패를 못 내고 FAIL.
|
|
105
|
-
|
|
106
|
-
- [ ] **Step 3: 구현 — 게이트 경로 수정**
|
|
107
|
-
|
|
108
|
-
`validators/validate-run.py` 의 `_validate_conformance` 에서:
|
|
109
|
-
|
|
110
|
-
```python
|
|
111
|
-
qa_dir = report_path.parent.parent / "qa"
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
를 다음으로 바꾼다:
|
|
115
|
-
|
|
116
|
-
```python
|
|
117
|
-
# conformance 산출물은 task-level(<task_root>/qa)에 있어 planning/
|
|
118
|
-
# implementation/final-verification 가 공유한다. report_path 는
|
|
119
|
-
# task_root/runs/<task-type>/reports/final-report.md 이므로 task_root 는
|
|
120
|
-
# run_dir(=report_path.parent.parent)에서 두 단계 위.
|
|
121
|
-
run_dir = report_path.parent.parent
|
|
122
|
-
qa_dir = run_dir.parent.parent / "qa"
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
- [ ] **Step 4: 통과 확인 + 전체 회귀 + workflow validator**
|
|
126
|
-
|
|
127
|
-
Run: `python3 -m pytest tests/test_validate_run_conformance.py -q` → Expected: PASS (7 passed)
|
|
128
|
-
Run: `python3 -m pytest tests/ -q` → Expected: 전부 통과
|
|
129
|
-
Run: `bash validators/validate-workflow.sh` → Expected: PASS (fixture 에 `<task_root>/qa` 없음 → inert)
|
|
130
|
-
|
|
131
|
-
- [ ] **Step 5: 커밋**
|
|
132
|
-
|
|
133
|
-
```bash
|
|
134
|
-
git add validators/validate-run.py tests/test_validate_run_conformance.py
|
|
135
|
-
git commit -m "fix(validators): conformance 게이트를 task-level qa 로 전환(final-verification 공유)"
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
---
|
|
139
|
-
|
|
140
|
-
## Phase 4a Self-Review 체크
|
|
141
|
-
|
|
142
|
-
- [ ] `TASK_QA_PATH == <task_root>/qa` 인가?
|
|
143
|
-
- [ ] 게이트가 task_root/qa 를 읽어 implementation·final-verification 가 같은 위치를 보는가?
|
|
144
|
-
- [ ] inert(매니페스트 부재) 동작 유지 — 기존 run/ workflow validator 무영향?
|
|
145
|
-
- [ ] 전체 pytest + workflow validator 통과?
|
|
146
|
-
|
|
147
|
-
Phase 4a 완료 후 Phase 4b(`detect_surfaces` + diff-surface 교차검증) 계획을 작성한다.
|