@intutic/sync-daemon 1.6.0
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/LICENSE +21 -0
- package/README.md +73 -0
- package/dist/brainIndexer.d.ts +51 -0
- package/dist/brainIndexer.d.ts.map +1 -0
- package/dist/brainIndexer.js +148 -0
- package/dist/brainIndexer.js.map +1 -0
- package/dist/configReader.d.ts +46 -0
- package/dist/configReader.d.ts.map +1 -0
- package/dist/configReader.js +133 -0
- package/dist/configReader.js.map +1 -0
- package/dist/configWriter.d.ts +53 -0
- package/dist/configWriter.d.ts.map +1 -0
- package/dist/configWriter.js +503 -0
- package/dist/configWriter.js.map +1 -0
- package/dist/harness/aiderConfigMerger.d.ts +27 -0
- package/dist/harness/aiderConfigMerger.d.ts.map +1 -0
- package/dist/harness/aiderConfigMerger.js +139 -0
- package/dist/harness/aiderConfigMerger.js.map +1 -0
- package/dist/harness/antigravityHooks.d.ts +43 -0
- package/dist/harness/antigravityHooks.d.ts.map +1 -0
- package/dist/harness/antigravityHooks.js +193 -0
- package/dist/harness/antigravityHooks.js.map +1 -0
- package/dist/harness/claudeCodeHooks.d.ts +59 -0
- package/dist/harness/claudeCodeHooks.d.ts.map +1 -0
- package/dist/harness/claudeCodeHooks.js +414 -0
- package/dist/harness/claudeCodeHooks.js.map +1 -0
- package/dist/harness/claudeDesktopHooks.d.ts +30 -0
- package/dist/harness/claudeDesktopHooks.d.ts.map +1 -0
- package/dist/harness/claudeDesktopHooks.js +267 -0
- package/dist/harness/claudeDesktopHooks.js.map +1 -0
- package/dist/harness/clineHooks.d.ts +23 -0
- package/dist/harness/clineHooks.d.ts.map +1 -0
- package/dist/harness/clineHooks.js +169 -0
- package/dist/harness/clineHooks.js.map +1 -0
- package/dist/harness/continueHooks.d.ts +33 -0
- package/dist/harness/continueHooks.d.ts.map +1 -0
- package/dist/harness/continueHooks.js +124 -0
- package/dist/harness/continueHooks.js.map +1 -0
- package/dist/harness/cursorHooks.d.ts +27 -0
- package/dist/harness/cursorHooks.d.ts.map +1 -0
- package/dist/harness/cursorHooks.js +221 -0
- package/dist/harness/cursorHooks.js.map +1 -0
- package/dist/harness/cursorHooksJson.d.ts +29 -0
- package/dist/harness/cursorHooksJson.d.ts.map +1 -0
- package/dist/harness/cursorHooksJson.js +130 -0
- package/dist/harness/cursorHooksJson.js.map +1 -0
- package/dist/harness/gooseHardener.d.ts +39 -0
- package/dist/harness/gooseHardener.d.ts.map +1 -0
- package/dist/harness/gooseHardener.js +152 -0
- package/dist/harness/gooseHardener.js.map +1 -0
- package/dist/harness/gooseHooks.d.ts +24 -0
- package/dist/harness/gooseHooks.d.ts.map +1 -0
- package/dist/harness/gooseHooks.js +175 -0
- package/dist/harness/gooseHooks.js.map +1 -0
- package/dist/harness/gooseHooksWriter.d.ts +27 -0
- package/dist/harness/gooseHooksWriter.d.ts.map +1 -0
- package/dist/harness/gooseHooksWriter.js +147 -0
- package/dist/harness/gooseHooksWriter.js.map +1 -0
- package/dist/harness/hermesHooks.d.ts +31 -0
- package/dist/harness/hermesHooks.d.ts.map +1 -0
- package/dist/harness/hermesHooks.js +245 -0
- package/dist/harness/hermesHooks.js.map +1 -0
- package/dist/harness/mcpAutoWrite.d.ts +35 -0
- package/dist/harness/mcpAutoWrite.d.ts.map +1 -0
- package/dist/harness/mcpAutoWrite.js +334 -0
- package/dist/harness/mcpAutoWrite.js.map +1 -0
- package/dist/harness/n8nHooks.d.ts +28 -0
- package/dist/harness/n8nHooks.d.ts.map +1 -0
- package/dist/harness/n8nHooks.js +205 -0
- package/dist/harness/n8nHooks.js.map +1 -0
- package/dist/harness/openWebuiHooks.d.ts +31 -0
- package/dist/harness/openWebuiHooks.d.ts.map +1 -0
- package/dist/harness/openWebuiHooks.js +166 -0
- package/dist/harness/openWebuiHooks.js.map +1 -0
- package/dist/harness/openclawHooks.d.ts +34 -0
- package/dist/harness/openclawHooks.d.ts.map +1 -0
- package/dist/harness/openclawHooks.js +296 -0
- package/dist/harness/openclawHooks.js.map +1 -0
- package/dist/harness/openhandsHooks.d.ts +24 -0
- package/dist/harness/openhandsHooks.d.ts.map +1 -0
- package/dist/harness/openhandsHooks.js +178 -0
- package/dist/harness/openhandsHooks.js.map +1 -0
- package/dist/harness/openhandsHooksWriter.d.ts +23 -0
- package/dist/harness/openhandsHooksWriter.d.ts.map +1 -0
- package/dist/harness/openhandsHooksWriter.js +146 -0
- package/dist/harness/openhandsHooksWriter.js.map +1 -0
- package/dist/harness/piHooks.d.ts +32 -0
- package/dist/harness/piHooks.d.ts.map +1 -0
- package/dist/harness/piHooks.js +257 -0
- package/dist/harness/piHooks.js.map +1 -0
- package/dist/harness/rooCodeHooks.d.ts +31 -0
- package/dist/harness/rooCodeHooks.d.ts.map +1 -0
- package/dist/harness/rooCodeHooks.js +300 -0
- package/dist/harness/rooCodeHooks.js.map +1 -0
- package/dist/harness/windsurfHooks.d.ts +27 -0
- package/dist/harness/windsurfHooks.d.ts.map +1 -0
- package/dist/harness/windsurfHooks.js +202 -0
- package/dist/harness/windsurfHooks.js.map +1 -0
- package/dist/hashReporter.d.ts +33 -0
- package/dist/hashReporter.d.ts.map +1 -0
- package/dist/hashReporter.js +69 -0
- package/dist/hashReporter.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/integrityStore.d.ts +43 -0
- package/dist/integrityStore.d.ts.map +1 -0
- package/dist/integrityStore.js +94 -0
- package/dist/integrityStore.js.map +1 -0
- package/dist/lib/complianceProbes.d.ts +39 -0
- package/dist/lib/complianceProbes.d.ts.map +1 -0
- package/dist/lib/complianceProbes.js +115 -0
- package/dist/lib/complianceProbes.js.map +1 -0
- package/dist/lib/processPoller.d.ts +2 -0
- package/dist/lib/processPoller.d.ts.map +1 -0
- package/dist/lib/processPoller.js +87 -0
- package/dist/lib/processPoller.js.map +1 -0
- package/dist/lib/runtimeEnv.d.ts +49 -0
- package/dist/lib/runtimeEnv.d.ts.map +1 -0
- package/dist/lib/runtimeEnv.js +70 -0
- package/dist/lib/runtimeEnv.js.map +1 -0
- package/dist/skillWriter.d.ts +24 -0
- package/dist/skillWriter.d.ts.map +1 -0
- package/dist/skillWriter.js +112 -0
- package/dist/skillWriter.js.map +1 -0
- package/dist/syncLoop.d.ts +70 -0
- package/dist/syncLoop.d.ts.map +1 -0
- package/dist/syncLoop.js +546 -0
- package/dist/syncLoop.js.map +1 -0
- package/dist/trajectoryMonitor.d.ts +126 -0
- package/dist/trajectoryMonitor.d.ts.map +1 -0
- package/dist/trajectoryMonitor.js +291 -0
- package/dist/trajectoryMonitor.js.map +1 -0
- package/dist/watcher/driftWatcher.d.ts +25 -0
- package/dist/watcher/driftWatcher.d.ts.map +1 -0
- package/dist/watcher/driftWatcher.js +72 -0
- package/dist/watcher/driftWatcher.js.map +1 -0
- package/dist/watcher/settingsGuard.d.ts +32 -0
- package/dist/watcher/settingsGuard.d.ts.map +1 -0
- package/dist/watcher/settingsGuard.js +250 -0
- package/dist/watcher/settingsGuard.js.map +1 -0
- package/dist/wsClient.d.ts +49 -0
- package/dist/wsClient.d.ts.map +1 -0
- package/dist/wsClient.js +149 -0
- package/dist/wsClient.js.map +1 -0
- package/package.json +96 -0
package/dist/syncLoop.js
ADDED
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* syncLoop.ts — Core bidirectional sync loop.
|
|
3
|
+
*
|
|
4
|
+
* The sync loop is the heartbeat of the daemon. Each iteration:
|
|
5
|
+
* 1. Fetches config from the control plane (POST /api/v1/sync/config)
|
|
6
|
+
* 2. If configVersion > local → writes SOP content to harness files
|
|
7
|
+
* 3. Computes SHA-256 hashes of local config files
|
|
8
|
+
* 4. Reports hashes + status back to the control plane
|
|
9
|
+
* 5. Calls the onSync callback with the result
|
|
10
|
+
* 6. Sleeps for pollIntervalMs (AbortSignal-aware)
|
|
11
|
+
* 7. Repeats until signal.aborted
|
|
12
|
+
*
|
|
13
|
+
* Design: never crash on a single iteration failure. Errors are
|
|
14
|
+
* caught per-iteration, logged, and the loop continues.
|
|
15
|
+
*
|
|
16
|
+
* HLD §3.14 — Real-Time State Mirroring
|
|
17
|
+
* LLD #8 — Sync Daemon / CLI
|
|
18
|
+
*
|
|
19
|
+
* @module
|
|
20
|
+
*/
|
|
21
|
+
import * as crypto from 'node:crypto';
|
|
22
|
+
import * as path from 'node:path';
|
|
23
|
+
import * as fs from 'node:fs';
|
|
24
|
+
import * as os from 'node:os';
|
|
25
|
+
import { newIso } from '@intutic/id';
|
|
26
|
+
import { writeConfigFiles, HARNESS_FILES, applyConfigEdits } from './configWriter.js';
|
|
27
|
+
import { computeFileHashes } from './hashReporter.js';
|
|
28
|
+
import { loadIntegrity, saveIntegrity } from './integrityStore.js';
|
|
29
|
+
import { drainHookEvents } from './harness/claudeCodeHooks.js';
|
|
30
|
+
import { writeRuntimeEnv } from './lib/runtimeEnv.js';
|
|
31
|
+
import { runComplianceProbes } from './lib/complianceProbes.js';
|
|
32
|
+
import { startWatcher } from './watcher/driftWatcher.js';
|
|
33
|
+
import { shouldCaptureThisIteration, captureAndUpload } from './configReader.js';
|
|
34
|
+
import { watch } from 'chokidar';
|
|
35
|
+
import Redis from 'ioredis';
|
|
36
|
+
import { TrajectoryMonitor } from './trajectoryMonitor.js';
|
|
37
|
+
// ─── Default constants ───────────────────────────────────────────────
|
|
38
|
+
const DEFAULT_POLL_INTERVAL_MS = 30_000;
|
|
39
|
+
// ─── Core sync loop ──────────────────────────────────────────────────
|
|
40
|
+
/**
|
|
41
|
+
* Start the sync loop. This function runs indefinitely until the
|
|
42
|
+
* AbortSignal is triggered or the process exits.
|
|
43
|
+
*
|
|
44
|
+
* @param options - Sync loop configuration.
|
|
45
|
+
*/
|
|
46
|
+
export async function startSyncLoop(options) {
|
|
47
|
+
const { controlPlaneUrl, apiKey, workspaceId, workspaceRoot, pollIntervalMs = DEFAULT_POLL_INTERVAL_MS, onSync, signal, adapterId, } = options;
|
|
48
|
+
// Step -1: Start the Trajectory Monitor & Valkey Subscriber
|
|
49
|
+
let trajectoryMonitor = null;
|
|
50
|
+
let trajectorySubscriber = null;
|
|
51
|
+
if (process.env.VALKEY_URL || apiKey) {
|
|
52
|
+
const valkeyUrl = process.env.VALKEY_URL ?? 'redis://127.0.0.1:6379';
|
|
53
|
+
trajectoryMonitor = new TrajectoryMonitor({
|
|
54
|
+
valkeyUrl,
|
|
55
|
+
controlPlaneUrl,
|
|
56
|
+
apiKey,
|
|
57
|
+
windowMs: 300_000,
|
|
58
|
+
submitIntervalMs: 60_000,
|
|
59
|
+
});
|
|
60
|
+
try {
|
|
61
|
+
await trajectoryMonitor.start();
|
|
62
|
+
trajectorySubscriber = new Redis(valkeyUrl);
|
|
63
|
+
await trajectorySubscriber.psubscribe('trace:live:*');
|
|
64
|
+
trajectorySubscriber.on('pmessage', (pattern, channel, message) => {
|
|
65
|
+
try {
|
|
66
|
+
const event = JSON.parse(message);
|
|
67
|
+
trajectoryMonitor?.handleTraceEvent(event);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
// Non-blocking warning
|
|
71
|
+
console.warn('[sync-daemon] Failed to parse trajectory trace event:', err);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
console.log('[sync-daemon] Trajectory monitor & subscriber started successfully');
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
console.warn('[sync-daemon] Could not start trajectory monitor:', err);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Tracking latest settings for use in drift handler
|
|
81
|
+
let latestSettings;
|
|
82
|
+
let latestSops = [];
|
|
83
|
+
let latestProxyUrl = '';
|
|
84
|
+
let latestHarnesses = [];
|
|
85
|
+
// Step 0: Write runtime env file (hook scripts source this for credentials)
|
|
86
|
+
// Runs once at startup and then again on every iteration.
|
|
87
|
+
try {
|
|
88
|
+
await writeRuntimeEnv({ controlPlaneUrl, apiKey, workspaceId });
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
console.warn('[sync-daemon] Could not write runtime env file (non-fatal):', err);
|
|
92
|
+
}
|
|
93
|
+
// Try to sync offline traces back to PostgreSQL
|
|
94
|
+
try {
|
|
95
|
+
await syncOfflineTraces(controlPlaneUrl, apiKey);
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
console.warn('[sync-daemon] Could not sync offline traces (non-fatal):', err);
|
|
99
|
+
}
|
|
100
|
+
// Set up FSEvents-driven hook event drain (replaces 30s fixed poll for drain step).
|
|
101
|
+
// Drains immediately when the hook-events.jsonl file changes (written by hook scripts).
|
|
102
|
+
// Falls back to a 60s safety-net interval for NFS/Docker mounts where inotify may not fire.
|
|
103
|
+
const hookEventsLog = `${workspaceRoot}/.intutic/events/hook-events.jsonl`;
|
|
104
|
+
let fsWatcher = null;
|
|
105
|
+
let drainSafetyTimer = null;
|
|
106
|
+
const runDrain = async () => {
|
|
107
|
+
try {
|
|
108
|
+
const drained = await drainHookEvents(workspaceRoot, controlPlaneUrl, apiKey);
|
|
109
|
+
if (drained > 0) {
|
|
110
|
+
console.log(`[sync-daemon] Drained ${drained} hook governance events to control plane`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
console.warn('[sync-daemon] Hook event drain error (non-fatal):', err);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
try {
|
|
118
|
+
fsWatcher = watch(hookEventsLog, { ignoreInitial: true, persistent: false });
|
|
119
|
+
fsWatcher.on('change', runDrain);
|
|
120
|
+
fsWatcher.on('add', runDrain);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// chokidar unavailable — rely on the 60s safety-net only
|
|
124
|
+
}
|
|
125
|
+
// 60-second safety-net drain poll (catches events missed by FSEvents on NFS/Docker)
|
|
126
|
+
drainSafetyTimer = setInterval(runDrain, 60_000);
|
|
127
|
+
signal?.addEventListener('abort', () => {
|
|
128
|
+
fsWatcher?.close();
|
|
129
|
+
if (drainSafetyTimer)
|
|
130
|
+
clearInterval(drainSafetyTimer);
|
|
131
|
+
trajectoryMonitor?.stop();
|
|
132
|
+
trajectorySubscriber?.disconnect();
|
|
133
|
+
}, { once: true });
|
|
134
|
+
// WS-5 — Drift watcher with onDriftDetected callback
|
|
135
|
+
// Wired once after first successful sync (when we have harness list).
|
|
136
|
+
// The callback fires a config_tamper governance event and immediately rewrites config.
|
|
137
|
+
let driftWatcher = null;
|
|
138
|
+
const onDriftDetected = async (changedPath) => {
|
|
139
|
+
// 1. Immediately rewrite config (if settings allow)
|
|
140
|
+
if (latestSettings?.bypassEnforcementTier !== 'alert-only') {
|
|
141
|
+
try {
|
|
142
|
+
await writeConfigFiles(workspaceRoot, latestSops, latestProxyUrl, latestHarnesses, workspaceId, latestSettings?.bypassEnforcementTier);
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
console.warn('[sync-daemon] onDriftDetected: writeConfigFiles failed (non-fatal):', err);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// 2. Append config_tamper event to hook-events JSONL
|
|
149
|
+
try {
|
|
150
|
+
const tamperEntry = JSON.stringify({
|
|
151
|
+
event: 'config_tamper',
|
|
152
|
+
toolName: 'config_file',
|
|
153
|
+
reason: 'Harness config file modified outside sync-daemon',
|
|
154
|
+
workspaceId,
|
|
155
|
+
filePath: changedPath,
|
|
156
|
+
timestamp: new Date().toISOString(),
|
|
157
|
+
incidentId: crypto.createHash('sha1').update(changedPath + Date.now()).digest('hex').slice(0, 16),
|
|
158
|
+
}) + '\n';
|
|
159
|
+
const hookEventsJsonl = path.join(os.homedir(), '.intutic', 'events', 'hook-events.jsonl');
|
|
160
|
+
fs.appendFileSync(hookEventsJsonl, tamperEntry, { flag: 'a' });
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
console.warn('[sync-daemon] onDriftDetected: failed to write tamper event (non-fatal):', err);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
let iterationCount = 0;
|
|
167
|
+
while (!signal?.aborted) {
|
|
168
|
+
try {
|
|
169
|
+
// Refresh runtime env on every iteration (key rotation)
|
|
170
|
+
const result = await runSyncIteration({
|
|
171
|
+
controlPlaneUrl,
|
|
172
|
+
apiKey,
|
|
173
|
+
workspaceId,
|
|
174
|
+
workspaceRoot,
|
|
175
|
+
onSync,
|
|
176
|
+
adapterId,
|
|
177
|
+
});
|
|
178
|
+
// Update cached state for drift handler
|
|
179
|
+
if (result) {
|
|
180
|
+
latestSettings = result.settings;
|
|
181
|
+
latestSops = result.sops ?? [];
|
|
182
|
+
latestProxyUrl = result.proxyUrl ?? '';
|
|
183
|
+
latestHarnesses = result.harnesses ?? [];
|
|
184
|
+
await writeRuntimeEnv({
|
|
185
|
+
controlPlaneUrl,
|
|
186
|
+
apiKey,
|
|
187
|
+
workspaceId,
|
|
188
|
+
mcpProxyFailBehavior: result.settings?.mcpProxyFailBehavior,
|
|
189
|
+
mcpProxyMode: result.settings?.mcpProxyMode,
|
|
190
|
+
bypassEnforcementTier: result.settings?.bypassEnforcementTier,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
// Start the drift watcher on first successful sync (once harnesses are known)
|
|
194
|
+
if (!driftWatcher && latestHarnesses.length > 0) {
|
|
195
|
+
try {
|
|
196
|
+
driftWatcher = startWatcher(workspaceRoot, latestHarnesses, onDriftDetected);
|
|
197
|
+
signal?.addEventListener('abort', () => driftWatcher?.stop(), { once: true });
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
console.warn('[sync-daemon] Could not start drift watcher (non-fatal):', err);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Run network compliance probes to check for proxy bypass
|
|
204
|
+
try {
|
|
205
|
+
const probeResults = await runComplianceProbes(workspaceId);
|
|
206
|
+
for (const res of probeResults) {
|
|
207
|
+
if (!res.contained && res.incident) {
|
|
208
|
+
const entry = JSON.stringify(res.incident) + '\n';
|
|
209
|
+
fs.appendFileSync(hookEventsLog, entry, { flag: 'a' });
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
console.warn('[sync-daemon] Compliance probes failed (non-fatal):', err);
|
|
215
|
+
}
|
|
216
|
+
// 4b. Capture harness configs back to control plane (every Nth iteration)
|
|
217
|
+
if (shouldCaptureThisIteration(iterationCount)) {
|
|
218
|
+
try {
|
|
219
|
+
await captureAndUpload(controlPlaneUrl, apiKey, workspaceId, workspaceRoot, latestHarnesses);
|
|
220
|
+
}
|
|
221
|
+
catch (err) {
|
|
222
|
+
console.warn('[sync-daemon] Config capture failed (non-fatal):', err);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
iterationCount++;
|
|
226
|
+
}
|
|
227
|
+
catch (err) {
|
|
228
|
+
console.error('[sync-daemon] iteration error:', err);
|
|
229
|
+
}
|
|
230
|
+
await sleep(pollIntervalMs, signal);
|
|
231
|
+
}
|
|
232
|
+
// Cleanup on exit
|
|
233
|
+
fsWatcher?.close();
|
|
234
|
+
driftWatcher?.stop();
|
|
235
|
+
if (drainSafetyTimer)
|
|
236
|
+
clearInterval(drainSafetyTimer);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Execute a single sync iteration:
|
|
240
|
+
* 1. Fetch config from control plane
|
|
241
|
+
* 2. Write config files if version is newer
|
|
242
|
+
* 3. Compute file hashes
|
|
243
|
+
* 4. Report status back to control plane
|
|
244
|
+
* 5. Update local integrity store
|
|
245
|
+
* 6. Call onSync callback
|
|
246
|
+
*/
|
|
247
|
+
async function runSyncIteration(ctx) {
|
|
248
|
+
const { controlPlaneUrl, apiKey, workspaceId, workspaceRoot, onSync, adapterId } = ctx;
|
|
249
|
+
// 1. Fetch config from control plane
|
|
250
|
+
const config = await fetchConfig(controlPlaneUrl, apiKey, workspaceId);
|
|
251
|
+
// 2. Load local integrity store
|
|
252
|
+
const integrity = await loadIntegrity(workspaceRoot);
|
|
253
|
+
const localVersion = integrity?.configVersion ?? -1;
|
|
254
|
+
let sopsWritten = 0;
|
|
255
|
+
// 3. If remote version is newer → write config files
|
|
256
|
+
if (config.configVersion > localVersion) {
|
|
257
|
+
const harnesses = extractHarnesses(config);
|
|
258
|
+
const writeResult = await writeConfigFiles(workspaceRoot, config.sops, config.proxyUrl, harnesses);
|
|
259
|
+
sopsWritten = writeResult.filesWritten.length;
|
|
260
|
+
}
|
|
261
|
+
// 3b. Apply custom config edits from SkillOpt suggestions
|
|
262
|
+
if (config.appliedEdits && config.appliedEdits.length > 0) {
|
|
263
|
+
const forceApply = sopsWritten > 0;
|
|
264
|
+
const appliedSuggestionsPath = path.join(workspaceRoot, '.intutic', 'applied-suggestions.json');
|
|
265
|
+
let localAppliedIds = [];
|
|
266
|
+
try {
|
|
267
|
+
if (fs.existsSync(appliedSuggestionsPath)) {
|
|
268
|
+
localAppliedIds = JSON.parse(fs.readFileSync(appliedSuggestionsPath, 'utf-8'));
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
catch {
|
|
272
|
+
// ignore
|
|
273
|
+
}
|
|
274
|
+
const toApply = forceApply
|
|
275
|
+
? config.appliedEdits
|
|
276
|
+
: config.appliedEdits.filter(edit => !localAppliedIds.includes(edit.suggestionId));
|
|
277
|
+
if (toApply.length > 0) {
|
|
278
|
+
try {
|
|
279
|
+
await applyConfigEdits(workspaceRoot, toApply, config.settings.bypassEnforcementTier);
|
|
280
|
+
const newlyAppliedIds = Array.from(new Set([...localAppliedIds, ...toApply.map(e => e.suggestionId)]));
|
|
281
|
+
try {
|
|
282
|
+
fs.mkdirSync(path.dirname(appliedSuggestionsPath), { recursive: true });
|
|
283
|
+
fs.writeFileSync(appliedSuggestionsPath, JSON.stringify(newlyAppliedIds, null, 2), 'utf-8');
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
// ignore
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
catch (err) {
|
|
290
|
+
console.warn('[sync-daemon] Failed to apply custom SkillOpt config edits:', err);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// 4. Compute file hashes for drift detection
|
|
295
|
+
const harnesses = extractHarnesses(config);
|
|
296
|
+
const canonicalHashes = buildCanonicalHashMap(config);
|
|
297
|
+
const fileHashes = await computeFileHashes(workspaceRoot, harnesses, canonicalHashes);
|
|
298
|
+
const driftCount = fileHashes.filter((f) => f.drifted).length;
|
|
299
|
+
// 5. Report status back to control plane per active harness
|
|
300
|
+
for (const harness of harnesses) {
|
|
301
|
+
const filename = HARNESS_FILES[harness];
|
|
302
|
+
if (!filename)
|
|
303
|
+
continue;
|
|
304
|
+
const harnessHashes = fileHashes.filter((f) => f.filePath === filename);
|
|
305
|
+
if (harnessHashes.length > 0) {
|
|
306
|
+
await reportStatus(controlPlaneUrl, apiKey, workspaceId, harness, harnessHashes);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// 6. Update local integrity store
|
|
310
|
+
const newFiles = {};
|
|
311
|
+
for (const fh of fileHashes) {
|
|
312
|
+
if (fh.localHash) {
|
|
313
|
+
newFiles[fh.filePath] = fh.localHash;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
await saveIntegrity(workspaceRoot, {
|
|
317
|
+
lastSyncAt: newIso(),
|
|
318
|
+
configVersion: config.configVersion,
|
|
319
|
+
files: newFiles,
|
|
320
|
+
});
|
|
321
|
+
// 6b. ContextGraph Indexing Scan & Sync (WS1: LLD #16)
|
|
322
|
+
if (adapterId) {
|
|
323
|
+
try {
|
|
324
|
+
const { BrainIndexer } = await import('./brainIndexer.js');
|
|
325
|
+
const { loadContextIntegrity, saveContextIntegrity } = await import('./integrityStore.js');
|
|
326
|
+
const scanResult = await BrainIndexer.scanWorkspace(workspaceRoot);
|
|
327
|
+
const contextIntegrity = await loadContextIntegrity(workspaceRoot);
|
|
328
|
+
const delta = BrainIndexer.computeDelta(scanResult, contextIntegrity);
|
|
329
|
+
if (delta.upserted.length > 0 || delta.deleted.length > 0) {
|
|
330
|
+
const syncUrl = `${controlPlaneUrl}/api/v1/context/sync`;
|
|
331
|
+
const res = await fetch(syncUrl, {
|
|
332
|
+
method: 'POST',
|
|
333
|
+
headers: {
|
|
334
|
+
'Content-Type': 'application/json',
|
|
335
|
+
Authorization: `Bearer ${apiKey}`,
|
|
336
|
+
},
|
|
337
|
+
body: JSON.stringify({
|
|
338
|
+
adapterId,
|
|
339
|
+
delta,
|
|
340
|
+
}),
|
|
341
|
+
signal: AbortSignal.timeout(15_000),
|
|
342
|
+
});
|
|
343
|
+
if (res.ok) {
|
|
344
|
+
const newContextFiles = {};
|
|
345
|
+
for (const [filePath, file] of Object.entries(scanResult.files)) {
|
|
346
|
+
newContextFiles[filePath] = file.hash;
|
|
347
|
+
}
|
|
348
|
+
await saveContextIntegrity(workspaceRoot, {
|
|
349
|
+
lastSyncAt: newIso(),
|
|
350
|
+
configVersion: config.configVersion,
|
|
351
|
+
files: newContextFiles,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
console.warn(`[sync-daemon] ContextGraph sync failed: ${res.status} ${res.statusText}`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
catch (err) {
|
|
360
|
+
console.warn('[sync-daemon] ContextGraph sync error:', err);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// 6c. Hook event drain is now FSEvents-driven (see startSyncLoop).
|
|
364
|
+
// No per-iteration drain needed here; the chokidar watcher handles it.
|
|
365
|
+
// 7. Invoke onSync callback
|
|
366
|
+
const result = {
|
|
367
|
+
configVersion: config.configVersion,
|
|
368
|
+
sopsWritten,
|
|
369
|
+
driftCount,
|
|
370
|
+
timestamp: newIso(),
|
|
371
|
+
settings: config.settings,
|
|
372
|
+
sops: config.sops,
|
|
373
|
+
proxyUrl: config.proxyUrl,
|
|
374
|
+
harnesses,
|
|
375
|
+
};
|
|
376
|
+
onSync?.(result);
|
|
377
|
+
return result;
|
|
378
|
+
}
|
|
379
|
+
// ─── HTTP helpers ────────────────────────────────────────────────────
|
|
380
|
+
/**
|
|
381
|
+
* Fetch the sync config from the control plane.
|
|
382
|
+
*
|
|
383
|
+
* POST /api/v1/sync/config
|
|
384
|
+
*/
|
|
385
|
+
async function fetchConfig(controlPlaneUrl, apiKey, workspaceId) {
|
|
386
|
+
const url = `${controlPlaneUrl}/api/v1/sync/config`;
|
|
387
|
+
const res = await fetch(url, {
|
|
388
|
+
method: 'POST',
|
|
389
|
+
headers: {
|
|
390
|
+
'Content-Type': 'application/json',
|
|
391
|
+
Authorization: `Bearer ${apiKey}`,
|
|
392
|
+
},
|
|
393
|
+
body: JSON.stringify({ workspaceId }),
|
|
394
|
+
signal: AbortSignal.timeout(15_000), // 15s request timeout
|
|
395
|
+
});
|
|
396
|
+
if (!res.ok) {
|
|
397
|
+
throw new Error(`[sync-daemon] fetchConfig failed: ${res.status} ${res.statusText}`);
|
|
398
|
+
}
|
|
399
|
+
return (await res.json());
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Report file hashes and status back to the control plane.
|
|
403
|
+
*
|
|
404
|
+
* POST /api/v1/sync/sop-hash
|
|
405
|
+
*/
|
|
406
|
+
async function reportStatus(controlPlaneUrl, apiKey, workspaceId, harnessType, files) {
|
|
407
|
+
const url = `${controlPlaneUrl}/api/v1/sync/sop-hash`;
|
|
408
|
+
const res = await fetch(url, {
|
|
409
|
+
method: 'POST',
|
|
410
|
+
headers: {
|
|
411
|
+
'Content-Type': 'application/json',
|
|
412
|
+
Authorization: `Bearer ${apiKey}`,
|
|
413
|
+
},
|
|
414
|
+
body: JSON.stringify({
|
|
415
|
+
workspaceId,
|
|
416
|
+
harnessType,
|
|
417
|
+
files,
|
|
418
|
+
reportedAt: newIso(),
|
|
419
|
+
}),
|
|
420
|
+
signal: AbortSignal.timeout(15_000),
|
|
421
|
+
});
|
|
422
|
+
if (!res.ok) {
|
|
423
|
+
// Non-fatal: log but don't throw (control plane might be temporarily down)
|
|
424
|
+
console.warn(`[sync-daemon] reportStatus failed for ${harnessType}: ${res.status} ${res.statusText}`);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
// ─── Helpers ─────────────────────────────────────────────────────────
|
|
428
|
+
/**
|
|
429
|
+
* Extract unique harness types from a sync config payload.
|
|
430
|
+
*/
|
|
431
|
+
function extractHarnesses(config) {
|
|
432
|
+
const set = new Set();
|
|
433
|
+
for (const sop of config.sops) {
|
|
434
|
+
for (const h of sop.harnessTargets) {
|
|
435
|
+
set.add(h);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return [...set];
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Build a filePath → canonical hash map from the config's SOPs.
|
|
442
|
+
* Uses the first canonical hash found for each file path.
|
|
443
|
+
*/
|
|
444
|
+
function buildCanonicalHashMap(config) {
|
|
445
|
+
const map = {};
|
|
446
|
+
for (const sop of config.sops) {
|
|
447
|
+
// Each SOP has a single contentHash; in a multi-harness scenario
|
|
448
|
+
// the same hash applies to the content source (not the formatted output).
|
|
449
|
+
// For per-file canonical hashes, the control plane would need to
|
|
450
|
+
// provide them per-harness. For now we use sop.contentHash as a
|
|
451
|
+
// proxy keyed by sopId.
|
|
452
|
+
map[sop.sopId] = sop.contentHash;
|
|
453
|
+
}
|
|
454
|
+
return map;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Sleep for the given duration with AbortSignal support.
|
|
458
|
+
*
|
|
459
|
+
* Resolves immediately if the signal is already aborted.
|
|
460
|
+
* Otherwise, resolves after `ms` milliseconds or when the
|
|
461
|
+
* signal fires, whichever comes first.
|
|
462
|
+
*/
|
|
463
|
+
function sleep(ms, signal) {
|
|
464
|
+
if (signal?.aborted)
|
|
465
|
+
return Promise.resolve();
|
|
466
|
+
return new Promise((resolve) => {
|
|
467
|
+
const timer = setTimeout(() => {
|
|
468
|
+
signal?.removeEventListener('abort', onAbort);
|
|
469
|
+
resolve();
|
|
470
|
+
}, ms);
|
|
471
|
+
function onAbort() {
|
|
472
|
+
clearTimeout(timer);
|
|
473
|
+
resolve();
|
|
474
|
+
}
|
|
475
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
export async function syncOfflineTraces(controlPlaneUrl, apiKey) {
|
|
479
|
+
const logsDir = path.join(os.homedir(), '.intutic', 'logs');
|
|
480
|
+
if (!fs.existsSync(logsDir))
|
|
481
|
+
return;
|
|
482
|
+
try {
|
|
483
|
+
const files = fs.readdirSync(logsDir);
|
|
484
|
+
const traceFiles = files.filter(f => f.startsWith('traces-') && f.endsWith('.jsonl'));
|
|
485
|
+
if (traceFiles.length === 0)
|
|
486
|
+
return;
|
|
487
|
+
for (const file of traceFiles) {
|
|
488
|
+
const originalPath = path.join(logsDir, file);
|
|
489
|
+
const syncingPath = originalPath + '.syncing';
|
|
490
|
+
// Rename to avoid write race conditions with the Rust proxy
|
|
491
|
+
try {
|
|
492
|
+
fs.renameSync(originalPath, syncingPath);
|
|
493
|
+
}
|
|
494
|
+
catch (renameErr) {
|
|
495
|
+
console.error(`[sync-daemon] Failed to lock/rename file ${file}:`, renameErr.message);
|
|
496
|
+
continue;
|
|
497
|
+
}
|
|
498
|
+
try {
|
|
499
|
+
const raw = fs.readFileSync(syncingPath, 'utf-8');
|
|
500
|
+
const lines = raw.split('\n').map(l => l.trim()).filter(Boolean);
|
|
501
|
+
if (lines.length === 0) {
|
|
502
|
+
// Empty file, just clean it up
|
|
503
|
+
fs.unlinkSync(syncingPath);
|
|
504
|
+
continue;
|
|
505
|
+
}
|
|
506
|
+
const traces = lines.map(line => JSON.parse(line));
|
|
507
|
+
console.log(`[sync-daemon] Found ${traces.length} offline traces to sync back in ${file}.`);
|
|
508
|
+
// Batch in groups of 100
|
|
509
|
+
const batchSize = 100;
|
|
510
|
+
for (let i = 0; i < traces.length; i += batchSize) {
|
|
511
|
+
const batch = traces.slice(i, i + batchSize);
|
|
512
|
+
const res = await fetch(`${controlPlaneUrl}/api/v1/traces/sync-back`, {
|
|
513
|
+
method: 'POST',
|
|
514
|
+
headers: {
|
|
515
|
+
'Content-Type': 'application/json',
|
|
516
|
+
Authorization: `Bearer ${apiKey}`,
|
|
517
|
+
},
|
|
518
|
+
body: JSON.stringify({ traces: batch }),
|
|
519
|
+
});
|
|
520
|
+
if (!res.ok) {
|
|
521
|
+
throw new Error(`Sync-back API returned status ${res.status}`);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
// Successfully synced this sharded file, delete it
|
|
525
|
+
fs.unlinkSync(syncingPath);
|
|
526
|
+
console.log(`[sync-daemon] Successfully synced ${traces.length} offline traces back from ${file}.`);
|
|
527
|
+
}
|
|
528
|
+
catch (err) {
|
|
529
|
+
console.error(`[sync-daemon] Failed to sync offline traces back from ${file}:`, err.message);
|
|
530
|
+
// Revert rename on failure to allow retry on next cycle
|
|
531
|
+
try {
|
|
532
|
+
if (fs.existsSync(syncingPath)) {
|
|
533
|
+
fs.renameSync(syncingPath, originalPath);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
catch (revertErr) {
|
|
537
|
+
console.error(`[sync-daemon] Failed to revert rename for ${file}:`, revertErr.message);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
catch (err) {
|
|
543
|
+
console.error(`[sync-daemon] Failed to scan offline traces directory:`, err.message);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
//# sourceMappingURL=syncLoop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"syncLoop.js","sourceRoot":"","sources":["../src/syncLoop.ts"],"names":[],"mappings":"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"}
|