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,320 +0,0 @@
|
|
|
1
|
-
# implementation run-산출물 stage 격리 — 활성화 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:** `implementation` run 의 산출물을 `runs/implementation/stage-<N>/` 로 격리해, 같은 task 의 독립 stage 를 동시 실행해도 보고서·state·worker-results 가 섞이지 않게 한다.
|
|
6
|
-
|
|
7
|
-
**Architecture:** foundation(`paths.py`/`run_context.py` 의 `stage` 파라미터, 이미 커밋 `baafa40`)은 `stage` 인자가 오면 `RUN_DIR=runs/implementation/stage-<N>` 를 만든다(현재 무동작). 본 plan 은 `prepare_task_bundle` 의 **stage 선택을 경로 계산 앞으로 옮겨** 그 stage 를 `compute_and_write_run_context` 에 전달해 활성화한다. 동시성 불변(`select == registry flock 예약` 원자성)을 보존하기 위해, stage 선택+base 결정+stage-worktree 예약(=registry flock)을 **하나의 함수로 묶어 경로 계산 전에 1회** 호출한다. `consumers.jsonl` 은 approved-plan 경로 기준이라 격리 대상이 아니다(공유 유지).
|
|
8
|
-
|
|
9
|
-
**Tech Stack:** Python (okstra_ctl), pytest(+ 실 git/flock 기반 e2e), okstra build(`npm run build`).
|
|
10
|
-
|
|
11
|
-
설계 근거: [docs/superpowers/specs/2026-06-09-implementation-run-artifact-stage-isolation-design.md](../specs/2026-06-09-implementation-run-artifact-stage-isolation-design.md)
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## File Structure
|
|
16
|
-
|
|
17
|
-
- Modify: `scripts/okstra_ctl/run.py` — `_reserve_implementation_stages` 를 (a) 경로-무관 **선택+예약+provision** 부분과 (b) `ctx` 의존 **wiring(EXECUTOR_WORKTREE_* 세팅 + consumers append)** 부분으로 분리. `prepare_task_bundle` 에서 (a)를 `compute_and_write_run_context` 앞으로 이동하고 selected stage 를 전달.
|
|
18
|
-
- Modify: `scripts/okstra_ctl/run_context.py` — (foundation 에서 이미 `stage` param 수용) 변경 없음 예상. 확인만.
|
|
19
|
-
- Test: `tests/test_e2e_impl_stage_artifact_isolation.py` (신규) — 동시 stage-1/stage-2 가 분리된 `stage-<N>/` 산출물 트리 + 분리 `lead-pane.id` + 공유 `consumers.jsonl` 을 갖는지.
|
|
20
|
-
- Test: `tests/test_okstra_ctl_paths.py` (기존 있으면 확장; 없으면 신규) — `compute_run_paths(task_type="implementation", stage=N)` 가 `runs/implementation/stage-N/...` 를 반환, `stage=None`/비-impl 은 불변.
|
|
21
|
-
- Modify(필요 시): `validators/validate-run.py`, `scripts/okstra_ctl/{render.py,report_views.py,context_cost.py,index.py,reconcile.py,backfill.py}` — `runs/implementation` hard-coded 경로가 있으면 stage-aware 로. (대부분 ctx/path-dict 경유라 무변경; Task 5 에서 grep 로 확정.)
|
|
22
|
-
- Modify: `CHANGES.md`, `docs/kr/architecture.md` — 사용자 영향 + 팀 lifecycle 절.
|
|
23
|
-
|
|
24
|
-
`runtime/` 는 빌드 출력 — source 수정 후 `npm run build`.
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## Task 1: paths 단위 테스트로 foundation 동작 고정
|
|
29
|
-
|
|
30
|
-
**Files:**
|
|
31
|
-
- Test: `tests/test_okstra_ctl_paths.py`
|
|
32
|
-
|
|
33
|
-
- [ ] **Step 1: 실패/통과 테스트 작성**
|
|
34
|
-
|
|
35
|
-
`tests/test_okstra_ctl_paths.py` 에 추가(파일 없으면 신규 생성, 상단에 `from okstra_ctl.paths import compute_run_paths` + `from pathlib import Path`):
|
|
36
|
-
|
|
37
|
-
```python
|
|
38
|
-
def _common(**over):
|
|
39
|
-
base = dict(
|
|
40
|
-
project_root=Path("/tmp/proj"), workspace_root=Path("/tmp/ws"),
|
|
41
|
-
project_id="p", task_group="g", task_id="t",
|
|
42
|
-
task_type="implementation", run_seq_override=1,
|
|
43
|
-
)
|
|
44
|
-
base.update(over)
|
|
45
|
-
return base
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def test_implementation_stage_namespaces_run_dir():
|
|
49
|
-
ctx = compute_run_paths(stage=3, **_common())
|
|
50
|
-
assert ctx["RUN_DIR"].endswith("/runs/implementation/stage-3")
|
|
51
|
-
assert ctx["RUN_REPORTS_DIR"].endswith("/runs/implementation/stage-3/reports")
|
|
52
|
-
assert ctx["RUN_STATE_DIR"].endswith("/runs/implementation/stage-3/state")
|
|
53
|
-
assert ctx["RUN_STAGE"] == "3"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def test_implementation_without_stage_is_flat():
|
|
57
|
-
ctx = compute_run_paths(stage=None, **_common())
|
|
58
|
-
assert ctx["RUN_DIR"].endswith("/runs/implementation")
|
|
59
|
-
assert ctx["RUN_STAGE"] == ""
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def test_non_implementation_ignores_stage():
|
|
63
|
-
ctx = compute_run_paths(stage=3, **_common(task_type="final-verification"))
|
|
64
|
-
assert ctx["RUN_DIR"].endswith("/runs/final-verification")
|
|
65
|
-
assert "stage-3" not in ctx["RUN_DIR"]
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
- [ ] **Step 2: 실행해서 통과 확인** (foundation 이 이미 land 됨)
|
|
69
|
-
|
|
70
|
-
Run: `python3 -m pytest tests/test_okstra_ctl_paths.py -v`
|
|
71
|
-
Expected: 3개 PASS. 실패하면 foundation(`paths.py` stage 분기) 회귀이므로 먼저 수정.
|
|
72
|
-
|
|
73
|
-
- [ ] **Step 3: 커밋**
|
|
74
|
-
|
|
75
|
-
```bash
|
|
76
|
-
git add tests/test_okstra_ctl_paths.py
|
|
77
|
-
git commit -m "test(paths): pin implementation stage-namespaced RUN_DIR"
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
---
|
|
81
|
-
|
|
82
|
-
## Task 2: `_reserve_implementation_stages` 를 선택/예약 vs wiring 으로 분리
|
|
83
|
-
|
|
84
|
-
**Files:**
|
|
85
|
-
- Modify: `scripts/okstra_ctl/run.py` (`_reserve_implementation_stages` 1274–1386 영역)
|
|
86
|
-
|
|
87
|
-
현재 함수는 한 덩어리로 (1) consumers/registry 읽기 → `_resolve_effective_stages` 선택, (2) base anchor + `_resolve_stage_base_commit` + `provision_stage_worktree`(registry 원자 예약), (3) `ctx["EXECUTOR_WORKTREE_*"]` 세팅 + `append_consumer(started)` 를 한다. (1)+(2)는 run-경로와 무관하지만 (3)은 `ctx` 가 필요하다.
|
|
88
|
-
|
|
89
|
-
- [ ] **Step 1: 선택+예약+provision 을 반환 객체로 추출**
|
|
90
|
-
|
|
91
|
-
`scripts/okstra_ctl/run.py` 에 신규 헬퍼 추가(`_reserve_implementation_stages` 위). `ctx` 대신 segment 값을 인자로 받아 **경로-무관**하게 만든다. (segment 는 `slugify_task_segment(inp.task_group/task_id)` 로 직접 도출 — `ctx` 불필요.)
|
|
92
|
-
|
|
93
|
-
```python
|
|
94
|
-
from dataclasses import dataclass
|
|
95
|
-
|
|
96
|
-
@dataclass
|
|
97
|
-
class StageSelection:
|
|
98
|
-
stage: int
|
|
99
|
-
worktree_path: str
|
|
100
|
-
worktree_branch: str
|
|
101
|
-
worktree_base_ref: str
|
|
102
|
-
worktree_status: str
|
|
103
|
-
worktree_note: str
|
|
104
|
-
started_head_commit: str # consumers append 용 (degrade 경로는 HEAD sha)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
def _select_and_provision_implementation_stage(
|
|
108
|
-
inp: "PrepareInputs", ctx_stage_map: list,
|
|
109
|
-
task_group_segment: str, task_id_segment: str, task_key: str,
|
|
110
|
-
executor_worktree_status: str,
|
|
111
|
-
) -> StageSelection:
|
|
112
|
-
"""run 경로 계산 전에 호출: ready stage 1개 선택 → (degrade 가 아니면)
|
|
113
|
-
base 결정 + stage worktree 발급(registry flock 으로 stage-key 원자 예약).
|
|
114
|
-
선택과 예약이 한 호출에 묶여 동시성 불변(spec §2.3)을 보존한다.
|
|
115
|
-
consumers append 는 호출자가 ctx 확정 후 수행한다(반환값 사용)."""
|
|
116
|
-
from .consumers import read_consumers
|
|
117
|
-
from . import worktree as _worktree
|
|
118
|
-
from . import worktree_registry as _reg
|
|
119
|
-
|
|
120
|
-
plan_run_root = Path(inp.approved_plan_path).resolve().parents[1]
|
|
121
|
-
consumed = read_consumers(plan_run_root)
|
|
122
|
-
done_stages = {r["stage"] for r in consumed if r.get("status") == "done"}
|
|
123
|
-
started_stages = {r["stage"] for r in consumed if r.get("status") == "started"}
|
|
124
|
-
reserved_stages = _reg.list_active_stage_numbers(
|
|
125
|
-
inp.project_id, inp.task_group, inp.task_id,
|
|
126
|
-
)
|
|
127
|
-
batch = _resolve_effective_stages(
|
|
128
|
-
ctx_stage_map, done_stages, inp.stage,
|
|
129
|
-
started_stages=started_stages, reserved_stages=reserved_stages,
|
|
130
|
-
)
|
|
131
|
-
selected = batch[0]
|
|
132
|
-
|
|
133
|
-
# degradation(non-git / nested-worktree): worktree 미발급, consumers 만.
|
|
134
|
-
if executor_worktree_status.startswith("skipped"):
|
|
135
|
-
head = _git_out(inp.project_root, "rev-parse", "HEAD")
|
|
136
|
-
return StageSelection(selected, "", "", "", executor_worktree_status, "", head)
|
|
137
|
-
|
|
138
|
-
head_sha = _git_out(inp.project_root, "rev-parse", "HEAD")
|
|
139
|
-
if head_sha:
|
|
140
|
-
_reg.set_implementation_base(inp.project_id, inp.task_group, inp.task_id, head_sha)
|
|
141
|
-
anchor = _reg.get_implementation_base(inp.project_id, inp.task_group, inp.task_id) or ""
|
|
142
|
-
selected_stage = next(s for s in ctx_stage_map if s["stage_number"] == selected)
|
|
143
|
-
consumer_done_rows = [r for r in consumed if r.get("status") == "done"]
|
|
144
|
-
stage_base = _resolve_stage_base_commit(
|
|
145
|
-
selected_stage, consumer_done_rows, anchor_base_commit=anchor,
|
|
146
|
-
candidate_base=head_sha, project_root=Path(inp.project_root),
|
|
147
|
-
)
|
|
148
|
-
try:
|
|
149
|
-
prov = _worktree.provision_stage_worktree(
|
|
150
|
-
project_root=Path(inp.project_root), project_id=inp.project_id,
|
|
151
|
-
task_group_segment=task_group_segment, task_id_segment=task_id_segment,
|
|
152
|
-
work_category=inp.work_category, stage_number=selected, base_commit=stage_base,
|
|
153
|
-
)
|
|
154
|
-
except RuntimeError as exc:
|
|
155
|
-
raise PrepareError(f"stage worktree provisioning failed: {exc}") from exc
|
|
156
|
-
return StageSelection(
|
|
157
|
-
selected, prov.path, prov.branch, prov.base_ref, prov.status, prov.note, prov.base_ref,
|
|
158
|
-
)
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
- [ ] **Step 2: wiring 헬퍼로 교체** — `_reserve_implementation_stages` 본문을 selection 결과를 ctx 에 반영 + consumers append 로 축소:
|
|
162
|
-
|
|
163
|
-
```python
|
|
164
|
-
def _apply_implementation_stage(
|
|
165
|
-
inp: "PrepareInputs", ctx: dict, ctx_stage_map: list, sel: "StageSelection",
|
|
166
|
-
) -> None:
|
|
167
|
-
"""이미 선택·예약된 stage(sel)를 ctx 에 반영하고 consumers 에 started 기록."""
|
|
168
|
-
from .consumers import append_consumer
|
|
169
|
-
import datetime as _dt
|
|
170
|
-
ctx["parsed_stage_map"] = ctx_stage_map
|
|
171
|
-
ctx["effective_stages"] = [sel.stage]
|
|
172
|
-
ctx["EFFECTIVE_STAGES"] = str(sel.stage)
|
|
173
|
-
ctx["STAGE_BATCH_DIRECTIVE"] = (
|
|
174
|
-
f"- **Stage for this implementation run:** `{sel.stage}`. "
|
|
175
|
-
"Execute exactly this Stage Map stage — this is the authoritative scope. "
|
|
176
|
-
"Do NOT recompute from `consumers.jsonl`; the runtime already selected "
|
|
177
|
-
"and reserved this stage."
|
|
178
|
-
)
|
|
179
|
-
inp.stage = str(sel.stage)
|
|
180
|
-
if sel.worktree_status and not sel.worktree_status.startswith("skipped"):
|
|
181
|
-
ctx["EXECUTOR_WORKTREE_PATH"] = sel.worktree_path
|
|
182
|
-
ctx["EXECUTOR_WORKTREE_BRANCH"] = sel.worktree_branch
|
|
183
|
-
ctx["EXECUTOR_WORKTREE_BASE_REF"] = sel.worktree_base_ref
|
|
184
|
-
ctx["EXECUTOR_WORKTREE_STATUS"] = sel.worktree_status
|
|
185
|
-
ctx["EXECUTOR_WORKTREE_NOTE"] = sel.worktree_note
|
|
186
|
-
plan_run_root = Path(inp.approved_plan_path).resolve().parents[1]
|
|
187
|
-
now = _dt.datetime.now(_dt.timezone.utc).isoformat()
|
|
188
|
-
append_consumer(
|
|
189
|
-
plan_run_root, impl_task_key=ctx["TASK_KEY"], stage=sel.stage,
|
|
190
|
-
status="started", started_at=now, head_commit=sel.started_head_commit,
|
|
191
|
-
)
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
- [ ] **Step 3: 정적 검사**
|
|
195
|
-
|
|
196
|
-
Run: `python3 -c "import ast; ast.parse(open('scripts/okstra_ctl/run.py').read()); print('ok')"`
|
|
197
|
-
Expected: `ok`
|
|
198
|
-
|
|
199
|
-
- [ ] **Step 4: 커밋**
|
|
200
|
-
|
|
201
|
-
```bash
|
|
202
|
-
git add scripts/okstra_ctl/run.py
|
|
203
|
-
git commit -m "refactor(run): split impl stage select+reserve (path-independent) from ctx wiring"
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
---
|
|
207
|
-
|
|
208
|
-
## Task 3: `prepare_task_bundle` reorder — stage 를 경로 계산 전에 선택
|
|
209
|
-
|
|
210
|
-
**Files:**
|
|
211
|
-
- Modify: `scripts/okstra_ctl/run.py` (`prepare_task_bundle` 1651–1810)
|
|
212
|
-
|
|
213
|
-
- [ ] **Step 1: 현재 흐름 확인** — `compute_and_write_run_context`(1686) 호출 직전에 `ctx_stage_map` 와 `inp.task_type == "implementation"` 가용한지, `EXECUTOR_WORKTREE_STATUS` 의 초기값(task worktree provision 결과)을 어디서 얻는지 read 로 확인. (degrade 신호가 task-worktree provision 에서 오면, stage select 는 그 신호가 필요 → task worktree provision 을 stage select 보다 먼저 두거나, stage select 안에서 자체 degrade 판정.)
|
|
214
|
-
|
|
215
|
-
- [ ] **Step 2: reorder 적용** — implementation 분기에서:
|
|
216
|
-
1. `compute_and_write_run_context` **앞에서** `sel = _select_and_provision_implementation_stage(...)` 호출(`executor_worktree_status` 는 task-worktree provision 결과 또는 `provision_task_worktree` 의 사전 판정값 전달).
|
|
217
|
-
2. `compute_and_write_run_context(..., stage=sel.stage)` 호출 → stage-namespaced ctx.
|
|
218
|
-
3. ctx 생성 후 `_apply_implementation_stage(inp, ctx, ctx_stage_map, sel)` 로 wiring.
|
|
219
|
-
4. 기존 `_reserve_implementation_stages(inp, ctx, ctx_stage_map)` 호출(1807) **제거**(위 1~3 이 대체). 비-implementation 경로는 불변.
|
|
220
|
-
|
|
221
|
-
> 핵심 불변: registry stage-key 예약은 `provision_stage_worktree`(sel 단계) **1회**만. 재선택/재예약 없음.
|
|
222
|
-
|
|
223
|
-
- [ ] **Step 3: 전체 단위 테스트**
|
|
224
|
-
|
|
225
|
-
Run: `python3 -m pytest tests/ -q`
|
|
226
|
-
Expected: 전부 PASS(2 skip 허용). 특히 `tests/test_e2e_multi_stage_q1_q9.py`, `tests/test_okstra_ctl_rerun_*` 회귀 없을 것. 실패 시 reorder 의 ctx_stage_map/worktree-status 전달 누락 점검.
|
|
227
|
-
|
|
228
|
-
- [ ] **Step 4: 커밋**
|
|
229
|
-
|
|
230
|
-
```bash
|
|
231
|
-
git add scripts/okstra_ctl/run.py
|
|
232
|
-
git commit -m "feat(run): resolve implementation stage before run-path compute (activate stage isolation)"
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
---
|
|
236
|
-
|
|
237
|
-
## Task 4: 동시 stage 격리 e2e
|
|
238
|
-
|
|
239
|
-
**Files:**
|
|
240
|
-
- Test: `tests/test_e2e_impl_stage_artifact_isolation.py` (신규)
|
|
241
|
-
|
|
242
|
-
- [ ] **Step 1: e2e 작성** — 기존 `tests/test_e2e_multi_stage_q1_q9.py` 의 픽스처(임시 git project + approved plan with ≥2 독립 stage)를 재사용/모사. 두 `prepare_task_bundle` 를 **순차 호출**(동시성은 flock 으로 직렬화되므로 순차 2회가 동치)해 각각 다른 ready stage 를 잡게 한 뒤:
|
|
243
|
-
|
|
244
|
-
```python
|
|
245
|
-
def test_two_runs_isolate_stage_artifacts(tmp_impl_project):
|
|
246
|
-
out1 = prepare_task_bundle(tmp_impl_project.inputs(stage="auto"))
|
|
247
|
-
out2 = prepare_task_bundle(tmp_impl_project.inputs(stage="auto"))
|
|
248
|
-
d1, d2 = Path(out1.ctx["RUN_DIR"]), Path(out2.ctx["RUN_DIR"])
|
|
249
|
-
# 서로 다른 stage-<N> 트리
|
|
250
|
-
assert d1 != d2
|
|
251
|
-
assert d1.name.startswith("stage-") and d2.name.startswith("stage-")
|
|
252
|
-
# lead-pane.id 가 분리(부모 공유 아님)
|
|
253
|
-
assert d1.parent == d2.parent == (tmp_impl_project.task_root / "runs" / "implementation")
|
|
254
|
-
# consumers.jsonl 은 공유(plan-run-root 1개)
|
|
255
|
-
cons = tmp_impl_project.plan_run_root / "consumers.jsonl"
|
|
256
|
-
rows = [json.loads(l) for l in cons.read_text().splitlines() if l.strip()]
|
|
257
|
-
stages = sorted(r["stage"] for r in rows if r["status"] == "started")
|
|
258
|
-
assert stages == [out1.ctx["RUN_STAGE"] and int(out1.ctx["RUN_STAGE"]),
|
|
259
|
-
int(out2.ctx["RUN_STAGE"])] or len(set(stages)) == 2
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
(픽스처 정확한 형태는 기존 e2e 의 헬퍼에 맞춰 작성 — 실행 시 `tests/test_e2e_multi_stage_q1_q9.py` 의 setup 함수를 import/모방.)
|
|
263
|
-
|
|
264
|
-
- [ ] **Step 2: 실행**
|
|
265
|
-
|
|
266
|
-
Run: `python3 -m pytest tests/test_e2e_impl_stage_artifact_isolation.py -v`
|
|
267
|
-
Expected: PASS. tmux/flock 불가 환경이면 skip 마커. 실패 시 두 run 이 같은 `RUN_DIR` 를 잡는지(=stage select 가 reorder 에서 실제 적용됐는지) 확인.
|
|
268
|
-
|
|
269
|
-
- [ ] **Step 3: 커밋**
|
|
270
|
-
|
|
271
|
-
```bash
|
|
272
|
-
git add tests/test_e2e_impl_stage_artifact_isolation.py
|
|
273
|
-
git commit -m "test(e2e): concurrent implementation stages isolate run artifacts"
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
---
|
|
277
|
-
|
|
278
|
-
## Task 5: reader/validator sweep + 문서 + 빌드
|
|
279
|
-
|
|
280
|
-
**Files:**
|
|
281
|
-
- Modify(조건부): `validators/validate-run.py`, `scripts/okstra_ctl/{render.py,report_views.py,context_cost.py,index.py,reconcile.py,backfill.py,workflow.py}`
|
|
282
|
-
- Modify: `CHANGES.md`, `docs/kr/architecture.md`
|
|
283
|
-
|
|
284
|
-
- [ ] **Step 1: hard-coded 경로 grep**
|
|
285
|
-
|
|
286
|
-
Run: `grep -rn "runs/implementation\|/runs/\" *+\|task_type_segment *== *.implementation" scripts/okstra_ctl/ validators/`
|
|
287
|
-
점검: `runs/implementation` 를 **stage 없이 직접** 조립/스캔하는 곳을 찾는다. ctx/path-dict(`RUN_DIR`, `RUN_REPORTS_DIR` 등) 경유면 자동 흡수되어 무변경. 직접 조립이면 stage-aware 로 수정(예: timeline/index 가 `runs/<type>/reports/*` 글롭이면 `runs/<type>/**/reports/*` 로).
|
|
288
|
-
|
|
289
|
-
- [ ] **Step 2: 발견 건 수정 + 회귀 테스트** — 수정한 모듈별로 해당 테스트 재실행. 없으면 Step 1 결과를 `없음(모두 ctx 경유)` 으로 기록.
|
|
290
|
-
|
|
291
|
-
- [ ] **Step 3: 문서 + 빌드**
|
|
292
|
-
|
|
293
|
-
`CHANGES.md` 최상단:
|
|
294
|
-
```
|
|
295
|
-
## 2026-06-09 — implementation 산출물 stage 격리
|
|
296
|
-
- 변경: implementation run 산출물이 `runs/implementation/stage-<N>/` 로 stage 별 격리. stage 선택을 경로 계산 전에 수행하고 registry flock 으로 1회 예약.
|
|
297
|
-
- 사용자 영향: 같은 task 의 여러 stage 를 동시 실행해도 보고서·state·worker-results 가 섞이지 않는다. (무호환: 이전 `runs/implementation/` 루트 산출물은 자동 인식 안 됨 — 재실행 권장.)
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
`docs/kr/architecture.md` 의 stage worktree 절에 "run-산출물도 `runs/implementation/stage-<N>/` 로 격리; consumers.jsonl·registry 는 공유" 1문장 추가.
|
|
301
|
-
|
|
302
|
-
Run: `cd <repo> && npm run build && python3 -m pytest tests/ -q && bash validators/validate-workflow.sh`
|
|
303
|
-
Expected: 빌드 24/24, 테스트 PASS, validator exit 0.
|
|
304
|
-
|
|
305
|
-
- [ ] **Step 4: 커밋**
|
|
306
|
-
|
|
307
|
-
```bash
|
|
308
|
-
git add -A
|
|
309
|
-
git commit -m "docs(changes,architecture): implementation run-artifact stage isolation; reader sweep"
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
---
|
|
313
|
-
|
|
314
|
-
## Self-Review (작성자 체크)
|
|
315
|
-
|
|
316
|
-
- **Spec coverage**: D1(stage-namespace RUN_DIR)=Task1+foundation, D2(seq in stage dir)=foundation(자동), D3(consumers 공유)=Task2/3 가 plan_run_root 유지 + Task4 e2e 가드, D4(lead-pane.id 격리)=Task4 e2e(부모 분리 확인), D5(degrade fallback)=Task2 `executor_worktree_status.startswith("skipped")` 분기. 전 D 매핑됨.
|
|
317
|
-
- **동시성 불변**: registry stage-key 예약은 `provision_stage_worktree` 1회만 — Task2 추출 + Task3 가 기존 `_reserve_implementation_stages` 호출 제거로 이중예약 차단.
|
|
318
|
-
- **Placeholder scan**: TBD/TODO 없음. Task4 픽스처는 기존 e2e 헬퍼 재사용 명시(코드 형태 제시).
|
|
319
|
-
- **식별자 일관성**: `StageSelection`, `_select_and_provision_implementation_stage`, `_apply_implementation_stage`, `stage` param 이 Task2/3/4 에서 동일.
|
|
320
|
-
- **알려진 한계**: 무호환(이전 루트 산출물), consumers/registry 공유는 spec 에 명시.
|