@cleocode/core 2026.10.8 → 2026.10.9
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/build-provenance.json +2 -2
- package/dist/cloud/auto-sync-command-entry.d.ts +13 -0
- package/dist/cloud/auto-sync-command-entry.d.ts.map +1 -0
- package/dist/cloud/auto-sync-command-entry.js +18 -0
- package/dist/cloud/auto-sync-command-entry.js.map +1 -0
- package/dist/cloud/auto-sync-command.d.ts +64 -0
- package/dist/cloud/auto-sync-command.d.ts.map +1 -0
- package/dist/cloud/auto-sync-command.js +109 -0
- package/dist/cloud/auto-sync-command.js.map +1 -0
- package/dist/cloud/auto-sync.d.ts +111 -0
- package/dist/cloud/auto-sync.d.ts.map +1 -0
- package/dist/cloud/auto-sync.js +275 -0
- package/dist/cloud/auto-sync.js.map +1 -0
- package/dist/cloud/nexus-cloud-device-overview.d.ts +52 -0
- package/dist/cloud/nexus-cloud-device-overview.d.ts.map +1 -0
- package/dist/cloud/nexus-cloud-device-overview.js +105 -0
- package/dist/cloud/nexus-cloud-device-overview.js.map +1 -0
- package/dist/cloud/nexus-cloud-journal-activity.d.ts +56 -0
- package/dist/cloud/nexus-cloud-journal-activity.d.ts.map +1 -0
- package/dist/cloud/nexus-cloud-journal-activity.js +98 -0
- package/dist/cloud/nexus-cloud-journal-activity.js.map +1 -0
- package/dist/cloud/nexus-cloud-status.d.ts.map +1 -1
- package/dist/cloud/nexus-cloud-status.js +88 -5
- package/dist/cloud/nexus-cloud-status.js.map +1 -1
- package/dist/cloud/nexus-vault.d.ts +19 -5
- package/dist/cloud/nexus-vault.d.ts.map +1 -1
- package/dist/cloud/nexus-vault.js +376 -71
- package/dist/cloud/nexus-vault.js.map +1 -1
- package/dist/cloud/replica-rebind.d.ts +14 -0
- package/dist/cloud/replica-rebind.d.ts.map +1 -1
- package/dist/cloud/replica-rebind.js +20 -1
- package/dist/cloud/replica-rebind.js.map +1 -1
- package/dist/config.d.ts +10 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +19 -0
- package/dist/config.js.map +1 -1
- package/dist/docs/docs-ops.d.ts +4 -2
- package/dist/docs/docs-ops.d.ts.map +1 -1
- package/dist/docs/docs-ops.js +107 -15
- package/dist/docs/docs-ops.js.map +1 -1
- package/dist/doctor/system-health.d.ts +76 -2
- package/dist/doctor/system-health.d.ts.map +1 -1
- package/dist/doctor/system-health.js +264 -41
- package/dist/doctor/system-health.js.map +1 -1
- package/dist/hooks/project-runner.d.ts +10 -0
- package/dist/hooks/project-runner.d.ts.map +1 -0
- package/dist/hooks/project-runner.js +328 -0
- package/dist/hooks/project-runner.js.map +1 -0
- package/dist/hooks/project-state.d.ts +41 -0
- package/dist/hooks/project-state.d.ts.map +1 -0
- package/dist/hooks/project-state.js +331 -0
- package/dist/hooks/project-state.js.map +1 -0
- package/dist/hooks/release-gate.d.ts +61 -0
- package/dist/hooks/release-gate.d.ts.map +1 -0
- package/dist/hooks/release-gate.js +70 -0
- package/dist/hooks/release-gate.js.map +1 -0
- package/dist/nexus/analyze-orchestrator.d.ts +2 -0
- package/dist/nexus/analyze-orchestrator.d.ts.map +1 -1
- package/dist/nexus/analyze-orchestrator.js +1 -0
- package/dist/nexus/analyze-orchestrator.js.map +1 -1
- package/dist/nexus/freshness.d.ts +67 -3
- package/dist/nexus/freshness.d.ts.map +1 -1
- package/dist/nexus/freshness.js +130 -9
- package/dist/nexus/freshness.js.map +1 -1
- package/dist/nexus/refresh-child.d.ts +14 -0
- package/dist/nexus/refresh-child.d.ts.map +1 -0
- package/dist/nexus/refresh-child.js +24 -0
- package/dist/nexus/refresh-child.js.map +1 -0
- package/dist/orchestrate/spawn-ops.d.ts +8 -1
- package/dist/orchestrate/spawn-ops.d.ts.map +1 -1
- package/dist/orchestrate/spawn-ops.js +42 -12
- package/dist/orchestrate/spawn-ops.js.map +1 -1
- package/dist/orchestration/spawn.d.ts +5 -0
- package/dist/orchestration/spawn.d.ts.map +1 -1
- package/dist/orchestration/spawn.js +4 -1
- package/dist/orchestration/spawn.js.map +1 -1
- package/dist/release/channel.d.ts.map +1 -1
- package/dist/release/channel.js +10 -0
- package/dist/release/channel.js.map +1 -1
- package/dist/release/github-pr.d.ts.map +1 -1
- package/dist/release/github-pr.js +1 -0
- package/dist/release/github-pr.js.map +1 -1
- package/dist/release/plan.d.ts +8 -3
- package/dist/release/plan.d.ts.map +1 -1
- package/dist/release/plan.js +72 -15
- package/dist/release/plan.js.map +1 -1
- package/dist/release/reconcile.d.ts.map +1 -1
- package/dist/release/reconcile.js +6 -15
- package/dist/release/reconcile.js.map +1 -1
- package/dist/sentient/daemon-entry.d.ts +6 -0
- package/dist/sentient/daemon-entry.d.ts.map +1 -1
- package/dist/sentient/daemon-entry.js +12 -0
- package/dist/sentient/daemon-entry.js.map +1 -1
- package/dist/sentient/worktree-dispatch.d.ts +7 -0
- package/dist/sentient/worktree-dispatch.d.ts.map +1 -1
- package/dist/sentient/worktree-dispatch.js +37 -1
- package/dist/sentient/worktree-dispatch.js.map +1 -1
- package/dist/sessions/session-end-snapshot-entry.d.ts +4 -1
- package/dist/sessions/session-end-snapshot-entry.d.ts.map +1 -1
- package/dist/sessions/session-end-snapshot-entry.js +9 -1
- package/dist/sessions/session-end-snapshot-entry.js.map +1 -1
- package/dist/spawn/agent-identity.d.ts.map +1 -1
- package/dist/spawn/agent-identity.js +96 -1
- package/dist/spawn/agent-identity.js.map +1 -1
- package/dist/spawn/branch-lock.d.ts +27 -8
- package/dist/spawn/branch-lock.d.ts.map +1 -1
- package/dist/spawn/branch-lock.js +57 -73
- package/dist/spawn/branch-lock.js.map +1 -1
- package/dist/store/agent-resolver.d.ts +6 -0
- package/dist/store/agent-resolver.d.ts.map +1 -1
- package/dist/store/agent-resolver.js +2 -0
- package/dist/store/agent-resolver.js.map +1 -1
- package/dist/store/dual-scope-db.d.ts +20 -0
- package/dist/store/dual-scope-db.d.ts.map +1 -1
- package/dist/store/dual-scope-db.js +81 -8
- package/dist/store/dual-scope-db.js.map +1 -1
- package/dist/store/exodus/bare-family.d.ts.map +1 -1
- package/dist/store/exodus/bare-family.js +4 -1
- package/dist/store/exodus/bare-family.js.map +1 -1
- package/dist/store/exodus/migrate.d.ts.map +1 -1
- package/dist/store/exodus/migrate.js +2 -0
- package/dist/store/exodus/migrate.js.map +1 -1
- package/dist/store/exodus/on-open.d.ts.map +1 -1
- package/dist/store/exodus/on-open.js +16 -4
- package/dist/store/exodus/on-open.js.map +1 -1
- package/dist/store/exodus/reconcile.d.ts.map +1 -1
- package/dist/store/exodus/reconcile.js +2 -0
- package/dist/store/exodus/reconcile.js.map +1 -1
- package/dist/store/portable-bundle-import.d.ts +17 -0
- package/dist/store/portable-bundle-import.d.ts.map +1 -1
- package/dist/store/portable-bundle-import.js +46 -31
- package/dist/store/portable-bundle-import.js.map +1 -1
- package/dist/store/portable-bundle-scan.d.ts.map +1 -1
- package/dist/store/portable-bundle-scan.js +5 -0
- package/dist/store/portable-bundle-scan.js.map +1 -1
- package/dist/store/row-identity-registry.d.ts +4 -3
- package/dist/store/row-identity-registry.d.ts.map +1 -1
- package/dist/store/row-identity-registry.js +37 -35
- package/dist/store/row-identity-registry.js.map +1 -1
- package/dist/store/row-identity.d.ts.map +1 -1
- package/dist/store/row-identity.js +6 -1
- package/dist/store/row-identity.js.map +1 -1
- package/dist/store/schema/cleo-global/agent-registry.d.ts +16 -0
- package/dist/store/schema/cleo-global/agent-registry.d.ts.map +1 -1
- package/dist/store/schema/cleo-global/agent-registry.js +4 -1
- package/dist/store/schema/cleo-global/agent-registry.js.map +1 -1
- package/dist/store/schema/cleo-project/provenance-orphans.d.ts +126 -1
- package/dist/store/schema/cleo-project/provenance-orphans.d.ts.map +1 -1
- package/dist/store/schema/cleo-project/provenance-orphans.js +41 -1
- package/dist/store/schema/cleo-project/provenance-orphans.js.map +1 -1
- package/dist/store/sqlite-data-accessor.d.ts +40 -0
- package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
- package/dist/store/sqlite-data-accessor.js +122 -0
- package/dist/store/sqlite-data-accessor.js.map +1 -1
- package/dist/store/sync/activity.d.ts +64 -0
- package/dist/store/sync/activity.d.ts.map +1 -0
- package/dist/store/sync/activity.js +220 -0
- package/dist/store/sync/activity.js.map +1 -0
- package/dist/store/sync/apply/applier.d.ts.map +1 -1
- package/dist/store/sync/apply/applier.js +58 -2
- package/dist/store/sync/apply/applier.js.map +1 -1
- package/dist/store/sync/apply/write-api.d.ts.map +1 -1
- package/dist/store/sync/apply/write-api.js +45 -3
- package/dist/store/sync/apply/write-api.js.map +1 -1
- package/dist/store/sync/capture.d.ts +6 -4
- package/dist/store/sync/capture.d.ts.map +1 -1
- package/dist/store/sync/capture.js +16 -4
- package/dist/store/sync/capture.js.map +1 -1
- package/dist/store/sync/collision-settle.d.ts +120 -0
- package/dist/store/sync/collision-settle.d.ts.map +1 -1
- package/dist/store/sync/collision-settle.js +342 -5
- package/dist/store/sync/collision-settle.js.map +1 -1
- package/dist/store/sync/flags.d.ts +34 -0
- package/dist/store/sync/flags.d.ts.map +1 -1
- package/dist/store/sync/flags.js +46 -0
- package/dist/store/sync/flags.js.map +1 -1
- package/dist/store/sync/genesis.d.ts +8 -0
- package/dist/store/sync/genesis.d.ts.map +1 -1
- package/dist/store/sync/genesis.js +18 -5
- package/dist/store/sync/genesis.js.map +1 -1
- package/dist/store/sync/push.d.ts +4 -2
- package/dist/store/sync/push.d.ts.map +1 -1
- package/dist/store/sync/push.js +10 -1
- package/dist/store/sync/push.js.map +1 -1
- package/dist/store/sync/rebind.d.ts +20 -0
- package/dist/store/sync/rebind.d.ts.map +1 -1
- package/dist/store/sync/rebind.js +86 -4
- package/dist/store/sync/rebind.js.map +1 -1
- package/dist/store/sync/reconcile-copy.d.ts +152 -0
- package/dist/store/sync/reconcile-copy.d.ts.map +1 -0
- package/dist/store/sync/reconcile-copy.js +428 -0
- package/dist/store/sync/reconcile-copy.js.map +1 -0
- package/dist/store/sync/reconcile.d.ts +80 -0
- package/dist/store/sync/reconcile.d.ts.map +1 -1
- package/dist/store/sync/reconcile.js +97 -5
- package/dist/store/sync/reconcile.js.map +1 -1
- package/dist/store/sync/repair.d.ts +11 -0
- package/dist/store/sync/repair.d.ts.map +1 -1
- package/dist/store/sync/repair.js +14 -3
- package/dist/store/sync/repair.js.map +1 -1
- package/dist/store/sync/replica.d.ts +74 -1
- package/dist/store/sync/replica.d.ts.map +1 -1
- package/dist/store/sync/replica.js +104 -6
- package/dist/store/sync/replica.js.map +1 -1
- package/dist/store/sync/row-meta.d.ts +4 -2
- package/dist/store/sync/row-meta.d.ts.map +1 -1
- package/dist/store/sync/row-meta.js +6 -4
- package/dist/store/sync/row-meta.js.map +1 -1
- package/dist/store/sync/sealer.d.ts +2 -0
- package/dist/store/sync/sealer.d.ts.map +1 -1
- package/dist/store/sync/sealer.js +33 -4
- package/dist/store/sync/sealer.js.map +1 -1
- package/dist/store/sync/structural.d.ts.map +1 -1
- package/dist/store/sync/structural.js +3 -1
- package/dist/store/sync/structural.js.map +1 -1
- package/dist/store/sync/timestamp-canon.d.ts.map +1 -1
- package/dist/store/sync/timestamp-canon.js +2 -0
- package/dist/store/sync/timestamp-canon.js.map +1 -1
- package/dist/store/table-classification.d.ts +29 -0
- package/dist/store/table-classification.d.ts.map +1 -1
- package/dist/store/table-classification.js +85 -19
- package/dist/store/table-classification.js.map +1 -1
- package/dist/store/twin-collapse.d.ts.map +1 -1
- package/dist/store/twin-collapse.js +28 -10
- package/dist/store/twin-collapse.js.map +1 -1
- package/dist/store/vault-manifest.d.ts +5 -0
- package/dist/store/vault-manifest.d.ts.map +1 -1
- package/dist/store/vault-manifest.js +14 -1
- package/dist/store/vault-manifest.js.map +1 -1
- package/dist/tasks/affected-packages.d.ts +15 -5
- package/dist/tasks/affected-packages.d.ts.map +1 -1
- package/dist/tasks/affected-packages.js +20 -8
- package/dist/tasks/affected-packages.js.map +1 -1
- package/dist/tasks/done-record.d.ts +14 -4
- package/dist/tasks/done-record.d.ts.map +1 -1
- package/dist/tasks/done-record.js +21 -9
- package/dist/tasks/done-record.js.map +1 -1
- package/dist/tasks/evidence.d.ts.map +1 -1
- package/dist/tasks/evidence.js +45 -4
- package/dist/tasks/evidence.js.map +1 -1
- package/dist/tasks/gate-runner.d.ts +5 -4
- package/dist/tasks/gate-runner.d.ts.map +1 -1
- package/dist/tasks/gate-runner.js +18 -11
- package/dist/tasks/gate-runner.js.map +1 -1
- package/dist/tasks/tool-cache.d.ts +27 -1
- package/dist/tasks/tool-cache.d.ts.map +1 -1
- package/dist/tasks/tool-cache.js +110 -6
- package/dist/tasks/tool-cache.js.map +1 -1
- package/dist/tools/fs.d.ts +3 -1
- package/dist/tools/fs.d.ts.map +1 -1
- package/dist/tools/fs.js +35 -2
- package/dist/tools/fs.js.map +1 -1
- package/dist/validation/engine-ops.d.ts +10 -3
- package/dist/validation/engine-ops.d.ts.map +1 -1
- package/dist/validation/engine-ops.js +17 -8
- package/dist/validation/engine-ops.js.map +1 -1
- package/migrations/drizzle-cleo-global/20261010180000_t12915-agent-registry-uids/migration.sql +18 -0
- package/migrations/drizzle-cleo-project/20261010170000_t12896b-brain-task-observations/migration.sql +37 -0
- package/migrations/sync-journal/20261009150000_t13335-capture-pin/migration.sql +13 -0
- package/package.json +18 -13
- package/schemas/config.schema.json +12 -0
- package/schemas/project-context.schema.json +5 -0
- package/templates/CLEO-INJECTION.md +2 -2
- package/templates/CLEO-REFERENCE.md +6 -4
- package/templates/git-hooks/pre-push +29 -1
- package/templates/workflows/release-prepare.yml.tmpl +1 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detached worker for the command piggyback sync (T13553), spawned by
|
|
3
|
+
* `startCommandAutoSync` (`cloud/auto-sync-command.ts`). Runs
|
|
4
|
+
* {@link runCommandAutoSync}: the `cloud.autoSync` opt-out, then a
|
|
5
|
+
* throttled, single-flight, bounded `autoCloudSync`. No stdout: this process
|
|
6
|
+
* has no reader.
|
|
7
|
+
*
|
|
8
|
+
* argv: `<projectRoot>`
|
|
9
|
+
*
|
|
10
|
+
* @task T13553
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=auto-sync-command-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-sync-command-entry.d.ts","sourceRoot":"","sources":["../../src/cloud/auto-sync-command-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detached worker for the command piggyback sync (T13553), spawned by
|
|
3
|
+
* `startCommandAutoSync` (`cloud/auto-sync-command.ts`). Runs
|
|
4
|
+
* {@link runCommandAutoSync}: the `cloud.autoSync` opt-out, then a
|
|
5
|
+
* throttled, single-flight, bounded `autoCloudSync`. No stdout: this process
|
|
6
|
+
* has no reader.
|
|
7
|
+
*
|
|
8
|
+
* argv: `<projectRoot>`
|
|
9
|
+
*
|
|
10
|
+
* @task T13553
|
|
11
|
+
*/
|
|
12
|
+
import { runCommandAutoSync } from './auto-sync-command.js';
|
|
13
|
+
const projectRoot = process.argv[2];
|
|
14
|
+
if (!projectRoot)
|
|
15
|
+
process.exit(2);
|
|
16
|
+
await runCommandAutoSync(projectRoot);
|
|
17
|
+
process.exit(0);
|
|
18
|
+
//# sourceMappingURL=auto-sync-command-entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-sync-command-entry.js","sourceRoot":"","sources":["../../src/cloud/auto-sync-command-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpC,IAAI,CAAC,WAAW;IAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClC,MAAM,kBAAkB,CAAC,WAAW,CAAC,CAAC;AACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Piggyback sync on normal CLI commands (T13553): a command in a linked
|
|
3
|
+
* project starts a detached `autoCloudSync(projectRoot, 'command')` child at
|
|
4
|
+
* most once per {@link autoSyncIntervalMs}, the way the presence refresh
|
|
5
|
+
* piggybacks (T13289). No daemon, timer or server; the foreground command
|
|
6
|
+
* never waits for the child.
|
|
7
|
+
*
|
|
8
|
+
* The check on the command's path is one `stat` of a stamp under the CLEO
|
|
9
|
+
* home. The stamp is written before the spawn, so a failing child is retried
|
|
10
|
+
* a window later, not on every command. Everything else (the config opt-out
|
|
11
|
+
* `cloud.autoSync`, flags, login, the network) runs in the child, where
|
|
12
|
+
* `autoCloudSync` adds its own throttle and the cross-process lock that keeps
|
|
13
|
+
* this, session end and the sentient tick from syncing twice.
|
|
14
|
+
*
|
|
15
|
+
* Never spawned for heavy or evidence runs (`CLEO_RUN_CLASS` is set in every
|
|
16
|
+
* governed child), for `cleo run` / `cleo verify` / `cleo cloud`, or when
|
|
17
|
+
* `CLEO_DISABLE_AUTO_SYNC=1` or `CLEO_AUTO_SYNC_INTERVAL_MIN=0`.
|
|
18
|
+
*
|
|
19
|
+
* @task T13553
|
|
20
|
+
*/
|
|
21
|
+
import { type AutoSyncOutcome } from './auto-sync.js';
|
|
22
|
+
/** Environment switch that turns the command piggyback off (`1`). */
|
|
23
|
+
export declare const AUTO_SYNC_DISABLE_ENV = "CLEO_DISABLE_AUTO_SYNC";
|
|
24
|
+
/** How {@link startCommandAutoSync} ended. */
|
|
25
|
+
export type CommandAutoSyncOutcome = 'disabled' | 'skipped' | 'throttled' | 'spawned' | 'failed';
|
|
26
|
+
/** Options for {@link startCommandAutoSync}. */
|
|
27
|
+
export interface CommandAutoSyncOptions {
|
|
28
|
+
/** The linked project root. */
|
|
29
|
+
projectRoot: string;
|
|
30
|
+
/** The command's root verb (`show`, `add`, …), if any. */
|
|
31
|
+
verb?: string;
|
|
32
|
+
/** Environment. @defaultValue process.env */
|
|
33
|
+
env?: NodeJS.ProcessEnv;
|
|
34
|
+
/** CLEO home holding the stamp. @defaultValue getCleoHome() */
|
|
35
|
+
cleoHome?: string;
|
|
36
|
+
/** Clock. */
|
|
37
|
+
now?: () => Date;
|
|
38
|
+
/** Starts the detached child; defaults to spawning the worker entry. */
|
|
39
|
+
spawnWorker?: (projectRoot: string) => void;
|
|
40
|
+
/** The unreleased flags; test seam. @defaultValue UNRELEASED_FLAGS */
|
|
41
|
+
unreleasedFlags?: ReadonlySet<string>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Start a background sync for this linked project if the window has elapsed.
|
|
45
|
+
* Never throws and never waits for the sync.
|
|
46
|
+
*
|
|
47
|
+
* @param opts - Project root, verb and test seams.
|
|
48
|
+
* @returns What happened on the command's path.
|
|
49
|
+
*/
|
|
50
|
+
export declare function startCommandAutoSync(opts: CommandAutoSyncOptions): CommandAutoSyncOutcome;
|
|
51
|
+
/**
|
|
52
|
+
* The detached child's body: honour the config opt-out `cloud.autoSync:
|
|
53
|
+
* false` (project, then global), then {@link autoCloudSync} with reason
|
|
54
|
+
* `command`. Never throws.
|
|
55
|
+
*
|
|
56
|
+
* @param projectRoot - The linked project root.
|
|
57
|
+
* @param seams - Test seams.
|
|
58
|
+
* @returns The sync outcome, or `disabled` when the config turns it off.
|
|
59
|
+
*/
|
|
60
|
+
export declare function runCommandAutoSync(projectRoot: string, seams?: {
|
|
61
|
+
readConfig?: (projectRoot: string) => Promise<boolean | undefined>;
|
|
62
|
+
sync?: (projectRoot: string) => Promise<AutoSyncOutcome>;
|
|
63
|
+
}): Promise<AutoSyncOutcome>;
|
|
64
|
+
//# sourceMappingURL=auto-sync-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-sync-command.d.ts","sourceRoot":"","sources":["../../src/cloud/auto-sync-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAOH,OAAO,EACL,KAAK,eAAe,EAIrB,MAAM,gBAAgB,CAAC;AAExB,qEAAqE;AACrE,eAAO,MAAM,qBAAqB,2BAA2B,CAAC;AAO9D,8CAA8C;AAC9C,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEjG,gDAAgD;AAChD,MAAM,WAAW,sBAAsB;IACrC,+BAA+B;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa;IACb,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,wEAAwE;IACxE,WAAW,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,sEAAsE;IACtE,eAAe,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACvC;AAeD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,sBAAsB,GAAG,sBAAsB,CAyBzF;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,KAAK,GAAE;IACL,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;IACnE,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;CACrD,GACL,OAAO,CAAC,eAAe,CAAC,CAa1B"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Piggyback sync on normal CLI commands (T13553): a command in a linked
|
|
3
|
+
* project starts a detached `autoCloudSync(projectRoot, 'command')` child at
|
|
4
|
+
* most once per {@link autoSyncIntervalMs}, the way the presence refresh
|
|
5
|
+
* piggybacks (T13289). No daemon, timer or server; the foreground command
|
|
6
|
+
* never waits for the child.
|
|
7
|
+
*
|
|
8
|
+
* The check on the command's path is one `stat` of a stamp under the CLEO
|
|
9
|
+
* home. The stamp is written before the spawn, so a failing child is retried
|
|
10
|
+
* a window later, not on every command. Everything else (the config opt-out
|
|
11
|
+
* `cloud.autoSync`, flags, login, the network) runs in the child, where
|
|
12
|
+
* `autoCloudSync` adds its own throttle and the cross-process lock that keeps
|
|
13
|
+
* this, session end and the sentient tick from syncing twice.
|
|
14
|
+
*
|
|
15
|
+
* Never spawned for heavy or evidence runs (`CLEO_RUN_CLASS` is set in every
|
|
16
|
+
* governed child), for `cleo run` / `cleo verify` / `cleo cloud`, or when
|
|
17
|
+
* `CLEO_DISABLE_AUTO_SYNC=1` or `CLEO_AUTO_SYNC_INTERVAL_MIN=0`.
|
|
18
|
+
*
|
|
19
|
+
* @task T13553
|
|
20
|
+
*/
|
|
21
|
+
import { spawn } from 'node:child_process';
|
|
22
|
+
import { mkdirSync, statSync, utimesSync, writeFileSync } from 'node:fs';
|
|
23
|
+
import { createRequire } from 'node:module';
|
|
24
|
+
import { join } from 'node:path';
|
|
25
|
+
import { getCleoHome } from '../paths.js';
|
|
26
|
+
import { autoCloudSync, autoSyncIntervalMs, autoSyncReleased, } from './auto-sync.js';
|
|
27
|
+
/** Environment switch that turns the command piggyback off (`1`). */
|
|
28
|
+
export const AUTO_SYNC_DISABLE_ENV = 'CLEO_DISABLE_AUTO_SYNC';
|
|
29
|
+
/** Root verbs that never piggyback: heavy/evidence runs and explicit cloud commands. */
|
|
30
|
+
const SKIP_VERBS = new Set(['run', 'verify', 'cloud']);
|
|
31
|
+
const WORKER_SPECIFIER = '@cleocode/core/cloud/auto-sync-command-entry.js';
|
|
32
|
+
function spawnDetachedWorker(projectRoot) {
|
|
33
|
+
const entry = createRequire(import.meta.url).resolve(WORKER_SPECIFIER);
|
|
34
|
+
const child = spawn(process.execPath, [entry, projectRoot], {
|
|
35
|
+
detached: true,
|
|
36
|
+
stdio: 'ignore',
|
|
37
|
+
cwd: projectRoot,
|
|
38
|
+
env: process.env,
|
|
39
|
+
});
|
|
40
|
+
// A spawn failure is emitted asynchronously; never let it escape the command.
|
|
41
|
+
child.on('error', () => { });
|
|
42
|
+
child.unref();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Start a background sync for this linked project if the window has elapsed.
|
|
46
|
+
* Never throws and never waits for the sync.
|
|
47
|
+
*
|
|
48
|
+
* @param opts - Project root, verb and test seams.
|
|
49
|
+
* @returns What happened on the command's path.
|
|
50
|
+
*/
|
|
51
|
+
export function startCommandAutoSync(opts) {
|
|
52
|
+
try {
|
|
53
|
+
const env = opts.env ?? process.env;
|
|
54
|
+
if (env[AUTO_SYNC_DISABLE_ENV] === '1')
|
|
55
|
+
return 'disabled';
|
|
56
|
+
// Inert until T13549 releases sync.push/sync.pull: no stamp, no spawn.
|
|
57
|
+
if (!autoSyncReleased(opts.unreleasedFlags))
|
|
58
|
+
return 'disabled';
|
|
59
|
+
if (env['CLEO_RUN_CLASS'] !== undefined)
|
|
60
|
+
return 'skipped';
|
|
61
|
+
if (opts.verb !== undefined && SKIP_VERBS.has(opts.verb))
|
|
62
|
+
return 'skipped';
|
|
63
|
+
const gap = autoSyncIntervalMs();
|
|
64
|
+
if (gap === null)
|
|
65
|
+
return 'disabled';
|
|
66
|
+
const now = (opts.now ?? (() => new Date()))();
|
|
67
|
+
const stamp = join(opts.cleoHome ?? getCleoHome(), 'auto-sync-command.stamp');
|
|
68
|
+
try {
|
|
69
|
+
if (now.getTime() - statSync(stamp).mtimeMs < gap)
|
|
70
|
+
return 'throttled';
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// No stamp yet: due.
|
|
74
|
+
}
|
|
75
|
+
mkdirSync(join(stamp, '..'), { recursive: true });
|
|
76
|
+
writeFileSync(stamp, now.toISOString());
|
|
77
|
+
utimesSync(stamp, now, now);
|
|
78
|
+
(opts.spawnWorker ?? spawnDetachedWorker)(opts.projectRoot);
|
|
79
|
+
return 'spawned';
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return 'failed';
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The detached child's body: honour the config opt-out `cloud.autoSync:
|
|
87
|
+
* false` (project, then global), then {@link autoCloudSync} with reason
|
|
88
|
+
* `command`. Never throws.
|
|
89
|
+
*
|
|
90
|
+
* @param projectRoot - The linked project root.
|
|
91
|
+
* @param seams - Test seams.
|
|
92
|
+
* @returns The sync outcome, or `disabled` when the config turns it off.
|
|
93
|
+
*/
|
|
94
|
+
export async function runCommandAutoSync(projectRoot, seams = {}) {
|
|
95
|
+
try {
|
|
96
|
+
const readConfig = seams.readConfig ??
|
|
97
|
+
(async (root) => {
|
|
98
|
+
const { getConfigValue } = await import('../config/registry.js');
|
|
99
|
+
return getConfigValue('cloud.autoSync', { projectRoot: root });
|
|
100
|
+
});
|
|
101
|
+
if ((await readConfig(projectRoot)) === false)
|
|
102
|
+
return 'disabled';
|
|
103
|
+
return await (seams.sync ?? ((root) => autoCloudSync(root, 'command')))(projectRoot);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return 'failed';
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=auto-sync-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-sync-command.js","sourceRoot":"","sources":["../../src/cloud/auto-sync-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Automatic main-brain sync (T13468): `cleo cloud sync` without the user
|
|
3
|
+
* typing it. Runs from hooks CLEO already has, never a daemon or server of
|
|
4
|
+
* its own:
|
|
5
|
+
*
|
|
6
|
+
* - session end: the detached session-end worker
|
|
7
|
+
* (`sessions/session-end-snapshot.ts`), after its snapshot;
|
|
8
|
+
* - the sentient tick (`sentient/tick.ts`), at most once per
|
|
9
|
+
* {@link autoSyncIntervalMs};
|
|
10
|
+
* - a normal CLI command in a linked project (T13553,
|
|
11
|
+
* `cloud/auto-sync-command.ts`): a detached child, same interval.
|
|
12
|
+
*
|
|
13
|
+
* Best-effort and bounded: a store with no sync flag on, a signed-out
|
|
14
|
+
* device or an unlinked project is a quiet skip; any other failure
|
|
15
|
+
* (offline, refused) is recorded in `<CLEO_HOME>/auto-sync.json`, which
|
|
16
|
+
* `cleo cloud status` reports as one {@link W_AUTO_SYNC_FAILED} warning.
|
|
17
|
+
* Single-flight across processes under a lock, admitted by the governor as
|
|
18
|
+
* `db-heavy` (skipped, not queued, under pressure). Never throws.
|
|
19
|
+
*
|
|
20
|
+
* @task T13468
|
|
21
|
+
*/
|
|
22
|
+
import type { CloudWarning } from '@cleocode/contracts';
|
|
23
|
+
/** Default minimum gap between tick-driven syncs. */
|
|
24
|
+
export declare const AUTO_SYNC_INTERVAL_MS: number;
|
|
25
|
+
/** Minimum gap between session-end syncs: coalesces a burst of session ends. */
|
|
26
|
+
export declare const AUTO_SYNC_SESSION_END_MIN_MS = 60000;
|
|
27
|
+
/** Upper bound on one automatic sync. */
|
|
28
|
+
export declare const AUTO_SYNC_TIMEOUT_MS = 120000;
|
|
29
|
+
/** Warning code `cleo cloud status` shows for a failed automatic sync. */
|
|
30
|
+
export declare const W_AUTO_SYNC_FAILED = "W_AUTO_SYNC_FAILED";
|
|
31
|
+
/** What triggered an automatic sync. */
|
|
32
|
+
export type AutoSyncReason = 'session-end' | 'tick' | 'command';
|
|
33
|
+
/** Persisted state of automatic sync. */
|
|
34
|
+
export interface AutoSyncState {
|
|
35
|
+
/** When the last attempt started (ISO), else absent. */
|
|
36
|
+
lastAttemptAt?: string;
|
|
37
|
+
/** When the last attempt succeeded (ISO), else absent. */
|
|
38
|
+
lastOkAt?: string;
|
|
39
|
+
/** The last failure, cleared by a success. */
|
|
40
|
+
lastError?: {
|
|
41
|
+
at: string;
|
|
42
|
+
code: string;
|
|
43
|
+
message: string;
|
|
44
|
+
} | null;
|
|
45
|
+
}
|
|
46
|
+
/** Outcome of {@link autoCloudSync}. */
|
|
47
|
+
export type AutoSyncOutcome = 'synced' | 'throttled' | 'disabled' | 'skipped' | 'busy' | 'deferred' | 'failed';
|
|
48
|
+
/** Test seams for {@link autoCloudSync}. */
|
|
49
|
+
export interface AutoSyncOptions {
|
|
50
|
+
/** Clock. */
|
|
51
|
+
now?: Date;
|
|
52
|
+
/** CLEO home holding the global store and the state file. */
|
|
53
|
+
cleoHome?: string;
|
|
54
|
+
/** Runs the sync; defaults to `cloudSync`. */
|
|
55
|
+
sync?: (projectRoot: string) => Promise<unknown>;
|
|
56
|
+
/** Whether a store has a journal push/pull flag on; defaults to a read-only check. */
|
|
57
|
+
syncEnabled?: (dbPath: string) => Promise<boolean>;
|
|
58
|
+
/** Governor admission; `null` = deferred. */
|
|
59
|
+
admit?: () => Promise<{
|
|
60
|
+
release: () => Promise<void>;
|
|
61
|
+
} | null>;
|
|
62
|
+
/** Single-flight lock; throws when held. `onCompromised` fires if the lock is lost while held. */
|
|
63
|
+
lock?: (onCompromised: (err: Error) => void) => Promise<{
|
|
64
|
+
release: () => Promise<void>;
|
|
65
|
+
abandon?: () => Promise<void>;
|
|
66
|
+
}>;
|
|
67
|
+
/** The unreleased flags; test seam. @defaultValue UNRELEASED_FLAGS */
|
|
68
|
+
unreleasedFlags?: ReadonlySet<string>;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Whether automatic sync may run: never while both `sync.push` and
|
|
72
|
+
* `sync.pull` are unreleased (T13553; T13549 releases them).
|
|
73
|
+
*
|
|
74
|
+
* @param unreleased - The unreleased set. @defaultValue UNRELEASED_FLAGS
|
|
75
|
+
* @returns True once either flag ships.
|
|
76
|
+
*/
|
|
77
|
+
export declare function autoSyncReleased(unreleased?: ReadonlySet<string>): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* The tick interval: `CLEO_AUTO_SYNC_INTERVAL_MIN` minutes, else
|
|
80
|
+
* {@link AUTO_SYNC_INTERVAL_MS}. `0` turns the tick-driven sync off.
|
|
81
|
+
*
|
|
82
|
+
* @returns Milliseconds, or `null` when the tick sync is off.
|
|
83
|
+
*/
|
|
84
|
+
export declare function autoSyncIntervalMs(): number | null;
|
|
85
|
+
/**
|
|
86
|
+
* Read the automatic sync state. Missing or malformed means empty.
|
|
87
|
+
*
|
|
88
|
+
* @param cleoHome - CLEO home. @defaultValue getCleoHome()
|
|
89
|
+
* @returns The state.
|
|
90
|
+
*/
|
|
91
|
+
export declare function readAutoSyncState(cleoHome?: string): AutoSyncState;
|
|
92
|
+
/**
|
|
93
|
+
* The `cleo cloud status` warning for a failed automatic sync: present while
|
|
94
|
+
* the last failure is newer than the last success.
|
|
95
|
+
*
|
|
96
|
+
* @param cleoHome - CLEO home. @defaultValue getCleoHome()
|
|
97
|
+
* @returns The warning, or `null`.
|
|
98
|
+
*/
|
|
99
|
+
export declare function autoSyncWarning(cleoHome?: string): CloudWarning | null;
|
|
100
|
+
/**
|
|
101
|
+
* Run one automatic `cloud sync` of the project and global stores, if due.
|
|
102
|
+
* Never throws.
|
|
103
|
+
*
|
|
104
|
+
* @param projectRoot - The project whose session ended or whose tick ran.
|
|
105
|
+
* @param reason - What triggered it; a tick or command honours {@link autoSyncIntervalMs}.
|
|
106
|
+
* @param opts - Test seams.
|
|
107
|
+
* @returns What happened.
|
|
108
|
+
* @task T13468
|
|
109
|
+
*/
|
|
110
|
+
export declare function autoCloudSync(projectRoot: string, reason: AutoSyncReason, opts?: AutoSyncOptions): Promise<AutoSyncOutcome>;
|
|
111
|
+
//# sourceMappingURL=auto-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-sync.d.ts","sourceRoot":"","sources":["../../src/cloud/auto-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAKxD,qDAAqD;AACrD,eAAO,MAAM,qBAAqB,QAAc,CAAC;AAEjD,gFAAgF;AAChF,eAAO,MAAM,4BAA4B,QAAS,CAAC;AAEnD,yCAAyC;AACzC,eAAO,MAAM,oBAAoB,SAAU,CAAC;AAE5C,0EAA0E;AAC1E,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AAUvD,wCAAwC;AACxC,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;AAEhE,yCAAyC;AACzC,MAAM,WAAW,aAAa;IAC5B,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,SAAS,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAClE;AAED,wCAAwC;AACxC,MAAM,MAAM,eAAe,GACvB,QAAQ,GACR,WAAW,GACX,UAAU,GACV,SAAS,GACT,MAAM,GACN,UAAU,GACV,QAAQ,CAAC;AAEb,4CAA4C;AAC5C,MAAM,WAAW,eAAe;IAC9B,aAAa;IACb,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,sFAAsF;IACtF,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnD,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAC/D,kGAAkG;IAClG,IAAI,CAAC,EAAE,CACL,aAAa,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,KAChC,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC,CAAC;IAC9E,sEAAsE;IACtE,eAAe,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACvC;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,GAAE,WAAW,CAAC,MAAM,CAAoB,GAAG,OAAO,CAE5F;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,IAAI,CAMlD;AAOD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,GAAE,MAAsB,GAAG,aAAa,CAMjF;AAcD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,QAAQ,GAAE,MAAsB,GAAG,YAAY,GAAG,IAAI,CAOrF;AAsCD;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,eAAe,CAAC,CAgH1B"}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Automatic main-brain sync (T13468): `cleo cloud sync` without the user
|
|
3
|
+
* typing it. Runs from hooks CLEO already has, never a daemon or server of
|
|
4
|
+
* its own:
|
|
5
|
+
*
|
|
6
|
+
* - session end: the detached session-end worker
|
|
7
|
+
* (`sessions/session-end-snapshot.ts`), after its snapshot;
|
|
8
|
+
* - the sentient tick (`sentient/tick.ts`), at most once per
|
|
9
|
+
* {@link autoSyncIntervalMs};
|
|
10
|
+
* - a normal CLI command in a linked project (T13553,
|
|
11
|
+
* `cloud/auto-sync-command.ts`): a detached child, same interval.
|
|
12
|
+
*
|
|
13
|
+
* Best-effort and bounded: a store with no sync flag on, a signed-out
|
|
14
|
+
* device or an unlinked project is a quiet skip; any other failure
|
|
15
|
+
* (offline, refused) is recorded in `<CLEO_HOME>/auto-sync.json`, which
|
|
16
|
+
* `cleo cloud status` reports as one {@link W_AUTO_SYNC_FAILED} warning.
|
|
17
|
+
* Single-flight across processes under a lock, admitted by the governor as
|
|
18
|
+
* `db-heavy` (skipped, not queued, under pressure). Never throws.
|
|
19
|
+
*
|
|
20
|
+
* @task T13468
|
|
21
|
+
*/
|
|
22
|
+
import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
23
|
+
import { join } from 'node:path';
|
|
24
|
+
import { getLogger } from '../logger.js';
|
|
25
|
+
import { getCleoHome, resolveCleoDir } from '../paths.js';
|
|
26
|
+
import { UNRELEASED_FLAGS } from '../store/sync/flags.js';
|
|
27
|
+
/** Default minimum gap between tick-driven syncs. */
|
|
28
|
+
export const AUTO_SYNC_INTERVAL_MS = 15 * 60_000;
|
|
29
|
+
/** Minimum gap between session-end syncs: coalesces a burst of session ends. */
|
|
30
|
+
export const AUTO_SYNC_SESSION_END_MIN_MS = 60_000;
|
|
31
|
+
/** Upper bound on one automatic sync. */
|
|
32
|
+
export const AUTO_SYNC_TIMEOUT_MS = 120_000;
|
|
33
|
+
/** Warning code `cleo cloud status` shows for a failed automatic sync. */
|
|
34
|
+
export const W_AUTO_SYNC_FAILED = 'W_AUTO_SYNC_FAILED';
|
|
35
|
+
/** Error codes that mean "nothing to sync here", not a failure. */
|
|
36
|
+
const QUIET_SKIP_CODES = new Set([
|
|
37
|
+
'E_SYNC_DISABLED',
|
|
38
|
+
'E_NEXUS_NOT_SIGNED_IN',
|
|
39
|
+
'E_NEXUS_VAULT_NOT_LINKED',
|
|
40
|
+
'E_NEXUS_DEVICE_REQUIRED',
|
|
41
|
+
]);
|
|
42
|
+
/**
|
|
43
|
+
* Whether automatic sync may run: never while both `sync.push` and
|
|
44
|
+
* `sync.pull` are unreleased (T13553; T13549 releases them).
|
|
45
|
+
*
|
|
46
|
+
* @param unreleased - The unreleased set. @defaultValue UNRELEASED_FLAGS
|
|
47
|
+
* @returns True once either flag ships.
|
|
48
|
+
*/
|
|
49
|
+
export function autoSyncReleased(unreleased = UNRELEASED_FLAGS) {
|
|
50
|
+
return !(unreleased.has('sync.push') && unreleased.has('sync.pull'));
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The tick interval: `CLEO_AUTO_SYNC_INTERVAL_MIN` minutes, else
|
|
54
|
+
* {@link AUTO_SYNC_INTERVAL_MS}. `0` turns the tick-driven sync off.
|
|
55
|
+
*
|
|
56
|
+
* @returns Milliseconds, or `null` when the tick sync is off.
|
|
57
|
+
*/
|
|
58
|
+
export function autoSyncIntervalMs() {
|
|
59
|
+
const raw = process.env['CLEO_AUTO_SYNC_INTERVAL_MIN'];
|
|
60
|
+
if (raw === undefined || raw.trim() === '')
|
|
61
|
+
return AUTO_SYNC_INTERVAL_MS;
|
|
62
|
+
const min = Number(raw);
|
|
63
|
+
if (!Number.isFinite(min) || min < 0)
|
|
64
|
+
return AUTO_SYNC_INTERVAL_MS;
|
|
65
|
+
return min === 0 ? null : min * 60_000;
|
|
66
|
+
}
|
|
67
|
+
/** Path of the state file. */
|
|
68
|
+
function statePath(cleoHome) {
|
|
69
|
+
return join(cleoHome, 'auto-sync.json');
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Read the automatic sync state. Missing or malformed means empty.
|
|
73
|
+
*
|
|
74
|
+
* @param cleoHome - CLEO home. @defaultValue getCleoHome()
|
|
75
|
+
* @returns The state.
|
|
76
|
+
*/
|
|
77
|
+
export function readAutoSyncState(cleoHome = getCleoHome()) {
|
|
78
|
+
try {
|
|
79
|
+
return JSON.parse(readFileSync(statePath(cleoHome), 'utf-8'));
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return {};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function writeState(cleoHome, state) {
|
|
86
|
+
try {
|
|
87
|
+
mkdirSync(cleoHome, { recursive: true });
|
|
88
|
+
// tmp then rename, so a concurrent reader never sees a torn record.
|
|
89
|
+
const tmp = `${statePath(cleoHome)}.${process.pid}.tmp`;
|
|
90
|
+
writeFileSync(tmp, `${JSON.stringify(state)}\n`);
|
|
91
|
+
renameSync(tmp, statePath(cleoHome));
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Best-effort: a lost record only loses the throttle and the warning.
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The `cleo cloud status` warning for a failed automatic sync: present while
|
|
99
|
+
* the last failure is newer than the last success.
|
|
100
|
+
*
|
|
101
|
+
* @param cleoHome - CLEO home. @defaultValue getCleoHome()
|
|
102
|
+
* @returns The warning, or `null`.
|
|
103
|
+
*/
|
|
104
|
+
export function autoSyncWarning(cleoHome = getCleoHome()) {
|
|
105
|
+
const s = readAutoSyncState(cleoHome);
|
|
106
|
+
if (!s.lastError)
|
|
107
|
+
return null;
|
|
108
|
+
return {
|
|
109
|
+
code: W_AUTO_SYNC_FAILED,
|
|
110
|
+
message: `automatic sync failed at ${s.lastError.at} (${s.lastError.code}): ${s.lastError.message}; run \`cleo cloud sync\` to retry`,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/** Whether a store has `sync.push` or `sync.pull` on, read-only. Absent or unreadable is off. */
|
|
114
|
+
async function storeSyncEnabled(dbPath) {
|
|
115
|
+
const { existsSync } = await import('node:fs');
|
|
116
|
+
if (!existsSync(dbPath))
|
|
117
|
+
return false;
|
|
118
|
+
const [{ openCleoDbSnapshot }, { readSyncFlags }] = await Promise.all([
|
|
119
|
+
import('../store/open-cleo-db.js'),
|
|
120
|
+
import('../store/sync/flags.js'),
|
|
121
|
+
]);
|
|
122
|
+
let snap;
|
|
123
|
+
try {
|
|
124
|
+
snap = openCleoDbSnapshot(dbPath, { readOnly: true, applyPragmas: false });
|
|
125
|
+
const f = readSyncFlags(snap.db);
|
|
126
|
+
return f['sync.push'] || f['sync.pull'];
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
snap?.close();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async function defaultAdmit() {
|
|
136
|
+
try {
|
|
137
|
+
const { governor } = await import('../resources/governor.js');
|
|
138
|
+
const admit = await governor.acquire('db-heavy', { blocking: false });
|
|
139
|
+
return admit.deferred ? null : { release: admit.release };
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return { release: async () => { } };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function errorCode(err) {
|
|
146
|
+
return err instanceof Error && 'code' in err && typeof err.code === 'string'
|
|
147
|
+
? err.code
|
|
148
|
+
: 'E_AUTO_SYNC';
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Run one automatic `cloud sync` of the project and global stores, if due.
|
|
152
|
+
* Never throws.
|
|
153
|
+
*
|
|
154
|
+
* @param projectRoot - The project whose session ended or whose tick ran.
|
|
155
|
+
* @param reason - What triggered it; a tick or command honours {@link autoSyncIntervalMs}.
|
|
156
|
+
* @param opts - Test seams.
|
|
157
|
+
* @returns What happened.
|
|
158
|
+
* @task T13468
|
|
159
|
+
*/
|
|
160
|
+
export async function autoCloudSync(projectRoot, reason, opts = {}) {
|
|
161
|
+
const log = getLogger('auto-sync');
|
|
162
|
+
const cleoHome = opts.cleoHome ?? getCleoHome();
|
|
163
|
+
const now = opts.now ?? new Date();
|
|
164
|
+
try {
|
|
165
|
+
// Inert until T13549 releases sync.push/sync.pull: no state read, no network.
|
|
166
|
+
if (!autoSyncReleased(opts.unreleasedFlags))
|
|
167
|
+
return 'disabled';
|
|
168
|
+
const gap = reason === 'session-end' ? AUTO_SYNC_SESSION_END_MIN_MS : autoSyncIntervalMs();
|
|
169
|
+
if (gap === null)
|
|
170
|
+
return 'disabled';
|
|
171
|
+
const due = () => {
|
|
172
|
+
const last = readAutoSyncState(cleoHome).lastAttemptAt;
|
|
173
|
+
return last === undefined || now.getTime() - Date.parse(last) >= gap;
|
|
174
|
+
};
|
|
175
|
+
if (!due())
|
|
176
|
+
return 'throttled';
|
|
177
|
+
const enabled = opts.syncEnabled ?? storeSyncEnabled;
|
|
178
|
+
const any = (await enabled(join(resolveCleoDir(projectRoot), 'cleo.db'))) ||
|
|
179
|
+
(await enabled(join(cleoHome, 'cleo.db')));
|
|
180
|
+
if (!any)
|
|
181
|
+
return 'skipped';
|
|
182
|
+
let held;
|
|
183
|
+
// A long synchronous SQLite step can starve the lock refresh past `stale`;
|
|
184
|
+
// proper-lockfile's default onCompromised throws asynchronously and would crash the daemon.
|
|
185
|
+
let compromised = false;
|
|
186
|
+
const onCompromised = (err) => {
|
|
187
|
+
compromised = true;
|
|
188
|
+
log.warn({ err, reason }, 'automatic cloud sync lock compromised');
|
|
189
|
+
};
|
|
190
|
+
try {
|
|
191
|
+
held = await (opts.lock ??
|
|
192
|
+
(async (onLost) => {
|
|
193
|
+
const { acquireAbandonableLock } = await import('../store/lock.js');
|
|
194
|
+
mkdirSync(cleoHome, { recursive: true });
|
|
195
|
+
// The lock needs its target to exist; appending nothing creates it.
|
|
196
|
+
writeFileSync(statePath(cleoHome), '', { flag: 'a' });
|
|
197
|
+
return acquireAbandonableLock(statePath(cleoHome), {
|
|
198
|
+
retries: 0,
|
|
199
|
+
stale: AUTO_SYNC_TIMEOUT_MS * 3,
|
|
200
|
+
onCompromised: onLost,
|
|
201
|
+
});
|
|
202
|
+
}))(onCompromised);
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
return 'busy';
|
|
206
|
+
}
|
|
207
|
+
try {
|
|
208
|
+
if (!due())
|
|
209
|
+
return 'throttled';
|
|
210
|
+
const admission = await (opts.admit ?? defaultAdmit)();
|
|
211
|
+
if (admission === null)
|
|
212
|
+
return 'deferred';
|
|
213
|
+
const state = readAutoSyncState(cleoHome);
|
|
214
|
+
writeState(cleoHome, { ...state, lastAttemptAt: now.toISOString() });
|
|
215
|
+
// The sync itself, kept so the lock and admission outlive a timeout (T13500).
|
|
216
|
+
let inFlight;
|
|
217
|
+
try {
|
|
218
|
+
const sync = opts.sync ??
|
|
219
|
+
(async (root) => {
|
|
220
|
+
const { cloudSync } = await import('./nexus-vault.js');
|
|
221
|
+
return cloudSync({ projectRoot: root });
|
|
222
|
+
});
|
|
223
|
+
let timer;
|
|
224
|
+
inFlight = sync(projectRoot);
|
|
225
|
+
await Promise.race([
|
|
226
|
+
inFlight,
|
|
227
|
+
new Promise((_, reject) => {
|
|
228
|
+
timer = setTimeout(() => reject(Object.assign(new Error(`timed out after ${AUTO_SYNC_TIMEOUT_MS} ms`), {
|
|
229
|
+
code: 'E_AUTO_SYNC_TIMEOUT',
|
|
230
|
+
})), AUTO_SYNC_TIMEOUT_MS);
|
|
231
|
+
timer.unref?.();
|
|
232
|
+
}),
|
|
233
|
+
]).finally(() => clearTimeout(timer));
|
|
234
|
+
writeState(cleoHome, {
|
|
235
|
+
...state,
|
|
236
|
+
lastAttemptAt: now.toISOString(),
|
|
237
|
+
lastOkAt: new Date().toISOString(),
|
|
238
|
+
lastError: null,
|
|
239
|
+
});
|
|
240
|
+
return 'synced';
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
const code = errorCode(err);
|
|
244
|
+
if (QUIET_SKIP_CODES.has(code))
|
|
245
|
+
return 'skipped';
|
|
246
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
247
|
+
writeState(cleoHome, {
|
|
248
|
+
...state,
|
|
249
|
+
lastAttemptAt: now.toISOString(),
|
|
250
|
+
lastError: { at: new Date().toISOString(), code, message },
|
|
251
|
+
});
|
|
252
|
+
log.warn({ reason, code, message }, 'automatic cloud sync failed');
|
|
253
|
+
return 'failed';
|
|
254
|
+
}
|
|
255
|
+
finally {
|
|
256
|
+
// A timed-out sync keeps running: hold the lock and admission until it
|
|
257
|
+
// settles, so no second sync overlaps it and a worker never exits mid-sync.
|
|
258
|
+
await inFlight?.catch(() => undefined);
|
|
259
|
+
await admission.release();
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
finally {
|
|
263
|
+
// A compromised lock may now belong to another process: never remove its directory.
|
|
264
|
+
if (compromised && held.abandon)
|
|
265
|
+
await held.abandon();
|
|
266
|
+
else
|
|
267
|
+
await held.release().catch(() => undefined);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
catch (err) {
|
|
271
|
+
log.warn({ err, reason }, 'automatic cloud sync skipped');
|
|
272
|
+
return 'failed';
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=auto-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-sync.js","sourceRoot":"","sources":["../../src/cloud/auto-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,qDAAqD;AACrD,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,GAAG,MAAM,CAAC;AAEjD,gFAAgF;AAChF,MAAM,CAAC,MAAM,4BAA4B,GAAG,MAAM,CAAC;AAEnD,yCAAyC;AACzC,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAE5C,0EAA0E;AAC1E,MAAM,CAAC,MAAM,kBAAkB,GAAG,oBAAoB,CAAC;AAEvD,mEAAmE;AACnE,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IAC/B,iBAAiB;IACjB,uBAAuB;IACvB,0BAA0B;IAC1B,yBAAyB;CAC1B,CAAC,CAAC;AA6CH;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,aAAkC,gBAAgB;IACjF,OAAO,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;AACvE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;IACvD,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,qBAAqB,CAAC;IACzE,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACxB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,qBAAqB,CAAC;IACnE,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,MAAM,CAAC;AACzC,CAAC;AAED,8BAA8B;AAC9B,SAAS,SAAS,CAAC,QAAgB;IACjC,OAAO,IAAI,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;AAC1C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAAmB,WAAW,EAAE;IAChE,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAkB,CAAC;IACjF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,QAAgB,EAAE,KAAoB;IACxD,IAAI,CAAC;QACH,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,oEAAoE;QACpE,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;QACxD,aAAa,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjD,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,sEAAsE;IACxE,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,WAAmB,WAAW,EAAE;IAC9D,MAAM,CAAC,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,CAAC,CAAC,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC9B,OAAO;QACL,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,4BAA4B,CAAC,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,CAAC,SAAS,CAAC,OAAO,oCAAoC;KACtI,CAAC;AACJ,CAAC;AAED,iGAAiG;AACjG,KAAK,UAAU,gBAAgB,CAAC,MAAc;IAC5C,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IAC/C,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,MAAM,CAAC,EAAE,kBAAkB,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACpE,MAAM,CAAC,0BAA0B,CAAC;QAClC,MAAM,CAAC,wBAAwB,CAAC;KACjC,CAAC,CAAC;IACH,IAAI,IAAuD,CAAC;IAC5D,IAAI,CAAC;QACH,IAAI,GAAG,kBAAkB,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3E,MAAM,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjC,OAAO,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;YAAS,CAAC;QACT,IAAI,EAAE,KAAK,EAAE,CAAC;IAChB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY;IACzB,IAAI,CAAC;QACH,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;QAC9D,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QACtE,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE,CAAC;IACrC,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,GAAY;IAC7B,OAAO,GAAG,YAAY,KAAK,IAAI,MAAM,IAAI,GAAG,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;QAC1E,CAAC,CAAC,GAAG,CAAC,IAAI;QACV,CAAC,CAAC,aAAa,CAAC;AACpB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,WAAmB,EACnB,MAAsB,EACtB,OAAwB,EAAE;IAE1B,MAAM,GAAG,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,WAAW,EAAE,CAAC;IAChD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IACnC,IAAI,CAAC;QACH,8EAA8E;QAC9E,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,eAAe,CAAC;YAAE,OAAO,UAAU,CAAC;QAC/D,MAAM,GAAG,GAAG,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC;QAC3F,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,UAAU,CAAC;QACpC,MAAM,GAAG,GAAG,GAAY,EAAE;YACxB,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC,aAAa,CAAC;YACvD,OAAO,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC;QACvE,CAAC,CAAC;QACF,IAAI,CAAC,GAAG,EAAE;YAAE,OAAO,WAAW,CAAC;QAE/B,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,IAAI,gBAAgB,CAAC;QACrD,MAAM,GAAG,GACP,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;YAC7D,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;QAC7C,IAAI,CAAC,GAAG;YAAE,OAAO,SAAS,CAAC;QAE3B,IAAI,IAAqE,CAAC;QAC1E,2EAA2E;QAC3E,4FAA4F;QAC5F,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,MAAM,aAAa,GAAG,CAAC,GAAU,EAAQ,EAAE;YACzC,WAAW,GAAG,IAAI,CAAC;YACnB,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,uCAAuC,CAAC,CAAC;QACrE,CAAC,CAAC;QACF,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,CACX,IAAI,CAAC,IAAI;gBACT,CAAC,KAAK,EAAE,MAA4B,EAAE,EAAE;oBACtC,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;oBACpE,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;oBACzC,oEAAoE;oBACpE,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;oBACtD,OAAO,sBAAsB,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;wBACjD,OAAO,EAAE,CAAC;wBACV,KAAK,EAAE,oBAAoB,GAAG,CAAC;wBAC/B,aAAa,EAAE,MAAM;qBACtB,CAAC,CAAC;gBACL,CAAC,CAAC,CACH,CAAC,aAAa,CAAC,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,IAAI,CAAC;YACH,IAAI,CAAC,GAAG,EAAE;gBAAE,OAAO,WAAW,CAAC;YAC/B,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,YAAY,CAAC,EAAE,CAAC;YACvD,IAAI,SAAS,KAAK,IAAI;gBAAE,OAAO,UAAU,CAAC;YAC1C,MAAM,KAAK,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAC1C,UAAU,CAAC,QAAQ,EAAE,EAAE,GAAG,KAAK,EAAE,aAAa,EAAE,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;YACrE,8EAA8E;YAC9E,IAAI,QAAsC,CAAC;YAC3C,IAAI,CAAC;gBACH,MAAM,IAAI,GACR,IAAI,CAAC,IAAI;oBACT,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;wBACtB,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;wBACvD,OAAO,SAAS,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;oBAC1C,CAAC,CAAC,CAAC;gBACL,IAAI,KAAgD,CAAC;gBACrD,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC;gBAC7B,MAAM,OAAO,CAAC,IAAI,CAAC;oBACjB,QAAQ;oBACR,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;wBACxB,KAAK,GAAG,UAAU,CAChB,GAAG,EAAE,CACH,MAAM,CACJ,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,oBAAoB,KAAK,CAAC,EAAE;4BACrE,IAAI,EAAE,qBAAqB;yBAC5B,CAAC,CACH,EACH,oBAAoB,CACrB,CAAC;wBACF,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;oBAClB,CAAC,CAAC;iBACH,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;gBACtC,UAAU,CAAC,QAAQ,EAAE;oBACnB,GAAG,KAAK;oBACR,aAAa,EAAE,GAAG,CAAC,WAAW,EAAE;oBAChC,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;oBAClC,SAAS,EAAE,IAAI;iBAChB,CAAC,CAAC;gBACH,OAAO,QAAQ,CAAC;YAClB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;gBAC5B,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,OAAO,SAAS,CAAC;gBACjD,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjE,UAAU,CAAC,QAAQ,EAAE;oBACnB,GAAG,KAAK;oBACR,aAAa,EAAE,GAAG,CAAC,WAAW,EAAE;oBAChC,SAAS,EAAE,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;iBAC3D,CAAC,CAAC;gBACH,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,6BAA6B,CAAC,CAAC;gBACnE,OAAO,QAAQ,CAAC;YAClB,CAAC;oBAAS,CAAC;gBACT,uEAAuE;gBACvE,4EAA4E;gBAC5E,MAAM,QAAQ,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;gBACvC,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC;YAC5B,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,oFAAoF;YACpF,IAAI,WAAW,IAAI,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;;gBACjD,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,8BAA8B,CAAC,CAAC;QAC1D,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC"}
|