@intutic/sync-daemon 2.1.0 → 2.3.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/README.md +1 -1
- package/dist/agentReporter.d.ts +24 -11
- package/dist/agentReporter.d.ts.map +1 -1
- package/dist/agentReporter.js +20 -13
- package/dist/agentReporter.js.map +1 -1
- package/dist/configReader.d.ts +45 -25
- package/dist/configReader.d.ts.map +1 -1
- package/dist/configReader.js +70 -46
- package/dist/configReader.js.map +1 -1
- package/dist/configWriter.d.ts +32 -45
- package/dist/configWriter.d.ts.map +1 -1
- package/dist/configWriter.js +52 -686
- package/dist/configWriter.js.map +1 -1
- package/dist/disconnect/harnesses.d.ts +29 -0
- package/dist/disconnect/harnesses.d.ts.map +1 -0
- package/dist/disconnect/harnesses.js +805 -0
- package/dist/disconnect/harnesses.js.map +1 -0
- package/dist/disconnect/index.d.ts +25 -0
- package/dist/disconnect/index.d.ts.map +1 -0
- package/dist/disconnect/index.js +92 -0
- package/dist/disconnect/index.js.map +1 -0
- package/dist/disconnect/mcp.d.ts +81 -0
- package/dist/disconnect/mcp.d.ts.map +1 -0
- package/dist/disconnect/mcp.js +354 -0
- package/dist/disconnect/mcp.js.map +1 -0
- package/dist/disconnect/originals.d.ts +88 -0
- package/dist/disconnect/originals.d.ts.map +1 -0
- package/dist/disconnect/originals.js +257 -0
- package/dist/disconnect/originals.js.map +1 -0
- package/dist/disconnect/plan.d.ts +175 -0
- package/dist/disconnect/plan.d.ts.map +1 -0
- package/dist/disconnect/plan.js +580 -0
- package/dist/disconnect/plan.js.map +1 -0
- package/dist/disconnect/recognise.d.ts +43 -0
- package/dist/disconnect/recognise.d.ts.map +1 -0
- package/dist/disconnect/recognise.js +108 -0
- package/dist/disconnect/recognise.js.map +1 -0
- package/dist/disconnect/tomlLines.d.ts +39 -0
- package/dist/disconnect/tomlLines.d.ts.map +1 -0
- package/dist/disconnect/tomlLines.js +105 -0
- package/dist/disconnect/tomlLines.js.map +1 -0
- package/dist/harness/aiderConfigMerger.d.ts +29 -8
- package/dist/harness/aiderConfigMerger.d.ts.map +1 -1
- package/dist/harness/aiderConfigMerger.js +63 -12
- package/dist/harness/aiderConfigMerger.js.map +1 -1
- package/dist/harness/antigravityCliHooks.d.ts +61 -0
- package/dist/harness/antigravityCliHooks.d.ts.map +1 -0
- package/dist/harness/antigravityCliHooks.js +207 -0
- package/dist/harness/antigravityCliHooks.js.map +1 -0
- package/dist/harness/antigravityHooks.d.ts +12 -2
- package/dist/harness/antigravityHooks.d.ts.map +1 -1
- package/dist/harness/antigravityHooks.js +38 -16
- package/dist/harness/antigravityHooks.js.map +1 -1
- package/dist/harness/antigravityProducts.d.ts +40 -0
- package/dist/harness/antigravityProducts.d.ts.map +1 -0
- package/dist/harness/antigravityProducts.js +109 -0
- package/dist/harness/antigravityProducts.js.map +1 -0
- package/dist/harness/claudeAgentsMd.d.ts +29 -0
- package/dist/harness/claudeAgentsMd.d.ts.map +1 -0
- package/dist/harness/claudeAgentsMd.js +80 -0
- package/dist/harness/claudeAgentsMd.js.map +1 -0
- package/dist/harness/claudeCodeHooks.d.ts +6 -6
- package/dist/harness/claudeCodeHooks.d.ts.map +1 -1
- package/dist/harness/claudeCodeHooks.js +115 -28
- package/dist/harness/claudeCodeHooks.js.map +1 -1
- package/dist/harness/claudeProjectApproval.d.ts +53 -0
- package/dist/harness/claudeProjectApproval.d.ts.map +1 -0
- package/dist/harness/claudeProjectApproval.js +159 -0
- package/dist/harness/claudeProjectApproval.js.map +1 -0
- package/dist/harness/clineHooks.d.ts +0 -1
- package/dist/harness/clineHooks.d.ts.map +1 -1
- package/dist/harness/clineHooks.js +13 -4
- package/dist/harness/clineHooks.js.map +1 -1
- package/dist/harness/codexConfigMerger.d.ts.map +1 -1
- package/dist/harness/codexConfigMerger.js +4 -0
- package/dist/harness/codexConfigMerger.js.map +1 -1
- package/dist/harness/codexHooks.d.ts +2 -0
- package/dist/harness/codexHooks.d.ts.map +1 -1
- package/dist/harness/codexHooks.js +15 -4
- package/dist/harness/codexHooks.js.map +1 -1
- package/dist/harness/continueConfigMerger.d.ts.map +1 -1
- package/dist/harness/continueConfigMerger.js +4 -0
- package/dist/harness/continueConfigMerger.js.map +1 -1
- package/dist/harness/cursorHooks.d.ts +5 -2
- package/dist/harness/cursorHooks.d.ts.map +1 -1
- package/dist/harness/cursorHooks.js +12 -3
- package/dist/harness/cursorHooks.js.map +1 -1
- package/dist/harness/dshHooks.d.ts +5 -5
- package/dist/harness/dshHooks.d.ts.map +1 -1
- package/dist/harness/dshHooks.js +12 -5
- package/dist/harness/dshHooks.js.map +1 -1
- package/dist/harness/gateArtifacts.d.ts +35 -0
- package/dist/harness/gateArtifacts.d.ts.map +1 -0
- package/dist/harness/gateArtifacts.js +88 -0
- package/dist/harness/gateArtifacts.js.map +1 -0
- package/dist/harness/gateBody.d.ts +195 -69
- package/dist/harness/gateBody.d.ts.map +1 -1
- package/dist/harness/gateBody.js +847 -182
- package/dist/harness/gateBody.js.map +1 -1
- package/dist/harness/gateSightings.d.ts +47 -0
- package/dist/harness/gateSightings.d.ts.map +1 -0
- package/dist/harness/gateSightings.js +159 -0
- package/dist/harness/gateSightings.js.map +1 -0
- package/dist/harness/githubCopilotHooks.d.ts.map +1 -1
- package/dist/harness/githubCopilotHooks.js +11 -10
- package/dist/harness/githubCopilotHooks.js.map +1 -1
- package/dist/harness/gooseHardener.d.ts +0 -1
- package/dist/harness/gooseHardener.d.ts.map +1 -1
- package/dist/harness/gooseHardener.js +1 -1
- package/dist/harness/gooseHardener.js.map +1 -1
- package/dist/harness/gooseHooks.d.ts +29 -1
- package/dist/harness/gooseHooks.d.ts.map +1 -1
- package/dist/harness/gooseHooks.js +107 -69
- package/dist/harness/gooseHooks.js.map +1 -1
- package/dist/harness/grokHooks.d.ts +2 -2
- package/dist/harness/grokHooks.d.ts.map +1 -1
- package/dist/harness/grokHooks.js +20 -18
- package/dist/harness/grokHooks.js.map +1 -1
- package/dist/harness/hermesHooks.d.ts +18 -8
- package/dist/harness/hermesHooks.d.ts.map +1 -1
- package/dist/harness/hermesHooks.js +55 -19
- package/dist/harness/hermesHooks.js.map +1 -1
- package/dist/harness/holdRedaction.d.ts +4 -1
- package/dist/harness/holdRedaction.d.ts.map +1 -1
- package/dist/harness/holdRedaction.js +32 -8
- package/dist/harness/holdRedaction.js.map +1 -1
- package/dist/harness/jetbrainsXmlConfig.d.ts +20 -0
- package/dist/harness/jetbrainsXmlConfig.d.ts.map +1 -1
- package/dist/harness/jetbrainsXmlConfig.js +39 -18
- package/dist/harness/jetbrainsXmlConfig.js.map +1 -1
- package/dist/harness/mcpAutoWrite.d.ts +62 -25
- package/dist/harness/mcpAutoWrite.d.ts.map +1 -1
- package/dist/harness/mcpAutoWrite.js +406 -95
- package/dist/harness/mcpAutoWrite.js.map +1 -1
- package/dist/harness/museHooks.d.ts +3 -3
- package/dist/harness/museHooks.d.ts.map +1 -1
- package/dist/harness/museHooks.js +15 -7
- package/dist/harness/museHooks.js.map +1 -1
- package/dist/harness/n8nHooks.d.ts +0 -1
- package/dist/harness/n8nHooks.d.ts.map +1 -1
- package/dist/harness/n8nHooks.js +4 -1
- package/dist/harness/n8nHooks.js.map +1 -1
- package/dist/harness/openCodeHooks.d.ts +2 -2
- package/dist/harness/openCodeHooks.d.ts.map +1 -1
- package/dist/harness/openCodeHooks.js +9 -8
- package/dist/harness/openCodeHooks.js.map +1 -1
- package/dist/harness/openWebuiHooks.d.ts +0 -1
- package/dist/harness/openWebuiHooks.d.ts.map +1 -1
- package/dist/harness/openWebuiHooks.js +11 -3
- package/dist/harness/openWebuiHooks.js.map +1 -1
- package/dist/harness/openclawHooks.d.ts +75 -18
- package/dist/harness/openclawHooks.d.ts.map +1 -1
- package/dist/harness/openclawHooks.js +214 -160
- package/dist/harness/openclawHooks.js.map +1 -1
- package/dist/harness/openhandsHooks.d.ts +37 -11
- package/dist/harness/openhandsHooks.d.ts.map +1 -1
- package/dist/harness/openhandsHooks.js +148 -97
- package/dist/harness/openhandsHooks.js.map +1 -1
- package/dist/harness/piHooks.d.ts +52 -17
- package/dist/harness/piHooks.d.ts.map +1 -1
- package/dist/harness/piHooks.js +177 -163
- package/dist/harness/piHooks.js.map +1 -1
- package/dist/harness/protectedPaths.d.ts +107 -25
- package/dist/harness/protectedPaths.d.ts.map +1 -1
- package/dist/harness/protectedPaths.js +342 -48
- package/dist/harness/protectedPaths.js.map +1 -1
- package/dist/harness/rulesSection.d.ts +62 -0
- package/dist/harness/rulesSection.d.ts.map +1 -0
- package/dist/harness/rulesSection.js +145 -0
- package/dist/harness/rulesSection.js.map +1 -0
- package/dist/harness/windsurfHooks.d.ts +18 -3
- package/dist/harness/windsurfHooks.d.ts.map +1 -1
- package/dist/harness/windsurfHooks.js +41 -8
- package/dist/harness/windsurfHooks.js.map +1 -1
- package/dist/harness/windsurfJetBrainsProxy.d.ts +1 -1
- package/dist/harness/windsurfJetBrainsProxy.d.ts.map +1 -1
- package/dist/harness/windsurfJetBrainsProxy.js +5 -1
- package/dist/harness/windsurfJetBrainsProxy.js.map +1 -1
- package/dist/index.d.ts +21 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -19
- package/dist/index.js.map +1 -1
- package/dist/inventory.d.ts +53 -0
- package/dist/inventory.d.ts.map +1 -0
- package/dist/inventory.js +133 -0
- package/dist/inventory.js.map +1 -0
- package/dist/lib/complianceProbes.d.ts +2 -1
- package/dist/lib/complianceProbes.d.ts.map +1 -1
- package/dist/lib/complianceProbes.js +1 -1
- package/dist/lib/complianceProbes.js.map +1 -1
- package/dist/lib/decisionsDigest.d.ts +35 -17
- package/dist/lib/decisionsDigest.d.ts.map +1 -1
- package/dist/lib/decisionsDigest.js +106 -47
- package/dist/lib/decisionsDigest.js.map +1 -1
- package/dist/lib/egressPolicy.d.ts +2 -2
- package/dist/lib/egressPolicy.js +2 -2
- package/dist/lib/mcpRegistryPy.d.ts +11 -0
- package/dist/lib/mcpRegistryPy.d.ts.map +1 -0
- package/dist/lib/mcpRegistryPy.js +173 -0
- package/dist/lib/mcpRegistryPy.js.map +1 -0
- package/dist/lib/phrasesPy.d.ts +11 -0
- package/dist/lib/phrasesPy.d.ts.map +1 -0
- package/dist/lib/phrasesPy.js +351 -0
- package/dist/lib/phrasesPy.js.map +1 -0
- package/dist/lib/policySnapshot.d.ts +63 -9
- package/dist/lib/policySnapshot.d.ts.map +1 -1
- package/dist/lib/policySnapshot.js +269 -45
- package/dist/lib/policySnapshot.js.map +1 -1
- package/dist/lib/processPoller.d.ts.map +1 -1
- package/dist/lib/processPoller.js +9 -2
- package/dist/lib/processPoller.js.map +1 -1
- package/dist/lib/regexLinearity.d.ts +43 -0
- package/dist/lib/regexLinearity.d.ts.map +1 -0
- package/dist/lib/regexLinearity.js +275 -0
- package/dist/lib/regexLinearity.js.map +1 -0
- package/dist/lib/runtimeEnv.d.ts +1 -3
- package/dist/lib/runtimeEnv.d.ts.map +1 -1
- package/dist/lib/runtimeEnv.js +0 -2
- package/dist/lib/runtimeEnv.js.map +1 -1
- package/dist/lib/sequencePy.d.ts +10 -0
- package/dist/lib/sequencePy.d.ts.map +1 -0
- package/dist/lib/sequencePy.js +102 -0
- package/dist/lib/sequencePy.js.map +1 -0
- package/dist/sessionReporter.d.ts +18 -12
- package/dist/sessionReporter.d.ts.map +1 -1
- package/dist/sessionReporter.js +37 -24
- package/dist/sessionReporter.js.map +1 -1
- package/dist/skillWriter.d.ts +23 -5
- package/dist/skillWriter.d.ts.map +1 -1
- package/dist/skillWriter.js +159 -16
- package/dist/skillWriter.js.map +1 -1
- package/dist/syncCycle.d.ts +142 -0
- package/dist/syncCycle.d.ts.map +1 -0
- package/dist/syncCycle.js +327 -0
- package/dist/syncCycle.js.map +1 -0
- package/dist/trajectoryMonitor.d.ts +2 -4
- package/dist/trajectoryMonitor.d.ts.map +1 -1
- package/dist/trajectoryMonitor.js +2 -5
- package/dist/trajectoryMonitor.js.map +1 -1
- package/dist/watcher/driftWatcher.d.ts +0 -1
- package/dist/watcher/driftWatcher.d.ts.map +1 -1
- package/dist/watcher/driftWatcher.js +1 -2
- package/dist/watcher/driftWatcher.js.map +1 -1
- package/dist/watcher/settingsGuard.d.ts +36 -7
- package/dist/watcher/settingsGuard.d.ts.map +1 -1
- package/dist/watcher/settingsGuard.js +397 -60
- package/dist/watcher/settingsGuard.js.map +1 -1
- package/dist/watcher/vscodeHookSettings.d.ts +30 -0
- package/dist/watcher/vscodeHookSettings.d.ts.map +1 -0
- package/dist/watcher/vscodeHookSettings.js +170 -0
- package/dist/watcher/vscodeHookSettings.js.map +1 -0
- package/dist/wsClient.d.ts +0 -1
- package/dist/wsClient.d.ts.map +1 -1
- package/dist/wsClient.js +0 -1
- package/dist/wsClient.js.map +1 -1
- package/package.json +5 -5
- package/dist/harness/claudeDesktopHooks.d.ts +0 -30
- package/dist/harness/claudeDesktopHooks.d.ts.map +0 -1
- package/dist/harness/claudeDesktopHooks.js +0 -254
- package/dist/harness/claudeDesktopHooks.js.map +0 -1
- package/dist/harness/continueHooks.d.ts +0 -63
- package/dist/harness/continueHooks.d.ts.map +0 -1
- package/dist/harness/continueHooks.js +0 -247
- package/dist/harness/continueHooks.js.map +0 -1
- package/dist/harness/gateKind.d.ts +0 -164
- package/dist/harness/gateKind.d.ts.map +0 -1
- package/dist/harness/gateKind.js +0 -144
- package/dist/harness/gateKind.js.map +0 -1
- package/dist/harness/rooCodeHooks.d.ts +0 -31
- package/dist/harness/rooCodeHooks.d.ts.map +0 -1
- package/dist/harness/rooCodeHooks.js +0 -286
- package/dist/harness/rooCodeHooks.js.map +0 -1
- package/dist/hashReporter.d.ts +0 -33
- package/dist/hashReporter.d.ts.map +0 -1
- package/dist/hashReporter.js +0 -69
- package/dist/hashReporter.js.map +0 -1
- package/dist/integrityStore.d.ts +0 -35
- package/dist/integrityStore.d.ts.map +0 -1
- package/dist/integrityStore.js +0 -71
- package/dist/integrityStore.js.map +0 -1
- package/dist/lib/gitWorktrees.d.ts +0 -140
- package/dist/lib/gitWorktrees.d.ts.map +0 -1
- package/dist/lib/gitWorktrees.js +0 -191
- package/dist/lib/gitWorktrees.js.map +0 -1
- package/dist/syncLoop.d.ts +0 -172
- package/dist/syncLoop.d.ts.map +0 -1
- package/dist/syncLoop.js +0 -878
- package/dist/syncLoop.js.map +0 -1
package/dist/hashReporter.d.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* hashReporter.ts — SHA-256 hash computation + integrity comparison.
|
|
3
|
-
*
|
|
4
|
-
* Computes SHA-256 hashes of local harness config files and compares
|
|
5
|
-
* them against canonical hashes from the control plane. This enables
|
|
6
|
-
* SOP drift detection: if a developer manually edits a governed file,
|
|
7
|
-
* the daemon flags it as drifted in the next sync report.
|
|
8
|
-
*
|
|
9
|
-
* HLD §3.14 — SOP Integrity Verification
|
|
10
|
-
* LLD #8 — Sync Daemon / CLI
|
|
11
|
-
*
|
|
12
|
-
* @module
|
|
13
|
-
*/
|
|
14
|
-
import type { HarnessType, SopFileHash } from '@intutic/shared-types';
|
|
15
|
-
/**
|
|
16
|
-
* Compute SHA-256 hashes for all harness config files and compare
|
|
17
|
-
* against canonical hashes from the control plane.
|
|
18
|
-
*
|
|
19
|
-
* @param workspaceRoot - Absolute path to the workspace root.
|
|
20
|
-
* @param harnesses - Harness types detected in the workspace.
|
|
21
|
-
* @param canonicalHashes - Expected hashes from last sync (filePath → SHA-256).
|
|
22
|
-
* @returns Array of SopFileHash entries with drift detection flags.
|
|
23
|
-
*/
|
|
24
|
-
export declare function computeFileHashes(workspaceRoot: string, harnesses: HarnessType[], canonicalHashes: Record<string, string>): Promise<SopFileHash[]>;
|
|
25
|
-
/**
|
|
26
|
-
* Compute the SHA-256 hex digest of a file's contents.
|
|
27
|
-
*
|
|
28
|
-
* @param filePath - Absolute path to the file.
|
|
29
|
-
* @returns 64-character lowercase hex SHA-256 hash.
|
|
30
|
-
* @throws If the file does not exist or is not readable.
|
|
31
|
-
*/
|
|
32
|
-
export declare function hashFile(filePath: string): Promise<string>;
|
|
33
|
-
//# sourceMappingURL=hashReporter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hashReporter.d.ts","sourceRoot":"","sources":["../src/hashReporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAGrE;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,WAAW,EAAE,EACxB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtC,OAAO,CAAC,WAAW,EAAE,CAAC,CAiCxB;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhE"}
|
package/dist/hashReporter.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* hashReporter.ts — SHA-256 hash computation + integrity comparison.
|
|
3
|
-
*
|
|
4
|
-
* Computes SHA-256 hashes of local harness config files and compares
|
|
5
|
-
* them against canonical hashes from the control plane. This enables
|
|
6
|
-
* SOP drift detection: if a developer manually edits a governed file,
|
|
7
|
-
* the daemon flags it as drifted in the next sync report.
|
|
8
|
-
*
|
|
9
|
-
* HLD §3.14 — SOP Integrity Verification
|
|
10
|
-
* LLD #8 — Sync Daemon / CLI
|
|
11
|
-
*
|
|
12
|
-
* @module
|
|
13
|
-
*/
|
|
14
|
-
import { createHash } from 'node:crypto';
|
|
15
|
-
import * as node_fs from 'node:fs/promises';
|
|
16
|
-
import * as node_path from 'node:path';
|
|
17
|
-
import { HARNESS_FILES } from './configWriter.js';
|
|
18
|
-
/**
|
|
19
|
-
* Compute SHA-256 hashes for all harness config files and compare
|
|
20
|
-
* against canonical hashes from the control plane.
|
|
21
|
-
*
|
|
22
|
-
* @param workspaceRoot - Absolute path to the workspace root.
|
|
23
|
-
* @param harnesses - Harness types detected in the workspace.
|
|
24
|
-
* @param canonicalHashes - Expected hashes from last sync (filePath → SHA-256).
|
|
25
|
-
* @returns Array of SopFileHash entries with drift detection flags.
|
|
26
|
-
*/
|
|
27
|
-
export async function computeFileHashes(workspaceRoot, harnesses, canonicalHashes) {
|
|
28
|
-
const results = [];
|
|
29
|
-
for (const harness of harnesses) {
|
|
30
|
-
const filename = HARNESS_FILES[harness];
|
|
31
|
-
if (!filename)
|
|
32
|
-
continue; // Phase 2 deferred
|
|
33
|
-
const configPath = node_path.join(workspaceRoot, filename);
|
|
34
|
-
const relativePath = filename;
|
|
35
|
-
try {
|
|
36
|
-
const localHash = await hashFile(configPath);
|
|
37
|
-
const canonical = canonicalHashes[relativePath] ?? '';
|
|
38
|
-
const drifted = canonical !== '' && localHash !== canonical;
|
|
39
|
-
results.push({
|
|
40
|
-
filePath: relativePath,
|
|
41
|
-
localHash,
|
|
42
|
-
canonicalHash: canonical,
|
|
43
|
-
drifted,
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
// File doesn't exist or isn't readable — report empty hash, not drifted
|
|
48
|
-
results.push({
|
|
49
|
-
filePath: relativePath,
|
|
50
|
-
localHash: '',
|
|
51
|
-
canonicalHash: canonicalHashes[relativePath] ?? '',
|
|
52
|
-
drifted: false,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return results;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Compute the SHA-256 hex digest of a file's contents.
|
|
60
|
-
*
|
|
61
|
-
* @param filePath - Absolute path to the file.
|
|
62
|
-
* @returns 64-character lowercase hex SHA-256 hash.
|
|
63
|
-
* @throws If the file does not exist or is not readable.
|
|
64
|
-
*/
|
|
65
|
-
export async function hashFile(filePath) {
|
|
66
|
-
const content = await node_fs.readFile(filePath, 'utf-8');
|
|
67
|
-
return createHash('sha256').update(content, 'utf-8').digest('hex');
|
|
68
|
-
}
|
|
69
|
-
//# sourceMappingURL=hashReporter.js.map
|
package/dist/hashReporter.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hashReporter.js","sourceRoot":"","sources":["../src/hashReporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,SAAS,MAAM,WAAW,CAAA;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,aAAqB,EACrB,SAAwB,EACxB,eAAuC;IAEvC,MAAM,OAAO,GAAkB,EAAE,CAAA;IAEjC,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;QACvC,IAAI,CAAC,QAAQ;YAAE,SAAQ,CAAC,mBAAmB;QAE3C,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAA;QAC1D,MAAM,YAAY,GAAG,QAAQ,CAAA;QAE7B,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,CAAA;YAC5C,MAAM,SAAS,GAAG,eAAe,CAAC,YAAY,CAAC,IAAI,EAAE,CAAA;YACrD,MAAM,OAAO,GAAG,SAAS,KAAK,EAAE,IAAI,SAAS,KAAK,SAAS,CAAA;YAE3D,OAAO,CAAC,IAAI,CAAC;gBACX,QAAQ,EAAE,YAAY;gBACtB,SAAS;gBACT,aAAa,EAAE,SAAS;gBACxB,OAAO;aACR,CAAC,CAAA;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,wEAAwE;YACxE,OAAO,CAAC,IAAI,CAAC;gBACX,QAAQ,EAAE,YAAY;gBACtB,SAAS,EAAE,EAAE;gBACb,aAAa,EAAE,eAAe,CAAC,YAAY,CAAC,IAAI,EAAE;gBAClD,OAAO,EAAE,KAAK;aACf,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,QAAgB;IAC7C,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IACzD,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACpE,CAAC"}
|
package/dist/integrityStore.d.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* integrityStore.ts — Local .intutic/integrity.json manager.
|
|
3
|
-
*
|
|
4
|
-
* Maintains a per-workspace integrity store that tracks the last sync
|
|
5
|
-
* timestamp, config version, and canonical file hashes. This allows
|
|
6
|
-
* the daemon to skip redundant syncs when the config version hasn't
|
|
7
|
-
* changed and to detect local drift between sync cycles.
|
|
8
|
-
*
|
|
9
|
-
* HLD §3.14 — Real-Time State Mirroring
|
|
10
|
-
* LLD #8 — Sync Daemon / CLI
|
|
11
|
-
*
|
|
12
|
-
* @module
|
|
13
|
-
*/
|
|
14
|
-
import type { IntegrityStore } from '@intutic/shared-types';
|
|
15
|
-
/**
|
|
16
|
-
* Load the local integrity store from `.intutic/integrity.json`.
|
|
17
|
-
*
|
|
18
|
-
* Returns `null` if the file doesn't exist (first sync) or is
|
|
19
|
-
* corrupted (will be overwritten on next save).
|
|
20
|
-
*
|
|
21
|
-
* @param workspaceRoot - Absolute path to the workspace root.
|
|
22
|
-
* @returns The parsed IntegrityStore, or null if not found.
|
|
23
|
-
*/
|
|
24
|
-
export declare function loadIntegrity(workspaceRoot: string): Promise<IntegrityStore | null>;
|
|
25
|
-
/**
|
|
26
|
-
* Save the integrity store to `.intutic/integrity.json`.
|
|
27
|
-
*
|
|
28
|
-
* Creates the `.intutic/` directory if it doesn't exist.
|
|
29
|
-
* Uses atomic write (tmp → rename) to prevent corruption.
|
|
30
|
-
*
|
|
31
|
-
* @param workspaceRoot - Absolute path to the workspace root.
|
|
32
|
-
* @param store - The IntegrityStore to persist.
|
|
33
|
-
*/
|
|
34
|
-
export declare function saveIntegrity(workspaceRoot: string, store: IntegrityStore): Promise<void>;
|
|
35
|
-
//# sourceMappingURL=integrityStore.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"integrityStore.d.ts","sourceRoot":"","sources":["../src/integrityStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAQ3D;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAqBhC;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,IAAI,CAAC,CAUf"}
|
package/dist/integrityStore.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* integrityStore.ts — Local .intutic/integrity.json manager.
|
|
3
|
-
*
|
|
4
|
-
* Maintains a per-workspace integrity store that tracks the last sync
|
|
5
|
-
* timestamp, config version, and canonical file hashes. This allows
|
|
6
|
-
* the daemon to skip redundant syncs when the config version hasn't
|
|
7
|
-
* changed and to detect local drift between sync cycles.
|
|
8
|
-
*
|
|
9
|
-
* HLD §3.14 — Real-Time State Mirroring
|
|
10
|
-
* LLD #8 — Sync Daemon / CLI
|
|
11
|
-
*
|
|
12
|
-
* @module
|
|
13
|
-
*/
|
|
14
|
-
import * as node_fs from 'node:fs/promises';
|
|
15
|
-
import * as node_path from 'node:path';
|
|
16
|
-
/** Filename for the integrity store within the `.intutic/` directory. */
|
|
17
|
-
const INTEGRITY_FILE = 'integrity.json';
|
|
18
|
-
/** Directory name for Intutic local state. */
|
|
19
|
-
const INTUTIC_DIR = '.intutic';
|
|
20
|
-
/**
|
|
21
|
-
* Load the local integrity store from `.intutic/integrity.json`.
|
|
22
|
-
*
|
|
23
|
-
* Returns `null` if the file doesn't exist (first sync) or is
|
|
24
|
-
* corrupted (will be overwritten on next save).
|
|
25
|
-
*
|
|
26
|
-
* @param workspaceRoot - Absolute path to the workspace root.
|
|
27
|
-
* @returns The parsed IntegrityStore, or null if not found.
|
|
28
|
-
*/
|
|
29
|
-
export async function loadIntegrity(workspaceRoot) {
|
|
30
|
-
const filePath = node_path.join(workspaceRoot, INTUTIC_DIR, INTEGRITY_FILE);
|
|
31
|
-
try {
|
|
32
|
-
const raw = await node_fs.readFile(filePath, 'utf-8');
|
|
33
|
-
const parsed = JSON.parse(raw);
|
|
34
|
-
// Basic shape validation
|
|
35
|
-
if (typeof parsed.lastSyncAt !== 'string' ||
|
|
36
|
-
typeof parsed.configVersion !== 'number' ||
|
|
37
|
-
typeof parsed.files !== 'object') {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
return parsed;
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
// File doesn't exist or is corrupted
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Save the integrity store to `.intutic/integrity.json`.
|
|
49
|
-
*
|
|
50
|
-
* Creates the `.intutic/` directory if it doesn't exist.
|
|
51
|
-
* Uses atomic write (tmp → rename) to prevent corruption.
|
|
52
|
-
*
|
|
53
|
-
* @param workspaceRoot - Absolute path to the workspace root.
|
|
54
|
-
* @param store - The IntegrityStore to persist.
|
|
55
|
-
*/
|
|
56
|
-
export async function saveIntegrity(workspaceRoot, store) {
|
|
57
|
-
const dir = node_path.join(workspaceRoot, INTUTIC_DIR);
|
|
58
|
-
await node_fs.mkdir(dir, { recursive: true });
|
|
59
|
-
const filePath = node_path.join(dir, INTEGRITY_FILE);
|
|
60
|
-
const tmpPath = `${filePath}.tmp`;
|
|
61
|
-
const content = JSON.stringify(store, null, 2) + '\n';
|
|
62
|
-
await node_fs.writeFile(tmpPath, content, 'utf-8');
|
|
63
|
-
await node_fs.rename(tmpPath, filePath);
|
|
64
|
-
}
|
|
65
|
-
// `loadContextIntegrity` / `saveContextIntegrity` were removed on 2026-07-30. They
|
|
66
|
-
// had no callers in either repo — not even tests — while
|
|
67
|
-
// `.intutic/context_integrity.json` sat in three harness hook denylists as a
|
|
68
|
-
// protected path. The file was never created, so those hooks guarded nothing. The
|
|
69
|
-
// config integrity store above already hashes every governed file `syncLoop` writes,
|
|
70
|
-
// which is what the second store would have duplicated.
|
|
71
|
-
//# sourceMappingURL=integrityStore.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"integrityStore.js","sourceRoot":"","sources":["../src/integrityStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,SAAS,MAAM,WAAW,CAAA;AAGtC,yEAAyE;AACzE,MAAM,cAAc,GAAG,gBAAgB,CAAA;AAEvC,8CAA8C;AAC9C,MAAM,WAAW,GAAG,UAAU,CAAA;AAE9B;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,aAAqB;IAErB,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,EAAE,cAAc,CAAC,CAAA;IAE3E,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QACrD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAmB,CAAA;QAEhD,yBAAyB;QACzB,IACE,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ;YACrC,OAAO,MAAM,CAAC,aAAa,KAAK,QAAQ;YACxC,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAChC,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,MAAM,CAAC;QACP,qCAAqC;QACrC,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,aAAqB,EACrB,KAAqB;IAErB,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAA;IACtD,MAAM,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAE7C,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;IACpD,MAAM,OAAO,GAAG,GAAG,QAAQ,MAAM,CAAA;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAA;IAErD,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IAClD,MAAM,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;AACzC,CAAC;AAGD,mFAAmF;AACnF,yDAAyD;AACzD,6EAA6E;AAC7E,kFAAkF;AAClF,qFAAqF;AACrF,wDAAwD"}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* gitWorktrees.ts — discovers every `git worktree` checkout of a repo the
|
|
3
|
-
* sync daemon is watching, so project-tier governance files can be written
|
|
4
|
-
* into each one, not just the main checkout.
|
|
5
|
-
*
|
|
6
|
-
* # The gap this closes
|
|
7
|
-
*
|
|
8
|
-
* `git worktree add <path>` creates a second, fully independent WORKING
|
|
9
|
-
* TREE that shares the main checkout's `.git` object store (via a `.git`
|
|
10
|
-
* FILE pointing back at `<main>/.git/worktrees/<name>`) but has its own
|
|
11
|
-
* untracked files. Every project-tier governance file this product writes
|
|
12
|
-
* — `.claude/settings.json`, `.cursor/hooks.json`, `.intutic/hooks/*`,
|
|
13
|
-
* `AGENTS.md`'s sibling hook registrations, the wrapped `.mcp.json` entries,
|
|
14
|
-
* etc. — is untracked by convention (SOP content is workspace-specific and
|
|
15
|
-
* synced from the control plane, not committed). That means none of it
|
|
16
|
-
* exists in a worktree's working tree by default: `writeConfigFiles`/
|
|
17
|
-
* `injectMcpServer` running against only the main checkout's `workspaceRoot`
|
|
18
|
-
* leaves every OTHER worktree of that same repo completely ungoverned,
|
|
19
|
-
* regardless of what the main checkout has configured.
|
|
20
|
-
*
|
|
21
|
-
* This was already true for any hand-rolled `git worktree` workflow before
|
|
22
|
-
* this module existed — Xirp (an orchestrator that spawns CLI agents each
|
|
23
|
-
* inside its own tmux session + git worktree, see `tools/cli/src/harness/
|
|
24
|
-
* xirp.ts`) is what surfaced it, but the fix here is general: it benefits
|
|
25
|
-
* ANY worktree-based workflow, Xirp-managed or not. See TD-390.
|
|
26
|
-
*
|
|
27
|
-
* # Verifying the mechanics for real
|
|
28
|
-
*
|
|
29
|
-
* Confirmed against a real throwaway repo during this module's development
|
|
30
|
-
* (not asserted from memory of git's docs): an untracked file written into
|
|
31
|
-
* a main checkout is NOT visible from a `git worktree add`-created sibling
|
|
32
|
-
* checkout's directory. `git worktree list --porcelain`'s block format,
|
|
33
|
-
* including `locked`/`prunable`/`bare`/`detached` fields, was captured from
|
|
34
|
-
* a real `git worktree list --porcelain` run (this module's own test suite
|
|
35
|
-
* builds the same kind of fixture, in an isolated temp directory, rather
|
|
36
|
-
* than relying on this description alone).
|
|
37
|
-
*
|
|
38
|
-
* @module
|
|
39
|
-
*/
|
|
40
|
-
/** One block of `git worktree list --porcelain` output, parsed. */
|
|
41
|
-
export interface WorktreeInfo {
|
|
42
|
-
/** Absolute path to this worktree's working directory. */
|
|
43
|
-
path: string;
|
|
44
|
-
/** Commit the worktree's HEAD points at, or null if not reported (bare). */
|
|
45
|
-
head: string | null;
|
|
46
|
-
/** Branch ref this worktree has checked out (e.g. `refs/heads/main`), or
|
|
47
|
-
* null when detached or bare. */
|
|
48
|
-
branch: string | null;
|
|
49
|
-
/** True if this worktree's HEAD is detached (no branch checked out). */
|
|
50
|
-
detached: boolean;
|
|
51
|
-
/** True for the bare-repository worktree entry — the repo root itself
|
|
52
|
-
* when it has no working tree of its own files (only ever the first
|
|
53
|
-
* entry, and only for a bare repo). */
|
|
54
|
-
bare: boolean;
|
|
55
|
-
/** True if this worktree is locked (`git worktree lock`) — git will not
|
|
56
|
-
* prune it even if its directory looks gone. Locking does not restrict
|
|
57
|
-
* reading or writing ordinary files in it, so this does not by itself
|
|
58
|
-
* change whether `discoverWorktrees` includes the path. */
|
|
59
|
-
locked: boolean;
|
|
60
|
-
/** Reason string passed to `git worktree lock --reason`, if any. */
|
|
61
|
-
lockedReason: string | null;
|
|
62
|
-
/** True if git has flagged this worktree's directory as missing/invalid
|
|
63
|
-
* and a candidate for `git worktree prune`. */
|
|
64
|
-
prunable: boolean;
|
|
65
|
-
/** Reason string git reports for why this worktree is prunable, if any. */
|
|
66
|
-
prunableReason: string | null;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Parses `git worktree list --porcelain` output.
|
|
70
|
-
*
|
|
71
|
-
* Real format (verified against a live `git worktree list --porcelain` run,
|
|
72
|
-
* git 2.x): one block per worktree, separated by a blank line, each line a
|
|
73
|
-
* bare keyword or `<keyword> <value>`:
|
|
74
|
-
*
|
|
75
|
-
* ```
|
|
76
|
-
* worktree /path/to/main
|
|
77
|
-
* HEAD 56bdba0a04f83da4e821a0a3e7a6208d43fcaec5
|
|
78
|
-
* branch refs/heads/master
|
|
79
|
-
*
|
|
80
|
-
* worktree /path/to/locked-wt
|
|
81
|
-
* HEAD 56bdba0a04f83da4e821a0a3e7a6208d43fcaec5
|
|
82
|
-
* branch refs/heads/feature2
|
|
83
|
-
* locked testing lock
|
|
84
|
-
*
|
|
85
|
-
* worktree /path/to/detached-wt
|
|
86
|
-
* HEAD 56bdba0a04f83da4e821a0a3e7a6208d43fcaec5
|
|
87
|
-
* detached
|
|
88
|
-
* ```
|
|
89
|
-
*
|
|
90
|
-
* Deliberately implemented with plain string methods (`startsWith`/`slice`)
|
|
91
|
-
* rather than a line-matching regex — this parses `git`-controlled, not
|
|
92
|
-
* attacker-controlled, input, but a sibling Wave 1 phase shipped a
|
|
93
|
-
* CodeQL-flagged polynomial-regex bug from exactly this kind of "just trim
|
|
94
|
-
* a path" text handling, so the same class of construct is avoided here on
|
|
95
|
-
* principle even though the input source differs.
|
|
96
|
-
*/
|
|
97
|
-
export declare function parseWorktreeListPorcelain(output: string): WorktreeInfo[];
|
|
98
|
-
/**
|
|
99
|
-
* Discovers every worktree of the git repository containing `repoRoot`,
|
|
100
|
-
* returning the absolute paths that should be treated as additional
|
|
101
|
-
* project-tier workspace roots.
|
|
102
|
-
*
|
|
103
|
-
* Filtering decisions, made explicit rather than left implicit:
|
|
104
|
-
*
|
|
105
|
-
* - **The main checkout is included.** `git worktree list` always lists it
|
|
106
|
-
* first (confirmed against a live run) — it needs no special-casing by
|
|
107
|
-
* callers; a caller that already writes to `repoRoot` directly can simply
|
|
108
|
-
* skip a returned path equal to `repoRoot` if it wants to avoid a
|
|
109
|
-
* redundant duplicate write, but the list is uniformly correct either way.
|
|
110
|
-
* - **Locked worktrees are included.** `git worktree lock` only prevents
|
|
111
|
-
* git's own pruning of a worktree it cannot otherwise verify still
|
|
112
|
-
* exists (e.g. on removable storage) — it says nothing about whether the
|
|
113
|
-
* directory is currently present and writable, which it normally is.
|
|
114
|
-
* Excluding locked worktrees would silently under-cover a workflow (like
|
|
115
|
-
* Xirp's) that locks worktrees deliberately to protect them from being
|
|
116
|
-
* pruned out from under a long-running session — exactly the worktrees
|
|
117
|
-
* most worth covering.
|
|
118
|
-
* - **Prunable worktrees are EXCLUDED.** `prunable` means git itself has
|
|
119
|
-
* flagged the worktree's directory as missing or otherwise administratively
|
|
120
|
-
* invalid. Writing into that path would either fail or (via this
|
|
121
|
-
* codebase's `mkdir(dir, { recursive: true })` write convention) silently
|
|
122
|
-
* RECREATE a directory git considers gone — resurrecting a deleted
|
|
123
|
-
* worktree's folder with governance files nobody asked for. Skipping it
|
|
124
|
-
* is what "don't write into a directory git says isn't really there"
|
|
125
|
-
* means in practice.
|
|
126
|
-
* - **Bare-repository entries are EXCLUDED.** A bare repo's own `worktree`
|
|
127
|
-
* porcelain entry names its root path but has no working tree of ordinary
|
|
128
|
-
* files to write project-tier config into.
|
|
129
|
-
*
|
|
130
|
-
* Best-effort by design: returns `[]` (never throws) if `repoRoot` is not
|
|
131
|
-
* inside a git repository, if `git` is not on `PATH`, or on any other
|
|
132
|
-
* failure — this is additive coverage on top of the existing single-root
|
|
133
|
-
* write path, so a git failure here must not break the sync cycle that
|
|
134
|
-
* already succeeds for the main `workspaceRoot`. This also means a
|
|
135
|
-
* non-worktree, single-checkout project (the common case) is a harmless
|
|
136
|
-
* no-extra-work path: `git worktree list` still runs, still succeeds, and
|
|
137
|
-
* returns exactly one entry (the main checkout itself).
|
|
138
|
-
*/
|
|
139
|
-
export declare function discoverWorktrees(repoRoot: string): Promise<string[]>;
|
|
140
|
-
//# sourceMappingURL=gitWorktrees.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gitWorktrees.d.ts","sourceRoot":"","sources":["../../src/lib/gitWorktrees.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAOH,mEAAmE;AACnE,MAAM,WAAW,YAAY;IAC3B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAA;IACZ,4EAA4E;IAC5E,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB;sCACkC;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,wEAAwE;IACxE,QAAQ,EAAE,OAAO,CAAA;IACjB;;4CAEwC;IACxC,IAAI,EAAE,OAAO,CAAA;IACb;;;gEAG4D;IAC5D,MAAM,EAAE,OAAO,CAAA;IACf,oEAAoE;IACpE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B;oDACgD;IAChD,QAAQ,EAAE,OAAO,CAAA;IACjB,2EAA2E;IAC3E,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE,CAuDzE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAgB3E"}
|
package/dist/lib/gitWorktrees.js
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* gitWorktrees.ts — discovers every `git worktree` checkout of a repo the
|
|
3
|
-
* sync daemon is watching, so project-tier governance files can be written
|
|
4
|
-
* into each one, not just the main checkout.
|
|
5
|
-
*
|
|
6
|
-
* # The gap this closes
|
|
7
|
-
*
|
|
8
|
-
* `git worktree add <path>` creates a second, fully independent WORKING
|
|
9
|
-
* TREE that shares the main checkout's `.git` object store (via a `.git`
|
|
10
|
-
* FILE pointing back at `<main>/.git/worktrees/<name>`) but has its own
|
|
11
|
-
* untracked files. Every project-tier governance file this product writes
|
|
12
|
-
* — `.claude/settings.json`, `.cursor/hooks.json`, `.intutic/hooks/*`,
|
|
13
|
-
* `AGENTS.md`'s sibling hook registrations, the wrapped `.mcp.json` entries,
|
|
14
|
-
* etc. — is untracked by convention (SOP content is workspace-specific and
|
|
15
|
-
* synced from the control plane, not committed). That means none of it
|
|
16
|
-
* exists in a worktree's working tree by default: `writeConfigFiles`/
|
|
17
|
-
* `injectMcpServer` running against only the main checkout's `workspaceRoot`
|
|
18
|
-
* leaves every OTHER worktree of that same repo completely ungoverned,
|
|
19
|
-
* regardless of what the main checkout has configured.
|
|
20
|
-
*
|
|
21
|
-
* This was already true for any hand-rolled `git worktree` workflow before
|
|
22
|
-
* this module existed — Xirp (an orchestrator that spawns CLI agents each
|
|
23
|
-
* inside its own tmux session + git worktree, see `tools/cli/src/harness/
|
|
24
|
-
* xirp.ts`) is what surfaced it, but the fix here is general: it benefits
|
|
25
|
-
* ANY worktree-based workflow, Xirp-managed or not. See TD-390.
|
|
26
|
-
*
|
|
27
|
-
* # Verifying the mechanics for real
|
|
28
|
-
*
|
|
29
|
-
* Confirmed against a real throwaway repo during this module's development
|
|
30
|
-
* (not asserted from memory of git's docs): an untracked file written into
|
|
31
|
-
* a main checkout is NOT visible from a `git worktree add`-created sibling
|
|
32
|
-
* checkout's directory. `git worktree list --porcelain`'s block format,
|
|
33
|
-
* including `locked`/`prunable`/`bare`/`detached` fields, was captured from
|
|
34
|
-
* a real `git worktree list --porcelain` run (this module's own test suite
|
|
35
|
-
* builds the same kind of fixture, in an isolated temp directory, rather
|
|
36
|
-
* than relying on this description alone).
|
|
37
|
-
*
|
|
38
|
-
* @module
|
|
39
|
-
*/
|
|
40
|
-
import { execFile as _execFile } from 'node:child_process';
|
|
41
|
-
import { promisify } from 'node:util';
|
|
42
|
-
const execFile = promisify(_execFile);
|
|
43
|
-
/**
|
|
44
|
-
* Parses `git worktree list --porcelain` output.
|
|
45
|
-
*
|
|
46
|
-
* Real format (verified against a live `git worktree list --porcelain` run,
|
|
47
|
-
* git 2.x): one block per worktree, separated by a blank line, each line a
|
|
48
|
-
* bare keyword or `<keyword> <value>`:
|
|
49
|
-
*
|
|
50
|
-
* ```
|
|
51
|
-
* worktree /path/to/main
|
|
52
|
-
* HEAD 56bdba0a04f83da4e821a0a3e7a6208d43fcaec5
|
|
53
|
-
* branch refs/heads/master
|
|
54
|
-
*
|
|
55
|
-
* worktree /path/to/locked-wt
|
|
56
|
-
* HEAD 56bdba0a04f83da4e821a0a3e7a6208d43fcaec5
|
|
57
|
-
* branch refs/heads/feature2
|
|
58
|
-
* locked testing lock
|
|
59
|
-
*
|
|
60
|
-
* worktree /path/to/detached-wt
|
|
61
|
-
* HEAD 56bdba0a04f83da4e821a0a3e7a6208d43fcaec5
|
|
62
|
-
* detached
|
|
63
|
-
* ```
|
|
64
|
-
*
|
|
65
|
-
* Deliberately implemented with plain string methods (`startsWith`/`slice`)
|
|
66
|
-
* rather than a line-matching regex — this parses `git`-controlled, not
|
|
67
|
-
* attacker-controlled, input, but a sibling Wave 1 phase shipped a
|
|
68
|
-
* CodeQL-flagged polynomial-regex bug from exactly this kind of "just trim
|
|
69
|
-
* a path" text handling, so the same class of construct is avoided here on
|
|
70
|
-
* principle even though the input source differs.
|
|
71
|
-
*/
|
|
72
|
-
export function parseWorktreeListPorcelain(output) {
|
|
73
|
-
const blocks = output.split('\n\n');
|
|
74
|
-
const worktrees = [];
|
|
75
|
-
for (const block of blocks) {
|
|
76
|
-
const trimmedBlock = block.trim();
|
|
77
|
-
if (!trimmedBlock)
|
|
78
|
-
continue;
|
|
79
|
-
let path = '';
|
|
80
|
-
let head = null;
|
|
81
|
-
let branch = null;
|
|
82
|
-
let detached = false;
|
|
83
|
-
let bare = false;
|
|
84
|
-
let locked = false;
|
|
85
|
-
let lockedReason = null;
|
|
86
|
-
let prunable = false;
|
|
87
|
-
let prunableReason = null;
|
|
88
|
-
for (const rawLine of trimmedBlock.split('\n')) {
|
|
89
|
-
const line = rawLine.trim();
|
|
90
|
-
if (!line)
|
|
91
|
-
continue;
|
|
92
|
-
if (line === 'bare') {
|
|
93
|
-
bare = true;
|
|
94
|
-
}
|
|
95
|
-
else if (line === 'detached') {
|
|
96
|
-
detached = true;
|
|
97
|
-
}
|
|
98
|
-
else if (line.startsWith('worktree ')) {
|
|
99
|
-
path = line.slice('worktree '.length).trim();
|
|
100
|
-
}
|
|
101
|
-
else if (line.startsWith('HEAD ')) {
|
|
102
|
-
head = line.slice('HEAD '.length).trim();
|
|
103
|
-
}
|
|
104
|
-
else if (line.startsWith('branch ')) {
|
|
105
|
-
branch = line.slice('branch '.length).trim();
|
|
106
|
-
}
|
|
107
|
-
else if (line === 'locked') {
|
|
108
|
-
locked = true;
|
|
109
|
-
}
|
|
110
|
-
else if (line.startsWith('locked ')) {
|
|
111
|
-
locked = true;
|
|
112
|
-
lockedReason = line.slice('locked '.length).trim() || null;
|
|
113
|
-
}
|
|
114
|
-
else if (line === 'prunable') {
|
|
115
|
-
prunable = true;
|
|
116
|
-
}
|
|
117
|
-
else if (line.startsWith('prunable ')) {
|
|
118
|
-
prunable = true;
|
|
119
|
-
prunableReason = line.slice('prunable '.length).trim() || null;
|
|
120
|
-
}
|
|
121
|
-
// Any other line is a porcelain field this parser does not know about
|
|
122
|
-
// yet (git has added a few over the years) — ignored rather than
|
|
123
|
-
// treated as an error, so a future git version adding a new field
|
|
124
|
-
// degrades gracefully instead of breaking discovery entirely.
|
|
125
|
-
}
|
|
126
|
-
if (path) {
|
|
127
|
-
worktrees.push({ path, head, branch, detached, bare, locked, lockedReason, prunable, prunableReason });
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
return worktrees;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Discovers every worktree of the git repository containing `repoRoot`,
|
|
134
|
-
* returning the absolute paths that should be treated as additional
|
|
135
|
-
* project-tier workspace roots.
|
|
136
|
-
*
|
|
137
|
-
* Filtering decisions, made explicit rather than left implicit:
|
|
138
|
-
*
|
|
139
|
-
* - **The main checkout is included.** `git worktree list` always lists it
|
|
140
|
-
* first (confirmed against a live run) — it needs no special-casing by
|
|
141
|
-
* callers; a caller that already writes to `repoRoot` directly can simply
|
|
142
|
-
* skip a returned path equal to `repoRoot` if it wants to avoid a
|
|
143
|
-
* redundant duplicate write, but the list is uniformly correct either way.
|
|
144
|
-
* - **Locked worktrees are included.** `git worktree lock` only prevents
|
|
145
|
-
* git's own pruning of a worktree it cannot otherwise verify still
|
|
146
|
-
* exists (e.g. on removable storage) — it says nothing about whether the
|
|
147
|
-
* directory is currently present and writable, which it normally is.
|
|
148
|
-
* Excluding locked worktrees would silently under-cover a workflow (like
|
|
149
|
-
* Xirp's) that locks worktrees deliberately to protect them from being
|
|
150
|
-
* pruned out from under a long-running session — exactly the worktrees
|
|
151
|
-
* most worth covering.
|
|
152
|
-
* - **Prunable worktrees are EXCLUDED.** `prunable` means git itself has
|
|
153
|
-
* flagged the worktree's directory as missing or otherwise administratively
|
|
154
|
-
* invalid. Writing into that path would either fail or (via this
|
|
155
|
-
* codebase's `mkdir(dir, { recursive: true })` write convention) silently
|
|
156
|
-
* RECREATE a directory git considers gone — resurrecting a deleted
|
|
157
|
-
* worktree's folder with governance files nobody asked for. Skipping it
|
|
158
|
-
* is what "don't write into a directory git says isn't really there"
|
|
159
|
-
* means in practice.
|
|
160
|
-
* - **Bare-repository entries are EXCLUDED.** A bare repo's own `worktree`
|
|
161
|
-
* porcelain entry names its root path but has no working tree of ordinary
|
|
162
|
-
* files to write project-tier config into.
|
|
163
|
-
*
|
|
164
|
-
* Best-effort by design: returns `[]` (never throws) if `repoRoot` is not
|
|
165
|
-
* inside a git repository, if `git` is not on `PATH`, or on any other
|
|
166
|
-
* failure — this is additive coverage on top of the existing single-root
|
|
167
|
-
* write path, so a git failure here must not break the sync cycle that
|
|
168
|
-
* already succeeds for the main `workspaceRoot`. This also means a
|
|
169
|
-
* non-worktree, single-checkout project (the common case) is a harmless
|
|
170
|
-
* no-extra-work path: `git worktree list` still runs, still succeeds, and
|
|
171
|
-
* returns exactly one entry (the main checkout itself).
|
|
172
|
-
*/
|
|
173
|
-
export async function discoverWorktrees(repoRoot) {
|
|
174
|
-
try {
|
|
175
|
-
const { stdout } = await execFile('git', ['worktree', 'list', '--porcelain'], {
|
|
176
|
-
cwd: repoRoot,
|
|
177
|
-
encoding: 'utf-8',
|
|
178
|
-
timeout: 5000,
|
|
179
|
-
});
|
|
180
|
-
return parseWorktreeListPorcelain(stdout)
|
|
181
|
-
.filter((wt) => !wt.bare && !wt.prunable)
|
|
182
|
-
.map((wt) => wt.path);
|
|
183
|
-
}
|
|
184
|
-
catch {
|
|
185
|
-
// Not a git repo, git not installed, or a transient failure — additive
|
|
186
|
-
// coverage, so this degrades to "no extra worktrees found", not a
|
|
187
|
-
// thrown error the caller must handle.
|
|
188
|
-
return [];
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
//# sourceMappingURL=gitWorktrees.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gitWorktrees.js","sourceRoot":"","sources":["../../src/lib/gitWorktrees.ts"],"names":[],"mappings":"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"}
|