@indigoai-us/hq-cloud 6.13.3 → 6.13.5
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-company.d.ts.map +1 -1
- package/dist/bin/sync-runner-company.js +15 -0
- package/dist/bin/sync-runner-company.js.map +1 -1
- package/dist/bin/sync-runner-rollup.d.ts +7 -0
- package/dist/bin/sync-runner-rollup.d.ts.map +1 -1
- package/dist/bin/sync-runner-rollup.js +15 -0
- package/dist/bin/sync-runner-rollup.js.map +1 -1
- package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -1
- package/dist/bin/sync-runner-watch-loop.js +10 -1
- package/dist/bin/sync-runner-watch-loop.js.map +1 -1
- package/dist/bin/sync-runner.d.ts +7 -0
- package/dist/bin/sync-runner.d.ts.map +1 -1
- package/dist/bin/sync-runner.js +36 -7
- package/dist/bin/sync-runner.js.map +1 -1
- package/dist/bin/sync-runner.test.js +142 -0
- package/dist/bin/sync-runner.test.js.map +1 -1
- package/dist/cli/share.js +15 -2
- package/dist/cli/share.js.map +1 -1
- package/dist/cli/share.test.js +39 -0
- package/dist/cli/share.test.js.map +1 -1
- package/dist/cli/sync.d.ts +22 -0
- package/dist/cli/sync.d.ts.map +1 -1
- package/dist/cli/sync.js +14 -0
- package/dist/cli/sync.js.map +1 -1
- package/dist/lib/net-errors.d.ts +36 -0
- package/dist/lib/net-errors.d.ts.map +1 -0
- package/dist/lib/net-errors.js +81 -0
- package/dist/lib/net-errors.js.map +1 -0
- package/dist/lib/net-errors.test.d.ts +2 -0
- package/dist/lib/net-errors.test.d.ts.map +1 -0
- package/dist/lib/net-errors.test.js +47 -0
- package/dist/lib/net-errors.test.js.map +1 -0
- package/dist/qmd-reindex.d.ts +14 -0
- package/dist/qmd-reindex.d.ts.map +1 -1
- package/dist/qmd-reindex.js +93 -19
- package/dist/qmd-reindex.js.map +1 -1
- package/dist/qmd-reindex.test.js +47 -0
- package/dist/qmd-reindex.test.js.map +1 -1
- package/package.json +1 -1
- package/src/bin/sync-runner-company.ts +21 -0
- package/src/bin/sync-runner-rollup.ts +23 -0
- package/src/bin/sync-runner-watch-loop.ts +11 -1
- package/src/bin/sync-runner.test.ts +167 -0
- package/src/bin/sync-runner.ts +49 -9
- package/src/cli/share.test.ts +46 -0
- package/src/cli/share.ts +14 -2
- package/src/cli/sync.ts +40 -0
- package/src/lib/net-errors.test.ts +53 -0
- package/src/lib/net-errors.ts +83 -0
- package/src/qmd-reindex.test.ts +50 -0
- package/src/qmd-reindex.ts +124 -18
package/dist/qmd-reindex.js
CHANGED
|
@@ -37,6 +37,7 @@ const defaultExec = (args) => {
|
|
|
37
37
|
});
|
|
38
38
|
return { status: res.status, stdout: res.stdout ?? "" };
|
|
39
39
|
};
|
|
40
|
+
const DEFAULT_CHANGED_PATH_DEBOUNCE_MS = 60_000;
|
|
40
41
|
/**
|
|
41
42
|
* Reindex qmd for an HQ tree after a sync. Never throws — all failures are
|
|
42
43
|
* swallowed so a reindex problem can never mask or fail the sync result.
|
|
@@ -46,11 +47,29 @@ const defaultExec = (args) => {
|
|
|
46
47
|
export function reindexAfterSync(hqRoot, opts = {}) {
|
|
47
48
|
const exec = opts.exec ?? defaultExec;
|
|
48
49
|
const existsSync = opts.existsSync ?? fs.existsSync;
|
|
49
|
-
const result = {
|
|
50
|
+
const result = {
|
|
51
|
+
qmdAvailable: false,
|
|
52
|
+
collectionsAdded: [],
|
|
53
|
+
updated: false,
|
|
54
|
+
embedded: false,
|
|
55
|
+
pendingDirty: false,
|
|
56
|
+
};
|
|
50
57
|
try {
|
|
51
58
|
// Guard: only operate on a real HQ tree.
|
|
52
59
|
if (!existsSync(path.join(hqRoot, "core", "core.yaml")))
|
|
53
60
|
return result;
|
|
61
|
+
const statePath = opts.statePath ?? path.join(hqRoot, ".hq", "qmd-reindex-state.json");
|
|
62
|
+
const state = readState(statePath);
|
|
63
|
+
const changedPaths = opts.changedPaths;
|
|
64
|
+
const dirtyFromChanges = changedPaths === undefined ||
|
|
65
|
+
changedPaths.some(isKnowledgeMarkdownPath);
|
|
66
|
+
const registrationMayBeStale = opts.forceCollectionRefresh === true ||
|
|
67
|
+
changedPaths === undefined ||
|
|
68
|
+
dirtyFromChanges;
|
|
69
|
+
const pendingDirty = state.pendingDirty === true;
|
|
70
|
+
if (!dirtyFromChanges && !registrationMayBeStale && !pendingDirty) {
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
54
73
|
// Guard: qmd must be installed. `qmd collection list` doubles as the
|
|
55
74
|
// availability probe AND the source for which collections already exist.
|
|
56
75
|
const list = exec(["collection", "list"]);
|
|
@@ -59,27 +78,61 @@ export function reindexAfterSync(hqRoot, opts = {}) {
|
|
|
59
78
|
result.qmdAvailable = true;
|
|
60
79
|
const existingCollections = list.stdout;
|
|
61
80
|
// 1. Auto-register missing company knowledge collections.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
81
|
+
if (registrationMayBeStale) {
|
|
82
|
+
const companiesDir = path.join(hqRoot, "companies");
|
|
83
|
+
const slugs = (opts.readCompanies ?? defaultReadCompanies)(companiesDir);
|
|
84
|
+
for (const slug of slugs) {
|
|
85
|
+
const knowledgeDir = path.join(companiesDir, slug, "knowledge");
|
|
86
|
+
if (!existsSync(knowledgeDir))
|
|
87
|
+
continue;
|
|
88
|
+
const hasMd = (opts.hasIndexableMarkdown ?? defaultHasIndexableMarkdown)(knowledgeDir);
|
|
89
|
+
if (!hasMd)
|
|
90
|
+
continue;
|
|
91
|
+
// Already registered? qmd collection URIs look like `qmd://<slug>/`.
|
|
92
|
+
if (existingCollections.includes(`qmd://${slug}/`))
|
|
93
|
+
continue;
|
|
94
|
+
const add = exec(["collection", "add", knowledgeDir, "--name", slug, "--mask", "**/*.md"]);
|
|
95
|
+
if (add.status === 0) {
|
|
96
|
+
exec(["context", "add", `qmd://${slug}`, `Knowledge base for ${slug}.`]);
|
|
97
|
+
result.collectionsAdded.push(slug);
|
|
98
|
+
}
|
|
78
99
|
}
|
|
79
100
|
}
|
|
80
101
|
// 2. Incremental lexical reindex.
|
|
81
|
-
const
|
|
82
|
-
|
|
102
|
+
const shouldUpdate = dirtyFromChanges || pendingDirty;
|
|
103
|
+
if (shouldUpdate) {
|
|
104
|
+
const nowMs = opts.nowMs ?? Date.now();
|
|
105
|
+
const debounceMs = opts.debounceMs ??
|
|
106
|
+
(changedPaths === undefined ? 0 : DEFAULT_CHANGED_PATH_DEBOUNCE_MS);
|
|
107
|
+
const pendingSinceMs = pendingDirty && typeof state.pendingSinceMs === "number"
|
|
108
|
+
? state.pendingSinceMs
|
|
109
|
+
: nowMs;
|
|
110
|
+
if (debounceMs > 0 && nowMs - pendingSinceMs < debounceMs) {
|
|
111
|
+
writeState(statePath, {
|
|
112
|
+
...state,
|
|
113
|
+
pendingDirty: true,
|
|
114
|
+
pendingSinceMs,
|
|
115
|
+
});
|
|
116
|
+
result.pendingDirty = true;
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
const update = exec(["update"]);
|
|
120
|
+
result.updated = update.status === 0;
|
|
121
|
+
if (result.updated) {
|
|
122
|
+
writeState(statePath, {
|
|
123
|
+
pendingDirty: false,
|
|
124
|
+
lastSuccessMs: nowMs,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
writeState(statePath, {
|
|
129
|
+
...state,
|
|
130
|
+
pendingDirty: true,
|
|
131
|
+
pendingSinceMs,
|
|
132
|
+
});
|
|
133
|
+
result.pendingDirty = true;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
83
136
|
// 3. Embeddings only on explicit request.
|
|
84
137
|
if (opts.embed) {
|
|
85
138
|
const embed = exec(["embed"]);
|
|
@@ -102,6 +155,27 @@ export function reindexAfterSync(hqRoot, opts = {}) {
|
|
|
102
155
|
}
|
|
103
156
|
return result;
|
|
104
157
|
}
|
|
158
|
+
function readState(statePath) {
|
|
159
|
+
try {
|
|
160
|
+
return JSON.parse(fs.readFileSync(statePath, "utf8"));
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
return {};
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function writeState(statePath, state) {
|
|
167
|
+
try {
|
|
168
|
+
fs.mkdirSync(path.dirname(statePath), { recursive: true });
|
|
169
|
+
fs.writeFileSync(statePath, JSON.stringify(state, null, 2) + "\n");
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
// State is an optimization/guarantee aid; QMD failures must not fail sync.
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function isKnowledgeMarkdownPath(relPath) {
|
|
176
|
+
const normalized = relPath.split(path.sep).join("/");
|
|
177
|
+
return /^companies\/[^/]+\/knowledge\/.+\.md$/i.test(normalized);
|
|
178
|
+
}
|
|
105
179
|
function defaultReadCompanies(companiesDir) {
|
|
106
180
|
try {
|
|
107
181
|
return fs
|
package/dist/qmd-reindex.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qmd-reindex.js","sourceRoot":"","sources":["../src/qmd-reindex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAO1C,MAAM,WAAW,GAAY,CAAC,IAAI,EAAE,EAAE;IACpC,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE;QACjC,QAAQ,EAAE,MAAM;QAChB,qEAAqE;QACrE,wCAAwC;QACxC,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IACH,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;AAC1D,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"qmd-reindex.js","sourceRoot":"","sources":["../src/qmd-reindex.ts"],"names":[],"mappings":"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"}
|
package/dist/qmd-reindex.test.js
CHANGED
|
@@ -89,6 +89,53 @@ describe("reindexAfterSync", () => {
|
|
|
89
89
|
expect(r.collectionsAdded).toEqual([]);
|
|
90
90
|
expect(calls).toEqual([["collection", "list"], ["update"]]);
|
|
91
91
|
});
|
|
92
|
+
it("skips qmd entirely when provided changed paths do not touch knowledge markdown", () => {
|
|
93
|
+
const { exec, calls } = fakeExec({ listStdout: "" });
|
|
94
|
+
const r = reindexAfterSync("/hq", {
|
|
95
|
+
exec,
|
|
96
|
+
existsSync: () => true,
|
|
97
|
+
changedPaths: ["companies/acme/docs/readme.txt"],
|
|
98
|
+
});
|
|
99
|
+
expect(r.qmdAvailable).toBe(false);
|
|
100
|
+
expect(r.updated).toBe(false);
|
|
101
|
+
expect(calls).toEqual([]);
|
|
102
|
+
});
|
|
103
|
+
it("debounces dirty updates with a pending marker and flushes the final update later", () => {
|
|
104
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "hq-qmd-debounce-"));
|
|
105
|
+
try {
|
|
106
|
+
const statePath = path.join(dir, "qmd-state.json");
|
|
107
|
+
const { exec, calls } = fakeExec({ listStdout: "acme (qmd://acme/)\n" });
|
|
108
|
+
const first = reindexAfterSync("/hq", {
|
|
109
|
+
exec,
|
|
110
|
+
existsSync: () => true,
|
|
111
|
+
changedPaths: ["companies/acme/knowledge/note.md"],
|
|
112
|
+
debounceMs: 60_000,
|
|
113
|
+
nowMs: 100_000,
|
|
114
|
+
statePath,
|
|
115
|
+
});
|
|
116
|
+
expect(first.updated).toBe(false);
|
|
117
|
+
expect(first.pendingDirty).toBe(true);
|
|
118
|
+
expect(calls).toEqual([["collection", "list"]]);
|
|
119
|
+
const second = reindexAfterSync("/hq", {
|
|
120
|
+
exec,
|
|
121
|
+
existsSync: () => true,
|
|
122
|
+
changedPaths: [],
|
|
123
|
+
debounceMs: 60_000,
|
|
124
|
+
nowMs: 161_000,
|
|
125
|
+
statePath,
|
|
126
|
+
});
|
|
127
|
+
expect(second.updated).toBe(true);
|
|
128
|
+
expect(second.pendingDirty).toBe(false);
|
|
129
|
+
expect(calls).toEqual([
|
|
130
|
+
["collection", "list"],
|
|
131
|
+
["collection", "list"],
|
|
132
|
+
["update"],
|
|
133
|
+
]);
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
137
|
+
}
|
|
138
|
+
});
|
|
92
139
|
it("runs embed only when embed:true", () => {
|
|
93
140
|
const { exec, calls } = fakeExec({ listStdout: "" });
|
|
94
141
|
const r = reindexAfterSync("/hq", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qmd-reindex.test.js","sourceRoot":"","sources":["../src/qmd-reindex.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"qmd-reindex.test.js","sourceRoot":"","sources":["../src/qmd-reindex.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -168,6 +168,7 @@ export async function executeCompanyFanout(options: {
|
|
|
168
168
|
filesOutOfScope: 0,
|
|
169
169
|
scopeOrphansRemoved: 0,
|
|
170
170
|
scopeOrphansBlocked: 0,
|
|
171
|
+
changedPaths: [],
|
|
171
172
|
};
|
|
172
173
|
|
|
173
174
|
// Local (non-cloud) companies always sync to the personal vault. The
|
|
@@ -255,6 +256,7 @@ export async function executeCompanyFanout(options: {
|
|
|
255
256
|
...(options.operationLockAlreadyHeld
|
|
256
257
|
? { operationLockAlreadyHeld: true }
|
|
257
258
|
: {}),
|
|
259
|
+
skipReindex: true,
|
|
258
260
|
onEvent: tagAndEmit,
|
|
259
261
|
});
|
|
260
262
|
}
|
|
@@ -273,6 +275,12 @@ export async function executeCompanyFanout(options: {
|
|
|
273
275
|
|
|
274
276
|
state.filesDownloaded = pullResult.filesDownloaded;
|
|
275
277
|
state.bytesDownloaded = pullResult.bytesDownloaded;
|
|
278
|
+
state.filesTombstoned = pullResult.filesTombstoned;
|
|
279
|
+
state.scopeOrphansRemoved = pullResult.scopeOrphansRemoved;
|
|
280
|
+
state.changedPaths = normalizePullChangedPaths(
|
|
281
|
+
target,
|
|
282
|
+
pullResult.changedPaths,
|
|
283
|
+
);
|
|
276
284
|
state.filesUploaded = pushResult.filesUploaded;
|
|
277
285
|
state.bytesUploaded = pushResult.bytesUploaded;
|
|
278
286
|
state.status = companyHadTransferError
|
|
@@ -342,6 +350,7 @@ export async function executeCompanyFanout(options: {
|
|
|
342
350
|
filesOutOfScope: 0,
|
|
343
351
|
scopeOrphansRemoved: 0,
|
|
344
352
|
scopeOrphansBlocked: 0,
|
|
353
|
+
changedPaths: [],
|
|
345
354
|
});
|
|
346
355
|
options.emit({
|
|
347
356
|
type: "error",
|
|
@@ -354,3 +363,15 @@ export async function executeCompanyFanout(options: {
|
|
|
354
363
|
|
|
355
364
|
return { stateByCompany, errors, allConflicts };
|
|
356
365
|
}
|
|
366
|
+
|
|
367
|
+
function normalizePullChangedPaths(
|
|
368
|
+
target: RunnerTarget,
|
|
369
|
+
changedPaths: string[] | undefined,
|
|
370
|
+
): string[] {
|
|
371
|
+
const paths = changedPaths ?? [];
|
|
372
|
+
return paths.map((p) => {
|
|
373
|
+
const normalized = p.split(path.sep).join("/");
|
|
374
|
+
if (target.personalMode === true) return normalized;
|
|
375
|
+
return `companies/${target.slug}/${normalized}`;
|
|
376
|
+
});
|
|
377
|
+
}
|
|
@@ -8,6 +8,9 @@ export interface CompanyState {
|
|
|
8
8
|
status: CompanyStatus;
|
|
9
9
|
filesDownloaded: number;
|
|
10
10
|
bytesDownloaded: number;
|
|
11
|
+
filesTombstoned: number;
|
|
12
|
+
scopeOrphansRemoved: number;
|
|
13
|
+
changedPaths: string[];
|
|
11
14
|
filesUploaded: number;
|
|
12
15
|
bytesUploaded: number;
|
|
13
16
|
}
|
|
@@ -15,8 +18,12 @@ export interface CompanyState {
|
|
|
15
18
|
export interface AllCompleteRollup {
|
|
16
19
|
totalDownloaded: number;
|
|
17
20
|
totalDownloadedBytes: number;
|
|
21
|
+
totalTombstoned: number;
|
|
22
|
+
totalScopeOrphansRemoved: number;
|
|
18
23
|
totalUploaded: number;
|
|
19
24
|
totalUploadedBytes: number;
|
|
25
|
+
changedPaths: string[];
|
|
26
|
+
needsReindex: boolean;
|
|
20
27
|
partial: boolean;
|
|
21
28
|
companies: Extract<RunnerEvent, { type: "all-complete" }>["companies"];
|
|
22
29
|
}
|
|
@@ -27,6 +34,9 @@ export function createCompanyState(company: string): CompanyState {
|
|
|
27
34
|
status: "errored",
|
|
28
35
|
filesDownloaded: 0,
|
|
29
36
|
bytesDownloaded: 0,
|
|
37
|
+
filesTombstoned: 0,
|
|
38
|
+
scopeOrphansRemoved: 0,
|
|
39
|
+
changedPaths: [],
|
|
30
40
|
filesUploaded: 0,
|
|
31
41
|
bytesUploaded: 0,
|
|
32
42
|
};
|
|
@@ -38,8 +48,11 @@ export function rollupAllComplete(
|
|
|
38
48
|
): AllCompleteRollup {
|
|
39
49
|
let totalDownloaded = 0;
|
|
40
50
|
let totalDownloadedBytes = 0;
|
|
51
|
+
let totalTombstoned = 0;
|
|
52
|
+
let totalScopeOrphansRemoved = 0;
|
|
41
53
|
let totalUploaded = 0;
|
|
42
54
|
let totalUploadedBytes = 0;
|
|
55
|
+
const changedPaths: string[] = [];
|
|
43
56
|
let partial = false;
|
|
44
57
|
const companies: AllCompleteRollup["companies"] = [];
|
|
45
58
|
|
|
@@ -48,8 +61,11 @@ export function rollupAllComplete(
|
|
|
48
61
|
if (!s) continue;
|
|
49
62
|
totalDownloaded += s.filesDownloaded;
|
|
50
63
|
totalDownloadedBytes += s.bytesDownloaded;
|
|
64
|
+
totalTombstoned += s.filesTombstoned;
|
|
65
|
+
totalScopeOrphansRemoved += s.scopeOrphansRemoved;
|
|
51
66
|
totalUploaded += s.filesUploaded;
|
|
52
67
|
totalUploadedBytes += s.bytesUploaded;
|
|
68
|
+
changedPaths.push(...s.changedPaths);
|
|
53
69
|
if (s.status !== "complete") partial = true;
|
|
54
70
|
companies.push({
|
|
55
71
|
company: s.company,
|
|
@@ -64,8 +80,15 @@ export function rollupAllComplete(
|
|
|
64
80
|
return {
|
|
65
81
|
totalDownloaded,
|
|
66
82
|
totalDownloadedBytes,
|
|
83
|
+
totalTombstoned,
|
|
84
|
+
totalScopeOrphansRemoved,
|
|
67
85
|
totalUploaded,
|
|
68
86
|
totalUploadedBytes,
|
|
87
|
+
changedPaths,
|
|
88
|
+
needsReindex:
|
|
89
|
+
totalDownloaded > 0 ||
|
|
90
|
+
totalTombstoned > 0 ||
|
|
91
|
+
totalScopeOrphansRemoved > 0,
|
|
69
92
|
partial,
|
|
70
93
|
companies,
|
|
71
94
|
};
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
OPERATION_LOCKED_EXIT,
|
|
9
9
|
} from "../operation-lock.js";
|
|
10
10
|
import { describeError } from "../lib/describe-error.js";
|
|
11
|
+
import { TRANSIENT_NETWORK_EXIT } from "../lib/net-errors.js";
|
|
11
12
|
import { getOrCreateMachineId } from "../lib/machine-id.js";
|
|
12
13
|
import {
|
|
13
14
|
TreeWatcher,
|
|
@@ -430,7 +431,16 @@ export async function runWatchLoop(
|
|
|
430
431
|
try {
|
|
431
432
|
while (!stopped) {
|
|
432
433
|
const result = await runGuarded(passArgv);
|
|
433
|
-
if (result
|
|
434
|
+
if (result === TRANSIENT_NETWORK_EXIT) {
|
|
435
|
+
// The machine was briefly offline (the discovery fetch failed after
|
|
436
|
+
// retries). That is NOT a crash — stay alive and retry on the next
|
|
437
|
+
// poll. Returning it here would exit the watcher and the menubar would
|
|
438
|
+
// report "watcher exited unexpectedly" for every network blip
|
|
439
|
+
// (HQ-SYNC-1W). Log to stderr so it still shows up as a breadcrumb.
|
|
440
|
+
process.stderr.write(
|
|
441
|
+
"hq-sync-runner: watch pass skipped — transient network failure; retrying next poll\n",
|
|
442
|
+
);
|
|
443
|
+
} else if (result !== 0) {
|
|
434
444
|
return result;
|
|
435
445
|
}
|
|
436
446
|
await Promise.race([sleep(pollMs), stoppedSignal]);
|
|
@@ -35,6 +35,7 @@ import { FakeClock } from "../watcher.js";
|
|
|
35
35
|
import { PERSONAL_VAULT_JOURNAL_SLUG } from "../journal.js";
|
|
36
36
|
import { HQ_CLOUD_VERSION } from "../version.js";
|
|
37
37
|
import { lockPathFor, OPERATION_LOCKED_EXIT } from "../operation-lock.js";
|
|
38
|
+
import { TRANSIENT_NETWORK_EXIT } from "../lib/net-errors.js";
|
|
38
39
|
import type { SyncResult, SyncOptions } from "../cli/sync.js";
|
|
39
40
|
import type { ShareResult, ShareOptions } from "../cli/share.js";
|
|
40
41
|
import type {
|
|
@@ -112,6 +113,7 @@ function defaultSyncResult(overrides: Partial<SyncResult> = {}): SyncResult {
|
|
|
112
113
|
filesOutOfScope: 0,
|
|
113
114
|
scopeOrphansRemoved: 0,
|
|
114
115
|
scopeOrphansBlocked: 0,
|
|
116
|
+
changedPaths: [],
|
|
115
117
|
...overrides,
|
|
116
118
|
};
|
|
117
119
|
}
|
|
@@ -205,6 +207,14 @@ function makeDeps(overrides: Partial<RunnerDeps> = {}): TestDeps {
|
|
|
205
207
|
getAccessToken: vi.fn().mockResolvedValue("test-access-token"),
|
|
206
208
|
createVaultClient: vi.fn().mockImplementation(() => makeVaultStub()),
|
|
207
209
|
sync: vi.fn().mockResolvedValue(defaultSyncResult()),
|
|
210
|
+
reindex: vi.fn(() => ({ status: 0 })),
|
|
211
|
+
qmdReindex: vi.fn(() => ({
|
|
212
|
+
qmdAvailable: true,
|
|
213
|
+
collectionsAdded: [],
|
|
214
|
+
updated: true,
|
|
215
|
+
embedded: false,
|
|
216
|
+
pendingDirty: false,
|
|
217
|
+
})),
|
|
208
218
|
...overrides,
|
|
209
219
|
stdout,
|
|
210
220
|
stderr,
|
|
@@ -388,6 +398,49 @@ describe("memberships retry", () => {
|
|
|
388
398
|
});
|
|
389
399
|
});
|
|
390
400
|
|
|
401
|
+
it("a transient network failure (fetch failed) during discovery returns TRANSIENT_NETWORK_EXIT, not 1 (HQ-SYNC-1W)", async () => {
|
|
402
|
+
// Regression for the "auto-sync watcher exited unexpectedly (code=Some(1))"
|
|
403
|
+
// cluster: a machine that stays offline through all 3 membership retries
|
|
404
|
+
// used to `return 1`, which the watch loop propagated and the menubar
|
|
405
|
+
// reported as a crash for every network blip. undici surfaces the blip as
|
|
406
|
+
// `TypeError: fetch failed`; that must map to the retryable exit code so the
|
|
407
|
+
// watcher stays alive instead of crash-reporting. A one-shot run still sees
|
|
408
|
+
// a non-zero exit.
|
|
409
|
+
let listCalls = 0;
|
|
410
|
+
const stub = makeVaultStub();
|
|
411
|
+
stub.listMyMemberships = () => {
|
|
412
|
+
listCalls++;
|
|
413
|
+
return Promise.reject(new TypeError("fetch failed"));
|
|
414
|
+
};
|
|
415
|
+
const deps = makeDeps({ createVaultClient: () => stub });
|
|
416
|
+
const code = await runRunner(["--companies"], deps);
|
|
417
|
+
expect(code).toBe(TRANSIENT_NETWORK_EXIT);
|
|
418
|
+
expect(listCalls).toBe(3);
|
|
419
|
+
// Still surfaced for observability — just no longer a "code 1" crash.
|
|
420
|
+
const events = deps.stderr.events();
|
|
421
|
+
expect(events).toHaveLength(1);
|
|
422
|
+
expect(events[0]).toMatchObject({
|
|
423
|
+
type: "error",
|
|
424
|
+
message: "fetch failed",
|
|
425
|
+
path: "(discovery)",
|
|
426
|
+
});
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
it("a NON-transient discovery failure still returns 1 (unchanged)", async () => {
|
|
430
|
+
// Guard the conservative classifier: a generic error (not a transport
|
|
431
|
+
// shape) is still a hard exit 1, exactly as before.
|
|
432
|
+
let listCalls = 0;
|
|
433
|
+
const stub = makeVaultStub();
|
|
434
|
+
stub.listMyMemberships = () => {
|
|
435
|
+
listCalls++;
|
|
436
|
+
return Promise.reject(new Error("unexpected 500 from vault api"));
|
|
437
|
+
};
|
|
438
|
+
const deps = makeDeps({ createVaultClient: () => stub });
|
|
439
|
+
const code = await runRunner(["--companies"], deps);
|
|
440
|
+
expect(code).toBe(1);
|
|
441
|
+
expect(listCalls).toBe(3);
|
|
442
|
+
});
|
|
443
|
+
|
|
391
444
|
it("VaultAuthError short-circuits retry (no retries on auth failure)", async () => {
|
|
392
445
|
let listCalls = 0;
|
|
393
446
|
const stub = makeVaultStub();
|
|
@@ -1602,6 +1655,87 @@ describe("all-complete aggregate", () => {
|
|
|
1602
1655
|
});
|
|
1603
1656
|
});
|
|
1604
1657
|
|
|
1658
|
+
it("skips per-target native reindex and runs one final reindex for tombstones or scope orphans", async () => {
|
|
1659
|
+
const slugs: Record<string, string> = { cmp_a: "acme", cmp_b: "beta" };
|
|
1660
|
+
const reindex = vi.fn(() => ({ status: 0 }));
|
|
1661
|
+
const syncSpy = vi
|
|
1662
|
+
.fn<(opts: SyncOptions) => Promise<SyncResult>>()
|
|
1663
|
+
.mockResolvedValueOnce(defaultSyncResult({ filesTombstoned: 1 }))
|
|
1664
|
+
.mockResolvedValueOnce(defaultSyncResult({ scopeOrphansRemoved: 1 }));
|
|
1665
|
+
const deps = makeDeps({
|
|
1666
|
+
operationLockAlreadyHeld: true,
|
|
1667
|
+
createVaultClient: () =>
|
|
1668
|
+
makeVaultStub({
|
|
1669
|
+
memberships: [{ companyUid: "cmp_a" }, { companyUid: "cmp_b" }],
|
|
1670
|
+
entityGet: (uid: string) =>
|
|
1671
|
+
Promise.resolve({ uid, slug: slugs[uid] ?? uid } as unknown as EntityInfo),
|
|
1672
|
+
}),
|
|
1673
|
+
sync: syncSpy,
|
|
1674
|
+
reindex,
|
|
1675
|
+
} as Partial<RunnerDeps>);
|
|
1676
|
+
|
|
1677
|
+
const code = await runRunner(["--companies", "--hq-root", "/tmp/fake-hq"], deps);
|
|
1678
|
+
|
|
1679
|
+
expect(code).toBe(0);
|
|
1680
|
+
expect(syncSpy).toHaveBeenCalledTimes(2);
|
|
1681
|
+
expect(syncSpy.mock.calls.map(([opts]) => opts.skipReindex)).toEqual([
|
|
1682
|
+
true,
|
|
1683
|
+
true,
|
|
1684
|
+
]);
|
|
1685
|
+
expect(reindex).toHaveBeenCalledTimes(1);
|
|
1686
|
+
expect(reindex).toHaveBeenCalledWith({
|
|
1687
|
+
repoRoot: "/tmp/fake-hq",
|
|
1688
|
+
skipLock: true,
|
|
1689
|
+
});
|
|
1690
|
+
});
|
|
1691
|
+
|
|
1692
|
+
it("gates qmd to knowledge markdown changes and propagates hq-relative changed paths", async () => {
|
|
1693
|
+
const slugs: Record<string, string> = { cmp_a: "acme", cmp_b: "beta" };
|
|
1694
|
+
const qmdReindex = vi.fn(() => ({
|
|
1695
|
+
qmdAvailable: true,
|
|
1696
|
+
collectionsAdded: [],
|
|
1697
|
+
updated: true,
|
|
1698
|
+
embedded: false,
|
|
1699
|
+
pendingDirty: false,
|
|
1700
|
+
}));
|
|
1701
|
+
const deps = makeDeps({
|
|
1702
|
+
createVaultClient: () =>
|
|
1703
|
+
makeVaultStub({
|
|
1704
|
+
memberships: [{ companyUid: "cmp_a" }, { companyUid: "cmp_b" }],
|
|
1705
|
+
entityGet: (uid: string) =>
|
|
1706
|
+
Promise.resolve({ uid, slug: slugs[uid] ?? uid } as unknown as EntityInfo),
|
|
1707
|
+
}),
|
|
1708
|
+
sync: vi
|
|
1709
|
+
.fn<(opts: SyncOptions) => Promise<SyncResult>>()
|
|
1710
|
+
.mockResolvedValueOnce(
|
|
1711
|
+
defaultSyncResult({
|
|
1712
|
+
filesDownloaded: 1,
|
|
1713
|
+
changedPaths: ["docs/readme.txt"],
|
|
1714
|
+
} as Partial<SyncResult>),
|
|
1715
|
+
)
|
|
1716
|
+
.mockResolvedValueOnce(
|
|
1717
|
+
defaultSyncResult({
|
|
1718
|
+
filesTombstoned: 1,
|
|
1719
|
+
changedPaths: ["knowledge/old.md"],
|
|
1720
|
+
} as Partial<SyncResult>),
|
|
1721
|
+
),
|
|
1722
|
+
reindex: vi.fn(() => ({ status: 0 })),
|
|
1723
|
+
qmdReindex,
|
|
1724
|
+
} as Partial<RunnerDeps>);
|
|
1725
|
+
|
|
1726
|
+
const code = await runRunner(["--companies", "--hq-root", "/tmp/fake-hq"], deps);
|
|
1727
|
+
|
|
1728
|
+
expect(code).toBe(0);
|
|
1729
|
+
expect(qmdReindex).toHaveBeenCalledTimes(1);
|
|
1730
|
+
expect(qmdReindex).toHaveBeenCalledWith(
|
|
1731
|
+
"/tmp/fake-hq",
|
|
1732
|
+
expect.objectContaining({
|
|
1733
|
+
changedPaths: ["companies/beta/knowledge/old.md"],
|
|
1734
|
+
forceCollectionRefresh: true,
|
|
1735
|
+
}),
|
|
1736
|
+
);
|
|
1737
|
+
});
|
|
1738
|
+
|
|
1605
1739
|
it("collects company-level errors into the all-complete errors array", async () => {
|
|
1606
1740
|
const slugs: Record<string, string> = { cmp_a: "acme", cmp_b: "beta" };
|
|
1607
1741
|
const deps = makeDeps({
|
|
@@ -3217,6 +3351,39 @@ describe("runRunnerWithLoop — event-push wiring", () => {
|
|
|
3217
3351
|
expect(watcher.disposed).toBe(true);
|
|
3218
3352
|
});
|
|
3219
3353
|
|
|
3354
|
+
it("a TRANSIENT_NETWORK_EXIT poll pass does NOT surface as a crash — the loop retries (HQ-SYNC-1W)", async () => {
|
|
3355
|
+
// A transient offline blip must keep the watcher alive: the loop logs and
|
|
3356
|
+
// polls again instead of returning the code and letting the process exit
|
|
3357
|
+
// (which the menubar reports as "watcher exited unexpectedly"). A genuine
|
|
3358
|
+
// hard error on a later pass still terminates the loop.
|
|
3359
|
+
const watcher = makeWatcherStub();
|
|
3360
|
+
let n = 0;
|
|
3361
|
+
const runPass = vi.fn().mockImplementation(async () => {
|
|
3362
|
+
n++;
|
|
3363
|
+
// First pass: machine is offline (transient). Second pass: a real hard
|
|
3364
|
+
// error, used here only to end the otherwise-infinite loop deterministically.
|
|
3365
|
+
return n === 1 ? TRANSIENT_NETWORK_EXIT : 2;
|
|
3366
|
+
});
|
|
3367
|
+
|
|
3368
|
+
const code = await runRunnerWithLoop(
|
|
3369
|
+
["--companies", "--watch", "--event-push", "--hq-root", "/tmp/hq"],
|
|
3370
|
+
{
|
|
3371
|
+
runPass,
|
|
3372
|
+
clock: new FakeClock(),
|
|
3373
|
+
createWatcher: () => watcher,
|
|
3374
|
+
sleep: () => Promise.resolve(),
|
|
3375
|
+
onShutdownSignal: () => () => {},
|
|
3376
|
+
},
|
|
3377
|
+
);
|
|
3378
|
+
|
|
3379
|
+
// The transient pass did NOT end the loop — it ran again…
|
|
3380
|
+
expect(runPass).toHaveBeenCalledTimes(2);
|
|
3381
|
+
// …and the transient code was never surfaced as the watcher's exit code.
|
|
3382
|
+
expect(code).toBe(2);
|
|
3383
|
+
expect(code).not.toBe(TRANSIENT_NETWORK_EXIT);
|
|
3384
|
+
expect(watcher.disposed).toBe(true);
|
|
3385
|
+
});
|
|
3386
|
+
|
|
3220
3387
|
it("without --event-push, no watcher is created (poll-only safety net)", async () => {
|
|
3221
3388
|
let triggerShutdown = () => {};
|
|
3222
3389
|
const createWatcher = vi.fn(() => makeWatcherStub());
|