okstra 0.2.0 → 0.4.0
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.md +1451 -17
- package/bin/okstra +7 -5
- package/package.json +5 -7
- package/runtime/BUILD.json +2 -2
- package/runtime/skills/okstra-context-loader/SKILL.md +140 -0
- package/runtime/skills/okstra-convergence/SKILL.md +289 -0
- package/runtime/skills/okstra-history/SKILL.md +137 -0
- package/runtime/skills/okstra-report-finder/SKILL.md +87 -0
- package/runtime/skills/okstra-report-writer/SKILL.md +256 -0
- package/runtime/skills/okstra-run/SKILL.md +231 -0
- package/runtime/skills/okstra-schedule/SKILL.md +627 -0
- package/runtime/skills/okstra-setup/SKILL.md +138 -0
- package/runtime/skills/okstra-status/SKILL.md +230 -0
- package/runtime/skills/okstra-team-contract/SKILL.md +402 -0
- package/runtime/skills/okstra-time-summary/SKILL.md +138 -0
- package/src/check-project.mjs +188 -0
- package/src/doctor.mjs +15 -0
- package/src/install.mjs +91 -2
- package/src/paths.mjs +2 -2
- package/src/uninstall.mjs +59 -6
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: okstra-report-finder
|
|
3
|
+
description: Use when the user provides a task key and needs to find the final report path, or wants to read a previous okstra report to continue work based on its findings. Trigger words include "find report", "show report for", "read the okstra report", "continue from report".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# OKSTRA Report Finder
|
|
7
|
+
|
|
8
|
+
## When to Use
|
|
9
|
+
|
|
10
|
+
- 사용자가 task-key를 주고 해당 최종 보고서를 찾을 때
|
|
11
|
+
- 이전 okstra 보고서를 읽고 후속 작업을 진행할 때
|
|
12
|
+
- 보고서 내용을 기반으로 구현, 수정, 추가 검증을 시작할 때
|
|
13
|
+
|
|
14
|
+
## Step 0: Verify okstra runtime + project setup
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npx -y okstra@latest ensure-installed >/dev/null 2>&1 || {
|
|
18
|
+
echo "FAIL: okstra not installed; tell the user to run: npx okstra@latest install" >&2
|
|
19
|
+
exit 1
|
|
20
|
+
}
|
|
21
|
+
eval "$(npx -y okstra@latest paths --shell)"
|
|
22
|
+
export PYTHONPATH="$OKSTRA_PYTHONPATH"
|
|
23
|
+
OKSTRA_PROJECT_INFO="$(npx -y okstra@latest check-project --json)" || {
|
|
24
|
+
echo "FAIL: this project has no okstra setup. Tell the user to run /okstra-setup first." >&2
|
|
25
|
+
echo "$OKSTRA_PROJECT_INFO" >&2
|
|
26
|
+
exit 1
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`$OKSTRA_PROJECT_INFO` (JSON `{ok, projectRoot, projectJsonPath, projectId}`) —
|
|
31
|
+
`projectRoot` 로 catalog/manifest 위치를 잡는다.
|
|
32
|
+
|
|
33
|
+
## Step 1: Task Key로 Report 경로 찾기
|
|
34
|
+
|
|
35
|
+
task-key 형식: `<project-id>:<task-group>:<task-id>`
|
|
36
|
+
|
|
37
|
+
### 방법 A: task-catalog.json (빠름)
|
|
38
|
+
|
|
39
|
+
1. `.project-docs/okstra/discovery/task-catalog.json`을 읽는다.
|
|
40
|
+
2. `tasks` 배열에서 `taskKey`가 일치하는 항목을 찾는다.
|
|
41
|
+
3. `latestReportPath` 필드가 최신 보고서 경로이다.
|
|
42
|
+
|
|
43
|
+
### 방법 B: task-manifest.json (직접)
|
|
44
|
+
|
|
45
|
+
task-catalog가 없거나 최신이 아닌 경우:
|
|
46
|
+
|
|
47
|
+
1. task-key에서 task-group과 task-id를 추출한다.
|
|
48
|
+
2. `.project-docs/okstra/tasks/<task-group>/<task-id>/task-manifest.json`을 읽는다.
|
|
49
|
+
3. `latestReportPath` 필드가 최신 보고서 경로이다.
|
|
50
|
+
|
|
51
|
+
### 방법 C: timeline.json (특정 run의 보고서)
|
|
52
|
+
|
|
53
|
+
특정 날짜나 run의 보고서가 필요한 경우:
|
|
54
|
+
|
|
55
|
+
1. `.project-docs/okstra/tasks/<task-group>/<task-id>/history/timeline.json`을 읽는다.
|
|
56
|
+
2. `runs` 배열에서 원하는 run을 찾는다 (날짜, 상태 등으로 필터).
|
|
57
|
+
3. `reportPath` 필드가 해당 run의 보고서 경로이다.
|
|
58
|
+
|
|
59
|
+
## Step 2: Report 존재 확인
|
|
60
|
+
|
|
61
|
+
1. 찾은 경로에 파일이 실제로 존재하는지 확인한다.
|
|
62
|
+
2. 존재하면 경로를 표시하고 읽을지 사용자에게 확인한다.
|
|
63
|
+
3. 존재하지 않으면:
|
|
64
|
+
- `task-manifest.json`의 `currentStatus`를 확인한다.
|
|
65
|
+
- status가 `completed`가 아니면: "이 task는 아직 완료되지 않았습니다 (status: `<status>`)."
|
|
66
|
+
- 파일만 없으면: "보고서 파일이 존재하지 않습니다: `<path>`"
|
|
67
|
+
|
|
68
|
+
## Step 3: Report 읽기 및 후속 작업 안내
|
|
69
|
+
|
|
70
|
+
보고서를 읽은 후 사용자에게 가능한 후속 작업을 안내한다:
|
|
71
|
+
|
|
72
|
+
1. **구현 진행**: 보고서의 "권장 다음 단계" 섹션 기반으로 코드 수정
|
|
73
|
+
2. **추가 검증**: 같은 task-key로 새 okstra run 실행 (`okstra-history` 스킬로 재실행 커맨드 생성)
|
|
74
|
+
3. **관련 task 확인**: 보고서의 관련 task 참조가 있으면 해당 task의 보고서도 조회
|
|
75
|
+
|
|
76
|
+
## Output
|
|
77
|
+
|
|
78
|
+
```markdown
|
|
79
|
+
## Report for <task-key>
|
|
80
|
+
|
|
81
|
+
- Status: `<status>`
|
|
82
|
+
- Report path: `<relative-path>`
|
|
83
|
+
- Run date: `<YYYY-MM-DD HH:MM>`
|
|
84
|
+
- Task type: `<task-type>`
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
이후 사용자 요청에 따라 보고서를 읽고 후속 작업을 진행한다.
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: okstra-report-writer
|
|
3
|
+
description: Use when okstra is in Phase 6 or Phase 7 — writing the final synthesis report, persisting artifacts, or updating manifests.
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# OKSTRA Report Writer
|
|
8
|
+
|
|
9
|
+
## File-author ownership (BLOCKING)
|
|
10
|
+
|
|
11
|
+
The final-report file at `runs/<task-type>/reports/final-report-<task-type>-<seq>.md` is authored by the `Report writer worker` subagent when that worker is in the run's roster. Claude lead reviews the file but does NOT write it itself in that case. Lead-authored fallback is permitted only after a real Report writer worker dispatch attempt with a recorded non-`completed` terminal status (`error` / `timeout` / `not-run`) and a logged reason (`okstra-error-log.py`).
|
|
12
|
+
|
|
13
|
+
If you are reading this skill **as the report-writer-worker subagent**, YOU are the one calling the `Write` tool against the result path. Do not return the report inline — the file on disk is the canonical artifact.
|
|
14
|
+
|
|
15
|
+
If you are reading this skill **as Claude lead**, your job in Phase 6 is to (a) prepare the report-writer prompt, (b) dispatch the Report writer worker per the Phase 6 dispatch template in SKILL.md, (c) review the produced file in Phase 7. Do not call `Write` against the final-report path yourself when Report writer worker is in the roster.
|
|
16
|
+
|
|
17
|
+
## When to Use
|
|
18
|
+
|
|
19
|
+
- During Phase 6 of the OKSTRA skill (final report assembly)
|
|
20
|
+
- During Phase 7 of the OKSTRA skill (artifact persistence — verification only when Report writer worker is in roster)
|
|
21
|
+
- When verifying the structure of the final report
|
|
22
|
+
|
|
23
|
+
## Phase 6 dispatch template (Report writer worker)
|
|
24
|
+
|
|
25
|
+
Lead dispatches the report-writer worker via the Agent tool. Lead does NOT write the final-report file when this worker is in the roster.
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
Agent(
|
|
29
|
+
description: "Author final report for <task-key>",
|
|
30
|
+
prompt: "<report-writer prompt: see this skill + Required reading clause + Available MCP Servers section>",
|
|
31
|
+
name: "report-writer",
|
|
32
|
+
subagent_type: "report-writer-worker",
|
|
33
|
+
team_name: "okstra-<task-key>", # omit if team is not alive — see Resume-safe dispatch
|
|
34
|
+
model: "opus",
|
|
35
|
+
mode: "auto"
|
|
36
|
+
)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The prompt MUST include, in this order at the top:
|
|
40
|
+
|
|
41
|
+
1. `**Project Root:** <absolute-path>`
|
|
42
|
+
2. `**Prompt History Path:** <project-relative-path>` (under current run `prompts/`)
|
|
43
|
+
3. `**Result Path:** runs/<task-type>/reports/final-report-<task-type>-<seq>.md` — canonical final-report file (user-facing)
|
|
44
|
+
4. `**Worker Result Path:** runs/<task-type>/worker-results/report-writer-worker-<task-type>-<seq>.md` — mandatory validator-checked worker-results audit file
|
|
45
|
+
5. `Assigned worker prompt history path: <absolute-path>`
|
|
46
|
+
6. `**Model:** Report writer worker, <modelExecutionValue>` (resolved per Phase 5.5 anchor-header rules)
|
|
47
|
+
7. The full `[Required reading]` clause (see [okstra-team-contract](../okstra-team-contract/SKILL.md)) including `final-report-template.md`.
|
|
48
|
+
8. The verbatim `## Available MCP Servers` block from the task brief, if present.
|
|
49
|
+
9. The convergence classifications (Full/Partial/Contested/Worker-Unique) and pointers to all worker result files under `worker-results/`.
|
|
50
|
+
10. For implementation-planning runs: a literal block listing the 8 required English section headings the validator scans for (`Option Candidates`, `Trade-off`, `Recommended Option`, `Stepwise Execution Order`, `Dependency`, `Validation Checklist`, `Rollback`, `User Approval Request`). The writer must use these exact substrings as section headings (Korean translation in parentheses is allowed).
|
|
51
|
+
11. An explicit instruction: `You are the author of TWO files: (a) the final-report file at <Result Path>, (b) the worker-results file at <Worker Result Path>. Write both directly using your Write tool. Do not return the report inline. The validator fails the run when (b) is missing.`
|
|
52
|
+
|
|
53
|
+
### Resume-safe dispatch
|
|
54
|
+
|
|
55
|
+
A resumed lead session can ALWAYS dispatch a fresh Report writer worker. The Agent tool does not require a previously created Team to be alive:
|
|
56
|
+
|
|
57
|
+
- If `TeamCreate` for `okstra-<task-key>` still succeeds (or the team is still listed), include `team_name` in the dispatch.
|
|
58
|
+
- If `TeamCreate` reports the name is taken or the team is gone, omit `team_name` from the dispatch — the worker still runs as a background subagent and its session is still recoverable by `agentName: "report-writer"` in `okstra-token-usage.py`.
|
|
59
|
+
- Do NOT skip dispatch because of any team-related error. Record the team status in team-state and proceed without `team_name`.
|
|
60
|
+
|
|
61
|
+
### Lead-authored fallback (only if dispatch failed)
|
|
62
|
+
|
|
63
|
+
Lead-authored fallback is permitted only if all of the following are true and recorded in team-state:
|
|
64
|
+
|
|
65
|
+
1. A Report writer worker dispatch was actually attempted (Agent call was issued).
|
|
66
|
+
2. The attempt recorded a terminal status of `error`, `timeout`, or `not-run` with a concrete reason (tool error message, timeout duration, or external blocker).
|
|
67
|
+
3. The reason is logged via `okstra-error-log.py append-observed --error-type cli-failure ...` (or `tool-failure` if the failure was internal).
|
|
68
|
+
|
|
69
|
+
Speculative reasons such as "session resume constraint", "team object no longer exists", or "lead can do it faster" are NOT valid.
|
|
70
|
+
|
|
71
|
+
## Phase 7 token-usage collector (BLOCKING)
|
|
72
|
+
|
|
73
|
+
At the start of Phase 7, run the token-usage collector with the final-report substitution flag. This step is BLOCKING — both the team-state aggregation AND the final-report placeholder substitution happen here, in one invocation:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
python3 scripts/okstra-token-usage.py \
|
|
77
|
+
<runDirectoryPath>/state/team-state-<task-type>-<seq>.json \
|
|
78
|
+
--write --summary \
|
|
79
|
+
--substitute-final-report <runDirectoryPath>/reports/final-report-<task-type>-<seq>.md
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
This:
|
|
83
|
+
|
|
84
|
+
- Populates `leadUsage`, every `workers[].usage`, and `usageSummary` in team-state from session transcripts.
|
|
85
|
+
- Substitutes the 10 token-related placeholders (`{{LEAD_TOTAL_TOKENS}}`, `{{LEAD_BILLABLE_TOKENS}}`, `{{LEAD_COST_USD}}`, `{{WORKER_TOTAL_TOKENS}}`, `{{WORKER_BILLABLE_TOKENS}}`, `{{WORKER_COST_USD}}`, `{{GRAND_TOTAL_TOKENS}}`, `{{GRAND_BILLABLE_TOKENS}}`, `{{GRAND_COST_USD}}`, `{{CLI_COST_USD}}`) in the final-report file with concrete values from the freshly computed usageSummary.
|
|
86
|
+
|
|
87
|
+
Skipping `--substitute-final-report` is the recurring root cause of reports shipping with literal `{{LEAD_TOTAL_TOKENS}}` etc. in their Token Usage Summary table. Always pass the flag — never run the collector without it during Phase 7.
|
|
88
|
+
|
|
89
|
+
The final-report file MUST already exist before this step runs (it's authored by Report writer worker in Phase 6, or by Lead in the documented fallback case). The status file can be written after this step completes.
|
|
90
|
+
|
|
91
|
+
## Final Report Structure
|
|
92
|
+
|
|
93
|
+
The final report follows the structure below. If `instruction-set/final-report-template.md` exists, that format takes precedence.
|
|
94
|
+
|
|
95
|
+
### Report Header
|
|
96
|
+
|
|
97
|
+
```markdown
|
|
98
|
+
# <task-key> - Multi-Agent Cross Verification Final Report
|
|
99
|
+
- Date: <ISO 8601 timestamp>
|
|
100
|
+
- Task Key: <task-key>
|
|
101
|
+
- Task Type: <task-type>
|
|
102
|
+
- Author: `<Report writer worker if in roster, else Claude lead>`
|
|
103
|
+
- Lead model: `<lead-model>`
|
|
104
|
+
- Preparation Method: Final report authored by Report writer worker (or lead-authored fallback — record the documented dispatch failure reason here when applicable)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Agent-Specific Execution Status Table
|
|
108
|
+
|
|
109
|
+
```markdown
|
|
110
|
+
| Agent | Role | Model | Status | 처리 토큰 | 환산 토큰 | 비용 (USD) | Duration | Summary of Key Findings |
|
|
111
|
+
|-------|------|-------|--------|-----------|-----------|------------|----------|------------------------|
|
|
112
|
+
| Claude Code | Claude lead | opus | completed | 10,479,327 | 1,769,798 | $26.55 | 59m 12s | Final synthesis status |
|
|
113
|
+
| Claude Code | Claude worker | sonnet | completed | 1,941,396 | 475,136 | $1.43 | 13m 33s | Key findings summary |
|
|
114
|
+
| Codex | Codex worker | gpt-5.5 | completed | 2,274,011 (CLI: 5,261,833) | 586,223 | $8.79 (+ CLI $4.20) | 22m 06s | Key findings summary |
|
|
115
|
+
| Gemini | Gemini worker | auto | completed | 3,107,795 | 746,623 | $11.20 | 22m 06s | Key findings summary |
|
|
116
|
+
| Claude Code | Report writer | opus | completed | 665,497 | 267,210 | $4.01 | 4m 20s | Report organization |
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Table Generation Rules:
|
|
120
|
+
- The first row is always `Claude lead` with data from `leadUsage`; subsequent rows follow `recommendedWorkers` / `resultContract.requiredWorkerRoles` order.
|
|
121
|
+
- Agent labels: Claude worker/Report writer → "Claude Code", Codex worker → "Codex", Gemini worker → "Gemini".
|
|
122
|
+
- **처리 토큰** = `usage.totalTokens` (input + output + cache_creation + cache_read; the raw volume processed).
|
|
123
|
+
- **환산 토큰** = `usage.billableEquivalentTokens` (cache reads weighted at 0.1×, cache_creation 1.25×, output 5×; useful as a single number for "how big was this session in cost terms").
|
|
124
|
+
- **비용 (USD)** = `usage.estimatedCostUsd`. For Codex/Gemini workers that actually invoked the CLI, append `(+ CLI $X.XX)` from `usage.cliEstimatedCostUsd`.
|
|
125
|
+
- For Codex/Gemini workers, append `(CLI: <cliTotalTokens>)` to the 처리 토큰 cell when `usage.cliTotalTokens` is set.
|
|
126
|
+
- Status values are retrieved from team-state; format duration as `Xm Ys` from `usage.durationMs`.
|
|
127
|
+
- Workers with status `not-run` or with `source: "unavailable"` show `--` for tokens/cost/duration; quote the `note` underneath the table if useful.
|
|
128
|
+
|
|
129
|
+
### Token Usage Summary Section
|
|
130
|
+
|
|
131
|
+
Place this section immediately after the execution status table.
|
|
132
|
+
|
|
133
|
+
```markdown
|
|
134
|
+
### 토큰 사용량 요약
|
|
135
|
+
|
|
136
|
+
| 항목 | 처리 토큰 | 환산 토큰 (input 기준) | 비용 (USD) |
|
|
137
|
+
|------|-----------|------------------------|------------|
|
|
138
|
+
| Lead | 10,479,327 | 1,769,798 | $26.55 |
|
|
139
|
+
| Worker 합계 | 7,988,699 | 2,075,192 | $25.43 |
|
|
140
|
+
| **전체 합계** | **18,468,026** | **3,844,990** | **$51.97** |
|
|
141
|
+
| Codex/Gemini CLI 추가 비용 | | | $0.00 |
|
|
142
|
+
|
|
143
|
+
> **읽는 법**: "처리 토큰"은 모델이 실제로 처리한 raw 토큰 합계(input + output + cache_creation + cache_read). 긴 세션에서는 cache_read가 95% 이상을 차지해 숫자가 커 보입니다. "환산 토큰"은 cache_read를 0.1×, cache_creation을 1.25×, output을 5×로 가중한 input-등가 토큰으로, 비용 감각에 가깝습니다. 비용은 공시 가격(Anthropic/OpenAI/Google) 기준 추정치입니다.
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Token Summary Generation Rules:
|
|
147
|
+
- All values come from `usageSummary` (populated by `scripts/okstra-token-usage.py` at the start of Phase 7). Do not estimate or invent.
|
|
148
|
+
- **Lead** row: `usageSummary.leadTotalTokens` / `usageSummary.leadBillableEquivalentTokens` / `usageSummary.estimatedCostUsd.lead`.
|
|
149
|
+
- **Worker 합계** row: `usageSummary.workerTotalTokens` / `usageSummary.workerBillableEquivalentTokens` / `usageSummary.estimatedCostUsd.claudeWorkers`.
|
|
150
|
+
- **전체 합계** row: `usageSummary.grandTotalTokens` / `usageSummary.grandBillableEquivalentTokens` / sum of `lead + claudeWorkers`.
|
|
151
|
+
- **Codex/Gemini CLI 추가 비용** row: `usageSummary.estimatedCostUsd.cliWorkers`. If 0, still show the row so the reader sees that no CLI work was billed under those providers (or that CLI fallback occurred).
|
|
152
|
+
- Format tokens with comma separators (e.g., `32,500`); format USD with two decimals (e.g., `$1.43`).
|
|
153
|
+
- If `lead` or any `worker.usage` has `source: "unavailable"`, show `--` for that row and append a one-line note (`reason: <note>`).
|
|
154
|
+
- If pricing for a model is unknown, the script omits `estimatedCostUsd` for that block — show `N/A` in that column and add a note like `pricing missing for model <model>`.
|
|
155
|
+
|
|
156
|
+
### Implementation-planning section heading contract (BLOCKING)
|
|
157
|
+
|
|
158
|
+
When the run's `task-type` is `implementation-planning`, the final report MUST contain section headings whose **lines include each of the 8 literal English substrings below**. The validator (`validators/validate-run.py`) does plain substring matching on the report text — 7-of-8 missing was a real, repeatedly observed failure mode caused by translating the headings to Korean.
|
|
159
|
+
|
|
160
|
+
| # | Required substring | Recommended heading form |
|
|
161
|
+
|---|--------------------|--------------------------|
|
|
162
|
+
| 1 | `Option Candidates` | `### Option Candidates (옵션 후보)` |
|
|
163
|
+
| 2 | `Trade-off` | `### Trade-off Matrix (트레이드오프 매트릭스)` |
|
|
164
|
+
| 3 | `Recommended Option` | `### Recommended Option (권장 옵션)` |
|
|
165
|
+
| 4 | `Stepwise Execution Order` | `### Stepwise Execution Order (단계별 실행 순서)` |
|
|
166
|
+
| 5 | `Dependency` | `### Dependency / Migration Risk (의존성·마이그레이션 위험)` |
|
|
167
|
+
| 6 | `Validation Checklist` | `### Validation Checklist (검증 체크리스트)` |
|
|
168
|
+
| 7 | `Rollback` | `### Rollback Strategy (롤백 전략)` |
|
|
169
|
+
| 8 | `User Approval Request` | `### User Approval Request (사용자 승인 요청)` |
|
|
170
|
+
|
|
171
|
+
The Korean translation in parentheses is optional but the English keyword is mandatory. The body of each section is written in Korean per the writing rules below. For non-`implementation-planning` runs, omit this entire block — these headings are NOT validator-checked for other task-types.
|
|
172
|
+
|
|
173
|
+
The final-report template `okstra-final-report.template.md` Section 4.5 already encodes this contract — copy that block verbatim and fill in.
|
|
174
|
+
|
|
175
|
+
### Mandatory worker-results file (BLOCKING)
|
|
176
|
+
|
|
177
|
+
You (the report-writer-worker subagent) MUST also write a worker-results audit file at the path the lead provides as `**Worker Result Path:**`, defaulting to:
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
runs/<task-type>/worker-results/report-writer-worker-<task-type>-<seq>.md
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
This file is checked by the validator whenever the role's terminal status is `completed`. Without it the run fails with `report-writer is completed but worker result file is missing`.
|
|
184
|
+
|
|
185
|
+
The file content is short: it begins with the standard worker-result header from `okstra-team-contract`, then names the canonical final-report path you wrote, lists the input artifacts you reconciled, and records any structural deviations from `final-report-template.md`. Do NOT duplicate the full final-report body here — it's an audit pointer, not a second copy.
|
|
186
|
+
|
|
187
|
+
Skipping this file because "the real report is in `reports/`" is wrong. Both files are required.
|
|
188
|
+
|
|
189
|
+
### Main Body Section
|
|
190
|
+
|
|
191
|
+
Section numbering matches `okstra-final-report.template.md`. Section 0 is the carry-in reconciliation that runs first when a clarification response was provided; sections 1–7 follow the template's main body order.
|
|
192
|
+
|
|
193
|
+
0. **Clarification Response Carried In** - if `{{CLARIFICATION_RESPONSE_RELATIVE_PATH}}` is non-empty, read `instruction-set/clarification-response.md`, reconcile every prior `Q*` row, and record the outcome (`resolved`/`obsolete`) plus the new evidence in this section before drafting the verdict
|
|
194
|
+
1. **Problem or Verification Summary** - Key summary based on the brief and data (3–5 bullet points)
|
|
195
|
+
2. **Cross Verification Results** (Use 4 categories when convergence is enabled, per `okstra-convergence`)
|
|
196
|
+
- Full Consensus: Findings agreed upon by all workers
|
|
197
|
+
- Partial Consensus: Agreed upon by a majority of workers; dissenting opinions are specified
|
|
198
|
+
- Contested: No consensus after max rounds; each worker’s position specified
|
|
199
|
+
- Worker-Unique: Verified only by the discoverer; verification history specified
|
|
200
|
+
- In runs with convergence disabled, maintain the existing Consensus/Differences format
|
|
201
|
+
3. **Final Verdict** - Conclusion based on comprehensive evidence; direction provided
|
|
202
|
+
4. **Evidence and Detailed Analysis**
|
|
203
|
+
- Key Evidence: File path, line number, actual evidence
|
|
204
|
+
- If explicit expected values are present in `reference-expectations.md`, specify whether they match or differ from the expected values in config files / deployment manifests
|
|
205
|
+
- Supporting evidence or alternative interpretations
|
|
206
|
+
5. **Missing Information and Risks** - Uncertain/I don't know items
|
|
207
|
+
6. **Clarification Requests for the Next Run** - structured Q&A table the user fills inline before reruns
|
|
208
|
+
- Required for `task-type` `error-analysis` and `requirements-discovery` whenever blocking uncertainty remains
|
|
209
|
+
- Optional for other task-types; explicitly state "no clarification needed" when none
|
|
210
|
+
- Follow the table format from `final-report-template.md` exactly (columns: Question ID, Blocking, Why this matters, Question, Expected answer shape, Status, Answer)
|
|
211
|
+
- Use stable `Q1`, `Q2`, ... ids and never delete prior ids on rerun; mark them `resolved` or `obsolete` instead
|
|
212
|
+
7. **Recommended Next Steps** - Actions by Priority
|
|
213
|
+
|
|
214
|
+
### Writing Guidelines
|
|
215
|
+
|
|
216
|
+
- Write in Markdown (actively use tables, bullet points, and code blocks)
|
|
217
|
+
- Write the final report body in Korean.
|
|
218
|
+
- Keep technical identifiers such as file paths, code symbols, model names, and status values in their original form when needed.
|
|
219
|
+
- If only one worker is usable, perform a reduced-confidence synthesis
|
|
220
|
+
- If evidence is insufficient, explicitly state "I don't know"
|
|
221
|
+
- If expected values are present in `reference-expectations.md`, list matches, gaps, and missing evidence separately
|
|
222
|
+
- If `reference-expectations.md` is explicitly empty, report the absence of expected states as missing information
|
|
223
|
+
- If there are no substantive differences between workers, state "No difference"
|
|
224
|
+
- Write the actual analysis text instead of a meta-description
|
|
225
|
+
- Do not make unfounded assertions
|
|
226
|
+
- Include findings from all four categories. Do not omit "contested" or "worker-unique" findings
|
|
227
|
+
- Include the convergence round history and a summary of votes by worker for each finding
|
|
228
|
+
- The report writer worker does not participate in the re-verification vote. It is responsible only for drafting the final report
|
|
229
|
+
|
|
230
|
+
## Artifact Persistence Checklist
|
|
231
|
+
|
|
232
|
+
Persistence steps that must be performed in Phase 7:
|
|
233
|
+
|
|
234
|
+
- [ ] 1. **Draft final report**: Save to `runs/<task-type>/reports/final-report-<task-type>-<seq>.md`
|
|
235
|
+
- [ ] 2. **Update team state**: Update `runs/<task-type>/state/team-state-<task-type>-<seq>.json`
|
|
236
|
+
- Final status, start/end times, and result file paths for each worker
|
|
237
|
+
- Overall run status
|
|
238
|
+
- [ ] 3. **Update run manifest**: Update `runs/<task-type>/manifests/run-manifest-<task-type>-<seq>.json`
|
|
239
|
+
- [ ] 4. **Update task-manifest.json**: Reflect task-level status and workflow lifecycle metadata
|
|
240
|
+
- Update `workCategory` if the run produced a confident classification
|
|
241
|
+
- Update `workflow.currentPhase`, `workflow.currentPhaseState`, `workflow.lastCompletedPhase`, and `workflow.phaseStates`
|
|
242
|
+
- Update `workflow.nextRecommendedPhase`, `workflow.awaitingApproval`, and `workflow.routingStatus`
|
|
243
|
+
- Update `workflow.lastSafeCheckpoint` to the best resume point for the current task
|
|
244
|
+
- [ ] 5. **Update task-index.md**: Refresh human-readable summary
|
|
245
|
+
- [ ] 6. **Generate final status file**: `runs/<task-type>/status/final-<task-type>-<seq>.status` (if necessary)
|
|
246
|
+
- [ ] 7. **Save convergence state**: `runs/<task-type>/state/convergence-<task-type>-<seq>.json` (when convergence is enabled)
|
|
247
|
+
|
|
248
|
+
### Response after Persistence
|
|
249
|
+
|
|
250
|
+
Provide a concise report in Korean covering the following:
|
|
251
|
+
- Completion status
|
|
252
|
+
- Final report path
|
|
253
|
+
- Team-state path
|
|
254
|
+
- Validator results
|
|
255
|
+
- Resume command path
|
|
256
|
+
- Remaining blockers (if any)
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: okstra-run
|
|
3
|
+
description: Use when the user wants to start an okstra task (cross-verification run) directly from the current Claude Code session — without spawning a new claude process. Equivalent in effect to `okstra.sh --task-type ...` but driven through interactive prompts. Trigger words include "okstra run", "okstra start", "start okstra", "begin okstra task", "run okstra in this session", "okstra here".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# OKSTRA Run (in-session)
|
|
7
|
+
|
|
8
|
+
Launch an okstra task — gather inputs interactively, render the full task bundle through the single python entrypoint, then take over as `Claude lead` in the current session.
|
|
9
|
+
|
|
10
|
+
**Single authority**: this skill and `okstra.sh` both call the exact same python function `okstra_ctl.run.prepare_task_bundle()`. The skill does NOT shell out to `okstra.sh` — that would create a second orchestration path and reintroduce env-var leakage between the parent claude session and child bash.
|
|
11
|
+
|
|
12
|
+
## When to Use
|
|
13
|
+
|
|
14
|
+
- The user is already inside a Claude Code session and asks to start an okstra task ("run okstra here", "start an error-analysis on this branch", "okstra implementation-planning for INV-1234").
|
|
15
|
+
- Continue an existing task (next phase) without leaving the current claude session.
|
|
16
|
+
|
|
17
|
+
## When NOT to Use
|
|
18
|
+
|
|
19
|
+
- User explicitly asks to spawn a new terminal / new claude — use `okstra-history` Step 4 (resume command) or instruct them to run `okstra.sh` in another terminal.
|
|
20
|
+
- User wants status only — use `okstra-status`.
|
|
21
|
+
- User wants past runs — use `okstra-history`.
|
|
22
|
+
|
|
23
|
+
## Authority Files (disk-only — no env var caching for per-run identity)
|
|
24
|
+
|
|
25
|
+
Every step reads disk afresh. The `OKSTRA_*` env vars below identify the
|
|
26
|
+
**runtime installation** (stable across runs) — they are NOT per-task identity.
|
|
27
|
+
|
|
28
|
+
- `~/.okstra/version` — okstra runtime version stamp
|
|
29
|
+
- `<PROJECT_ROOT>/.project-docs/okstra/project.json`
|
|
30
|
+
- `<PROJECT_ROOT>/.project-docs/okstra/discovery/{task-catalog,latest-task}.json`
|
|
31
|
+
- `<task-root>/task-manifest.json`
|
|
32
|
+
|
|
33
|
+
## Step 0: Verify okstra runtime + project setup
|
|
34
|
+
|
|
35
|
+
Do NOT hard-code or guess any okstra path. Every run loads them fresh from
|
|
36
|
+
the single authority — `okstra`:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# 1) Ensure runtime is fresh (idempotent, cached when up-to-date)
|
|
40
|
+
npx -y okstra@latest ensure-installed >/dev/null 2>&1 || {
|
|
41
|
+
echo "FAIL: okstra not installed; tell the user to run: npx okstra@latest install" >&2
|
|
42
|
+
exit 1
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# 2) Load all runtime paths into the shell as OKSTRA_* exports
|
|
46
|
+
eval "$(npx -y okstra@latest paths --shell)"
|
|
47
|
+
export PYTHONPATH="$OKSTRA_PYTHONPATH"
|
|
48
|
+
|
|
49
|
+
# 3) Verify the current project has okstra metadata (project.json + projectId)
|
|
50
|
+
OKSTRA_PROJECT_INFO="$(npx -y okstra@latest check-project --json)" || {
|
|
51
|
+
echo "FAIL: this project has no okstra setup. Tell the user to run /okstra-setup first." >&2
|
|
52
|
+
echo "$OKSTRA_PROJECT_INFO" >&2
|
|
53
|
+
exit 1
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
After Step 0 the following are guaranteed:
|
|
58
|
+
|
|
59
|
+
| Variable | Meaning |
|
|
60
|
+
|---|---|
|
|
61
|
+
| `$OKSTRA_WORKSPACE` | passed to python as `workspace_root` (prompts/, templates/, validators/, agents/ root) |
|
|
62
|
+
| `$OKSTRA_AGENTS_DIR` | source dir of worker `*.md` (subagent definitions) |
|
|
63
|
+
| `$OKSTRA_PYTHONPATH` | already exported as `PYTHONPATH` |
|
|
64
|
+
| `$OKSTRA_BIN` | bash entrypoints (`okstra.sh`, codex/gemini exec wrappers) |
|
|
65
|
+
| `$OKSTRA_HOME` | `~/.okstra` (recent.jsonl, locks, projects/, archive/) |
|
|
66
|
+
| `$OKSTRA_PROJECT_INFO` | JSON: `{ok, projectRoot, projectJsonPath, projectId}` — parse and reuse instead of re-resolving in Step 1 |
|
|
67
|
+
|
|
68
|
+
## Step 1: Resolve PROJECT_ROOT and projectId
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
python3 - <<'PY'
|
|
72
|
+
import sys, json
|
|
73
|
+
from okstra_project import resolve_project_root, ResolverError
|
|
74
|
+
try:
|
|
75
|
+
pr = resolve_project_root(explicit_root="", cwd=".")
|
|
76
|
+
except ResolverError as e:
|
|
77
|
+
print(f"FAIL\t{e}"); raise SystemExit(0)
|
|
78
|
+
print(f"OK\t{pr}")
|
|
79
|
+
PY
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- If `OK`: read `<PROJECT_ROOT>/.project-docs/okstra/project.json` and extract `projectId`.
|
|
83
|
+
- If `FAIL`: ask the user (`AskUserQuestion`, free text) for an absolute project-root path; rerun the resolver with `explicit_root=<their input>`.
|
|
84
|
+
|
|
85
|
+
## Step 2: Choose task — existing vs new
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
python3 -c "
|
|
89
|
+
import json, sys
|
|
90
|
+
from pathlib import Path
|
|
91
|
+
from okstra_project import list_project_tasks, read_latest_task
|
|
92
|
+
pr = Path(sys.argv[1])
|
|
93
|
+
tasks = list_project_tasks(pr)
|
|
94
|
+
latest = read_latest_task(pr)
|
|
95
|
+
print(json.dumps({'tasks': tasks, 'latest': latest}))
|
|
96
|
+
" "$PROJECT_ROOT"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Use `AskUserQuestion`:
|
|
100
|
+
|
|
101
|
+
- **Label**: "Which task?"
|
|
102
|
+
- **Options**: each existing task with label `"<taskKey> · <currentPhase or taskType> · next: <nextRecommendedPhase>"`; mark the `latest` entry with `(latest)`. Final option: `"Start a brand-new task"`. Limit to 8 candidates per page; add `"More..."` if more exist.
|
|
103
|
+
|
|
104
|
+
For an existing pick, read its `task-manifest.json` to capture `taskType` and `workflow.nextRecommendedPhase`.
|
|
105
|
+
|
|
106
|
+
## Step 3: For new tasks — collect identity
|
|
107
|
+
|
|
108
|
+
Skip if continuing existing.
|
|
109
|
+
|
|
110
|
+
`AskUserQuestion` (free text, one at a time):
|
|
111
|
+
|
|
112
|
+
1. `"Task group (e.g. backend-api, INV-1234, refactor)"` → `task_group`
|
|
113
|
+
2. `"Task id (e.g. login-error-analysis, dev-9043)"` → `task_id`
|
|
114
|
+
|
|
115
|
+
Validate that slugified `task_group` and `task_id` each contain at least one alphanumeric character. Re-ask if not.
|
|
116
|
+
|
|
117
|
+
## Step 4: Choose task-type
|
|
118
|
+
|
|
119
|
+
`AskUserQuestion` with five fixed options:
|
|
120
|
+
|
|
121
|
+
| Option | Description |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `requirements-discovery` | Classify request and route to next safe phase |
|
|
124
|
+
| `error-analysis` | Evidence-based root-cause analysis (no code changes) |
|
|
125
|
+
| `implementation-planning` | Plan options + request user approval |
|
|
126
|
+
| `implementation` | Execute approved plan (requires `--approved-plan`) |
|
|
127
|
+
| `final-verification` | Acceptance + residual-risk review |
|
|
128
|
+
|
|
129
|
+
For existing tasks, present `nextRecommendedPhase` as the first option (recommended default).
|
|
130
|
+
|
|
131
|
+
If `implementation` chosen, ask one more `AskUserQuestion`:
|
|
132
|
+
- `"Path to the approved final-report.md (must contain APPROVED marker)"` — the underlying python `prepare_task_bundle` re-validates the marker, but you can pre-check with `grep`.
|
|
133
|
+
|
|
134
|
+
## Step 5: Brief path
|
|
135
|
+
|
|
136
|
+
- New task: `AskUserQuestion` (free text) `"Path to the task brief markdown (relative to project root)"`. Verify file exists; re-ask on failure.
|
|
137
|
+
- Existing task: default to the manifest's `taskBriefPath`. Show it; ask whether to keep or change.
|
|
138
|
+
|
|
139
|
+
## Step 6 (optional): Directive / workers / models / related / clarification
|
|
140
|
+
|
|
141
|
+
Single `AskUserQuestion` first: `"Use default workers and models, or customize?"`
|
|
142
|
+
|
|
143
|
+
- `Use defaults` → all overrides remain empty.
|
|
144
|
+
- `Customize` → ask each in turn (free text, blank = use default):
|
|
145
|
+
- workers CSV (subset of `claude,codex,gemini,report-writer`)
|
|
146
|
+
- `lead-model`, `claude-model`, `codex-model`, `gemini-model`, `report-writer-model`
|
|
147
|
+
- `directive`
|
|
148
|
+
- `related-tasks` CSV
|
|
149
|
+
- `clarification-response` path (relevant for follow-up `requirements-discovery` / `error-analysis` runs)
|
|
150
|
+
|
|
151
|
+
## Step 7: Call `prepare_task_bundle` directly
|
|
152
|
+
|
|
153
|
+
This is the single line that materializes the entire task bundle. **Pass `render_only=True`** — the current claude session itself takes over as lead; we do not exec a new claude.
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
python3 - <<PY
|
|
157
|
+
import os
|
|
158
|
+
from pathlib import Path
|
|
159
|
+
from okstra_ctl.run import PrepareInputs, prepare_task_bundle
|
|
160
|
+
from okstra_ctl.path_resolve import resolve_user_file
|
|
161
|
+
|
|
162
|
+
project_root = Path("<project-root>")
|
|
163
|
+
brief_abs = resolve_user_file("<brief-path-from-user>", project_root)
|
|
164
|
+
clarification_abs = resolve_user_file("<clarification-or-empty>", project_root) if "<clarification-or-empty>" else None
|
|
165
|
+
|
|
166
|
+
out = prepare_task_bundle(PrepareInputs(
|
|
167
|
+
workspace_root=Path(os.environ["OKSTRA_WORKSPACE"]),
|
|
168
|
+
project_root=project_root,
|
|
169
|
+
project_id="<project-id>",
|
|
170
|
+
task_group="<task-group>",
|
|
171
|
+
task_id="<task-id>",
|
|
172
|
+
task_type="<task-type>",
|
|
173
|
+
brief_path=brief_abs,
|
|
174
|
+
directive="<directive or empty>",
|
|
175
|
+
workers_override="<workers csv or empty>",
|
|
176
|
+
lead_model="...", claude_model="...", codex_model="...",
|
|
177
|
+
gemini_model="...", report_writer_model="...",
|
|
178
|
+
related_tasks_raw="...",
|
|
179
|
+
approved_plan_path="<approved-plan-or-empty>",
|
|
180
|
+
clarification_response_path=str(clarification_abs) if clarification_abs else "",
|
|
181
|
+
render_only=True,
|
|
182
|
+
))
|
|
183
|
+
|
|
184
|
+
# Print key paths so the next step can read them.
|
|
185
|
+
ctx = out.ctx
|
|
186
|
+
print("TASK_ROOT", ctx["TASK_ROOT"])
|
|
187
|
+
print("INSTRUCTION_SET_DIR", ctx["INSTRUCTION_SET_DIR"])
|
|
188
|
+
print("LEAD_PROMPT", str(Path(ctx["INSTRUCTION_SET_DIR"]) / "claude-execution-prompt.md"))
|
|
189
|
+
PY
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
The python function is mutex-protected (`~/.okstra/.locks/<task-key>.lock`), writes `run-context-*.json` + `run-inputs-*.json` + all manifests + discovery files, and registers the run in `~/.okstra/recent.jsonl` with status `prepared`.
|
|
193
|
+
|
|
194
|
+
## Step 8: Take over as Claude lead
|
|
195
|
+
|
|
196
|
+
Read these files (do not paraphrase) and enter `Claude lead` mode:
|
|
197
|
+
|
|
198
|
+
1. `<INSTRUCTION_SET_DIR>/claude-execution-prompt.md` — the lead prompt
|
|
199
|
+
2. `<INSTRUCTION_SET_DIR>/analysis-profile.md` — per-task-type allowed outputs / forbidden actions
|
|
200
|
+
3. `<INSTRUCTION_SET_DIR>/analysis-material.md` — task brief + directive
|
|
201
|
+
4. `<INSTRUCTION_SET_DIR>/reference-expectations.md`
|
|
202
|
+
5. `<INSTRUCTION_SET_DIR>/final-report-template.md`
|
|
203
|
+
|
|
204
|
+
Then proceed through the phases exactly as the lead prompt directs (Phase 1 context → Phase 2+ worker dispatch → final synthesis → final report).
|
|
205
|
+
|
|
206
|
+
Inform the user with one short line:
|
|
207
|
+
> Took over as Claude lead for `<taskKey>` (`<task-type>`). Run dir: `<RUN_DIR_RELATIVE_PATH>`. Beginning Phase 1 (context loading).
|
|
208
|
+
|
|
209
|
+
## Concurrency
|
|
210
|
+
|
|
211
|
+
- `prepare_task_bundle` serializes per-task via `~/.okstra/.locks/<task-key>.lock`. Concurrent skill invocations on the same task wait; different tasks proceed in parallel.
|
|
212
|
+
- The skill must NOT call `okstra.sh` or any other bash entrypoint that would re-implement the orchestration. The python function is the single authority.
|
|
213
|
+
- No env var carries identity across steps — every step re-reads disk authority.
|
|
214
|
+
|
|
215
|
+
## Failure Modes
|
|
216
|
+
|
|
217
|
+
| Symptom | Cause | Fix |
|
|
218
|
+
|---|---|---|
|
|
219
|
+
| `okstra runtime missing: ...` | First run on this machine, or stale install | `npx okstra@latest install` once, retry. |
|
|
220
|
+
| `OKSTRA_PYTHONPATH unbound` / `ModuleNotFoundError: okstra_project` | Step 0 was skipped or env vars dropped | Re-run Step 0; never invoke python without exporting `PYTHONPATH=$OKSTRA_PYTHONPATH`. |
|
|
221
|
+
| `task root not found for <key>` | catalog entry stale or task-key typo | Re-run Step 2; show available keys from `list_project_tasks` |
|
|
222
|
+
| `PROJECT_ROOT 를 해석할 수 없습니다` | cwd outside okstra project, no git toplevel | Ask user for absolute path |
|
|
223
|
+
| `approved plan has no recognised user-approval marker` | `implementation` without proper approval | Ask user to add `APPROVED` to the plan, or pick a different task-type |
|
|
224
|
+
| `task brief not found` | brief-path doesn't resolve relative to cwd or project-root | Re-ask Step 5 |
|
|
225
|
+
| record_start failed | `~/.okstra` lock or disk issue | Non-fatal — bundle is valid; warn and continue |
|
|
226
|
+
|
|
227
|
+
## Output Rules
|
|
228
|
+
|
|
229
|
+
- Echo each `AskUserQuestion` outcome on one short line so user sees what was captured.
|
|
230
|
+
- Never invent identity; re-ask if blank.
|
|
231
|
+
- After Step 8, begin the lead workflow without re-summarizing the skill itself.
|