okstra 0.102.1 → 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.
Files changed (162) hide show
  1. package/README.kr.md +5 -6
  2. package/README.md +5 -6
  3. package/docs/kr/architecture/storage-model.md +1 -1
  4. package/docs/kr/architecture.md +8 -12
  5. package/docs/kr/cli.md +6 -6
  6. package/docs/kr/container.md +1 -1
  7. package/docs/kr/performance-improvement-plan-v2.md +2 -2
  8. package/docs/project-structure-overview.md +2 -2
  9. package/package.json +7 -2
  10. package/runtime/BUILD.json +2 -2
  11. package/runtime/bin/okstra-antigravity-exec.sh +1 -2
  12. package/runtime/bin/okstra-codex-exec.sh +1 -2
  13. package/runtime/bin/okstra-render-final-report.py +2 -9
  14. package/runtime/bin/okstra-spawn-followups.py +4 -6
  15. package/runtime/bin/okstra-trace-cleanup.sh +24 -4
  16. package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
  17. package/runtime/prompts/lead/report-writer.md +1 -1
  18. package/runtime/prompts/profiles/_common-contract.md +9 -11
  19. package/runtime/python/okstra_ctl/codex_dispatch.py +4 -12
  20. package/runtime/python/okstra_ctl/consumers.py +35 -0
  21. package/runtime/python/okstra_ctl/container.py +4 -6
  22. package/runtime/python/okstra_ctl/dispatch_core.py +4 -12
  23. package/runtime/python/okstra_ctl/final_report_paths.py +24 -0
  24. package/runtime/python/okstra_ctl/handoff.py +2 -1
  25. package/runtime/python/okstra_ctl/implementation_stage.py +7 -11
  26. package/runtime/python/okstra_ctl/report_view_artifacts.py +14 -0
  27. package/runtime/python/okstra_ctl/report_views.py +7 -4
  28. package/runtime/python/okstra_ctl/run.py +3 -10
  29. package/runtime/python/okstra_ctl/stage_targets.py +18 -0
  30. package/runtime/python/okstra_ctl/wizard.py +24 -25
  31. package/runtime/python/okstra_ctl/wizard_stage_intent.py +54 -0
  32. package/runtime/python/okstra_token_usage/report.py +2 -5
  33. package/runtime/validators/validate-report-views.py +2 -1
  34. package/runtime/validators/validate-run.py +1 -11
  35. package/src/cli-registry.mjs +1 -1
  36. package/src/commands/lifecycle/install.mjs +10 -20
  37. package/src/commands/lifecycle/uninstall.mjs +7 -10
  38. package/docs/superpowers/plans/2026-05-12-ticket-id-in-reports.md +0 -638
  39. package/docs/superpowers/plans/2026-05-14-convergence-queue-pruning.md +0 -1568
  40. package/docs/superpowers/plans/2026-05-17-dual-format-final-report.md +0 -167
  41. package/docs/superpowers/plans/2026-05-20-final-report-language.md +0 -1501
  42. package/docs/superpowers/plans/2026-05-20-implementation-planning-multi-stage.md +0 -1267
  43. package/docs/superpowers/plans/2026-05-20-okstra-run-prompt-sot-b1.md +0 -1007
  44. package/docs/superpowers/plans/2026-05-20-wizard-messages-json-sot.md +0 -720
  45. package/docs/superpowers/plans/2026-05-20-wizard-prompt-json-sot-a1.md +0 -681
  46. package/docs/superpowers/plans/2026-05-21-improvement-discovery-task-type.md +0 -1691
  47. package/docs/superpowers/plans/2026-05-24-implementation-lead-context-slimming.md +0 -1700
  48. package/docs/superpowers/plans/2026-05-25-okstra-project-root-rename.md +0 -158
  49. package/docs/superpowers/plans/2026-05-26-wizard-3-option-picker.md +0 -860
  50. package/docs/superpowers/plans/2026-06-02-final-verification-protocol-hardening.md +0 -326
  51. package/docs/superpowers/plans/2026-06-02-okstra-run-branch-confirm-step.md +0 -337
  52. package/docs/superpowers/plans/2026-06-02-okstra-run-phase-pane-cleanup.md +0 -410
  53. package/docs/superpowers/plans/2026-06-02-requirements-discovery-fanout.md +0 -728
  54. package/docs/superpowers/plans/2026-06-04-adversarial-implementation-planning.md +0 -294
  55. package/docs/superpowers/plans/2026-06-04-adversarial-verification.md +0 -570
  56. package/docs/superpowers/plans/2026-06-04-coverage-critic.md +0 -516
  57. package/docs/superpowers/plans/2026-06-04-stage-cohesion-planner.md +0 -351
  58. package/docs/superpowers/plans/2026-06-04-stage-run-batching.md +0 -457
  59. package/docs/superpowers/plans/2026-06-05-acceptance-critic.md +0 -251
  60. package/docs/superpowers/plans/2026-06-05-compact-markdown-report-tables.md +0 -323
  61. package/docs/superpowers/plans/2026-06-05-wizard-batch-prompts.md +0 -559
  62. package/docs/superpowers/plans/2026-06-06-final-verification-whole-task-gate.md +0 -993
  63. package/docs/superpowers/plans/2026-06-06-stage-parallel-and-pending-fixes.md +0 -93
  64. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p1.md +0 -447
  65. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p2.md +0 -289
  66. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p3.md +0 -774
  67. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p4.md +0 -303
  68. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p5-multidep-base.md +0 -387
  69. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase2.md +0 -275
  70. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase3.md +0 -282
  71. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4a.md +0 -147
  72. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4b.md +0 -262
  73. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4c.md +0 -184
  74. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4d.md +0 -88
  75. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4e.md +0 -250
  76. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa.md +0 -409
  77. package/docs/superpowers/plans/2026-06-09-implementation-run-artifact-stage-isolation.md +0 -320
  78. package/docs/superpowers/plans/2026-06-10-concurrent-run-team-guard.md +0 -456
  79. package/docs/superpowers/plans/2026-06-10-git-reconcile-stale-sha-recovery.md +0 -1408
  80. package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling-PROBE.md +0 -42
  81. package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling.md +0 -337
  82. package/docs/superpowers/plans/2026-06-10-p6-token-usage-incremental.md +0 -1029
  83. package/docs/superpowers/plans/2026-06-10-stage-group-handoff.md +0 -1572
  84. package/docs/superpowers/plans/2026-06-11-fix-cycle.md +0 -1290
  85. package/docs/superpowers/plans/2026-06-11-wizard-whole-task-final-verification.md +0 -526
  86. package/docs/superpowers/plans/2026-06-12-html-plan-approval.md +0 -1000
  87. package/docs/superpowers/plans/2026-06-13-repo-risk-hardening.md +0 -493
  88. package/docs/superpowers/plans/2026-06-14-host-runtime-auto-execution.md +0 -1775
  89. package/docs/superpowers/plans/2026-06-15-coding-preflight-pack-dispatch-path.md +0 -504
  90. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-final-fixups.md +0 -342
  91. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-fixups.md +0 -258
  92. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-remaining-fixups.md +0 -387
  93. package/docs/superpowers/plans/2026-06-15-internal-skill-resource-migration.md +0 -749
  94. package/docs/superpowers/plans/2026-06-15-worker-prompt-anchor-final-fixups.md +0 -828
  95. package/docs/superpowers/plans/2026-06-15-worker-prompt-header-error-contract.md +0 -490
  96. package/docs/superpowers/plans/2026-06-17-okstra-error-report.md +0 -724
  97. package/docs/superpowers/plans/2026-06-18-subagent-pane-reclaim.md +0 -483
  98. package/docs/superpowers/plans/2026-06-19-agent-operating-standard.md +0 -476
  99. package/docs/superpowers/plans/2026-06-19-okstra-inspect-recap-facet.md +0 -647
  100. package/docs/superpowers/plans/2026-06-20-error-feedback-loop.md +0 -1019
  101. package/docs/superpowers/plans/2026-06-20-run-index-row-normalization.md +0 -583
  102. package/docs/superpowers/plans/2026-06-20-stage-auto-integrate-teardown.md +0 -819
  103. package/docs/superpowers/plans/2026-06-21-okstra-container-local-user-test.md +0 -714
  104. package/docs/superpowers/plans/2026-06-21-release-handoff-local-checkout.md +0 -348
  105. package/docs/superpowers/plans/2026-06-23-implementation-stage-multiselect-chain.md +0 -630
  106. package/docs/superpowers/plans/2026-06-23-implementation-step-commit-granularity.md +0 -274
  107. package/docs/superpowers/plans/2026-06-23-phase-batch-cleanup-enforcement.md +0 -409
  108. package/docs/superpowers/plans/2026-06-24-cross-project-precondition.md +0 -542
  109. package/docs/superpowers/plans/2026-06-24-decision-drafts-render-gap.md +0 -568
  110. package/docs/superpowers/plans/2026-06-24-manual-user-test-section.md +0 -203
  111. package/docs/superpowers/plans/2026-06-24-okstra-container-build-rename.md +0 -525
  112. package/docs/superpowers/specs/2026-05-12-ticket-id-in-reports-design.md +0 -131
  113. package/docs/superpowers/specs/2026-05-15-implementation-plan-verification-design.md +0 -254
  114. package/docs/superpowers/specs/2026-05-20-final-report-language-design.md +0 -383
  115. package/docs/superpowers/specs/2026-05-20-implementation-planning-multi-stage-design.md +0 -322
  116. package/docs/superpowers/specs/2026-05-20-okstra-run-prompt-sot-design.md +0 -299
  117. package/docs/superpowers/specs/2026-05-21-improvement-discovery-task-type-design.md +0 -335
  118. package/docs/superpowers/specs/2026-06-02-okstra-run-branch-confirm-step-design.md +0 -113
  119. package/docs/superpowers/specs/2026-06-02-okstra-run-phase-pane-cleanup-design.md +0 -173
  120. package/docs/superpowers/specs/2026-06-02-requirements-discovery-fanout-design.md +0 -154
  121. package/docs/superpowers/specs/2026-06-04-adversarial-implementation-planning-design.md +0 -90
  122. package/docs/superpowers/specs/2026-06-04-adversarial-verification-design.md +0 -176
  123. package/docs/superpowers/specs/2026-06-04-coverage-critic-design.md +0 -99
  124. package/docs/superpowers/specs/2026-06-04-stage-splitting-cost-aware-design.md +0 -98
  125. package/docs/superpowers/specs/2026-06-05-acceptance-critic-design.md +0 -90
  126. package/docs/superpowers/specs/2026-06-05-compact-markdown-report-tables-design.md +0 -87
  127. package/docs/superpowers/specs/2026-06-05-wizard-batch-prompts-design.md +0 -121
  128. package/docs/superpowers/specs/2026-06-06-final-verification-whole-task-gate-design.md +0 -126
  129. package/docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md +0 -180
  130. package/docs/superpowers/specs/2026-06-06-vertical-slice-tdd-planning-design.md +0 -179
  131. package/docs/superpowers/specs/2026-06-07-stage-conformance-qa-design.md +0 -169
  132. package/docs/superpowers/specs/2026-06-09-executor-model-custom-id-cascade-design.md +0 -66
  133. package/docs/superpowers/specs/2026-06-09-implementation-run-artifact-stage-isolation-design.md +0 -87
  134. package/docs/superpowers/specs/2026-06-10-blocking-contract-posthoc-conformance-design.md +0 -168
  135. package/docs/superpowers/specs/2026-06-10-concurrent-run-team-guard-design.md +0 -107
  136. package/docs/superpowers/specs/2026-06-10-git-reconcile-stale-sha-recovery-design.md +0 -105
  137. package/docs/superpowers/specs/2026-06-10-lead-worker-completion-polling-design.md +0 -113
  138. package/docs/superpowers/specs/2026-06-10-stage-group-handoff-design.md +0 -156
  139. package/docs/superpowers/specs/2026-06-11-brief-entry-only-handoff-stage-entry-design.md +0 -158
  140. package/docs/superpowers/specs/2026-06-11-fix-cycle-design.md +0 -94
  141. package/docs/superpowers/specs/2026-06-11-wizard-whole-task-final-verification-design.md +0 -89
  142. package/docs/superpowers/specs/2026-06-12-codex-lead-adapter-design.md +0 -358
  143. package/docs/superpowers/specs/2026-06-12-html-plan-approval-design.md +0 -85
  144. package/docs/superpowers/specs/2026-06-12-stage-discipline-rule-design.md +0 -108
  145. package/docs/superpowers/specs/2026-06-13-forbidden-actions-ssot-design.md +0 -134
  146. package/docs/superpowers/specs/2026-06-13-neutral-tmux-lead-adapter-design.md +0 -284
  147. package/docs/superpowers/specs/2026-06-14-host-runtime-auto-execution-design.md +0 -404
  148. package/docs/superpowers/specs/2026-06-17-okstra-error-report-design.md +0 -123
  149. package/docs/superpowers/specs/2026-06-18-subagent-pane-reclaim-design.md +0 -150
  150. package/docs/superpowers/specs/2026-06-19-agent-operating-standard-design.md +0 -120
  151. package/docs/superpowers/specs/2026-06-19-okstra-inspect-recap-facet-design.md +0 -96
  152. package/docs/superpowers/specs/2026-06-20-error-feedback-loop-design.md +0 -171
  153. package/docs/superpowers/specs/2026-06-20-run-index-row-normalization-design.md +0 -112
  154. package/docs/superpowers/specs/2026-06-20-stage-auto-integrate-teardown-design.md +0 -145
  155. package/docs/superpowers/specs/2026-06-21-okstra-container-local-user-test-design.md +0 -125
  156. package/docs/superpowers/specs/2026-06-21-release-handoff-local-checkout-design.md +0 -113
  157. package/docs/superpowers/specs/2026-06-23-implementation-stage-multiselect-chain-design.md +0 -138
  158. package/docs/superpowers/specs/2026-06-23-implementation-step-commit-granularity-design.md +0 -120
  159. package/docs/superpowers/specs/2026-06-24-cross-project-precondition-design.md +0 -129
  160. package/docs/superpowers/specs/2026-06-24-decision-drafts-render-gap-design.md +0 -185
  161. package/docs/superpowers/specs/2026-06-24-manual-user-test-section-design.md +0 -121
  162. package/docs/superpowers/specs/2026-06-24-okstra-container-build-rename-design.md +0 -110
@@ -1,409 +0,0 @@
1
- # Phase-batch cleanup 강제화 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:** lead 가 phase 전환(배치 경계)마다 이전 팀원·pane 을 정리하도록, 정리 단계를 검증 가능한 `PROGRESS: phase-batch-cleanup` 체크포인트로 만들고 conformance 검증기가 누락 시 run 을 `contract-violated` 로 실패시킨다.
6
-
7
- **Architecture:** 정리 로직 자체는 이미 `prompts/profiles/_common-contract.md` "Phase-start cleanup" 에 존재하나 **강제 장치가 없어** lead 가 조용히 건너뛴다(검증되는 PROGRESS 마커 목록에 cleanup 항목 부재). freeform 상태줄을 구조화 마커로 승격하고, 기존 `_check_progress_checkpoints` 의 timestamp-anchor 패턴(이미 `_check_implementation_sidecar_reads` 에서 검증됨)을 그대로 써서 "convergence round 1 직전" 과 "report-writer dispatch 직전" 두 경계에 cleanup 마커가 선행하는지 검사한다. 부수적으로 cleanup 스크립트가 `lead_pane` 미해석 시 worker-agent pane 정리를 통째로 건너뛰던 약점을 태그-기반 anchor fallback 으로 보강한다(Task 2, 선택).
8
-
9
- **Tech Stack:** Python 3 (검증기 `validators/`, pytest `tests/`), Bash (`scripts/okstra-trace-cleanup.sh`), Markdown 계약 문서(`prompts/`), Node 빌드(`tools/build.mjs` via `npm run build`).
10
-
11
- ## Global Constraints
12
-
13
- - `runtime/` 는 빌드 산출물 — **직접 수정 금지**. 소스(`prompts/`, `scripts/`, `validators/`)만 고치고 `npm run build` 로 동기화한다.
14
- - 수정은 반드시 **소스 파일**에 — 개인 `.claude/` 가 아니라 end-user 에게 전파되는 seed/template/소스 파일에.
15
- - CI 게이트 = `npm run check` 가 exit 0 (test:js 실패 시 test:py 가 안 돌므로 통합 명령으로 확인).
16
- - 신규/대폭 수정 함수는 effective 50줄 이하.
17
- - 마커 토큰명: 정확히 **`phase-batch-cleanup`** (validator·계약 문서·테스트 3곳 철자 일치 필수).
18
- - 문서 산문은 한국어, 코드·경로·식별자·CLI 인자는 영어.
19
-
20
- ---
21
-
22
- ## File Structure
23
-
24
- | 파일 | 책임 | 작업 |
25
- |---|---|---|
26
- | `validators/validate_session_conformance.py` | conformance 검증기. `_check_progress_checkpoints` 가 필수 PROGRESS 체크포인트를 `require()`/anchor 로 강제 | 신규 헬퍼 `_check_batch_cleanup_checkpoints` 추가 + 호출부 배선 |
27
- | `tests/contract/test_validate_session_conformance.py` | 검증기 단위 테스트. `Fixture` 빌더 + `HAPPY_PROGRESS` 공용 시퀀스 | `HAPPY_PROGRESS` 에 cleanup 마커 추가, `Fixture.write_convergence_state` 헬퍼 추가, 신규 테스트 3종 |
28
- | `prompts/lead/okstra-lead-contract.md` | lead 계약 SSOT. "Progress reporting (BLOCKING)" 의 필수 마커 목록 + Enforcement 문구 | 마커 1줄 추가 + enforcement 문구에 cleanup 검사 포함 |
29
- | `prompts/profiles/_common-contract.md` | "Phase-start cleanup" 정의(공유 sidecar) | freeform 상태줄 → 구조화 마커 emit 으로 문구 교체 |
30
- | `scripts/okstra-trace-cleanup.sh` | (Task 2, 선택) run 의 trace+worker-agent pane 닫기 | `lead_pane` 미해석 시 태그-anchor 세션 fallback |
31
- | `tests/worktree/test_okstra_trace_cleanup.py` | (Task 2, 선택) cleanup 스크립트 real-tmux 테스트 | anchor fallback 테스트 1종 |
32
- | `runtime/**` | 빌드 산출물 | 손대지 않음 — `npm run build` 가 갱신 |
33
-
34
- **왜 검증기 + 계약 문서를 한 Task 로 묶는가:** 마커 정의(계약)와 강제(검증기)는 함께 배포돼야 의미가 있다 — 검사 없는 마커, 또는 문서화 안 된 마커를 강제하는 검증기는 둘 다 미완성이라 리뷰어가 함께 reject 한다.
35
-
36
- ---
37
-
38
- ## Task 1: cleanup 마커 강제화 (검증기 + 계약 문서)
39
-
40
- **Files:**
41
- - Modify: `validators/validate_session_conformance.py` (헬퍼 추가 ~line 349 뒤, 호출부 `_check_progress_checkpoints` line 395-407)
42
- - Test: `tests/contract/test_validate_session_conformance.py` (`HAPPY_PROGRESS` line 131-142, `Fixture` class line 154-232, 신규 테스트는 `test_missing_checkpoints_each_reported` line 347 부근 뒤)
43
- - Modify: `prompts/lead/okstra-lead-contract.md` (line 103 뒤 마커 추가, line 112 enforcement 문구)
44
- - Modify: `prompts/profiles/_common-contract.md` (line 37, line 43)
45
-
46
- **Interfaces:**
47
- - Consumes: 기존 `_check_progress_checkpoints(evidence, team_state, run_dir, suffix, errors)`, `_convergence_rounds_ran(run_dir, suffix) -> bool`, `by_phase: dict[str, list[tuple[ts, line]]]`, `_DISPATCHED_STATUSES`, `_is_report_writer(worker)`.
48
- - Produces: `_check_batch_cleanup_checkpoints(by_phase, convergence_ran: bool, report_writer_dispatched: bool, errors: list[str]) -> None` — `phase-batch-cleanup` 마커가 두 배치 경계에 선행하지 않으면 `errors` 에 문자열 append.
49
- - 새 마커 토큰: `phase-batch-cleanup` (라인 형식 `PROGRESS: phase-batch-cleanup panes=<n> teammates=<m>`).
50
-
51
- - [ ] **Step 1: 실패 테스트 작성 — report-writer 직전 cleanup 누락**
52
-
53
- `tests/contract/test_validate_session_conformance.py` 의 `test_missing_checkpoints_each_reported`(line 347) 바로 뒤에 추가:
54
-
55
- ```python
56
- def test_missing_batch_cleanup_before_report_writer_fails(tmp_path, module):
57
- """report-writer dispatch(phase-6-synthesis) 직전에 phase-batch-cleanup
58
- 마커가 없으면 실패 — 이전 배치 pane/teammate 가 안 치워진 채 다음 배치가
59
- 뜨는(화면 누적) 상태를 잡는다."""
60
- fx = Fixture(tmp_path)
61
- progress = [(ts, line) for ts, line in HAPPY_PROGRESS
62
- if "phase-batch-cleanup" not in line]
63
- fx.write_jsonl([_text_record(ts, line) for ts, line in progress])
64
- fx.write_heartbeat()
65
- errors = "\n".join(fx.validate(module).errors)
66
- assert "phase-batch-cleanup" in errors
67
- assert "phase-6-synthesis" in errors
68
- ```
69
-
70
- - [ ] **Step 2: 테스트 실패 확인**
71
-
72
- Run: `python3 -m pytest tests/contract/test_validate_session_conformance.py::test_missing_batch_cleanup_before_report_writer_fails -v`
73
- Expected: FAIL — `HAPPY_PROGRESS` 에 아직 `phase-batch-cleanup` 이 없어 `progress` 필터가 무의미하고, 검증기도 마커를 요구하지 않아 `errors` 가 비어 `assert "phase-batch-cleanup" in errors` 가 깨진다.
74
-
75
- - [ ] **Step 3: 검증기 헬퍼 구현**
76
-
77
- `validators/validate_session_conformance.py` 의 `_check_worker_checkpoint_lines`(line 323-348) 정의 **뒤**, `_check_progress_checkpoints` **앞**에 추가:
78
-
79
- ```python
80
- def _check_batch_cleanup_checkpoints(
81
- by_phase: dict[str, list[tuple[str, str]]],
82
- convergence_ran: bool,
83
- report_writer_dispatched: bool,
84
- errors: list[str],
85
- ) -> None:
86
- """phase-batch-cleanup: 각 배치 경계 직전에 이전 배치 pane/teammate 정리가
87
- 실제로 일어났는지 (prompts/profiles/_common-contract.md 'Phase-start cleanup').
88
- R1=convergence round 1 직전, R2=report-writer dispatch 직전(수렴이 있었으면
89
- 마지막 라운드 이후 별도 1회). ISO-8601 ts 는 lexicographic 비교가 곧 시간순."""
90
- detail = "prompts/profiles/_common-contract.md 'Phase-start cleanup'"
91
- cleanup_ts = sorted(ts for ts, _line in by_phase.get("phase-batch-cleanup", []))
92
- conv_ts = sorted(ts for ts, _line in by_phase.get("phase-5.5-convergence", []))
93
- synth_ts = sorted(ts for ts, _line in by_phase.get("phase-6-synthesis", []))
94
-
95
- if convergence_ran and conv_ts and not any(ts <= conv_ts[0] for ts in cleanup_ts):
96
- errors.append(
97
- "PROGRESS checkpoint missing: no `phase-batch-cleanup` line before the "
98
- f"first `phase-5.5-convergence` round ({conv_ts[0]}) — the prior analysis "
99
- f"batch's panes/teammates must be cleared first ({detail})."
100
- )
101
-
102
- if report_writer_dispatched and synth_ts:
103
- lower = conv_ts[-1] if (convergence_ran and conv_ts) else ""
104
- if not any(lower <= ts <= synth_ts[0] for ts in cleanup_ts):
105
- errors.append(
106
- "PROGRESS checkpoint missing: no `phase-batch-cleanup` line before "
107
- f"`phase-6-synthesis` ({synth_ts[0]}) — the prior batch must be cleared "
108
- f"before dispatching report-writer ({detail})."
109
- )
110
- ```
111
-
112
- - [ ] **Step 4: 호출부 배선**
113
-
114
- `_check_progress_checkpoints` 의 마지막 블록(현재 line 395-407)을 교체. 기존:
115
-
116
- ```python
117
- require(
118
- "phase-5.5-convergence",
119
- _convergence_rounds_ran(run_dir, suffix),
120
- "at the start of each convergence round (state artifact records totalRounds >= 1)",
121
- )
122
- report_writer = next((w for w in workers if _is_report_writer(w)), None)
123
- require(
124
- "phase-6-synthesis",
125
- report_writer is not None
126
- and str(report_writer.get("status", "")).strip() in _DISPATCHED_STATUSES,
127
- "at the start of Phase 6 (report-writer dispatch)",
128
- )
129
- require("phase-7-persist", True, "at the start of Phase 7")
130
- ```
131
-
132
- 교체 후:
133
-
134
- ```python
135
- convergence_ran = _convergence_rounds_ran(run_dir, suffix)
136
- require(
137
- "phase-5.5-convergence",
138
- convergence_ran,
139
- "at the start of each convergence round (state artifact records totalRounds >= 1)",
140
- )
141
- report_writer = next((w for w in workers if _is_report_writer(w)), None)
142
- report_writer_dispatched = (
143
- report_writer is not None
144
- and str(report_writer.get("status", "")).strip() in _DISPATCHED_STATUSES
145
- )
146
- require(
147
- "phase-6-synthesis",
148
- report_writer_dispatched,
149
- "at the start of Phase 6 (report-writer dispatch)",
150
- )
151
- require("phase-7-persist", True, "at the start of Phase 7")
152
- _check_batch_cleanup_checkpoints(
153
- by_phase, convergence_ran, report_writer_dispatched, errors
154
- )
155
- ```
156
-
157
- - [ ] **Step 5: HAPPY_PROGRESS 에 cleanup 마커 추가**
158
-
159
- `HAPPY_PROGRESS`(line 131-142)의 `phase-6-synthesis`(`T.format(30)`) 항목 **앞**에 한 줄 삽입:
160
-
161
- ```python
162
- (T.format(20), "PROGRESS: phase-5-collect worker=claude-worker status=completed"),
163
- (T.format(21), "PROGRESS: phase-5-collect worker=codex-worker status=completed"),
164
- (T.format(25), "PROGRESS: phase-batch-cleanup panes=2 teammates=2"),
165
- (T.format(30), "PROGRESS: phase-6-synthesis dispatching report-writer-worker"),
166
- ```
167
-
168
- `HAPPY_PROGRESS` 는 `test_happy_path_passes` / `test_codex_lead_events_...` / `test_external_lead_events_...` 3곳이 공유하므로 이 한 줄로 세 happy-path 가 모두 green 유지. (happy-path 는 convergence state artifact 가 없어 `convergence_ran=False` → R1 미적용, R2 만 `lower=""` 로 적용되어 `T.format(25) <= T.format(30)` 충족.)
169
-
170
- - [ ] **Step 6: 실패 테스트가 통과로 바뀌는지 확인**
171
-
172
- Run: `python3 -m pytest tests/contract/test_validate_session_conformance.py -v`
173
- Expected: PASS — Step 1 의 신규 테스트 + 기존 happy-path 3종 포함 전부 통과.
174
-
175
- - [ ] **Step 7: convergence 경계 테스트 2종 추가**
176
-
177
- 먼저 `Fixture` class(line 154-232)에 헬퍼 추가 — `validate` 메서드(line 236) 앞:
178
-
179
- ```python
180
- def write_convergence_state(self, total_rounds: int = 1) -> None:
181
- (self.run_dir / "state" / f"convergence-{self.suffix}.json").write_text(
182
- json.dumps({"totalRounds": total_rounds}), encoding="utf-8"
183
- )
184
- ```
185
-
186
- 그리고 Step 1 테스트 뒤에 추가:
187
-
188
- ```python
189
- def test_batch_cleanup_before_convergence_required_when_rounds_ran(tmp_path, module):
190
- """convergence 가 실제로 돌았으면(round 1 직전) 그 앞에 cleanup 마커가
191
- 있어야 한다 — 분석 워커 배치가 안 치워진 채 reverify 가 뜨는 걸 잡는다."""
192
- fx = Fixture(tmp_path)
193
- fx.write_convergence_state(total_rounds=1)
194
- progress = [
195
- (T.format(1), "PROGRESS: phase-1-intake reading task bundle"),
196
- (T.format(2), "PROGRESS: phase-1-intake complete"),
197
- (T.format(3), "PROGRESS: phase-2-prompts preparing 3 worker prompts"),
198
- (T.format(4), "PROGRESS: phase-3-team-create attempting TeamCreate"),
199
- (T.format(5), "PROGRESS: phase-4-dispatch worker=claude-worker model=opus"),
200
- (T.format(6), "PROGRESS: phase-4-dispatch worker=codex-worker model=gpt-5.5"),
201
- (T.format(20), "PROGRESS: phase-5-collect worker=claude-worker status=completed"),
202
- (T.format(21), "PROGRESS: phase-5-collect worker=codex-worker status=completed"),
203
- # NOTE: round 1 직전 cleanup 누락
204
- (T.format(22), "PROGRESS: phase-5.5-convergence round=1 queue=3"),
205
- (T.format(28), "PROGRESS: phase-batch-cleanup panes=2 teammates=2"),
206
- (T.format(30), "PROGRESS: phase-6-synthesis dispatching report-writer-worker"),
207
- (T.format(40), "PROGRESS: phase-7-persist updating manifests"),
208
- ]
209
- fx.write_jsonl([_text_record(ts, line) for ts, line in progress])
210
- fx.write_heartbeat()
211
- errors = "\n".join(fx.validate(module).errors)
212
- assert "phase-batch-cleanup" in errors
213
- assert "phase-5.5-convergence" in errors
214
-
215
-
216
- def test_batch_cleanup_two_boundaries_pass(tmp_path, module):
217
- """convergence round 1 직전 + report-writer 직전 두 번 cleanup 하면 통과."""
218
- fx = Fixture(tmp_path)
219
- fx.write_convergence_state(total_rounds=1)
220
- progress = [
221
- (T.format(1), "PROGRESS: phase-1-intake reading task bundle"),
222
- (T.format(2), "PROGRESS: phase-1-intake complete"),
223
- (T.format(3), "PROGRESS: phase-2-prompts preparing 3 worker prompts"),
224
- (T.format(4), "PROGRESS: phase-3-team-create attempting TeamCreate"),
225
- (T.format(5), "PROGRESS: phase-4-dispatch worker=claude-worker model=opus"),
226
- (T.format(6), "PROGRESS: phase-4-dispatch worker=codex-worker model=gpt-5.5"),
227
- (T.format(20), "PROGRESS: phase-5-collect worker=claude-worker status=completed"),
228
- (T.format(21), "PROGRESS: phase-5-collect worker=codex-worker status=completed"),
229
- (T.format(7), "PROGRESS: phase-batch-cleanup panes=3 teammates=3"),
230
- (T.format(22), "PROGRESS: phase-5.5-convergence round=1 queue=3"),
231
- (T.format(28), "PROGRESS: phase-batch-cleanup panes=2 teammates=2"),
232
- (T.format(30), "PROGRESS: phase-6-synthesis dispatching report-writer-worker"),
233
- (T.format(40), "PROGRESS: phase-7-persist updating manifests"),
234
- ]
235
- fx.write_jsonl([_text_record(ts, line) for ts, line in progress])
236
- fx.write_heartbeat()
237
- result = fx.validate(module)
238
- assert result.errors == []
239
- assert result.ok
240
- ```
241
-
242
- 주의: `T.format(7)` 이 list 상 `T.format(20/21)` 뒤에 오지만, 검증기는 `by_phase` 안에서 ts 로 정렬(`sorted`)하므로 list 순서 무관 — `T.format(7) <= T.format(22)`(round 1) 이 성립해 R1 충족. (`T = "2026-06-08T01:{:02d}:00Z"` 의 `{:02d}` 가 항상 zero-pad → `01:07:00 <= 01:22:00` lexicographic = 시간순 보장. 확인 완료, 추가 조치 불필요.)
243
-
244
- - [ ] **Step 8: 신규 테스트 3종 통과 확인**
245
-
246
- Run: `python3 -m pytest tests/contract/test_validate_session_conformance.py -v`
247
- Expected: PASS (전체).
248
-
249
- - [ ] **Step 9: 계약 문서 — 필수 마커 목록에 추가**
250
-
251
- `prompts/lead/okstra-lead-contract.md` line 103 (`phase-6-synthesis` 마커) **앞**에 한 줄 삽입:
252
-
253
- ```markdown
254
- - `PROGRESS: phase-batch-cleanup panes=<n> teammates=<m>` — 이전 배치 pane·완료 teammate 를 정리한 직후, 각 배치 경계에서(① 첫 `phase-5.5-convergence` round 직전 ② `phase-6-synthesis` report-writer dispatch 직전). 카운트만 노출하고 `%NNN`/lead-pane.id/raw Agent name 은 절대 노출하지 않는다. 첫 배치(분석 워커 dispatch) 직전엔 치울 게 없어 no-op 이며 마커도 생략.
255
- ```
256
-
257
- - [ ] **Step 10: 계약 문서 — Enforcement 문구 갱신**
258
-
259
- `prompts/lead/okstra-lead-contract.md` line 112 의 Enforcement 문단에서, 검사 항목 열거에 cleanup 을 포함하도록 수정. 기존 `... including the per-worker `phase-4-dispatch` / `phase-5-collect` lines, which must name each worker's role.` 를:
260
-
261
- ```markdown
262
- ... including the per-worker `phase-4-dispatch` / `phase-5-collect` lines (which must name each worker's role) and the `phase-batch-cleanup` lines that MUST precede the first `phase-5.5-convergence` round and the `phase-6-synthesis` report-writer dispatch.
263
- ```
264
-
265
- - [ ] **Step 11: `_common-contract.md` — freeform 상태줄을 구조화 마커로 교체**
266
-
267
- `prompts/profiles/_common-contract.md` line 43 의 마지막 문장에서 freeform 예시(`이전 배치 okstra pane 3개 · teammate 2명 정리`)를 마커 emit 으로 교체. 기존:
268
-
269
- ```markdown
270
- - Both (a) and (b) run **automatically without any interactive prompt**. Still emit one short, plain-language status line for the pair (e.g. `이전 배치 okstra pane 3개 · teammate 2명 정리`) and proceed — never expose internal identifiers (`%NNN`, `lead-pane.id`, raw Agent names, step names like "phase-start cleanup"). **Effect caveat:** ...
271
- ```
272
-
273
- 교체 후(앞부분만 수정, `**Effect caveat:**` 이후는 유지):
274
-
275
- ```markdown
276
- - Both (a) and (b) run **automatically without any interactive prompt**. After running them, emit the checkpoint line `PROGRESS: phase-batch-cleanup panes=<n> teammates=<m>` (counts only — NEVER expose `%NNN`, `lead-pane.id`, or raw Agent names) and proceed; this is the BLOCKING checkpoint the Phase 7 validator requires before each convergence round and before the report-writer dispatch (`prompts/lead/okstra-lead-contract.md` "Progress reporting (BLOCKING)"). **Effect caveat:** ...
277
- ```
278
-
279
- 그리고 line 37 의 boundary 설명이 마커 기준임을 명확히 — 기존 `at the SAME boundaries: just before each `PROGRESS: phase-5.5-convergence round=<N>` marker and just before `PROGRESS: phase-6-synthesis dispatching report-writer-worker`` 는 그대로 두되, 이미 정확하므로 수정 불필요(확인만).
280
-
281
- - [ ] **Step 12: 마커명 일관성 grep**
282
-
283
- Run: `grep -rn "phase-batch-cleanup" prompts/ validators/ tests/`
284
- Expected: `okstra-lead-contract.md`(마커 목록 + enforcement), `_common-contract.md`(emit 문구), `validate_session_conformance.py`(헬퍼), `test_validate_session_conformance.py`(HAPPY_PROGRESS + 테스트 3종) — 철자 `phase-batch-cleanup` 로 전부 일치, 오타/변형 없음.
285
-
286
- - [ ] **Step 13: 빌드 + 전체 CI**
287
-
288
- Run: `npm run build && npm run check`
289
- Expected: `npm run build` 가 `runtime/` 동기화(특히 `runtime/prompts/`, `runtime/python/`), `npm run check` exit 0.
290
-
291
- - [ ] **Step 14: 커밋**
292
-
293
- ```bash
294
- git add validators/validate_session_conformance.py \
295
- tests/contract/test_validate_session_conformance.py \
296
- prompts/lead/okstra-lead-contract.md \
297
- prompts/profiles/_common-contract.md \
298
- runtime/
299
- git commit -m "feat(conformance): enforce phase-batch-cleanup checkpoint before each batch boundary"
300
- ```
301
-
302
- ---
303
-
304
- ## Task 2 (선택, defense-in-depth): cleanup 스크립트 anchor fallback
305
-
306
- **근거:** Task 1 로 lead 가 정리를 실제 수행하면, tmux 안에서 실행된 run 은 `lead-pane.id` 가 정상 기록되어 `okstra-trace-cleanup.sh` 가 worker-agent pane 까지 닫는다. 다만 `lead-pane.id` 기록이 실패하거나 foreign pane 으로 해석되면 worker-agent title 스캔(`scripts/okstra-trace-cleanup.sh:165`)이 통째로 skip 되어 `claude-worker` 류 pane 이 남는다. 같은 run 의 태그된 trace pane 을 세션 anchor 로 써서 이 경우를 보강한다. **이 Task 는 mixed run(codex/antigravity 가 있어 `-tail` trace pane 이 존재)에서만 효과** — 순수 claude run 은 태그 anchor 가 없어 여전히 `lead-pane.id` 의존. 그래서 선택 사항.
307
-
308
- **Files:**
309
- - Modify: `scripts/okstra-trace-cleanup.sh` (`collect_okstra_panes` line 131-181)
310
- - Test: `tests/worktree/test_okstra_trace_cleanup.py` (real-tmux, tmux 없으면 skip)
311
-
312
- **Interfaces:**
313
- - Consumes: 기존 tag 스캔이 채우는 `panes` 배열, `lead_pane`, `_tag_in_scope`.
314
- - Produces: `lead_pane` 미해석 시에도 태그된 in-scope pane 의 세션에서 worker-agent title 스캔 수행.
315
-
316
- - [ ] **Step 1: 실패 테스트 작성**
317
-
318
- `tests/worktree/test_okstra_trace_cleanup.py` 기존 패턴(`_new_detached_session`/`_split_pane`/`@okstra_trace_run` 태깅)을 따라 추가. lead-pane.id 를 **쓰지 않고**, 태그된 trace pane + `claude-worker` 제목 pane 을 같은 세션에 두고 `--list` 가 worker-agent pane 을 집어내는지 검증:
319
-
320
- ```python
321
- def test_worker_agent_pane_found_via_tag_anchor_without_lead_pane_id(session_name, tmp_path):
322
- if not _TMUX_SPAWN_AVAILABLE:
323
- pytest.skip("tmux detached sessions not available")
324
- run_dir = tmp_path / "run"
325
- (run_dir / "state").mkdir(parents=True) # lead-pane.id 는 일부러 쓰지 않음
326
-
327
- lead = _new_detached_session(session_name)
328
- trace = _split_pane(session_name)
329
- worker = _split_pane(session_name)
330
- _tmux("set-option", "-p", "-t", trace, "@okstra_trace_run", str(run_dir.resolve()))
331
- _tmux("select-pane", "-t", worker, "-T", "claude-worker")
332
-
333
- res = subprocess.run(
334
- ["bash", str(SCRIPT), "--list", "--run-dir", str(run_dir)],
335
- capture_output=True, text=True, check=False,
336
- )
337
- out_ids = {line.split("\t", 1)[0] for line in res.stdout.strip().splitlines() if line}
338
- assert worker in out_ids, res.stdout # anchor fallback 으로 worker-agent pane 포착
339
- assert lead not in out_ids # lead pane 은 절대 미포함
340
- ```
341
-
342
- (헬퍼 시그니처는 파일 상단 실제 정의와 맞춘다 — `_split_pane` 가 `session` 만 받는지, 반환이 pane_id 인지 line 85-90 확인.)
343
-
344
- - [ ] **Step 2: 테스트 실패 확인**
345
-
346
- Run: `python3 -m pytest tests/worktree/test_okstra_trace_cleanup.py::test_worker_agent_pane_found_via_tag_anchor_without_lead_pane_id -v`
347
- Expected: FAIL — `lead_pane` 미해석 → 현재 코드는 title 스캔 자체를 skip → `worker` pane 이 출력에 없음.
348
-
349
- - [ ] **Step 3: anchor fallback 구현**
350
-
351
- `scripts/okstra-trace-cleanup.sh` `collect_okstra_panes`(line 131-181) 수정. (1) tag 스캔 루프에서 in-scope 첫 pane 을 `scope_anchor` 로 기억, (2) title 스캔을 `lead_pane` 과 `scope_anchor` 두 세션에 대해 수행(dedup 은 기존 line 178-180 이 처리). 기존 `local pid trace_tag worker_tag status_tag title` 선언에 `scope_anchor` 추가하고, in-scope 매치 직후 `[[ -z "$scope_anchor" ]] && scope_anchor="$pid"` 한 줄 추가. title 스캔 블록(line 165-175)을 교체:
352
-
353
- ```bash
354
- # (2) Title-allowlisted worker-agent panes. Scope to the lead's session AND
355
- # (fallback when lead-pane.id was unrecorded or resolved to a foreign pane) the
356
- # session of any tagged in-scope pane found above — both are THIS run's session,
357
- # so the scan never reaches unrelated sessions. dedup below drops overlaps.
358
- if [[ "$REAP" -eq 0 && "$RECLAIM" -eq 0 ]]; then
359
- local -a _scopes=()
360
- [[ -n "$lead_pane" ]] && _scopes+=("$lead_pane")
361
- [[ -n "$scope_anchor" ]] && _scopes+=("$scope_anchor")
362
- local _scope
363
- for _scope in "${_scopes[@]}"; do
364
- while IFS=$'\t' read -r pid title; do
365
- [[ -n "$pid" ]] || continue
366
- [[ "$pid" == "$lead_pane" ]] && continue
367
- case "$title" in
368
- *claude-worker*|*codex-worker*|*antigravity-worker*|*report-writer-worker*)
369
- panes+=("$pid") ;;
370
- esac
371
- done < <(tmux list-panes -s -t "$_scope" \
372
- -F '#{pane_id}'$'\t''#{pane_title}' 2>/dev/null || true)
373
- done
374
- fi
375
- ```
376
-
377
- - [ ] **Step 4: 테스트 통과 확인**
378
-
379
- Run: `python3 -m pytest tests/worktree/test_okstra_trace_cleanup.py -v`
380
- Expected: PASS (신규 + 기존 전부). lead-pane.id 가 있는 기존 테스트도 `_scopes` 에 `lead_pane` 우선 포함되어 동작 동일.
381
-
382
- - [ ] **Step 5: 빌드 + CI + 커밋**
383
-
384
- ```bash
385
- npm run build && npm run check
386
- git add scripts/okstra-trace-cleanup.sh tests/worktree/test_okstra_trace_cleanup.py runtime/
387
- git commit -m "fix(cleanup): scope worker-agent pane scan via tagged anchor when lead pane unresolved"
388
- ```
389
-
390
- ---
391
-
392
- ## 범위 밖 (이번 계획에서 다루지 않음)
393
-
394
- - **완료 감지 강제화(Fix 3):** 사용자의 최초 질문이었으나 스크린샷상 이번 run 은 감지가 동작 중(`@report-writer-2 came to rest` → result-missing 분류까지 진행). lead 가 idle 알림 대신 항상 background 폴링 루프를 띄우게 하는 enforcement 는 별도 설계 대상(`team-contract.md` "Worker-completion detection")이라 분리. 필요 시 후속 계획으로.
395
- - **roster idle-pill 잔상:** `_common-contract.md:43` 의 "Effect caveat" — Claude Code 가 mid-run roster 항목을 외과적으로 지우는 도구를 노출하지 않음. tmux **pane** 은 이 계획으로 닫히지만 FleetView **pill** 잔상은 harness 한계로 남음(고칠 수 없음, 문서화된 상태 유지).
396
-
397
- ---
398
-
399
- ## Self-Review
400
-
401
- **1. Spec coverage:**
402
- - "phase 전환 시 정리 안 됨 → 화면 복잡" 근본원인(강제 부재) → Task 1 (마커 + 검증기).
403
- - "정리하고 다음 팀원 생성" 두 경계(convergence 직전 / report-writer 직전) → Task 1 R1+R2.
404
- - pane 이 실제로 안 닫히는 보조 결함(`lead_pane` skip) → Task 2.
405
- - 최초 질문(완료 감지) → 범위 밖으로 명시 + 근거.
406
-
407
- **2. Placeholder scan:** 모든 Step 에 실제 코드/명령/기대출력 기재. TBD/"적절히 처리" 없음. `T` zero-pad 가정은 Step 7 에서 grep 확인 + 대체값 명시로 방어.
408
-
409
- **3. Type consistency:** 마커 토큰 `phase-batch-cleanup` 4개 파일 동일(Step 12 grep 으로 강제). 헬퍼 시그니처 `_check_batch_cleanup_checkpoints(by_phase, convergence_ran, report_writer_dispatched, errors)` — 호출부(Step 4)와 정의(Step 3) 인자 순서·이름 일치. `by_phase` 값 타입 `(ts, line)` — 기존 line 358-360 과 동일. `_convergence_rounds_ran`/`_DISPATCHED_STATUSES`/`_is_report_writer` 모두 기존 심볼 재사용.