okstra 0.125.5 → 0.127.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/docs/architecture.md +2 -1
- package/docs/project-structure-overview.md +2 -0
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/report-writer-worker.md +2 -2
- package/runtime/bin/okstra-antigravity-exec.sh +8 -2
- package/runtime/bin/okstra-claude-exec.sh +8 -2
- package/runtime/bin/okstra-codex-exec.sh +65 -8
- package/runtime/prompts/lead/adapters/claude-code.md +1 -0
- package/runtime/prompts/lead/convergence.md +4 -1
- package/runtime/prompts/lead/okstra-lead-contract.md +24 -1
- package/runtime/prompts/lead/report-writer.md +1 -1
- package/runtime/prompts/lead/team-contract.md +3 -0
- package/runtime/prompts/profiles/_common-contract.md +1 -1
- package/runtime/python/okstra_ctl/design_surfaces.py +30 -14
- package/runtime/python/okstra_ctl/render_final_report.py +71 -5
- package/runtime/python/okstra_ctl/run.py +3 -1
- package/runtime/python/okstra_ctl/schema_excerpt.py +17 -1
- package/runtime/python/okstra_ctl/worker_heartbeat.py +50 -0
- package/runtime/python/okstra_ctl/worker_liveness.py +140 -0
- package/runtime/python/okstra_ctl/worker_prompt_headers.py +20 -0
- package/runtime/templates/reports/final-report.template.md +9 -9
- package/runtime/templates/worker-prompt-preamble.md +1 -0
- package/runtime/validators/forbidden_actions.py +43 -4
- package/runtime/validators/validate-implementation-plan-stages.py +6 -4
- package/runtime/validators/validate-report-views.py +4 -4
- package/runtime/validators/validate-run.py +117 -7
- package/runtime/validators/validate-schedule.py +6 -4
- package/runtime/validators/validate_fanout.py +4 -3
- package/runtime/validators/validate_improvement_report.py +6 -4
- package/runtime/validators/validate_session_conformance.py +16 -7
- package/src/cli-registry.mjs +7 -0
- package/src/commands/inspect/worker-liveness.mjs +31 -0
- package/src/commands/lifecycle/preflight.mjs +25 -2
- package/src/lib/helper-scripts.mjs +23 -0
- package/src/lib/python-helper.mjs +1 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { runPythonModule } from "../../lib/python-helper.mjs";
|
|
2
|
+
|
|
3
|
+
const USAGE = `okstra worker-liveness — report whether pending workers are still alive
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
okstra worker-liveness [--audit <path>]... [--prompt <path>]...
|
|
7
|
+
[--max-idle <seconds>] [--launch-grace <seconds>] [--json]
|
|
8
|
+
|
|
9
|
+
--audit a claude-worker audit sidecar; stale past the heartbeat cadence means
|
|
10
|
+
the in-process worker hung.
|
|
11
|
+
--prompt a CLI-wrapper prompt-history path; no sibling .log or .status.json
|
|
12
|
+
past the launch grace means the wrapper never started.
|
|
13
|
+
|
|
14
|
+
Output: JSON { ok, checkedAt, probes[], unhealthy[] }. Exit 1 when any worker is
|
|
15
|
+
stalled or did not launch, so a poll loop can branch on the exit code. Read-only:
|
|
16
|
+
it reports, it never kills or re-dispatches.
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
export async function run(args) {
|
|
20
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
21
|
+
process.stdout.write(USAGE);
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const result = await runPythonModule({
|
|
26
|
+
module: "okstra_ctl.worker_liveness",
|
|
27
|
+
args,
|
|
28
|
+
stdio: "inherit-stdout",
|
|
29
|
+
});
|
|
30
|
+
return result.code;
|
|
31
|
+
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { checkProject } from "./check-project.mjs";
|
|
2
2
|
import { runEnsureInstalled } from "./install.mjs";
|
|
3
|
+
import { missingHelperScripts } from "../../lib/helper-scripts.mjs";
|
|
4
|
+
import { resolveInstalledScript } from "../../lib/python-helper.mjs";
|
|
5
|
+
import { resolvePaths } from "../../lib/paths.mjs";
|
|
3
6
|
|
|
4
7
|
const USAGE = `okstra preflight — one-call skill preflight (ensure-installed + check-project)
|
|
5
8
|
|
|
@@ -11,8 +14,9 @@ verifies the target project has .okstra/project.json. Prints one JSON object:
|
|
|
11
14
|
|
|
12
15
|
ok: true {ok, projectRoot, projectJsonPath, projectId}
|
|
13
16
|
ok: false {ok, stage, reason, ...}
|
|
14
|
-
stage: install |
|
|
15
|
-
|
|
17
|
+
stage: install | helper_scripts_missing | resolve |
|
|
18
|
+
project_json_missing | project_json_invalid |
|
|
19
|
+
python | parse
|
|
16
20
|
|
|
17
21
|
Options:
|
|
18
22
|
--runtime <name> Runtime whose assets must be present (e.g. claude-code);
|
|
@@ -48,6 +52,12 @@ function emit(payload) {
|
|
|
48
52
|
process.stdout.write(JSON.stringify(payload, null, 2) + "\n");
|
|
49
53
|
}
|
|
50
54
|
|
|
55
|
+
// A BLOCKING lead step calls these mid-run; resolving them here turns a stale
|
|
56
|
+
// install into an up-front failure instead of a dead end hours into a run.
|
|
57
|
+
async function findMissingHelperScripts() {
|
|
58
|
+
return missingHelperScripts(await resolvePaths(), resolveInstalledScript);
|
|
59
|
+
}
|
|
60
|
+
|
|
51
61
|
export async function run(args) {
|
|
52
62
|
if (args.includes("--help") || args.includes("-h")) {
|
|
53
63
|
process.stdout.write(USAGE);
|
|
@@ -76,6 +86,19 @@ export async function run(args) {
|
|
|
76
86
|
return installCode === 2 ? 2 : 1;
|
|
77
87
|
}
|
|
78
88
|
|
|
89
|
+
const missingHelpers = await findMissingHelperScripts();
|
|
90
|
+
if (missingHelpers.length > 0) {
|
|
91
|
+
emit({
|
|
92
|
+
ok: false,
|
|
93
|
+
stage: "helper_scripts_missing",
|
|
94
|
+
missingHelpers,
|
|
95
|
+
reason:
|
|
96
|
+
`${missingHelpers.length} helper script(s) a lead prompt can call are not ` +
|
|
97
|
+
"installed — run 'okstra install' to repair before starting a run.",
|
|
98
|
+
});
|
|
99
|
+
return 1;
|
|
100
|
+
}
|
|
101
|
+
|
|
79
102
|
const { code, payload } = await checkProject({ cwd: opts.cwd });
|
|
80
103
|
emit(payload);
|
|
81
104
|
return code;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Single source of truth for the python helper scripts that `okstra <cmd>`
|
|
2
|
+
// subcommands front through runInstalledScript(). Preflight asserts every one
|
|
3
|
+
// of them resolves under ~/.okstra/bin so a stale install fails at the cheap
|
|
4
|
+
// environment gate instead of at the blocking lead step that calls it mid-run.
|
|
5
|
+
// A contract test keeps this list in step with the `scriptName:` literals in
|
|
6
|
+
// src/commands/**.
|
|
7
|
+
|
|
8
|
+
export const HELPER_SCRIPT_NAMES = Object.freeze([
|
|
9
|
+
"okstra-error-log.py",
|
|
10
|
+
"okstra-incremental-carry.py",
|
|
11
|
+
"okstra-incremental-scope.py",
|
|
12
|
+
"okstra-inject-report-index.py",
|
|
13
|
+
"okstra-render-final-report.py",
|
|
14
|
+
"okstra-render-report-views.py",
|
|
15
|
+
"okstra-spawn-followups.py",
|
|
16
|
+
"okstra-token-usage.py",
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
// `resolve` is the same resolver the wrappers call, so preflight cannot pass a
|
|
20
|
+
// script the dispatch path would then fail to find.
|
|
21
|
+
export function missingHelperScripts(paths, resolve) {
|
|
22
|
+
return HELPER_SCRIPT_NAMES.filter((name) => !resolve(paths, name));
|
|
23
|
+
}
|
|
@@ -4,7 +4,7 @@ import { join, resolve as resolvePath } from "node:path";
|
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { buildPythonpath, resolvePaths } from "./paths.mjs";
|
|
6
6
|
|
|
7
|
-
function resolveInstalledScript(paths, scriptName) {
|
|
7
|
+
export function resolveInstalledScript(paths, scriptName) {
|
|
8
8
|
// Prefer the installed copy under ~/.okstra/bin (what production users run);
|
|
9
9
|
// fall back to the in-repo source when invoked from a checkout that has not
|
|
10
10
|
// been installed (dev / CI).
|