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,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` 모두 기존 심볼 재사용.
|