okstra 0.68.0 → 0.70.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.
Files changed (37) hide show
  1. package/bin/okstra +18 -0
  2. package/docs/kr/architecture.md +1 -0
  3. package/docs/kr/cli.md +2 -1
  4. package/docs/superpowers/plans/2026-06-11-wizard-whole-task-final-verification.md +526 -0
  5. package/docs/superpowers/specs/2026-06-11-wizard-whole-task-final-verification-design.md +89 -0
  6. package/package.json +1 -1
  7. package/runtime/BUILD.json +2 -2
  8. package/runtime/agents/SKILL.md +3 -3
  9. package/runtime/agents/workers/claude-worker.md +1 -1
  10. package/runtime/agents/workers/codex-worker.md +3 -3
  11. package/runtime/agents/workers/gemini-worker.md +3 -3
  12. package/runtime/agents/workers/report-writer-worker.md +2 -2
  13. package/runtime/prompts/launch.template.md +2 -2
  14. package/runtime/prompts/profiles/_implementation-deliverable.md +1 -0
  15. package/runtime/prompts/profiles/_implementation-executor.md +3 -1
  16. package/runtime/prompts/profiles/_implementation-verifier.md +1 -0
  17. package/runtime/prompts/profiles/improvement-discovery.md +1 -1
  18. package/runtime/prompts/wizard/prompts.ko.json +8 -4
  19. package/runtime/python/okstra_ctl/conformance.py +17 -0
  20. package/runtime/python/okstra_ctl/paths.py +7 -4
  21. package/runtime/python/okstra_ctl/render.py +10 -3
  22. package/runtime/python/okstra_ctl/run.py +97 -20
  23. package/runtime/python/okstra_ctl/wizard.py +140 -38
  24. package/runtime/python/okstra_ctl/worktree.py +18 -0
  25. package/runtime/python/okstra_token_usage/collect.py +27 -0
  26. package/runtime/skills/okstra-convergence/SKILL.md +3 -3
  27. package/runtime/skills/okstra-inspect/SKILL.md +1 -1
  28. package/runtime/skills/okstra-report-writer/SKILL.md +6 -6
  29. package/runtime/skills/okstra-team-contract/SKILL.md +5 -5
  30. package/runtime/validators/validate-run.py +2 -2
  31. package/src/_python-helper.mjs +52 -0
  32. package/src/error-log.mjs +19 -0
  33. package/src/inject-report-index.mjs +22 -0
  34. package/src/render-final-report.mjs +22 -0
  35. package/src/render-views.mjs +9 -48
  36. package/src/spawn-followups.mjs +23 -0
  37. package/src/token-usage.mjs +3 -34
@@ -0,0 +1,22 @@
1
+ import { runInstalledScript } from "./_python-helper.mjs";
2
+
3
+ const USAGE = `okstra render-final-report — render the markdown sibling of a final-report data.json
4
+
5
+ Wraps the python helper (\`okstra-render-final-report.py\`) installed under
6
+ \`~/.okstra/bin/\` so skills call \`okstra render-final-report\` instead of
7
+ emitting a \`python3 "$HOME/..."\` invocation (which breaks \`Bash(okstra:*)\`
8
+ permission matching and prompts on every call).
9
+
10
+ Usage:
11
+ okstra render-final-report <path-to-final-report.data.json>
12
+
13
+ The argument is forwarded verbatim to the python helper.
14
+ `;
15
+
16
+ export async function run(args) {
17
+ return runInstalledScript({
18
+ scriptName: "okstra-render-final-report.py",
19
+ args,
20
+ usage: USAGE,
21
+ });
22
+ }
@@ -1,18 +1,14 @@
1
- import { spawn } from "node:child_process";
2
- import { existsSync } from "node:fs";
3
- import { resolve as resolvePath } from "node:path";
4
- import { fileURLToPath } from "node:url";
5
- import { resolvePaths } from "./paths.mjs";
1
+ import { runInstalledScript } from "./_python-helper.mjs";
6
2
 
7
- const USAGE = `okstra render-views — render slim AI + self-contained HTML views of a final-report
3
+ const USAGE = `okstra render-views — render the self-contained HTML view of a final-report
8
4
 
9
5
  A thin spawn shim over \`scripts/okstra-render-report-views.py\` (installed
10
6
  at \`$HOME/.okstra/bin/okstra-render-report-views.py\`). Reads the final-
11
- report MD and writes two siblings:
7
+ report MD and writes a single sibling:
12
8
 
13
- <stem>.slim.md — token-saving AI consumption copy
14
9
  <stem>.html — single-file self-contained human view with form
15
- controls on §5 clarification rows
10
+ controls on §5 clarification rows (skipped when the
11
+ report has no §5 C-* clarification rows)
16
12
 
17
13
  Usage:
18
14
  okstra render-views <path-to-final-report.md>
@@ -23,45 +19,10 @@ When the optional flags are omitted the script infers from the report
23
19
  path and its '- Task Type:' / '- Task Key:' lines.
24
20
  `;
25
21
 
26
- function resolveEntrypoint(paths) {
27
- // Prefer the installed copy under ~/.okstra/bin (what production users
28
- // see); fall back to the in-repo dev source when running from a
29
- // checkout that hasn't been installed.
30
- const installed = resolvePath(paths.home, "bin", "okstra-render-report-views.py");
31
- if (existsSync(installed)) return installed;
32
- const here = fileURLToPath(new URL("..", import.meta.url));
33
- const dev = resolvePath(here, "scripts", "okstra-render-report-views.py");
34
- if (existsSync(dev)) return dev;
35
- return null;
36
- }
37
-
38
22
  export async function run(args) {
39
- if (args.includes("--help") || args.includes("-h")) {
40
- process.stdout.write(USAGE);
41
- return 0;
42
- }
43
- if (args.length === 0) {
44
- process.stderr.write("error: missing <path-to-final-report.md>\n");
45
- process.stderr.write(USAGE);
46
- return 2;
47
- }
48
- const paths = await resolvePaths();
49
- const entry = resolveEntrypoint(paths);
50
- if (!entry) {
51
- process.stderr.write(
52
- "error: okstra-render-report-views.py not found. " +
53
- "Run `okstra install` to install the runtime.\n",
54
- );
55
- return 1;
56
- }
57
- return await new Promise((res) => {
58
- const child = spawn("python3", [entry, ...args], {
59
- stdio: ["ignore", "inherit", "inherit"],
60
- });
61
- child.on("error", (err) => {
62
- process.stderr.write(`error: ${err.message}\n`);
63
- res(1);
64
- });
65
- child.on("close", (code) => res(code ?? 0));
23
+ return runInstalledScript({
24
+ scriptName: "okstra-render-report-views.py",
25
+ args,
26
+ usage: USAGE,
66
27
  });
67
28
  }
@@ -0,0 +1,23 @@
1
+ import { runInstalledScript } from "./_python-helper.mjs";
2
+
3
+ const USAGE = `okstra spawn-followups — create follow-up task bundles from a final report
4
+
5
+ Wraps the python helper (\`okstra-spawn-followups.py\`) installed under
6
+ \`~/.okstra/bin/\` so skills call \`okstra spawn-followups\` instead of
7
+ emitting a \`python3 "$HOME/..."\` invocation (which breaks \`Bash(okstra:*)\`
8
+ permission matching and prompts on every call).
9
+
10
+ Usage:
11
+ okstra spawn-followups <args...>
12
+
13
+ All arguments are forwarded verbatim to the python helper. See
14
+ \`okstra spawn-followups --help\` for the full option list.
15
+ `;
16
+
17
+ export async function run(args) {
18
+ return runInstalledScript({
19
+ scriptName: "okstra-spawn-followups.py",
20
+ args,
21
+ usage: USAGE,
22
+ });
23
+ }
@@ -1,7 +1,4 @@
1
- import { spawn } from "node:child_process";
2
- import { join } from "node:path";
3
- import { promises as fs } from "node:fs";
4
- import { resolvePaths } from "./paths.mjs";
1
+ import { runInstalledScript } from "./_python-helper.mjs";
5
2
 
6
3
  const USAGE = `okstra token-usage — collect token usage for a run
7
4
 
@@ -15,37 +12,9 @@ Usage:
15
12
  okstra token-usage <state-file> [--write] [--summary] [...]
16
13
 
17
14
  Arguments and flags after the state-file path are forwarded verbatim to
18
- the python helper. See \`python3 ~/.okstra/bin/okstra-token-usage.py --help\`
19
- for the full option list.
15
+ the python helper. See \`okstra token-usage --help\` for the full option list.
20
16
  `;
21
17
 
22
18
  export async function run(args) {
23
- if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
24
- process.stdout.write(USAGE);
25
- return args.length === 0 ? 2 : 0;
26
- }
27
-
28
- const paths = await resolvePaths();
29
- const script = join(paths.bin, "okstra-token-usage.py");
30
-
31
- try {
32
- await fs.access(script);
33
- } catch {
34
- process.stderr.write(
35
- `error: ${script} not found — run 'okstra install' (or 'okstra ensure-installed') first\n`,
36
- );
37
- return 1;
38
- }
39
-
40
- return await new Promise((resolve) => {
41
- const child = spawn("python3", [script, ...args], {
42
- stdio: "inherit",
43
- env: { ...process.env, PYTHONPATH: paths.pythonpath },
44
- });
45
- child.on("error", (err) => {
46
- process.stderr.write(`error: failed to spawn python3: ${err.message}\n`);
47
- resolve(1);
48
- });
49
- child.on("close", (code) => resolve(typeof code === "number" ? code : 1));
50
- });
19
+ return runInstalledScript({ scriptName: "okstra-token-usage.py", args, usage: USAGE });
51
20
  }