okstra 0.28.0 → 0.29.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.
@@ -0,0 +1,67 @@
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";
6
+
7
+ const USAGE = `okstra render-views — render slim AI + self-contained HTML views of a final-report
8
+
9
+ A thin spawn shim over \`scripts/okstra-render-report-views.py\` (installed
10
+ at \`$HOME/.okstra/bin/okstra-render-report-views.py\`). Reads the final-
11
+ report MD and writes two siblings:
12
+
13
+ <stem>.slim.md — token-saving AI consumption copy
14
+ <stem>.html — single-file self-contained human view with form
15
+ controls on §5 clarification rows
16
+
17
+ Usage:
18
+ okstra render-views <path-to-final-report.md>
19
+ [--task-key <key>] [--task-type <type>] [--seq <NNN>]
20
+ [--source-report <project-relative-path>]
21
+
22
+ When the optional flags are omitted the script infers from the report
23
+ path and its '- Task Type:' / '- Task Key:' lines.
24
+ `;
25
+
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
+ 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));
66
+ });
67
+ }