@indigoai-us/hq-cloud 6.13.5 → 6.14.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-company.d.ts +1 -0
- package/dist/bin/sync-runner-company.d.ts.map +1 -1
- package/dist/bin/sync-runner-company.js +41 -2
- package/dist/bin/sync-runner-company.js.map +1 -1
- package/dist/bin/sync-runner-watch-loop.d.ts +9 -1
- package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -1
- package/dist/bin/sync-runner-watch-loop.js +75 -50
- package/dist/bin/sync-runner-watch-loop.js.map +1 -1
- package/dist/bin/sync-runner-watch-routes.d.ts +3 -0
- package/dist/bin/sync-runner-watch-routes.d.ts.map +1 -1
- package/dist/bin/sync-runner-watch-routes.js +52 -1
- package/dist/bin/sync-runner-watch-routes.js.map +1 -1
- package/dist/bin/sync-runner.d.ts.map +1 -1
- package/dist/bin/sync-runner.js +10 -0
- package/dist/bin/sync-runner.js.map +1 -1
- package/dist/bin/sync-runner.test.js +597 -45
- package/dist/bin/sync-runner.test.js.map +1 -1
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +18 -0
- package/dist/watcher.js.map +1 -1
- package/dist/watcher.test.js +27 -0
- package/dist/watcher.test.js.map +1 -1
- package/package.json +1 -1
- package/src/bin/sync-runner-company.ts +61 -2
- package/src/bin/sync-runner-watch-loop.ts +105 -54
- package/src/bin/sync-runner-watch-routes.ts +57 -1
- package/src/bin/sync-runner.test.ts +697 -50
- package/src/bin/sync-runner.ts +11 -0
- package/src/watcher.test.ts +42 -0
- package/src/watcher.ts +18 -0
package/src/bin/sync-runner.ts
CHANGED
|
@@ -723,6 +723,8 @@ interface ParsedArgs {
|
|
|
723
723
|
* mode (single-company runs never visit the personal target).
|
|
724
724
|
*/
|
|
725
725
|
skipPersonal: boolean;
|
|
726
|
+
/** Repeatable company/personal-relative path scope for push-only passes. */
|
|
727
|
+
scopePaths: string[];
|
|
726
728
|
/**
|
|
727
729
|
* Bounded wait (seconds) for the per-root operation lock when another op is
|
|
728
730
|
* already running. `0` → refuse immediately (pre-wait behavior); omitted →
|
|
@@ -742,6 +744,7 @@ function parseArgs(argv: string[]): ParsedArgs | { error: string } {
|
|
|
742
744
|
let watch = false;
|
|
743
745
|
let pollRemoteMs: number | undefined;
|
|
744
746
|
let skipPersonal = false;
|
|
747
|
+
const scopePaths: string[] = [];
|
|
745
748
|
let eventPush = false;
|
|
746
749
|
let lockTimeoutSec: number | undefined;
|
|
747
750
|
|
|
@@ -817,6 +820,12 @@ function parseArgs(argv: string[]): ParsedArgs | { error: string } {
|
|
|
817
820
|
// @getindigo.ai identities for the first release.
|
|
818
821
|
eventPush = true;
|
|
819
822
|
break;
|
|
823
|
+
case "--scope-path": {
|
|
824
|
+
const val = argv[++i];
|
|
825
|
+
if (!val) return { error: "--scope-path requires a value" };
|
|
826
|
+
scopePaths.push(val);
|
|
827
|
+
break;
|
|
828
|
+
}
|
|
820
829
|
case "--lock-timeout": {
|
|
821
830
|
const val = argv[++i];
|
|
822
831
|
if (!val) return { error: "--lock-timeout requires a value (seconds)" };
|
|
@@ -867,6 +876,7 @@ function parseArgs(argv: string[]): ParsedArgs | { error: string } {
|
|
|
867
876
|
watch,
|
|
868
877
|
pollRemoteMs,
|
|
869
878
|
skipPersonal,
|
|
879
|
+
scopePaths,
|
|
870
880
|
eventPush,
|
|
871
881
|
lockTimeoutSec,
|
|
872
882
|
};
|
|
@@ -1219,6 +1229,7 @@ export async function runRunner(
|
|
|
1219
1229
|
shareFn,
|
|
1220
1230
|
resolveDeletePolicy,
|
|
1221
1231
|
emit,
|
|
1232
|
+
scopePaths: parsed.scopePaths,
|
|
1222
1233
|
});
|
|
1223
1234
|
const { errors, allConflicts } = fanout;
|
|
1224
1235
|
const rollup = rollupAllComplete(plan, fanout.stateByCompany);
|
package/src/watcher.test.ts
CHANGED
|
@@ -350,6 +350,48 @@ describe("US-002: createWatchPathFilter — personal-vault exclusions", () => {
|
|
|
350
350
|
// mode the ignore stack alone governs and lets it through.
|
|
351
351
|
expect(nonPersonal(path.join(ROOT, "companies/indigo/board.json"))).toBe(true);
|
|
352
352
|
});
|
|
353
|
+
|
|
354
|
+
// ── Never-synced heavy buckets pruned in BOTH modes ─────────────────────
|
|
355
|
+
// In --companies mode personalMode=false, so the excluded-top-level layer
|
|
356
|
+
// never ran and the watcher descended into the local git worktrees
|
|
357
|
+
// (workspace/worktrees/, ~200k transient files from agent coding runs) and
|
|
358
|
+
// the on-box repos checkout (repos/). Neither ever vault-syncs in any mode,
|
|
359
|
+
// so watching them only burns inotify watches (near the OS limit) + CPU on
|
|
360
|
+
// build churn it discards, and can trip the overflow→full-reconcile fallback.
|
|
361
|
+
it("non-personal mode EXCLUDES never-synced heavy buckets (workspace/worktrees, repos)", () => {
|
|
362
|
+
expect(
|
|
363
|
+
nonPersonal(path.join(ROOT, "workspace/worktrees/hq-console/src/a.ts")),
|
|
364
|
+
).toBe(false);
|
|
365
|
+
// The bucket dir itself is pruned so chokidar never descends into it.
|
|
366
|
+
expect(nonPersonal(path.join(ROOT, "workspace/worktrees"), true)).toBe(false);
|
|
367
|
+
expect(
|
|
368
|
+
nonPersonal(path.join(ROOT, "repos/private/hq-cloud/src/x.ts")),
|
|
369
|
+
).toBe(false);
|
|
370
|
+
expect(nonPersonal(path.join(ROOT, "repos"), true)).toBe(false);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
it("non-personal mode STILL watches synced content (companies/, workspace/agency, continuity)", () => {
|
|
374
|
+
expect(
|
|
375
|
+
nonPersonal(path.join(ROOT, "companies/indigo/board.json")),
|
|
376
|
+
).toBe(true);
|
|
377
|
+
expect(
|
|
378
|
+
nonPersonal(path.join(ROOT, "workspace/agency/indigo/nick/status.json")),
|
|
379
|
+
).toBe(true);
|
|
380
|
+
expect(
|
|
381
|
+
nonPersonal(path.join(ROOT, "workspace/threads/handoff.json")),
|
|
382
|
+
).toBe(true);
|
|
383
|
+
// chokidar must still descend into workspace/ to reach agency + continuity.
|
|
384
|
+
expect(nonPersonal(path.join(ROOT, "workspace"), true)).toBe(true);
|
|
385
|
+
// A worktrees SIBLING under workspace/ is unaffected (only worktrees pruned).
|
|
386
|
+
expect(
|
|
387
|
+
nonPersonal(path.join(ROOT, "workspace/agency"), true),
|
|
388
|
+
).toBe(true);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it("personal mode still excludes worktrees + repos (regression, unchanged)", () => {
|
|
392
|
+
expect(personal(path.join(ROOT, "workspace/worktrees/x/a.ts"))).toBe(false);
|
|
393
|
+
expect(personal(path.join(ROOT, "repos/private/x/a.ts"))).toBe(false);
|
|
394
|
+
});
|
|
353
395
|
});
|
|
354
396
|
|
|
355
397
|
describe("US-002: TreeWatcher — debounce coalesce (FakeClock seam)", () => {
|
package/src/watcher.ts
CHANGED
|
@@ -407,6 +407,24 @@ export function createWatchPathFilter(
|
|
|
407
407
|
// createIgnoreFilter returns true = "sync this"; false = "ignored".
|
|
408
408
|
if (!ignoreFilter(absolutePath, isDir)) return false;
|
|
409
409
|
|
|
410
|
+
// Never-synced heavy buckets — pruned in BOTH modes. The local git worktrees
|
|
411
|
+
// (`workspace/worktrees/`, where `/worktree` and agent coding runs check out
|
|
412
|
+
// repos — often 100k+ transient source/build files) and the on-box `repos/`
|
|
413
|
+
// checkout are never vault-synced in any mode. In personalMode the
|
|
414
|
+
// excluded-top-level layer below already drops them; in `--companies` mode
|
|
415
|
+
// that layer is skipped, so without this the watcher descends into every
|
|
416
|
+
// worktree source tree — tens of thousands of wasted inotify watches (the
|
|
417
|
+
// outpost sat at ~78% of the OS limit) plus CPU spent processing build churn
|
|
418
|
+
// it immediately discards, and enough backlog to trip the
|
|
419
|
+
// overflow → full-reconcile fallback. Returning false for the dir probe too
|
|
420
|
+
// prunes the whole subtree at descent instead of per-file. `companies/` and
|
|
421
|
+
// the synced `workspace/agency/` + continuity-pointer paths are untouched.
|
|
422
|
+
const topSegments = rel.split("/");
|
|
423
|
+
if (topSegments[0] === "repos") return false;
|
|
424
|
+
if (topSegments[0] === "workspace" && topSegments[1] === "worktrees") {
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
427
|
+
|
|
410
428
|
if (personalMode) {
|
|
411
429
|
// Continuity-pointer carve-out: the session pointer lives under the
|
|
412
430
|
// otherwise-excluded `workspace/`, so it must re-include BEFORE the
|