@indigoai-us/hq-cloud 6.14.23 → 6.14.25

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 (131) hide show
  1. package/dist/bin/sync-runner-company.d.ts.map +1 -1
  2. package/dist/bin/sync-runner-company.js +11 -0
  3. package/dist/bin/sync-runner-company.js.map +1 -1
  4. package/dist/bin/sync-runner-planning.d.ts +11 -0
  5. package/dist/bin/sync-runner-planning.d.ts.map +1 -1
  6. package/dist/bin/sync-runner-planning.js +37 -2
  7. package/dist/bin/sync-runner-planning.js.map +1 -1
  8. package/dist/bin/sync-runner-planning.test.js +1 -0
  9. package/dist/bin/sync-runner-planning.test.js.map +1 -1
  10. package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -1
  11. package/dist/bin/sync-runner-watch-loop.js +17 -1
  12. package/dist/bin/sync-runner-watch-loop.js.map +1 -1
  13. package/dist/bin/sync-runner.d.ts +6 -0
  14. package/dist/bin/sync-runner.d.ts.map +1 -1
  15. package/dist/bin/sync-runner.js +14 -2
  16. package/dist/bin/sync-runner.js.map +1 -1
  17. package/dist/bin/sync-runner.test.js +155 -1
  18. package/dist/bin/sync-runner.test.js.map +1 -1
  19. package/dist/cli/doctor.d.ts +119 -0
  20. package/dist/cli/doctor.d.ts.map +1 -0
  21. package/dist/cli/doctor.js +485 -0
  22. package/dist/cli/doctor.js.map +1 -0
  23. package/dist/cli/doctor.test.d.ts +13 -0
  24. package/dist/cli/doctor.test.d.ts.map +1 -0
  25. package/dist/cli/doctor.test.js +485 -0
  26. package/dist/cli/doctor.test.js.map +1 -0
  27. package/dist/cli/index.d.ts +2 -0
  28. package/dist/cli/index.d.ts.map +1 -1
  29. package/dist/cli/index.js +4 -0
  30. package/dist/cli/index.js.map +1 -1
  31. package/dist/cli/share.js +6 -1
  32. package/dist/cli/share.js.map +1 -1
  33. package/dist/cli/sync.d.ts +29 -0
  34. package/dist/cli/sync.d.ts.map +1 -1
  35. package/dist/cli/sync.js +140 -2
  36. package/dist/cli/sync.js.map +1 -1
  37. package/dist/cli/sync.test.js +223 -1
  38. package/dist/cli/sync.test.js.map +1 -1
  39. package/dist/cognito-auth.test.js +7 -0
  40. package/dist/cognito-auth.test.js.map +1 -1
  41. package/dist/company-resolver.d.ts +31 -1
  42. package/dist/company-resolver.d.ts.map +1 -1
  43. package/dist/company-resolver.js +329 -21
  44. package/dist/company-resolver.js.map +1 -1
  45. package/dist/company-resolver.test.js +371 -1
  46. package/dist/company-resolver.test.js.map +1 -1
  47. package/dist/index.d.ts +2 -0
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +3 -0
  50. package/dist/index.js.map +1 -1
  51. package/dist/lib/conflict-file.d.ts.map +1 -1
  52. package/dist/lib/conflict-file.js +5 -1
  53. package/dist/lib/conflict-file.js.map +1 -1
  54. package/dist/lib/conflict-index.d.ts.map +1 -1
  55. package/dist/lib/conflict-index.js +7 -2
  56. package/dist/lib/conflict-index.js.map +1 -1
  57. package/dist/lib/machine-id.test.js +14 -0
  58. package/dist/lib/machine-id.test.js.map +1 -1
  59. package/dist/local-path-codec.d.ts +18 -0
  60. package/dist/local-path-codec.d.ts.map +1 -1
  61. package/dist/local-path-codec.js +63 -0
  62. package/dist/local-path-codec.js.map +1 -1
  63. package/dist/local-path-codec.test.d.ts +14 -0
  64. package/dist/local-path-codec.test.d.ts.map +1 -0
  65. package/dist/local-path-codec.test.js +102 -0
  66. package/dist/local-path-codec.test.js.map +1 -0
  67. package/dist/machine-auth.test.js +7 -0
  68. package/dist/machine-auth.test.js.map +1 -1
  69. package/dist/s3.d.ts +5 -0
  70. package/dist/s3.d.ts.map +1 -1
  71. package/dist/s3.js +129 -3
  72. package/dist/s3.js.map +1 -1
  73. package/dist/s3.symlink-materialize.test.d.ts +18 -0
  74. package/dist/s3.symlink-materialize.test.d.ts.map +1 -0
  75. package/dist/s3.symlink-materialize.test.js +394 -0
  76. package/dist/s3.symlink-materialize.test.js.map +1 -0
  77. package/dist/s3.test.js +19 -0
  78. package/dist/s3.test.js.map +1 -1
  79. package/dist/skill-telemetry.d.ts.map +1 -1
  80. package/dist/skill-telemetry.js +24 -3
  81. package/dist/skill-telemetry.js.map +1 -1
  82. package/dist/skill-telemetry.test.js +17 -0
  83. package/dist/skill-telemetry.test.js.map +1 -1
  84. package/dist/telemetry.d.ts +10 -1
  85. package/dist/telemetry.d.ts.map +1 -1
  86. package/dist/telemetry.js +95 -4
  87. package/dist/telemetry.js.map +1 -1
  88. package/dist/telemetry.test.js +177 -0
  89. package/dist/telemetry.test.js.map +1 -1
  90. package/dist/vault-client.d.ts +42 -0
  91. package/dist/vault-client.d.ts.map +1 -1
  92. package/dist/vault-client.js +40 -0
  93. package/dist/vault-client.js.map +1 -1
  94. package/dist/watcher.d.ts.map +1 -1
  95. package/dist/watcher.js +10 -1
  96. package/dist/watcher.js.map +1 -1
  97. package/dist/watcher.test.js +28 -0
  98. package/dist/watcher.test.js.map +1 -1
  99. package/package.json +1 -1
  100. package/src/bin/sync-runner-company.ts +10 -0
  101. package/src/bin/sync-runner-planning.test.ts +1 -0
  102. package/src/bin/sync-runner-planning.ts +46 -3
  103. package/src/bin/sync-runner-watch-loop.ts +19 -1
  104. package/src/bin/sync-runner.test.ts +174 -0
  105. package/src/bin/sync-runner.ts +17 -1
  106. package/src/cli/doctor.test.ts +581 -0
  107. package/src/cli/doctor.ts +640 -0
  108. package/src/cli/index.ts +14 -0
  109. package/src/cli/share.ts +6 -1
  110. package/src/cli/sync.test.ts +281 -1
  111. package/src/cli/sync.ts +184 -2
  112. package/src/cognito-auth.test.ts +5 -0
  113. package/src/company-resolver.test.ts +432 -1
  114. package/src/company-resolver.ts +362 -23
  115. package/src/index.ts +10 -0
  116. package/src/lib/conflict-file.ts +6 -1
  117. package/src/lib/conflict-index.ts +7 -2
  118. package/src/lib/machine-id.test.ts +10 -0
  119. package/src/local-path-codec.test.ts +138 -0
  120. package/src/local-path-codec.ts +66 -0
  121. package/src/machine-auth.test.ts +5 -0
  122. package/src/s3.symlink-materialize.test.ts +492 -0
  123. package/src/s3.test.ts +24 -0
  124. package/src/s3.ts +148 -4
  125. package/src/skill-telemetry.test.ts +19 -0
  126. package/src/skill-telemetry.ts +32 -3
  127. package/src/telemetry.test.ts +241 -0
  128. package/src/telemetry.ts +124 -6
  129. package/src/vault-client.ts +68 -0
  130. package/src/watcher.test.ts +33 -0
  131. package/src/watcher.ts +10 -1
@@ -0,0 +1,485 @@
1
+ /**
2
+ * Unit tests for `hq sync doctor` (US-003,
3
+ * hq-sync-windows-skill-symlink-collision): skill-key family dedupe in the
4
+ * vault + junk-wrapper GC in the local `.claude/skills/` farm.
5
+ *
6
+ * The object store is dependency-injected (`SyncDoctorOptions.store`) with an
7
+ * in-memory fake, so no test touches a network or a real vault. Local-farm
8
+ * cases run against a mkdtemp root with real symlinks (the same approach as
9
+ * s3.symlink-materialize.test.ts) and pin win32 naming via the injectable
10
+ * `win32` option rather than the host platform.
11
+ */
12
+ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
13
+ import * as fs from "fs";
14
+ import * as os from "os";
15
+ import * as path from "path";
16
+ import { syncDoctor, SKILLS_KEY_PREFIX } from "./doctor.js";
17
+ const vaultConfig = {
18
+ apiUrl: "https://vault-api.test",
19
+ authToken: "test-jwt-token",
20
+ region: "us-east-1",
21
+ };
22
+ /**
23
+ * In-memory DoctorStore. Pages listings two keys at a time so the doctor's
24
+ * continuation-token loop is exercised by every test, and records every
25
+ * mutation so dry-run tests can assert "nothing was written".
26
+ */
27
+ class FakeStore {
28
+ objects = new Map();
29
+ puts = [];
30
+ deletes = [];
31
+ set(key, body, lastModified, metadata) {
32
+ this.objects.set(key, {
33
+ body: Buffer.from(body, "utf-8"),
34
+ lastModified: new Date(lastModified),
35
+ metadata,
36
+ });
37
+ }
38
+ async listObjects(input) {
39
+ const keys = [...this.objects.keys()]
40
+ .filter((k) => k.startsWith(input.prefix ?? ""))
41
+ .sort();
42
+ const start = input.continuationToken ? Number(input.continuationToken) : 0;
43
+ const page = keys.slice(start, start + 2);
44
+ return {
45
+ objects: page.map((key) => ({
46
+ key,
47
+ size: this.objects.get(key).body.length,
48
+ lastModified: this.objects.get(key).lastModified,
49
+ etag: `"etag-${key}"`,
50
+ })),
51
+ nextContinuationToken: start + 2 < keys.length ? String(start + 2) : undefined,
52
+ };
53
+ }
54
+ async getObject(key) {
55
+ const obj = this.objects.get(key);
56
+ if (!obj)
57
+ throw new Error(`NoSuchKey: ${key}`);
58
+ return { body: obj.body, metadata: obj.metadata };
59
+ }
60
+ async putObject(input) {
61
+ this.puts.push(input.key);
62
+ this.objects.set(input.key, {
63
+ body: input.body,
64
+ lastModified: new Date(),
65
+ metadata: input.metadata,
66
+ });
67
+ return { etag: '"put-etag"' };
68
+ }
69
+ async deleteObject(key) {
70
+ this.deletes.push(key);
71
+ this.objects.delete(key);
72
+ }
73
+ }
74
+ const FARM = `${SKILLS_KEY_PREFIX}`;
75
+ describe("syncDoctor — vault skill-key dedupe", () => {
76
+ let tmpRoot;
77
+ let store;
78
+ beforeEach(() => {
79
+ tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "hq-doctor-test-"));
80
+ store = new FakeStore();
81
+ // Keep the plan printer quiet in test output; assertions run against the
82
+ // returned result, not the console.
83
+ vi.spyOn(console, "log").mockImplementation(() => { });
84
+ vi.spyOn(console, "error").mockImplementation(() => { });
85
+ });
86
+ afterEach(() => {
87
+ vi.restoreAllMocks();
88
+ fs.rmSync(tmpRoot, { recursive: true, force: true });
89
+ delete process.env.HQ_SYNC_DELETE_BULK_OVERRIDE;
90
+ });
91
+ function run(overrides = {}) {
92
+ return syncDoctor({
93
+ entity: "prs_TEST",
94
+ vaultConfig,
95
+ hqRoot: tmpRoot,
96
+ store,
97
+ win32: true,
98
+ ...overrides,
99
+ });
100
+ }
101
+ it("groups 3+ encoded generations into one canonical family and (re)writes the missing ':' key from the newest body", async () => {
102
+ // Three junk generations of the same logical wrapper, no canonical key.
103
+ // %3A -> %253A -> %25253A all decode (to fixpoint) to ':'.
104
+ store.set(`${FARM}eng%3Aarchitect/SKILL.md`, "hq-symlink:../a", "2026-07-01T00:00:00Z");
105
+ store.set(`${FARM}eng%253Aarchitect/SKILL.md`, "hq-symlink:../b", "2026-07-02T00:00:00Z");
106
+ store.set(`${FARM}eng%25253Aarchitect/SKILL.md`, "hq-symlink:../c", "2026-07-03T00:00:00Z");
107
+ const res = await run({ yes: true });
108
+ // One family; the newest-bodied spelling (%25253A generation) wins.
109
+ expect(res.plan.rewrites).toEqual([
110
+ {
111
+ key: `${FARM}eng:architect/SKILL.md`,
112
+ fromSpelling: `${FARM}eng%25253Aarchitect/SKILL.md`,
113
+ },
114
+ ]);
115
+ expect(res.keysRewritten).toBe(1);
116
+ expect(store.objects.get(`${FARM}eng:architect/SKILL.md`).body.toString("utf-8")).toBe("hq-symlink:../c");
117
+ // Every non-canonical spelling is tombstoned (marker bodies = safe).
118
+ expect(res.plan.tombstones.sort()).toEqual([
119
+ `${FARM}eng%25253Aarchitect/SKILL.md`,
120
+ `${FARM}eng%253Aarchitect/SKILL.md`,
121
+ `${FARM}eng%3Aarchitect/SKILL.md`,
122
+ ]);
123
+ expect(res.keysDeleted).toBe(3);
124
+ expect([...store.objects.keys()]).toEqual([`${FARM}eng:architect/SKILL.md`]);
125
+ expect(res.plan.manualReview).toEqual([]);
126
+ });
127
+ it("newest-wins: a junk spelling newer than the canonical key rewrites the canonical body", async () => {
128
+ store.set(`${FARM}indigo:capture/scripts`, "hq-symlink:../old", "2026-07-01T00:00:00Z");
129
+ store.set(`${FARM}indigo%3Acapture/scripts`, "hq-symlink:../new", "2026-07-05T00:00:00Z");
130
+ const res = await run({ yes: true });
131
+ expect(res.plan.rewrites).toEqual([
132
+ {
133
+ key: `${FARM}indigo:capture/scripts`,
134
+ fromSpelling: `${FARM}indigo%3Acapture/scripts`,
135
+ },
136
+ ]);
137
+ expect(store.objects.get(`${FARM}indigo:capture/scripts`).body.toString("utf-8")).toBe("hq-symlink:../new");
138
+ expect(res.plan.tombstones).toEqual([`${FARM}indigo%3Acapture/scripts`]);
139
+ expect(store.objects.has(`${FARM}indigo%3Acapture/scripts`)).toBe(false);
140
+ });
141
+ it("keeps an up-to-date canonical key untouched when its body is already the newest", async () => {
142
+ store.set(`${FARM}indigo:recall/SKILL.md`, "hq-symlink:../t", "2026-07-05T00:00:00Z");
143
+ store.set(`${FARM}indigo%3Arecall/SKILL.md`, "hq-symlink:../t", "2026-07-01T00:00:00Z");
144
+ const res = await run({ yes: true });
145
+ expect(res.plan.rewrites).toEqual([]);
146
+ expect(res.plan.keep).toContain(`${FARM}indigo:recall/SKILL.md`);
147
+ expect(store.puts).toEqual([]);
148
+ expect(res.plan.tombstones).toEqual([`${FARM}indigo%3Arecall/SKILL.md`]);
149
+ });
150
+ it("safety gate: a non-marker body that differs from the canonical twin goes to manual review, never deleted", async () => {
151
+ // Canonical is newest (so the junk spelling is NOT the winner); the junk
152
+ // body is real content, not a symlink marker, and differs byte-wise.
153
+ store.set(`${FARM}indigo:notes/SKILL.md`, "canonical content", "2026-07-05T00:00:00Z");
154
+ store.set(`${FARM}indigo%3Anotes/SKILL.md`, "divergent real content", "2026-07-01T00:00:00Z");
155
+ const res = await run({ yes: true });
156
+ expect(res.plan.tombstones).toEqual([]);
157
+ expect(res.keysDeleted).toBe(0);
158
+ expect(res.plan.manualReview).toEqual([
159
+ {
160
+ key: `${FARM}indigo%3Anotes/SKILL.md`,
161
+ reason: "body is neither a symlink marker nor byte-identical to the canonical key — not auto-deleted",
162
+ },
163
+ ]);
164
+ // The divergent object is still in the store — surfaced, not removed.
165
+ expect(store.objects.has(`${FARM}indigo%3Anotes/SKILL.md`)).toBe(true);
166
+ });
167
+ it("safety gate: a non-marker body byte-identical to the canonical twin IS safe to delete", async () => {
168
+ store.set(`${FARM}indigo:notes/SKILL.md`, "same real content", "2026-07-05T00:00:00Z");
169
+ store.set(`${FARM}indigo%3Anotes/SKILL.md`, "same real content", "2026-07-01T00:00:00Z");
170
+ const res = await run({ yes: true });
171
+ expect(res.plan.tombstones).toEqual([`${FARM}indigo%3Anotes/SKILL.md`]);
172
+ expect(res.keysDeleted).toBe(1);
173
+ expect(res.plan.manualReview).toEqual([]);
174
+ });
175
+ it("a body-fetch failure is a loud non-fatal skip: the spelling lands in manual review and the run continues", async () => {
176
+ store.set(`${FARM}indigo:ok/SKILL.md`, "hq-symlink:../t", "2026-07-05T00:00:00Z");
177
+ store.set(`${FARM}indigo%3Aok/SKILL.md`, "hq-symlink:../t", "2026-07-01T00:00:00Z");
178
+ const failingKey = `${FARM}indigo%253Aok/SKILL.md`;
179
+ store.set(failingKey, "hq-symlink:../t", "2026-07-02T00:00:00Z");
180
+ const realGet = store.getObject.bind(store);
181
+ vi.spyOn(store, "getObject").mockImplementation(async (key) => {
182
+ if (key === failingKey)
183
+ throw new Error("simulated 500");
184
+ return realGet(key);
185
+ });
186
+ const res = await run({ yes: true });
187
+ expect(res.plan.manualReview).toEqual([
188
+ { key: failingKey, reason: "body fetch failed — bytes unknown, not touched" },
189
+ ]);
190
+ expect(res.warnings).toBeGreaterThan(0);
191
+ // The healthy sibling was still processed.
192
+ expect(res.plan.tombstones).toEqual([`${FARM}indigo%3Aok/SKILL.md`]);
193
+ });
194
+ it("does not delete a family's tombstones when its canonical rewrite failed (the junk spelling may hold the only body)", async () => {
195
+ // Newest (only) body lives at the junk spelling; canonical key is absent,
196
+ // so applying requires rewrite-then-delete. Fail the rewrite: the delete
197
+ // leg must skip this family's tombstones or the only copy is lost.
198
+ store.set(`${FARM}eng%3Afoo/SKILL.md`, "hq-symlink:../only", "2026-07-01T00:00:00Z");
199
+ const put = store.putObject.bind(store);
200
+ vi.spyOn(store, "putObject").mockImplementation(async (input) => {
201
+ if (input.key === `${FARM}eng:foo/SKILL.md`)
202
+ throw new Error("503 SlowDown");
203
+ return put(input);
204
+ });
205
+ const res = await run({ yes: true });
206
+ expect(res.keysRewritten).toBe(0);
207
+ expect(res.keysDeleted).toBe(0);
208
+ expect(store.deletes).toEqual([]);
209
+ expect(store.objects.has(`${FARM}eng%3Afoo/SKILL.md`)).toBe(true);
210
+ expect(res.warnings).toBeGreaterThanOrEqual(2); // failed rewrite + skipped delete
211
+ });
212
+ it("colon-free percent spellings are their own canonical: no rewrite, no move, no delete (round-9)", async () => {
213
+ // A legitimate skill whose NAME contains a percent escape must never be
214
+ // 'collapsed' into the decoded name — that would move/delete real
215
+ // content. Both spellings coexist as independent keys.
216
+ store.set(`${FARM}foo%20bar/SKILL.md`, "real skill content", "2026-07-01T00:00:00Z");
217
+ store.set(`${FARM}foo bar/SKILL.md`, "a different real skill", "2026-07-01T00:00:00Z");
218
+ const res = await run({ yes: true });
219
+ expect(res.plan.rewrites).toEqual([]);
220
+ expect(res.plan.tombstones).toEqual([]);
221
+ expect(res.keysDeleted).toBe(0);
222
+ expect(store.objects.has(`${FARM}foo%20bar/SKILL.md`)).toBe(true);
223
+ expect(store.objects.has(`${FARM}foo bar/SKILL.md`)).toBe(true);
224
+ expect(res.plan.keep.sort()).toEqual([
225
+ `${FARM}foo bar/SKILL.md`,
226
+ `${FARM}foo%20bar/SKILL.md`,
227
+ ]);
228
+ });
229
+ it("fences canonical rewrites with CAS: ifNoneMatch:'*' when absent, ifMatch:<listed etag> when stale", async () => {
230
+ store.set(`${FARM}eng%3Acasnew/SKILL.md`, "hq-symlink:../a", "2026-07-01T00:00:00Z");
231
+ store.set(`${FARM}eng:casstale/SKILL.md`, "hq-symlink:../old", "2026-07-01T00:00:00Z");
232
+ store.set(`${FARM}eng%3Acasstale/SKILL.md`, "hq-symlink:../new", "2026-07-02T00:00:00Z");
233
+ const putSpy = vi.spyOn(store, "putObject");
234
+ await run({ yes: true });
235
+ const puts = putSpy.mock.calls.map((c) => c[0]);
236
+ const created = puts.find((p) => p.key === `${FARM}eng:casnew/SKILL.md`);
237
+ expect(created.ifNoneMatch).toBe("*");
238
+ expect(created.ifMatch).toBeUndefined();
239
+ const updated = puts.find((p) => p.key === `${FARM}eng:casstale/SKILL.md`);
240
+ expect(updated.ifMatch).toBe(`"etag-${FARM}eng:casstale/SKILL.md"`);
241
+ expect(updated.ifNoneMatch).toBeUndefined();
242
+ });
243
+ it("a 412 precondition failure on the rewrite keeps the family's tombstones (no clobber, no orphaned delete)", async () => {
244
+ store.set(`${FARM}eng:casrace/SKILL.md`, "hq-symlink:../old", "2026-07-01T00:00:00Z");
245
+ store.set(`${FARM}eng%3Acasrace/SKILL.md`, "hq-symlink:../new", "2026-07-02T00:00:00Z");
246
+ vi.spyOn(store, "putObject").mockImplementation(async () => {
247
+ throw Object.assign(new Error("PreconditionFailed"), { $metadata: { httpStatusCode: 412 } });
248
+ });
249
+ const res = await run({ yes: true });
250
+ expect(res.keysRewritten).toBe(0);
251
+ expect(res.keysDeleted).toBe(0);
252
+ expect(store.objects.has(`${FARM}eng%3Acasrace/SKILL.md`)).toBe(true);
253
+ expect(res.warnings).toBeGreaterThanOrEqual(2);
254
+ });
255
+ it("parks the whole family when the canonical body fetch fails — no rewrite from a junk sibling, no deletes", async () => {
256
+ // Round-4 review P1: a transient/403 canonical read must not let the
257
+ // newest junk sibling overwrite unknown canonical bytes.
258
+ store.set(`${FARM}eng:parked/SKILL.md`, "possibly-real user content", "2026-07-01T00:00:00Z");
259
+ store.set(`${FARM}eng%3Aparked/SKILL.md`, "hq-symlink:../newer", "2026-07-02T00:00:00Z");
260
+ const get = store.getObject.bind(store);
261
+ vi.spyOn(store, "getObject").mockImplementation(async (key) => {
262
+ if (key === `${FARM}eng:parked/SKILL.md`)
263
+ throw new Error("403 slow down");
264
+ return get(key);
265
+ });
266
+ const res = await run({ yes: true });
267
+ expect(res.plan.rewrites).toEqual([]);
268
+ expect(res.plan.tombstones).toEqual([]);
269
+ expect(res.keysRewritten).toBe(0);
270
+ expect(res.keysDeleted).toBe(0);
271
+ expect(res.plan.manualReview).toEqual(expect.arrayContaining([
272
+ {
273
+ key: `${FARM}eng:parked/SKILL.md`,
274
+ reason: "body fetch failed — bytes unknown, not touched",
275
+ },
276
+ {
277
+ key: `${FARM}eng%3Aparked/SKILL.md`,
278
+ reason: "canonical body unknown (fetch failed) — family not touched",
279
+ },
280
+ ]));
281
+ expect(store.objects.has(`${FARM}eng:parked/SKILL.md`)).toBe(true);
282
+ expect(store.objects.has(`${FARM}eng%3Aparked/SKILL.md`)).toBe(true);
283
+ });
284
+ it("bulk-asymmetry guard: a large delete plan is refused without an explicit override (policy sync-delete-bulk-asymmetry-guard)", async () => {
285
+ // 12 families, each canonical + one identical junk twin: 12 tombstones out
286
+ // of 24 in-scope keys (50% >= 10%, 12 >= 10) — the breaker must trip.
287
+ for (let i = 0; i < 12; i++) {
288
+ store.set(`${FARM}ns:skill-${i}/SKILL.md`, `hq-symlink:../${i}`, "2026-07-05T00:00:00Z");
289
+ store.set(`${FARM}ns%3Askill-${i}/SKILL.md`, `hq-symlink:../${i}`, "2026-07-01T00:00:00Z");
290
+ }
291
+ const refused = await run({ yes: true });
292
+ expect(refused.plan.bulkRefused).toBe(true);
293
+ expect(refused.plan.tombstones).toHaveLength(12);
294
+ expect(refused.keysDeleted).toBe(0);
295
+ expect(store.deletes).toEqual([]);
296
+ // Explicit override flag applies the same plan.
297
+ const applied = await run({ yes: true, bulkDeleteOverride: true });
298
+ expect(applied.plan.bulkRefused).toBe(false);
299
+ expect(applied.keysDeleted).toBe(12);
300
+ });
301
+ it("bulk-asymmetry guard honors the HQ_SYNC_DELETE_BULK_OVERRIDE env rollback knob", async () => {
302
+ for (let i = 0; i < 12; i++) {
303
+ store.set(`${FARM}ns:skill-${i}/SKILL.md`, `hq-symlink:../${i}`, "2026-07-05T00:00:00Z");
304
+ store.set(`${FARM}ns%3Askill-${i}/SKILL.md`, `hq-symlink:../${i}`, "2026-07-01T00:00:00Z");
305
+ }
306
+ process.env.HQ_SYNC_DELETE_BULK_OVERRIDE = "1";
307
+ const res = await run({ yes: true });
308
+ expect(res.plan.bulkRefused).toBe(false);
309
+ expect(res.keysDeleted).toBe(12);
310
+ });
311
+ it("dry-run is the default: the full plan is produced and NOTHING is written", async () => {
312
+ store.set(`${FARM}eng%3Aarchitect/SKILL.md`, "hq-symlink:../a", "2026-07-01T00:00:00Z");
313
+ store.set(`${FARM}eng%253Aarchitect/SKILL.md`, "hq-symlink:../b", "2026-07-02T00:00:00Z");
314
+ // Junk local wrapper next to its canonical twin, GC-eligible.
315
+ const skillsDir = path.join(tmpRoot, ".claude", "skills");
316
+ fs.mkdirSync(path.join(skillsDir, "eng%3Aarchitect"), { recursive: true });
317
+ const junkDir = path.join(skillsDir, "eng%25253Aarchitect");
318
+ fs.mkdirSync(junkDir);
319
+ fs.writeFileSync(path.join(tmpRoot, "target.md"), "x");
320
+ fs.symlinkSync(path.join(tmpRoot, "target.md"), path.join(junkDir, "link.md"));
321
+ const res = await run(); // no `yes`
322
+ // Plan is fully populated…
323
+ expect(res.plan.rewrites).toHaveLength(1);
324
+ expect(res.plan.tombstones).toHaveLength(2);
325
+ expect(res.plan.localRemovals).toEqual([junkDir]);
326
+ // …but nothing was applied: no puts, no deletes, junk dir still on disk.
327
+ expect(res.applied).toBe(false);
328
+ expect(store.puts).toEqual([]);
329
+ expect(store.deletes).toEqual([]);
330
+ expect(store.objects.has(`${FARM}eng%3Aarchitect/SKILL.md`)).toBe(true);
331
+ expect(fs.existsSync(junkDir)).toBe(true);
332
+ expect(res.keysRewritten).toBe(0);
333
+ expect(res.keysDeleted).toBe(0);
334
+ expect(res.dirsRemoved).toBe(0);
335
+ });
336
+ });
337
+ describe("syncDoctor — local skill-farm GC", () => {
338
+ let tmpRoot;
339
+ let skillsDir;
340
+ let store;
341
+ beforeEach(() => {
342
+ tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "hq-doctor-gc-test-"));
343
+ skillsDir = path.join(tmpRoot, ".claude", "skills");
344
+ fs.mkdirSync(skillsDir, { recursive: true });
345
+ store = new FakeStore();
346
+ vi.spyOn(console, "log").mockImplementation(() => { });
347
+ vi.spyOn(console, "error").mockImplementation(() => { });
348
+ });
349
+ afterEach(() => {
350
+ vi.restoreAllMocks();
351
+ fs.rmSync(tmpRoot, { recursive: true, force: true });
352
+ });
353
+ function run(overrides = {}) {
354
+ return syncDoctor({
355
+ entity: "prs_TEST",
356
+ vaultConfig,
357
+ hqRoot: tmpRoot,
358
+ store,
359
+ win32: true,
360
+ ...overrides,
361
+ });
362
+ }
363
+ /** Junk-named dir containing only symlinks — the 134-dirs incident shape. */
364
+ function makeSymlinkFarmDir(name) {
365
+ const dir = path.join(skillsDir, name);
366
+ fs.mkdirSync(dir);
367
+ const target = path.join(tmpRoot, `${name}-target.md`);
368
+ fs.writeFileSync(target, "target");
369
+ fs.symlinkSync(target, path.join(dir, "link.md"));
370
+ return dir;
371
+ }
372
+ it("removes a junk dir whose name decodes to a canonical wrapper that exists on disk (symlink content only)", async () => {
373
+ // The incident's exact shape: 'hq-pack-engineering%25253Aarchitect'
374
+ // decodes to 'hq-pack-engineering:architect', whose canonical win32
375
+ // wrapper 'hq-pack-engineering%3Aarchitect' already exists.
376
+ fs.mkdirSync(path.join(skillsDir, "hq-pack-engineering%3Aarchitect"));
377
+ const junk = makeSymlinkFarmDir("hq-pack-engineering%25253Aarchitect");
378
+ const res = await run({ yes: true });
379
+ expect(res.plan.localRemovals).toEqual([junk]);
380
+ expect(res.dirsRemoved).toBe(1);
381
+ expect(fs.existsSync(junk)).toBe(false);
382
+ // The canonical wrapper is untouched.
383
+ expect(fs.existsSync(path.join(skillsDir, "hq-pack-engineering%3Aarchitect"))).toBe(true);
384
+ });
385
+ it("refuses a junk dir that contains any real (non-symlink) file — manual review only", async () => {
386
+ fs.mkdirSync(path.join(skillsDir, "eng%3Aweb"));
387
+ const junk = path.join(skillsDir, "eng%253Aweb");
388
+ fs.mkdirSync(junk);
389
+ fs.writeFileSync(path.join(junk, "real-file.md"), "user data");
390
+ const res = await run({ yes: true });
391
+ expect(res.plan.localRemovals).toEqual([]);
392
+ expect(res.plan.localManualReview).toEqual([
393
+ { path: junk, reason: "contains real (non-symlink) files — never auto-deleted" },
394
+ ]);
395
+ expect(res.dirsRemoved).toBe(0);
396
+ expect(fs.existsSync(path.join(junk, "real-file.md"))).toBe(true);
397
+ });
398
+ it("apply-time recheck: a regular file that replaced a planned entry between plan and apply is never removed", async () => {
399
+ // The plan/apply race the recheck exists for: planning classifies a junk
400
+ // SYMLINK entry as removable; before the apply loop reaches it, a sync
401
+ // pass or user edit replaces it with a REGULAR FILE. printPlan() runs
402
+ // between the two phases, so the first plan-print callback is the exact
403
+ // race window — swap the entry there.
404
+ fs.mkdirSync(path.join(skillsDir, "eng%3Arace"));
405
+ const junk = path.join(skillsDir, "eng%253Arace");
406
+ fs.symlinkSync(path.join(skillsDir, "eng%3Arace"), junk);
407
+ let swapped = false;
408
+ vi.spyOn(console, "log").mockImplementation(() => {
409
+ if (swapped)
410
+ return;
411
+ swapped = true;
412
+ try {
413
+ fs.unlinkSync(junk);
414
+ }
415
+ catch {
416
+ fs.rmdirSync(junk); // win32 directory symlink
417
+ }
418
+ fs.writeFileSync(junk, "user data written mid-run");
419
+ });
420
+ const res = await run({ yes: true });
421
+ expect(swapped).toBe(true);
422
+ expect(res.plan.localRemovals).toEqual([junk]);
423
+ expect(res.dirsRemoved).toBe(0);
424
+ expect(fs.readFileSync(junk, "utf-8")).toBe("user data written mid-run");
425
+ expect(res.warnings).toBeGreaterThanOrEqual(1);
426
+ });
427
+ it("refuses a junk-named entry when its canonical wrapper is missing on disk (it may be the only copy)", async () => {
428
+ const junk = makeSymlinkFarmDir("eng%253Aorphan");
429
+ const res = await run({ yes: true });
430
+ expect(res.plan.localRemovals).toEqual([]);
431
+ expect(res.plan.localManualReview).toEqual([
432
+ {
433
+ path: junk,
434
+ reason: "canonical wrapper 'eng%3Aorphan' missing on disk — junk-named entry may be the only copy",
435
+ },
436
+ ]);
437
+ expect(fs.existsSync(junk)).toBe(true);
438
+ });
439
+ it("removes a junk-named entry that is itself a symlink (farm content by definition)", async () => {
440
+ const target = path.join(tmpRoot, "wrapper-target.md");
441
+ fs.writeFileSync(target, "t");
442
+ fs.mkdirSync(path.join(skillsDir, "eng%3Alink"));
443
+ const junkLink = path.join(skillsDir, "eng%253Alink");
444
+ fs.symlinkSync(target, junkLink);
445
+ const res = await run({ yes: true });
446
+ expect(res.plan.localRemovals).toEqual([junkLink]);
447
+ expect(res.dirsRemoved).toBe(1);
448
+ expect(fs.existsSync(junkLink)).toBe(false);
449
+ // Symlink removal never follows through to the target.
450
+ expect(fs.existsSync(target)).toBe(true);
451
+ });
452
+ it("never GCs a colon-free percent-named wrapper, even when its double-encoded twin exists on disk", async () => {
453
+ // Codex P2 (round-9 follow-up): `canonicalVaultSegmentSpelling` returns
454
+ // colon-free names UNCHANGED on purpose — `foo%25bar` is the legitimate
455
+ // win32 wrapper for the canonical skill name `foo%bar`, not a generation
456
+ // of a `<ns>:<skill>` amplifier family. Pre-fix, the local GC re-encoded
457
+ // that already-canonical name for the host (`foo%2525bar`); because that
458
+ // spelling differs from the entry's own, the entry fell through the
459
+ // "already canonical" guard and, with a matching double-encoded sibling
460
+ // on disk, `--yes` deleted the legitimate wrapper. Both spellings here
461
+ // are their own canonical form, so BOTH must survive untouched.
462
+ const legit = makeSymlinkFarmDir("foo%25bar");
463
+ const twin = makeSymlinkFarmDir("foo%2525bar");
464
+ // A genuine namespaced amplifier family in the same directory proves the
465
+ // guard is scoped to colon-free names and did not disable the GC.
466
+ fs.mkdirSync(path.join(skillsDir, "eng%3Aarchitect"));
467
+ const amplifierJunk = makeSymlinkFarmDir("eng%253Aarchitect");
468
+ const res = await run({ yes: true });
469
+ expect(res.plan.localRemovals).toEqual([amplifierJunk]);
470
+ expect(res.plan.localManualReview).toEqual([]);
471
+ expect(fs.existsSync(legit)).toBe(true);
472
+ expect(fs.existsSync(twin)).toBe(true);
473
+ expect(fs.existsSync(amplifierJunk)).toBe(false);
474
+ });
475
+ it("leaves canonical wrapper names and ordinary skill dirs alone", async () => {
476
+ fs.mkdirSync(path.join(skillsDir, "eng%3Aarchitect")); // canonical win32 wrapper
477
+ fs.mkdirSync(path.join(skillsDir, "plain-skill")); // no encoding at all
478
+ const res = await run({ yes: true });
479
+ expect(res.plan.localRemovals).toEqual([]);
480
+ expect(res.plan.localManualReview).toEqual([]);
481
+ expect(fs.existsSync(path.join(skillsDir, "eng%3Aarchitect"))).toBe(true);
482
+ expect(fs.existsSync(path.join(skillsDir, "plain-skill"))).toBe(true);
483
+ });
484
+ });
485
+ //# sourceMappingURL=doctor.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.test.js","sourceRoot":"","sources":["../../src/cli/doctor.test.ts"],"names":[],"mappings":"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"}
@@ -20,4 +20,6 @@ export { reindex } from "./reindex.js";
20
20
  export type { ReindexOptions, ReindexResult } from "./reindex.js";
21
21
  export { rescue, buildRescueArgs } from "./rescue.js";
22
22
  export type { RescueOptions, RescueResult } from "./rescue.js";
23
+ export { syncDoctor, SKILLS_KEY_PREFIX } from "./doctor.js";
24
+ export type { SyncDoctorOptions, SyncDoctorResult, SyncDoctorPlan, SkillKeyRewrite, DoctorManualReviewItem, LocalGcManualReviewItem, DoctorStore, } from "./doctor.js";
23
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE5E,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC1D,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAGxF,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvG,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE/D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIlE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIlE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE5E,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC1D,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAGxF,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvG,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE/D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIlE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIlE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK/D,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC5D,YAAY,EACV,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,sBAAsB,EACtB,uBAAuB,EACvB,WAAW,GACZ,MAAM,aAAa,CAAC"}
package/dist/cli/index.js CHANGED
@@ -17,4 +17,8 @@ export { reindex } from "./reindex.js";
17
17
  // Drift-preserving HQ-core re-sync (formerly bundled only inside the HQ Sync
18
18
  // menubar app). Now shared between the app and `hq rescue`.
19
19
  export { rescue, buildRescueArgs } from "./rescue.js";
20
+ // Bounded skill-key dedupe + local `.claude/skills/` farm GC for the
21
+ // mixed-version amplifier (`hq sync doctor`, US-003
22
+ // hq-sync-windows-skill-symlink-collision). Dry-run by default; --yes applies.
23
+ export { syncDoctor, SKILLS_KEY_PREFIX } from "./doctor.js";
20
24
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG1D,8BAA8B;AAC9B,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,0EAA0E;AAC1E,8CAA8C;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,6EAA6E;AAC7E,4DAA4D;AAC5D,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG1D,8BAA8B;AAC9B,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,0EAA0E;AAC1E,8CAA8C;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,6EAA6E;AAC7E,4DAA4D;AAC5D,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGtD,qEAAqE;AACrE,oDAAoD;AACpD,+EAA+E;AAC/E,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
package/dist/cli/share.js CHANGED
@@ -941,7 +941,12 @@ async function executeDeletes(run, deletePlan, decommissionPlan, counters, files
941
941
  item.intentVersion !== null &&
942
942
  (!hasCurrentLocalDeleteIntent(entry) ||
943
943
  entry.localDeleteIntent.version !== item.intentVersion ||
944
- !isLocallyAbsent(path.join(run.syncRoot, relativePath)))) {
944
+ // Codec boundary: journal keys are canonical; the last-second
945
+ // absence re-check must probe the ENCODED local path or a win32
946
+ // colon key always looks absent (a raw `:` name can never exist
947
+ // on disk) and the remote delete proceeds while the encoded local
948
+ // file is still present.
949
+ !isLocallyAbsent(localPathForVaultKey(run.syncRoot, relativePath)))) {
945
950
  if (entry?.localDeleteIntent) {
946
951
  delete entry.localDeleteIntent;
947
952
  }