@indigoai-us/hq-cli 5.345.122 → 5.345.124

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 (53) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +15 -0
  3. package/assets/scaffold/core/scripts/handoff-sync-prefetch.sh +121 -0
  4. package/assets/scaffold/core/scripts/handoff-sync-publish.sh +124 -0
  5. package/assets/scaffold/core/scripts/knowledge-pulse-lock.sh +27 -0
  6. package/assets/scaffold/core/scripts/lib/session-skill-catalog.sh +226 -0
  7. package/assets/scaffold/core/scripts/skill-installed.sh +43 -0
  8. package/assets/scaffold/core/scripts/work-mesh-project-registration-offer.sh +77 -0
  9. package/assets/scaffold/core/scripts/workflow-gate.sh +247 -0
  10. package/dist/command-catalog.generated.d.ts +332 -0
  11. package/dist/command-catalog.generated.js +402 -0
  12. package/dist/command-registration-plan.d.ts +6 -0
  13. package/dist/command-registration-plan.js +1 -0
  14. package/dist/commands/core-bucket-c-handoff-sync-fast.d.ts +3 -0
  15. package/dist/commands/core-bucket-c-handoff-sync-fast.js +16 -0
  16. package/dist/commands/core-bucket-c-handoff-sync-native.d.ts +45 -0
  17. package/dist/commands/core-bucket-c-handoff-sync-native.js +300 -0
  18. package/dist/commands/core-bucket-c-small-fast.d.ts +5 -0
  19. package/dist/commands/core-bucket-c-small-fast.js +19 -0
  20. package/dist/commands/core-bucket-c-small-native.d.ts +11 -0
  21. package/dist/commands/core-bucket-c-small-native.js +197 -0
  22. package/dist/commands/core-bucket-c-work-mesh-offer-native.d.ts +7 -0
  23. package/dist/commands/core-bucket-c-work-mesh-offer-native.js +147 -0
  24. package/dist/commands/core-bucket-c-workflow-gate-fast.d.ts +3 -0
  25. package/dist/commands/core-bucket-c-workflow-gate-fast.js +17 -0
  26. package/dist/commands/core-bucket-c-workflow-gate-native.d.ts +7 -0
  27. package/dist/commands/core-bucket-c-workflow-gate-native.js +250 -0
  28. package/dist/commands/core-derive-trigger-facts-native.js +4 -1
  29. package/dist/commands/core.js +37 -0
  30. package/dist/commands/deploy-comments.d.ts +2 -0
  31. package/dist/commands/deploy-comments.js +2 -2
  32. package/dist/commands/deploy-list.d.ts +22 -0
  33. package/dist/commands/deploy-list.js +153 -0
  34. package/dist/commands/lanes.js +41 -2
  35. package/dist/commands/mesh.js +457 -16
  36. package/dist/fast-scaffold.js +74 -0
  37. package/dist/lib/core-utils/session-company.d.ts +3 -0
  38. package/dist/lib/core-utils/session-company.js +78 -0
  39. package/dist/lib/lanes/quota-notice.d.ts +24 -0
  40. package/dist/lib/lanes/quota-notice.js +61 -0
  41. package/dist/lib/lanes/quota.d.ts +44 -8
  42. package/dist/lib/lanes/quota.js +187 -45
  43. package/dist/lib/lanes/reconcile.js +17 -1
  44. package/dist/lib/lanes/watcher.js +13 -1
  45. package/dist/lib/mesh/api.d.ts +2 -0
  46. package/dist/lib/mesh/api.js +3 -0
  47. package/dist/lib/mesh/client.d.ts +6 -1
  48. package/dist/lib/mesh/client.js +18 -5
  49. package/dist/lib/mesh/team-coordination.d.ts +106 -0
  50. package/dist/lib/mesh/team-coordination.js +297 -0
  51. package/dist/lib/work-context/auto-bind.d.ts +75 -0
  52. package/dist/lib/work-context/auto-bind.js +245 -0
  53. package/package.json +1 -1
@@ -0,0 +1,300 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { spawn } from "node:child_process";
4
+ import { fileURLToPath } from "node:url";
5
+ import { buildSpawnPlan } from "../utils/windows-spawn.js";
6
+ export const HANDOFF_SYNC_PREFETCH_ASSET = "core/scripts/handoff-sync-prefetch.sh";
7
+ export const HANDOFF_SYNC_PUBLISH_ASSET = "core/scripts/handoff-sync-publish.sh";
8
+ const PREFETCH_HELP = [
9
+ "!/bin/bash",
10
+ "handoff-sync-prefetch.sh - pull the latest session continuity pointer before",
11
+ "a fresh session reads it.",
12
+ "",
13
+ "`/startwork` and `/resumework` both read `workspace/threads/handoff.json`",
14
+ "(and the thread file it references) to decide what to resume. On a second",
15
+ "device those files only exist after a vault pull has landed, so a naive",
16
+ "resume right after sign-in sees stale state. This helper runs that pull",
17
+ "BEFORE the skill reads the pointer.",
18
+ "",
19
+ "Fail-soft:",
20
+ " - no-op when the `hq` CLI is missing",
21
+ " - no-op when offline or not logged in",
22
+ " - timeboxed (default 25s)",
23
+ " - never fails the caller: a successful or failed pull are both exit 0;",
24
+ " the caller falls through to the local pointer either way.",
25
+ "",
26
+ "Usage:",
27
+ " handoff-sync-prefetch.sh [--hq-root PATH] [--timeout SECONDS] [--log PATH]",
28
+ "",
29
+ "Prints one line of status on stdout for the caller to echo (or ignore):",
30
+ " `ok` - pull completed within the timeout",
31
+ " `missing-cli` - `hq` is not on PATH; nothing was attempted",
32
+ " `skipped` - CLI is present but the pull refused to start (no login,",
33
+ " locked, etc.); local pointer is still used",
34
+ " `timed-out` - pull exceeded the timeout and was killed",
35
+ " `error:<rc>` - pull returned a non-zero exit code",
36
+ "",
37
+ "Exits 0 in every case so a shell `|| true` is unnecessary at call sites.",
38
+ "",
39
+ ].join("\n");
40
+ const PUBLISH_HELP = [
41
+ "!/bin/bash",
42
+ "handoff-sync-publish.sh - push the session continuity pointer to the personal vault.",
43
+ "",
44
+ "Cross-device handoff depends on `workspace/threads/handoff.json` and the",
45
+ "single thread file it points to reaching the vault before a fresh session on",
46
+ "another machine runs `/startwork` or `/resumework`. The workspace tree is",
47
+ "otherwise machine-local (`PERSONAL_VAULT_EXCLUDED_TOP_LEVEL`), so without a",
48
+ "push run between the two sessions machine B sees stale state or no handoff",
49
+ "at all. See hq-cloud-sync `computeContinuityPointerPaths`.",
50
+ "",
51
+ "This helper is intentionally minimal and fail-soft:",
52
+ " - no-op when the `hq` CLI is missing (fresh install, agent box without CLI)",
53
+ " - no-op when offline or not logged in (vault push will fail; we never",
54
+ " block /handoff on cloud reachability)",
55
+ " - timeboxed (default 25s) so a slow network cannot stall session end",
56
+ " - detached by default; the handoff-finalize payload is already emitted",
57
+ "",
58
+ "Usage:",
59
+ " handoff-sync-publish.sh [--hq-root PATH] [--timeout SECONDS]",
60
+ " [--sync] [--log PATH]",
61
+ "",
62
+ " --sync Run synchronously in the foreground and return the exit code.",
63
+ " Default behaviour forks a backgrounded worker and prints its PID.",
64
+ " --timeout Wall-clock bound in seconds; the push is killed on expiry.",
65
+ " --log Append combined stdout/stderr to this path (default: `/tmp/handoff-sync-publish.log`).",
66
+ "",
67
+ "Exits 0 on dispatch (background mode) or on push success (sync mode).",
68
+ "A sync-mode failure returns the underlying `hq` exit, or 124 on timeout.",
69
+ "",
70
+ ].join("\n");
71
+ const result = (code, stdout = "", stderr = "") => ({ code, stdout, stderr });
72
+ const fail = (message, code = 1) => result(code, "", message + "\n");
73
+ const defaults = () => ({ spawn: (command, args, options) => spawn(command, args, options), cwd: process.cwd(), env: process.env, pid: process.pid, now: () => new Date() });
74
+ function parseArgs(args, kind, env = process.env) {
75
+ let root = "";
76
+ let timeout = kind === "prefetch"
77
+ ? (env.HQ_HANDOFF_PREFETCH_TIMEOUT ?? "25")
78
+ : (env.HQ_HANDOFF_PUBLISH_TIMEOUT ?? "25");
79
+ let log = kind === "prefetch" ? "/tmp/handoff-sync-prefetch.log" : "/tmp/handoff-sync-publish.log";
80
+ let sync = false;
81
+ let child = false;
82
+ for (let index = 0; index < args.length;) {
83
+ const token = args[index];
84
+ if (token === "--hq-root" || token === "--timeout" || token === "--log") {
85
+ if (index + 1 >= args.length) {
86
+ const script = kind === "prefetch" ? "handoff-sync-prefetch.sh" : "handoff-sync-publish.sh";
87
+ const line = kind === "prefetch"
88
+ ? { "--hq-root": 39, "--timeout": 40, "--log": 41 }[token]
89
+ : { "--hq-root": 39, "--timeout": 40, "--log": 42 }[token];
90
+ const scriptPath = shellScriptPath(fileURLToPath(new URL(`../../assets/scaffold/core/scripts/${script}`, import.meta.url)));
91
+ return result(1, "", `${scriptPath}: line ${line}: $2: unbound variable\n`);
92
+ }
93
+ const value = args[index + 1];
94
+ if (token === "--hq-root")
95
+ root = value;
96
+ else if (token === "--timeout")
97
+ timeout = value;
98
+ else
99
+ log = value;
100
+ index += 2;
101
+ continue;
102
+ }
103
+ if (token === "--sync" && kind === "publish") {
104
+ sync = true;
105
+ index += 1;
106
+ continue;
107
+ }
108
+ if (token === "--child" && kind === "publish") {
109
+ sync = true;
110
+ child = true;
111
+ index += 1;
112
+ continue;
113
+ }
114
+ if (token === "-h" || token === "--help")
115
+ return result(0, `${kind === "prefetch" ? PREFETCH_HELP : PUBLISH_HELP}\n`);
116
+ return fail(`handoff-sync-${kind}: unknown arg: ${token}`, 2);
117
+ }
118
+ return { root, timeout, log, sync, child };
119
+ }
120
+ function shellScriptPath(value) {
121
+ if (process.platform !== "win32")
122
+ return value;
123
+ const normalized = value.replaceAll("\\", "/");
124
+ const drivePath = normalized.match(/^([A-Za-z]):\/(.*)$/);
125
+ return drivePath ? `/${drivePath[1].toLowerCase()}/${drivePath[2]}` : normalized;
126
+ }
127
+ function exitCode(code, signal) {
128
+ if (code !== null)
129
+ return code;
130
+ if (signal === "SIGTERM")
131
+ return 143;
132
+ if (signal === "SIGKILL")
133
+ return 137;
134
+ return 1;
135
+ }
136
+ function runWithTimeout(deps, logFd, timeoutText, args) {
137
+ return new Promise((resolve) => {
138
+ let child;
139
+ try {
140
+ const plan = buildSpawnPlan("hq", args);
141
+ child = deps.spawn(plan.cmd, plan.args, {
142
+ cwd: deps.cwd, env: deps.env, stdio: ["ignore", logFd, logFd], windowsHide: true,
143
+ shell: plan.shell,
144
+ ...(plan.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}),
145
+ });
146
+ }
147
+ catch {
148
+ fs.writeSync(logFd, "spawn hq failed\n");
149
+ resolve({ code: 127, timedOut: false });
150
+ return;
151
+ }
152
+ const seconds = Number(timeoutText);
153
+ let timedOut = false;
154
+ let killTimer;
155
+ let timeoutTimer;
156
+ if (Number.isFinite(seconds)) {
157
+ timeoutTimer = setTimeout(() => {
158
+ timedOut = true;
159
+ child.kill("SIGTERM");
160
+ killTimer = setTimeout(() => child.kill("SIGKILL"), 1000);
161
+ }, Math.max(0, seconds) * 1000);
162
+ timeoutTimer.unref();
163
+ }
164
+ child.once("error", () => {
165
+ if (timeoutTimer)
166
+ clearTimeout(timeoutTimer);
167
+ if (killTimer)
168
+ clearTimeout(killTimer);
169
+ fs.writeSync(logFd, "hq: command not found\n");
170
+ resolve({ code: 127, timedOut });
171
+ });
172
+ child.once("exit", (code, signal) => {
173
+ if (timeoutTimer)
174
+ clearTimeout(timeoutTimer);
175
+ if (killTimer)
176
+ clearTimeout(killTimer);
177
+ resolve({ code: exitCode(code, signal), timedOut });
178
+ });
179
+ });
180
+ }
181
+ function openLog(log) {
182
+ try {
183
+ fs.mkdirSync(path.dirname(log), { recursive: true });
184
+ }
185
+ catch { /* the shell ignores mkdir failure */ }
186
+ try {
187
+ return fs.openSync(log, "a");
188
+ }
189
+ catch (cause) {
190
+ return fail(String(cause.message));
191
+ }
192
+ }
193
+ function header(deps, root, kind, timeout, mode = "") {
194
+ return `\n--- handoff-sync-${kind} ${deps.now().toISOString().replace(/\.\d{3}Z$/, "Z")} hq_root=${root} ${mode ? `mode=${mode} ` : ""}timeout=${timeout}s ---\n`;
195
+ }
196
+ function resolveRoot(root, deps) {
197
+ return root || (deps.env.HQ_ROOT ?? deps.cwd);
198
+ }
199
+ function commandOnPath(name, env) {
200
+ const pathKey = Object.keys(env).find((key) => key.toUpperCase() === "PATH");
201
+ const searchPath = pathKey ? env[pathKey] ?? "" : "";
202
+ const windows = process.platform === "win32";
203
+ const pathExtKey = Object.keys(env).find((key) => key.toUpperCase() === "PATHEXT");
204
+ const extensions = windows
205
+ ? (pathExtKey ? env[pathExtKey] ?? ".COM;.EXE;.BAT;.CMD" : ".COM;.EXE;.BAT;.CMD").split(";")
206
+ : [""];
207
+ const names = windows && path.extname(name) ? [name] : extensions.map((extension) => `${name}${extension}`);
208
+ for (const directory of searchPath.split(path.delimiter)) {
209
+ for (const executable of names) {
210
+ try {
211
+ const target = path.join(directory || ".", executable);
212
+ fs.accessSync(target, windows ? fs.constants.F_OK : fs.constants.X_OK);
213
+ if (fs.statSync(target).isFile())
214
+ return true;
215
+ }
216
+ catch {
217
+ // command -v advances through the path when an entry is absent or unusable.
218
+ }
219
+ }
220
+ }
221
+ return false;
222
+ }
223
+ export async function runHandoffSyncPrefetch(args, hqRoot, deps = defaults()) {
224
+ const parsed = parseArgs(args, "prefetch", deps.env);
225
+ if ("code" in parsed)
226
+ return parsed;
227
+ if (!commandOnPath("hq", deps.env))
228
+ return result(0, "missing-cli\n");
229
+ const root = resolveRoot(parsed.root || hqRoot, deps);
230
+ const fd = openLog(parsed.log);
231
+ if (typeof fd !== "number")
232
+ return fd;
233
+ try {
234
+ fs.writeSync(fd, header(deps, root, "prefetch", parsed.timeout));
235
+ const run = await runWithTimeout(deps, fd, parsed.timeout, ["sync", "pull", "--personal", "--hq-root", root, "--lock-timeout", "0"]);
236
+ fs.writeSync(fd, `exit=${run.timedOut ? 124 : run.code}\n`);
237
+ const text = fs.readFileSync(parsed.log, "utf8");
238
+ if (run.timedOut)
239
+ return result(0, "timed-out\n");
240
+ if (run.code === 0)
241
+ return result(0, "ok\n");
242
+ return result(0, /not logged in|no cached session|refused immediately|requires login/i.test(text) ? "skipped\n" : `error:${run.code}\n`);
243
+ }
244
+ finally {
245
+ fs.closeSync(fd);
246
+ }
247
+ }
248
+ export async function runHandoffSyncPublish(args, hqRoot, deps = defaults()) {
249
+ const parsed = parseArgs(args, "publish", deps.env);
250
+ if ("code" in parsed)
251
+ return parsed;
252
+ if (!commandOnPath("hq", deps.env))
253
+ return result(0);
254
+ const root = resolveRoot(parsed.root || hqRoot, deps);
255
+ const fd = openLog(parsed.log);
256
+ if (typeof fd !== "number")
257
+ return fd;
258
+ if (!parsed.child)
259
+ fs.writeSync(fd, header(deps, root, "publish", parsed.timeout, parsed.sync ? "sync" : "background"));
260
+ if (!parsed.sync) {
261
+ fs.closeSync(fd);
262
+ let output;
263
+ try {
264
+ output = fs.openSync(parsed.log, "a");
265
+ }
266
+ catch (cause) {
267
+ return fail(String(cause.message));
268
+ }
269
+ let child;
270
+ try {
271
+ const args = ["core", "--hq-root", root, "handoff-sync-publish", "--timeout", parsed.timeout, "--log", parsed.log, "--child"];
272
+ const plan = buildSpawnPlan("hq", args);
273
+ child = deps.spawn(plan.cmd, plan.args, {
274
+ cwd: deps.cwd, env: deps.env, detached: true, windowsHide: true, stdio: ["ignore", output, output],
275
+ shell: plan.shell,
276
+ ...(plan.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}),
277
+ });
278
+ }
279
+ catch {
280
+ if (typeof output === "number")
281
+ fs.closeSync(output);
282
+ return fail("handoff-sync-publish: failed to detach hq");
283
+ }
284
+ fs.closeSync(output);
285
+ return new Promise((resolve) => {
286
+ child.once("spawn", () => { child.unref(); resolve(result(0, `${child.pid ?? 0}\n`)); });
287
+ child.once("error", () => resolve(result(0, `${child.pid ?? 0}\n`)));
288
+ });
289
+ }
290
+ try {
291
+ const run = await runWithTimeout(deps, fd, parsed.timeout, ["sync", "push", "--personal", "--hq-root", root, "--lock-timeout", "0", "--message", "handoff continuity pointer"]);
292
+ fs.writeSync(fd, `exit=${run.timedOut ? 124 : run.code}\n`);
293
+ return result(run.timedOut ? 124 : run.code);
294
+ }
295
+ finally {
296
+ fs.closeSync(fd);
297
+ }
298
+ }
299
+ export const __handoffSyncTest = { parseArgs, exitCode, runWithTimeout, openLog, header, resolveRoot, commandOnPath };
300
+ //# sourceMappingURL=core-bucket-c-handoff-sync-native.js.map
@@ -0,0 +1,5 @@
1
+ import { KNOWLEDGE_PULSE_LOCK_ASSET, runKnowledgePulseLock, runSkillInstalled, SKILL_INSTALLED_ASSET } from "./core-bucket-c-small-native.js";
2
+ export { KNOWLEDGE_PULSE_LOCK_ASSET, SKILL_INSTALLED_ASSET, runKnowledgePulseLock, runSkillInstalled };
3
+ export declare function runKnowledgePulseLockFast(args: string[], _stdin: string, _cwd: string, _root: string): number;
4
+ export declare function runSkillInstalledFast(args: string[], _stdin: string, _cwd: string, root: string): Promise<number>;
5
+ //# sourceMappingURL=core-bucket-c-small-fast.d.ts.map
@@ -0,0 +1,19 @@
1
+ import { KNOWLEDGE_PULSE_LOCK_ASSET, runKnowledgePulseLock, runSkillInstalled, SKILL_INSTALLED_ASSET } from "./core-bucket-c-small-native.js";
2
+ export { KNOWLEDGE_PULSE_LOCK_ASSET, SKILL_INSTALLED_ASSET, runKnowledgePulseLock, runSkillInstalled };
3
+ export function runKnowledgePulseLockFast(args, _stdin, _cwd, _root) {
4
+ const result = runKnowledgePulseLock(args);
5
+ if (result.stdout)
6
+ process.stdout.write(result.stdout);
7
+ if (result.stderr)
8
+ process.stderr.write(result.stderr);
9
+ return result.code;
10
+ }
11
+ export async function runSkillInstalledFast(args, _stdin, _cwd, root) {
12
+ const result = await runSkillInstalled(args, root);
13
+ if (result.stdout)
14
+ process.stdout.write(result.stdout);
15
+ if (result.stderr)
16
+ process.stderr.write(result.stderr);
17
+ return result.code;
18
+ }
19
+ //# sourceMappingURL=core-bucket-c-small-fast.js.map
@@ -0,0 +1,11 @@
1
+ export declare const KNOWLEDGE_PULSE_LOCK_ASSET = "core/scripts/knowledge-pulse-lock.sh";
2
+ export declare const SKILL_INSTALLED_ASSET = "core/scripts/skill-installed.sh";
3
+ export type BucketCSmallResult = {
4
+ code: number;
5
+ stdout: string;
6
+ stderr: string;
7
+ };
8
+ export declare function mkdirFailure(error: unknown, target: string, platform?: NodeJS.Platform): string;
9
+ export declare function runKnowledgePulseLock(args: readonly string[]): BucketCSmallResult;
10
+ export declare function runSkillInstalled(args: readonly string[], root: string, env?: NodeJS.ProcessEnv): Promise<BucketCSmallResult>;
11
+ //# sourceMappingURL=core-bucket-c-small-native.d.ts.map
@@ -0,0 +1,197 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ export const KNOWLEDGE_PULSE_LOCK_ASSET = "core/scripts/knowledge-pulse-lock.sh";
4
+ export const SKILL_INSTALLED_ASSET = "core/scripts/skill-installed.sh";
5
+ const failure = (stderr, code = 1) => ({ code, stdout: "", stderr: `${stderr}\n` });
6
+ export function mkdirFailure(error, target, platform = process.platform) {
7
+ const fsError = error;
8
+ // Node's Windows fs wrapper may report this ENOTDIR as code UNKNOWN, errno -20.
9
+ let code = platform === "win32" && fsError.errno === -20 ? "ENOTDIR" : fsError.code;
10
+ const absolute = path.resolve(target);
11
+ const parsed = path.parse(absolute);
12
+ const parts = absolute.slice(parsed.root.length).split(path.sep).filter(Boolean);
13
+ if (platform === "win32" && parts.some((part) => part.length > 255))
14
+ code = "ENAMETOOLONG";
15
+ const reason = {
16
+ EACCES: "Permission denied",
17
+ EEXIST: "File exists",
18
+ ELOOP: "Too many levels of symbolic links",
19
+ EMFILE: "Too many open files",
20
+ ENAMETOOLONG: "File name too long",
21
+ ENFILE: "Too many open files in system",
22
+ ENOENT: "No such file or directory",
23
+ ENOMEM: "Cannot allocate memory",
24
+ ENOSPC: "No space left on device",
25
+ ENOTDIR: "Not a directory",
26
+ EPERM: "Operation not permitted",
27
+ EROFS: "Read-only file system",
28
+ }[code ?? ""] ?? "Input/output error";
29
+ let failingPath = target;
30
+ if (code === "ENOTDIR" || code === "ELOOP" || code === "ENAMETOOLONG") {
31
+ let current = parsed.root;
32
+ for (const part of parts) {
33
+ current = path.join(current, part);
34
+ if (platform === "win32" && part.length > 255) {
35
+ failingPath = current;
36
+ break;
37
+ }
38
+ try {
39
+ if (!fs.statSync(current).isDirectory()) {
40
+ failingPath = current;
41
+ break;
42
+ }
43
+ }
44
+ catch (error) {
45
+ if (error.code === code)
46
+ failingPath = current;
47
+ break;
48
+ }
49
+ }
50
+ }
51
+ if (platform === "darwin")
52
+ return `mkdir: ${failingPath}: ${reason}`;
53
+ if (platform === "win32") {
54
+ const shellPathParts = path.parse(failingPath);
55
+ // MSYS converts the incoming drive path for mkdir, retaining Node's root slash and adding its own.
56
+ const driveRoot = shellPathParts.root.endsWith("\\") ? `${shellPathParts.root}\\` : shellPathParts.root;
57
+ const shellPath = `${driveRoot}${failingPath.slice(shellPathParts.root.length).replaceAll("\\", "/")}`;
58
+ return `mkdir: cannot create directory '${shellPath}': ${reason}`;
59
+ }
60
+ return `mkdir: cannot create directory ‘${failingPath}’: ${reason}`;
61
+ }
62
+ export function runKnowledgePulseLock(args) {
63
+ if (args.length !== 4 || args[0] !== "claim") {
64
+ return failure("Usage: knowledge-pulse-lock.sh claim <claim-root> <company-slug> <YYYY-MM-DD>", 2);
65
+ }
66
+ const [_, claimRoot, company, date] = args;
67
+ if (!claimRoot || !/^[a-z0-9][a-z0-9-]*$/.test(company) || !/^\d{4}-\d{2}-\d{2}$/.test(date)) {
68
+ return failure("knowledge-pulse-lock: invalid claim root, company slug, or date", 2);
69
+ }
70
+ try {
71
+ fs.mkdirSync(claimRoot, { recursive: true });
72
+ }
73
+ catch (error) {
74
+ return failure(mkdirFailure(error, claimRoot));
75
+ }
76
+ const marker = path.join(claimRoot, `${company}-${date}.claimed`);
77
+ try {
78
+ fs.mkdirSync(marker);
79
+ return { code: 0, stdout: "claimed\n", stderr: "" };
80
+ }
81
+ catch (error) {
82
+ if (error.code === "EEXIST") {
83
+ try {
84
+ if (fs.statSync(marker).isDirectory())
85
+ return { code: 0, stdout: "already-claimed\n", stderr: "" };
86
+ }
87
+ catch { /* fall through to the shell-compatible failure */ }
88
+ }
89
+ return failure("knowledge-pulse-lock: could not create claim marker");
90
+ }
91
+ }
92
+ function skillName(file) {
93
+ try {
94
+ if (!fs.statSync(file).isFile())
95
+ return undefined;
96
+ const contents = fs.readFileSync(file, "utf8");
97
+ const lines = (process.platform === "win32" ? contents.replaceAll("\r\n", "\n") : contents).split("\n");
98
+ let inFrontmatter = false;
99
+ let name;
100
+ for (const line of lines) {
101
+ if (/^---[ \t]*$/.test(line)) {
102
+ if (inFrontmatter)
103
+ return name;
104
+ inFrontmatter = true;
105
+ continue;
106
+ }
107
+ if (!inFrontmatter || !/^name:[ \t]*/.test(line))
108
+ continue;
109
+ name = line.replace(/^name:[ \t]*/, "").replace(/^["']|["']$/g, "");
110
+ }
111
+ }
112
+ catch { /* unreadable skill files are skipped by the shell catalog */ }
113
+ return undefined;
114
+ }
115
+ function skillFiles(root, companies) {
116
+ const files = [];
117
+ const appendDirectories = (base, skipHidden) => {
118
+ let names;
119
+ try {
120
+ names = fs.readdirSync(base).sort((a, b) => a.localeCompare(b, "en"));
121
+ }
122
+ catch {
123
+ return;
124
+ }
125
+ for (const name of names) {
126
+ if (name.startsWith(".") || (skipHidden && (name.startsWith("_") || name.startsWith("README"))))
127
+ continue;
128
+ const dir = path.join(base, name);
129
+ try {
130
+ if (!fs.statSync(dir).isDirectory())
131
+ continue;
132
+ const file = path.join(dir, "SKILL.md");
133
+ if (fs.statSync(file).isFile())
134
+ files.push(file);
135
+ }
136
+ catch { /* non-directories and missing/unreadable files are skipped */ }
137
+ }
138
+ };
139
+ for (const company of companies)
140
+ appendDirectories(path.join(root, "companies", company, "skills"), false);
141
+ appendDirectories(path.join(root, ".claude", "skills"), true);
142
+ let packages = [];
143
+ try {
144
+ packages = fs.readdirSync(path.join(root, "core", "packages")).sort((a, b) => a.localeCompare(b, "en"));
145
+ }
146
+ catch {
147
+ return files;
148
+ }
149
+ for (const pkg of packages)
150
+ appendDirectories(path.join(root, "core", "packages", pkg, "skills"), false);
151
+ return files;
152
+ }
153
+ export async function runSkillInstalled(args, root, env = process.env) {
154
+ const skill = args[0] ?? "";
155
+ let company = args[1] ?? env.HQ_ACTIVE_COMPANY ?? "";
156
+ if (!company) {
157
+ const [{ sessionCompanySlugs }, { fastFlagEnabledDefaultOn }, { MULTI_COMPANY_SESSION_LOCK_FLAG }] = await Promise.all([
158
+ import("../lib/core-utils/session-company.js"),
159
+ import("../native-fast-route.js"),
160
+ import("../lib/cli-flag-keys.js"),
161
+ ]);
162
+ const multiCompanyLockEnabled = await fastFlagEnabledDefaultOn(MULTI_COMPANY_SESSION_LOCK_FLAG, env);
163
+ company = sessionCompanySlugs(root, env, multiCompanyLockEnabled).join(",");
164
+ }
165
+ if (!/^[a-z0-9][a-z0-9_-]*$/.test(skill))
166
+ return { code: 1, stdout: "", stderr: "" };
167
+ if (!company)
168
+ company = "__hq_unbound_session__";
169
+ const companies = company.split(",");
170
+ if (companies.at(-1) === "")
171
+ companies.pop();
172
+ if (companies.some((slug) => !/^[a-z][a-z0-9_-]*$/.test(slug)))
173
+ return { code: 1, stdout: "", stderr: "" };
174
+ const resolver = path.join(root, "core", "scripts", "lib", "session-skill-catalog.sh");
175
+ try {
176
+ fs.accessSync(resolver, fs.constants.R_OK);
177
+ }
178
+ catch {
179
+ return failure(`skill availability resolver is missing: ${resolver}`, 2);
180
+ }
181
+ const seen = new Set();
182
+ for (const file of skillFiles(root, companies)) {
183
+ const name = skillName(file);
184
+ if (!name || seen.has(name))
185
+ continue;
186
+ seen.add(name);
187
+ if (name === skill) {
188
+ try {
189
+ if (fs.statSync(file).isFile())
190
+ return { code: 0, stdout: "", stderr: "" };
191
+ }
192
+ catch { /* catalog entry disappeared, continue */ }
193
+ }
194
+ }
195
+ return { code: 1, stdout: "", stderr: "" };
196
+ }
197
+ //# sourceMappingURL=core-bucket-c-small-native.js.map
@@ -0,0 +1,7 @@
1
+ export type WorkMeshOfferResult = {
2
+ code: number;
3
+ stdout: string;
4
+ stderr: string;
5
+ };
6
+ export declare function runWorkMeshProjectRegistrationOffer(args: readonly string[], root: string, env?: NodeJS.ProcessEnv): Promise<WorkMeshOfferResult>;
7
+ //# sourceMappingURL=core-bucket-c-work-mesh-offer-native.d.ts.map