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,150 +0,0 @@
|
|
|
1
|
-
# SubagentStop 기반 worker pane 완료-즉시 회수 + 내성 fallback 설계
|
|
2
|
-
|
|
3
|
-
- 작성일: 2026-06-18
|
|
4
|
-
- 상태: 설계(승인 대기)
|
|
5
|
-
- 관련: [_common-contract.md](../../../prompts/profiles/_common-contract.md) phase-start cleanup, [okstra-trace-cleanup.sh](../../../scripts/okstra-trace-cleanup.sh), [tmux.py](../../../scripts/okstra_ctl/tmux.py), [settings.template.json](../../../templates/reports/settings.template.json)
|
|
6
|
-
|
|
7
|
-
## 1. 배경 — 근거로 확정된 실제 원인
|
|
8
|
-
|
|
9
|
-
`jobs:uploadfont:dev-9047` 의 implementation-planning run 에서 13번째 worker dispatch(antigravity gap-verify)가 하니스 에러로 실패했다:
|
|
10
|
-
|
|
11
|
-
> `Failed to create teammate pane: no space for new pane — no room for another tmux split`
|
|
12
|
-
|
|
13
|
-
이 run 의 lead 가 `state/session-work-summary.md` 5절에 자가 분석을 남겼으나, 그 두 전제가 디스크 데이터와 어긋났다. 코드/데이터로 재검증한 결과는 다음과 같다.
|
|
14
|
-
|
|
15
|
-
### 1.1 정정된 사실
|
|
16
|
-
|
|
17
|
-
- **에러 주체는 okstra 가 아니라 Claude Code 하니스다.** okstra 의 `split_worker_pane` 은 실패해도 조용히 degrade 한다([dispatch_core.py](../../../scripts/okstra_ctl/dispatch_core.py) `_start_tmux_or_degrade`). 위 메시지는 하니스의 teammate pane 생성이 낸 것이다.
|
|
18
|
-
- **"lead-pane.id 빈 값 → lead 가 tmux 밖"(자가분석 주장 4)은 사실과 다르다.** 그 run 의 `state/lead-pane.id` = `%319` 로, lead 는 tmux 안에 있었고 기록도 정상이었다. phase-start cleanup 의 lead-in-tmux 게이트는 통과 가능한 상태였다.
|
|
19
|
-
- **"no-team 이라 shutdown_request 가 skip 되어 pane 누적"(주장 3)은 인과가 틀렸다.** `shutdown_request` 는 FleetView roster 정리이지 tmux pane 회수가 아니다([_common-contract.md:42](../../../prompts/profiles/_common-contract.md) — dismissed teammate 는 idle pill 로 남는다고 명시). tmux pane 회수는 전적으로 `okstra-trace-cleanup.sh` 의 일이고 no-team 여부와 무관하다.
|
|
20
|
-
|
|
21
|
-
### 1.2 진짜 원인
|
|
22
|
-
|
|
23
|
-
lead 가 tmux 안이었으므로 pane 회수((a) `okstra-trace-cleanup.sh`)는 돌 수 있었는데 누적을 못 막았다. 두 구조적 사실 때문이다.
|
|
24
|
-
|
|
25
|
-
1. **cleanup 미실행 정황.** phase-start cleanup 은 prompt 계약일 뿐 코드 강제가 아니며, 그 run 의 Phase 진행 내역에 실행 기록이 없다.
|
|
26
|
-
2. **okstra 는 하니스가 만든 teammate pane 에 태그를 못 단다.** `tag_pane` 은 okstra 가 직접 split 한 pane 에만 붙는다([tmux.py](../../../scripts/okstra_ctl/tmux.py) `split_worker_pane` 내부). 하니스 teammate pane 의 식별 수단은 title 매칭뿐이고, 그건 하니스가 pane title 을 어떻게 다는지에 의존해 불확실하다.
|
|
27
|
-
|
|
28
|
-
그 run 의 pane 구성: 하니스 teammate pane 13개 + codex/antigravity wrapper 가 만든 trace pane 7개 = 한 window 에 20개 누적 → 분할 한도 초과.
|
|
29
|
-
|
|
30
|
-
## 2. 목표 / 비목표
|
|
31
|
-
|
|
32
|
-
### 목표
|
|
33
|
-
- 완료된 worker 의 pane 을 **완료 즉시** 회수해 한 window 의 누적이 분할 한도에 닿지 않게 한다(예방).
|
|
34
|
-
- 그럼에도 한도에 닿으면 run 이 멈추지 않고 자동으로 in-process 대체로 진행한다(내성).
|
|
35
|
-
|
|
36
|
-
### 비목표
|
|
37
|
-
- 하니스가 teammate pane 을 만드는 행위 자체를 막거나 바꾸지 않는다(okstra 통제 밖).
|
|
38
|
-
- 외부 CLI 워커(codex/antigravity)를 제거해 cross-verification 다양성을 훼손하지 않는다.
|
|
39
|
-
- FleetView roster 표시(idle pill) 정리는 본 설계 범위 밖(별개 메커니즘).
|
|
40
|
-
|
|
41
|
-
## 3. 제약 (설계가 마주한 벽)
|
|
42
|
-
|
|
43
|
-
| pane 종류 | 누가 만드나 | okstra 통제력 |
|
|
44
|
-
|---|---|---|
|
|
45
|
-
| 외부 CLI trace pane (`<cli>-<role>-<pid>-tail`) | codex/antigravity wrapper = **okstra 코드** | 높음 — `@okstra_trace_run` 태그로 식별·회수 |
|
|
46
|
-
| teammate pane (`*-worker` title) | **하니스** (Agent 도구 / Teams Task) | 낮음 — 태그 불가, title 매칭에만 의존 |
|
|
47
|
-
|
|
48
|
-
→ 확실히 회수 가능한 것은 **trace pane**(태그). teammate pane 은 title 회수가 되는지 **실측 게이트**(§6)로 확정해야 하며, 안 되면 내성(④)으로 백업한다.
|
|
49
|
-
|
|
50
|
-
## 4. 설계
|
|
51
|
-
|
|
52
|
-
### ① 훅 포인트: `SubagentStop`(+`TaskCompleted`)
|
|
53
|
-
|
|
54
|
-
PreToolUse(Agent)는 병렬 dispatch 시 Agent 호출마다 N회 발화하므로, dispatch 직전 일괄 cleanup 은 **같은 batch 의 진행 중 형제 worker pane 을 죽인다**(claude-code-guide 가 공식 hooks 문서로 확인). 따라서 채택하지 않는다.
|
|
55
|
-
|
|
56
|
-
대신 **완료 이벤트**에 건다 — 완료된 그 worker 만 정리하므로 진행 중 worker 는 건드리지 않고, 누적이 batch 경계까지 쌓이지 않는다.
|
|
57
|
-
|
|
58
|
-
- no-team(Agent background) 경로 → **`SubagentStop`** (입력: `session_id`, `agent_id`, `agent_type`, `agent_transcript_path`).
|
|
59
|
-
- Teams(`TaskCreate`) 경로 → **`TaskCompleted`** (입력: `task_id`, `teammate_name`, `team_name`, `session_id`).
|
|
60
|
-
|
|
61
|
-
두 훅 모두 [settings.template.json](../../../templates/reports/settings.template.json) 의 `hooks` 에 신규 배선한다(기존 SessionEnd `--reap`, PreToolUse coding-preflight 는 유지). 둘 다 부수효과 전용 — 스크립트는 항상 `exit 0`, 도구/세션 진행을 차단하지 않는다.
|
|
62
|
-
|
|
63
|
-
### ② cleanup 에 "완료된 worker만" 안전 모드 추가
|
|
64
|
-
|
|
65
|
-
현재 `okstra-trace-cleanup.sh --run-dir <RUN_DIR>` 은 그 run 의 태그/title pane 을 **진행 중 여부와 무관하게** 모두 닫는다. 완료 이벤트 훅에서 안전하게 쓰려면, **결과 파일이 이미 존재하는(=완료된) worker 의 pane 만** 닫는 모드가 필요하다.
|
|
66
|
-
|
|
67
|
-
새 모드(가칭) `--reclaim-completed --run-dir <RUN_DIR>`:
|
|
68
|
-
- §6 실측 결과에 따라 닫는 대상이 정해진다.
|
|
69
|
-
- 항상 닫음(확실): `@okstra_trace_run == RUN_DIR` 태그 trace pane 중, 대응 worker 의 `result_path` 가 존재하는 것.
|
|
70
|
-
- 조건부(실측 통과 시): lead 세션 안에서 title 이 `*-worker` allowlist 에 맞고 대응 worker 의 `result_path` 가 존재하는 teammate pane.
|
|
71
|
-
- 진행 중(result 미존재) worker pane 은 **절대 닫지 않는다** — 이 가드가 본 모드의 핵심.
|
|
72
|
-
|
|
73
|
-
trace pane → worker 매핑은 pane title(`<cli>-<role>-<pid>-tail`)의 role 과 run-dir 의 worker 산출물 경로(result_path) 규약으로 해석한다. 정확한 매핑 규약은 구현 plan 에서 `dispatch_core` 의 `status_path_for_prompt` / `result_path` 명명과 대조해 확정한다.
|
|
74
|
-
|
|
75
|
-
### ③ session ↔ run-dir 매핑 기록 (훅이 run-dir 을 알기 위함)
|
|
76
|
-
|
|
77
|
-
`SubagentStop`/`TaskCompleted` 입력은 `session_id`(lead 세션)를 주지만, 훅의 `cwd` 가 run-dir 과 일치한다는 보장이 없고 run-dir 전용 env 도 없다(공식 문서 확인). 그리고 **현재 `active.jsonl` row 에는 `leadSessionId` 가 없다**([index.py](../../../scripts/okstra_ctl/index.py) `reserve_active` row — `runId/taskKey/runDirRel/...` 만).
|
|
78
|
-
|
|
79
|
-
따라서 lead 가 run 시작 시 자기 `session_id ↔ RUN_DIR` 매핑을 알려진 위치에 기록한다. 두 후보:
|
|
80
|
-
|
|
81
|
-
- **(권장)** `~/.okstra/sessions/<session_id>.run` 단일 파일에 현재 RUN_DIR(절대경로)을 기록. run 시작 시 갱신, SessionEnd `--reap` 가 정리. 한 세션이 여러 run 을 순차 구동하면 **가장 최근 run-dir** 로 덮어쓴다(완료 이벤트는 항상 최근 run 소속이므로 안전).
|
|
82
|
-
- (대안) `active.jsonl` row 에 `leadSessionId` 필드를 추가. 다만 한 세션 = 여러 active row 일 때 최근 row 선택 로직이 필요하고 중앙 락 경합을 늘린다.
|
|
83
|
-
|
|
84
|
-
훅 스크립트는 stdin JSON 의 `session_id` 로 이 파일을 읽어 RUN_DIR 을 얻은 뒤 ②를 호출한다. 매핑이 없으면(파일 부재) silent no-op.
|
|
85
|
-
|
|
86
|
-
### ④ 내성 — lead 계약의 pane-실패 fallback
|
|
87
|
-
|
|
88
|
-
하니스의 teammate pane 생성은 okstra Python 이 관여하지 않으므로 코드로 강제할 수 없다. lead 행동 계약([_common-contract.md](../../../prompts/profiles/_common-contract.md) convergence/dispatch 절)에 명시한다:
|
|
89
|
-
|
|
90
|
-
- worker dispatch 가 `no room for another tmux split`(또는 동등한 pane 생성 실패)로 거부되면, 그 worker 를 **`run_in_background` 없이 in-process** 로 재시도하거나, 외부 CLI 워커였다면 in-process claude 분석으로 대체하고 그 사실(provider 불가)을 run 기록에 남긴다.
|
|
91
|
-
- 이미 `session-work-summary.md` 의 완화방안에 등장한 동작을 계약으로 승격하는 것이며, 코드 강제가 아닌 prompt 지시임을 문서에 명시(declaration ≠ enforcement 규칙).
|
|
92
|
-
|
|
93
|
-
## 5. 데이터 흐름
|
|
94
|
-
|
|
95
|
-
```
|
|
96
|
-
run 시작 (lead)
|
|
97
|
-
└─ ~/.okstra/sessions/<session_id>.run := RUN_DIR (③)
|
|
98
|
-
|
|
99
|
-
worker N 완료
|
|
100
|
-
└─ 하니스가 SubagentStop / TaskCompleted 발화
|
|
101
|
-
└─ 훅 command: okstra-subagent-reclaim.sh (stdin: session_id, agent_*)
|
|
102
|
-
├─ session_id → RUN_DIR (sessions/<id>.run 읽기, 없으면 no-op)
|
|
103
|
-
└─ okstra-trace-cleanup.sh --reclaim-completed --run-dir RUN_DIR (②)
|
|
104
|
-
├─ result_path 존재하는 worker 의 trace pane(태그) kill [확실]
|
|
105
|
-
└─ (실측 통과 시) result_path 존재하는 worker 의 teammate pane(title) kill [조건부]
|
|
106
|
-
※ 진행 중(result 미존재) worker pane 은 보존
|
|
107
|
-
|
|
108
|
-
dispatch 가 pane 실패로 거부 (lead)
|
|
109
|
-
└─ in-process 대체로 진행 + 기록 (④)
|
|
110
|
-
|
|
111
|
-
session 종료
|
|
112
|
-
└─ SessionEnd: okstra-trace-cleanup.sh --reap (기존 유지)
|
|
113
|
-
└─ sessions/<session_id>.run 정리
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
## 6. 실측 게이트 (구현 첫 단계, 코드 작성 전)
|
|
117
|
-
|
|
118
|
-
문서로 확인 불가한 단 하나의 가정 — **하니스가 teammate pane title 을 `*-worker` allowlist 에 맞게 다는가.**
|
|
119
|
-
|
|
120
|
-
검증 절차: tmux 안에서 okstra worker(claude-worker) 1개를 띄운 직후 `tmux list-panes -a -F '#{pane_id}\t#{pane_title}'` 로 그 pane 의 실제 title 을 확인한다.
|
|
121
|
-
- 매칭됨 → ② 의 teammate pane 회수(조건부)를 활성화한다.
|
|
122
|
-
- 매칭 안 됨 → ② 는 trace pane 만 회수하고, teammate pane 누적은 ④ 내성에 전적으로 의존한다(설계 문서·계약에 그 한계를 명시).
|
|
123
|
-
|
|
124
|
-
이 결과가 ②의 범위를 확정하므로, 구현 plan 의 첫 task 로 둔다.
|
|
125
|
-
|
|
126
|
-
> **구현 후 결론 (2026-06-18).** 실측과 무관하게 **hook 경로의 teammate pane 회수는 구조적으로 불가**로 확정됐다. hook 은 완료 이벤트마다 worker 하나씩 발화하는데 teammate pane 은 generic title(`*claude-worker*` 등)로만 식별되고 per-worker 태그가 없어([okstra-trace-cleanup.sh](../../../scripts/okstra-trace-cleanup.sh) `collect_okstra_panes` 의 title allowlist), 같은 batch 의 진행 중 형제 pane 과 완료 pane 을 구분할 수 없다 → title kill 시 진행 중 worker 를 죽일 위험. 그래서 `--reclaim-completed` 는 title 스캔을 건너뛴다(`RECLAIM -eq 0` 가드). teammate pane 을 안전하게 회수할 수 있는 유일한 지점은 **batch 경계**(직전 batch 의 모든 worker 가 완료된 시점)이며, 그것이 lead 의 phase-start cleanup(`--run-dir`, RECLAIM=0)이다. 위 §6 의 title-매칭 여부는 이 batch-경계 스캔의 유효성에 대한 질문일 뿐 hook 가능성과는 직교한다. 따라서 ②의 teammate 부분은 hook 에 넣지 않고 lead 의 batch-경계 cleanup 에 맡긴다.
|
|
127
|
-
|
|
128
|
-
## 7. 변경 대상 (구현 plan 에서 구체화)
|
|
129
|
-
|
|
130
|
-
| 파일 | 변경 |
|
|
131
|
-
|---|---|
|
|
132
|
-
| `templates/reports/settings.template.json` | `SubagentStop` + `TaskCompleted` 훅 신규 배선 |
|
|
133
|
-
| `scripts/okstra-subagent-reclaim.sh` (신규) | 훅 진입점 — stdin `session_id` → RUN_DIR → cleanup 호출 |
|
|
134
|
-
| `scripts/okstra-trace-cleanup.sh` | `--reclaim-completed` 모드(완료 worker pane 만) 추가 |
|
|
135
|
-
| `scripts/okstra_ctl/*` (run 시작 경로) | `~/.okstra/sessions/<session_id>.run` 매핑 기록 |
|
|
136
|
-
| `prompts/profiles/_common-contract.md` | ④ 내성 계약 명시(pane-실패 → in-process 대체) |
|
|
137
|
-
| `src/install.mjs` 관련 시드 | 신규 스크립트/훅이 설치 payload 에 포함되는지 확인 |
|
|
138
|
-
|
|
139
|
-
## 8. 테스트 전략
|
|
140
|
-
|
|
141
|
-
- `okstra-trace-cleanup.sh --reclaim-completed` 단위: result_path 존재/부재로 진행 중 worker pane 보존 vs 완료 pane 회수를 가르는지(태그 fixture 기반, tmux 없는 환경에서 list 모드로 검증).
|
|
142
|
-
- session↔run-dir 매핑 기록/조회 단위.
|
|
143
|
-
- 훅 진입점: stdin JSON(`session_id`) 파싱 → 매핑 부재 시 no-op, 존재 시 올바른 RUN_DIR 전달.
|
|
144
|
-
- e2e: 모의 worker 산출물 + 태그 pane 으로 "완료 즉시 회수, 진행 중 보존" 시나리오(tmux 가용 시).
|
|
145
|
-
|
|
146
|
-
## 9. 미해결 / 리스크
|
|
147
|
-
|
|
148
|
-
- **~~teammate pane title 회수 가능성~~ → 해소(2026-06-18).** §6 구현 후 결론 참조: hook 경로의 teammate pane 회수는 구조적으로 불가(generic title + per-worker 태그 부재). teammate pane 은 lead 의 batch-경계 phase-start cleanup 이 회수하며, 그 단계는 아래 de-gate 로 항상 실행된다.
|
|
149
|
-
- **~~한 세션 다중 run~~ → 무효(미채택).** 구현은 `sessions/<id>.run` 세션 매핑(③) 대신 `okstra-subagent-reclaim.sh` 가 `active.jsonl` 의 활성 run 전체를 순회하고 per-pane 완료 판정(`pane_reclaim`)으로 cross-run 안전을 보장하는 방식을 택했다 — session_id 매핑이 없으므로 이 리스크는 발생하지 않는다(§5 데이터 흐름의 session 매핑 서술은 미구현). 동시 병렬 run 도 완료 판정이 막아준다.
|
|
150
|
-
- **④ 내성은 코드 강제 불가** — prompt 계약이라 lead 가 따르지 않으면 무효(이번 원인과 동일 계열). **보강(2026-06-18, `b2278a6`):** phase-start cleanup / wrap-up disposition 의 lead-pane.id 해석 게이트를 제거해 lead 가 cleanup 스크립트를 *항상* 호출하도록 바꿨다(스크립트가 tmux 밖이면 자가 no-op). 이로써 "lead 가 lead-pane.id 를 오판해 정리를 통째로 skip" 하는 이번 원인 계열이 일차 방어선(①②)에서 제거된다. 내성(④)은 그래도 한도에 닿는 경우의 최후 안전망으로 남는다.
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
# 에이전트 작업 자세(Operating Standard) 주입 설계
|
|
2
|
-
|
|
3
|
-
- 날짜: 2026-06-19
|
|
4
|
-
- 상태: 설계 승인 대기
|
|
5
|
-
- 범위: okstra 전 에이전트(분석 워커 / executor·verifier / report-writer / 리드)에 공통 "작업 자세" 행동 규약을 주입하고, 코드 작성 워커에 완료 전 자기검증 게이트를 추가한다.
|
|
6
|
-
|
|
7
|
-
## 1. 배경과 목적
|
|
8
|
-
|
|
9
|
-
사용자가 모든 okstra 에이전트에 "노련하고 효율적이고 성실하고 전문가스러운" 태도를 주입하길 원했다. 출력에서 아쉬웠던 점은 깊이·정확도, 태도·성의, 일관성, 장황함, 그리고 특히 **코드 작성 품질**(함수 길이/복잡, 프로젝트 패턴 무시, 주석·네이밍 부실, 검증 없이 완료 선언) 전반이었다.
|
|
10
|
-
|
|
11
|
-
## 2. 핵심 통찰 — "규약 부재"가 아니라 "이행 부재"
|
|
12
|
-
|
|
13
|
-
사용자가 지목한 코드 품질 4개는 **이미 규약에 전부 존재**한다:
|
|
14
|
-
|
|
15
|
-
- 함수 50줄 상한 → 글로벌 `CLAUDE.md` 4.5, [_coding-conventions-preflight.md](../../../prompts/profiles/_coding-conventions-preflight.md) "single-purpose functions ≤50 effective lines"
|
|
16
|
-
- 프로젝트 패턴 따르기 → `CLAUDE.md` 3.1, preflight 의 routed pack + project review packs
|
|
17
|
-
- 이름=무엇 / 주석=왜 → `CLAUDE.md` 4.1, preflight 의 "truthful names"
|
|
18
|
-
- 증거 기반 완료 → `CLAUDE.md` 2.6·7장, preflight 의 "lint/test green 은 필요조건일 뿐"
|
|
19
|
-
|
|
20
|
-
따라서 규약 텍스트를 늘리는 것은 역효과다(안 읽히는 글만 길어진다). 설계는 **"얼마나 자주 마주치고, 출력 전에 스스로 검증하게 만드느냐"**(이행률)로 향한다. 막연한 정체성 페르소나("당신은 20년 경력 전문가다")는 현대 모델에서 추론 능력을 끌어올리지 못하고 장황함·과신·아첨을 유발하므로 채택하지 않는다 — 형용사를 **검증 가능한 동사**로 번역한다.
|
|
21
|
-
|
|
22
|
-
## 3. 범위
|
|
23
|
-
|
|
24
|
-
### 포함
|
|
25
|
-
- 전 에이전트 공통 "작업 자세" 헤더(형용사 → 행동 규약).
|
|
26
|
-
- 역할별 한 줄 분기(워커 독립성 / 리드 종합 / report-writer 제외).
|
|
27
|
-
- 코드 작성 워커(executor·verifier)의 **완료 전 자기검증 게이트** — 기존 시작 전 preflight 의 짝.
|
|
28
|
-
|
|
29
|
-
### 비포함 (NOT)
|
|
30
|
-
- 정체성/경력 서사형 페르소나 문구.
|
|
31
|
-
- validator 기반 기계 강제(C안) — 정적으로 잡히는 항목이 제한적이라 본 작업에서 제외. 자기보고(self-check) 방식으로 간다.
|
|
32
|
-
- 워커별로 서로 다른 페르소나(관점 다양성은 독립성 조항으로 보존하되, 자세 규약 자체는 통일).
|
|
33
|
-
|
|
34
|
-
## 4. 설계
|
|
35
|
-
|
|
36
|
-
### 4.1 공통 작업 자세 헤더 (SSOT, 영어)
|
|
37
|
-
|
|
38
|
-
기존 preamble·contract 가 영어이고 워커 출력 언어와 무관하므로 영어로 둔다. 톤은 기존 preamble 의 간결 명령형을 따른다.
|
|
39
|
-
|
|
40
|
-
```
|
|
41
|
-
## Operating standard
|
|
42
|
-
|
|
43
|
-
Work like a senior engineer who owns this result, not a commentator on it.
|
|
44
|
-
- Evidence over assertion — back every claim with a file:line, or mark it an
|
|
45
|
-
explicit assumption. Never state the unverified as fact.
|
|
46
|
-
- Read before you reason — read each required input end to end; when you lack
|
|
47
|
-
basis, write "insufficient evidence" instead of filling the gap plausibly.
|
|
48
|
-
- Shortest sound path — chase the most likely cause first; don't re-verify what
|
|
49
|
-
is settled or pad with restatement.
|
|
50
|
-
- Decide, don't survey — when options exist, give the trade-off and one
|
|
51
|
-
recommendation, not an exhaustive list.
|
|
52
|
-
- Fit what's here — match the surrounding code and prose; size the response to
|
|
53
|
-
the request.
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### 4.2 역할별 한 줄 분기 (동질화 방지)
|
|
57
|
-
|
|
58
|
-
cross-verification 은 세 워커의 관점이 **독립적**이어야 triangulation 이 성립한다. 자세 규약은 통일하되 관점은 보존한다.
|
|
59
|
-
|
|
60
|
-
- **분석/검증 워커 전용** 추가 한 줄:
|
|
61
|
-
`Hold your own line — reason from your independent angle; do not drift toward the other workers' likely answers or echo the user. Triangulation fails if your view isn't genuinely yours.`
|
|
62
|
-
- **리드 전용** 추가 한 줄:
|
|
63
|
-
`Own the synthesis — weigh worker outputs on evidence, not consensus; a better-grounded dissent outranks the majority.`
|
|
64
|
-
- **report-writer**: 독립성 조항 없음(독립 분석을 하지 않는 작성자). 공통 코어만 적용.
|
|
65
|
-
|
|
66
|
-
### 4.3 코드 워커 완료 전 자기검증 게이트
|
|
67
|
-
|
|
68
|
-
[_coding-conventions-preflight.md](../../../prompts/profiles/_coding-conventions-preflight.md)(시작 전 BLOCKING)에 대응하는 **완료 전 BLOCKING** 게이트. executor·verifier 가 "done" 을 선언하기 직전, audit 사이드카에 항목별 한 줄 확정을 쓴다. 항목은 사용자가 지목한 4개에 1:1 대응한다.
|
|
69
|
-
|
|
70
|
-
```
|
|
71
|
-
## Implementation self-check (BLOCKING — before you claim done)
|
|
72
|
-
|
|
73
|
-
Before declaring the change complete, write one confirming line per item to your
|
|
74
|
-
audit sidecar. If any fails, fix it or surface the violation — do not claim done.
|
|
75
|
-
- functions: every new/edited function ≤50 effective lines, single purpose
|
|
76
|
-
- conventions: applied the routed pack + project patterns (name them)
|
|
77
|
-
- names & comments: names say what, comments say why; no obvious-restatement
|
|
78
|
-
comments; no truthful-name violations
|
|
79
|
-
- verification: ran the actual build/test (paste command + result); no
|
|
80
|
-
dead/commented-out code left
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
이 게이트는 시작 전 preflight 와 **별개 관심사**(완료 전 검증)이므로 별도 sidecar `prompts/profiles/_implementation-self-check.md` 로 신설한다. 전달 경로는 preflight 와 동일하다: Claude executor 는 직접 read, codex/antigravity executor 는 sidecar 를 read 할 수 없으므로 lead 가 dispatch 시 프롬프트에 본문을 append 한다. [_implementation-executor.md](../../../prompts/profiles/_implementation-executor.md)·[_implementation-verifier.md](../../../prompts/profiles/_implementation-verifier.md) 가 이 sidecar 를 완료 전 단계에서 참조하도록 배선한다.
|
|
84
|
-
|
|
85
|
-
### 4.4 주입 지점과 단일 참조점
|
|
86
|
-
|
|
87
|
-
build.mjs 는 단순 복사이고(파일 include 합성 없음), 워커는 `**Worker Preamble Path:**` 앵커로 [worker-prompt-preamble.md](../../../templates/worker-prompt-preamble.md)를 통째로 read 한다. 리드는 [okstra-lead-contract.md](../../../prompts/lead/okstra-lead-contract.md)·[team-contract.md](../../../prompts/lead/team-contract.md)를 읽는다.
|
|
88
|
-
|
|
89
|
-
공통 코어(4.1)는 두 호출자(워커 preamble·리드 contract)를 가지므로 추출 대상이다. 실현 방식:
|
|
90
|
-
|
|
91
|
-
- **채택**: `templates/operating-standard.md` 를 SSOT 로 신설(4.1 코어 + 역할 분기 규칙 명시). 워커 preamble 과 리드 contract 는 코어 문장을 **인라인**한다(앵커 추가-read 없음 — okstra 는 audience-scoped enumeration 을 성능 최적화로 명시할 만큼 워커 토큰에 민감하므로, 5줄짜리 코어를 위해 매 워커 +1 파일 read 를 추가하지 않는다). 인라인 중복은 **단위 테스트로 drift 를 차단**한다(세 위치의 코어 문장이 SSOT 와 일치하는지 grep 검증).
|
|
92
|
-
- 코드 워커 게이트(4.3)는 별도 sidecar `prompts/profiles/_implementation-self-check.md` 로 신설한다(preflight 와 별개 관심사).
|
|
93
|
-
|
|
94
|
-
주입 대상 파일:
|
|
95
|
-
|
|
96
|
-
| 파일 | 추가 내용 |
|
|
97
|
-
|---|---|
|
|
98
|
-
| `templates/operating-standard.md` (신설) | 공통 코어 + 역할 분기 규칙 (SSOT) |
|
|
99
|
-
| [templates/worker-prompt-preamble.md](../../../templates/worker-prompt-preamble.md) | 공통 코어 인라인 + 워커 독립성 한 줄 |
|
|
100
|
-
| [prompts/lead/okstra-lead-contract.md](../../../prompts/lead/okstra-lead-contract.md) | 공통 코어 인라인 + 리드 종합 한 줄 |
|
|
101
|
-
| `prompts/profiles/_implementation-self-check.md` (신설) | 완료 전 자기검증 게이트 |
|
|
102
|
-
| [_implementation-executor.md](../../../prompts/profiles/_implementation-executor.md) · [_implementation-verifier.md](../../../prompts/profiles/_implementation-verifier.md) | 완료 전 self-check sidecar 참조 배선 |
|
|
103
|
-
|
|
104
|
-
## 5. 검증 / 테스트
|
|
105
|
-
|
|
106
|
-
- **단위 테스트(신규)**: `operating-standard.md` 의 코어 문장이 worker-prompt-preamble.md 와 okstra-lead-contract.md 에 모두 존재하는지(동기화), 워커 독립성 한 줄이 preamble 에만·리드 종합 한 줄이 contract 에만 있는지 검증.
|
|
107
|
-
- **단위 테스트(신규)**: 코드 워커 자기검증 게이트의 4개 항목 헤딩이 preflight 전달 경로에 포함되는지 검증.
|
|
108
|
-
- `npm run build` 후 `runtime/` 동기화 확인.
|
|
109
|
-
- `bash validators/validate-workflow.sh` 통과.
|
|
110
|
-
- `python3 -m pytest tests/` 전체 통과.
|
|
111
|
-
|
|
112
|
-
## 6. 사용자 영향 (CHANGES.md 예정)
|
|
113
|
-
|
|
114
|
-
okstra 의 모든 에이전트가 출력 전 공통 "작업 자세"(증거 우선·끝까지 읽기·최단 경로·결정 후 추천·주변에 맞추기)를 마주치고, 코드 작성 워커는 "done" 선언 전 함수 길이·패턴·네이밍·실제 검증을 audit 사이드카에 자기보고한다. 워커 독립성 조항으로 cross-verification 의 관점 다양성은 보존된다.
|
|
115
|
-
|
|
116
|
-
## 7. 리스크 / 미해결
|
|
117
|
-
|
|
118
|
-
- 자기검증은 self-check 이므로 100% 보장이 아니다(설계상 수용 — 기계 강제는 비포함). 다만 audit 사이드카 자기보고는 "조용히 건너뛰기"를 어렵게 만든다.
|
|
119
|
-
- 공통 코어 인라인 중복은 테스트로 drift 를 막지만, 테스트가 코어 문장을 문자열로 들고 있어야 한다(SSOT 변경 시 테스트도 갱신). 수용 가능한 트레이드오프.
|
|
120
|
-
- 헤더가 기존 preamble/contract 의 분량을 늘린다(코어 ~6줄 + 분기 1줄). 토큰 영향은 미미하나, 기존 "장황함 줄이기" 목표와 상충하지 않도록 코어를 6줄 이내로 유지한다.
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
# okstra-inspect `recap` facet 설계 — task-id 전/후 요약 + 자유 Q&A
|
|
2
|
-
|
|
3
|
-
> 작성: 2026-06-19 · 상태: 설계 승인 대기
|
|
4
|
-
|
|
5
|
-
## 1. 배경 / 문제
|
|
6
|
-
|
|
7
|
-
okstra 는 작업을 `task-id` 단위로 나누고, task-id 하나에 충분한 맥락이 이미 축적된다:
|
|
8
|
-
|
|
9
|
-
- `task-manifest.json` 의 `workflow.phaseStates` 등 현재 시점 스냅샷 ([scripts/okstra_ctl/render.py:1010](../../../scripts/okstra_ctl/render.py))
|
|
10
|
-
- `history/timeline.json` 의 `runs[]` — 각 run 기록 시점의 `workflowSnapshot`(`currentPhase / currentPhaseState / lastCompletedPhase / nextRecommendedPhase`)이 append-only 로 누적 ([render.py:1388](../../../scripts/okstra_ctl/render.py))
|
|
11
|
-
- 각 phase 의 `runs/<task-type>/reports/final-report-*.md` ([paths.py:180](../../../scripts/okstra_ctl/paths.py))
|
|
12
|
-
|
|
13
|
-
읽기 기능은 `okstra-inspect` 스킬에 7개 facet(status / history / report / time / logs / cost / errors)이 있으나 전부 **정형 출력**이다. `report` facet 은 final-report **원문을 그대로 보여줄 뿐** 내용 요약·질의는 하지 않는다 ([skills/okstra-inspect/SKILL.md:285](../../../skills/okstra-inspect/SKILL.md)).
|
|
14
|
-
|
|
15
|
-
빠진 것: **"이 task-id 에 쌓인 맥락 위에서 처리 전/후를 요약하고, 그 작업에 대해 자유롭게 묻고 답하는"** 읽기 기능. 현재 task-id 단위 자유 Q&A 는 존재하지 않는다 — `task-root/qa/` 는 이름과 달리 구현 검증 산출물 저장소이고([paths.py:127](../../../scripts/okstra_ctl/paths.py)), `clarification` 은 final-report 의 정해진 섹션을 다음 run 으로 carry-in 하는 구조화 플로우라 임의 질문과 다르다.
|
|
16
|
-
|
|
17
|
-
목표: task-id 단위 **전/후 요약 + 자유 Q&A** 를 담는 8번째 facet `recap` 추가.
|
|
18
|
-
|
|
19
|
-
## 2. 범위 / 결정 (brainstorming 합의)
|
|
20
|
-
|
|
21
|
-
| 항목 | 결정 |
|
|
22
|
-
|---|---|
|
|
23
|
-
| 전달 형태 | `okstra-inspect` 의 **8번째 facet `recap`** — 기존 7개와 동일한 dispatch·task-key 해소 경로 재사용 |
|
|
24
|
-
| 동작 | (a) 진입 시 **전/후 요약** 기본 출력 + (b) 이어지는 **자유 Q&A 루프** |
|
|
25
|
-
| 요약 깊이 | **run 단위 변화 추적** — `timeline.runs[].workflowSnapshot` 을 인접 run 끼리 비교 |
|
|
26
|
-
| 맥락 범위 | **2-모드**: 기본 = `.okstra/` 서브트리만 / 코드 모드 = 사용자가 명시 요청할 때만 해당 task worktree 의 `git diff`·`git log` 추가 |
|
|
27
|
-
| 결과 저장 | **`.okstra/` 안에 저장** — `<task-root>/recap/recap-log.jsonl` append-only |
|
|
28
|
-
| 저장 경유 | python 엔트리포인트 `okstra recap record`(skill 이 JSON 을 손으로 쓰지 않음) |
|
|
29
|
-
| CLI 노출 | `okstra recap <assemble\|record>` — Node 래퍼(`src/recap.mjs` + cli-registry) → python. 다른 read facet(`error-report`/`context-cost`)과 동일하게 skill 은 항상 `okstra <verb>` 를 호출하고 PYTHONPATH 를 직접 다루지 않음 |
|
|
30
|
-
|
|
31
|
-
**비목표**: `okstra.sh` 인터랙티브 wizard 에 `recap` 노출(읽기 facet 이라 불필요) · 기존 산출물 변형(recap 은 자기 로그만 append) · clarification carry-in 플로우 변경.
|
|
32
|
-
|
|
33
|
-
## 3. 설계
|
|
34
|
-
|
|
35
|
-
### 3.1 경로 SSOT 확장
|
|
36
|
-
|
|
37
|
-
`compute_run_paths` 가 레이아웃 단일 출처이므로 여기에 recap 경로를 추가한다 ([paths.py:87](../../../scripts/okstra_ctl/paths.py)).
|
|
38
|
-
|
|
39
|
-
```
|
|
40
|
-
<task-root>/recap/
|
|
41
|
-
recap-log.jsonl # append-only Q&A·요약 로그
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
- task-manifest 에 포인터가 필요하면 `recapLogPath` 를 `render_task_manifest` payload 에 추가 ([render.py:968](../../../scripts/okstra_ctl/render.py)). 1차 구현에서는 경로가 결정론적(task-root 상대)이므로 포인터는 선택.
|
|
45
|
-
|
|
46
|
-
### 3.2 전/후 요약 (run 단위 변화 추적)
|
|
47
|
-
|
|
48
|
-
facet 진입 시 기본 출력. 맥락 소스는 전부 기존 산출물이며 **신규 측정 없음**:
|
|
49
|
-
|
|
50
|
-
1. `history/timeline.json` 의 `runs[]` 를 시간순으로 읽어, **인접 두 run 의 `workflowSnapshot` 을 비교** → "이 run 전/후로 `currentPhase` / `lastCompletedPhase` / `nextRecommendedPhase` 가 어떻게 바뀌었나"를 run 단위로 재구성.
|
|
51
|
-
2. 각 run 의 `reportPath`(final-report) 핵심 섹션과 `task-manifest.workflow.phaseStates` 로 "무엇을 했나"를 보강.
|
|
52
|
-
3. 출력: run 별 전→후 phase 전이 + 한 줄 요약 타임라인.
|
|
53
|
-
|
|
54
|
-
별도의 "before/after" 전용 레코드는 없으므로 인접 snapshot 비교가 1차 소스다. `team-state.phaseTimeline`(lead operating-phase 타임스탬프)은 존재하면 보조로만 쓰고 의존하지 않는다(collector 버전·Phase 7 도달 여부에 따라 부재 가능).
|
|
55
|
-
|
|
56
|
-
### 3.3 자유 Q&A 루프
|
|
57
|
-
|
|
58
|
-
요약 출력 뒤 사용자의 임의 질문을 받아, §3.2 의 산출물 위에서 답한다.
|
|
59
|
-
|
|
60
|
-
- 모든 사실 주장은 `.okstra` 파일 `path:line` 인용을 동반(검증 가능).
|
|
61
|
-
- 후속 질문 반복. 각 질문·답변은 §3.5 로 기록.
|
|
62
|
-
|
|
63
|
-
### 3.4 2-모드 (맥락 범위)
|
|
64
|
-
|
|
65
|
-
- **기본 모드** — `.okstra/` 서브트리만 읽음. artifact-home 규칙 준수, 모든 인용이 `.okstra` 파일로 귀결.
|
|
66
|
-
- **코드 모드** — 사용자가 명시적으로 "코드 변경까지 봐줘" 류로 요청할 때만, 해당 task 의 worktree/브랜치 `git diff`·`git log` 를 추가로 읽어 코드 레벨로 답. **진입 시 자동 확장 금지** — 사용자의 verbatim 요청이 있을 때만.
|
|
67
|
-
|
|
68
|
-
### 3.5 결과 저장 (`recap-log.jsonl` append-only)
|
|
69
|
-
|
|
70
|
-
- 형식: 줄당 한 엔트리
|
|
71
|
-
```json
|
|
72
|
-
{"ts": "<ISO8601>", "kind": "summary|qa", "mode": "artifact|code",
|
|
73
|
-
"question": "<질문 또는 빈 문자열>", "answerSummary": "<요약>", "citations": ["path:line", ...]}
|
|
74
|
-
```
|
|
75
|
-
summary 엔트리처럼 질문이 없으면 `question` 은 `null` 이 아니라 빈 문자열 `""` 로 저장한다(타입 일관성).
|
|
76
|
-
- **append-only** 이므로 중복 제거 로직 불필요.
|
|
77
|
-
- 쓰기는 **python 엔트리포인트 `okstra recap record` 서브커맨드** 경유 — skill 이 JSON 을 직접 작성하지 않음(단일 참조점 규칙; errors facet 이 .md 리포트를 산출하는 선례와 동일 결).
|
|
78
|
-
- recap 은 `recap-log.jsonl` 만 append 하고 **다른 산출물은 불변**. status facet 외 "read-only" 철학을 깨는 유일한 지점이므로 facet 문서에 이 경계를 명시.
|
|
79
|
-
|
|
80
|
-
## 4. 영향 범위 (수정 파일)
|
|
81
|
-
|
|
82
|
-
| 파일 | 변경 |
|
|
83
|
-
|---|---|
|
|
84
|
-
| [scripts/okstra_ctl/paths.py](../../../scripts/okstra_ctl/paths.py) | `compute_run_paths` 에 `recap/` + `recap-log.jsonl` 경로 추가 |
|
|
85
|
-
| `scripts/okstra_ctl/recap.py` (신규) | `assemble`(run 간 전이 조립) + `record`(append 1줄) 서브커맨드 |
|
|
86
|
-
| `src/recap.mjs` (신규) + [src/cli-registry.mjs](../../../src/cli-registry.mjs) | `okstra recap` Node 래퍼 + introspection 카테고리 등록 |
|
|
87
|
-
| [skills/okstra-inspect/SKILL.md](../../../skills/okstra-inspect/SKILL.md) | facet 테이블에 `recap` 등록 + recap 섹션(요약/Q&A/2-모드/저장 경계) |
|
|
88
|
-
| [docs/kr/architecture.md](../../../docs/kr/architecture.md) | task-root 트리에 `recap/` 추가 |
|
|
89
|
-
| 빌드 | `npm run build` 로 runtime 동기화 |
|
|
90
|
-
|
|
91
|
-
## 5. 검증
|
|
92
|
-
|
|
93
|
-
- `paths.py` recap 경로: 기존 `compute_task_paths` 테스트 패턴에 recap 경로 assert 추가(`tests/`).
|
|
94
|
-
- `recap record` append: 빈 로그 → 1줄 → 2줄 append 단위 테스트.
|
|
95
|
-
- facet 동작(요약·Q&A·2-모드)은 skill-markdown 주도라 자동 단위 테스트 대상이 아님 → e2e 또는 수동 스모크(`okstra recap <task-id>`)로 확인.
|
|
96
|
-
- 정형 검증 불가한 "요약 품질"은 spec 의 범위 밖(휴리스틱).
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
# 에러 환류 루프 (cross-project → okstra 자가수정) — 설계 spec
|
|
2
|
-
|
|
3
|
-
- Date: 2026-06-20
|
|
4
|
-
- Status: Draft (사용자 검토 대기)
|
|
5
|
-
- Owner: Claude lead (현재 세션)
|
|
6
|
-
- Related: `scripts/okstra_ctl/index.py`, `scripts/okstra_ctl/error_report.py`, `scripts/okstra_ctl/paths.py`, `scripts/okstra-error-log.py`, `skills/okstra-inspect/SKILL.md`, `src/commands/inspect/`, `skills/okstra-brief/SKILL.md`, `prompts/profiles/error-analysis.md`
|
|
7
|
-
|
|
8
|
-
## 1. 문제
|
|
9
|
-
|
|
10
|
-
okstra 가 타겟 프로젝트에서 구동될 때, 에이전트 실행 중 발생하는 에러는 errorType 3종(`tool-failure`, `cli-failure`, `contract-violation`)으로 각 타겟의 `<target>/.okstra/tasks/<group>/<id>/runs/<task-type>/logs/errors-<task-type>-<seq>.jsonl` 에 적재된다 (정본 writer: `scripts/okstra-error-log.py`).
|
|
11
|
-
|
|
12
|
-
이 3종 에러는 대부분 **타겟 코드의 결함이 아니라 okstra 자체의 결함 신호**다:
|
|
13
|
-
|
|
14
|
-
- `cli-failure` — codex/antigravity 래퍼의 비정상 종료·타임아웃·결과파일 누락. 래퍼 로직/폴링 cap/프롬프트 계약 문제.
|
|
15
|
-
- `contract-violation` — 워커 출력이 phase contract 를 위반. 프로파일 계약 모호성·validator 와 프로파일의 불일치.
|
|
16
|
-
- `tool-failure` — 워커 도구 호출 실패. 권한 seed 누락(`templates/reports/settings.template.json`)·도구 사용 패턴 결함 등 okstra 인프라 문제인 경우가 다수.
|
|
17
|
-
|
|
18
|
-
그러나 현재 이 에러를 **okstra 자신의 수정으로 환류시키는 경로가 없다**:
|
|
19
|
-
|
|
20
|
-
- `skills/okstra-inspect` 의 errors facet(`scripts/okstra_ctl/error_report.py`)은 **단일 task_root 안**의 JSONL 만 글롭해 markdown 으로 집계한다. 읽기 전용·단일 task·진단까지만.
|
|
21
|
-
- `improvement-discovery` sidetrack 은 코드 스캔 기반이며 **에러 로그를 입력으로 전혀 쓰지 않는다**.
|
|
22
|
-
|
|
23
|
-
결과적으로 여러 타겟에 흩어진 okstra 결함 신호는 수집·분석되지 못한 채 각 타겟의 `.okstra/` 안에 고립된다.
|
|
24
|
-
|
|
25
|
-
## 2. 목표와 비목표
|
|
26
|
-
|
|
27
|
-
### 목표
|
|
28
|
-
|
|
29
|
-
- 머신 내 **모든 타겟 프로젝트**에 흩어진 errors-*.jsonl 을 글로벌 run-index(`~/.okstra/recent.jsonl`, `active.jsonl`)로 발견·수집하는 cross-project 수집기 `okstra-error-zip` 도입.
|
|
30
|
-
- 수집 결과를 errorType·source·phase·agent·메시지패턴별로 집계하고, 익명화한 뒤 **`.zip` 아카이브**(집계 리포트 `.md` + 원본 JSONL)로 묶어 **사용자 지정 경로**에 저장.
|
|
31
|
-
- 저장 경로는 이전 입력값을 글로벌 config 에 기억하고, 재실행 시 **재사용/직접입력 3-옵션 picker** 로 제시 (마지막 옵션은 항상 직접입력).
|
|
32
|
-
- zip 을 입력으로 받아 빈발 클러스터 1개를 `error-analysis` brief 로 변환하는 `okstra-brief` 의 `error-feedback` variant 도입.
|
|
33
|
-
- 그 brief 를 **okstra 레포 자신을 타겟으로** 한 기존 `error-analysis → implementation-planning → implementation` lifecycle 에 태워 okstra 소스(`prompts/`·`agents/`·`scripts/`·`templates/`)를 실제 수정.
|
|
34
|
-
- **errorType 비결합 원칙**: 집계·클러스터링·익명화 로직은 특정 errorType 값(`tool-failure`·`cli-failure`·`contract-violation`)에 하드코딩 분기하지 않는다. errorType 은 JSONL 레코드에서 읽은 값을 그대로 그룹 키로 쓰는 **data-driven 방식**으로 다뤄, 새 errorType 이 추가돼도 error-zip 코드를 수정하지 않고 자동 집계된다. errorType 정본 목록이 필요한 지점(예: 미지 타입 경고)은 `scripts/okstra-error-log.py` 의 `ALLOWED_ERROR_TYPES`(`okstra-error-log.py:18`) 를 **단일 참조**한다 — error-zip 코드에 errorType 목록을 재정의하지 않는다.
|
|
35
|
-
|
|
36
|
-
### 비목표
|
|
37
|
-
|
|
38
|
-
- **새 task-type / phase 신설하지 않음.** 수집은 결정적 파일시스템 작업이므로 LLM phase 가 아니라 Python 코드가 맡고, 수정은 기존 error-analysis lifecycle 을 재사용한다. (검토했던 접근 B 기각 — §7)
|
|
39
|
-
- **자동 실행하지 않음.** run 종료 시 자동 적치·정기 스캔은 도입하지 않는다. 전 과정은 사용자 온디맨드 트리거.
|
|
40
|
-
- **수집기가 소스를 수정하지 않음.** `okstra-error-zip` 은 읽기·집계·저장만. 실제 수정은 별도 lifecycle run 의 책임.
|
|
41
|
-
- **타겟 프로젝트 코드를 수정하지 않음.** 환류의 수정 대상은 오직 okstra 레포 소스.
|
|
42
|
-
- **errors JSONL 정본을 삭제·이동하지 않음.** 각 타겟의 정본은 그대로 두고 읽기만 한다 (artifact-home 규칙: 타겟의 `.okstra/` 는 타겟 메모리).
|
|
43
|
-
|
|
44
|
-
## 3. 전체 데이터 흐름
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
[1 수집·집계·저장] okstra-error-zip (신규, 결정적 Python)
|
|
48
|
-
~/.okstra/{recent,active}.jsonl 순회
|
|
49
|
-
→ 각 row 의 projectRoot + runDirRel 로 run 디렉터리 복원
|
|
50
|
-
→ 그 밑 logs/errors-*.jsonl (+ stage-*/logs/errors-*.jsonl) 글롭
|
|
51
|
-
→ errorType·source·phase·agent·메시지패턴별 집계 + 빈발 클러스터
|
|
52
|
-
→ 익명화 (타겟 고유 경로/코드 excerpt 상대화·축약)
|
|
53
|
-
→ .zip 아카이브 생성 (집계 report.md + 익명화 JSONL)
|
|
54
|
-
→ 사용자 지정 경로에 저장 (이전 경로 재사용/직접입력 picker)
|
|
55
|
-
│
|
|
56
|
-
▼
|
|
57
|
-
[2 brief화] okstra-brief error-feedback variant (신규)
|
|
58
|
-
zip 입력 → 빈발 클러스터 1개(= 단일 근본원인 후보) 선택
|
|
59
|
-
→ error-analysis brief 생성 (Source Material 에 원본 JSONL 레코드 인용)
|
|
60
|
-
│
|
|
61
|
-
▼
|
|
62
|
-
[3 수정] 기존 lifecycle 재사용 (신규 0)
|
|
63
|
-
okstra 레포 대상 okstra-run --task-type error-analysis
|
|
64
|
-
→ 원인분석(소스 자유 추적, scan-scope 제약 없음)
|
|
65
|
-
→ implementation-planning → implementation (실제 소스 수정)
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
## 4. okstra-error-zip (신규)
|
|
69
|
-
|
|
70
|
-
### 4.1 진입 표면
|
|
71
|
-
|
|
72
|
-
`skills/okstra-inspect` 의 **9번째 facet `error-zip`** 으로 둔다. 근거:
|
|
73
|
-
|
|
74
|
-
- read-side okstra inspection 의 SSOT 는 `okstra-inspect` 단일 디스패처다. cross-project 에러 집계도 읽기 작업이므로 같은 디스패처에 흡수하는 것이 단일참조원칙에 맞다.
|
|
75
|
-
- 사용자가 부른 트리거 "okstra error-zip" 은 이 facet 으로 라우팅한다.
|
|
76
|
-
|
|
77
|
-
핵심 로직은 신규 `scripts/okstra_ctl/error_zip.py`. 진입 래퍼는 `src/commands/inspect/` 에 facet 핸들러로 추가.
|
|
78
|
-
|
|
79
|
-
기존 errors facet(단일 task 진단)과 error-zip facet(cross-project 환류)은 **성격이 다른 별개 facet**으로 공존한다. 단, 글롭·tally 코어는 §4.5 대로 공유한다.
|
|
80
|
-
|
|
81
|
-
### 4.2 수집 알고리즘
|
|
82
|
-
|
|
83
|
-
1. 글로벌 홈(`OKSTRA_HOME`, 기본 `~/.okstra`; `paths.py:40-42`)의 `recent.jsonl` + `active.jsonl` 의 모든 row 를 읽는다.
|
|
84
|
-
2. 각 row 에서 run 디렉터리 절대경로를 복원한다: `Path(projectRoot) / runDirRel` (`index.py:76`, `index.py:95`). `runDirRel` 은 이미 정규화된 상대경로라 가장 안전한 앵커다.
|
|
85
|
-
3. 각 run 디렉터리 밑에서 `logs/errors-*.jsonl` 과 `stage-*/logs/errors-*.jsonl` 을 글롭한다 (기존 `error_report.py:18-23` `_glob_error_logs` 의 패턴과 동일).
|
|
86
|
-
4. 각 JSONL 줄을 파싱해 레코드를 모은다. 파싱 실패 줄은 건너뛰되 카운트한다 (`error_report.py:27-45` 패턴 재사용).
|
|
87
|
-
|
|
88
|
-
> 누락 처리: row 의 `projectRoot` 경로가 더 이상 존재하지 않으면(프로젝트 삭제·이동) skip 하고 집계 리포트에 "도달 불가 run" 수를 명시한다. 침묵 누락 금지.
|
|
89
|
-
|
|
90
|
-
### 4.3 집계
|
|
91
|
-
|
|
92
|
-
errorType·source·phase·agent·메시지패턴별 tally 와 빈도순 정렬, 그리고 **빈발 클러스터**(같은 errorType + 유사 메시지패턴 + 동일 phase/agent 의 묶음)를 도출한다. 클러스터는 §6 brief 분할의 단위가 된다.
|
|
93
|
-
|
|
94
|
-
집계 결과에는 각 클러스터의 출처 프로젝트 수·발생 횟수·대표 레코드 인용이 포함된다.
|
|
95
|
-
|
|
96
|
-
**data-driven 키 수집** (§2 errorType 비결합 원칙 적용): tally 의 그룹 키(errorType 을 포함한 모든 차원)는 레코드에서 발견된 값을 그대로 동적으로 수집한다. 알려진 errorType 목록을 코드에 나열해 분기하지 않으며, 미지의 새 errorType 도 자동으로 자기 그룹으로 잡힌다. 클러스터링은 "errorType 값이 같은가"라는 **동등성 비교**만 쓰고 특정 errorType 이름을 case 분기하지 않는다. 선택적으로, 발견된 errorType 이 `ALLOWED_ERROR_TYPES` SSOT 에 없으면 집계 리포트에 "미등록 errorType" 으로 표시할 수 있으나(이때만 SSOT 참조), 집계 자체는 막지 않는다.
|
|
97
|
-
|
|
98
|
-
### 4.4 익명화 정책 (열린 디테일 — §8.1 에서 확정)
|
|
99
|
-
|
|
100
|
-
cross-project 수집이므로 타겟 코드 경로·excerpt 가 섞인다. okstra 결함 진단에 필요한 메타(`errorType`/`command`/`exitCode`/`phase`/`agent`/stderr 패턴)는 보존하되, 타겟 고유 식별 정보는 축약한다:
|
|
101
|
-
|
|
102
|
-
- 타겟 절대경로 → projectRoot 기준 상대경로로 치환.
|
|
103
|
-
- projectId / projectRoot 자체 → 안정적 짧은 토큰(예: `proj-<n>`)으로 치환하고, 매핑 표는 zip 에 포함하지 않는다(또는 별도 분리).
|
|
104
|
-
- stderr/메시지의 코드 excerpt → okstra 진단에 무관한 부분은 길이 제한·축약.
|
|
105
|
-
|
|
106
|
-
okstra 자신의 결함은 errorType·command·exit-code·phase·agent·okstra 소스 경로 패턴에서 드러나므로, 타겟 고유 정보를 축약해도 진단력은 유지된다.
|
|
107
|
-
|
|
108
|
-
### 4.5 코드 공유 (단일참조)
|
|
109
|
-
|
|
110
|
-
`error_report.py` 의 글롭(`_glob_error_logs`)과 tally 로직을 공용 모듈로 추출해 errors facet 과 error-zip facet 이 함께 쓴다. 중복 구현 금지. errors facet 은 "단일 task_root 글롭", error-zip 은 "index 순회 후 다수 run-dir 글롭"으로 **입력 경로 집합만 다르고 집계는 동일**하다.
|
|
111
|
-
|
|
112
|
-
### 4.6 출력 / 저장 UX
|
|
113
|
-
|
|
114
|
-
- 출력물: 단일 `.zip` 아카이브. 내부 구성:
|
|
115
|
-
- `report.md` — §4.3 집계 리포트 (사람이 읽는 면).
|
|
116
|
-
- `errors/` — 익명화된 원본 JSONL (lifecycle 이 근거로 인용하는 면).
|
|
117
|
-
- 저장 경로: 사용자 입력. 이전 입력 경로를 글로벌 config(`~/.okstra/` 하위, 정확한 파일명은 §8.2)에 기억.
|
|
118
|
-
- picker (메모리 규칙 "추천 1~2개 + 직접 입력 = 3-옵션" 준수):
|
|
119
|
-
1. (이전 경로가 있으면) 이전 경로 재사용 — 추천, 첫 옵션.
|
|
120
|
-
2. (없으면) 합리적 기본 경로 제안 — 추천.
|
|
121
|
-
3. 직접 입력 — 항상 마지막 옵션.
|
|
122
|
-
- artifact-home 충돌 회피: cross-project 집계물은 특정 프로젝트 소유가 아니다. 따라서 okstra 의 어느 프로젝트 `.okstra/` 에도 강제 적치하지 않고 **사용자가 지정한 경로**(예: okstra 레포 작업공간, 또는 임의 위치)에 저장한다.
|
|
123
|
-
|
|
124
|
-
## 5. okstra-brief error-feedback variant (신규)
|
|
125
|
-
|
|
126
|
-
`skills/okstra-brief/SKILL.md` 에 새 variant 를 추가한다. 입력은 §4 의 `.zip`.
|
|
127
|
-
|
|
128
|
-
- zip 을 풀어 `report.md` 의 빈발 클러스터 목록을 제시하고, 사용자가 **클러스터 1개**를 고른다.
|
|
129
|
-
- 그 클러스터를 단일 `error-analysis` brief 로 변환한다. brief 의 `Source Material` 에 해당 클러스터의 원본 JSONL 레코드(errorType·command·exitCode·phase·agent·메시지)를 인용한다.
|
|
130
|
-
- 한 brief = 한 클러스터 = 한 근본원인 후보. 이질적 에러를 한 brief 에 섞지 않는다 (§6).
|
|
131
|
-
|
|
132
|
-
## 6. 수정 lifecycle 연결 (기존 재사용)
|
|
133
|
-
|
|
134
|
-
`error-analysis` 는 brief 입력 entry phase 이며 scan-scope 제약이 없어, 워커가 okstra 레포 소스 전체를 `Read`/`Grep` 으로 자유 추적할 수 있다 (`prompts/profiles/error-analysis.md`). errorType 3종이 정확히 일치하므로 brief 의 symptom 으로 그대로 받는다.
|
|
135
|
-
|
|
136
|
-
**구조적 제약 — symptom-lock 단일성**: error-analysis 의 진단 루프는 "하나의 관측 가능한 실패조건"을 요구한다 (`error-analysis.md` Symptom lock). 따라서 cross-project 로 수집한 이질적 에러를 한 brief 에 섞으면 첫 blocker 로 "단일 실패조건 도출 불가"가 뜬다. 이 때문에 §4.3 의 **클러스터가 brief 분할의 단위**가 되어야 한다.
|
|
137
|
-
|
|
138
|
-
흐름: 원인이 evidence 로 확정되면 error-analysis 가 `implementation-planning` 으로 라우팅(`workflow.py` `DEFAULT_NEXT_PHASE["error-analysis"] = "implementation-planning"`)하고, 그 다음 `implementation` run 이 okstra 소스를 실제 수정한다. error-analysis run 자체는 소스를 고치지 않는다(프로파일 비목표).
|
|
139
|
-
|
|
140
|
-
## 7. 검토한 대안
|
|
141
|
-
|
|
142
|
-
| 접근 | 내용 | 기각/채택 사유 |
|
|
143
|
-
|---|---|---|
|
|
144
|
-
| **A (채택)** | 수집기(결정적 Python) + brief variant + 기존 lifecycle 재사용 | 신규 표면 최소. 수집=결정적/수정=LLM 책임 분리. validator·lifecycle 100% 재사용 |
|
|
145
|
-
| B (기각) | improvement-discovery 대칭으로 전용 task-type `error-feedback-discovery` 신설 | 프로파일+validator+wizard+상수+테스트 한 벌 복제(YAGNI). **파일시스템 순회를 LLM phase 에 넣으면 비결정적** — 수집의 본질과 불일치 |
|
|
146
|
-
| C (기각) | 수집기 CLI 만, brief화·수정은 사람 | "실질적으로 수정하는 프로세스"가 끊김 — 요구 미충족 |
|
|
147
|
-
|
|
148
|
-
## 8. 열린 디테일 (구현 계획에서 확정)
|
|
149
|
-
|
|
150
|
-
### 8.1 익명화 정책의 정확한 경계
|
|
151
|
-
보존 필드 화이트리스트와 축약 규칙을 확정한다. allowlist 기반(보존할 필드를 명시, 그 외는 축약)으로 설계한다.
|
|
152
|
-
|
|
153
|
-
### 8.2 저장 경로 기억 위치
|
|
154
|
-
이전 출력 경로를 기억할 글로벌 config 파일을 확정한다. 기존 `~/.okstra/` 하위 config 가 있으면 거기에 키를 추가하고, 없으면 전용 파일을 둔다. env var 대신 명시적 파일로 (메모리 규칙: env var 지양).
|
|
155
|
-
|
|
156
|
-
### 8.3 클러스터 분할 기준
|
|
157
|
-
빈발 클러스터를 묶는 정확한 기준(errorType 일치 + 메시지패턴 유사도 + phase/agent 동일)의 임계값을 확정한다.
|
|
158
|
-
|
|
159
|
-
## 9. 신규/수정 표면 요약
|
|
160
|
-
|
|
161
|
-
| 파일 | 작업 |
|
|
162
|
-
|---|---|
|
|
163
|
-
| `scripts/okstra_ctl/error_zip.py` | 신규 — index 순회·집계·익명화·zip 생성. errorType 은 data-driven(§2 비결합 원칙), 목록 필요 시 `ALLOWED_ERROR_TYPES` SSOT 참조 |
|
|
164
|
-
| `scripts/okstra_ctl/error_report.py` | 글롭/tally 코어를 공용 모듈로 추출(리팩터) |
|
|
165
|
-
| `skills/okstra-inspect/SKILL.md` | `error-zip` facet 추가 + 저장경로 picker 문구 |
|
|
166
|
-
| `src/commands/inspect/` | error-zip facet 진입 래퍼 |
|
|
167
|
-
| `skills/okstra-brief/SKILL.md` | `error-feedback` variant 추가 |
|
|
168
|
-
| `~/.okstra/` config | 이전 출력 경로 기억 키 (§8.2) |
|
|
169
|
-
| `tests/inspect/`, `tests/report/` | 수집·집계·익명화·picker 단위 테스트 |
|
|
170
|
-
|
|
171
|
-
> `runtime/` 은 빌드 산출물이므로 직접 수정하지 않는다. 소스 수정 후 `npm run build` 로 동기화한다.
|