@indigoai-us/hq-cloud 6.13.2 → 6.13.3
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/cli/reindex.d.ts.map +1 -1
- package/dist/cli/reindex.js +38 -0
- package/dist/cli/reindex.js.map +1 -1
- package/dist/cli/reindex.test.js +77 -0
- package/dist/cli/reindex.test.js.map +1 -1
- package/dist/cli/sync.js +46 -1
- package/dist/cli/sync.js.map +1 -1
- package/dist/cli/sync.test.js +88 -0
- package/dist/cli/sync.test.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/reindex.test.ts +92 -0
- package/src/cli/reindex.ts +35 -0
- package/src/cli/sync.test.ts +105 -0
- package/src/cli/sync.ts +61 -1
package/dist/cli/sync.test.js
CHANGED
|
@@ -2645,6 +2645,94 @@ describe("sync", () => {
|
|
|
2645
2645
|
// Local directory still intact.
|
|
2646
2646
|
expect(fs.existsSync(path.join(localDir, "inside.md"))).toBe(true);
|
|
2647
2647
|
});
|
|
2648
|
+
it("stale personal-overlay marker vs release-shipped core dir: skips cleanly, no 'rm -rf' advice (feedback_ce9aeede)", async () => {
|
|
2649
|
+
// Reporter feedback_ce9aeede: a stale personal-overlay symlink marker in
|
|
2650
|
+
// the vault at core/knowledge/public/agent-browser collided with the REAL,
|
|
2651
|
+
// release-shipped core directory of the same name (the overlay mirror once
|
|
2652
|
+
// symlinked it into core/, pushed the marker, then a release shipped a real
|
|
2653
|
+
// dir there). Pre-fix, the pull planner hit the generic dir-vs-object
|
|
2654
|
+
// collision branch and emitted, on EVERY sync, a "manual reconciliation
|
|
2655
|
+
// required (rm -rf the local directory to pull)" warning — advice that here
|
|
2656
|
+
// would DESTROY release-shipped core content to pull an inert marker. The
|
|
2657
|
+
// reporter had to hand-delete the vault object. Fix: recognize the
|
|
2658
|
+
// overlay-mirror core key, keep the local directory, and skip quietly.
|
|
2659
|
+
const markerKey = "core/knowledge/public/agent-browser";
|
|
2660
|
+
const localDir = path.join(tmpDir, "core", "knowledge", "public", "agent-browser");
|
|
2661
|
+
fs.mkdirSync(localDir, { recursive: true });
|
|
2662
|
+
fs.writeFileSync(path.join(localDir, "INDEX.md"), "release-shipped core content");
|
|
2663
|
+
vi.mocked(s3Module.listRemoteFiles).mockResolvedValueOnce([
|
|
2664
|
+
{ key: markerKey, size: 40, lastModified: new Date(), etag: '"stale-marker"' },
|
|
2665
|
+
]);
|
|
2666
|
+
const errSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2667
|
+
let crashed = false;
|
|
2668
|
+
let result;
|
|
2669
|
+
try {
|
|
2670
|
+
result = await sync({
|
|
2671
|
+
company: "acme",
|
|
2672
|
+
vaultConfig: mockConfig,
|
|
2673
|
+
hqRoot: tmpDir,
|
|
2674
|
+
// personalMode → companyRoot === hqRoot, so a `core/...` key resolves
|
|
2675
|
+
// under the HQ root exactly as the reporter's personal-vault pull did.
|
|
2676
|
+
personalMode: true,
|
|
2677
|
+
});
|
|
2678
|
+
}
|
|
2679
|
+
catch {
|
|
2680
|
+
crashed = true;
|
|
2681
|
+
}
|
|
2682
|
+
const errOutput = errSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
2683
|
+
errSpy.mockRestore();
|
|
2684
|
+
expect(crashed).toBe(false);
|
|
2685
|
+
expect(result).toBeDefined();
|
|
2686
|
+
// Marker ignored, nothing downloaded, release-shipped dir intact.
|
|
2687
|
+
expect(result.filesDownloaded).toBe(0);
|
|
2688
|
+
expect(result.filesSkipped).toBe(1);
|
|
2689
|
+
expect(fs.readFileSync(path.join(localDir, "INDEX.md"), "utf-8")).toBe("release-shipped core content");
|
|
2690
|
+
// The dangerous, recurring reconciliation advice is GONE...
|
|
2691
|
+
expect(errOutput).not.toContain("rm -rf");
|
|
2692
|
+
expect(errOutput).not.toContain("manual");
|
|
2693
|
+
// ...replaced by a calm, no-action-needed note naming the stale marker.
|
|
2694
|
+
expect(errOutput).toContain("stale personal-overlay marker");
|
|
2695
|
+
expect(errOutput).toContain(markerKey);
|
|
2696
|
+
});
|
|
2697
|
+
it("dir-vs-object collision OUTSIDE the overlay-mirror core namespace still warns to reconcile (no over-broadening)", async () => {
|
|
2698
|
+
// Boundary guard for the feedback_ce9aeede fix: the quiet skip is scoped to
|
|
2699
|
+
// core/{knowledge,policies,workers,settings}/ overlay-mirror keys ONLY. A
|
|
2700
|
+
// dir-vs-object collision at any OTHER key (here `core/docs/...`, a core
|
|
2701
|
+
// subtree that is NOT an overlay-mirror type) is a genuine structural
|
|
2702
|
+
// collision the operator must resolve, so the original warning path — and
|
|
2703
|
+
// its skip-local-only classification — must remain intact.
|
|
2704
|
+
const key = "core/docs/agent-browser";
|
|
2705
|
+
const localDir = path.join(tmpDir, "core", "docs", "agent-browser");
|
|
2706
|
+
fs.mkdirSync(localDir, { recursive: true });
|
|
2707
|
+
fs.writeFileSync(path.join(localDir, "inside.md"), "local content");
|
|
2708
|
+
vi.mocked(s3Module.listRemoteFiles).mockResolvedValueOnce([
|
|
2709
|
+
{ key, size: 40, lastModified: new Date(), etag: '"obj"' },
|
|
2710
|
+
]);
|
|
2711
|
+
const errSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2712
|
+
let crashed = false;
|
|
2713
|
+
let result;
|
|
2714
|
+
try {
|
|
2715
|
+
result = await sync({
|
|
2716
|
+
company: "acme",
|
|
2717
|
+
vaultConfig: mockConfig,
|
|
2718
|
+
hqRoot: tmpDir,
|
|
2719
|
+
personalMode: true,
|
|
2720
|
+
});
|
|
2721
|
+
}
|
|
2722
|
+
catch {
|
|
2723
|
+
crashed = true;
|
|
2724
|
+
}
|
|
2725
|
+
const errOutput = errSpy.mock.calls.map((c) => c.join(" ")).join("\n");
|
|
2726
|
+
errSpy.mockRestore();
|
|
2727
|
+
expect(crashed).toBe(false);
|
|
2728
|
+
expect(result.filesDownloaded).toBe(0);
|
|
2729
|
+
expect(result.filesSkipped).toBe(1);
|
|
2730
|
+
expect(fs.existsSync(path.join(localDir, "inside.md"))).toBe(true);
|
|
2731
|
+
// Generic collision path preserved: reconciliation warning still emitted,
|
|
2732
|
+
// NOT the overlay-marker note.
|
|
2733
|
+
expect(errOutput).toContain("manual");
|
|
2734
|
+
expect(errOutput).not.toContain("stale personal-overlay marker");
|
|
2735
|
+
});
|
|
2648
2736
|
it("pulls a remote symlink record under an .hqinclude dir-only allowlist pattern", async () => {
|
|
2649
2737
|
// Codex round-7 P1 follow-up: pre-fix, computePullPlan called
|
|
2650
2738
|
// shouldSync(localPath) with the default isDir=false. LIST gives
|