okstra 0.30.0 → 0.30.2
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/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/prompts/profiles/_common-contract.md +9 -0
- package/runtime/python/okstra_ctl/worktree.py +32 -0
- package/runtime/skills/okstra-brief/SKILL.md +14 -16
- package/runtime/skills/okstra-history/SKILL.md +11 -20
- package/runtime/skills/okstra-logs/SKILL.md +18 -30
- package/runtime/skills/okstra-report-finder/SKILL.md +11 -20
- package/runtime/skills/okstra-schedule/SKILL.md +10 -22
- package/runtime/skills/okstra-setup/SKILL.md +17 -29
- package/runtime/skills/okstra-status/SKILL.md +12 -24
- package/runtime/skills/okstra-time-summary/SKILL.md +11 -20
package/package.json
CHANGED
package/runtime/BUILD.json
CHANGED
|
@@ -77,3 +77,12 @@ profile document.
|
|
|
77
77
|
- Audit sidecar (shared — applies to every analysis-worker output and every final-report):
|
|
78
78
|
- Reading Confirmation lines (one short line per input file confirming end-to-end reading) live in the **worker audit sidecar** at `runs/<task-type>/worker-results/<worker>-audit-<task-type>-<seq>.md`, NOT in the worker's main worker-results file. The worker-results body starts at section 1 (Findings). The validator fails worker-results files that contain a `## 0. Reading Confirmation` heading.
|
|
79
79
|
- The audit sidecar carries any other meta the worker wants to log (tool-call counts, MCP query summaries, timing notes). The lead's final-report does NOT duplicate this content — it is consumed by the validator and by post-run audit tooling, not by end-user readers.
|
|
80
|
+
|
|
81
|
+
- Markdown authoring (shared — applies to every markdown document produced by the lead or any worker, including final-reports, worker-results, briefs, and ad-hoc notes):
|
|
82
|
+
- every document must begin with an `Index` section.
|
|
83
|
+
- include only information necessary to fulfill the user's stated purpose and directly related requirements.
|
|
84
|
+
- follow only the sections, format, tone, and scope specified by the user, plus the required `Index` section.
|
|
85
|
+
- when writing task instructions or work orders, define the scope of work clearly and specifically, including deliverables, acceptance criteria, and verification steps when relevant.
|
|
86
|
+
- define scope positively by stating what work is included. Work outside the defined scope must not be performed.
|
|
87
|
+
- before adding any structure or content not explicitly specified, ask the user for confirmation, except for the required `Index` section.
|
|
88
|
+
- before completion, verify that the document exactly matches the requested scope and contains no unrelated material.
|
|
@@ -43,6 +43,7 @@ from typing import Optional
|
|
|
43
43
|
|
|
44
44
|
from .ids import _safe_fs_segment
|
|
45
45
|
from . import worktree_registry
|
|
46
|
+
from .seeding import SettingsLinkError, ensure_project_settings_symlink
|
|
46
47
|
|
|
47
48
|
|
|
48
49
|
# Project-root directories that hold okstra task state, ignored by git, or
|
|
@@ -361,6 +362,34 @@ def _link_sync_files(source_root: Path, worktree_path: Path) -> list[str]:
|
|
|
361
362
|
return notes
|
|
362
363
|
|
|
363
364
|
|
|
365
|
+
def _seed_worktree_settings_symlink(worktree_path: Path) -> None:
|
|
366
|
+
"""Seed `.claude/settings.local.json` in the worker worktree so dispatched
|
|
367
|
+
Claude / codex / gemini sessions inherit the okstra read-only / write
|
|
368
|
+
allowlist. Mirrors the main-project seeding done in `run.py` — needed
|
|
369
|
+
because `_link_sync_dirs` skips `.claude/` whenever `git worktree add`
|
|
370
|
+
already materialised the directory (e.g. tracked `.claude/handoff-*.md`).
|
|
371
|
+
Failures degrade to stderr warning so worktree provisioning still
|
|
372
|
+
succeeds.
|
|
373
|
+
"""
|
|
374
|
+
try:
|
|
375
|
+
link = ensure_project_settings_symlink(project_root=worktree_path)
|
|
376
|
+
except SettingsLinkError as exc:
|
|
377
|
+
print(
|
|
378
|
+
f"okstra-settings: failed to seed worker worktree symlink at "
|
|
379
|
+
f"{worktree_path / '.claude/settings.local.json'} — worker dispatch "
|
|
380
|
+
f"may be blocked by Claude Code permissions. ({exc})",
|
|
381
|
+
file=__import__("sys").stderr,
|
|
382
|
+
)
|
|
383
|
+
return
|
|
384
|
+
if link is None:
|
|
385
|
+
print(
|
|
386
|
+
"okstra-settings: ~/.okstra/templates/settings.local.json missing — "
|
|
387
|
+
"re-run 'npx okstra@latest install' (0.14.0+) to provision the "
|
|
388
|
+
"symlink target.",
|
|
389
|
+
file=__import__("sys").stderr,
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
|
|
364
393
|
def _copy_snapshot_files(source_root: Path, worktree_path: Path) -> list[str]:
|
|
365
394
|
"""Copy fixture files from MAIN → task worktree as read-only snapshots
|
|
366
395
|
(FU-V3).
|
|
@@ -485,6 +514,7 @@ def provision_task_worktree(
|
|
|
485
514
|
existing = worktree_registry.lookup(safe_project, safe_group, safe_task)
|
|
486
515
|
if existing is not None and existing.status == "active":
|
|
487
516
|
worktree_registry.touch_phase(safe_project, safe_group, safe_task, task_type)
|
|
517
|
+
_seed_worktree_settings_symlink(Path(existing.worktree_path))
|
|
488
518
|
return WorktreeProvision(
|
|
489
519
|
status="reused",
|
|
490
520
|
path=existing.worktree_path,
|
|
@@ -586,6 +616,8 @@ def provision_task_worktree(
|
|
|
586
616
|
_git(main_root, "branch", "-D", branch)
|
|
587
617
|
raise
|
|
588
618
|
|
|
619
|
+
_seed_worktree_settings_symlink(worktree_path)
|
|
620
|
+
|
|
589
621
|
base_label = (
|
|
590
622
|
f"{base_origin} @ {resolved_base_ref[:12]}"
|
|
591
623
|
if base_origin != "HEAD"
|
|
@@ -107,26 +107,24 @@ at external `docs/adr/`.
|
|
|
107
107
|
|
|
108
108
|
## Step 0: Resolve project root
|
|
109
109
|
|
|
110
|
-
Reuse the same
|
|
110
|
+
Reuse the same literal-token-first rule as `okstra-run`. Each command below is a **separate Bash tool call** starting with the literal token `okstra` so the `Bash(okstra:*)` permission match succeeds. Do **not** wrap any of them in `if`, `eval`, `export`, `$(...)`, `VAR=...`, `||`, or `&&`, and do **not** introduce a `$OKSTRA_CMD` variable or an `npx -y okstra@latest` fallback — those leading tokens defeat the permission match and force a confirmation prompt on every call.
|
|
111
111
|
|
|
112
112
|
```bash
|
|
113
|
-
|
|
114
|
-
OKSTRA_CMD="okstra"
|
|
115
|
-
else
|
|
116
|
-
# `~/.okstra/bin/okstra.sh` exists on every installed machine but it is
|
|
117
|
-
# the bash run-wrapper, NOT the Node CLI — it does not implement
|
|
118
|
-
# `check-project`. Do not branch into it as a fallback. Go straight to
|
|
119
|
-
# `npx` so the user always reaches a working `check-project` even when
|
|
120
|
-
# the Node CLI is off-$PATH.
|
|
121
|
-
OKSTRA_CMD="npx -y okstra@latest"
|
|
122
|
-
fi
|
|
123
|
-
$OKSTRA_CMD check-project --cwd "$(pwd)"
|
|
113
|
+
okstra check-project --json
|
|
124
114
|
```
|
|
125
115
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
116
|
+
Parse the JSON from stdout:
|
|
117
|
+
|
|
118
|
+
- `ok: true` → use `projectRoot` from the JSON output. Carry it as a literal string into the steps below.
|
|
119
|
+
- `ok: false` → ask the user with a **plain text prompt** for an absolute project-root path, then rerun as a separate tool call with the literal absolute path (no `$(pwd)`, no shell variables):
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
okstra check-project --cwd /abs/path/from/user --json
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
If still `ok: false`, tell the user to run `okstra-setup` and stop.
|
|
126
|
+
|
|
127
|
+
> If the `okstra` binary is not on `PATH` at all, the command above will not run. In that case tell the user verbatim: "okstra not installed — run `npx okstra@latest install` once, then retry this skill." Do **not** try to invoke `npx -y okstra@latest ...` from this skill — `npx` is not on the literal-token allow-list this skill targets and will force a confirmation prompt on every subsequent call.
|
|
130
128
|
|
|
131
129
|
## Step 1: Choose input source
|
|
132
130
|
|
|
@@ -26,27 +26,18 @@ If the user is ambiguous, ask. Defaulting to the wrong one either wastes a fresh
|
|
|
26
26
|
|
|
27
27
|
## Step 0: Verify okstra runtime + project setup
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
eval "$($OKSTRA_CMD paths --shell)"
|
|
40
|
-
export PYTHONPATH="$OKSTRA_PYTHONPATH"
|
|
41
|
-
OKSTRA_PROJECT_INFO="$($OKSTRA_CMD check-project --json)" || {
|
|
42
|
-
echo "FAIL: this project has no okstra setup. Tell the user to run /okstra-setup first." >&2
|
|
43
|
-
echo "$OKSTRA_PROJECT_INFO" >&2
|
|
44
|
-
exit 1
|
|
45
|
-
}
|
|
46
|
-
```
|
|
29
|
+
Run each of the following commands as a **separate Bash tool call**. Each command starts with the literal token `okstra` so the `Bash(okstra:*)` permission match succeeds. Do **not** wrap any of them in `if`, `eval`, `export`, `$(...)`, `VAR=...`, `||`, or `&&`, and do **not** introduce a `$OKSTRA_CMD` variable or an `npx -y okstra@latest` fallback — those leading tokens defeat the permission match and force a confirmation prompt on every call. The LLM (you) inspects each command's output and decides what to do next in natural language — never in shell.
|
|
30
|
+
|
|
31
|
+
1. `okstra ensure-installed`
|
|
32
|
+
If this exits non-zero, tell the user: "okstra not installed — run `npx okstra@latest install` once, then retry this skill." Then stop. Do **not** try to invoke `npx -y okstra@latest ...` as a fallback.
|
|
33
|
+
|
|
34
|
+
2. `okstra check-project --json`
|
|
35
|
+
Reads the project from the current working directory. Parse the JSON from stdout. The shape is `{ok, projectRoot, projectJsonPath, projectId}`.
|
|
36
|
+
|
|
37
|
+
- `ok: false` → tell the user: "this project has no okstra setup. Run `/okstra-setup` first." Then stop.
|
|
38
|
+
- `ok: true` → carry `projectRoot` as a literal string and use it to locate `.project-docs/okstra/discovery/task-catalog.json`.
|
|
47
39
|
|
|
48
|
-
|
|
49
|
-
use `projectRoot` to locate `.project-docs/okstra/discovery/task-catalog.json`.
|
|
40
|
+
Subsequent `okstra <subcmd>` calls self-bootstrap their Python path, so this skill never needs `okstra paths --shell` / `export PYTHONPATH=...`.
|
|
50
41
|
|
|
51
42
|
## Step 1: Read the Task Catalog
|
|
52
43
|
|
|
@@ -36,57 +36,45 @@ multi-MB logs; analysis-phase dispatches are typically smaller.
|
|
|
36
36
|
|
|
37
37
|
## Step 0: Verify okstra runtime + project setup
|
|
38
38
|
|
|
39
|
-
Before any other step,
|
|
40
|
-
project's okstra metadata are in place:
|
|
39
|
+
Before any other step, run each of the following commands as a **separate Bash tool call**. Each command starts with the literal token `okstra` so the `Bash(okstra:*)` permission match succeeds. Do **not** wrap any of them in `if`, `eval`, `export`, `$(...)`, `VAR=...`, `||`, or `&&`, and do **not** introduce a `$OKSTRA_CMD` variable or an `npx -y okstra@latest` fallback — those leading tokens defeat the permission match and force a confirmation prompt on every call. The LLM (you) inspects each command's output and decides what to do next in natural language — never in shell.
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
exit 1
|
|
51
|
-
}
|
|
52
|
-
eval "$($OKSTRA_CMD paths --shell)"
|
|
53
|
-
export PYTHONPATH="$OKSTRA_PYTHONPATH"
|
|
54
|
-
OKSTRA_PROJECT_INFO="$($OKSTRA_CMD check-project --json)" || {
|
|
55
|
-
echo "FAIL: this project has no okstra setup. Tell the user to run /okstra-setup first." >&2
|
|
56
|
-
echo "$OKSTRA_PROJECT_INFO" >&2
|
|
57
|
-
exit 1
|
|
58
|
-
}
|
|
59
|
-
```
|
|
41
|
+
1. `okstra ensure-installed`
|
|
42
|
+
If this exits non-zero, tell the user: "okstra not installed — run `npx okstra@latest install` once, then retry this skill." Then stop. Do **not** try to invoke `npx -y okstra@latest ...` as a fallback.
|
|
43
|
+
|
|
44
|
+
2. `okstra check-project --json`
|
|
45
|
+
Reads the project from the current working directory. Parse the JSON from stdout. The shape is `{ok, projectRoot, projectJsonPath, projectId}`.
|
|
46
|
+
|
|
47
|
+
- `ok: false` → tell the user: "this project has no okstra setup. Run `/okstra-setup` first." Then stop.
|
|
48
|
+
- `ok: true` → carry `projectRoot` as a literal string and use it as the search root for the steps below.
|
|
60
49
|
|
|
61
|
-
|
|
62
|
-
steps below.
|
|
50
|
+
Subsequent `okstra <subcmd>` calls self-bootstrap their Python path, so this skill never needs `okstra paths --shell` / `export PYTHONPATH=...`.
|
|
63
51
|
|
|
64
52
|
## Step 1: Inventory
|
|
65
53
|
|
|
66
54
|
Find all wrapper log files and collect metadata. Use a single `find` to
|
|
67
55
|
keep the I/O cost predictable, then format the results.
|
|
68
56
|
|
|
69
|
-
|
|
70
|
-
PROJECT_ROOT=$(echo "$OKSTRA_PROJECT_INFO" | python3 -c 'import sys,json;print(json.load(sys.stdin)["projectRoot"])')
|
|
71
|
-
LOGS_ROOT="$PROJECT_ROOT/.project-docs/okstra/tasks"
|
|
57
|
+
Construct the logs root by appending `/.project-docs/okstra/tasks` to the literal `projectRoot` value parsed in Step 0, and paste it as a literal absolute path in place of `<LOGS_ROOT>` below (no shell variables, no `$(...)`):
|
|
72
58
|
|
|
73
|
-
|
|
74
|
-
find
|
|
59
|
+
```bash
|
|
60
|
+
find <LOGS_ROOT> -type f -path '*/runs/*/prompts/*.log' \
|
|
75
61
|
-printf '%s\t%T@\t%p\n' 2>/dev/null \
|
|
76
62
|
| sort -k1,1nr
|
|
77
63
|
```
|
|
78
64
|
|
|
79
|
-
|
|
65
|
+
The columns produced are `size_bytes | mtime_epoch | path`.
|
|
66
|
+
|
|
67
|
+
On macOS, `find -printf` is unavailable. Fall back to `stat` — again substitute the literal `<LOGS_ROOT>`:
|
|
80
68
|
|
|
81
69
|
```bash
|
|
82
|
-
find
|
|
70
|
+
find <LOGS_ROOT> -type f -path '*/runs/*/prompts/*.log' 2>/dev/null \
|
|
83
71
|
| while IFS= read -r p; do
|
|
84
72
|
stat -f '%z%t%m%t%N' "$p"
|
|
85
73
|
done \
|
|
86
74
|
| sort -k1,1nr
|
|
87
75
|
```
|
|
88
76
|
|
|
89
|
-
If the result is empty, report `No wrapper log files found under <
|
|
77
|
+
If the result is empty, report `No wrapper log files found under <projectRoot>` and exit.
|
|
90
78
|
|
|
91
79
|
## Step 2: Summary table
|
|
92
80
|
|
|
@@ -14,27 +14,18 @@ user-invocable: false
|
|
|
14
14
|
|
|
15
15
|
## Step 0: Verify okstra runtime + project setup
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
eval "$($OKSTRA_CMD paths --shell)"
|
|
28
|
-
export PYTHONPATH="$OKSTRA_PYTHONPATH"
|
|
29
|
-
OKSTRA_PROJECT_INFO="$($OKSTRA_CMD check-project --json)" || {
|
|
30
|
-
echo "FAIL: this project has no okstra setup. Tell the user to run /okstra-setup first." >&2
|
|
31
|
-
echo "$OKSTRA_PROJECT_INFO" >&2
|
|
32
|
-
exit 1
|
|
33
|
-
}
|
|
34
|
-
```
|
|
17
|
+
각 명령은 **별도 Bash tool call** 로 실행한다. 모든 명령은 리터럴 `okstra` 토큰으로 시작해 `Bash(okstra:*)` 권한 매칭을 통과해야 한다. `if`, `eval`, `export`, `$(...)`, `VAR=...`, `||`, `&&` 로 감싸지 말고, `$OKSTRA_CMD` 변수나 `npx -y okstra@latest` 폴백도 도입하지 않는다 — 첫 토큰이 비리터럴이면 권한 매칭이 깨져 호출마다 확인 프롬프트가 뜬다. 각 명령의 출력은 LLM(너) 이 보고 자연어로 분기 판단을 한다 — shell 분기는 쓰지 않는다.
|
|
18
|
+
|
|
19
|
+
1. `okstra ensure-installed`
|
|
20
|
+
비정상 종료 → 사용자에게 그대로 안내: "okstra not installed — run `npx okstra@latest install` once, then retry this skill." 그리고 중단. 폴백으로 `npx -y okstra@latest ...` 를 호출하지 않는다.
|
|
21
|
+
|
|
22
|
+
2. `okstra check-project --json`
|
|
23
|
+
현재 작업 디렉터리 기준 프로젝트를 읽는다. stdout 의 JSON shape: `{ok, projectRoot, projectJsonPath, projectId}`.
|
|
24
|
+
|
|
25
|
+
- `ok: false` → 사용자에게 "this project has no okstra setup. Run `/okstra-setup` first." 안내 후 중단.
|
|
26
|
+
- `ok: true` → `projectRoot` 를 리터럴 문자열로 들고 catalog/manifest 위치를 잡는다.
|
|
35
27
|
|
|
36
|
-
|
|
37
|
-
`projectRoot` 로 catalog/manifest 위치를 잡는다.
|
|
28
|
+
후속 `okstra <subcmd>` 호출은 Python path 를 자체 부트스트랩하므로 본 스킬은 `okstra paths --shell` / `export PYTHONPATH=...` 를 필요로 하지 않는다.
|
|
38
29
|
|
|
39
30
|
## Step 1: Task Key로 Report 경로 찾기
|
|
40
31
|
|
|
@@ -37,30 +37,18 @@ If `--title` is omitted, derive a default title from `task-group` (e.g. `uploadF
|
|
|
37
37
|
|
|
38
38
|
## Preflight: Verify okstra runtime + project setup
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
Before anything else in this skill, run each of the following commands as a **separate Bash tool call**. Each command starts with the literal token `okstra` so the `Bash(okstra:*)` permission match succeeds. Do **not** wrap any of them in `if`, `eval`, `export`, `$(...)`, `VAR=...`, `||`, or `&&`, and do **not** introduce a `$OKSTRA_CMD` variable or an `npx -y okstra@latest` fallback — those leading tokens defeat the permission match and force a confirmation prompt on every call. The LLM (you) inspects each command's output and decides what to do next in natural language — never in shell.
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
exit 1
|
|
51
|
-
}
|
|
52
|
-
eval "$($OKSTRA_CMD paths --shell)"
|
|
53
|
-
export PYTHONPATH="$OKSTRA_PYTHONPATH"
|
|
54
|
-
OKSTRA_PROJECT_INFO="$($OKSTRA_CMD check-project --json)" || {
|
|
55
|
-
echo "FAIL: this project has no okstra setup. Tell the user to run /okstra-setup first." >&2
|
|
56
|
-
echo "$OKSTRA_PROJECT_INFO" >&2
|
|
57
|
-
exit 1
|
|
58
|
-
}
|
|
59
|
-
```
|
|
42
|
+
1. `okstra ensure-installed`
|
|
43
|
+
If this exits non-zero, tell the user: "okstra not installed — run `npx okstra@latest install` once, then retry this skill." Then stop. Do **not** try to invoke `npx -y okstra@latest ...` as a fallback.
|
|
44
|
+
|
|
45
|
+
2. `okstra check-project --json`
|
|
46
|
+
Reads the project from the current working directory. Parse the JSON from stdout. The shape is `{ok, projectRoot, projectJsonPath, projectId}`.
|
|
47
|
+
|
|
48
|
+
- `ok: false` → tell the user: "this project has no okstra setup. Run `/okstra-setup` first." Then stop.
|
|
49
|
+
- `ok: true` → carry `projectRoot` as a literal string and use it to locate `.project-docs/okstra/discovery/task-catalog.json` and the task-group directory.
|
|
60
50
|
|
|
61
|
-
|
|
62
|
-
use `projectRoot` to locate `.project-docs/okstra/discovery/task-catalog.json`
|
|
63
|
-
and the task-group directory.
|
|
51
|
+
Subsequent `okstra <subcmd>` calls self-bootstrap their Python path, so this skill never needs `okstra paths --shell` / `export PYTHONPATH=...`.
|
|
64
52
|
|
|
65
53
|
## Process Procedure
|
|
66
54
|
|
|
@@ -53,44 +53,32 @@ Show the final summary line back to the user (`version stamp: x.y.z`).
|
|
|
53
53
|
If install fails, surface the stderr verbatim. Do NOT try to "fix" it by
|
|
54
54
|
running the legacy `okstra-install.sh` — that path is dev-only.
|
|
55
55
|
|
|
56
|
-
## Step 2: Load runtime paths
|
|
56
|
+
## Step 2: Load runtime paths (no-op)
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
# Prefer PATH-resolved okstra (npm-installed) over npx — avoids per-call registry lookup.
|
|
60
|
-
if command -v okstra >/dev/null 2>&1; then
|
|
61
|
-
OKSTRA_CMD="okstra"
|
|
62
|
-
else
|
|
63
|
-
OKSTRA_CMD="npx -y okstra@latest"
|
|
64
|
-
fi
|
|
65
|
-
eval "$($OKSTRA_CMD paths --shell)"
|
|
66
|
-
export PYTHONPATH="$OKSTRA_PYTHONPATH"
|
|
67
|
-
```
|
|
58
|
+
After `okstra install`, every `okstra <subcmd>` call self-bootstraps its Python path, so this skill does NOT run `okstra paths --shell` / `eval ...` / `export PYTHONPATH=...`. The previously-set `$OKSTRA_WORKSPACE`, `$OKSTRA_AGENTS_DIR`, `$OKSTRA_PYTHONPATH`, `$OKSTRA_BIN`, `$OKSTRA_HOME` env vars are NOT set by this skill. If a later step needs one of those paths, call `okstra paths --json` as a **separate Bash tool call** (literal-token-first) and read the value from JSON output.
|
|
68
59
|
|
|
69
|
-
|
|
70
|
-
`$OKSTRA_BIN`, `$OKSTRA_HOME` are all set. Do not hardcode any of these — read
|
|
71
|
-
them from the env vars.
|
|
60
|
+
**Bash invocation rule (permission-friendly)**: from this step on, every Bash command in this skill MUST begin with the literal token `okstra` and pass literal argument values. Do not introduce shell variables (`$PROJECT_ROOT`, `$PROJECT_ID`, ...), `$(...)` command substitution, leading `VAR=...` assignments, or wrap commands in `if`/`eval`/`||`/`&&` — any of those make the leading token non-literal, defeat the `Bash(okstra:*)` permission match, and force a confirmation prompt on every call. When a prior tool call emitted a path or value, read it from the tool output and paste the literal string into the next command.
|
|
72
61
|
|
|
73
62
|
## Step 3: Resolve PROJECT_ROOT
|
|
74
63
|
|
|
75
64
|
```bash
|
|
76
|
-
|
|
65
|
+
okstra check-project --json
|
|
77
66
|
```
|
|
78
67
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
`
|
|
82
|
-
absolute project root and rerun with
|
|
68
|
+
Parse the JSON from stdout. The shape is `{ok, projectRoot, projectJsonPath, projectId, stage?}`.
|
|
69
|
+
|
|
70
|
+
- `ok: true` → carry `projectRoot` as a literal absolute string and paste it into every subsequent command in this skill.
|
|
71
|
+
- `ok: false`, `stage: "resolve"` → ask the user (`AskUserQuestion`, free text) for an absolute project root and rerun as a separate Bash tool call with the literal absolute path:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
okstra check-project --cwd /abs/path/from/user --json
|
|
75
|
+
```
|
|
83
76
|
|
|
84
77
|
## Step 4: Inspect or create `project.json`
|
|
85
78
|
|
|
86
|
-
|
|
87
|
-
PROJECT_JSON="$PROJECT_ROOT/.project-docs/okstra/project.json"
|
|
88
|
-
if [ -f "$PROJECT_JSON" ]; then
|
|
89
|
-
cat "$PROJECT_JSON"
|
|
90
|
-
fi
|
|
91
|
-
```
|
|
79
|
+
Use the `Read` tool on the literal absolute path `<projectRoot>/.project-docs/okstra/project.json` (substitute the literal `projectRoot` value parsed in Step 3). If `Read` errors with "file does not exist", treat that as the "create" branch below; otherwise the file exists and you can inspect its contents inline.
|
|
92
80
|
|
|
93
|
-
If the file exists,
|
|
81
|
+
If the file exists, surface its `projectId`/`projectRoot` and ask whether to
|
|
94
82
|
keep or overwrite. Default is to keep — okstra refuses to change `projectId`
|
|
95
83
|
on an existing project (see `okstra_project.resolver.upsert_project_json`),
|
|
96
84
|
so overwriting requires manually deleting the file first.
|
|
@@ -104,10 +92,10 @@ If the file does NOT exist, ask via `AskUserQuestion`:
|
|
|
104
92
|
`error: --project-id is required (no existing project.json, not a TTY)`,
|
|
105
93
|
so passing the user's empty answer through is a silent failure path.
|
|
106
94
|
|
|
107
|
-
Then create the file:
|
|
95
|
+
Then create the file — paste the literal `projectRoot` from Step 3 and the literal `projectId` from the user's answer (no shell variables):
|
|
108
96
|
|
|
109
97
|
```bash
|
|
110
|
-
okstra setup --yes --project-root
|
|
98
|
+
okstra setup --yes --project-root /abs/path/to/projectRoot --project-id my-project-id
|
|
111
99
|
```
|
|
112
100
|
|
|
113
101
|
> After this, **Steps 4.5–4.8 are all optional**. The built-in defaults
|
|
@@ -266,7 +254,7 @@ If the user chose `나중에`, tell them they can register later with one of:
|
|
|
266
254
|
## Step 5: Verify
|
|
267
255
|
|
|
268
256
|
```bash
|
|
269
|
-
|
|
257
|
+
okstra doctor
|
|
270
258
|
```
|
|
271
259
|
|
|
272
260
|
If all checks return `OK`, the setup is complete. If any check fails, surface
|
|
@@ -13,30 +13,18 @@ description: Use when the user asks for overall okstra task status, current life
|
|
|
13
13
|
|
|
14
14
|
## Step 0: Verify okstra runtime + project setup
|
|
15
15
|
|
|
16
|
-
Before any other step,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
echo "FAIL: okstra not installed; tell the user to run: npx okstra@latest install" >&2
|
|
27
|
-
exit 1
|
|
28
|
-
}
|
|
29
|
-
eval "$($OKSTRA_CMD paths --shell)"
|
|
30
|
-
export PYTHONPATH="$OKSTRA_PYTHONPATH"
|
|
31
|
-
OKSTRA_PROJECT_INFO="$($OKSTRA_CMD check-project --json)" || {
|
|
32
|
-
echo "FAIL: this project has no okstra setup. Tell the user to run /okstra-setup first." >&2
|
|
33
|
-
echo "$OKSTRA_PROJECT_INFO" >&2
|
|
34
|
-
exit 1
|
|
35
|
-
}
|
|
36
|
-
```
|
|
16
|
+
Before any other step, run each of the following commands as a **separate Bash tool call**. Each command starts with the literal token `okstra` so the `Bash(okstra:*)` permission match succeeds. Do **not** wrap any of them in `if`, `eval`, `export`, `$(...)`, `VAR=...`, `||`, or `&&`, and do **not** introduce a `$OKSTRA_CMD` variable or an `npx -y okstra@latest` fallback — those leading tokens defeat the permission match and force a confirmation prompt on every call. The LLM (you) inspects each command's output and decides what to do next in natural language — never in shell.
|
|
17
|
+
|
|
18
|
+
1. `okstra ensure-installed`
|
|
19
|
+
If this exits non-zero, tell the user: "okstra not installed — run `npx okstra@latest install` once, then retry this skill." Then stop. Do **not** try to invoke `npx -y okstra@latest ...` as a fallback.
|
|
20
|
+
|
|
21
|
+
2. `okstra check-project --json`
|
|
22
|
+
Reads the project from the current working directory. Parse the JSON from stdout. The shape is `{ok, projectRoot, projectJsonPath, projectId}`.
|
|
23
|
+
|
|
24
|
+
- `ok: false` → tell the user: "this project has no okstra setup. Run `/okstra-setup` first." Then stop.
|
|
25
|
+
- `ok: true` → carry `projectRoot` as a literal string into the steps below; reuse it instead of re-resolving.
|
|
37
26
|
|
|
38
|
-
|
|
39
|
-
parse and reuse it instead of re-resolving in the steps below.
|
|
27
|
+
Subsequent `okstra <subcmd>` calls self-bootstrap their Python path, so this skill never needs `okstra paths --shell` / `export PYTHONPATH=...`.
|
|
40
28
|
|
|
41
29
|
## Step 1: Overall Project Status
|
|
42
30
|
|
|
@@ -255,4 +243,4 @@ This skill updates `task-manifest.json` only. `discovery/task-catalog.json` may
|
|
|
255
243
|
|
|
256
244
|
## Out-of-Scope Backlog
|
|
257
245
|
|
|
258
|
-
- **Step 0 boilerplate duplication.** The `ensure-installed` + `
|
|
246
|
+
- **Step 0 boilerplate duplication.** The `ensure-installed` + `check-project --json` preamble (literal-token-first, separate Bash calls) is near-identical across every user-facing okstra skill. The Claude Code skill framework has no include/snippet mechanism today, so each skill duplicates the prose. A future change should either (a) extract the preamble into a single `okstra preflight` subcommand the skill can call in one line, or (b) ship the block as a shared SKILL fragment if the framework gains include support. Not actionable inside this skill alone.
|
|
@@ -29,27 +29,18 @@ If a run never reached Phase 7, its `team-state` will not have `durationMs` fill
|
|
|
29
29
|
|
|
30
30
|
## Step 0: Verify okstra runtime + project setup
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
eval "$($OKSTRA_CMD paths --shell)"
|
|
43
|
-
export PYTHONPATH="$OKSTRA_PYTHONPATH"
|
|
44
|
-
OKSTRA_PROJECT_INFO="$($OKSTRA_CMD check-project --json)" || {
|
|
45
|
-
echo "FAIL: this project has no okstra setup. Tell the user to run /okstra-setup first." >&2
|
|
46
|
-
echo "$OKSTRA_PROJECT_INFO" >&2
|
|
47
|
-
exit 1
|
|
48
|
-
}
|
|
49
|
-
```
|
|
32
|
+
Run each of the following commands as a **separate Bash tool call**. Each command starts with the literal token `okstra` so the `Bash(okstra:*)` permission match succeeds. Do **not** wrap any of them in `if`, `eval`, `export`, `$(...)`, `VAR=...`, `||`, or `&&`, and do **not** introduce a `$OKSTRA_CMD` variable or an `npx -y okstra@latest` fallback — those leading tokens defeat the permission match and force a confirmation prompt on every call. The LLM (you) inspects each command's output and decides what to do next in natural language — never in shell.
|
|
33
|
+
|
|
34
|
+
1. `okstra ensure-installed`
|
|
35
|
+
If this exits non-zero, tell the user: "okstra not installed — run `npx okstra@latest install` once, then retry this skill." Then stop. Do **not** try to invoke `npx -y okstra@latest ...` as a fallback.
|
|
36
|
+
|
|
37
|
+
2. `okstra check-project --json`
|
|
38
|
+
Reads the project from the current working directory. Parse the JSON from stdout. The shape is `{ok, projectRoot, projectJsonPath, projectId}`.
|
|
39
|
+
|
|
40
|
+
- `ok: false` → tell the user: "this project has no okstra setup. Run `/okstra-setup` first." Then stop.
|
|
41
|
+
- `ok: true` → carry `projectRoot` as a literal string and use it to locate `.project-docs/okstra/discovery/task-catalog.json`.
|
|
50
42
|
|
|
51
|
-
|
|
52
|
-
gives `projectRoot` for locating `.project-docs/okstra/discovery/task-catalog.json`.
|
|
43
|
+
Subsequent `okstra <subcmd>` calls self-bootstrap their Python path, so this skill never needs `okstra paths --shell` / `export PYTHONPATH=...`.
|
|
53
44
|
|
|
54
45
|
## Step 1: Resolve task-id → timeline path
|
|
55
46
|
|