@indigoai-us/hq-cloud 6.1.0 → 6.2.1
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/dist/bin/sync-runner.d.ts.map +1 -1
- package/dist/bin/sync-runner.js +18 -0
- package/dist/bin/sync-runner.js.map +1 -1
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/reindex.d.ts +4 -11
- package/dist/cli/reindex.d.ts.map +1 -1
- package/dist/cli/reindex.js +336 -30
- package/dist/cli/reindex.js.map +1 -1
- package/dist/cli/reindex.test.d.ts +3 -3
- package/dist/cli/reindex.test.js +36 -11
- package/dist/cli/reindex.test.js.map +1 -1
- package/dist/cli/rescue-core.d.ts +36 -0
- package/dist/cli/rescue-core.d.ts.map +1 -0
- package/dist/cli/rescue-core.js +1589 -0
- package/dist/cli/rescue-core.js.map +1 -0
- package/dist/cli/rescue-drift-reconcile.test.js +33 -10
- package/dist/cli/rescue-drift-reconcile.test.js.map +1 -1
- package/dist/cli/rescue-journal-reconcile.test.d.ts +2 -0
- package/dist/cli/rescue-journal-reconcile.test.d.ts.map +1 -0
- package/dist/cli/rescue-journal-reconcile.test.js +135 -0
- package/dist/cli/rescue-journal-reconcile.test.js.map +1 -0
- package/dist/cli/rescue-mtime-preserve.test.js +36 -12
- package/dist/cli/rescue-mtime-preserve.test.js.map +1 -1
- package/dist/cli/rescue.d.ts +4 -10
- package/dist/cli/rescue.d.ts.map +1 -1
- package/dist/cli/rescue.js +14 -37
- package/dist/cli/rescue.js.map +1 -1
- package/dist/cli/rescue.reindex.test.js +9 -8
- package/dist/cli/rescue.reindex.test.js.map +1 -1
- package/dist/cli/rescue.test.js +1 -10
- package/dist/cli/rescue.test.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/conflict-index.d.ts +40 -0
- package/dist/lib/conflict-index.d.ts.map +1 -1
- package/dist/lib/conflict-index.js +121 -0
- package/dist/lib/conflict-index.js.map +1 -1
- package/dist/lib/conflict.test.js +145 -1
- package/dist/lib/conflict.test.js.map +1 -1
- package/package.json +1 -1
- package/src/bin/sync-runner.ts +18 -0
- package/src/cli/index.ts +2 -2
- package/src/cli/reindex.test.ts +45 -12
- package/src/cli/reindex.ts +345 -36
- package/src/cli/rescue-core.ts +1719 -0
- package/src/cli/rescue-drift-reconcile.test.ts +33 -12
- package/src/cli/rescue-journal-reconcile.test.ts +156 -0
- package/src/cli/rescue-mtime-preserve.test.ts +36 -15
- package/src/cli/rescue.reindex.test.ts +9 -8
- package/src/cli/rescue.test.ts +1 -11
- package/src/cli/rescue.ts +15 -40
- package/src/index.ts +2 -2
- package/src/lib/conflict-index.ts +146 -0
- package/src/lib/conflict.test.ts +171 -0
- package/scripts/reindex.sh +0 -318
- package/scripts/replace-rescue.sh +0 -1522
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conflict.test.js","sourceRoot":"","sources":["../../src/lib/conflict.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"conflict.test.js","sourceRoot":"","sources":["../../src/lib/conflict.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/bin/sync-runner.ts
CHANGED
|
@@ -99,6 +99,7 @@ import {
|
|
|
99
99
|
import { collectAndSendTelemetry } from "../telemetry.js";
|
|
100
100
|
import { collectAndSendSkillTelemetry } from "../skill-telemetry.js";
|
|
101
101
|
import { reindexAfterSync } from "../qmd-reindex.js";
|
|
102
|
+
import { pruneConflictIndex } from "../lib/conflict-index.js";
|
|
102
103
|
import { describeError } from "../lib/describe-error.js";
|
|
103
104
|
import { getOrCreateMachineId } from "../lib/machine-id.js";
|
|
104
105
|
import {
|
|
@@ -1639,6 +1640,23 @@ export async function runRunner(
|
|
|
1639
1640
|
}
|
|
1640
1641
|
}
|
|
1641
1642
|
|
|
1643
|
+
// Post-sync conflict-ledger prune — also a best-effort tail step (runs AFTER
|
|
1644
|
+
// `all-complete`, never touches the exit code). The producers only append a
|
|
1645
|
+
// conflict row after proving real divergence, but the ledger has no other
|
|
1646
|
+
// self-healing path: rows for byte-identical false positives (legacy or
|
|
1647
|
+
// since-reverted) and orphaned `.conflict-*` mirrors otherwise linger
|
|
1648
|
+
// forever and make `.hq-conflicts/index.json` over-report. One GC pass per
|
|
1649
|
+
// run keeps it converged. Idempotent and cheap on a clean ledger (a no-row
|
|
1650
|
+
// index returns immediately and never rewrites the file). Opt-out via
|
|
1651
|
+
// HQ_CONFLICT_PRUNE_ON_SYNC=0.
|
|
1652
|
+
if (process.env.HQ_CONFLICT_PRUNE_ON_SYNC !== "0") {
|
|
1653
|
+
try {
|
|
1654
|
+
pruneConflictIndex(parsed.hqRoot);
|
|
1655
|
+
} catch {
|
|
1656
|
+
// Defensive: a prune failure must never affect the sync outcome.
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1642
1660
|
// Exit 2 only when something actually threw (`errors.length > 0`). A clean
|
|
1643
1661
|
// conflict-abort sets `partial: true` in the JSON but exits 0 — the Tauri
|
|
1644
1662
|
// menubar's non-zero-exit Sentry capture would otherwise fire for normal
|
package/src/cli/index.ts
CHANGED
|
@@ -26,10 +26,10 @@ export type { PromoteOptions, PromoteResult } from "./promote.js";
|
|
|
26
26
|
|
|
27
27
|
// Skill/personal-overlay mirroring + workers-registry regen (formerly the
|
|
28
28
|
// hq-core master-sync.sh hook; `hq reindex`).
|
|
29
|
-
export { reindex
|
|
29
|
+
export { reindex } from "./reindex.js";
|
|
30
30
|
export type { ReindexOptions, ReindexResult } from "./reindex.js";
|
|
31
31
|
|
|
32
32
|
// Drift-preserving HQ-core re-sync (formerly bundled only inside the HQ Sync
|
|
33
33
|
// menubar app). Now shared between the app and `hq rescue`.
|
|
34
|
-
export { rescue,
|
|
34
|
+
export { rescue, buildRescueArgs } from "./rescue.js";
|
|
35
35
|
export type { RescueOptions, RescueResult } from "./rescue.js";
|
package/src/cli/reindex.test.ts
CHANGED
|
@@ -2,25 +2,17 @@
|
|
|
2
2
|
* Unit tests for `hq reindex` (the formerly-bash hq-core hook, now shipped
|
|
3
3
|
* in this package and invoked via the CLI).
|
|
4
4
|
*
|
|
5
|
-
* The logic
|
|
6
|
-
*
|
|
5
|
+
* The logic is implemented natively in TypeScript in ./reindex.ts; these tests
|
|
6
|
+
* exercise reindex() directly against a temp HQ tree, asserting the observable
|
|
7
7
|
* filesystem outcomes (skill wrappers, personal-overlay mirroring) rather than
|
|
8
|
-
* re-deriving the
|
|
8
|
+
* re-deriving the implementation internals.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
12
12
|
import * as fs from "fs";
|
|
13
13
|
import * as path from "path";
|
|
14
14
|
import * as os from "os";
|
|
15
|
-
import { reindex
|
|
16
|
-
|
|
17
|
-
describe("reindexScriptPath", () => {
|
|
18
|
-
it("resolves to the bundled script and the file exists", () => {
|
|
19
|
-
const p = reindexScriptPath();
|
|
20
|
-
expect(p.endsWith(path.join("scripts", "reindex.sh"))).toBe(true);
|
|
21
|
-
expect(fs.existsSync(p)).toBe(true);
|
|
22
|
-
});
|
|
23
|
-
});
|
|
15
|
+
import { reindex } from "./reindex.js";
|
|
24
16
|
|
|
25
17
|
describe("reindex", () => {
|
|
26
18
|
let root: string;
|
|
@@ -91,4 +83,45 @@ describe("reindex", () => {
|
|
|
91
83
|
fs.readlinkSync(path.join(root, ".claude/skills/core:demo/SKILL.md")),
|
|
92
84
|
).toBe("../../../core/skills/demo/SKILL.md");
|
|
93
85
|
});
|
|
86
|
+
|
|
87
|
+
it("skips `_`-prefixed and dotfile skill folders", () => {
|
|
88
|
+
writeSkill("core/skills/_template");
|
|
89
|
+
fs.mkdirSync(path.join(root, "core/skills/.hidden"), { recursive: true });
|
|
90
|
+
fs.writeFileSync(path.join(root, "core/skills/.hidden/SKILL.md"), "x\n");
|
|
91
|
+
writeSkill("core/skills/real");
|
|
92
|
+
|
|
93
|
+
reindex({ repoRoot: root });
|
|
94
|
+
|
|
95
|
+
expect(fs.existsSync(path.join(root, ".claude/skills/core:real"))).toBe(true);
|
|
96
|
+
expect(fs.existsSync(path.join(root, ".claude/skills/core:_template"))).toBe(false);
|
|
97
|
+
expect(fs.existsSync(path.join(root, ".claude/skills/core:.hidden"))).toBe(false);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("removes legacy .claude/commands/<ns>/<skill>.md bridge symlinks", () => {
|
|
101
|
+
const cmdDir = path.join(root, ".claude/commands/core");
|
|
102
|
+
fs.mkdirSync(cmdDir, { recursive: true });
|
|
103
|
+
// Legacy bridge symlink (matches the cleanup pattern) → removed.
|
|
104
|
+
fs.symlinkSync("../../../core/skills/demo/SKILL.md", path.join(cmdDir, "demo.md"));
|
|
105
|
+
// A real file (non-symlink) → preserved.
|
|
106
|
+
fs.writeFileSync(path.join(cmdDir, "keep.md"), "manual\n");
|
|
107
|
+
|
|
108
|
+
reindex({ repoRoot: root });
|
|
109
|
+
|
|
110
|
+
expect(fs.existsSync(path.join(cmdDir, "demo.md"))).toBe(false);
|
|
111
|
+
expect(fs.existsSync(path.join(cmdDir, "keep.md"))).toBe(true);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("leaves hand-authored composite wrappers (unmanaged namespace) alone", () => {
|
|
115
|
+
// A wrapper whose namespace ('vendor') is not a managed namespace and
|
|
116
|
+
// whose target points into core/skills/<other> — must not be pruned.
|
|
117
|
+
const wrapper = path.join(root, ".claude/skills/vendor:tool");
|
|
118
|
+
fs.mkdirSync(wrapper, { recursive: true });
|
|
119
|
+
writeSkill("core/skills/helper");
|
|
120
|
+
fs.symlinkSync("../../../core/skills/helper/SKILL.md", path.join(wrapper, "SKILL.md"));
|
|
121
|
+
|
|
122
|
+
reindex({ repoRoot: root });
|
|
123
|
+
|
|
124
|
+
expect(fs.existsSync(wrapper)).toBe(true);
|
|
125
|
+
expect(fs.lstatSync(path.join(wrapper, "SKILL.md")).isSymbolicLink()).toBe(true);
|
|
126
|
+
});
|
|
94
127
|
});
|
package/src/cli/reindex.ts
CHANGED
|
@@ -1,30 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* hq reindex — surfaces namespaced skills as Claude Code skill wrappers
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* hq reindex — surfaces namespaced skills as Claude Code skill wrappers under
|
|
3
|
+
* .claude/skills/<ns>:<skill>/ (one symlink per source file), mirrors
|
|
4
|
+
* personal/{knowledge,policies,workers,settings}/<entry> into core/<type>/,
|
|
5
|
+
* prunes orphan wrappers + legacy command symlinks, and regenerates the
|
|
6
|
+
* workers registry.
|
|
5
7
|
*
|
|
6
|
-
* The
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* The logic historically lived in a bundled bash script (scripts/reindex.sh)
|
|
9
|
+
* that this module exec'd via `bash`. It is now implemented natively in
|
|
10
|
+
* TypeScript so the package ships a single, testable code path with no runtime
|
|
11
|
+
* dependency on a shipped shell script. Behaviour is preserved exactly: the
|
|
12
|
+
* same skill wrappers, personal-overlay mirrors, legacy-symlink cleanup, and
|
|
13
|
+
* idempotent re-runs as before. Historically the script ran directly as a
|
|
14
|
+
* Claude Code hook inside hq-core (named "master-sync"); the hq-core hook
|
|
15
|
+
* remains a thin shim over `hq reindex`.
|
|
12
16
|
*/
|
|
13
17
|
import { spawnSync } from "child_process";
|
|
14
|
-
import
|
|
15
|
-
import path from "path";
|
|
16
|
-
|
|
17
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
-
const __dirname = path.dirname(__filename);
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Absolute path to the bundled reindex.sh. From the compiled module at
|
|
22
|
-
* dist/cli/reindex.js, the package root is two levels up; the script lives
|
|
23
|
-
* at <package-root>/scripts/reindex.sh.
|
|
24
|
-
*/
|
|
25
|
-
export function reindexScriptPath(): string {
|
|
26
|
-
return path.resolve(__dirname, "..", "..", "scripts", "reindex.sh");
|
|
27
|
-
}
|
|
18
|
+
import * as fs from "fs";
|
|
19
|
+
import * as path from "path";
|
|
28
20
|
|
|
29
21
|
export interface ReindexOptions {
|
|
30
22
|
/** HQ root to operate on. Defaults to process.cwd(). */
|
|
@@ -32,26 +24,343 @@ export interface ReindexOptions {
|
|
|
32
24
|
}
|
|
33
25
|
|
|
34
26
|
export interface ReindexResult {
|
|
35
|
-
/**
|
|
27
|
+
/** 0 = success; 1 = invalid repo root (mirrors the old script's exit codes). */
|
|
36
28
|
status: number;
|
|
37
29
|
}
|
|
38
30
|
|
|
31
|
+
// --- small fs helpers (each mirrors a bash test operator) -------------------
|
|
32
|
+
|
|
33
|
+
/** `[ -d "$p" ]` — exists and is a directory (follows symlinks). */
|
|
34
|
+
function isDir(p: string): boolean {
|
|
35
|
+
try {
|
|
36
|
+
return fs.statSync(p).isDirectory();
|
|
37
|
+
} catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** `[ -f "$p" ]` — exists and is a regular file (follows symlinks). */
|
|
43
|
+
function isFile(p: string): boolean {
|
|
44
|
+
try {
|
|
45
|
+
return fs.statSync(p).isFile();
|
|
46
|
+
} catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** `[ -e "$p" ]` — exists, dereferencing symlinks (a broken symlink is false). */
|
|
52
|
+
function existsFollow(p: string): boolean {
|
|
53
|
+
try {
|
|
54
|
+
fs.statSync(p);
|
|
55
|
+
return true;
|
|
56
|
+
} catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** `[ -x "$p" ]` — exists and is executable. */
|
|
62
|
+
function isExecutable(p: string): boolean {
|
|
63
|
+
try {
|
|
64
|
+
fs.accessSync(p, fs.constants.X_OK);
|
|
65
|
+
return true;
|
|
66
|
+
} catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** lstat without throwing (null when the path doesn't exist). */
|
|
72
|
+
function lstatOrNull(p: string): fs.Stats | null {
|
|
73
|
+
try {
|
|
74
|
+
return fs.lstatSync(p);
|
|
75
|
+
} catch {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** readlink without throwing (null when not a symlink / missing). */
|
|
81
|
+
function readlinkOrNull(p: string): string | null {
|
|
82
|
+
try {
|
|
83
|
+
return fs.readlinkSync(p);
|
|
84
|
+
} catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
39
89
|
/**
|
|
40
|
-
*
|
|
90
|
+
* Entries of `dir` matching a bash `dir/*` glob: dotfiles excluded (no
|
|
91
|
+
* dotglob), sorted lexicographically (bash glob order). Missing dir → [].
|
|
92
|
+
*/
|
|
93
|
+
function globEntries(dir: string): string[] {
|
|
94
|
+
let names: string[];
|
|
95
|
+
try {
|
|
96
|
+
names = fs.readdirSync(dir);
|
|
97
|
+
} catch {
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
return names.filter((n) => !n.startsWith(".")).sort();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function warn(msg: string): void {
|
|
104
|
+
process.stderr.write(`${msg}\n`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// --- legacy `.claude/commands/<ns>/<skill>.md` symlink matcher --------------
|
|
108
|
+
// Mirrors the bash `case` patterns; `*` matches any chars (including `/`).
|
|
109
|
+
function isLegacyCommandTarget(t: string): boolean {
|
|
110
|
+
return (
|
|
111
|
+
/^\.\.\/\.\.\/\.\.\/companies\/.*\/skills\/.*\/SKILL\.md$/.test(t) ||
|
|
112
|
+
/^\.\.\/\.\.\/\.\.\/core\/skills\/.*\/SKILL\.md$/.test(t) ||
|
|
113
|
+
/^\.\.\/\.\.\/\.\.\/personal\/skills\/.*\/SKILL\.md$/.test(t) ||
|
|
114
|
+
/^\.\.\/\.\.\/\.\.\/core\/packages\/.*\/skills\/.*\/SKILL\.md$/.test(t)
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Run reindex against an HQ root. Synchronous — the work is cheap and
|
|
41
120
|
* idempotent, and callers (the hook shim, sync/rescue, tests) want the exit
|
|
42
|
-
* status.
|
|
43
|
-
*
|
|
44
|
-
* interprets).
|
|
121
|
+
* status. Diagnostics are written to stderr so the caller's stdout stays clean
|
|
122
|
+
* (hooks must not emit stdout that the agent interprets).
|
|
45
123
|
*/
|
|
46
124
|
export function reindex(opts: ReindexOptions = {}): ReindexResult {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
stdio: ["ignore", "inherit", "inherit"],
|
|
51
|
-
});
|
|
52
|
-
if (res.error) {
|
|
53
|
-
process.stderr.write(`reindex: failed to run ${script}: ${res.error.message}\n`);
|
|
125
|
+
const rawRoot = opts.repoRoot ?? process.cwd();
|
|
126
|
+
if (!isDir(rawRoot)) {
|
|
127
|
+
warn(`reindex: REPO_ROOT '${rawRoot}' is not a directory`);
|
|
54
128
|
return { status: 1 };
|
|
55
129
|
}
|
|
56
|
-
|
|
130
|
+
const root = path.resolve(rawRoot);
|
|
131
|
+
|
|
132
|
+
fs.mkdirSync(path.join(root, ".claude", "skills"), { recursive: true });
|
|
133
|
+
|
|
134
|
+
// --- Build (namespace, src_rel) pairs -------------------------------------
|
|
135
|
+
const pairs: { ns: string; srcRel: string }[] = [];
|
|
136
|
+
const addNs = (ns: string, srcRel: string): void => {
|
|
137
|
+
if (isDir(path.join(root, srcRel))) pairs.push({ ns, srcRel });
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
for (const slug of globEntries(path.join(root, "companies"))) {
|
|
141
|
+
if (isDir(path.join(root, "companies", slug))) {
|
|
142
|
+
addNs(slug, `companies/${slug}/skills`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
addNs("core", "core/skills");
|
|
146
|
+
addNs("personal", "personal/skills");
|
|
147
|
+
for (const pack of globEntries(path.join(root, "core", "packages"))) {
|
|
148
|
+
if (isDir(path.join(root, "core", "packages", pack))) {
|
|
149
|
+
addNs(pack, `core/packages/${pack}/skills`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// --- Cleanup pass A: drop legacy .claude/commands/<ns>/<skill>.md links ----
|
|
154
|
+
const commandsDir = path.join(root, ".claude", "commands");
|
|
155
|
+
if (isDir(commandsDir)) {
|
|
156
|
+
for (const nsName of globEntries(commandsDir)) {
|
|
157
|
+
const cmdNsDir = path.join(commandsDir, nsName);
|
|
158
|
+
// Only real directories (bash `*/`); folder-level symlinks are left for
|
|
159
|
+
// a human to resolve. lstat().isDirectory() is false for a symlink, so
|
|
160
|
+
// this single check covers both bash guards.
|
|
161
|
+
const st = lstatOrNull(cmdNsDir);
|
|
162
|
+
if (!st || !st.isDirectory()) continue;
|
|
163
|
+
|
|
164
|
+
for (const f of globEntries(cmdNsDir)) {
|
|
165
|
+
if (!f.endsWith(".md")) continue;
|
|
166
|
+
const fp = path.join(cmdNsDir, f);
|
|
167
|
+
const fst = lstatOrNull(fp);
|
|
168
|
+
if (!fst || !fst.isSymbolicLink()) continue;
|
|
169
|
+
const target = readlinkOrNull(fp);
|
|
170
|
+
if (target && isLegacyCommandTarget(target)) {
|
|
171
|
+
try {
|
|
172
|
+
fs.rmSync(fp);
|
|
173
|
+
} catch {
|
|
174
|
+
/* best-effort */
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// rmdir if empty; ignore "directory not empty".
|
|
180
|
+
try {
|
|
181
|
+
fs.rmdirSync(cmdNsDir);
|
|
182
|
+
} catch {
|
|
183
|
+
/* not empty / gone — fine */
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// --- Skill wrapper creation -----------------------------------------------
|
|
189
|
+
const expectedWrappers = new Set<string>();
|
|
190
|
+
const seen = new Set<string>();
|
|
191
|
+
|
|
192
|
+
for (const { ns, srcRel } of pairs) {
|
|
193
|
+
// First writer for a namespace wins.
|
|
194
|
+
if (seen.has(ns)) {
|
|
195
|
+
warn(
|
|
196
|
+
`reindex: namespace '${ns}' already claimed by an earlier source; skipping ${srcRel}`,
|
|
197
|
+
);
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
seen.add(ns);
|
|
201
|
+
|
|
202
|
+
const srcAbs = path.join(root, srcRel);
|
|
203
|
+
for (const skillName of globEntries(srcAbs)) {
|
|
204
|
+
const skillPath = path.join(srcAbs, skillName);
|
|
205
|
+
if (!isDir(skillPath)) continue;
|
|
206
|
+
// Skip `_shared`, `_template`, etc. (dotfiles already excluded by glob).
|
|
207
|
+
if (skillName.startsWith("_")) continue;
|
|
208
|
+
if (!isFile(path.join(skillPath, "SKILL.md"))) continue;
|
|
209
|
+
|
|
210
|
+
const wrapperName = `${ns}:${skillName}`;
|
|
211
|
+
const wrapper = path.join(root, ".claude", "skills", wrapperName);
|
|
212
|
+
expectedWrappers.add(wrapperName);
|
|
213
|
+
|
|
214
|
+
const wst = lstatOrNull(wrapper);
|
|
215
|
+
// If something non-directory, non-symlink occupies the slot, bail.
|
|
216
|
+
if (wst && !wst.isSymbolicLink() && !wst.isDirectory()) {
|
|
217
|
+
warn(`reindex: ${wrapper} exists and is not a directory; skipping`);
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
// If it's a symlink (legacy directory-symlink form), replace it with a
|
|
221
|
+
// real directory of per-file symlinks.
|
|
222
|
+
if (wst && wst.isSymbolicLink()) {
|
|
223
|
+
try {
|
|
224
|
+
fs.rmSync(wrapper);
|
|
225
|
+
} catch {
|
|
226
|
+
/* best-effort */
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
fs.mkdirSync(wrapper, { recursive: true });
|
|
230
|
+
|
|
231
|
+
// Symlink every (non-hidden) entry in the source skill folder. The
|
|
232
|
+
// wrapper lives three levels below REPO_ROOT.
|
|
233
|
+
for (const entry of globEntries(skillPath)) {
|
|
234
|
+
const entryPath = path.join(skillPath, entry);
|
|
235
|
+
if (!existsFollow(entryPath)) continue;
|
|
236
|
+
const linkPath = path.join(wrapper, entry);
|
|
237
|
+
const relativeTarget = `../../../${srcRel}/${skillName}/${entry}`;
|
|
238
|
+
|
|
239
|
+
const lst = lstatOrNull(linkPath);
|
|
240
|
+
if (lst && lst.isSymbolicLink()) {
|
|
241
|
+
const current = readlinkOrNull(linkPath);
|
|
242
|
+
if (current === relativeTarget) continue;
|
|
243
|
+
warn(
|
|
244
|
+
`reindex: .claude/skills/${wrapperName}/${entry} already points to '${current}' (expected '${relativeTarget}'); leaving alone`,
|
|
245
|
+
);
|
|
246
|
+
continue;
|
|
247
|
+
} else if (lst) {
|
|
248
|
+
warn(`reindex: ${linkPath} already exists and is not a symlink; skipping`);
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
fs.symlinkSync(relativeTarget, linkPath);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Prune symlinks in the wrapper whose source entry no longer exists.
|
|
256
|
+
for (const entry of globEntries(wrapper)) {
|
|
257
|
+
const linkPath = path.join(wrapper, entry);
|
|
258
|
+
const lst = lstatOrNull(linkPath);
|
|
259
|
+
if (!lst || !lst.isSymbolicLink()) continue;
|
|
260
|
+
if (existsFollow(linkPath)) continue;
|
|
261
|
+
try {
|
|
262
|
+
fs.rmSync(linkPath);
|
|
263
|
+
} catch {
|
|
264
|
+
/* best-effort */
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// --- Cleanup pass B: drop orphan <ns>:<skill> wrappers --------------------
|
|
271
|
+
const skillsDir = path.join(root, ".claude", "skills");
|
|
272
|
+
for (const entry of globEntries(skillsDir)) {
|
|
273
|
+
const entryPath = path.join(skillsDir, entry);
|
|
274
|
+
const lst = lstatOrNull(entryPath);
|
|
275
|
+
if (!lst) continue; // accept broken symlinks (lstat still succeeds)
|
|
276
|
+
if (!entry.includes(":")) continue; // not a namespaced wrapper
|
|
277
|
+
if (expectedWrappers.has(entry)) continue; // maintained this run
|
|
278
|
+
|
|
279
|
+
// A wrapper is "managed" only when its namespace prefix matches the
|
|
280
|
+
// namespace encoded in its symlink target — this distinguishes
|
|
281
|
+
// script-produced wrappers from hand-authored composite wrappers.
|
|
282
|
+
const ns = entry.slice(0, entry.indexOf(":"));
|
|
283
|
+
const matchTarget = (t: string | null, p: string): boolean => {
|
|
284
|
+
if (!t) return false;
|
|
285
|
+
if (t.startsWith(`${p}/personal/skills/`)) return ns === "personal";
|
|
286
|
+
if (t.startsWith(`${p}/core/skills/`)) return ns === "core";
|
|
287
|
+
if (t.startsWith(`${p}/companies/${ns}/skills/`)) return true;
|
|
288
|
+
if (t.startsWith(`${p}/core/packages/${ns}/skills/`)) return true;
|
|
289
|
+
return false;
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
let isManaged = false;
|
|
293
|
+
if (lst.isSymbolicLink()) {
|
|
294
|
+
// (a) directory-style symlink wrapper (older shape): 2-level target.
|
|
295
|
+
isManaged = matchTarget(readlinkOrNull(entryPath), "../..");
|
|
296
|
+
} else if (lst.isDirectory()) {
|
|
297
|
+
// (b) real directory of per-file symlinks (current shape): 3-level.
|
|
298
|
+
for (const f of globEntries(entryPath)) {
|
|
299
|
+
const fp = path.join(entryPath, f);
|
|
300
|
+
const fst = lstatOrNull(fp);
|
|
301
|
+
if (!fst || !fst.isSymbolicLink()) continue;
|
|
302
|
+
if (matchTarget(readlinkOrNull(fp), "../../..")) {
|
|
303
|
+
isManaged = true;
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (!isManaged) continue;
|
|
309
|
+
|
|
310
|
+
// Managed-namespace wrapper with no corresponding live source → drop.
|
|
311
|
+
try {
|
|
312
|
+
if (lst.isSymbolicLink()) {
|
|
313
|
+
fs.rmSync(entryPath);
|
|
314
|
+
} else if (lst.isDirectory()) {
|
|
315
|
+
fs.rmSync(entryPath, { recursive: true, force: true });
|
|
316
|
+
}
|
|
317
|
+
} catch {
|
|
318
|
+
/* best-effort */
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// --- Personal type mirroring ----------------------------------------------
|
|
323
|
+
// Mirror personal/<type>/<entry> into core/<type>/<entry> as symlinks.
|
|
324
|
+
for (const type of ["knowledge", "policies", "workers", "settings"]) {
|
|
325
|
+
const personalDir = path.join(root, "personal", type);
|
|
326
|
+
const coreDir = path.join(root, "core", type);
|
|
327
|
+
|
|
328
|
+
if (!isDir(personalDir)) continue;
|
|
329
|
+
fs.mkdirSync(coreDir, { recursive: true });
|
|
330
|
+
|
|
331
|
+
for (const entry of globEntries(personalDir)) {
|
|
332
|
+
const entryPath = path.join(personalDir, entry);
|
|
333
|
+
if (!existsFollow(entryPath)) continue;
|
|
334
|
+
|
|
335
|
+
const linkPath = path.join(coreDir, entry);
|
|
336
|
+
const relativeTarget = `../../personal/${type}/${entry}`;
|
|
337
|
+
|
|
338
|
+
const lst = lstatOrNull(linkPath);
|
|
339
|
+
if (lst && lst.isSymbolicLink()) {
|
|
340
|
+
const current = readlinkOrNull(linkPath);
|
|
341
|
+
if (current === relativeTarget) continue;
|
|
342
|
+
warn(
|
|
343
|
+
`reindex: core/${type}/${entry} already points to '${current}' (expected '${relativeTarget}'); leaving alone`,
|
|
344
|
+
);
|
|
345
|
+
continue;
|
|
346
|
+
} else if (lst) {
|
|
347
|
+
warn(`reindex: core/${type}/${entry} already exists and is not a symlink; skipping`);
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
fs.symlinkSync(relativeTarget, linkPath);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// --- Workers registry regeneration ----------------------------------------
|
|
356
|
+
// Source of truth: each worker.yaml. The registry is a derived index — the
|
|
357
|
+
// generator (when present in the operated-on tree) keeps it in sync.
|
|
358
|
+
// Best-effort and idempotent; never fails the reindex.
|
|
359
|
+
const genScript = path.join(root, "core", "scripts", "generate-workers-registry.sh");
|
|
360
|
+
if (isExecutable(genScript)) {
|
|
361
|
+
// Route the generator's stdout+stderr to our stderr (`>&2 2>&1`).
|
|
362
|
+
spawnSync("bash", [genScript], { stdio: ["ignore", 2, 2] });
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return { status: 0 };
|
|
57
366
|
}
|