okstra 0.123.0 → 0.125.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 +1 -0
- package/docs/architecture/storage-model.md +3 -1
- package/docs/architecture.md +16 -2
- package/docs/cli.md +3 -1
- package/docs/for-ai/README.md +41 -35
- package/docs/for-ai/skills/okstra-brief-gen.md +105 -105
- package/docs/for-ai/skills/okstra-container-build.md +61 -61
- package/docs/for-ai/skills/okstra-graphify.md +64 -0
- package/docs/for-ai/skills/okstra-inspect.md +87 -86
- package/docs/for-ai/skills/okstra-manager.md +32 -32
- package/docs/for-ai/skills/okstra-memory.md +49 -50
- package/docs/for-ai/skills/okstra-pr-gen.md +48 -0
- package/docs/for-ai/skills/okstra-rollup.md +58 -58
- package/docs/for-ai/skills/okstra-run.md +95 -95
- package/docs/for-ai/skills/okstra-schedule-gen.md +106 -106
- package/docs/for-ai/skills/okstra-setup.md +63 -64
- package/docs/for-ai/skills/okstra-user-response.md +48 -0
- package/docs/performance-improvement-plan-v2.md +6 -6
- package/docs/pr-template-usage.md +34 -34
- package/docs/project-structure-overview.md +91 -70
- package/docs/task-process/README.md +33 -33
- package/docs/task-process/common-flow.md +26 -26
- package/docs/task-process/error-analysis.md +20 -21
- package/docs/task-process/final-verification.md +41 -41
- package/docs/task-process/implementation-planning.md +33 -33
- package/docs/task-process/implementation.md +38 -38
- package/docs/task-process/release-handoff.md +46 -46
- package/docs/task-process/requirements-discovery.md +22 -23
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/antigravity-worker.md +4 -4
- package/runtime/agents/workers/claude-worker.md +2 -2
- package/runtime/agents/workers/codex-worker.md +4 -4
- package/runtime/agents/workers/report-writer-worker.md +4 -4
- package/runtime/bin/lib/okstra/usage.sh +1 -1
- package/runtime/prompts/coding-preflight/frameworks/node-server.md +1 -1
- package/runtime/prompts/launch.template.md +1 -1
- package/runtime/prompts/lead/convergence.md +10 -20
- package/runtime/prompts/lead/okstra-lead-contract.md +15 -17
- package/runtime/prompts/lead/plan-body-verification.md +18 -18
- package/runtime/prompts/lead/report-writer.md +46 -44
- package/runtime/prompts/lead/team-contract.md +11 -122
- package/runtime/prompts/profiles/_common-contract.md +15 -22
- package/runtime/prompts/profiles/_implementation-deliverable.md +1 -1
- package/runtime/prompts/profiles/_implementation-executor.md +1 -1
- package/runtime/prompts/profiles/_implementation-verifier.md +28 -2
- package/runtime/prompts/profiles/error-analysis.md +2 -2
- package/runtime/prompts/profiles/final-verification.md +1 -1
- package/runtime/prompts/profiles/implementation-planning.md +13 -13
- package/runtime/prompts/profiles/implementation.md +2 -1
- package/runtime/prompts/profiles/improvement-discovery.md +1 -1
- package/runtime/prompts/profiles/release-handoff.md +3 -3
- package/runtime/prompts/profiles/requirements-discovery.md +17 -18
- package/runtime/python/okstra_ctl/models.py +4 -2
- package/runtime/python/okstra_ctl/run.py +8 -2
- package/runtime/python/okstra_ctl/stage_fix_carry.py +112 -0
- package/runtime/schemas/final-report-v1.0.schema.json +6 -6
- package/runtime/skills/_fragments/bash-invocation-rule.md +1 -0
- package/runtime/skills/_fragments/preflight-outdated-cli.md +1 -0
- package/runtime/skills/_fragments/python-bootstrap-note.md +1 -0
- package/runtime/skills/okstra-brief-gen/SKILL.md +117 -122
- package/runtime/skills/okstra-container-build/SKILL.md +24 -14
- package/runtime/skills/okstra-graphify/SKILL.md +12 -4
- package/runtime/skills/okstra-inspect/SKILL.md +39 -747
- package/runtime/skills/okstra-inspect/facets/cost.md +84 -0
- package/runtime/skills/okstra-inspect/facets/error-zip.md +41 -0
- package/runtime/skills/okstra-inspect/facets/errors.md +69 -0
- package/runtime/skills/okstra-inspect/facets/history.md +90 -0
- package/runtime/skills/okstra-inspect/facets/logs.md +89 -0
- package/runtime/skills/okstra-inspect/facets/recap.md +96 -0
- package/runtime/skills/okstra-inspect/facets/report.md +61 -0
- package/runtime/skills/okstra-inspect/facets/status.md +145 -0
- package/runtime/skills/okstra-inspect/facets/time.md +56 -0
- package/runtime/skills/okstra-manager/SKILL.md +1 -1
- package/runtime/skills/okstra-memory/SKILL.md +3 -3
- package/runtime/skills/okstra-pr-gen/SKILL.md +3 -3
- package/runtime/skills/okstra-rollup/SKILL.md +12 -6
- package/runtime/skills/okstra-run/SKILL.md +49 -88
- package/runtime/skills/okstra-schedule-gen/SKILL.md +36 -30
- package/runtime/skills/okstra-setup/SKILL.md +1 -1
- package/runtime/skills/okstra-setup/references/project-config.md +17 -16
- package/runtime/skills/okstra-usage/SKILL.md +5 -2
- package/runtime/skills/okstra-user-response/SKILL.md +15 -3
- package/runtime/templates/prd/brief.template.md +92 -92
- package/runtime/templates/project-docs/task-index.template.md +1 -1
- package/runtime/templates/reports/error-analysis-input.template.md +1 -1
- package/runtime/templates/reports/fan-out-unit.template.md +6 -6
- package/runtime/templates/reports/final-verification-input.template.md +6 -6
- package/runtime/templates/reports/implementation-input.template.md +1 -1
- package/runtime/templates/reports/implementation-planning-input.template.md +1 -1
- package/runtime/templates/reports/improvement-discovery-input.template.md +1 -1
- package/runtime/templates/reports/quick-input.template.md +1 -1
- package/runtime/templates/reports/release-handoff-input.template.md +1 -1
- package/runtime/templates/reports/schedule.template.md +22 -22
- package/runtime/templates/reports/task-brief.template.md +3 -3
- package/runtime/templates/reports/user-response.template.md +20 -20
- package/runtime/templates/worker-prompt-preamble.md +111 -13
- package/runtime/validators/validate-schedule.py +1 -1
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: okstra-inspect
|
|
3
3
|
description: >-
|
|
4
|
-
Use this for everything that happens AFTER a single okstra task has already run — inspecting it or light bookkeeping on it, never launching new work. The tell is usually a named task id (PROD-1623, dev-9184), often dropped without the word "okstra." Reach for it when the user wants one task's: status, current/next phase, blockers, or approval gate; its final report — where it is or whether it passed (
|
|
4
|
+
Use this for everything that happens AFTER a single okstra task has already run — inspecting it or light bookkeeping on it, never launching new work. The tell is usually a named task id (PROD-1623, dev-9184), often dropped without the word "okstra." Reach for it when the user wants one task's: status, current/next phase, blockers, or approval gate; its final report — where it is or whether it passed (verdict / pass); its elapsed time or context/read cost; its run history, re-run, or resume; to mark it done / in-progress / blocked / todo; or a failed run's error logs gathered into a report (error report). Also bundles cross-project okstra errors into an anonymized feedback zip (error feedback). Use it even for a bare "mark it done" or "where's the report." NOT for starting a run (okstra-run), rollups/schedules (okstra-rollup / okstra-schedule-gen), a brief (okstra-brief-gen), setup (okstra-setup), or cross-project management (okstra-manager).
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# OKSTRA Inspect
|
|
8
8
|
|
|
9
|
-
Single read-side entry point for okstra runtime inspection plus the one status mutation that belongs here (`workStatus`) and read-derived artifact rendering (`errors` report).
|
|
9
|
+
Single read-side entry point for okstra runtime inspection plus the one status mutation that belongs here (`workStatus`) and read-derived artifact rendering (`errors` report). Each sub-command's full procedure lives in a lazily loaded facet file — after dispatch, Read exactly the one facet you need.
|
|
10
10
|
|
|
11
|
-
| Sub-command | What it does |
|
|
12
|
-
|
|
13
|
-
| `status` | Task / phase status, blockers, approval state. Also writes `workStatus` on user request. |
|
|
14
|
-
| `history` | List past okstra runs; assemble re-run or resume command. |
|
|
15
|
-
| `report` | Resolve final-report path for a task-key. Optionally read it. |
|
|
16
|
-
| `time` | Per-task-type and per-worker duration breakdown for a task. |
|
|
17
|
-
| `logs` | Inventory codex/antigravity wrapper `.log` sidecars; emit cleanup commands. |
|
|
18
|
-
| `cost` | Estimate file/read context cost for a task bundle. |
|
|
19
|
-
| `errors` | Aggregate okstra-run error logs for a task into a timestamped markdown report; print a summary. |
|
|
20
|
-
| `error-zip` | Collect cross-project okstra error logs into an anonymized zip (report + raw) and summarize clusters. |
|
|
21
|
-
| `recap` | Summarize a task's run-to-run phase transitions, then answer free-form questions over its `.okstra` artifacts. Appends each summary/Q&A to `recap/recap-log.jsonl`, and writes agent-authored notes to `notes/` for feeding into later runs. |
|
|
11
|
+
| Sub-command | Facet file | What it does |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `status` | `facets/status.md` | Task / phase status, blockers, approval state. Also writes `workStatus` on user request. |
|
|
14
|
+
| `history` | `facets/history.md` | List past okstra runs; assemble re-run or resume command. |
|
|
15
|
+
| `report` | `facets/report.md` | Resolve final-report path for a task-key. Optionally read it. |
|
|
16
|
+
| `time` | `facets/time.md` | Per-task-type and per-worker duration breakdown for a task. |
|
|
17
|
+
| `logs` | `facets/logs.md` | Inventory codex/antigravity wrapper `.log` sidecars; emit cleanup commands. |
|
|
18
|
+
| `cost` | `facets/cost.md` | Estimate file/read context cost for a task bundle. |
|
|
19
|
+
| `errors` | `facets/errors.md` | Aggregate okstra-run error logs for a task into a timestamped markdown report; print a summary. |
|
|
20
|
+
| `error-zip` | `facets/error-zip.md` | Collect cross-project okstra error logs into an anonymized zip (report + raw) and summarize clusters. |
|
|
21
|
+
| `recap` | `facets/recap.md` | Summarize a task's run-to-run phase transitions, then answer free-form questions over its `.okstra` artifacts. Appends each summary/Q&A to `recap/recap-log.jsonl`, and writes agent-authored notes to `notes/` for feeding into later runs. |
|
|
22
22
|
|
|
23
23
|
## Step 0: Preflight (shared)
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
<!-- BEGIN FRAGMENT: bash-invocation-rule -->
|
|
26
|
+
Run one Bash tool call, starting with the literal token `okstra` (never wrapped in `if`/`eval`/`export`/`$(...)`/`VAR=...`/`||`/`&&`/`npx` — a non-literal leading token defeats the `Bash(okstra:*)` permission match):
|
|
27
|
+
<!-- END FRAGMENT: bash-invocation-rule -->
|
|
26
28
|
|
|
27
29
|
```bash
|
|
28
30
|
okstra preflight --runtime claude-code --json
|
|
@@ -32,758 +34,48 @@ The project check only sees the cwd of the Bash call. When the user is asking ab
|
|
|
32
34
|
|
|
33
35
|
Branch on the stdout JSON:
|
|
34
36
|
- `ok: true` → carry `projectRoot` as a literal string; it is the base for every sub-command step below.
|
|
35
|
-
- `ok: false` → before concluding "no setup", ask whether the user pointed at a specific project directory. If they did, re-run targeting it: `okstra preflight --runtime claude-code --cwd <that-dir> --json` (`--cwd` is the sanctioned way to target a project — a leading `cd` would break the permission match). Only if this **also** returns `ok:false` do you tell the user: "this project has no okstra setup. Run `/okstra-setup` first." Then stop.
|
|
36
|
-
|
|
37
|
-
Carry the resolved `projectRoot` into the sub-commands: read file artifacts under `<projectRoot>/.okstra/...`, and for sub-command CLIs that accept it (e.g. `recap`, `context-cost`) pass `--cwd <projectRoot>` / `--project-root <projectRoot>` so they target the same project rather than the Bash cwd. Subsequent `okstra <subcmd>` calls self-bootstrap their Python path, so this skill never needs `okstra paths --shell` / `export PYTHONPATH=...`.
|
|
38
|
-
|
|
39
|
-
## Step 1: Dispatch by intent
|
|
40
|
-
|
|
41
|
-
Classify the user's request into one sub-command using the trigger table above. If ambiguous (e.g. "okstra 보여줘"), ask which facet — do not silently default. After routing, the chosen sub-command's section below governs the rest of the response.
|
|
42
|
-
|
|
43
|
-
When you ask which facet, the option list is **authoritative**: enumerate every sub-command in the `Sub-command | What it does` table above as a numbered text list, in table order, each with its one-line description, and let the user pick by number or name. Never present a hand-picked subset — the AskUserQuestion 4-option cap is not a reason to drop facets; render the full menu as text in the question body so no facet (e.g. a newly added one) is ever hidden. The table is the single source of truth for this menu; adding a row there is all it takes for the facet to appear here.
|
|
44
|
-
|
|
45
|
-
When the user chains multiple facets in one message (e.g. "status, and then time for DEV-9047"), execute them sequentially — Step 0 runs once, each sub-command section runs once.
|
|
46
|
-
|
|
47
|
-
---
|
|
48
|
-
|
|
49
|
-
## status
|
|
50
|
-
|
|
51
|
-
Trigger phrases: "okstra status", "task status", "current phase", "next phase", "what is pending", "resume point", "okstra status set", "okstra mark", "<task-id> done", "<task-id> in-progress", "<task-id> 진행중", "<task-id> 완료".
|
|
52
|
-
|
|
53
|
-
### status.1 — Overall project status
|
|
54
|
-
|
|
55
|
-
Read `.okstra/discovery/task-catalog.json`. The catalog is the authoritative source — every field listed below (including `workStatus`, `workStatusUpdatedAt`, `workStatusNote`) is projected directly from each `task-manifest.json` by `scripts/okstra_ctl/render.py :: render_task_catalog_discovery`. Do NOT re-open individual manifests for the overview.
|
|
56
|
-
|
|
57
|
-
| Field | Description |
|
|
58
|
-
|------|------|
|
|
59
|
-
| `taskKey` | `<project-id>:<task-group>:<task-id>` |
|
|
60
|
-
| `taskType` | latest task type |
|
|
61
|
-
| `workCategory` | bugfix / feature / improvement / refactor / ops / unknown. Display `unknown` as-is, but flag with `(unset)` annotation so the reader knows the requirements-discovery classification was skipped or no `--work-category` flag was passed. |
|
|
62
|
-
| `currentStatus` | task-level status |
|
|
63
|
-
| `currentPhase` | lifecycle current phase |
|
|
64
|
-
| `currentPhaseState` | lifecycle phase state |
|
|
65
|
-
| `nextRecommendedPhase` | next recommended phase |
|
|
66
|
-
| `routingStatus` | routing decision status |
|
|
67
|
-
| `awaitingApproval` | approval 대기 여부 |
|
|
68
|
-
| `latestRunStatus` | latest run status |
|
|
69
|
-
| `latestReportPath` | latest report path |
|
|
70
|
-
| `latestResumeCommandPath` | latest resume command |
|
|
71
|
-
| `workStatus` | user-managed work status (todo / in-progress / blocked / done; default in-progress) |
|
|
72
|
-
| `updatedAt` | last update time |
|
|
73
|
-
|
|
74
|
-
Sort by `updatedAt` desc, then `taskKey`.
|
|
75
|
-
|
|
76
|
-
The overview table is intentionally narrow so it renders cleanly in a terminal. Only six columns are shown; for any task that needs a closer look (phase state, routing, approval gate, last run status, resume path, etc.) tell the user to run `/okstra-inspect status <task-key>` for the detail view in `status.2`.
|
|
77
|
-
|
|
78
|
-
If `awaitingApproval` is true OR `routingStatus == "pending"`, append a `*` to the `Next` cell and explain the marker once below the table.
|
|
79
|
-
|
|
80
|
-
```markdown
|
|
81
|
-
## okstra Status — <project-id>
|
|
82
|
-
|
|
83
|
-
| # | Task Key | Category | Phase | workStatus | Next |
|
|
84
|
-
|---|----------|----------|-------|------------|------|
|
|
85
|
-
| 1 | proj:group:id | bugfix | error-analysis | in-progress | implementation-planning |
|
|
86
|
-
| 2 | proj:group:id2 | feature | requirements-discovery | done | pending-routing-decision* |
|
|
87
|
-
|
|
88
|
-
`*` = awaiting user approval or pending routing decision. Run `/okstra-inspect status <task-key>` for details.
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### status.2 — Specific task status
|
|
92
|
-
|
|
93
|
-
Given a specific `task-key` or `task-group + task-id`:
|
|
94
|
-
|
|
95
|
-
1. If possible, quickly look it up in `task-catalog.json`.
|
|
96
|
-
2. If necessary, read `.okstra/tasks/<task-group>/<task-id>/task-manifest.json` directly.
|
|
97
|
-
3. If you need the latest run information, read `history/timeline.json` along with the latest run manifest.
|
|
98
|
-
|
|
99
|
-
Required fields: `taskKey`, `taskType`, `workCategory`, `currentStatus`, `latestRunStatus`, `workflow.{currentPhase, currentPhaseState, phaseStates, lastCompletedPhase, nextRecommendedPhase, awaitingApproval, routingStatus, lastSafeCheckpoint}`, `workStatus`, `workStatusUpdatedAt`, `workStatusNote`, `latestReportPath`, `latestResumeCommandPath`, `historyTimelinePath`.
|
|
100
|
-
|
|
101
|
-
```markdown
|
|
102
|
-
## okstra Task Status — <task-key>
|
|
103
|
-
|
|
104
|
-
- Work category: `<category>`
|
|
105
|
-
- Current phase: `<phase>`
|
|
106
|
-
- Current phase state: `<phase-state>`
|
|
107
|
-
- Last completed phase: `<phase-or-->`
|
|
108
|
-
- Next recommended phase: `<phase>`
|
|
109
|
-
- Awaiting approval: `<yes|no>`
|
|
110
|
-
- Routing status: `<routing-status>`
|
|
111
|
-
- Task status: `<task-status>`
|
|
112
|
-
- Latest run status: `<run-status>`
|
|
113
|
-
- Latest report: `<relative-path-or-->`
|
|
114
|
-
- Resume command: `<relative-path-or-->`
|
|
115
|
-
- workStatus: `<todo|in-progress|blocked|done>` (updated `<workStatusUpdatedAt-or-->`)
|
|
116
|
-
- workStatus note: `<workStatusNote-or-->`
|
|
117
|
-
|
|
118
|
-
### Phase States
|
|
119
|
-
|
|
120
|
-
- `requirements-discovery`: `<state>`
|
|
121
|
-
- `error-analysis`: `<state>`
|
|
122
|
-
- `implementation-planning`: `<state>`
|
|
123
|
-
- `implementation`: `<state>`
|
|
124
|
-
- `final-verification`: `<state>`
|
|
125
|
-
- `release-handoff`: `<state>`
|
|
126
|
-
|
|
127
|
-
### Safe Resume Checkpoint
|
|
128
|
-
|
|
129
|
-
- Label: `<checkpoint-label>`
|
|
130
|
-
- Run manifest: `<relative-path-or-->`
|
|
131
|
-
- Team state: `<relative-path-or-->`
|
|
132
|
-
- Report: `<relative-path-or-->`
|
|
133
|
-
- Resume command: `<relative-path-or-->`
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### status.3 — Resume / next-step guidance
|
|
137
|
-
|
|
138
|
-
The status response always includes one of:
|
|
37
|
+
- `ok: false` → before concluding "no setup", ask whether the user pointed at a specific project directory. If they did, re-run targeting it: `okstra preflight --runtime claude-code --cwd <that-dir> --json` (`--cwd` is the sanctioned way to target a project — a leading `cd` would break the permission match). Only if this **also** returns `ok:false` do you tell the user: "this project has no okstra setup. Run `/okstra-setup` first." Then stop.
|
|
139
38
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
4. **Need more information** — if `nextRecommendedPhase` is `pending-routing-decision` or `routingStatus` is `pending`.
|
|
144
|
-
5. **Task complete (terminal)** — if `nextRecommendedPhase` is `done-or-follow-up`, the task lifecycle has reached its terminal signal. This is **not** a "next phase" — do not propose a new okstra run. Surface the latest report and ask the user whether any follow-up task should be opened separately.
|
|
39
|
+
<!-- BEGIN FRAGMENT: preflight-outdated-cli -->
|
|
40
|
+
If the call fails with `unknown command: preflight`, the `okstra` binary on PATH predates this skill — tell the user to update it (`npm i -g okstra@latest`), then stop (`/okstra-setup` does not update the binary).
|
|
41
|
+
<!-- END FRAGMENT: preflight-outdated-cli -->
|
|
145
42
|
|
|
146
|
-
|
|
43
|
+
Carry the resolved `projectRoot` into the sub-commands: read file artifacts under `<projectRoot>/.okstra/...`, and for sub-command CLIs that accept it (e.g. `recap`, `context-cost`) pass `--cwd <projectRoot>` / `--project-root <projectRoot>` so they target the same project rather than the Bash cwd.
|
|
147
44
|
|
|
148
|
-
|
|
45
|
+
<!-- BEGIN FRAGMENT: python-bootstrap-note -->
|
|
46
|
+
Every subsequent `okstra <subcmd>` call self-bootstraps its Python path, so this skill never needs `okstra paths --shell` / `export PYTHONPATH=...`.
|
|
47
|
+
<!-- END FRAGMENT: python-bootstrap-note -->
|
|
149
48
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
Natural language: "DEV-6827 done으로 바꿔줘", "PROD-1623을 blocked로 표시", "DEV-9047 진행중", "Mark DEV-6827 as done".
|
|
153
|
-
|
|
154
|
-
Explicit phrasing (recognized user utterances — normalize each to a `okstra set-work-status` call below):
|
|
155
|
-
- `okstra status set <task-id> <status>`
|
|
156
|
-
- `okstra status set <task-group> <task-id> <status>` (disambiguation)
|
|
157
|
-
- `okstra mark <task-id> <status>`
|
|
158
|
-
- `okstra status set <task-id> <status> --note "<note>"`
|
|
159
|
-
|
|
160
|
-
Accepted `<status>` values: `todo`, `in-progress`, `blocked`, `done`.
|
|
161
|
-
|
|
162
|
-
**Procedure:** run the update through the CLI (one Bash call, literal `okstra` token) — never edit `task-manifest.json` by hand:
|
|
163
|
-
|
|
164
|
-
```bash
|
|
165
|
-
okstra set-work-status <token> <status> --project-root <projectRoot> --json
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
- `<token>` is a full task-key or a bare task-id. Add `--task-group <group>` to scope a duplicated id, `--note "<note>"` to set `workStatusNote` (flag omitted → any existing note is left untouched).
|
|
169
|
-
- Branch on the stdout JSON: `ok: true` → confirm below. `stage: "ambiguous"` → list `matches[]` (with `_matchedVia`) via a 3-option picker and retry with the chosen full task-key. `stage: "not-found"` → `<TASK-ID>를 찾을 수 없습니다.` An invalid `<status>` makes the CLI exit 2 with the allowed-values list — surface it verbatim; nothing was modified.
|
|
170
|
-
|
|
171
|
-
Confirm in Korean:
|
|
172
|
-
```
|
|
173
|
-
✓ <TASK-ID> workStatus: <previousWorkStatus> → <workStatus>
|
|
174
|
-
✓ task-manifest.json 업데이트됨
|
|
175
|
-
```
|
|
176
|
-
`<previousWorkStatus>` = `(없음)` when the JSON's `previousWorkStatus` is empty.
|
|
177
|
-
|
|
178
|
-
**Default value convention:** if `workStatus` is missing or empty, infer the display value from lifecycle state (DO NOT default to a static `in-progress`):
|
|
179
|
-
|
|
180
|
-
| Manifest state | Inferred display |
|
|
181
|
-
|---|---|
|
|
182
|
-
| `currentStatus == "completed"` AND `workflow.nextRecommendedPhase == "done-or-follow-up"` | `done` (inferred) |
|
|
183
|
-
| `currentStatus == "completed"` AND `workflow.currentPhaseState == "completed"` | `phase-done` (inferred) |
|
|
184
|
-
| `currentStatus == "contract-violated"` OR `workflow.currentPhaseState == "blocked"` | `blocked` (inferred) |
|
|
185
|
-
| anything else | `in-progress` (default) |
|
|
186
|
-
|
|
187
|
-
Annotate inferred values with `(inferred)` or `(default)`. Do not back-fill on read; only write when the user explicitly issues an update.
|
|
188
|
-
|
|
189
|
-
**Catalog sync note:** the CLI updates `task-manifest.json` only. `discovery/task-catalog.json` may be stale until the next run regenerates it; downstream consumers (e.g. `okstra-schedule-gen`) re-read each manifest directly.
|
|
190
|
-
|
|
191
|
-
---
|
|
192
|
-
|
|
193
|
-
## history
|
|
194
|
-
|
|
195
|
-
Trigger phrases: "okstra history", "past runs", "run history", "re-run", "list tasks", "다시 실행", "resume", "이어서".
|
|
196
|
-
|
|
197
|
-
**Re-run vs Resume — decide upfront.** Re-run = start a fresh run (new run-seq, new manifest, new report) reusing an old run's parameters → `history.3`. Resume = continue an interrupted Claude session for an existing run, no new run-seq → `history.4`. If the user is ambiguous, ask — defaulting to the wrong one either wastes a fresh run-seq or silently abandons a recoverable session.
|
|
198
|
-
|
|
199
|
-
### history.1 — Read the task catalog
|
|
200
|
-
|
|
201
|
-
1. Read `.okstra/discovery/task-catalog.json`.
|
|
202
|
-
2. Apply filters from user input (all optional, AND-combined):
|
|
203
|
-
- `--task-type <type>` → keep entries whose `taskType` matches.
|
|
204
|
-
- `--latest-run-status <status>` → keep entries whose `latestRunStatus` matches (`completed`, `contract-violated`, `error`).
|
|
205
|
-
- `--task-group <group>` → keep entries whose `taskGroup` matches.
|
|
206
|
-
3. Sort by `updatedAt` desc.
|
|
207
|
-
4. Page: default `--limit 20`. If truncated, add `... <N> more (pass --limit <N> to see all)`.
|
|
208
|
-
5. Extract: `taskKey`, `taskType`, `currentStatus`, `latestRunStatus`, `latestRunManifestPath`, `updatedAt`, `latestReportPath`, `latestResumeCommandPath`, `historyTimelinePath`.
|
|
209
|
-
|
|
210
|
-
```markdown
|
|
211
|
-
## okstra Task History — <project-id>
|
|
212
|
-
|
|
213
|
-
| # | Task Key | Type | currentStatus | latestRunStatus | Last Run | Report |
|
|
214
|
-
|---|----------|------|---------------|------------------|----------|--------|
|
|
215
|
-
| 1 | proj:group:id | error-analysis | completed | completed | 2026-04-05 22:59 | .project-docs/.../final-report-*.md |
|
|
216
|
-
| 2 | proj:group:id2 | final-verification | todo | error | 2026-04-04 15:30 | -- |
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
**Catalog absent — fallback.** Do NOT bail out. Manifests on disk are the source of truth.
|
|
220
|
-
|
|
221
|
-
1. Glob `<projectRoot>/.okstra/tasks/*/*/task-manifest.json`.
|
|
222
|
-
2. For each manifest, read the same fields as above.
|
|
223
|
-
3. Apply the same filters/sort/limit and print the same table, prefixed with: `note: task-catalog.json missing; reconstructed from task manifests on disk.`
|
|
224
|
-
4. Only if the glob yields zero manifests: `There is no okstra execution history yet.`
|
|
225
|
-
|
|
226
|
-
### history.2 — Run history by task
|
|
227
|
-
|
|
228
|
-
When a user selects a specific task:
|
|
229
|
-
|
|
230
|
-
1. Retrieve `historyTimelinePath`, read `runs` array.
|
|
231
|
-
2. Extract: `runTimestamp`, `runDateTimeSegment`, `taskType`, `status`, `runManifestPath`, `reportPath`, `resumeCommandPath`, `relatedTasks`.
|
|
232
|
-
|
|
233
|
-
```markdown
|
|
234
|
-
## Runs for <task-key>
|
|
235
|
-
|
|
236
|
-
| # | Timestamp | Type | Status | Report |
|
|
237
|
-
|---|-----------|------|--------|--------|
|
|
238
|
-
| 1 | 2026-04-05 22:59 | error-analysis | completed | .../final-report-*.md |
|
|
239
|
-
| 2 | 2026-04-04 15:30 | error-analysis | error | -- |
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
### history.3 — Re-run (NEW run from old parameters)
|
|
243
|
-
|
|
244
|
-
Builds a fresh run — new run-seq, new manifest, new report — using parameters from a previous `run-manifest-*.json`. Does NOT touch old artifacts; use `history.4` to continue an interrupted session.
|
|
245
|
-
|
|
246
|
-
1. Pick the source run-manifest: `runManifestPath` from `history.2`, or task's `latestRunManifestPath` from `history.1`. Note: `latestRunManifestPath` is projected from the timeline's latest run, so it is empty when the task has no recorded run yet (timeline absent) — in that case fall back to a `history.2` per-run `runManifestPath`, or ask the user.
|
|
247
|
-
2. Read the manifest and extract required arguments:
|
|
248
|
-
- `projectId` → `--project-id`
|
|
249
|
-
- `taskGroup` → `--task-group`
|
|
250
|
-
- `taskId` → `--task-id`
|
|
251
|
-
- `taskType` → `--task-type`
|
|
252
|
-
- `taskBriefPath` → `--task-brief`
|
|
253
|
-
3. Optional arguments (include only when present in source):
|
|
254
|
-
- `recommendedWorkers` → `--workers` (comma-separated)
|
|
255
|
-
- `relatedTasks` → `--related-tasks`
|
|
256
|
-
- model overrides → `--claude-model`, `--codex-model`, `--antigravity-model`
|
|
257
|
-
- for `taskType: implementation`: `teamContract.executor.provider` → `--executor <claude|codex|antigravity>` when different from `claude`.
|
|
258
|
-
4. **`taskType: implementation` only — resolve `--base-ref`:** base ref is NOT in the run-manifest; it lives in the worktree registry at `~/.okstra/worktrees/registry.json`. If a worktree is already registered, existing branch & base are reused — omit `--base-ref` unless the user explicitly wants a different starting point. If no worktree is registered (cleaned up), `--base-ref` is mandatory — ask the user before running.
|
|
259
|
-
5. Display the assembled command:
|
|
260
|
-
```bash
|
|
261
|
-
~/.okstra/bin/okstra.sh \
|
|
262
|
-
--project-id <project-id> \
|
|
263
|
-
--task-group <task-group> \
|
|
264
|
-
--task-id <task-id> \
|
|
265
|
-
--task-type <task-type> \
|
|
266
|
-
--task-brief <brief-path> \
|
|
267
|
-
--workers <worker-list>
|
|
268
|
-
```
|
|
269
|
-
6. Once the user confirms, execute it.
|
|
270
|
-
|
|
271
|
-
### history.4 — Resume (continue an interrupted run)
|
|
272
|
-
|
|
273
|
-
Continues an existing Claude session for an unfinished run. Does NOT create a new run-seq — for a fresh dispatch use `history.3`.
|
|
274
|
-
|
|
275
|
-
1. Read `latestResumeCommandPath` from `history.1` (or `resumeCommandPath` from a `history.2` timeline entry).
|
|
276
|
-
2. Verify the file exists on disk.
|
|
277
|
-
3. If it exists: `bash <resume-command-path>`.
|
|
278
|
-
4. If the path is empty or the file is missing: `No resume script available for this run. Use 'history.3' to start a fresh run instead.`
|
|
279
|
-
|
|
280
|
-
---
|
|
281
|
-
|
|
282
|
-
## report
|
|
283
|
-
|
|
284
|
-
Trigger phrases: "find report", "show report for", "read the okstra report", "continue from report".
|
|
285
|
-
|
|
286
|
-
### report.1 — Resolve report path
|
|
287
|
-
|
|
288
|
-
task-key format: `<project-id>:<task-group>:<task-id>`.
|
|
289
|
-
|
|
290
|
-
**Normalization:** task-key matching is lowercase. Disk segments are slugified (lowercase + non-alphanumeric runs → `-`) per `scripts/okstra_ctl/ids.py:88` (`slugify_task_segment`, the SSOT; `interactive.sh` consumes it via import). Catalog lookup is case-insensitive; file path assembly uses slugified segments.
|
|
291
|
-
|
|
292
|
-
Lookup methods (in priority order):
|
|
293
|
-
|
|
294
|
-
A. **`task-catalog.json` (fast):** read `.okstra/discovery/task-catalog.json`, match `taskKey` lowercase. `latestReportPath` is task-type-agnostic "most recent report".
|
|
295
|
-
|
|
296
|
-
B. **`task-manifest.json` (direct):** if catalog missing, slugify task-group / task-id, read `.okstra/tasks/<group-segment>/<id-segment>/task-manifest.json`, use `latestReportPath` (task-type-agnostic).
|
|
297
|
-
|
|
298
|
-
C. **`timeline.json` (specific run):** for a specific date or run, read `.okstra/tasks/<group-segment>/<id-segment>/history/timeline.json`, filter `runs[]` by `runTimestamp` / `status` / `taskType`, use `runs[].reportPath`.
|
|
299
|
-
|
|
300
|
-
D. **Specific task-type (fallback):** `latestReportPath` is task-type-agnostic. For a specific task-type's latest report, look under `.okstra/tasks/<group-segment>/<id-segment>/runs/<task-type-segment>/reports/`, filename pattern `final-report-<task-type-segment>-<NNN>.md` per `scripts/okstra_ctl/sequence.py:30`. Highest seq is latest. Stage-isolated runs (`implementation`, single-stage `final-verification`) keep their reports one level deeper at `runs/<task-type-segment>/stage-<N>/reports/` — scan those subdirectories too; seq is independent per stage. Cross-verify with `timeline.json`'s `runs[].taskType` filter.
|
|
301
|
-
|
|
302
|
-
### report.2 — Confirm existence
|
|
303
|
-
|
|
304
|
-
1. Verify `latestReportPath` is non-empty AND the file exists on disk. Either signal indicates report presence (tolerant).
|
|
305
|
-
2. If present, display the path and ask the user whether to read it.
|
|
306
|
-
3. If absent, check `task-manifest.json` signals:
|
|
307
|
-
- `latestReportPath` empty/missing AND `currentStatus != completed` AND `workStatus != done` AND `workflow.routingStatus` not completion-like → `이 task는 아직 완료되지 않았습니다 (currentStatus: <currentStatus>, workStatus: <workStatus>).`
|
|
308
|
-
- Any signal indicates completion but the file is missing → `보고서 파일이 존재하지 않습니다: <path>`
|
|
309
|
-
|
|
310
|
-
`workStatus` enum: `todo | in-progress | blocked | done`. `currentStatus`: `completed` / `contract-violated` etc. `"completed"` string does NOT exist in `workStatus` — do not confuse the two.
|
|
311
|
-
|
|
312
|
-
### report.3 — Read + next-step guidance
|
|
313
|
-
|
|
314
|
-
Match the depth of read to the request — final reports routinely run 300+ lines / 50K+ tokens, so ingesting the whole file just to answer "핵심만 요약" is wasteful:
|
|
315
|
-
|
|
316
|
-
- **Summary / verdict intent** ("요약", "핵심만", "결론", "통과했어?", "verdict"): do **not** read the whole report first. Read the `final-<task-type-segment>-<NNN>.status` sidecar under `runs/<task-type-segment>/status/` (stage-isolated: `runs/<task-type-segment>/stage-<N>/status/`) for the machine verdict, then read only the report's leading summary block (the first "종합 판정" / "Executive" / verdict heading and its body) to quote the gist. Offer to read the full report if the user wants detail.
|
|
317
|
-
- **Full-read intent** ("전체", "다 읽어", "본문"): ingest the resolved report file.
|
|
318
|
-
|
|
319
|
-
After reading, surface follow-up options:
|
|
320
|
-
|
|
321
|
-
1. **구현 진행:** based on the report's "권장 다음 단계" section.
|
|
322
|
-
2. **추가 검증:** to launch a new okstra run with the same task-key, assemble the command through the `history` sub-command — it offers the full option set (base-ref, workers, render-only) and renders a host-correct invocation.
|
|
323
|
-
3. **관련 task 확인:** if the report references related task-keys, fetch their reports too.
|
|
324
|
-
|
|
325
|
-
### report — Output template
|
|
326
|
-
|
|
327
|
-
```markdown
|
|
328
|
-
## Report for <task-key>
|
|
329
|
-
|
|
330
|
-
| Field | Value |
|
|
331
|
-
| ------------ | -------------------------------------------------- |
|
|
332
|
-
| Status | `<status>` |
|
|
333
|
-
| Task type | `<task-type>` |
|
|
334
|
-
| Run seq | `<NNN>` |
|
|
335
|
-
| Run date | `<runTimestamp ISO-8601>` |
|
|
336
|
-
| Report (rel) | `<relative-path-from-project-root>` |
|
|
337
|
-
| Report (abs) | `<absolute-path>` |
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
---
|
|
341
|
-
|
|
342
|
-
## time
|
|
343
|
-
|
|
344
|
-
Trigger phrases: "작업 시간", "소요 시간", "time summary", "duration", "elapsed", "얼마나 걸렸", "시간 분석".
|
|
345
|
-
|
|
346
|
-
Aggregate elapsed work time for a task, grouped by **task type** and broken down by **worker** (lead + each worker). The `time-report` CLI reads both data sources (`history/timeline.json` runs + each run's `team-state-*.json` usage blocks) and does **all** aggregation — cross-run sums, CPU-sum vs wall-clock, timestamp parsing, unavailable detection. You only resolve the task-key, call it, and render. **Never recompute durations by hand.**
|
|
347
|
-
|
|
348
|
-
### time.1 — Resolve the task-key
|
|
349
|
-
|
|
350
|
-
Same standard as `cost.1`: full task-key → use directly; bare token (task-id or task-group) → `okstra resolve-task-key <token> --project-root <projectRoot> --json` and branch on `matches[]` (0 = not found, 1 = use, N = 3-option picker). If no okstra history exists, say `No okstra history found. Run /okstra-run first.`
|
|
351
|
-
|
|
352
|
-
### time.2 — Fetch aggregated data
|
|
353
|
-
|
|
354
|
-
```bash
|
|
355
|
-
okstra time-report <task-key> --project-root <projectRoot> --json
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
Returns (all durations are **raw milliseconds**):
|
|
359
|
-
- `byTaskType[]` — `{taskType, runs, leadMs, workersMs, cpuSumMs}`, plus `grandTotal`
|
|
360
|
-
- `perWorker` — `{<taskType>: [{workerId, agents[], runs, totalMs, avgMs}]}`; only workers with a nonzero run appear, and `agents[]` lists agent labels that differ from `workerId`
|
|
361
|
-
- `perRunWallClock[]` — `{runTimestamp, taskType, wallClockMs}` (max `endedAt` − min `startedAt` per run)
|
|
362
|
-
- `phaseTimelines[]` — `{runTimestamp, taskType, phases:[{phase, firstAt, wallMsToNext}]}`
|
|
363
|
-
- `unavailable[]` — `{runTimestamp, taskType, reason}` for runs with no Phase-7 durations (never summed into totals)
|
|
364
|
-
|
|
365
|
-
### time.3 — Render
|
|
366
|
-
|
|
367
|
-
Convert every `*Ms` to `HH:MM:SS` (zero-pad; never show raw ms). Task types in `byTaskType` are already in chronological (first-appearance) order.
|
|
368
|
-
|
|
369
|
-
- **By task type** — `| Task type | Runs | CPU sum | Lead | Workers |` from `byTaskType`, plus a `grandTotal` row. `CPU sum` (= Lead + Workers) overlaps because workers run inside the lead's window — it is *not* wall-clock. Surface wall-clock only when the user explicitly asks, from `perRunWallClock`.
|
|
370
|
-
- **Per worker** (per task type) — `| Worker | Runs | Total | Avg/run |` from `perWorker`. Render the worker as bare `workerId` when `agents` is empty, else `workerId (agent1, agent2)`.
|
|
371
|
-
- **Phase breakdown** — "단계별"/"stage별"/"어느 단계가 오래" in okstra most often means the **lifecycle stage (task-type)** view, which the *By task type* table above already answers — lead with that table, do not treat the request as unanswerable. Render the intra-run phase timeline only when the user clearly means within-a-run phases ("어느 phase가", "Phase 1~7", "phase timeline"): one table per run from `phaseTimelines`: `| Phase | Start | Wall to next |` using `firstAt`/`wallMsToNext` (`null` → `--`). When `phaseTimelines` is empty, do **not** headline "측정 불가" — the By-task-type table is the stage answer; mention the missing intra-run markers only as a trailing footnote.
|
|
372
|
-
- If `unavailable[]` is non-empty, append a trailing note listing each run with its reason. Never fold them into totals.
|
|
373
|
-
- Show the resolved `<task-key>` in the heading.
|
|
374
|
-
|
|
375
|
-
```markdown
|
|
376
|
-
## Time summary — <task-key>
|
|
377
|
-
|
|
378
|
-
### By task type
|
|
379
|
-
|
|
380
|
-
| Task type | Runs | CPU sum | Lead | Workers |
|
|
381
|
-
|------------------------|------|-----------|----------|----------|
|
|
382
|
-
| requirements-discovery | 2 | 00:33:12 | 00:12:08 | 00:21:04 |
|
|
383
|
-
| **Grand total** | 6 | **03:03:06** | 01:05:49 | 01:57:17 |
|
|
384
|
-
|
|
385
|
-
### Per worker — requirements-discovery
|
|
386
|
-
|
|
387
|
-
| Worker | Runs | Total | Avg/run |
|
|
388
|
-
|----------------------|------|----------|----------|
|
|
389
|
-
| lead | 2 | 00:12:08 | 00:06:04 |
|
|
390
|
-
| claude (sonnet-eval) | 2 | 00:09:12 | 00:04:36 |
|
|
391
|
-
|
|
392
|
-
> Unavailable: 1 run (implementation / 2026-04-30_03-03-48) — Phase 7 not reached
|
|
393
|
-
```
|
|
394
|
-
|
|
395
|
-
---
|
|
396
|
-
|
|
397
|
-
## cost
|
|
398
|
-
|
|
399
|
-
Trigger phrases: "okstra context-cost", "context cost", "context-cost", "컨텍스트 비용", "읽기 비용", "산출물 비용", "task bundle cost", "agent read cost".
|
|
400
|
-
|
|
401
|
-
Read-only estimate of how much file/context surface a prepared task bundle asks the lead, analysis workers, and report-writer to absorb. This sub-command does **not** mutate task artifacts.
|
|
402
|
-
|
|
403
|
-
### cost.1 — Resolve target
|
|
49
|
+
## Step 1: Dispatch by intent
|
|
404
50
|
|
|
405
|
-
|
|
51
|
+
Classify the user's request into one sub-command using the trigger table above. If ambiguous (e.g. "show me okstra"), ask which facet — do not silently default. After routing, **Read the chosen row's facet file** (path relative to this skill's base directory) and follow it for the rest of the response. Load exactly one facet per sub-command — never preload the others.
|
|
406
52
|
|
|
407
|
-
|
|
408
|
-
2. Bare token — a task-id (e.g. `DEV-9184`) **or** a task-group (e.g. `PROD`).
|
|
409
|
-
3. Task root path, e.g. `<projectRoot>/.okstra/tasks/<group>/<task-id>`.
|
|
53
|
+
When you ask which facet, the option list is **authoritative**: enumerate every sub-command in the dispatch table above as a numbered text list, in table order, each with its one-line description, and let the user pick by number or name. Never present a hand-picked subset — the AskUserQuestion 4-option cap is not a reason to drop facets; render the full menu as text in the question body so no facet (e.g. a newly added one) is ever hidden. The table is the single source of truth for this menu; adding a row there (plus its facet file) is all it takes for the facet to appear here.
|
|
410
54
|
|
|
411
|
-
|
|
55
|
+
When the user chains multiple facets in one message (e.g. "status, and then time for DEV-9047"), execute them sequentially — Step 0 runs once, then load and run each facet in turn.
|
|
412
56
|
|
|
413
|
-
|
|
57
|
+
## Shared rules (referenced by facets)
|
|
414
58
|
|
|
415
|
-
|
|
416
|
-
okstra context-cost <task-key> --project-root <projectRoot>
|
|
417
|
-
```
|
|
59
|
+
### Standard task-key resolution (0/1/N)
|
|
418
60
|
|
|
419
|
-
|
|
61
|
+
Facets that accept a bare token (a task-id like `DEV-9184` **or** a task-group like `PROD`) resolve it with the shared resolver (SSOT — `scripts/okstra_ctl/resolve_task_key.py` / `okstra_project.resolve_task_reference`). The resolver matches the token as a task-id **and** as a task-group, unioning both (a group expands to its member tasks); each entry carries `_matchedVia` (`"taskId"` | `"taskGroup"`):
|
|
420
62
|
|
|
421
63
|
```bash
|
|
422
64
|
okstra resolve-task-key <token> --project-root <projectRoot> --json
|
|
423
65
|
```
|
|
424
66
|
|
|
425
|
-
Branch on the stdout JSON `matches[]
|
|
426
|
-
- **0
|
|
427
|
-
- **1
|
|
428
|
-
- **N
|
|
67
|
+
Branch on the stdout JSON `matches[]`:
|
|
68
|
+
- **0** → report the task cannot be found. Do not guess.
|
|
69
|
+
- **1** → use that entry's `taskKey`.
|
|
70
|
+
- **N** → list the candidate `taskKey`s (with `updatedAt`, and `_matchedVia` so the user sees which came from a task-id vs a task-group) and ask via a 3-option picker (1–2 recommendations + `Enter directly`), then use the chosen `taskKey`.
|
|
429
71
|
|
|
430
|
-
|
|
72
|
+
### No-task fallback
|
|
73
|
+
|
|
74
|
+
When a facet needs a task but the user did not name one:
|
|
431
75
|
|
|
432
76
|
1. Read `.okstra/discovery/task-catalog.json`.
|
|
433
77
|
2. If exactly one task exists, use it.
|
|
434
|
-
3. If multiple tasks exist, show the latest 10 by `updatedAt` and ask which
|
|
435
|
-
|
|
436
|
-
### cost.2 — Run estimator
|
|
437
|
-
|
|
438
|
-
Use the CLI output as the source of truth:
|
|
439
|
-
|
|
440
|
-
```bash
|
|
441
|
-
okstra context-cost <resolved-target> --project-root <projectRoot>
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
Do not re-count files manually unless the CLI fails and the user explicitly asks for manual fallback.
|
|
445
|
-
|
|
446
|
-
### cost.3 — Render
|
|
447
|
-
|
|
448
|
-
Render the CLI JSON into the cost.4 template. Each row's Files / Size / ~Tokens come from the matching output block — `totals` (Task bundle, Current run, Legacy timestamp), `instructionSet`, `leadPhase1`, `analysisWorker`, `reportWriter`, `skillAssets`; their exact field names are in the CLI output (do not re-list them here). Format bytes as raw + rounded KB/MB.
|
|
449
|
-
|
|
450
|
-
Field-specific notes (these affect interpretation, not just display):
|
|
451
|
-
- Analysis worker uses per-worker fields (`bytesPerWorker`, `estimatedTokensPerWorker`). Use `analysisWorker.estimatedReductionPercent` directly for the worker-input reduction — do **not** recompute it from `bytesPerWorker` when `mode == "analysis-packet-primary"` (that value is already the packet-primary cost).
|
|
452
|
-
- `estimatedTokens*` are a static ranking heuristic (~4 ASCII chars/token, non-ASCII ≈ 1 token/char), never billing numbers — actual cost is the token-usage collector's domain.
|
|
453
|
-
- `skillAssets` = the per-run hot-path instruction assets loaded OUTSIDE the task bundle (skill bodies + agent specs), sorted by size — the prompt-diet target.
|
|
454
|
-
|
|
455
|
-
### cost.4 — Output template
|
|
456
|
-
|
|
457
|
-
```markdown
|
|
458
|
-
## okstra Context Cost — <task-key>
|
|
459
|
-
|
|
460
|
-
| Surface | Files | Size | ~Tokens |
|
|
461
|
-
|---|---:|---:|---:|
|
|
462
|
-
| Task bundle | <N> | <bytes> (<human>) | - |
|
|
463
|
-
| Current run | <N> | <bytes> (<human>) | - |
|
|
464
|
-
| Instruction set | <N> | <bytes> (<human>) | <estimatedTokens> |
|
|
465
|
-
| Lead Phase 1 (`<mode>`) | <N> | <bytes> (<human>) | <estimatedTokens> |
|
|
466
|
-
| Analysis worker / worker (`<mode>`) | <N> | <bytes> (<human>) | <estimatedTokensPerWorker> |
|
|
467
|
-
| Report writer synthesis | <N> | <bytes> (<human>) | <estimatedTokens> |
|
|
468
|
-
| Skill assets (hot path) | <N> | <bytes> (<human>) | <estimatedTokens> |
|
|
469
|
-
|
|
470
|
-
- Current run: `<currentRunPath-or-->`
|
|
471
|
-
- Legacy timestamp artifacts: `<N>`
|
|
472
|
-
- Legacy full worker contract: `<legacyFullContractBytesPerWorker>` bytes (`<human>`) per analysis worker
|
|
473
|
-
- Packet estimate: `<estimatedPacketModeBytesPerWorker>` bytes (`<human>`) per analysis worker
|
|
474
|
-
- Estimated worker-input reduction: `<percent>%`
|
|
475
|
-
|
|
476
|
-
### Reading
|
|
477
|
-
|
|
478
|
-
<One or two Korean sentences explaining the main bottleneck and the next likely optimization target.>
|
|
479
|
-
```
|
|
480
|
-
|
|
481
|
-
Interpretation rules:
|
|
482
|
-
|
|
483
|
-
- `leadPhase1.mode == "active-run-context"` means the compact lead intake file is present and should be treated as the primary lead read surface.
|
|
484
|
-
- `leadPhase1.mode == "legacy-five-file"` means this task was prepared before active-run-context, or the manifest does not reference it.
|
|
485
|
-
- `analysisWorker.mode == "analysis-packet-primary"` means new workers should read `analysis-packet.md` first and open full source inputs only for evidence checks or missing detail.
|
|
486
|
-
- If `analysisWorker.mode == "full-input-contract"` and `estimatedReductionPercent` is low, the next target is worker prompt/input contract slimming.
|
|
487
|
-
- If `reportWriter.bytes` dominates, the next target is a compact `synthesis-input` artifact.
|
|
488
|
-
- If `skillAssets.estimatedTokens` dominates the per-run fixed cost, the next target is slimming the largest `skillAssets.files[]` entries (prompt diet — perf plan v2 P2), e.g. thin-core + lazy-sidecar split.
|
|
489
|
-
- If `legacyTimestampFileCount` is high, recommend current-view/cold-artifact separation or retention cleanup, not destructive deletion by default.
|
|
490
|
-
|
|
491
|
-
---
|
|
492
|
-
|
|
493
|
-
## logs
|
|
494
|
-
|
|
495
|
-
Trigger phrases: "okstra logs", "로그 현황", "로그 파일", "log files", "log size", "log status", "로그 정리", "log cleanup".
|
|
496
|
-
|
|
497
|
-
Read-only inventory of codex/antigravity wrapper log files written next to each prompt history file (`<prompt>.log`). Reports sizes, ages, totals, and suggests cleanup commands. **Does not delete** — the user runs whichever `find … -delete` line they like.
|
|
498
|
-
|
|
499
|
-
**Background:** codex/antigravity wrappers (`okstra-codex-exec.sh`, `okstra-antigravity-exec.sh`) write a sidecar log next to each prompt history file:
|
|
500
|
-
|
|
501
|
-
```
|
|
502
|
-
.okstra/tasks/<task-group>/<task-id>/runs/<phase>/prompts/
|
|
503
|
-
<worker>-worker-prompt-<phase>-<seq>.md <-- prompt (git-tracked)
|
|
504
|
-
<worker>-worker-prompt-<phase>-<seq>.log <-- live stdout+stderr mirror
|
|
505
|
-
```
|
|
506
|
-
|
|
507
|
-
The log is truncated at each dispatch (`: > "$log_path"`) — only the latest run for a given seq is preserved. Different seqs keep separate files. Long-running implementation dispatches can produce multi-MB logs; analysis-phase dispatches are typically smaller.
|
|
508
|
-
|
|
509
|
-
### logs.1 — Inventory
|
|
510
|
-
|
|
511
|
-
```bash
|
|
512
|
-
okstra log-report --project-root <projectRoot> --json
|
|
513
|
-
```
|
|
514
|
-
|
|
515
|
-
Scans `<projectRoot>/.okstra/tasks/**/runs/*/prompts/*.log` and parses task/phase/worker/seq from each path. Returns (sizes are **raw bytes**, mtimes **epoch seconds**):
|
|
516
|
-
- `topLargest[]` — `{path, sizeBytes, mtimeEpoch, taskKey, taskGroup, taskId, phase, worker, seq}`, size desc (widen with `--top <N>`)
|
|
517
|
-
- `perTask[]` — `{taskKey, fileCount, totalBytes, oldestEpoch, newestEpoch}`, total-size desc
|
|
518
|
-
- `totals` — `{fileCount, totalBytes, taskCount}`
|
|
519
|
-
|
|
520
|
-
If `totals.fileCount` is 0, report `No wrapper log files found under <projectRoot>` and stop.
|
|
521
|
-
|
|
522
|
-
### logs.2 — Summary tables
|
|
523
|
-
|
|
524
|
-
Render from the CLI output (format bytes → KB/MB; epoch → `Nd`/`Nh` relative to now):
|
|
525
|
-
|
|
526
|
-
**Table A — Top largest logs** (from `topLargest`): `| # | Task | Phase | Worker | Seq | Size | Age | Path |`.
|
|
527
|
-
|
|
528
|
-
**Table B — Per-task totals** (from `perTask`): `| Task Key | Files | Total Size | Oldest | Newest |`.
|
|
529
|
-
|
|
530
|
-
**Footer:** `Total: <fileCount> files, <totalBytes→MB> across <taskCount> tasks under <PROJECT_ROOT>`.
|
|
531
|
-
|
|
532
|
-
### logs.3 — Suggested cleanup commands
|
|
533
|
-
|
|
534
|
-
Emit a fenced bash block the user can copy-paste. Do NOT execute. Each block pairs a dry-run preview (`-print`) with the destructive (`-delete`) command:
|
|
535
|
-
|
|
536
|
-
```markdown
|
|
537
|
-
## Cleanup options (manual)
|
|
538
|
-
|
|
539
|
-
# 7일 이상 된 로그만 삭제
|
|
540
|
-
find <PROJECT_ROOT>/.okstra/tasks \
|
|
541
|
-
-type f -path '*/runs/*/prompts/*.log' -mtime +7 -print # dry-run
|
|
542
|
-
find <PROJECT_ROOT>/.okstra/tasks \
|
|
543
|
-
-type f -path '*/runs/*/prompts/*.log' -mtime +7 -delete
|
|
544
|
-
|
|
545
|
-
# 30일 이상 된 로그만 삭제
|
|
546
|
-
find <PROJECT_ROOT>/.okstra/tasks \
|
|
547
|
-
-type f -path '*/runs/*/prompts/*.log' -mtime +30 -print # dry-run
|
|
548
|
-
find <PROJECT_ROOT>/.okstra/tasks \
|
|
549
|
-
-type f -path '*/runs/*/prompts/*.log' -mtime +30 -delete
|
|
550
|
-
|
|
551
|
-
# 특정 task-group 의 로그 일괄 삭제 (예: dev-9388)
|
|
552
|
-
find <PROJECT_ROOT>/.okstra/tasks/dev-9388 \
|
|
553
|
-
-type f -name '*.log' -print # dry-run
|
|
554
|
-
find <PROJECT_ROOT>/.okstra/tasks/dev-9388 \
|
|
555
|
-
-type f -name '*.log' -delete
|
|
556
|
-
|
|
557
|
-
# 특정 task-id 의 로그 일괄 삭제 (예: dev-9428)
|
|
558
|
-
find <PROJECT_ROOT>/.okstra/tasks/*/dev-9428 \
|
|
559
|
-
-type f -name '*.log' -print # dry-run
|
|
560
|
-
find <PROJECT_ROOT>/.okstra/tasks/*/dev-9428 \
|
|
561
|
-
-type f -name '*.log' -delete
|
|
562
|
-
|
|
563
|
-
# 전체 일괄 삭제 (주의)
|
|
564
|
-
find <PROJECT_ROOT>/.okstra/tasks \
|
|
565
|
-
-type f -path '*/runs/*/prompts/*.log' -print # dry-run
|
|
566
|
-
find <PROJECT_ROOT>/.okstra/tasks \
|
|
567
|
-
-type f -path '*/runs/*/prompts/*.log' -delete
|
|
568
|
-
```
|
|
569
|
-
|
|
570
|
-
Substitute the literal `<PROJECT_ROOT>` with the resolved absolute path so the commands are directly copy-pasteable.
|
|
571
|
-
|
|
572
|
-
### logs.4 — Notes for the user
|
|
573
|
-
|
|
574
|
-
- Logs are truncated on each re-dispatch of the same `seq`, so deleting an in-flight run's log will cause the wrapper to recreate an empty file on the next dispatch — no data loss beyond the current trace.
|
|
575
|
-
- **If a dispatch is currently running, check the `status` sub-command first** and avoid deleting logs for tasks in `in-progress` state — you will lose the live trace for the active run.
|
|
576
|
-
- Prompt history files (`.md`) are separate and are NOT touched by these commands — only `.log` sidecars.
|
|
577
|
-
- This sub-command **does not modify any external files itself**, including `.gitignore`. If the project commits `.okstra/`, the user may want to add `.okstra/tasks/**/runs/**/prompts/*.log` to `.gitignore` manually to keep large logs out of git.
|
|
578
|
-
|
|
579
|
-
---
|
|
580
|
-
|
|
581
|
-
## errors
|
|
582
|
-
|
|
583
|
-
Trigger phrases: "okstra errors", "error report", "에러 리포트", "에러 보고", "에러 모아줘", "실패 로그 정리".
|
|
584
|
-
|
|
585
|
-
Aggregate a task's okstra-run error logs (`runs/*/logs/errors-*.jsonl`, lead-observed + worker-reported) into a timestamped markdown report and summarize it. This sub-command renders a **read-derived artifact** (a `.md` file) but never mutates task state (`task-manifest.json`, catalog, timeline).
|
|
586
|
-
|
|
587
|
-
### errors.1 — Resolve target
|
|
588
|
-
|
|
589
|
-
Accepted target forms (same as `cost`):
|
|
590
|
-
|
|
591
|
-
1. Full task-key: `<project-id>:<task-group>:<task-id>`.
|
|
592
|
-
2. Bare token (task-id or task-group) — resolve via `okstra resolve-task-key <token> --project-root <projectRoot> --json` and branch on `matches[]` using the standard 0/1/N rule from `cost.1` (0 = not found, 1 = use, N = picker).
|
|
593
|
-
3. Task root path.
|
|
594
|
-
|
|
595
|
-
사용자가 task 를 지정하지 않고 그냥 에러 리포트를 요청하면, `cost.1` 과 동일한 no-task fallback 을 적용한다 — 플레이스홀더 형식만 나열하고 되묻지 않는다: `.okstra/discovery/task-catalog.json` 을 읽어 task 가 1개면 그대로 사용하고, 여러 개면 `updatedAt` 최신 10개를 실제 task-key 로 나열해 물어본다(추측 금지).
|
|
596
|
-
|
|
597
|
-
### errors.2 — Run the renderer
|
|
598
|
-
|
|
599
|
-
Use the CLI output as the source of truth:
|
|
600
|
-
|
|
601
|
-
```bash
|
|
602
|
-
okstra error-report <resolved-target> --project-root <projectRoot>
|
|
603
|
-
```
|
|
604
|
-
|
|
605
|
-
For a task-root path, run `okstra error-report <path>` directly. Do not parse the jsonl files by hand unless the CLI fails and the user explicitly asks for a manual fallback.
|
|
606
|
-
|
|
607
|
-
### errors.3 — Summarize output
|
|
608
|
-
|
|
609
|
-
Parse the stdout JSON and report:
|
|
610
|
-
|
|
611
|
-
| Field | Source |
|
|
612
|
-
|---|---|
|
|
613
|
-
| Report file | `reportPath` (project-root-relative `.md`) |
|
|
614
|
-
| Total errors | `totals.errorCount` |
|
|
615
|
-
| Logs (runs) | `totals.runCount` |
|
|
616
|
-
| By errorType | `totals.byErrorType` (tool-failure / cli-failure / contract-violation) |
|
|
617
|
-
| By source | `totals.bySource` (lead-observed / worker-reported) |
|
|
618
|
-
| By phase | `byPhase[]` |
|
|
619
|
-
| By agent | `byAgent[]` |
|
|
620
|
-
| Parse-skipped lines | `parseSkipped` |
|
|
621
|
-
|
|
622
|
-
- If `reportPath` is empty AND `totals.errorCount == 0`: report `이 task 에는 기록된 에러 로그가 없습니다.` and do not claim a file was written.
|
|
623
|
-
- Otherwise show the `.md` path and offer to read it.
|
|
624
|
-
- If `parseSkipped > 0`, surface it (do not silently hide malformed lines).
|
|
625
|
-
|
|
626
|
-
### errors — Output template
|
|
627
|
-
|
|
628
|
-
```markdown
|
|
629
|
-
## okstra Error Report — <task-key>
|
|
630
|
-
|
|
631
|
-
- Report: `<reportPath-or-->`
|
|
632
|
-
- Total errors: <N> across <runCount> log(s)
|
|
633
|
-
- By type: <tool-failure: a, cli-failure: b, ...>
|
|
634
|
-
- By source: <lead-observed: x, worker-reported: y>
|
|
635
|
-
|
|
636
|
-
| Phase | Count |
|
|
637
|
-
|---|---:|
|
|
638
|
-
| implementation | 3 |
|
|
639
|
-
|
|
640
|
-
| Agent | Count |
|
|
641
|
-
|---|---:|
|
|
642
|
-
| codex-worker | 2 |
|
|
643
|
-
|
|
644
|
-
<If parseSkipped > 0: "⚠ 파싱 건너뛴 줄: <N>">
|
|
645
|
-
```
|
|
646
|
-
|
|
647
|
-
---
|
|
648
|
-
|
|
649
|
-
## error-zip
|
|
650
|
-
|
|
651
|
-
Trigger phrases: "okstra error-zip", "에러 zip", "에러 환류", "에러 번들", "cross-project 에러".
|
|
652
|
-
|
|
653
|
-
머신 내 모든 타겟 프로젝트의 okstra 실행 에러(`runs/*/logs/errors-*.jsonl`)를 글로벌 run-index 로 수집·익명화해 `.zip`(집계 리포트 + 익명화 JSONL)으로 묶는다. 모든 타겟의 `.okstra/` 에 대해 read-only.
|
|
654
|
-
|
|
655
|
-
### error-zip.1 — 출력 경로 결정 (picker)
|
|
656
|
-
|
|
657
|
-
이전 출력 경로를 `~/.okstra/error-zip.json` 의 `lastOutputPath` 에서 읽는다. 그 값이 있으면 3-옵션 picker 로 제시:
|
|
658
|
-
|
|
659
|
-
1. (이전 경로 있음) `<lastOutputPath>` 재사용 — 추천, 첫 옵션.
|
|
660
|
-
(이전 경로 없음) 기본 경로 `~/okstra-error-feedback-<YYYY-MM-DD>.zip` 제안 — 추천.
|
|
661
|
-
2. 직접 입력 (항상 마지막 옵션).
|
|
662
|
-
|
|
663
|
-
`~/.okstra/error-zip.json` 읽기는 Read 로 직접 수행한다(없으면 이전 경로 없음으로 간주).
|
|
664
|
-
|
|
665
|
-
### error-zip.2 — 렌더 실행
|
|
666
|
-
|
|
667
|
-
```bash
|
|
668
|
-
okstra error-zip --out <결정된 경로>
|
|
669
|
-
```
|
|
670
|
-
|
|
671
|
-
### error-zip.3 — 요약 보고
|
|
672
|
-
|
|
673
|
-
stdout JSON 을 파싱해 보고:
|
|
674
|
-
|
|
675
|
-
| 필드 | 출처 |
|
|
676
|
-
|---|---|
|
|
677
|
-
| 출력 zip | `outPath` |
|
|
678
|
-
| 총 에러 | `errorCount` |
|
|
679
|
-
| 로그(run) | `runCount` |
|
|
680
|
-
| 도달 불가 run | `unreachableRuns` |
|
|
681
|
-
| 클러스터 수 | `clusterCount` |
|
|
682
|
-
| 프로젝트 수 | `projectCount` |
|
|
683
|
-
|
|
684
|
-
- `unreachableRuns > 0` 이면 표면화한다(침묵 누락 금지).
|
|
685
|
-
- 끝에 다음 단계를 안내한다: "이 zip 으로 okstra 자신을 고치려면 `/okstra-brief-gen` 의 error-feedback variant 로 brief 를 만든 뒤 `okstra-run --task-type error-analysis` 를 okstra 레포에서 실행하세요."
|
|
686
|
-
|
|
687
|
-
---
|
|
688
|
-
|
|
689
|
-
## recap
|
|
690
|
-
|
|
691
|
-
Trigger phrases: "okstra recap", "recap", "작업 요약", "이 task 요약", "전후 요약", "이 작업 설명해줘", "task 질문".
|
|
692
|
-
|
|
693
|
-
task-id 하나에 쌓인 `.okstra` 산출물 위에서 (a) 처리 전/후 요약을 내고, (b) 그 작업에 대한 자유 질문에 답한다. 기본은 `.okstra/` 서브트리만 읽는다(artifact 모드). 사용자가 명시적으로 코드 변경까지 봐 달라고 요청할 때만 code 모드로 확장한다. 이 sub-command 는 `recap/recap-log.jsonl` append 와 `notes/` 노트 작성(recap.5)만 수행하고 `task-manifest.json` / catalog / timeline 은 절대 mutate 하지 않는다.
|
|
694
|
-
|
|
695
|
-
### recap.1 — Resolve target
|
|
696
|
-
|
|
697
|
-
`cost` / `errors` 와 동일한 3형식: ① full task-key, ② bare token(task-id 또는 task-group → `okstra resolve-task-key <token> --project-root <projectRoot> --json`; `cost.1` 의 표준 0/1/N 분기), ③ task-root path.
|
|
698
|
-
|
|
699
|
-
사용자가 task 를 지정하지 않고 그냥 recap 을 요청하면(예: "이 작업 요약해줘"), `cost.1` 과 동일한 no-task fallback 을 적용한다 — 절대 `<task-group>` 같은 플레이스홀더 형식만 나열하고 되묻지 않는다:
|
|
700
|
-
|
|
701
|
-
1. `.okstra/discovery/task-catalog.json` 을 읽는다.
|
|
702
|
-
2. task 가 정확히 1개면 그 task 를 그대로 사용한다.
|
|
703
|
-
3. 여러 개면 `updatedAt` 최신 10개를 실제 task-key 로 나열하고 어느 task 인지 물어본다(추측 금지).
|
|
704
|
-
|
|
705
|
-
### recap.2 — Assemble the before/after summary
|
|
706
|
-
|
|
707
|
-
CLI 출력을 source of truth 로 쓴다:
|
|
708
|
-
|
|
709
|
-
```bash
|
|
710
|
-
okstra recap assemble <resolved-target> --project-root <projectRoot>
|
|
711
|
-
```
|
|
712
|
-
|
|
713
|
-
stdout JSON(`{taskKey, runCount, transitions[], latestPhaseStates}`)을 파싱해 run 단위 전/후 전이를 서술한다. 각 `transitions[]` 항목의 `fromPhase → toPhase`(직전 run currentPhase → 이번 run currentPhase), `status`, `lastCompletedPhase`, `nextRecommendedPhase`, `reportPath` 를 시간순으로 보여준다. `runCount == 0` 이면 "이 task 에는 기록된 run 이 없습니다." 라고만 답하고 파일을 읽었다고 주장하지 않는다.
|
|
714
|
-
|
|
715
|
-
`reportPath` 가 있는 run 은 사용자가 더 깊은 요약을 원할 때만 해당 final-report 를 읽어 보강한다(자동으로 모두 읽지 않는다).
|
|
716
|
-
|
|
717
|
-
### recap.3 — Free-form Q&A loop
|
|
718
|
-
|
|
719
|
-
요약 출력 뒤 사용자의 임의 질문을 받는다.
|
|
720
|
-
|
|
721
|
-
- **artifact 모드(기본)**: `.okstra/` 산출물(timeline, task-manifest, 해당 run 의 final-report)만 근거로 답한다. 모든 사실 주장은 `.okstra` 파일 `path:line` 인용을 동반한다.
|
|
722
|
-
- **code 모드(opt-in)**: 사용자가 "코드 변경까지 / diff 까지 봐줘" 류로 **명시적으로 요청**할 때만, 해당 task 의 worktree/브랜치에서 `git diff` · `git log` 를 추가로 읽어 코드 레벨로 답한다. recap 진입만으로는 절대 code 모드로 넘어가지 않는다.
|
|
723
|
-
|
|
724
|
-
### recap.4 — Persist each turn
|
|
725
|
-
|
|
726
|
-
요약 1건과 각 Q&A 답변을 로그에 남긴다(append-only):
|
|
727
|
-
|
|
728
|
-
```bash
|
|
729
|
-
okstra recap record <resolved-target> --project-root <projectRoot> \
|
|
730
|
-
--kind <summary|qa> --mode <artifact|code> \
|
|
731
|
-
--question "<질문 또는 생략>" --answer "<한두 줄 요약>" \
|
|
732
|
-
--citation "<path:line>" --citation "<path:line>"
|
|
733
|
-
```
|
|
734
|
-
|
|
735
|
-
`--answer` 에는 전체 답변 전사가 아니라 한두 줄 요약을 넣는다. 인용이 여러 개면 `--citation` 을 반복한다. 기록 실패(비정상 종료)는 조용히 넘기지 말고 사용자에게 알린다.
|
|
736
|
-
|
|
737
|
-
### recap — Output template
|
|
738
|
-
|
|
739
|
-
```markdown
|
|
740
|
-
## okstra Recap — <task-key>
|
|
741
|
-
|
|
742
|
-
전/후 요약 (runs: <N>):
|
|
743
|
-
|
|
744
|
-
| # | when | task-type | from → to | status | next |
|
|
745
|
-
|---|---|---|---|---|---|
|
|
746
|
-
| 1 | <ts> | requirements-discovery | (시작) → requirements-discovery | done | error-analysis |
|
|
747
|
-
|
|
748
|
-
<이후 자유 질문을 받습니다. 코드 변경까지 보려면 "diff 까지 봐줘" 라고 요청하세요.>
|
|
749
|
-
```
|
|
750
|
-
|
|
751
|
-
### recap.5 — Agent 저작 노트 (`notes/`)
|
|
752
|
-
|
|
753
|
-
recap 중에 네가 **okstra task 를 위해** 만든 산출물 — 검증 증거, 설계·decision 초안, 분석 노트 — 이 앞으로의 run 에 근거로 쓰일 수 있고, 그 내용이 **렌더된 report 도 아니고 사용자 결정도 아닐 때**만 `notes/` 에 남긴다.
|
|
754
|
-
|
|
755
|
-
**소유권으로 라우팅한다.** 지금 쓰려는 것이 아래 어디에 해당하는지 먼저 판별한다:
|
|
756
|
-
|
|
757
|
-
| 내용 | 레인(경로) | 저작 주체 |
|
|
758
|
-
|---|---|---|
|
|
759
|
-
| final report 본문 | `runs/<type>/reports/*.md` (`*.data.json` 에서 렌더) | okstra 렌더러 — 절대 수기 편집 금지 |
|
|
760
|
-
| clarification 에 대한 사용자 답변 | `runs/<type>/user-responses/*.md` (`created-by: user`) | 사용자만 |
|
|
761
|
-
| 확정된 ADR | `.okstra/decisions/NNNN-*.md` | 승격·관리됨 |
|
|
762
|
-
| **Agent 증거 / 설계 초안 / 분석** | **`.okstra/tasks/<group>/<id>/notes/`** | 너(AI) |
|
|
763
|
-
|
|
764
|
-
렌더 산출물도, 사용자 결정도 아닌 **너 자신의 근거·초안**이면 `notes/` 로 간다. 노트는 손으로 찍지 말고 CLI 로 쓴다 — 경로·frontmatter·날짜를 코드가 보장하고, 다음 run 에 넘길 인자를 출력해 준다:
|
|
765
|
-
|
|
766
|
-
```bash
|
|
767
|
-
okstra recap note <resolved-target> --project-root <projectRoot> \
|
|
768
|
-
--kind <verification-evidence|decision-draft|analysis-note> \
|
|
769
|
-
--slug <short-topic-slug> \
|
|
770
|
-
--purpose "<한 줄 — 무엇이며 어느 run/decision 에 투입되는지>" \
|
|
771
|
-
--scope-note "<한 줄 — 무엇이 아닌지, 예: C-00x 에 대한 사용자 결정이 아님>" \
|
|
772
|
-
--body-file <노트 본문 마크다운 경로>
|
|
773
|
-
```
|
|
774
|
-
|
|
775
|
-
본문은 먼저 scratchpad 에 마크다운으로 쓴 뒤 `--body-file` 로 넘긴다(짧으면 `--body "<md>"` 인라인도 가능). CLI 는 `.okstra/tasks/<group>/<id>/notes/<slug>-<YYYY-MM-DD>.md` 를 생성하고 stdout JSON 으로 `notePath` 와 `clarificationResponseArg` 를 돌려준다.
|
|
776
|
-
|
|
777
|
-
**self-check 규칙 (validator 가 없으니 스스로 지킨다):**
|
|
778
|
-
|
|
779
|
-
1. **렌더된 report 를 수기 편집하지 않는다** (`runs/*/reports/` 아래 `*.md` / `*.data.json` / `*.html`). `data.json` 에서 재생성되므로 편집은 덮어써지고 SSOT 와 어긋난다. 발견 내용은 `notes/` 에 쓴다.
|
|
780
|
-
2. **`user-responses/` 파일을 작성하거나 `created-by: user` 를 달지 않는다.** 그건 사용자의 결정이며, 대신 쓰면 사용자가 내리지 않은 결정을 위조하는 것이다. 네 증거가 특정 답을 뒷받침하면 `notes/` 에 그렇게 적고 결정은 사용자에게 맡긴다. 단, `okstra-user-response` 스킬의 에코백 확인 흐름은 예외다 — 그 흐름에서는 사용자가 세션에서 직접 결정을 내리고 CLI 는 전사 채널일 뿐이므로, `write` 로 `created-by: user` sidecar 를 기록하는 것이 정당하다. 이 예외는 사용자가 명시적으로 "맞음" 을 확인한 뒤에만, verbatim 입력에 대해서만 성립한다.
|
|
781
|
-
3. **okstra 관리 디렉토리에 쓰지 않는다** (`runs/`, `instruction-set/`, `history/`, `recap/`, `.okstra/decisions/`). `notes/` 만이 agent 소유 레인이다. `recap/recap-log.jsonl` 은 예외적으로 쓰되 손으로 편집하지 말고 `okstra recap record` CLI 로만 남긴다.
|
|
782
|
-
4. **`notes/` 는 okstra 에 inert 하다** — 어떤 run 도 자동으로 읽지 않는다. 작성 후 CLI 가 출력한 `clarificationResponseArg`(예: `--clarification-response <notePath>`)를 사용자에게 그대로 알려, 다음 run 을 그 인자와 함께 실행해야만 반영된다는 것을 전한다.
|
|
783
|
-
|
|
784
|
-
**Guardrail:** `.okstra/` 는 gitignored 다 — `notes/` 는 로컬 scratch 로 취급하고 절대 `git add` 하지 않는다. 새 노트 생성은 되돌리기 쉬우니(파일 삭제), 생성물이나 사용자 소유 파일을 편집하는 것보다 항상 이쪽을 택한다.
|
|
785
|
-
|
|
786
|
-
---
|
|
78
|
+
3. If multiple tasks exist, show the latest 10 by `updatedAt` as real task-keys and ask which one. Do not guess, and do not answer with placeholder forms only.
|
|
787
79
|
|
|
788
80
|
## Output Rules (shared)
|
|
789
81
|
|