okstra 0.111.0 → 0.112.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.kr.md +2 -2
- package/README.md +2 -2
- package/bin/okstra +7 -1
- package/docs/for-ai/README.md +2 -2
- package/docs/for-ai/skills/okstra-brief.md +2 -3
- package/docs/for-ai/skills/okstra-container-build.md +2 -3
- package/docs/for-ai/skills/okstra-inspect.md +5 -12
- package/docs/for-ai/skills/okstra-rollup.md +3 -4
- package/docs/for-ai/skills/okstra-run.md +3 -5
- package/docs/for-ai/skills/okstra-schedule.md +2 -7
- package/docs/for-ai/skills/okstra-setup.md +1 -1
- package/docs/kr/architecture/storage-model.md +1 -2
- package/docs/kr/architecture.md +2 -2
- package/docs/kr/cli.md +4 -2
- package/docs/project-structure-overview.md +5 -3
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/prompts/coding-preflight/overview.md +3 -1
- package/runtime/prompts/launch.template.md +1 -5
- package/runtime/prompts/lead/context-loader.md +2 -4
- package/runtime/prompts/lead/convergence.md +11 -240
- package/runtime/prompts/lead/okstra-lead-contract.md +70 -34
- package/runtime/prompts/lead/plan-body-verification.md +240 -0
- package/runtime/prompts/lead/report-writer.md +7 -7
- package/runtime/prompts/lead/team-contract.md +15 -17
- package/runtime/prompts/profiles/_common-contract.md +1 -37
- package/runtime/prompts/profiles/_implementation-executor.md +2 -2
- package/runtime/prompts/profiles/_implementation-verifier.md +1 -1
- package/runtime/prompts/profiles/final-verification.md +1 -1
- package/runtime/prompts/profiles/implementation-planning.md +2 -2
- package/runtime/prompts/profiles/implementation.md +1 -1
- package/runtime/python/okstra_ctl/path_hints.py +1 -0
- package/runtime/python/okstra_ctl/paths.py +3 -0
- package/runtime/python/okstra_ctl/render.py +8 -0
- package/runtime/python/okstra_ctl/set_work_status.py +147 -0
- package/runtime/python/okstra_ctl/team_reconcile.py +1 -1
- package/runtime/skills/okstra-brief/SKILL.md +32 -176
- package/runtime/skills/okstra-brief/references/reporter-confirmations.md +71 -0
- package/runtime/skills/okstra-brief/references/tracker-recursion.md +90 -0
- package/runtime/skills/okstra-container-build/SKILL.md +7 -20
- package/runtime/skills/okstra-graphify/SKILL.md +8 -8
- package/runtime/skills/okstra-inspect/SKILL.md +27 -43
- package/runtime/skills/okstra-rollup/SKILL.md +6 -6
- package/runtime/skills/okstra-run/SKILL.md +7 -16
- package/runtime/skills/okstra-schedule/SKILL.md +64 -419
- package/runtime/skills/okstra-setup/SKILL.md +25 -223
- package/runtime/skills/okstra-setup/references/project-config.md +188 -0
- package/runtime/templates/reports/schedule.template.md +2 -2
- package/runtime/templates/worker-prompt-preamble.md +1 -1
- package/runtime/validators/validate-run.py +7 -7
- package/src/cli-registry.mjs +14 -0
- package/src/commands/inspect/set-work-status.mjs +31 -0
- package/src/commands/lifecycle/check-project.mjs +68 -56
- package/src/commands/lifecycle/install.mjs +1 -0
- package/src/commands/lifecycle/preflight.mjs +82 -0
|
@@ -20,23 +20,19 @@ Single read-side entry point for okstra runtime inspection plus the one status m
|
|
|
20
20
|
| `error-zip` | Collect cross-project okstra error logs into an anonymized zip (report + raw) and summarize clusters. |
|
|
21
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`. |
|
|
22
22
|
|
|
23
|
-
## Step 0:
|
|
23
|
+
## Step 0: Preflight (shared)
|
|
24
24
|
|
|
25
|
-
Before any sub-command, run
|
|
25
|
+
Before any sub-command, 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):
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
2. `okstra check-project --json`
|
|
31
|
-
Resolves PROJECT_ROOT from the directory the Bash call runs in, looks for `.okstra/project.json`, and prints `{ok, projectRoot, projectJsonPath, projectId}` (plus a `stage` on failure). Parse the JSON from stdout.
|
|
27
|
+
```bash
|
|
28
|
+
okstra preflight --runtime claude-code --json
|
|
29
|
+
```
|
|
32
30
|
|
|
33
|
-
|
|
31
|
+
The project check only sees the cwd of the Bash call. When the user is asking about a project that is **not** the cwd (a sibling repo, a monorepo subdir, or a project named explicitly in the request), the bare form resolves to the wrong project or none and returns `ok:false` — a false negative, not a missing setup; do not hard-stop on it.
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
`okstra check-project --cwd <that-dir> --json`
|
|
39
|
-
`--cwd` is the sanctioned way to target a project without a leading `cd`/`export`: the command still starts with the literal `okstra` token, so the `Bash(okstra:*)` permission match holds (a leading `cd` is exactly what would break it). Only if this **also** returns `ok:false` do you tell the user: "this project has no okstra setup. Run `/okstra-setup` first." Then stop.
|
|
33
|
+
Branch on the stdout JSON:
|
|
34
|
+
- `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. 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).
|
|
40
36
|
|
|
41
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=...`.
|
|
42
38
|
|
|
@@ -155,7 +151,7 @@ Recognize requests to change a task's `workStatus` and update the corresponding
|
|
|
155
151
|
|
|
156
152
|
Natural language: "DEV-6827 done으로 바꿔줘", "PROD-1623을 blocked로 표시", "DEV-9047 진행중", "Mark DEV-6827 as done".
|
|
157
153
|
|
|
158
|
-
Explicit phrasing (recognized user utterances —
|
|
154
|
+
Explicit phrasing (recognized user utterances — normalize each to a `okstra set-work-status` call below):
|
|
159
155
|
- `okstra status set <task-id> <status>`
|
|
160
156
|
- `okstra status set <task-group> <task-id> <status>` (disambiguation)
|
|
161
157
|
- `okstra mark <task-id> <status>`
|
|
@@ -163,31 +159,21 @@ Explicit phrasing (recognized user utterances — these are **not** okstra CLI s
|
|
|
163
159
|
|
|
164
160
|
Accepted `<status>` values: `todo`, `in-progress`, `blocked`, `done`.
|
|
165
161
|
|
|
166
|
-
**Procedure:**
|
|
162
|
+
**Procedure:** run the update through the CLI (one Bash call, literal `okstra` token) — never edit `task-manifest.json` by hand:
|
|
167
163
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
- Use a targeted in-place edit (Edit tool with old_string/new_string anchors).
|
|
182
|
-
- Do NOT round-trip the file through `JSON.parse` + `JSON.stringify` — that reorders keys, drops trailing newlines, normalizes spacing.
|
|
183
|
-
- Preserve existing key order, indentation, and trailing newline exactly.
|
|
184
|
-
|
|
185
|
-
5. **Confirm in Korean:**
|
|
186
|
-
```
|
|
187
|
-
✓ <TASK-ID> workStatus: <previous> → <new>
|
|
188
|
-
✓ task-manifest.json 업데이트됨
|
|
189
|
-
```
|
|
190
|
-
`<previous>` = `(없음)` if the field was absent before.
|
|
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.
|
|
191
177
|
|
|
192
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`):
|
|
193
179
|
|
|
@@ -200,7 +186,7 @@ Accepted `<status>` values: `todo`, `in-progress`, `blocked`, `done`.
|
|
|
200
186
|
|
|
201
187
|
Annotate inferred values with `(inferred)` or `(default)`. Do not back-fill on read; only write when the user explicitly issues an update.
|
|
202
188
|
|
|
203
|
-
**Catalog sync note:**
|
|
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`) re-read each manifest directly.
|
|
204
190
|
|
|
205
191
|
---
|
|
206
192
|
|
|
@@ -258,7 +244,6 @@ When a user selects a specific task:
|
|
|
258
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.
|
|
259
245
|
|
|
260
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.
|
|
261
|
-
**Migrated-task fallback (do not bail out on empty paths).** Tasks migrated from the old `.project-docs/okstra/...` layout often have empty `latestRunManifestPath` / per-run `runManifestPath` in the catalog and timeline even though the manifests exist on disk. Before asking the user, glob `<projectRoot>/.okstra/tasks/<group-seg>/<id-seg>/runs/**/manifests/run-manifest-*.json` and pick the latest by the `YYYY-MM-DD_HH-MM-SS` timestamp in the filename. Only if that glob is also empty do you ask the user.
|
|
262
247
|
2. Read the manifest and extract required arguments:
|
|
263
248
|
- `projectId` → `--project-id`
|
|
264
249
|
- `taskGroup` → `--task-group`
|
|
@@ -289,9 +274,8 @@ Continues an existing Claude session for an unfinished run. Does NOT create a ne
|
|
|
289
274
|
|
|
290
275
|
1. Read `latestResumeCommandPath` from `history.1` (or `resumeCommandPath` from a `history.2` timeline entry).
|
|
291
276
|
2. Verify the file exists on disk.
|
|
292
|
-
3.
|
|
293
|
-
4. If
|
|
294
|
-
5. If the glob is also empty: `No resume script available for this run. Use 'history.3' to start a fresh run instead.`
|
|
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.`
|
|
295
279
|
|
|
296
280
|
---
|
|
297
281
|
|
|
@@ -10,15 +10,15 @@ Cross-task roll-up: collect every catalog task's run results (optionally scoped
|
|
|
10
10
|
|
|
11
11
|
This skill is read-only. It never mutates task artifacts.
|
|
12
12
|
|
|
13
|
-
## Step 0:
|
|
13
|
+
## Step 0: Preflight
|
|
14
14
|
|
|
15
|
-
Run
|
|
15
|
+
Run one Bash tool call, starting with the literal token `okstra` (never wrapped in `if`/`eval`/`$(...)`/`VAR=...`/`||`/`&&`/`npx` — a non-literal leading token defeats the `Bash(okstra:*)` permission match):
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
```bash
|
|
18
|
+
okstra preflight --runtime claude-code --json
|
|
19
|
+
```
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
Parse `{ok, projectRoot, ...}` from stdout. `ok: false` → "this project has no okstra setup. Run `/okstra-setup` first." Then stop. `ok: true` → carry `projectRoot` as a literal string.
|
|
21
|
+
Parse the stdout JSON. `ok: true` → carry `projectRoot` as a literal string. `ok: false` → tell the user to run `/okstra-setup` first, then stop. 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).
|
|
22
22
|
|
|
23
23
|
## Step 1: Resolve scope
|
|
24
24
|
|
|
@@ -54,22 +54,15 @@ The final `confirm` step is a normal `pick` step with three options — `Proceed
|
|
|
54
54
|
|
|
55
55
|
Never invent additional questions. Never reorder. **Never drop, hide, or merge a `pick` / `pick_group` option** — render every `options[]` entry as its own selectable `AskUserQuestion` choice, including entries that carry a `(default)` / `(recommended)` suffix. Do NOT collapse a multi-option pick into a "recommended + 직접 입력 / Other" shortlist: the wizard's `options[]` array IS the complete, authoritative choice set. Example: if a pick's `options[]` carries N entries, render all N as selectable choices — never abbreviate a multi-option step down to one recommended value. The run-prompt recommendation rule (1–2 추천 + 직접 입력) applies ONLY to prompts this skill authors itself (e.g. the conformance-waiver picker), never to wizard-provided `options[]`. Never use `AskUserQuestion` for `text` prompts — the wizard explicitly chose `text` to avoid the picker-Other re-render lag.
|
|
56
56
|
|
|
57
|
-
## Step 1:
|
|
57
|
+
## Step 1: Preflight
|
|
58
58
|
|
|
59
|
-
Run
|
|
59
|
+
Run one Bash tool call (Bash invocation rule from the top of this file applies):
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
2. `okstra paths --json`
|
|
65
|
-
Read `pythonPath` and other path fields from the JSON output. **Do not** `export PYTHONPATH=...` from this skill — every subsequent `okstra <subcmd>` call already self-bootstraps its Python path. Keep the parsed values in mind only as diagnostic context.
|
|
66
|
-
|
|
67
|
-
3. `okstra check-project --json`
|
|
68
|
-
Reads the project from the current working directory. Parse the JSON from stdout. If `ok` is `false`, tell the user: "this project has no okstra setup. Run `/okstra-setup` first." Then stop.
|
|
69
|
-
|
|
70
|
-
Parse `projectRoot` and `projectId` from the successful `check-project --json` output and carry them as literal strings into Step 2.
|
|
61
|
+
```bash
|
|
62
|
+
okstra preflight --runtime claude-code --json
|
|
63
|
+
```
|
|
71
64
|
|
|
72
|
-
|
|
65
|
+
Parse the stdout JSON. `ok: true` → carry `projectRoot` and `projectId` as literal strings into Step 2. `ok: false` (or `okstra` not on `PATH` at all) → tell the user: "okstra not set up — run `/okstra-setup` first." Then stop. 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). Do **not** try to invoke `npx -y okstra@latest ...` as a fallback — `npx` is not on the literal-token allow-list and will force a confirmation prompt on every wizard call afterward. Every subsequent `okstra <subcmd>` call self-bootstraps its Python path, so never `export PYTHONPATH=...`.
|
|
73
66
|
|
|
74
67
|
## Step 2: Initialize the wizard
|
|
75
68
|
|
|
@@ -170,9 +163,7 @@ If an action has an unknown `command`, `key`, or `scope`, stop and report the wi
|
|
|
170
163
|
|
|
171
164
|
Build the `okstra render-bundle` invocation from `outcome.renderArgs`, passing each key as `--<key>` and the value verbatim (including empty strings — they are intentional `use phase default` markers).
|
|
172
165
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
**Escaping rule**: inside a double-quoted value, escape any literal `"` as `\"`. Do not collapse `--key ""` into `--key` even when the value is empty.
|
|
166
|
+
Step 3's empty-answer and escaping rules apply verbatim: every flag whose value is the empty string MUST still be passed explicitly as `--<key> ""` (e.g. `--workers ""`, `--directive ""`) — `render-bundle` distinguishes "flag absent" from "flag present with empty value", and the wizard's intent is always the latter.
|
|
176
167
|
|
|
177
168
|
The okstra-run skill is the Claude Code execution front door, so it marks the host explicitly with `--runtime claude-code` / `--lead-runtime claude-code`; bare `okstra run` cannot invoke Claude Code `TeamCreate` / `Agent(...)` from a terminal.
|
|
178
169
|
|