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.
Files changed (161) hide show
  1. package/README.kr.md +5 -5
  2. package/README.md +5 -5
  3. package/docs/kr/architecture/storage-model.md +1 -1
  4. package/docs/kr/architecture.md +7 -11
  5. package/docs/kr/cli.md +4 -4
  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/commands/lifecycle/install.mjs +5 -5
  36. package/src/commands/lifecycle/uninstall.mjs +4 -4
  37. package/docs/superpowers/plans/2026-05-12-ticket-id-in-reports.md +0 -638
  38. package/docs/superpowers/plans/2026-05-14-convergence-queue-pruning.md +0 -1568
  39. package/docs/superpowers/plans/2026-05-17-dual-format-final-report.md +0 -167
  40. package/docs/superpowers/plans/2026-05-20-final-report-language.md +0 -1501
  41. package/docs/superpowers/plans/2026-05-20-implementation-planning-multi-stage.md +0 -1267
  42. package/docs/superpowers/plans/2026-05-20-okstra-run-prompt-sot-b1.md +0 -1007
  43. package/docs/superpowers/plans/2026-05-20-wizard-messages-json-sot.md +0 -720
  44. package/docs/superpowers/plans/2026-05-20-wizard-prompt-json-sot-a1.md +0 -681
  45. package/docs/superpowers/plans/2026-05-21-improvement-discovery-task-type.md +0 -1691
  46. package/docs/superpowers/plans/2026-05-24-implementation-lead-context-slimming.md +0 -1700
  47. package/docs/superpowers/plans/2026-05-25-okstra-project-root-rename.md +0 -158
  48. package/docs/superpowers/plans/2026-05-26-wizard-3-option-picker.md +0 -860
  49. package/docs/superpowers/plans/2026-06-02-final-verification-protocol-hardening.md +0 -326
  50. package/docs/superpowers/plans/2026-06-02-okstra-run-branch-confirm-step.md +0 -337
  51. package/docs/superpowers/plans/2026-06-02-okstra-run-phase-pane-cleanup.md +0 -410
  52. package/docs/superpowers/plans/2026-06-02-requirements-discovery-fanout.md +0 -728
  53. package/docs/superpowers/plans/2026-06-04-adversarial-implementation-planning.md +0 -294
  54. package/docs/superpowers/plans/2026-06-04-adversarial-verification.md +0 -570
  55. package/docs/superpowers/plans/2026-06-04-coverage-critic.md +0 -516
  56. package/docs/superpowers/plans/2026-06-04-stage-cohesion-planner.md +0 -351
  57. package/docs/superpowers/plans/2026-06-04-stage-run-batching.md +0 -457
  58. package/docs/superpowers/plans/2026-06-05-acceptance-critic.md +0 -251
  59. package/docs/superpowers/plans/2026-06-05-compact-markdown-report-tables.md +0 -323
  60. package/docs/superpowers/plans/2026-06-05-wizard-batch-prompts.md +0 -559
  61. package/docs/superpowers/plans/2026-06-06-final-verification-whole-task-gate.md +0 -993
  62. package/docs/superpowers/plans/2026-06-06-stage-parallel-and-pending-fixes.md +0 -93
  63. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p1.md +0 -447
  64. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p2.md +0 -289
  65. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p3.md +0 -774
  66. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p4.md +0 -303
  67. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p5-multidep-base.md +0 -387
  68. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase2.md +0 -275
  69. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase3.md +0 -282
  70. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4a.md +0 -147
  71. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4b.md +0 -262
  72. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4c.md +0 -184
  73. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4d.md +0 -88
  74. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4e.md +0 -250
  75. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa.md +0 -409
  76. package/docs/superpowers/plans/2026-06-09-implementation-run-artifact-stage-isolation.md +0 -320
  77. package/docs/superpowers/plans/2026-06-10-concurrent-run-team-guard.md +0 -456
  78. package/docs/superpowers/plans/2026-06-10-git-reconcile-stale-sha-recovery.md +0 -1408
  79. package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling-PROBE.md +0 -42
  80. package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling.md +0 -337
  81. package/docs/superpowers/plans/2026-06-10-p6-token-usage-incremental.md +0 -1029
  82. package/docs/superpowers/plans/2026-06-10-stage-group-handoff.md +0 -1572
  83. package/docs/superpowers/plans/2026-06-11-fix-cycle.md +0 -1290
  84. package/docs/superpowers/plans/2026-06-11-wizard-whole-task-final-verification.md +0 -526
  85. package/docs/superpowers/plans/2026-06-12-html-plan-approval.md +0 -1000
  86. package/docs/superpowers/plans/2026-06-13-repo-risk-hardening.md +0 -493
  87. package/docs/superpowers/plans/2026-06-14-host-runtime-auto-execution.md +0 -1775
  88. package/docs/superpowers/plans/2026-06-15-coding-preflight-pack-dispatch-path.md +0 -504
  89. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-final-fixups.md +0 -342
  90. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-fixups.md +0 -258
  91. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-remaining-fixups.md +0 -387
  92. package/docs/superpowers/plans/2026-06-15-internal-skill-resource-migration.md +0 -749
  93. package/docs/superpowers/plans/2026-06-15-worker-prompt-anchor-final-fixups.md +0 -828
  94. package/docs/superpowers/plans/2026-06-15-worker-prompt-header-error-contract.md +0 -490
  95. package/docs/superpowers/plans/2026-06-17-okstra-error-report.md +0 -724
  96. package/docs/superpowers/plans/2026-06-18-subagent-pane-reclaim.md +0 -483
  97. package/docs/superpowers/plans/2026-06-19-agent-operating-standard.md +0 -476
  98. package/docs/superpowers/plans/2026-06-19-okstra-inspect-recap-facet.md +0 -647
  99. package/docs/superpowers/plans/2026-06-20-error-feedback-loop.md +0 -1019
  100. package/docs/superpowers/plans/2026-06-20-run-index-row-normalization.md +0 -583
  101. package/docs/superpowers/plans/2026-06-20-stage-auto-integrate-teardown.md +0 -819
  102. package/docs/superpowers/plans/2026-06-21-okstra-container-local-user-test.md +0 -714
  103. package/docs/superpowers/plans/2026-06-21-release-handoff-local-checkout.md +0 -348
  104. package/docs/superpowers/plans/2026-06-23-implementation-stage-multiselect-chain.md +0 -630
  105. package/docs/superpowers/plans/2026-06-23-implementation-step-commit-granularity.md +0 -274
  106. package/docs/superpowers/plans/2026-06-23-phase-batch-cleanup-enforcement.md +0 -409
  107. package/docs/superpowers/plans/2026-06-24-cross-project-precondition.md +0 -542
  108. package/docs/superpowers/plans/2026-06-24-decision-drafts-render-gap.md +0 -568
  109. package/docs/superpowers/plans/2026-06-24-manual-user-test-section.md +0 -203
  110. package/docs/superpowers/plans/2026-06-24-okstra-container-build-rename.md +0 -525
  111. package/docs/superpowers/specs/2026-05-12-ticket-id-in-reports-design.md +0 -131
  112. package/docs/superpowers/specs/2026-05-15-implementation-plan-verification-design.md +0 -254
  113. package/docs/superpowers/specs/2026-05-20-final-report-language-design.md +0 -383
  114. package/docs/superpowers/specs/2026-05-20-implementation-planning-multi-stage-design.md +0 -322
  115. package/docs/superpowers/specs/2026-05-20-okstra-run-prompt-sot-design.md +0 -299
  116. package/docs/superpowers/specs/2026-05-21-improvement-discovery-task-type-design.md +0 -335
  117. package/docs/superpowers/specs/2026-06-02-okstra-run-branch-confirm-step-design.md +0 -113
  118. package/docs/superpowers/specs/2026-06-02-okstra-run-phase-pane-cleanup-design.md +0 -173
  119. package/docs/superpowers/specs/2026-06-02-requirements-discovery-fanout-design.md +0 -154
  120. package/docs/superpowers/specs/2026-06-04-adversarial-implementation-planning-design.md +0 -90
  121. package/docs/superpowers/specs/2026-06-04-adversarial-verification-design.md +0 -176
  122. package/docs/superpowers/specs/2026-06-04-coverage-critic-design.md +0 -99
  123. package/docs/superpowers/specs/2026-06-04-stage-splitting-cost-aware-design.md +0 -98
  124. package/docs/superpowers/specs/2026-06-05-acceptance-critic-design.md +0 -90
  125. package/docs/superpowers/specs/2026-06-05-compact-markdown-report-tables-design.md +0 -87
  126. package/docs/superpowers/specs/2026-06-05-wizard-batch-prompts-design.md +0 -121
  127. package/docs/superpowers/specs/2026-06-06-final-verification-whole-task-gate-design.md +0 -126
  128. package/docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md +0 -180
  129. package/docs/superpowers/specs/2026-06-06-vertical-slice-tdd-planning-design.md +0 -179
  130. package/docs/superpowers/specs/2026-06-07-stage-conformance-qa-design.md +0 -169
  131. package/docs/superpowers/specs/2026-06-09-executor-model-custom-id-cascade-design.md +0 -66
  132. package/docs/superpowers/specs/2026-06-09-implementation-run-artifact-stage-isolation-design.md +0 -87
  133. package/docs/superpowers/specs/2026-06-10-blocking-contract-posthoc-conformance-design.md +0 -168
  134. package/docs/superpowers/specs/2026-06-10-concurrent-run-team-guard-design.md +0 -107
  135. package/docs/superpowers/specs/2026-06-10-git-reconcile-stale-sha-recovery-design.md +0 -105
  136. package/docs/superpowers/specs/2026-06-10-lead-worker-completion-polling-design.md +0 -113
  137. package/docs/superpowers/specs/2026-06-10-stage-group-handoff-design.md +0 -156
  138. package/docs/superpowers/specs/2026-06-11-brief-entry-only-handoff-stage-entry-design.md +0 -158
  139. package/docs/superpowers/specs/2026-06-11-fix-cycle-design.md +0 -94
  140. package/docs/superpowers/specs/2026-06-11-wizard-whole-task-final-verification-design.md +0 -89
  141. package/docs/superpowers/specs/2026-06-12-codex-lead-adapter-design.md +0 -358
  142. package/docs/superpowers/specs/2026-06-12-html-plan-approval-design.md +0 -85
  143. package/docs/superpowers/specs/2026-06-12-stage-discipline-rule-design.md +0 -108
  144. package/docs/superpowers/specs/2026-06-13-forbidden-actions-ssot-design.md +0 -134
  145. package/docs/superpowers/specs/2026-06-13-neutral-tmux-lead-adapter-design.md +0 -284
  146. package/docs/superpowers/specs/2026-06-14-host-runtime-auto-execution-design.md +0 -404
  147. package/docs/superpowers/specs/2026-06-17-okstra-error-report-design.md +0 -123
  148. package/docs/superpowers/specs/2026-06-18-subagent-pane-reclaim-design.md +0 -150
  149. package/docs/superpowers/specs/2026-06-19-agent-operating-standard-design.md +0 -120
  150. package/docs/superpowers/specs/2026-06-19-okstra-inspect-recap-facet-design.md +0 -96
  151. package/docs/superpowers/specs/2026-06-20-error-feedback-loop-design.md +0 -171
  152. package/docs/superpowers/specs/2026-06-20-run-index-row-normalization-design.md +0 -112
  153. package/docs/superpowers/specs/2026-06-20-stage-auto-integrate-teardown-design.md +0 -145
  154. package/docs/superpowers/specs/2026-06-21-okstra-container-local-user-test-design.md +0 -125
  155. package/docs/superpowers/specs/2026-06-21-release-handoff-local-checkout-design.md +0 -113
  156. package/docs/superpowers/specs/2026-06-23-implementation-stage-multiselect-chain-design.md +0 -138
  157. package/docs/superpowers/specs/2026-06-23-implementation-step-commit-granularity-design.md +0 -120
  158. package/docs/superpowers/specs/2026-06-24-cross-project-precondition-design.md +0 -129
  159. package/docs/superpowers/specs/2026-06-24-decision-drafts-render-gap-design.md +0 -185
  160. package/docs/superpowers/specs/2026-06-24-manual-user-test-section-design.md +0 -121
  161. package/docs/superpowers/specs/2026-06-24-okstra-container-build-rename-design.md +0 -110
@@ -1,348 +0,0 @@
1
- # release-handoff `local checkout` 액션 구현 계획
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:** release-handoff 에 `local checkout` 액션을 추가해, 검증된 task 브랜치를 메인 워크트리로 가져와 로컬 테스트 가능 상태로 만든다.
6
-
7
- **Architecture:** Python 헬퍼 `okstra handoff local-checkout` 가 registry 의 task-key 행에서 okstra 워크트리·브랜치를 해소하고, 메인 워크트리 cwd 에서 `git worktree remove --force`(브랜치 보존) → `release_status`(branch 슬롯 유지) → `git checkout` 을 수행한다. release-handoff 프로필이 확인을 받고 이 명령 하나만 호출한다. base 브랜치는 절대 건드리지 않는다.
8
-
9
- **Tech Stack:** Python 3 (argparse, subprocess), 기존 `okstra_ctl.handoff` / `worktree` / `worktree_registry`, Node CLI shim, markdown 프로필.
10
-
11
- ## Global Constraints
12
-
13
- - 설계 문서: [docs/superpowers/specs/2026-06-21-release-handoff-local-checkout-design.md](../specs/2026-06-21-release-handoff-local-checkout-design.md) — 충돌 시 spec 우선.
14
- - `runtime/` 직접 수정 금지(빌드 산출물). 소스는 `scripts/` `src/` `prompts/`; 변경 후 `npm run build`.
15
- - pre-1.0 — compat shim 불필요. `local only` 액션은 완전 제거.
16
- - 함수 본문 50줄 이하.
17
- - 동시 세션 환경 — git amend 금지, 항상 새 커밋. 내 작업 파일만 스테이징.
18
- - Conventional Commits, 메시지 한국어 prose, AI 트레일러 금지.
19
- - 사용자 영향 있는 변경은 [CHANGES.md](../../../CHANGES.md) 에 `사용자 영향:` 항목 추가(한국어).
20
- - `local checkout` 은 whole-task 모드 전용. base 브랜치 자동 머지는 비목표.
21
-
22
- ## File Structure
23
-
24
- - `scripts/okstra_ctl/handoff.py` — `local_checkout()` 코어 + `local-checkout` 서브커맨드/디스패치 추가.
25
- - `src/commands/execute/handoff.mjs` — USAGE 에 `local-checkout` 노출(동작은 기존 shim 이 그대로 forward).
26
- - `tests/handoff/test_handoff_local_checkout.py` — 신규: 성공/메인 dirty 거부/registry 행 없음 + 브랜치 보존 실증.
27
- - `prompts/profiles/release-handoff.md` — 액션 선택 재편 + 핸들러 + `local only` 잔존 참조 정리 + 보고 deliverable.
28
- - `CHANGES.md` — 사용자 영향 항목.
29
-
30
- ---
31
-
32
- ### Task 1: `local_checkout()` 코어 + CLI 서브커맨드
33
-
34
- **Files:**
35
- - Modify: `scripts/okstra_ctl/handoff.py` (import 확장 + `local_checkout()` 추가 + `main()` argparse/dispatch)
36
- - Modify: `src/commands/execute/handoff.mjs` (USAGE)
37
- - Test: `tests/handoff/test_handoff_local_checkout.py`
38
-
39
- **Interfaces:**
40
- - Consumes: `worktree_registry.lookup(project_id, task_group, task_id) -> Optional[WorktreeEntry]` (`.branch`, `.worktree_path`, `.status`); `worktree_registry.release_status(project_id, task_group, task_id)`; `worktree.main_worktree_path(Path) -> Path`; `worktree.is_dirty_excluding_okstra(cwd) -> bool`; `handoff._run_git(args, cwd, check=True)`.
41
- - Produces: `handoff.local_checkout(*, project_root, project_id, task_group, task_id) -> Dict[str, Any]` — 성공 시 `{"ok": True, "branch": str, "mainWorktreePath": str, "removedWorktree": str, "status": "checked-out"}`; 전제 위반 시 `HandoffError`(→ exit 1). CLI: `okstra handoff local-checkout --project-root <dir> --project-id <id> --task-group <g> --task-id <t>`.
42
-
43
- - [ ] **Step 1: 실패 테스트 작성**
44
-
45
- `tests/handoff/test_handoff_local_checkout.py` 생성:
46
-
47
- ```python
48
- """handoff.local_checkout — okstra 워크트리 제거 + 메인 checkout 의 git 실증."""
49
- import sys
50
- import subprocess
51
- from pathlib import Path
52
- from _paths import REPO_ROOT
53
-
54
- LIB_DIR = REPO_ROOT / "scripts"
55
- if str(LIB_DIR) not in sys.path:
56
- sys.path.insert(0, str(LIB_DIR))
57
-
58
- import pytest
59
-
60
- from okstra_ctl import handoff, worktree_registry
61
-
62
- ARGS = dict(project_id="proj", task_group="grp", task_id="task")
63
- BRANCH = "feature-development-task"
64
-
65
-
66
- def _git(repo, *args):
67
- r = subprocess.run(["git", *args], cwd=str(repo),
68
- capture_output=True, text=True)
69
- assert r.returncode == 0, r.stderr
70
- return r.stdout.strip()
71
-
72
-
73
- def _main_repo(tmp_path):
74
- repo = tmp_path / "main"
75
- repo.mkdir()
76
- _git(repo, "init", "-q", "-b", "main")
77
- _git(repo, "config", "user.email", "t@t")
78
- _git(repo, "config", "user.name", "t")
79
- (repo / "base.txt").write_text("base\n")
80
- _git(repo, "add", ".")
81
- _git(repo, "commit", "-q", "-m", "base")
82
- return repo
83
-
84
-
85
- def _provision_okstra_worktree(repo, tmp_path):
86
- """main repo 에서 task 브랜치를 든 okstra 워크트리를 만들고 registry 에 등록."""
87
- okstra_wt = tmp_path / "okstra-wt"
88
- _git(repo, "worktree", "add", "-b", BRANCH, str(okstra_wt), "main")
89
- (okstra_wt / "work.txt").write_text("task work\n")
90
- _git(okstra_wt, "add", ".")
91
- _git(okstra_wt, "commit", "-q", "-m", "task work")
92
- worktree_registry.reserve(**ARGS, worktree_path=str(okstra_wt),
93
- branch=BRANCH, base_ref="main")
94
- return okstra_wt
95
-
96
-
97
- def test_local_checkout_removes_worktree_and_checks_out_in_main(tmp_path):
98
- repo = _main_repo(tmp_path)
99
- okstra_wt = _provision_okstra_worktree(repo, tmp_path)
100
-
101
- out = handoff.local_checkout(project_root=repo, **ARGS)
102
-
103
- assert out["status"] == "checked-out"
104
- assert out["branch"] == BRANCH
105
- assert not okstra_wt.exists() # okstra 워크트리 제거
106
- assert _git(repo, "rev-parse", "--abbrev-ref", "HEAD") == BRANCH # 메인이 task 브랜치
107
- assert _git(repo, "rev-parse", "--verify", BRANCH) # 브랜치 ref 보존
108
- assert (repo / "work.txt").exists() # task 작업물이 메인에 보임
109
- assert worktree_registry.lookup(**ARGS).status == "released"
110
-
111
-
112
- def test_local_checkout_aborts_when_main_dirty(tmp_path):
113
- repo = _main_repo(tmp_path)
114
- okstra_wt = _provision_okstra_worktree(repo, tmp_path)
115
- (repo / "uncommitted.txt").write_text("dirty\n") # 메인 dirty (.okstra 밖)
116
-
117
- with pytest.raises(handoff.HandoffError, match="미커밋"):
118
- handoff.local_checkout(project_root=repo, **ARGS)
119
-
120
- assert okstra_wt.exists() # 보존
121
- assert worktree_registry.lookup(**ARGS).status == "active" # 미변경
122
-
123
-
124
- def test_local_checkout_errors_when_no_registry_entry(tmp_path):
125
- repo = _main_repo(tmp_path)
126
- with pytest.raises(handoff.HandoffError, match="registry"):
127
- handoff.local_checkout(project_root=repo, **ARGS)
128
- ```
129
-
130
- - [ ] **Step 2: 테스트 실패 확인**
131
-
132
- Run: `python3 -m pytest tests/handoff/test_handoff_local_checkout.py -v`
133
- Expected: FAIL — `AttributeError: module 'okstra_ctl.handoff' has no attribute 'local_checkout'`
134
-
135
- - [ ] **Step 3: import 확장**
136
-
137
- `scripts/okstra_ctl/handoff.py` 의 import 한 줄을 교체:
138
-
139
- ```python
140
- from .worktree import compute_branch_name, compute_worktree_path
141
- ```
142
-
143
- ```python
144
- from .worktree import (compute_branch_name, compute_worktree_path,
145
- main_worktree_path, is_dirty_excluding_okstra)
146
- ```
147
-
148
- - [ ] **Step 4: `local_checkout()` 구현**
149
-
150
- `scripts/okstra_ctl/handoff.py` 에 `assemble(...)` 정의 바로 다음(즉 `record_verified` 앞)에 추가:
151
-
152
- ```python
153
- def local_checkout(*, project_root, project_id, task_group, task_id) -> Dict[str, Any]:
154
- """whole-task: okstra task-key 워크트리를 제거하고 task 브랜치를 메인
155
- 워크트리에 checkout 한다(브랜치 보존). 메인이 dirty 면 거부. base 브랜치는
156
- 건드리지 않는다."""
157
- entry = worktree_registry.lookup(project_id, task_group, task_id)
158
- if not entry or not entry.branch or not entry.worktree_path:
159
- raise HandoffError(
160
- "task-key worktree registry 엔트리가 없습니다 — local checkout 대상 없음")
161
- main_wt = main_worktree_path(Path(project_root))
162
- if is_dirty_excluding_okstra(main_wt):
163
- raise HandoffError(
164
- f"메인 워크트리에 미커밋 변경이 있습니다 ({main_wt}) — "
165
- "커밋/스태시 후 다시 시도하세요")
166
- _run_git(["worktree", "remove", "--force", entry.worktree_path], main_wt)
167
- worktree_registry.release_status(project_id, task_group, task_id)
168
- co = _run_git(["checkout", entry.branch], main_wt, check=False)
169
- if co.returncode != 0:
170
- raise HandoffError(
171
- f"git checkout {entry.branch} 실패: {co.stderr.strip()} — 워크트리는 "
172
- f"제거됨; 메인({main_wt})에서 수동 checkout 으로 복구하세요")
173
- return {"ok": True, "branch": entry.branch, "mainWorktreePath": str(main_wt),
174
- "removedWorktree": entry.worktree_path, "status": "checked-out"}
175
- ```
176
-
177
- - [ ] **Step 5: argparse 서브커맨드 + 디스패치**
178
-
179
- `scripts/okstra_ctl/handoff.py` 의 `main()` 에서 `record-pr` 서브파서 등록 다음에 추가:
180
-
181
- ```python
182
- sp = sub.add_parser("local-checkout")
183
- common(sp, plan=False)
184
- sp.add_argument("--project-root", default=".")
185
- sp.add_argument("--project-id", required=True)
186
- sp.add_argument("--task-group", required=True)
187
- sp.add_argument("--task-id", required=True)
188
- ```
189
-
190
- 디스패치에서 `else:`(record-pr) 바로 앞에 elif 추가:
191
-
192
- ```python
193
- elif a.cmd == "local-checkout":
194
- out = local_checkout(
195
- project_root=Path(a.project_root).resolve(),
196
- project_id=a.project_id, task_group=a.task_group,
197
- task_id=a.task_id)
198
- ```
199
-
200
- - [ ] **Step 6: 테스트 통과 확인**
201
-
202
- Run: `python3 -m pytest tests/handoff/test_handoff_local_checkout.py -v`
203
- Expected: PASS (3 passed)
204
-
205
- - [ ] **Step 7: handoff.mjs USAGE 갱신**
206
-
207
- `src/commands/execute/handoff.mjs` 의 USAGE 에서 `record-pr` 줄 다음에 추가:
208
-
209
- ```
210
- okstra handoff record-pr --plan-run-root <dir> --stages 2,3 \\
211
- --branch <b> --url <u>
212
- okstra handoff local-checkout --project-root <dir> --project-id <id> \\
213
- --task-group <g> --task-id <t>
214
- ```
215
-
216
- - [ ] **Step 8: CLI 스모크**
217
-
218
- Run: `node bin/okstra handoff --help`
219
- Expected: 출력에 `local-checkout` 줄이 보임.
220
-
221
- - [ ] **Step 9: 커밋**
222
-
223
- ```bash
224
- git add scripts/okstra_ctl/handoff.py src/commands/execute/handoff.mjs tests/handoff/test_handoff_local_checkout.py
225
- git commit -m "feat(handoff): okstra handoff local-checkout 서브커맨드 추가"
226
- ```
227
-
228
- ---
229
-
230
- ### Task 2: release-handoff 프로필 — 액션 재편 + `local only` 정리
231
-
232
- **Files:**
233
- - Modify: `prompts/profiles/release-handoff.md`
234
-
235
- **Interfaces:**
236
- - Consumes: Task 1 의 CLI `okstra handoff local-checkout ...`.
237
- - Produces: 프로필 동작 — `local checkout`(첫째)/`push + PR`/`skip` 3지선다, whole-task 게이트, 확인 후 헬퍼 호출, 보고 deliverable.
238
-
239
- - [ ] **Step 1: 액션 선택 블록 교체**
240
-
241
- `prompts/profiles/release-handoff.md` 의 다음 블록(현재 22–26줄)을 교체:
242
-
243
- old:
244
- ```
245
- 1. **Action selection** — present three choices and capture exactly one:
246
- - `local only` — complete the handoff as a local delivery record: record the accepted, already-committed branch and end without push or PR.
247
- - `push + PR` — push the feature branch, then open or reuse a pull request.
248
- - `skip` — cancel delivery actions for now: record that release-handoff was intentionally skipped and end the run without any git command.
249
- If the user picks `skip`, route directly to the final-report self-review pass.
250
- ```
251
- new:
252
- ```
253
- 1. **Action selection** — present three choices and capture exactly one:
254
- - `local checkout` (whole-task mode only) — bring the verified task branch into the MAIN worktree for local testing (no push, no PR). See step 1c. When `HANDOFF_MODE` is `stage-group`, do NOT offer this option — tell the user "`local checkout` is whole-task mode only" and re-ask.
255
- - `push + PR` — push the feature branch, then open or reuse a pull request.
256
- - `skip` — cancel delivery actions for now: record that release-handoff was intentionally skipped and end the run without any git command.
257
- If the user picks `skip`, route directly to the final-report self-review pass.
258
- 1c. **Local checkout execution** (only when the user picked `local checkout`) — confirm with the user that okstra will remove the okstra task worktree and `git checkout <feature branch>` in the MAIN worktree, and that the base branch is never modified. On confirmation run:
259
- `okstra handoff local-checkout --project-root <project root> --project-id <id> --task-group <g> --task-id <t>`
260
- Exit 1 means a precondition failed (MAIN worktree dirty, registry entry missing, or checkout failed): show the error verbatim and re-ask the action selection. On success the okstra task worktree no longer exists — the lead's cwd is gone, so EVERY subsequent step (final-report authoring included) MUST use absolute paths or run from the MAIN worktree. Then route to the final-report self-review pass.
261
- ```
262
-
263
- - [ ] **Step 2: 잔존 `local only` 참조 정리**
264
-
265
- 다음 세 줄을 각각 교체:
266
-
267
- 68줄 old: ` - Q1 action: `local only` | `push + PR` | `skip`.`
268
- 68줄 new: ` - Q1 action: `local checkout` | `push + PR` | `skip`.`
269
-
270
- 75줄 old: ` - `- Not run (user picked local only or skip).``
271
- 75줄 new: ` - `- Not run (user picked local checkout or skip).``
272
-
273
- 79줄 old: ` - `- No PR action requested.` (user picked `local only` or `skip`)`
274
- 79줄 new: ` - `- No PR action requested.` (user picked `local checkout` or `skip`)`
275
-
276
- - [ ] **Step 3: Local Checkout Outcome deliverable 추가**
277
-
278
- `Required deliverable shape` 의 **Pull Request Outcome** 블록(현재 78–82줄) 다음에 새 deliverable 추가:
279
-
280
- old:
281
- ```
282
- - `- PR creation skipped: <reason>` for any user-driven cancellation
283
- - **Stage Group** (stage-group mode only): selected stages, each stage's single-stage verification report path + quoted `Verdict Token` row, collector branch name, merge commit SHAs from assemble, and the dependency-closure verdict (from the assemble output / error).
284
- ```
285
- new:
286
- ```
287
- - `- PR creation skipped: <reason>` for any user-driven cancellation
288
- - **Local Checkout Outcome**: one of
289
- - `- Not run (user picked push + PR or skip).`
290
- - `- Checked out <branch> into <main worktree path>; okstra task worktree <path> removed. Next: 로컬 테스트 후 PR 하려면 okstra-run 으로 release-handoff 재진입 → push + PR.`
291
- - **Stage Group** (stage-group mode only): selected stages, each stage's single-stage verification report path + quoted `Verdict Token` row, collector branch name, merge commit SHAs from assemble, and the dependency-closure verdict (from the assemble output / error).
292
- ```
293
-
294
- - [ ] **Step 4: 잔존 참조 일관성 확인**
295
-
296
- Run: `grep -n "local only" prompts/profiles/release-handoff.md`
297
- Expected: 출력 없음(모든 `local only` 제거됨).
298
-
299
- - [ ] **Step 5: 워크플로 validator**
300
-
301
- Run: `bash validators/validate-workflow.sh`
302
- Expected: PASS(또는 본 변경과 무관한 기존 상태 그대로 — 신규 실패 없음).
303
-
304
- - [ ] **Step 6: 커밋**
305
-
306
- ```bash
307
- git add prompts/profiles/release-handoff.md
308
- git commit -m "feat(handoff): release-handoff 에 local checkout 액션 + local only 제거"
309
- ```
310
-
311
- ---
312
-
313
- ### Task 3: CHANGES.md + 빌드 + 최종 검증
314
-
315
- **Files:**
316
- - Modify: `CHANGES.md`
317
-
318
- - [ ] **Step 1: CHANGES.md 항목 추가**
319
-
320
- `CHANGES.md` 의 `## 2026-06-21` 섹션(없으면 최상단 날짜 섹션 위에 생성)에 추가:
321
-
322
- ```markdown
323
- ### feat(handoff): release-handoff 에 `local checkout` 액션 추가 — 검증된 브랜치를 메인 워크트리로
324
-
325
- - **배경**: okstra task 작업은 격리된 git worktree(`~/.okstra/worktrees/...`)에서 진행돼, 검증이 끝난 뒤 사용자가 결과를 로컬에서 테스트하려면 그 폴더로 직접 `cd` 해야 했다. task 브랜치를 메인 작업 디렉터리로 가져오는 한-스텝 경로가 없었다.
326
- - **해결**: release-handoff 액션 선택을 `local checkout`(신규, 첫째)/`push + PR`/`skip` 으로 재편하고(중복이던 `local only` 제거), 신규 `okstra handoff local-checkout` 헬퍼가 메인 워크트리 dirty 확인 후 okstra task 워크트리를 제거(브랜치 보존)하고 메인에서 `git checkout <task-branch>` 를 수행한다. base 브랜치는 건드리지 않는다(whole-task 모드 전용).
327
- - 사용자 영향: release-handoff 에서 `local checkout` 을 고르면, 검증된 task 브랜치가 메인 작업 디렉터리에 바로 체크아웃돼 별도 `cd` 없이 로컬 테스트할 수 있다. 메인에 미커밋 변경이 있으면 중단·안내한다. 기존 `local only` 액션은 `skip` 과 중복이라 제거됐다. (설치 환경은 `okstra install` 로 런타임 갱신 후 적용.)
328
- ```
329
-
330
- - [ ] **Step 2: 런타임 빌드**
331
-
332
- Run: `npm run build`
333
- Expected: 성공(소스가 `runtime/` 으로 동기화됨).
334
-
335
- - [ ] **Step 3: 최종 검증 스윕**
336
-
337
- Run: `python3 -m pytest tests/handoff/test_handoff_local_checkout.py tests/handoff/test_handoff_assemble.py -q`
338
- Expected: PASS(신규 3 + 기존 회귀 무손상).
339
-
340
- Run: `node bin/okstra handoff --help`
341
- Expected: `local-checkout` 노출.
342
-
343
- - [ ] **Step 4: 커밋**
344
-
345
- ```bash
346
- git add CHANGES.md
347
- git commit -m "docs(handoff): local checkout 액션 CHANGES 기록"
348
- ```