@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
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* recognise.ts — how disconnect tells Intutic's entries from the user's.
|
|
3
|
+
*
|
|
4
|
+
* Every test here is on content Intutic writes and nothing else: a hook
|
|
5
|
+
* command that runs a gate script from an `.intutic/hooks/` directory, a
|
|
6
|
+
* rules file that starts with the generated header, a URL on the origin of
|
|
7
|
+
* the proxy connect pointed the harness at.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import * as node_fs from 'node:fs/promises';
|
|
12
|
+
import * as node_path from 'node:path';
|
|
13
|
+
import { HARNESS_RULES_FILES, proxyHost } from '@intutic/shared-types';
|
|
14
|
+
import { isObject } from './plan.js';
|
|
15
|
+
/** First line of every rules file Intutic generates. */
|
|
16
|
+
export const RULES_HEADER = '# Intutic Governance Rules (auto-generated)';
|
|
17
|
+
export function startsWithRulesHeader(text) {
|
|
18
|
+
return text.startsWith(RULES_HEADER);
|
|
19
|
+
}
|
|
20
|
+
/** Whether `text` mentions `marker`, for owned files recognised by a line Intutic writes in them. */
|
|
21
|
+
export function contains(marker) {
|
|
22
|
+
return (text) => text.includes(marker);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Whether `command` runs the gate script `script` from an `.intutic/hooks/`
|
|
26
|
+
* directory (any workspace's, or the home one) — however it is quoted or
|
|
27
|
+
* whichever interpreter runs it.
|
|
28
|
+
*/
|
|
29
|
+
export function runsGate(command, script) {
|
|
30
|
+
if (typeof command !== 'string')
|
|
31
|
+
return false;
|
|
32
|
+
const escaped = script.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
33
|
+
return new RegExp(`[\\\\/]\\.intutic[\\\\/]hooks[\\\\/]${escaped}(?=["'\\s]|$)`).test(command);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Whether a `{ matcher, hooks: [{ command }] }` entry is Intutic's: every
|
|
37
|
+
* hook in it runs `script`. The shape Claude Code, Codex, Continue, Muse,
|
|
38
|
+
* Gemini CLI and Pi share.
|
|
39
|
+
*/
|
|
40
|
+
export function isGateEntry(script) {
|
|
41
|
+
return (entry) => {
|
|
42
|
+
if (!isObject(entry) || !Array.isArray(entry.hooks) || entry.hooks.length === 0)
|
|
43
|
+
return false;
|
|
44
|
+
return entry.hooks.every((h) => isObject(h) && runsGate(h.command, script));
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** Whether a `{ command }` entry (Cursor, Windsurf) runs `script`. */
|
|
48
|
+
export function isGateCommandEntry(script) {
|
|
49
|
+
return (entry) => isObject(entry) && runsGate(entry.command, script);
|
|
50
|
+
}
|
|
51
|
+
/** Loopback hosts compare equal: connect writes `localhost` in one place and `127.0.0.1` in another. */
|
|
52
|
+
function originOf(value) {
|
|
53
|
+
try {
|
|
54
|
+
const url = new URL(value);
|
|
55
|
+
const host = url.hostname === 'localhost' || url.hostname === '[::1]' ? '127.0.0.1' : url.hostname;
|
|
56
|
+
const port = url.port || (url.protocol === 'https:' ? '443' : '80');
|
|
57
|
+
return `${url.protocol}//${host}:${port}`;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* A test for "this value is a URL on the Intutic proxy", given the proxy
|
|
65
|
+
* URLs connect is known to have written. Any path on the proxy's origin
|
|
66
|
+
* counts: connect writes the bare host for Anthropic SDKs, `/v1` for OpenAI
|
|
67
|
+
* ones, and a trailing slash for Continue.
|
|
68
|
+
*/
|
|
69
|
+
export function proxyUrlMatcher(proxyUrls) {
|
|
70
|
+
const origins = new Set(proxyUrls.map((u) => originOf(proxyHost(u))).filter((o) => o !== null));
|
|
71
|
+
return (value) => typeof value === 'string' && origins.size > 0 && origins.has(originOf(value) ?? '');
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Proxy URLs an earlier connect left in a workspace's own generated files:
|
|
75
|
+
* the "Proxy URL" line of a rules file and `INTUTIC_PROXY_URL` in
|
|
76
|
+
* `.env.intutic`. Used when connect predates the recorded list.
|
|
77
|
+
*/
|
|
78
|
+
export async function proxyUrlsInWorkspace(workspaceRoot) {
|
|
79
|
+
const found = new Set();
|
|
80
|
+
const files = [
|
|
81
|
+
...new Set(Object.values(HARNESS_RULES_FILES).flatMap((t) => (t.kind !== 'none' && t.scope === 'workspace' ? [t.path] : []))),
|
|
82
|
+
// Where earlier versions wrote the rules whole.
|
|
83
|
+
'CLAUDE.md',
|
|
84
|
+
'.cursorrules',
|
|
85
|
+
'.windsurfrules',
|
|
86
|
+
'.roorules',
|
|
87
|
+
'.env.intutic',
|
|
88
|
+
];
|
|
89
|
+
for (const rel of files) {
|
|
90
|
+
let text;
|
|
91
|
+
try {
|
|
92
|
+
text = await node_fs.readFile(node_path.join(workspaceRoot, rel), 'utf-8');
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
// A whole generated file, or one with the generated rules in it (a
|
|
98
|
+
// section, or after a rule file's front matter).
|
|
99
|
+
if (!text.includes(RULES_HEADER))
|
|
100
|
+
continue;
|
|
101
|
+
for (const m of text.matchAll(/^> \*\*Proxy URL:\*\* `([^`]+)`$/gm))
|
|
102
|
+
found.add(m[1]);
|
|
103
|
+
for (const m of text.matchAll(/^export INTUTIC_PROXY_URL="([^"]+)"$/gm))
|
|
104
|
+
found.add(m[1]);
|
|
105
|
+
}
|
|
106
|
+
return [...found];
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=recognise.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recognise.js","sourceRoot":"","sources":["../../src/disconnect/recognise.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tomlLines.ts — line-level TOML edits that keep the user's comments.
|
|
3
|
+
*
|
|
4
|
+
* Codex's and OpenHands' writers set a key or append a table by editing
|
|
5
|
+
* lines, so the user's comments survive; undoing them the same way keeps
|
|
6
|
+
* that promise. Only the shapes those writers produce are handled: a
|
|
7
|
+
* `key = value` line in the top level or in a `[table]`, and a whole table.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
interface Section {
|
|
12
|
+
/** Table name as written between the brackets, or null for the top level. */
|
|
13
|
+
name: string | null;
|
|
14
|
+
/** Index of the header line (-1 for the top level). */
|
|
15
|
+
header: number;
|
|
16
|
+
/** One past the last line of the section. */
|
|
17
|
+
end: number;
|
|
18
|
+
}
|
|
19
|
+
/** Splits lines into sections, ignoring `[` lines inside multi-line strings. */
|
|
20
|
+
export declare function tomlSections(lines: readonly string[]): Section[];
|
|
21
|
+
/** The value a one-line `key = value` assignment holds, or undefined when the line is not one. */
|
|
22
|
+
export declare function lineValue(line: string, key: string): unknown;
|
|
23
|
+
/** Index of `key`'s line in the first section named `table` (null: top level), or -1. */
|
|
24
|
+
export declare function findKeyLine(lines: readonly string[], table: string | null, key: string): number;
|
|
25
|
+
/**
|
|
26
|
+
* Removes the table named `table`, header to end, with the blank line a
|
|
27
|
+
* writer put before it when it appended the table.
|
|
28
|
+
*/
|
|
29
|
+
export declare function removeTable(lines: string[], table: string): boolean;
|
|
30
|
+
/** Removes a `[table]` header with nothing left under it but blank lines. */
|
|
31
|
+
export declare function removeEmptyTable(lines: string[], table: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Puts back one key a writer set. When the original text had the key in
|
|
34
|
+
* the same section its line is restored; otherwise the line is removed.
|
|
35
|
+
* Only a line whose value `isIntutic` recognises is touched.
|
|
36
|
+
*/
|
|
37
|
+
export declare function restoreKeyLine(lines: string[], table: string | null, key: string, originalLines: readonly string[] | null, isIntutic: (value: unknown) => boolean): boolean;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=tomlLines.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tomlLines.d.ts","sourceRoot":"","sources":["../../src/disconnect/tomlLines.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,UAAU,OAAO;IACf,6EAA6E;IAC7E,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAA;IACd,6CAA6C;IAC7C,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,EAAE,CAuBhE;AAED,kGAAkG;AAClG,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAO5D;AAED,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAO/F;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAOnE;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAKxE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EAAE,EACf,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,EACvC,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,GACrC,OAAO,CAWT"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tomlLines.ts — line-level TOML edits that keep the user's comments.
|
|
3
|
+
*
|
|
4
|
+
* Codex's and OpenHands' writers set a key or append a table by editing
|
|
5
|
+
* lines, so the user's comments survive; undoing them the same way keeps
|
|
6
|
+
* that promise. Only the shapes those writers produce are handled: a
|
|
7
|
+
* `key = value` line in the top level or in a `[table]`, and a whole table.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import { parse as parseToml } from 'smol-toml';
|
|
12
|
+
/** Splits lines into sections, ignoring `[` lines inside multi-line strings. */
|
|
13
|
+
export function tomlSections(lines) {
|
|
14
|
+
const sections = [{ name: null, header: -1, end: lines.length }];
|
|
15
|
+
let inString = null;
|
|
16
|
+
lines.forEach((line, i) => {
|
|
17
|
+
if (inString === null) {
|
|
18
|
+
// `[table]` or `[[array.of.tables]]`; the name is what is between the brackets.
|
|
19
|
+
const header = /^\s*\[\[?\s*([^\][]+?)\s*\]\]?\s*(#.*)?$/.exec(line);
|
|
20
|
+
if (header) {
|
|
21
|
+
sections[sections.length - 1].end = i;
|
|
22
|
+
sections.push({ name: header[1], header: i, end: lines.length });
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
for (const quote of ['"""', "'''"]) {
|
|
27
|
+
let at = line.indexOf(quote);
|
|
28
|
+
while (at !== -1) {
|
|
29
|
+
if (inString === null)
|
|
30
|
+
inString = quote;
|
|
31
|
+
else if (inString === quote)
|
|
32
|
+
inString = null;
|
|
33
|
+
at = line.indexOf(quote, at + 3);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
return sections;
|
|
38
|
+
}
|
|
39
|
+
/** The value a one-line `key = value` assignment holds, or undefined when the line is not one. */
|
|
40
|
+
export function lineValue(line, key) {
|
|
41
|
+
if (!new RegExp(`^\\s*${key}\\s*=`).test(line))
|
|
42
|
+
return undefined;
|
|
43
|
+
try {
|
|
44
|
+
return parseToml(line)[key];
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Index of `key`'s line in the first section named `table` (null: top level), or -1. */
|
|
51
|
+
export function findKeyLine(lines, table, key) {
|
|
52
|
+
const section = tomlSections(lines).find((s) => s.name === table);
|
|
53
|
+
if (!section)
|
|
54
|
+
return -1;
|
|
55
|
+
for (let i = section.header + 1; i < section.end; i++) {
|
|
56
|
+
if (lineValue(lines[i], key) !== undefined)
|
|
57
|
+
return i;
|
|
58
|
+
}
|
|
59
|
+
return -1;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Removes the table named `table`, header to end, with the blank line a
|
|
63
|
+
* writer put before it when it appended the table.
|
|
64
|
+
*/
|
|
65
|
+
export function removeTable(lines, table) {
|
|
66
|
+
const section = tomlSections(lines).find((s) => s.name === table);
|
|
67
|
+
if (!section)
|
|
68
|
+
return false;
|
|
69
|
+
let start = section.header;
|
|
70
|
+
if (start > 0 && lines[start - 1].trim() === '')
|
|
71
|
+
start--;
|
|
72
|
+
lines.splice(start, section.end - start);
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
/** Removes a `[table]` header with nothing left under it but blank lines. */
|
|
76
|
+
export function removeEmptyTable(lines, table) {
|
|
77
|
+
const section = tomlSections(lines).find((s) => s.name === table);
|
|
78
|
+
if (!section)
|
|
79
|
+
return false;
|
|
80
|
+
for (let i = section.header + 1; i < section.end; i++)
|
|
81
|
+
if (lines[i].trim() !== '')
|
|
82
|
+
return false;
|
|
83
|
+
return removeTable(lines, table);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Puts back one key a writer set. When the original text had the key in
|
|
87
|
+
* the same section its line is restored; otherwise the line is removed.
|
|
88
|
+
* Only a line whose value `isIntutic` recognises is touched.
|
|
89
|
+
*/
|
|
90
|
+
export function restoreKeyLine(lines, table, key, originalLines, isIntutic) {
|
|
91
|
+
const at = findKeyLine(lines, table, key);
|
|
92
|
+
if (at === -1 || !isIntutic(lineValue(lines[at], key)))
|
|
93
|
+
return false;
|
|
94
|
+
const was = originalLines ? findKeyLine(originalLines, table, key) : -1;
|
|
95
|
+
if (was !== -1) {
|
|
96
|
+
if (lines[at] === originalLines[was])
|
|
97
|
+
return false;
|
|
98
|
+
lines[at] = originalLines[was];
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
lines.splice(at, 1);
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=tomlLines.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tomlLines.js","sourceRoot":"","sources":["../../src/disconnect/tomlLines.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,8 +15,14 @@
|
|
|
15
15
|
* option; its model layer (LiteLLM) reads this variable, and wants the bare
|
|
16
16
|
* host because it appends `/v1/messages` itself. Entries the user set for
|
|
17
17
|
* other variables are kept.
|
|
18
|
-
* - `read:
|
|
19
|
-
* file (Aider's own mechanism for conventions), written
|
|
18
|
+
* - `read: <workspace>/.intutic/aider-sops.md` — the SOP text, as a
|
|
19
|
+
* read-only context file (Aider's own mechanism for conventions), written
|
|
20
|
+
* next to the config. The path is absolute: Aider resolves `read` entries
|
|
21
|
+
* against the directory it was started in (`Path(fn).expanduser().resolve()`,
|
|
22
|
+
* https://github.com/Aider-AI/aider/blob/main/aider/main.py), while it finds
|
|
23
|
+
* this config at the git root from any subdirectory
|
|
24
|
+
* (https://aider.chat/docs/config/aider_conf.html). A relative entry was
|
|
25
|
+
* missed whenever Aider ran below the workspace root.
|
|
20
26
|
*
|
|
21
27
|
* Earlier versions wrote `anthropic-api-base` and `extra-instructions`, which
|
|
22
28
|
* are not Aider options and stopped Aider from starting; both are removed.
|
|
@@ -26,13 +32,20 @@
|
|
|
26
32
|
* Each strip emits a governance_config_sanitized log entry visible in
|
|
27
33
|
* the control plane audit feed.
|
|
28
34
|
*
|
|
29
|
-
* LLD #14 — Phase 3 cross-harness defence
|
|
30
35
|
* HLD §3.14 — Three-Tier Defense Cascade
|
|
31
36
|
*
|
|
32
37
|
* @module
|
|
33
38
|
*/
|
|
34
|
-
/** SOP file, relative to the workspace root
|
|
39
|
+
/** SOP file, relative to the workspace root. */
|
|
35
40
|
export declare const AIDER_SOPS_FILE = ".intutic/aider-sops.md";
|
|
41
|
+
/** The decisions log's file, relative to the workspace root. */
|
|
42
|
+
export declare const AIDER_DECISIONS_FILE = ".intutic/aider-decisions.md";
|
|
43
|
+
/** Whether a `read` entry is the SOP file: the absolute path this version
|
|
44
|
+
* writes, or the workspace-relative one earlier versions wrote. */
|
|
45
|
+
export declare function isAiderSopsEntry(value: unknown, workspaceRoot: string): boolean;
|
|
46
|
+
/** Whether a `read` entry is one connect added: the SOP file or the decisions log's. */
|
|
47
|
+
export declare function isAiderIntuticEntry(value: unknown, workspaceRoot: string): boolean;
|
|
48
|
+
export declare function stripOwnHeader(raw: string): string;
|
|
36
49
|
/** Result of merging the Intutic keys into an Aider config's text. */
|
|
37
50
|
export interface AiderMergeResult {
|
|
38
51
|
/** New file content, or `null` when the file must be left untouched. */
|
|
@@ -43,11 +56,12 @@ export interface AiderMergeResult {
|
|
|
43
56
|
/**
|
|
44
57
|
* Merge the Intutic keys into the text of an `.aider.conf.yml`.
|
|
45
58
|
*
|
|
46
|
-
* @param raw
|
|
47
|
-
* @param proxyUrl
|
|
48
|
-
* @param
|
|
59
|
+
* @param raw - Current file content ('' when the file does not exist).
|
|
60
|
+
* @param proxyUrl - The proxy host (a trailing `/v1` is tolerated).
|
|
61
|
+
* @param workspaceRoot - The directory holding the config.
|
|
62
|
+
* @param hasSops - Whether the SOP file is to be listed under `read`.
|
|
49
63
|
*/
|
|
50
|
-
export declare function mergeAiderYaml(raw: string, proxyUrl: string, hasSops: boolean): AiderMergeResult;
|
|
64
|
+
export declare function mergeAiderYaml(raw: string, proxyUrl: string, workspaceRoot: string, hasSops: boolean): AiderMergeResult;
|
|
51
65
|
/**
|
|
52
66
|
* Merge Intutic governance settings into .aider.conf.yml.
|
|
53
67
|
*
|
|
@@ -60,4 +74,11 @@ export declare function mergeAiderYaml(raw: string, proxyUrl: string, hasSops: b
|
|
|
60
74
|
* untouched because it is not a YAML mapping (a warning is logged).
|
|
61
75
|
*/
|
|
62
76
|
export declare function mergeAiderConfig(configPath: string, proxyUrl: string, sopsText?: string): Promise<boolean>;
|
|
77
|
+
/**
|
|
78
|
+
* Lists `entry` (an absolute path) under `read:` in the `.aider.conf.yml` at
|
|
79
|
+
* `configPath`, keeping everything else in it: the decisions log's file,
|
|
80
|
+
* which Aider loads only if listed. A config that does not parse as a YAML
|
|
81
|
+
* mapping is left alone and reported.
|
|
82
|
+
*/
|
|
83
|
+
export declare function ensureAiderReadEntry(configPath: string, entry: string): Promise<void>;
|
|
63
84
|
//# sourceMappingURL=aiderConfigMerger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aiderConfigMerger.d.ts","sourceRoot":"","sources":["../../src/harness/aiderConfigMerger.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"aiderConfigMerger.d.ts","sourceRoot":"","sources":["../../src/harness/aiderConfigMerger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAoBH,gDAAgD;AAChD,eAAO,MAAM,eAAe,2BAA2B,CAAA;AAUvD,gEAAgE;AAChE,eAAO,MAAM,oBAAoB,gCAAgC,CAAA;AAEjE;oEACoE;AACpE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAE/E;AAED,wFAAwF;AACxF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAElF;AAMD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED,sEAAsE;AACtE,MAAM,WAAW,gBAAgB;IAC/B,wEAAwE;IACxE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAYD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,gBAAgB,CA2BvH;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CA8ClB;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB3F"}
|
|
@@ -15,8 +15,14 @@
|
|
|
15
15
|
* option; its model layer (LiteLLM) reads this variable, and wants the bare
|
|
16
16
|
* host because it appends `/v1/messages` itself. Entries the user set for
|
|
17
17
|
* other variables are kept.
|
|
18
|
-
* - `read:
|
|
19
|
-
* file (Aider's own mechanism for conventions), written
|
|
18
|
+
* - `read: <workspace>/.intutic/aider-sops.md` — the SOP text, as a
|
|
19
|
+
* read-only context file (Aider's own mechanism for conventions), written
|
|
20
|
+
* next to the config. The path is absolute: Aider resolves `read` entries
|
|
21
|
+
* against the directory it was started in (`Path(fn).expanduser().resolve()`,
|
|
22
|
+
* https://github.com/Aider-AI/aider/blob/main/aider/main.py), while it finds
|
|
23
|
+
* this config at the git root from any subdirectory
|
|
24
|
+
* (https://aider.chat/docs/config/aider_conf.html). A relative entry was
|
|
25
|
+
* missed whenever Aider ran below the workspace root.
|
|
20
26
|
*
|
|
21
27
|
* Earlier versions wrote `anthropic-api-base` and `extra-instructions`, which
|
|
22
28
|
* are not Aider options and stopped Aider from starting; both are removed.
|
|
@@ -26,7 +32,6 @@
|
|
|
26
32
|
* Each strip emits a governance_config_sanitized log entry visible in
|
|
27
33
|
* the control plane audit feed.
|
|
28
34
|
*
|
|
29
|
-
* LLD #14 — Phase 3 cross-harness defence
|
|
30
35
|
* HLD §3.14 — Three-Tier Defense Cascade
|
|
31
36
|
*
|
|
32
37
|
* @module
|
|
@@ -35,6 +40,7 @@ import * as fs from 'node:fs/promises';
|
|
|
35
40
|
import * as path from 'node:path';
|
|
36
41
|
import { parseDocument, isMap, isSeq, isScalar, YAMLSeq } from 'yaml';
|
|
37
42
|
import { createLogger } from '@intutic/logger';
|
|
43
|
+
import { keepOriginal } from '../disconnect/originals.js';
|
|
38
44
|
import { anthropicBaseUrl, openaiBaseUrl } from '@intutic/shared-types';
|
|
39
45
|
const log = createLogger('sync-aider-merger');
|
|
40
46
|
/**
|
|
@@ -44,7 +50,7 @@ const log = createLogger('sync-aider-merger');
|
|
|
44
50
|
const SUPPRESSED_KEYS = ['test-cmd', 'lint-cmd', 'auto-test', 'auto-lint', 'test_cmd', 'lint_cmd'];
|
|
45
51
|
/** Keys earlier versions wrote that Aider rejects as unrecognized arguments. */
|
|
46
52
|
const INVALID_LEGACY_KEYS = ['anthropic-api-base', 'extra-instructions'];
|
|
47
|
-
/** SOP file, relative to the workspace root
|
|
53
|
+
/** SOP file, relative to the workspace root. */
|
|
48
54
|
export const AIDER_SOPS_FILE = '.intutic/aider-sops.md';
|
|
49
55
|
/** Header written at the top of the file. Kept short: it sits above the
|
|
50
56
|
* user's own content, and is replaced, not stacked, on every sync. */
|
|
@@ -53,10 +59,21 @@ const HEADER = [
|
|
|
53
59
|
`# ${AIDER_SOPS_FILE} read entry are managed by intutic connect. test-cmd,`,
|
|
54
60
|
'# lint-cmd, auto-test and auto-lint are removed on every sync.',
|
|
55
61
|
];
|
|
62
|
+
/** The decisions log's file, relative to the workspace root. */
|
|
63
|
+
export const AIDER_DECISIONS_FILE = '.intutic/aider-decisions.md';
|
|
64
|
+
/** Whether a `read` entry is the SOP file: the absolute path this version
|
|
65
|
+
* writes, or the workspace-relative one earlier versions wrote. */
|
|
66
|
+
export function isAiderSopsEntry(value, workspaceRoot) {
|
|
67
|
+
return value === AIDER_SOPS_FILE || value === path.join(workspaceRoot, AIDER_SOPS_FILE);
|
|
68
|
+
}
|
|
69
|
+
/** Whether a `read` entry is one connect added: the SOP file or the decisions log's. */
|
|
70
|
+
export function isAiderIntuticEntry(value, workspaceRoot) {
|
|
71
|
+
return isAiderSopsEntry(value, workspaceRoot) || value === path.join(workspaceRoot, AIDER_DECISIONS_FILE);
|
|
72
|
+
}
|
|
56
73
|
/** Leading lines this product wrote (the header above, or the one earlier
|
|
57
74
|
* versions wrote), removed before the file is parsed. */
|
|
58
75
|
const OWN_HEADER_LINE = /^# (Intutic: |Intutic Governance Rules \(auto-generated|Last sync: |WARNING: test-cmd and lint-cmd keys are suppressed|\.intutic\/aider-sops\.md read entry|lint-cmd, auto-test and auto-lint are removed)/;
|
|
59
|
-
function stripOwnHeader(raw) {
|
|
76
|
+
export function stripOwnHeader(raw) {
|
|
60
77
|
const lines = raw.split('\n');
|
|
61
78
|
let i = 0;
|
|
62
79
|
while (i < lines.length && OWN_HEADER_LINE.test(lines[i]))
|
|
@@ -81,11 +98,12 @@ function ensureSeq(doc, key) {
|
|
|
81
98
|
/**
|
|
82
99
|
* Merge the Intutic keys into the text of an `.aider.conf.yml`.
|
|
83
100
|
*
|
|
84
|
-
* @param raw
|
|
85
|
-
* @param proxyUrl
|
|
86
|
-
* @param
|
|
101
|
+
* @param raw - Current file content ('' when the file does not exist).
|
|
102
|
+
* @param proxyUrl - The proxy host (a trailing `/v1` is tolerated).
|
|
103
|
+
* @param workspaceRoot - The directory holding the config.
|
|
104
|
+
* @param hasSops - Whether the SOP file is to be listed under `read`.
|
|
87
105
|
*/
|
|
88
|
-
export function mergeAiderYaml(raw, proxyUrl, hasSops) {
|
|
106
|
+
export function mergeAiderYaml(raw, proxyUrl, workspaceRoot, hasSops) {
|
|
89
107
|
const doc = parseDocument(stripOwnHeader(raw));
|
|
90
108
|
if (doc.errors.length > 0)
|
|
91
109
|
return { content: null, stripped: [] };
|
|
@@ -107,9 +125,9 @@ export function mergeAiderYaml(raw, proxyUrl, hasSops) {
|
|
|
107
125
|
});
|
|
108
126
|
setEnv.add(`ANTHROPIC_BASE_URL=${anthropicBaseUrl(proxyUrl)}`);
|
|
109
127
|
const read = ensureSeq(doc, 'read');
|
|
110
|
-
read.items = read.items.filter((item) => (isScalar(item) ? item.value : item
|
|
128
|
+
read.items = read.items.filter((item) => !isAiderSopsEntry(isScalar(item) ? item.value : item, workspaceRoot));
|
|
111
129
|
if (hasSops)
|
|
112
|
-
read.add(AIDER_SOPS_FILE);
|
|
130
|
+
read.add(path.join(workspaceRoot, AIDER_SOPS_FILE));
|
|
113
131
|
if (read.items.length === 0)
|
|
114
132
|
doc.delete('read');
|
|
115
133
|
return { content: `${HEADER.join('\n')}\n\n${doc.toString()}`, stripped };
|
|
@@ -134,7 +152,7 @@ export async function mergeAiderConfig(configPath, proxyUrl, sopsText) {
|
|
|
134
152
|
if (err.code !== 'ENOENT')
|
|
135
153
|
throw err;
|
|
136
154
|
}
|
|
137
|
-
const { content, stripped } = mergeAiderYaml(raw, proxyUrl, Boolean(sopsText));
|
|
155
|
+
const { content, stripped } = mergeAiderYaml(raw, proxyUrl, path.dirname(configPath), Boolean(sopsText));
|
|
138
156
|
if (content === null) {
|
|
139
157
|
log.warn({ action: 'aider_config_merge_skipped', path: configPath }, `${configPath} is not a YAML mapping — left untouched; fix it and the next sync will add the Intutic keys`);
|
|
140
158
|
return false;
|
|
@@ -154,10 +172,43 @@ export async function mergeAiderConfig(configPath, proxyUrl, sopsText) {
|
|
|
154
172
|
await fs.rm(sopsPath, { force: true });
|
|
155
173
|
}
|
|
156
174
|
const tmpPath = configPath + '.intutic-tmp';
|
|
175
|
+
// The config sits at the workspace root, so its directory is the workspace.
|
|
176
|
+
await keepOriginal(configPath, path.dirname(configPath));
|
|
157
177
|
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
158
178
|
await fs.writeFile(tmpPath, content, 'utf-8');
|
|
159
179
|
await fs.rename(tmpPath, configPath);
|
|
160
180
|
log.info({ action: 'aider_config_written', path: configPath, stripped }, 'Aider config merged with proxy URL and dangerous keys stripped');
|
|
161
181
|
return true;
|
|
162
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Lists `entry` (an absolute path) under `read:` in the `.aider.conf.yml` at
|
|
185
|
+
* `configPath`, keeping everything else in it: the decisions log's file,
|
|
186
|
+
* which Aider loads only if listed. A config that does not parse as a YAML
|
|
187
|
+
* mapping is left alone and reported.
|
|
188
|
+
*/
|
|
189
|
+
export async function ensureAiderReadEntry(configPath, entry) {
|
|
190
|
+
let raw = '';
|
|
191
|
+
try {
|
|
192
|
+
raw = await fs.readFile(configPath, 'utf-8');
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
if (err.code !== 'ENOENT')
|
|
196
|
+
throw err;
|
|
197
|
+
}
|
|
198
|
+
const doc = parseDocument(raw);
|
|
199
|
+
if (doc.contents === null && doc.errors.length === 0)
|
|
200
|
+
doc.contents = doc.createNode({});
|
|
201
|
+
if (doc.errors.length > 0 || !isMap(doc.contents)) {
|
|
202
|
+
log.warn({ action: 'aider_read_entry_skipped', path: configPath }, `${configPath} is not a YAML mapping — left untouched`);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const read = ensureSeq(doc, 'read');
|
|
206
|
+
if (read.items.some((item) => (isScalar(item) ? item.value : item) === entry))
|
|
207
|
+
return;
|
|
208
|
+
read.add(entry);
|
|
209
|
+
await keepOriginal(configPath, path.dirname(configPath));
|
|
210
|
+
const tmpPath = configPath + '.intutic-tmp';
|
|
211
|
+
await fs.writeFile(tmpPath, doc.toString(), 'utf-8');
|
|
212
|
+
await fs.rename(tmpPath, configPath);
|
|
213
|
+
}
|
|
163
214
|
//# sourceMappingURL=aiderConfigMerger.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aiderConfigMerger.js","sourceRoot":"","sources":["../../src/harness/aiderConfigMerger.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"aiderConfigMerger.js","sourceRoot":"","sources":["../../src/harness/aiderConfigMerger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAiB,MAAM,MAAM,CAAA;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AACzD,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAEvE,MAAM,GAAG,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAA;AAE7C;;;GAGG;AACH,MAAM,eAAe,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,CAAA;AAElG,gFAAgF;AAChF,MAAM,mBAAmB,GAAG,CAAC,oBAAoB,EAAE,oBAAoB,CAAC,CAAA;AAExE,gDAAgD;AAChD,MAAM,CAAC,MAAM,eAAe,GAAG,wBAAwB,CAAA;AAEvD;uEACuE;AACvE,MAAM,MAAM,GAAG;IACb,0EAA0E;IAC1E,KAAK,eAAe,uDAAuD;IAC3E,gEAAgE;CACjE,CAAA;AAED,gEAAgE;AAChE,MAAM,CAAC,MAAM,oBAAoB,GAAG,6BAA6B,CAAA;AAEjE;oEACoE;AACpE,MAAM,UAAU,gBAAgB,CAAC,KAAc,EAAE,aAAqB;IACpE,OAAO,KAAK,KAAK,eAAe,IAAI,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,CAAA;AACzF,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,mBAAmB,CAAC,KAAc,EAAE,aAAqB;IACvE,OAAO,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,oBAAoB,CAAC,CAAA;AAC3G,CAAC;AAED;0DAC0D;AAC1D,MAAM,eAAe,GAAG,4MAA4M,CAAA;AAEpO,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAC7B,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAAE,CAAC,EAAE,CAAA;IAC9D,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,GAAG,CAAA;IACvB,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,CAAC,EAAE,CAAA;IACtD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAClC,CAAC;AAUD,6EAA6E;AAC7E,SAAS,SAAS,CAAC,GAAa,EAAE,GAAW;IAC3C,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IAClC,IAAI,KAAK,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAA;IAClC,MAAM,GAAG,GAAG,IAAI,OAAO,EAAE,CAAA;IACzB,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,KAAK,EAAE;QAAE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC/F,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IACjB,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,QAAgB,EAAE,aAAqB,EAAE,OAAgB;IACnG,MAAM,GAAG,GAAa,aAAa,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAA;IACxD,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IACjE,wEAAwE;IACxE,yEAAyE;IACzE,6DAA6D;IAC7D,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI;QAAE,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;IAC5D,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IAEhE,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;IAC9D,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,QAAQ,EAAE,GAAG,mBAAmB,CAAC;QAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IAExE,GAAG,CAAC,GAAG,CAAC,iBAAiB,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEnD,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;IACxC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QAC1C,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;QAChD,OAAO,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAC,CAAA;IAChF,CAAC,CAAC,CAAA;IACF,MAAM,CAAC,GAAG,CAAC,sBAAsB,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;IAE9D,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;IACnC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAA;IAC9G,IAAI,OAAO;QAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC,CAAA;IAChE,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAE/C,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAA;AAC3E,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,UAAkB,EAClB,QAAgB,EAChB,QAAiB;IAEjB,IAAI,GAAG,GAAG,EAAE,CAAA;IACZ,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IAC9C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,GAAG,CAAA;IACjE,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,cAAc,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAA;IACxG,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,GAAG,CAAC,IAAI,CACN,EAAE,MAAM,EAAE,4BAA4B,EAAE,IAAI,EAAE,UAAU,EAAE,EAC1D,GAAG,UAAU,6FAA6F,CAC3G,CAAA;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,GAAG,CAAC,IAAI,CACN,EAAE,MAAM,EAAE,qBAAqB,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,EACnE,2DAA2D,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACjF,CAAA;IACH,CAAC;IAED,0EAA0E;IAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,eAAe,CAAC,CAAA;IACrE,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC3D,MAAM,OAAO,GAAG,QAAQ,GAAG,cAAc,CAAA;QACzC,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,GAAG,IAAI,EAAE,OAAO,CAAC,CAAA;QACrD,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;IACpC,CAAC;SAAM,CAAC;QACN,MAAM,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACxC,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,GAAG,cAAc,CAAA;IAC3C,4EAA4E;IAC5E,MAAM,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAA;IACxD,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC7D,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IAC7C,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;IAEpC,GAAG,CAAC,IAAI,CACN,EAAE,MAAM,EAAE,sBAAsB,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,EAC9D,gEAAgE,CACjE,CAAA;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,UAAkB,EAAE,KAAa;IAC1E,IAAI,GAAG,GAAG,EAAE,CAAA;IACZ,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IAC9C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,GAAG,CAAA;IACjE,CAAC;IACD,MAAM,GAAG,GAAa,aAAa,CAAC,GAAG,CAAC,CAAA;IACxC,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;IACvF,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClD,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,0BAA0B,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,GAAG,UAAU,yCAAyC,CAAC,CAAA;QAC1H,OAAM;IACR,CAAC;IACD,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;IACnC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC;QAAE,OAAM;IACrF,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IACf,MAAM,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAA;IACxD,MAAM,OAAO,GAAG,UAAU,GAAG,cAAc,CAAA;IAC3C,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAA;IACpD,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;AACtC,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* antigravityCliHooks.ts — Google Antigravity governance hook injection.
|
|
3
|
+
*
|
|
4
|
+
* Antigravity (the 2.0 desktop app, the IDE and Antigravity CLI, which
|
|
5
|
+
* replaced Gemini CLI for individual users in 2026) runs command hooks from
|
|
6
|
+
* `<workspace>/.agents/hooks.json` and `~/.gemini/config/hooks.json`
|
|
7
|
+
* (https://antigravity.google/docs/hooks/). This module:
|
|
8
|
+
*
|
|
9
|
+
* 1. Writes the gate script to `.intutic/hooks/antigravity-cli-check.js`.
|
|
10
|
+
* 2. Merges an `intutic-governance` entry into `~/.gemini/config/hooks.json`,
|
|
11
|
+
* keeping every other hook in the file. A file that is not a plain JSON
|
|
12
|
+
* object is left alone and reported.
|
|
13
|
+
*
|
|
14
|
+
* # The hook contract, from the documentation
|
|
15
|
+
*
|
|
16
|
+
* The file's top-level keys are hook names; each maps event names to
|
|
17
|
+
* handlers. `PreToolUse` takes `{matcher, hooks: [{type, command, timeout?}]}`
|
|
18
|
+
* entries, where a matcher of `"*"` applies to every tool. The command gets
|
|
19
|
+
* `{toolCall: {name, args}, conversationId, workspacePaths, ...}` on stdin,
|
|
20
|
+
* camelCase, with Antigravity's own tool names (`run_command` with
|
|
21
|
+
* `CommandLine`, `write_to_file` and `replace_file_content` with
|
|
22
|
+
* `TargetFile`). It refuses a call by printing
|
|
23
|
+
* `{"decision":"deny","reason":"..."}` on stdout — the same shape as Grok
|
|
24
|
+
* Build's, so the gate uses the `stdout-decision-deny` contract.
|
|
25
|
+
*
|
|
26
|
+
* On an allowed call the gate prints `{}`: a JSON object, which every hook
|
|
27
|
+
* must print, with no decision in it, so Antigravity's own permission
|
|
28
|
+
* settings decide. The documented values all change what the user sees:
|
|
29
|
+
* `allow` is documented to auto-approve the call past the permission prompts
|
|
30
|
+
* the user configured, `ask` and `force_ask` to prompt, and
|
|
31
|
+
* `deny_unless_prior_grant` to refuse what was never granted. The
|
|
32
|
+
* documentation marks `decision` as required without saying how a result
|
|
33
|
+
* without one is read, so it was read from Antigravity itself (2.21.1, its
|
|
34
|
+
* `language_server`): `decision` is an optional string, `{}` parses to an
|
|
35
|
+
* empty one, and an empty decision is the lowest-ranked result when several
|
|
36
|
+
* hooks answer (deny > force_ask > deny_unless_prior_grant > ask >
|
|
37
|
+
* auto_approve > allow > none), so it never overrides another hook, and the
|
|
38
|
+
* permission check skips it, leaving the call to the user's own permission
|
|
39
|
+
* settings. A decision Antigravity does not know is reported as an error.
|
|
40
|
+
*
|
|
41
|
+
* HLD §3.14 — Three-Tier Defense Cascade (Tier 1 Native Gating)
|
|
42
|
+
* @module
|
|
43
|
+
*/
|
|
44
|
+
/** The key Intutic owns in Antigravity's hooks file. */
|
|
45
|
+
export declare const ANTIGRAVITY_HOOK_NAME = "intutic-governance";
|
|
46
|
+
/** The gate script's file name in `.intutic/hooks/`. */
|
|
47
|
+
export declare const ANTIGRAVITY_CLI_GATE = "antigravity-cli-check.js";
|
|
48
|
+
/** `~/.gemini/config/hooks.json`, resolved at call time so a moved HOME is honoured. */
|
|
49
|
+
export declare function antigravityHooksPath(): string;
|
|
50
|
+
/** The `intutic-governance` entry for Antigravity's hooks file. */
|
|
51
|
+
export declare function buildAntigravityHookEntry(hookScriptPath: string): Record<string, unknown>;
|
|
52
|
+
/**
|
|
53
|
+
* Write the Antigravity gate script and merge its registration into
|
|
54
|
+
* `~/.gemini/config/hooks.json`.
|
|
55
|
+
*
|
|
56
|
+
* @param workspaceRoot - Absolute workspace root path.
|
|
57
|
+
* @param proxyUrl - Intutic proxy URL written into the script header.
|
|
58
|
+
* @param workspaceId - Workspace ID embedded in every hook event payload.
|
|
59
|
+
*/
|
|
60
|
+
export declare function writeAntigravityCliHooks(workspaceRoot: string, proxyUrl: string, workspaceId?: string): Promise<void>;
|
|
61
|
+
//# sourceMappingURL=antigravityCliHooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"antigravityCliHooks.d.ts","sourceRoot":"","sources":["../../src/harness/antigravityCliHooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAcH,wDAAwD;AACxD,eAAO,MAAM,qBAAqB,uBAAuB,CAAA;AAEzD,wDAAwD;AACxD,eAAO,MAAM,oBAAoB,6BAA6B,CAAA;AAE9D,wFAAwF;AACxF,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,mEAAmE;AACnE,wBAAgB,yBAAyB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAYzF;AAqGD;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAC5C,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,WAAW,SAAK,GACf,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
|