@indigoai-us/hq-cli 5.315.0 → 5.317.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/CHANGELOG.md +13 -0
- package/assets/scaffold/core/scripts/detect-stale-review-base.sh +199 -0
- package/assets/scaffold/core/scripts/repo-run-registry.sh +408 -0
- package/assets/scaffold/core/scripts/session-journal.sh +301 -0
- package/assets/scaffold/core/scripts/session-project.sh +800 -0
- package/assets/scaffold/core/scripts/session-title-config.sh +76 -0
- package/assets/scaffold/core/scripts/session-title.sh +305 -0
- package/assets/scaffold/core/scripts/share-suggestion-state.sh +541 -0
- package/dist/command-catalog.generated.d.ts +97 -0
- package/dist/command-catalog.generated.js +120 -0
- package/dist/commands/bot-jobs.d.ts +5 -1
- package/dist/commands/bot-jobs.js +24 -4
- package/dist/commands/core-detect-stale-review-base-native.d.ts +23 -0
- package/dist/commands/core-detect-stale-review-base-native.js +178 -0
- package/dist/commands/core-hook-state-helpers-native.d.ts +11 -0
- package/dist/commands/core-hook-state-helpers-native.js +74 -0
- package/dist/commands/core-repo-run-registry-native.d.ts +19 -0
- package/dist/commands/core-repo-run-registry-native.js +357 -0
- package/dist/commands/core-session-helper-runtime.d.ts +10 -0
- package/dist/commands/core-session-helper-runtime.js +7 -0
- package/dist/commands/core-session-journal-native.d.ts +4 -0
- package/dist/commands/core-session-journal-native.js +327 -0
- package/dist/commands/core-session-project-native.d.ts +3 -0
- package/dist/commands/core-session-project-native.js +855 -0
- package/dist/commands/core-session-title-config-native.d.ts +4 -0
- package/dist/commands/core-session-title-config-native.js +77 -0
- package/dist/commands/core-session-title-native.d.ts +3 -0
- package/dist/commands/core-session-title-native.js +306 -0
- package/dist/commands/core-share-suggestion-state-native.d.ts +18 -0
- package/dist/commands/core-share-suggestion-state-native.js +445 -0
- package/dist/commands/core.js +66 -0
- package/dist/commands/lanes.js +35 -5
- package/dist/fast-core.d.ts +1 -0
- package/dist/fast-core.js +10 -6
- package/dist/fast-scaffold.js +33 -0
- package/dist/lib/bot/job-quiet-flag.d.ts +4 -0
- package/dist/lib/bot/job-quiet-flag.js +14 -0
- package/dist/lib/bot/job-run.d.ts +5 -0
- package/dist/lib/bot/job-run.js +23 -3
- package/dist/lib/bot/run.d.ts +2 -0
- package/dist/lib/bot/run.js +15 -3
- package/dist/lib/core-utils/common.d.ts +0 -1
- package/dist/lib/core-utils/common.js +0 -9
- package/dist/lib/lanes/autopilot.d.ts +5 -1
- package/dist/lib/lanes/autopilot.js +72 -3
- package/dist/lib/lanes/disk-guard.d.ts +3 -4
- package/dist/lib/lanes/disk-guard.js +2 -2
- package/dist/lib/lanes/flag-keys.d.ts +3 -0
- package/dist/lib/lanes/flag-keys.js +3 -0
- package/dist/lib/lanes/hooks-install.js +78 -2
- package/dist/lib/lanes/keep-alive-audit.d.ts +6 -5
- package/dist/lib/lanes/outpost-dispatch.d.ts +9 -0
- package/dist/lib/lanes/outpost-dispatch.js +22 -0
- package/dist/utils/version-gate.js +8 -7
- package/package.json +1 -1
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
/** Native, dependency-light port of repo-run-registry.sh. */
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { serializeJqJson } from "../lib/core-utils/jq-json-serializer.js";
|
|
7
|
+
export const REPO_RUN_REGISTRY_ASSET = "core/scripts/repo-run-registry.sh";
|
|
8
|
+
function jsonOutput(code, value, format = "pretty") {
|
|
9
|
+
return { code, stdout: value === undefined ? "" : serializeJqJson(value, format), stderr: "" };
|
|
10
|
+
}
|
|
11
|
+
function iso(d) { return d.toISOString().replace(/\.\d{3}Z$/, "Z"); }
|
|
12
|
+
function jqOr(value, fallback) { return value === null || value === undefined || value === false ? fallback : value; }
|
|
13
|
+
function parseNaturalDateEpoch(value) {
|
|
14
|
+
const result = spawnSync("date", ["-u", "-d", value, "+%s"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
|
|
15
|
+
if (result.status !== 0)
|
|
16
|
+
return 0;
|
|
17
|
+
const parsed = Number(result.stdout.trim());
|
|
18
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
19
|
+
}
|
|
20
|
+
function epoch(value, parseDate) {
|
|
21
|
+
if (typeof value !== "string")
|
|
22
|
+
return 0;
|
|
23
|
+
const isoMatch = value.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$/);
|
|
24
|
+
if (isoMatch) {
|
|
25
|
+
const parsed = Date.parse(value);
|
|
26
|
+
if (Number.isFinite(parsed))
|
|
27
|
+
return Math.floor(parsed / 1000);
|
|
28
|
+
}
|
|
29
|
+
return parseDate(value);
|
|
30
|
+
}
|
|
31
|
+
function pathAbs(value, cwd, f) {
|
|
32
|
+
if (value.startsWith("/"))
|
|
33
|
+
return value;
|
|
34
|
+
const parent = path.dirname(value);
|
|
35
|
+
try {
|
|
36
|
+
f.statSync(path.resolve(cwd, parent));
|
|
37
|
+
return path.join(path.resolve(cwd, parent), path.basename(value));
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function parseStaleMinutes(root, f) {
|
|
44
|
+
const personal = path.join(root, "personal/settings/orchestrator.yaml");
|
|
45
|
+
const core = path.join(root, "core/settings/orchestrator.yaml");
|
|
46
|
+
const config = f.existsSync(personal) ? personal : core;
|
|
47
|
+
try {
|
|
48
|
+
const lines = f.readFileSync(config, "utf8").split(/\r?\n/);
|
|
49
|
+
let inRepo = false;
|
|
50
|
+
for (const line of lines) {
|
|
51
|
+
if (/^repo_coordination\s*:\s*(?:#.*)?$/.test(line)) {
|
|
52
|
+
inRepo = true;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (inRepo && /^\S/.test(line))
|
|
56
|
+
inRepo = false;
|
|
57
|
+
if (inRepo) {
|
|
58
|
+
const match = line.match(/^\s+stale_heartbeat_minutes\s*:\s*([^#\s]+)(?:\s+#.*)?$/);
|
|
59
|
+
if (match) {
|
|
60
|
+
const value = match[1].replace(/^(['"])(.*?)\1$/, "$2");
|
|
61
|
+
if (value === "null" || value === "~")
|
|
62
|
+
return 15;
|
|
63
|
+
const n = Number(value);
|
|
64
|
+
return Number.isFinite(n) ? n : 15;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch { /* shell falls back to 15 when yq or the config is unavailable */ }
|
|
70
|
+
return 15;
|
|
71
|
+
}
|
|
72
|
+
function defaultSleep(ms) { Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms); }
|
|
73
|
+
export function runRepoRunRegistry(args, deps) {
|
|
74
|
+
const f = deps.fs ?? fs, env = deps.env ?? process.env, now = deps.now ?? (() => new Date());
|
|
75
|
+
const pid = deps.pid ?? process.pid, sleep = deps.sleep ?? defaultSleep;
|
|
76
|
+
const root = deps.root || env.HQ_ROOT || process.cwd();
|
|
77
|
+
const regDir = path.join(root, "workspace/orchestrator"), regFile = path.join(regDir, "active-runs.json"), lockDir = `${regFile}.lock`;
|
|
78
|
+
const output = (code = 0, stdout = "", stderr = "") => ({ code, stdout, stderr });
|
|
79
|
+
const die = (message) => output(1, "", `ERROR: ${message}\n`);
|
|
80
|
+
const readState = () => {
|
|
81
|
+
try {
|
|
82
|
+
const parsed = JSON.parse(f.readFileSync(regFile, "utf8"));
|
|
83
|
+
return parsed && typeof parsed === "object" ? parsed : { version: 1, runs: [] };
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (error.code === "ENOENT")
|
|
87
|
+
return { version: 1, runs: [] };
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
const ensureReg = () => {
|
|
92
|
+
f.mkdirSync(regDir, { recursive: true });
|
|
93
|
+
if (!f.existsSync(regFile))
|
|
94
|
+
f.writeFileSync(regFile, '{"version":1,"runs":[]}\n');
|
|
95
|
+
};
|
|
96
|
+
const writeState = (state) => {
|
|
97
|
+
const tmp = `${regFile}.tmp.${pid}`;
|
|
98
|
+
f.writeFileSync(tmp, serializeJqJson(state, "pretty"));
|
|
99
|
+
f.renameSync(tmp, regFile);
|
|
100
|
+
};
|
|
101
|
+
const writeEmptyState = () => {
|
|
102
|
+
const tmp = `${regFile}.tmp.${pid}`;
|
|
103
|
+
f.writeFileSync(tmp, "");
|
|
104
|
+
f.renameSync(tmp, regFile);
|
|
105
|
+
};
|
|
106
|
+
const lock = () => {
|
|
107
|
+
try {
|
|
108
|
+
f.mkdirSync(regDir, { recursive: true });
|
|
109
|
+
}
|
|
110
|
+
catch { /* shell ignores parent mkdir failure here */ }
|
|
111
|
+
for (let tries = 1;; tries += 1) {
|
|
112
|
+
try {
|
|
113
|
+
f.mkdirSync(lockDir);
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
if (tries >= 50) {
|
|
118
|
+
if (f.existsSync(lockDir)) {
|
|
119
|
+
let mtimeMs = 0;
|
|
120
|
+
try {
|
|
121
|
+
mtimeMs = f.statSync(lockDir).mtimeMs;
|
|
122
|
+
}
|
|
123
|
+
catch { /* shell falls back to epoch zero when stat fails */ }
|
|
124
|
+
const age = Math.floor(now().getTime() / 1000) - Math.floor(mtimeMs / 1000);
|
|
125
|
+
if (age > 60) {
|
|
126
|
+
f.rmSync(lockDir, { recursive: true, force: true });
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
sleep(100);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return false;
|
|
136
|
+
};
|
|
137
|
+
const unlock = () => { try {
|
|
138
|
+
f.rmSync(lockDir, { recursive: true, force: true });
|
|
139
|
+
}
|
|
140
|
+
catch { /* shell ignores unlock failure */ } };
|
|
141
|
+
const alive = (raw) => {
|
|
142
|
+
if (raw === "" || raw === null || raw === undefined || raw === false || raw === "null")
|
|
143
|
+
return false;
|
|
144
|
+
const value = Number(raw);
|
|
145
|
+
if (!Number.isFinite(value))
|
|
146
|
+
return false;
|
|
147
|
+
try {
|
|
148
|
+
return deps.isPidAlive ? deps.isPidAlive(value) : (process.kill(value, 0), true);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
const parseDate = deps.parseDateEpoch ?? parseNaturalDateEpoch;
|
|
155
|
+
const staleMinutes = parseStaleMinutes(root, f);
|
|
156
|
+
const prune = () => {
|
|
157
|
+
ensureReg();
|
|
158
|
+
const state = readState();
|
|
159
|
+
if (state === null) {
|
|
160
|
+
writeEmptyState();
|
|
161
|
+
return 0;
|
|
162
|
+
}
|
|
163
|
+
const runs = Array.isArray(state.runs) ? state.runs : [];
|
|
164
|
+
const cutoff = Math.floor(now().getTime() / 1000) - staleMinutes * 60;
|
|
165
|
+
const kept = runs.filter((entry) => alive(entry?.pid) && epoch(jqOr(entry?.heartbeat_at, jqOr(entry?.started_at, "")), parseDate) >= cutoff);
|
|
166
|
+
state.runs = kept;
|
|
167
|
+
writeState(state);
|
|
168
|
+
return runs.length - kept.length;
|
|
169
|
+
};
|
|
170
|
+
const withPrune = () => {
|
|
171
|
+
if (!lock())
|
|
172
|
+
return;
|
|
173
|
+
try {
|
|
174
|
+
prune();
|
|
175
|
+
}
|
|
176
|
+
catch { /* _prune_stale_locked suppresses pruning errors */ }
|
|
177
|
+
finally {
|
|
178
|
+
unlock();
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
const owningRepo = (raw) => {
|
|
182
|
+
let target = pathAbs(raw, deps.cwd, f);
|
|
183
|
+
while (target && !f.existsSync(target)) {
|
|
184
|
+
const parent = path.dirname(target);
|
|
185
|
+
if (parent === target)
|
|
186
|
+
return "";
|
|
187
|
+
target = parent;
|
|
188
|
+
}
|
|
189
|
+
let dir = target;
|
|
190
|
+
try {
|
|
191
|
+
if (f.statSync(dir).isFile())
|
|
192
|
+
dir = path.dirname(dir);
|
|
193
|
+
}
|
|
194
|
+
catch { /* keep resolved path */ }
|
|
195
|
+
while (dir !== "/" && dir) {
|
|
196
|
+
if (f.existsSync(path.join(dir, ".git")))
|
|
197
|
+
return dir;
|
|
198
|
+
const parent = path.dirname(dir);
|
|
199
|
+
if (parent === dir)
|
|
200
|
+
break;
|
|
201
|
+
dir = parent;
|
|
202
|
+
}
|
|
203
|
+
return "";
|
|
204
|
+
};
|
|
205
|
+
const valueAfter = (list, key) => { const index = list.indexOf(key); return index >= 0 ? (list[index + 1] ?? "") : ""; };
|
|
206
|
+
const sub = args[0] ?? "";
|
|
207
|
+
if (!sub)
|
|
208
|
+
return die("usage: repo-run-registry.sh <subcommand> [args...]");
|
|
209
|
+
const rest = args.slice(1);
|
|
210
|
+
const useShellFallback = () => {
|
|
211
|
+
if (!deps.runShellFallback)
|
|
212
|
+
return undefined;
|
|
213
|
+
if (f.existsSync(regFile)) {
|
|
214
|
+
try {
|
|
215
|
+
const state = JSON.parse(f.readFileSync(regFile, "utf8"));
|
|
216
|
+
if (!state || typeof state !== "object" || !Array.isArray(state.runs))
|
|
217
|
+
return deps.runShellFallback(args);
|
|
218
|
+
if ((sub === "owner-of" || sub === "check") && state.runs.some((run) => typeof run?.scope === "string" && run.scope.startsWith("worktree:"))) {
|
|
219
|
+
return deps.runShellFallback(args);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
if (error.code !== "ENOENT")
|
|
224
|
+
return deps.runShellFallback(args);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (sub === "register") {
|
|
228
|
+
const valueFlags = ["--run-id", "--pid", "--session-id", "--command", "--project", "--repo", "--scope", "--host"];
|
|
229
|
+
if (rest.length > 0 && valueFlags.includes(rest.at(-1)))
|
|
230
|
+
return deps.runShellFallback(args);
|
|
231
|
+
const rawPid = valueAfter(rest, "--pid");
|
|
232
|
+
if (rawPid && (!Number.isFinite(Number(rawPid)) || !/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(rawPid))) {
|
|
233
|
+
return deps.runShellFallback(args);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return undefined;
|
|
237
|
+
};
|
|
238
|
+
const fallbackResult = useShellFallback();
|
|
239
|
+
if (fallbackResult)
|
|
240
|
+
return fallbackResult;
|
|
241
|
+
try {
|
|
242
|
+
if (sub === "register") {
|
|
243
|
+
let runId = valueAfter(rest, "--run-id"), runPid = valueAfter(rest, "--pid"), sessionId = valueAfter(rest, "--session-id"), command = valueAfter(rest, "--command"), project = valueAfter(rest, "--project"), repo = valueAfter(rest, "--repo"), scope = valueAfter(rest, "--scope"), host = valueAfter(rest, "--host");
|
|
244
|
+
if (!runPid || !command || !repo || !scope)
|
|
245
|
+
return die("register requires --pid --command --repo --scope");
|
|
246
|
+
repo = pathAbs(repo, deps.cwd, f);
|
|
247
|
+
if (!runId)
|
|
248
|
+
runId = `${command.replaceAll("/", "-")}-${Math.floor(now().getTime() / 1000)}-${project || "none"}-${runPid}`;
|
|
249
|
+
if (!host)
|
|
250
|
+
host = (deps.hostname ?? (() => os.hostname().split(".")[0] ?? "unknown"))();
|
|
251
|
+
if (!lock())
|
|
252
|
+
return die("registry lock timeout");
|
|
253
|
+
try {
|
|
254
|
+
ensureReg();
|
|
255
|
+
const pruned = prune();
|
|
256
|
+
const state = readState(), timestamp = iso(now());
|
|
257
|
+
if (state === null)
|
|
258
|
+
return output(0, `${runId}\n`, "");
|
|
259
|
+
state.runs = (Array.isArray(state.runs) ? state.runs : []).filter((run) => run?.run_id !== runId);
|
|
260
|
+
state.runs.push({ run_id: runId, pid: Number(runPid), session_id: sessionId, command, project, repo_path: repo, scope, host, started_at: timestamp, heartbeat_at: timestamp });
|
|
261
|
+
writeState(state);
|
|
262
|
+
if (pruned > 0)
|
|
263
|
+
return output(0, `${runId}\n`, `[repo-run-registry] pruned ${pruned} stale entries\n`);
|
|
264
|
+
}
|
|
265
|
+
finally {
|
|
266
|
+
unlock();
|
|
267
|
+
}
|
|
268
|
+
return output(0, `${runId}\n`, "");
|
|
269
|
+
}
|
|
270
|
+
if (sub === "deregister") {
|
|
271
|
+
const runId = valueAfter(rest, "--run-id");
|
|
272
|
+
if (!runId)
|
|
273
|
+
return die("deregister requires --run-id");
|
|
274
|
+
if (!lock())
|
|
275
|
+
return die("registry lock timeout");
|
|
276
|
+
try {
|
|
277
|
+
ensureReg();
|
|
278
|
+
const state = readState();
|
|
279
|
+
state.runs = (Array.isArray(state.runs) ? state.runs : []).filter((run) => run?.run_id !== runId);
|
|
280
|
+
writeState(state);
|
|
281
|
+
}
|
|
282
|
+
finally {
|
|
283
|
+
unlock();
|
|
284
|
+
}
|
|
285
|
+
return output();
|
|
286
|
+
}
|
|
287
|
+
if (sub === "heartbeat") {
|
|
288
|
+
const runId = valueAfter(rest, "--run-id");
|
|
289
|
+
if (!runId)
|
|
290
|
+
return die("heartbeat requires --run-id");
|
|
291
|
+
if (!lock())
|
|
292
|
+
return die("registry lock timeout");
|
|
293
|
+
try {
|
|
294
|
+
ensureReg();
|
|
295
|
+
const state = readState(), timestamp = iso(now());
|
|
296
|
+
state.runs = (Array.isArray(state.runs) ? state.runs : []).map((run) => run?.run_id === runId ? { ...run, heartbeat_at: timestamp } : run);
|
|
297
|
+
writeState(state);
|
|
298
|
+
}
|
|
299
|
+
finally {
|
|
300
|
+
unlock();
|
|
301
|
+
}
|
|
302
|
+
return output();
|
|
303
|
+
}
|
|
304
|
+
if (sub === "list") {
|
|
305
|
+
ensureReg();
|
|
306
|
+
withPrune();
|
|
307
|
+
const state = readState();
|
|
308
|
+
return state === null ? output() : jsonOutput(0, Array.isArray(state.runs) ? state.runs : []);
|
|
309
|
+
}
|
|
310
|
+
if (sub === "clean-stale") {
|
|
311
|
+
if (!lock())
|
|
312
|
+
return die("registry lock timeout");
|
|
313
|
+
try {
|
|
314
|
+
const count = prune();
|
|
315
|
+
return output(0, "", count > 0 ? `[repo-run-registry] pruned ${count} stale entries\n` : "");
|
|
316
|
+
}
|
|
317
|
+
finally {
|
|
318
|
+
unlock();
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (sub === "owner-of" || sub === "check") {
|
|
322
|
+
const target = valueAfter(rest, sub === "owner-of" ? "--path" : "--target");
|
|
323
|
+
if (!target)
|
|
324
|
+
return die(`${sub} requires --${sub === "owner-of" ? "path" : "target"}`);
|
|
325
|
+
if (sub === "check") {
|
|
326
|
+
ensureReg();
|
|
327
|
+
withPrune();
|
|
328
|
+
}
|
|
329
|
+
const repo = owningRepo(target);
|
|
330
|
+
if (!repo)
|
|
331
|
+
return sub === "owner-of" ? output(0, "\n", "") : output();
|
|
332
|
+
if (sub === "owner-of") {
|
|
333
|
+
ensureReg();
|
|
334
|
+
withPrune();
|
|
335
|
+
}
|
|
336
|
+
const state = readState();
|
|
337
|
+
if (state === null)
|
|
338
|
+
return output();
|
|
339
|
+
const absoluteTarget = pathAbs(target, deps.cwd, f), myPid = valueAfter(rest, "--pid") || "0", mySession = valueAfter(rest, "--session-id") || "__none__";
|
|
340
|
+
const runs = Array.isArray(state.runs) ? state.runs : [];
|
|
341
|
+
const covers = (run) => (run?.scope === "repo" && run?.repo_path === repo) || (typeof run?.scope === "string" && run.scope.startsWith("worktree:") && absoluteTarget.startsWith(run.scope.slice("worktree:".length)));
|
|
342
|
+
if (sub === "owner-of")
|
|
343
|
+
return jsonOutput(0, runs.filter(covers));
|
|
344
|
+
const owners = runs.filter((run) => covers(run) && String(run?.pid) !== myPid && run?.session_id !== mySession);
|
|
345
|
+
if (!owners.length)
|
|
346
|
+
return output();
|
|
347
|
+
const lines = owners.map((run) => `run_id=${run?.run_id} pid=${run?.pid} command=${run?.command} project=${run?.project} scope=${run?.scope} repo=${run?.repo_path} started=${run?.started_at} heartbeat=${run?.heartbeat_at}`).join("\n") + "\n";
|
|
348
|
+
return output(2, "", lines);
|
|
349
|
+
}
|
|
350
|
+
return die(`unknown subcommand: ${sub}`);
|
|
351
|
+
}
|
|
352
|
+
catch (error) {
|
|
353
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
354
|
+
return output(1, "", `${detail}\n`);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
//# sourceMappingURL=core-repo-run-registry-native.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type SessionHelperRuntimeOverrides = {
|
|
2
|
+
env?: NodeJS.ProcessEnv;
|
|
3
|
+
now?: () => Date;
|
|
4
|
+
};
|
|
5
|
+
export type SessionHelperRuntime = {
|
|
6
|
+
env: NodeJS.ProcessEnv;
|
|
7
|
+
now: () => Date;
|
|
8
|
+
};
|
|
9
|
+
export declare function resolveSessionHelperRuntime(overrides?: SessionHelperRuntimeOverrides): SessionHelperRuntime;
|
|
10
|
+
//# sourceMappingURL=core-session-helper-runtime.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type SessionHelperRuntimeOverrides } from "./core-session-helper-runtime.js";
|
|
2
|
+
/** Native implementation of the fail-soft session journal helper. */
|
|
3
|
+
export declare function runSessionJournalFast(args: readonly string[], _stdin: string, cwd: string, hqRoot: string | undefined, dependencies?: SessionHelperRuntimeOverrides): number;
|
|
4
|
+
//# sourceMappingURL=core-session-journal-native.d.ts.map
|