@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,207 @@
|
|
|
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
|
+
import * as fs from 'node:fs/promises';
|
|
45
|
+
import * as path from 'node:path';
|
|
46
|
+
import * as os from 'node:os';
|
|
47
|
+
import { createLogger } from '@intutic/logger';
|
|
48
|
+
import { keepOriginal } from '../disconnect/originals.js';
|
|
49
|
+
import { newIso } from '@intutic/id';
|
|
50
|
+
import { HOOK_TIMEOUT_SECONDS } from '@intutic/shared-types';
|
|
51
|
+
import { emitJsGate, emitJsFailClosedPrelude } from './gateBody.js';
|
|
52
|
+
import { readJsonObjectForMerge } from './jsonMergeTarget.js';
|
|
53
|
+
const log = createLogger('sync-antigravity-cli-hooks');
|
|
54
|
+
/** The key Intutic owns in Antigravity's hooks file. */
|
|
55
|
+
export const ANTIGRAVITY_HOOK_NAME = 'intutic-governance';
|
|
56
|
+
/** The gate script's file name in `.intutic/hooks/`. */
|
|
57
|
+
export const ANTIGRAVITY_CLI_GATE = 'antigravity-cli-check.js';
|
|
58
|
+
/** `~/.gemini/config/hooks.json`, resolved at call time so a moved HOME is honoured. */
|
|
59
|
+
export function antigravityHooksPath() {
|
|
60
|
+
return path.join(os.homedir(), '.gemini', 'config', 'hooks.json');
|
|
61
|
+
}
|
|
62
|
+
/** The `intutic-governance` entry for Antigravity's hooks file. */
|
|
63
|
+
export function buildAntigravityHookEntry(hookScriptPath) {
|
|
64
|
+
return {
|
|
65
|
+
enabled: true,
|
|
66
|
+
PreToolUse: [
|
|
67
|
+
{
|
|
68
|
+
// Every tool: the gate decides from the arguments, so a tool name
|
|
69
|
+
// nobody anticipated is still evaluated.
|
|
70
|
+
matcher: '*',
|
|
71
|
+
hooks: [{ type: 'command', command: `node ${JSON.stringify(hookScriptPath)}`, timeout: HOOK_TIMEOUT_SECONDS }],
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function buildHookScript(proxyUrl, workspaceRoot, workspaceId) {
|
|
77
|
+
const hookEventsLog = path.join(workspaceRoot, '.intutic', 'events', 'hook-events.jsonl');
|
|
78
|
+
return `#!/usr/bin/env node
|
|
79
|
+
/**
|
|
80
|
+
* Intutic Antigravity governance gate.
|
|
81
|
+
* Auto-generated by intutic sync-daemon. DO NOT EDIT.
|
|
82
|
+
* Proxy: ${proxyUrl}
|
|
83
|
+
* Generated: ${newIso()}
|
|
84
|
+
*/
|
|
85
|
+
${emitJsFailClosedPrelude({ harness: 'antigravity', contract: 'stdout-decision-deny', documentedFieldsOnly: true })}
|
|
86
|
+
const fs = require('fs');
|
|
87
|
+
const crypto = require('crypto');
|
|
88
|
+
const https = require('https');
|
|
89
|
+
|
|
90
|
+
// Runtime credentials
|
|
91
|
+
const _runtimeEnvPath = require('path').join(require('os').homedir(), '.intutic', 'env', 'runtime.env');
|
|
92
|
+
let _intuticHost = 'https://api.intutic.ai', _intuticKey = '', _intuticWsId = ${JSON.stringify(workspaceId)};
|
|
93
|
+
try {
|
|
94
|
+
fs.readFileSync(_runtimeEnvPath, 'utf-8').split('\\n').forEach(line => {
|
|
95
|
+
const eq = line.indexOf('='); if (eq < 0) return;
|
|
96
|
+
const k = line.slice(0, eq).trim(), v = line.slice(eq + 1).trim();
|
|
97
|
+
if (k === 'INTUTIC_HOST' && v) _intuticHost = v;
|
|
98
|
+
if (k === 'INTUTIC_API_KEY' && v) _intuticKey = v;
|
|
99
|
+
if (k === 'INTUTIC_WORKSPACE_ID' && v) _intuticWsId = v;
|
|
100
|
+
});
|
|
101
|
+
} catch {}
|
|
102
|
+
|
|
103
|
+
${emitJsGate({ harness: 'antigravity', contract: 'stdout-decision-deny', documentedFieldsOnly: true })}
|
|
104
|
+
|
|
105
|
+
let _intuticSessionId = '';
|
|
106
|
+
function logEvent(verdict, toolName, reason) {
|
|
107
|
+
try {
|
|
108
|
+
const ts = new Date().toISOString();
|
|
109
|
+
const incidentId = crypto.createHash('sha1').update(ts + toolName + _intuticWsId).digest('hex').slice(0, 16);
|
|
110
|
+
// The event's id: random, made once here, and resent with the line it is
|
|
111
|
+
// written into, so the control plane processes the event once.
|
|
112
|
+
const eventId = crypto.randomBytes(16).toString('hex');
|
|
113
|
+
const entry = JSON.stringify({
|
|
114
|
+
event: verdict,
|
|
115
|
+
toolName, reason: reason || '',
|
|
116
|
+
workspaceId: _intuticWsId,
|
|
117
|
+
harnessType: 'antigravity',
|
|
118
|
+
timestamp: ts,
|
|
119
|
+
incidentId,
|
|
120
|
+
eventId,
|
|
121
|
+
...(_intuticSessionId ? { sessionId: _intuticSessionId } : {}),
|
|
122
|
+
}) + '\\n';
|
|
123
|
+
fs.appendFileSync(${JSON.stringify(hookEventsLog)}, entry, { flag: 'a' });
|
|
124
|
+
if (_intuticKey) {
|
|
125
|
+
try {
|
|
126
|
+
const body = JSON.stringify({ events: [JSON.parse(entry)] });
|
|
127
|
+
const urlObj = new URL('/api/v1/hook-events', _intuticHost);
|
|
128
|
+
const mod = urlObj.protocol === 'https:' ? https : require('http');
|
|
129
|
+
const req = mod.request({ hostname: urlObj.hostname, port: urlObj.port || 443, path: urlObj.pathname, method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body), 'Authorization': 'Bearer ' + _intuticKey } });
|
|
130
|
+
req.on('error', () => { /* fire-and-forget */ });
|
|
131
|
+
req.write(body); req.end();
|
|
132
|
+
} catch { /* never crash the hook */ }
|
|
133
|
+
}
|
|
134
|
+
} catch { /* never crash the hook */ }
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let raw = '';
|
|
138
|
+
process.stdin.on('data', (c) => { raw += c; });
|
|
139
|
+
process.stdin.on('end', () => {
|
|
140
|
+
try {
|
|
141
|
+
const ctx = JSON.parse(raw);
|
|
142
|
+
_intuticSessionId = ctx.conversationId || ctx.session_id || '';
|
|
143
|
+
// Antigravity sends {toolCall: {name, args}}; the Claude-Code-shaped
|
|
144
|
+
// fields are read too, so the shared gate test matrix drives this gate
|
|
145
|
+
// with the payload it sends every other one.
|
|
146
|
+
intuticGuardEnvelope(ctx, ['toolCall', 'tool_name', 'tool_input'], logEvent);
|
|
147
|
+
const call = (ctx.toolCall && typeof ctx.toolCall === 'object') ? ctx.toolCall : {};
|
|
148
|
+
const toolName = call.name || ctx.tool_name || 'tool';
|
|
149
|
+
const input = call.args || ctx.tool_input || {};
|
|
150
|
+
|
|
151
|
+
const targetPath = input.TargetFile || input.AbsolutePath || input.path || input.file_path ||
|
|
152
|
+
input.filePath || input.target || '';
|
|
153
|
+
const command = input.CommandLine || input.command || input.cmd || '';
|
|
154
|
+
|
|
155
|
+
intuticGate(toolName, targetPath, command, logEvent, _intuticWsId, input);
|
|
156
|
+
|
|
157
|
+
// Allow: a result with no decision in it, so the user's own permission
|
|
158
|
+
// settings decide (see the module doc).
|
|
159
|
+
logEvent('tool_allowed', toolName, '');
|
|
160
|
+
process.stdout.write('{}\\n');
|
|
161
|
+
process.exit(0);
|
|
162
|
+
} catch (err) {
|
|
163
|
+
// Fail CLOSED — the stdout-decision-deny contract, even on a crash inside
|
|
164
|
+
// this handler (the module-level prelude above covers crashes outside it).
|
|
165
|
+
const errMsg = String(err);
|
|
166
|
+
process.stderr.write('[Intutic Governance] Hook error (fail-closed): ' + errMsg + '\\n');
|
|
167
|
+
logEvent('tool_blocked', 'unknown', errMsg);
|
|
168
|
+
process.stdout.write(JSON.stringify({ decision: 'deny', reason: '[Intutic Governance] Hook error (fail-closed): ' + errMsg + ' (refusal code GATE_CRASHED)' }) + '\\n');
|
|
169
|
+
process.exit(0);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
`;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Write the Antigravity gate script and merge its registration into
|
|
176
|
+
* `~/.gemini/config/hooks.json`.
|
|
177
|
+
*
|
|
178
|
+
* @param workspaceRoot - Absolute workspace root path.
|
|
179
|
+
* @param proxyUrl - Intutic proxy URL written into the script header.
|
|
180
|
+
* @param workspaceId - Workspace ID embedded in every hook event payload.
|
|
181
|
+
*/
|
|
182
|
+
export async function writeAntigravityCliHooks(workspaceRoot, proxyUrl, workspaceId = '') {
|
|
183
|
+
const hookScriptDir = path.join(workspaceRoot, '.intutic', 'hooks');
|
|
184
|
+
const hooksFile = antigravityHooksPath();
|
|
185
|
+
await keepOriginal(hooksFile, workspaceRoot);
|
|
186
|
+
await Promise.all([
|
|
187
|
+
fs.mkdir(hookScriptDir, { recursive: true }),
|
|
188
|
+
fs.mkdir(path.join(workspaceRoot, '.intutic', 'events'), { recursive: true }),
|
|
189
|
+
fs.mkdir(path.dirname(hooksFile), { recursive: true }),
|
|
190
|
+
]);
|
|
191
|
+
const hookScriptPath = path.join(hookScriptDir, ANTIGRAVITY_CLI_GATE);
|
|
192
|
+
const tmpScript = hookScriptPath + '.intutic-tmp';
|
|
193
|
+
await fs.writeFile(tmpScript, buildHookScript(proxyUrl, workspaceRoot, workspaceId), 'utf-8');
|
|
194
|
+
await fs.rename(tmpScript, hookScriptPath);
|
|
195
|
+
await fs.chmod(hookScriptPath, 0o755);
|
|
196
|
+
log.info({ action: 'antigravity_cli_hook_script_written', path: hookScriptPath }, 'Antigravity hook script written');
|
|
197
|
+
const existing = await readJsonObjectForMerge(hooksFile);
|
|
198
|
+
if (existing === null)
|
|
199
|
+
return;
|
|
200
|
+
// Only Intutic's own key is replaced; every hook the user registered stays.
|
|
201
|
+
const merged = { ...existing, [ANTIGRAVITY_HOOK_NAME]: buildAntigravityHookEntry(hookScriptPath) };
|
|
202
|
+
const tmp = hooksFile + '.intutic-tmp';
|
|
203
|
+
await fs.writeFile(tmp, JSON.stringify(merged, null, 2) + '\n', 'utf-8');
|
|
204
|
+
await fs.rename(tmp, hooksFile);
|
|
205
|
+
log.info({ action: 'antigravity_cli_hooks_written', path: hooksFile }, 'Merged Intutic PreToolUse hook into ~/.gemini/config/hooks.json');
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=antigravityCliHooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"antigravityCliHooks.js","sourceRoot":"","sources":["../../src/harness/antigravityCliHooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,14 +25,24 @@
|
|
|
25
25
|
*
|
|
26
26
|
* Hook events:
|
|
27
27
|
* Every block/allow is appended to `.intutic/events/hook-events.jsonl`
|
|
28
|
-
* and drained to the control plane via FSEvents-driven drain
|
|
28
|
+
* and drained to the control plane via FSEvents-driven drain, under the
|
|
29
|
+
* gate id `gemini-cli` rather than the harness id: the Antigravity gate
|
|
30
|
+
* reports as `antigravity`, so liveness, the AI inventory and SIEM can tell
|
|
31
|
+
* the two products apart (gateIdentity.ts in @intutic/shared-types).
|
|
29
32
|
*
|
|
30
|
-
* LLD #14 — Phase 3 cross-harness defence (Gap 3)
|
|
31
33
|
* HLD §3.14 — Three-Tier Defense Cascade (Tier 1 Native Gating)
|
|
32
34
|
* HLD §3.x — Gemini CLI / Antigravity harness
|
|
33
35
|
*
|
|
34
36
|
* @module
|
|
35
37
|
*/
|
|
38
|
+
/**
|
|
39
|
+
* The `BeforeTool` entry that registers the gate: a catch-all matcher, since
|
|
40
|
+
* the gate decides from the arguments and a tool name nobody anticipated is
|
|
41
|
+
* still evaluated. Shared with the MDM manifest, so the two cannot drift.
|
|
42
|
+
* Gemini CLI's \`timeout\` is in milliseconds (default 60 000), and it runs a
|
|
43
|
+
* call whose hook times out; the gate refuses at its own deadline inside it.
|
|
44
|
+
*/
|
|
45
|
+
export declare function buildGeminiBeforeToolEntry(hookScriptPath: string): Record<string, unknown>;
|
|
36
46
|
/**
|
|
37
47
|
* Write the Antigravity (Gemini CLI) governance hook script and merge
|
|
38
48
|
* hook configuration into `~/.gemini/settings.json`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"antigravityHooks.d.ts","sourceRoot":"","sources":["../../src/harness/antigravityHooks.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"antigravityHooks.d.ts","sourceRoot":"","sources":["../../src/harness/antigravityHooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AA4FH;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAU1F;AAQD;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,WAAW,SAAK,GACf,OAAO,CAAC,IAAI,CAAC,CAmEf"}
|
|
@@ -25,9 +25,11 @@
|
|
|
25
25
|
*
|
|
26
26
|
* Hook events:
|
|
27
27
|
* Every block/allow is appended to `.intutic/events/hook-events.jsonl`
|
|
28
|
-
* and drained to the control plane via FSEvents-driven drain
|
|
28
|
+
* and drained to the control plane via FSEvents-driven drain, under the
|
|
29
|
+
* gate id `gemini-cli` rather than the harness id: the Antigravity gate
|
|
30
|
+
* reports as `antigravity`, so liveness, the AI inventory and SIEM can tell
|
|
31
|
+
* the two products apart (gateIdentity.ts in @intutic/shared-types).
|
|
29
32
|
*
|
|
30
|
-
* LLD #14 — Phase 3 cross-harness defence (Gap 3)
|
|
31
33
|
* HLD §3.14 — Three-Tier Defense Cascade (Tier 1 Native Gating)
|
|
32
34
|
* HLD §3.x — Gemini CLI / Antigravity harness
|
|
33
35
|
*
|
|
@@ -37,8 +39,10 @@ import * as fs from 'node:fs/promises';
|
|
|
37
39
|
import * as path from 'node:path';
|
|
38
40
|
import * as os from 'node:os';
|
|
39
41
|
import { createLogger } from '@intutic/logger';
|
|
42
|
+
import { keepOriginal } from '../disconnect/originals.js';
|
|
40
43
|
import { newIso } from '@intutic/id';
|
|
41
|
-
import {
|
|
44
|
+
import { GEMINI_CLI_GATE_ID, HOOK_TIMEOUT_SECONDS } from '@intutic/shared-types';
|
|
45
|
+
import { emitShellGate, SHELL_EXTRACT, emitShellFailClosed } from './gateBody.js';
|
|
42
46
|
import { readJsonObjectForMerge } from './jsonMergeTarget.js';
|
|
43
47
|
const log = createLogger('sync-antigravity-hooks');
|
|
44
48
|
/** Governance-sensitive paths that the hook gate protects. */
|
|
@@ -52,7 +56,7 @@ function buildAntigravityCheckScript(proxyUrl, workspaceRoot, workspaceId) {
|
|
|
52
56
|
# Generated: ${newIso()}
|
|
53
57
|
# Workspace: ${workspaceId}
|
|
54
58
|
set -euo pipefail
|
|
55
|
-
${
|
|
59
|
+
${emitShellFailClosed(GEMINI_CLI_GATE_ID)}
|
|
56
60
|
INPUT="$(cat)"
|
|
57
61
|
${SHELL_EXTRACT}
|
|
58
62
|
|
|
@@ -92,7 +96,11 @@ log_event() {
|
|
|
92
96
|
ws="\${ws//\\\\/\\\\\\\\}"; ws="\${ws//\\"/\\\\\\"}"; ws="\${ws//[\$'\\x01'-\$'\\x1f']/ }"
|
|
93
97
|
local ts; ts="\$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
94
98
|
local incident_id; incident_id="\$(printf '%s' "\${ts}\${tool}\${INTUTIC_WORKSPACE_ID}" | sha1sum 2>/dev/null | cut -c1-16 || echo \"\$(date +%s)\")"
|
|
95
|
-
|
|
99
|
+
# The event's id: random, made once here, and resent with the line it is
|
|
100
|
+
# written into, so the control plane processes the event once.
|
|
101
|
+
local event_id; event_id="\$(od -An -N16 -tx1 /dev/urandom 2>/dev/null | tr -d ' \\n' || true)"
|
|
102
|
+
[ -n "\$event_id" ] || event_id="\$(date +%s)\$\$\${RANDOM}\${RANDOM}\${RANDOM}"
|
|
103
|
+
local entry="{\\"event\\":\\"\${verdict}\\",\\"toolName\\":\\"\${tool}\\",\\"reason\\":\\"\${reason}\\",\\"workspaceId\\":\\"\${ws}\\",\\"harnessType\\":\\"${GEMINI_CLI_GATE_ID}\\",\\"timestamp\\":\\"\${ts}\\",\\"incidentId\\":\\"\${incident_id}\\",\\"eventId\\":\\"\${event_id}\\"}"
|
|
96
104
|
printf '%s\\n' "\$entry" >> "\$HOOK_EVENTS_LOG" 2>/dev/null || true
|
|
97
105
|
if [ -n "\$INTUTIC_API_KEY" ]; then
|
|
98
106
|
curl -s -o /dev/null --max-time 3 -X POST \\
|
|
@@ -103,11 +111,32 @@ log_event() {
|
|
|
103
111
|
fi
|
|
104
112
|
}
|
|
105
113
|
|
|
106
|
-
${emitShellGate({ harness:
|
|
114
|
+
${emitShellGate({ harness: GEMINI_CLI_GATE_ID })}
|
|
107
115
|
log_event "tool_allowed" "$TOOL_NAME" ""
|
|
108
116
|
exit 0
|
|
109
117
|
`;
|
|
110
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* The `BeforeTool` entry that registers the gate: a catch-all matcher, since
|
|
121
|
+
* the gate decides from the arguments and a tool name nobody anticipated is
|
|
122
|
+
* still evaluated. Shared with the MDM manifest, so the two cannot drift.
|
|
123
|
+
* Gemini CLI's \`timeout\` is in milliseconds (default 60 000), and it runs a
|
|
124
|
+
* call whose hook times out; the gate refuses at its own deadline inside it.
|
|
125
|
+
*/
|
|
126
|
+
export function buildGeminiBeforeToolEntry(hookScriptPath) {
|
|
127
|
+
return {
|
|
128
|
+
matcher: '.*',
|
|
129
|
+
hooks: [{
|
|
130
|
+
name: 'intutic-governance',
|
|
131
|
+
type: 'command',
|
|
132
|
+
command: geminiGateCommand(hookScriptPath),
|
|
133
|
+
timeout: HOOK_TIMEOUT_SECONDS * 1000,
|
|
134
|
+
}],
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function geminiGateCommand(hookScriptPath) {
|
|
138
|
+
return `bash ${JSON.stringify(hookScriptPath)}`;
|
|
139
|
+
}
|
|
111
140
|
// ─── Main export ──────────────────────────────────────────────────────────────
|
|
112
141
|
/**
|
|
113
142
|
* Write the Antigravity (Gemini CLI) governance hook script and merge
|
|
@@ -126,6 +155,7 @@ export async function writeAntigravityHooks(workspaceRoot, proxyUrl, workspaceId
|
|
|
126
155
|
const hookEventsDir = path.join(workspaceRoot, '.intutic', 'events');
|
|
127
156
|
// homedir() read at call time so tests that move HOME are honoured.
|
|
128
157
|
const geminiSettings = path.join(os.homedir(), '.gemini', 'settings.json');
|
|
158
|
+
await keepOriginal(geminiSettings, workspaceRoot);
|
|
129
159
|
await Promise.all([
|
|
130
160
|
fs.mkdir(hookScriptDir, { recursive: true }),
|
|
131
161
|
fs.mkdir(hookEventsDir, { recursive: true }),
|
|
@@ -152,7 +182,7 @@ export async function writeAntigravityHooks(workspaceRoot, proxyUrl, workspaceId
|
|
|
152
182
|
const existingBeforeTool = Array.isArray(keptHooks.BeforeTool) ? keptHooks.BeforeTool : [];
|
|
153
183
|
// De-duplicated by command, so repeated syncs replace this entry rather than
|
|
154
184
|
// stacking copies, and every hook the user registered is kept.
|
|
155
|
-
const intuticCmd =
|
|
185
|
+
const intuticCmd = geminiGateCommand(hookScriptPath);
|
|
156
186
|
const filtered = existingBeforeTool.filter((entry) => {
|
|
157
187
|
if (typeof entry !== 'object' || entry === null)
|
|
158
188
|
return true;
|
|
@@ -164,15 +194,7 @@ export async function writeAntigravityHooks(workspaceRoot, proxyUrl, workspaceId
|
|
|
164
194
|
...existingSettings,
|
|
165
195
|
hooks: {
|
|
166
196
|
...keptHooks,
|
|
167
|
-
BeforeTool: [
|
|
168
|
-
...filtered,
|
|
169
|
-
{
|
|
170
|
-
// Catch-all: the gate decides from the arguments, so a tool name
|
|
171
|
-
// nobody anticipated is still evaluated.
|
|
172
|
-
matcher: '.*',
|
|
173
|
-
hooks: [{ name: 'intutic-governance', type: 'command', command: intuticCmd }],
|
|
174
|
-
},
|
|
175
|
-
],
|
|
197
|
+
BeforeTool: [...filtered, buildGeminiBeforeToolEntry(hookScriptPath)],
|
|
176
198
|
},
|
|
177
199
|
};
|
|
178
200
|
const tmpSettings = geminiSettings + '.intutic-tmp';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"antigravityHooks.js","sourceRoot":"","sources":["../../src/harness/antigravityHooks.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"antigravityHooks.js","sourceRoot":"","sources":["../../src/harness/antigravityHooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* antigravityProducts.ts — which of the two Google products behind the
|
|
3
|
+
* `antigravity` harness are on this machine.
|
|
4
|
+
*
|
|
5
|
+
* The harness installs two gates: Google Antigravity's (`PreToolUse` in
|
|
6
|
+
* `~/.gemini/config/hooks.json`) and Gemini CLI's (`BeforeTool` in
|
|
7
|
+
* `~/.gemini/settings.json`). Each reports under its own gate id
|
|
8
|
+
* (`gateIdentitiesOf` in `@intutic/shared-types`), and this says which of
|
|
9
|
+
* them to expect: the agent report registers a gate for each product found,
|
|
10
|
+
* so the silent-gate check does not wait on a gate whose product is absent,
|
|
11
|
+
* and the AI inventory lists each product with its own gate file and last
|
|
12
|
+
* event. The CLI's harness detection uses the same answer, so a machine with
|
|
13
|
+
* only Gemini CLI installed is detected too.
|
|
14
|
+
*
|
|
15
|
+
* - Antigravity: its app-data directories under `~/.gemini` (the 2.0 app, the
|
|
16
|
+
* CLI and the IDE), a project `.agents/hooks.json`, or `antigravity` on PATH.
|
|
17
|
+
* - Gemini CLI: `gemini` on PATH, a project `.gemini` directory, or a
|
|
18
|
+
* `~/.gemini/settings.json` holding a setting of its own. Intutic writes
|
|
19
|
+
* `hooks` and its own `intutic` MCP server into that file, so a file with
|
|
20
|
+
* nothing else in it is Intutic's and says nothing about Gemini CLI.
|
|
21
|
+
*
|
|
22
|
+
* @module
|
|
23
|
+
*/
|
|
24
|
+
export interface ProductProbeOptions {
|
|
25
|
+
home?: string;
|
|
26
|
+
/** The PATH to search; defaults to this process's. */
|
|
27
|
+
path?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The gate ids of the `antigravity` harness whose products are on this
|
|
31
|
+
* machine: `antigravity`, `gemini-cli`, both, or neither.
|
|
32
|
+
*/
|
|
33
|
+
export declare function antigravityGateIdentities(workspaceRoot: string, opts?: ProductProbeOptions): Promise<string[]>;
|
|
34
|
+
/**
|
|
35
|
+
* The gate ids a configured harness reports under on this machine: for
|
|
36
|
+
* `antigravity`, the products found, or the harness id itself when neither is
|
|
37
|
+
* (a configured harness is never dropped); for any other harness, its own id.
|
|
38
|
+
*/
|
|
39
|
+
export declare function presentGateIdentities(harness: string, workspaceRoot: string, opts?: ProductProbeOptions): Promise<string[]>;
|
|
40
|
+
//# sourceMappingURL=antigravityProducts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"antigravityProducts.d.ts","sourceRoot":"","sources":["../../src/harness/antigravityProducts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAOH,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AA+DD;;;GAGG;AACH,wBAAsB,yBAAyB,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,GAAE,mBAAwB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQxH;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,GAAE,mBAAwB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAIrI"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* antigravityProducts.ts — which of the two Google products behind the
|
|
3
|
+
* `antigravity` harness are on this machine.
|
|
4
|
+
*
|
|
5
|
+
* The harness installs two gates: Google Antigravity's (`PreToolUse` in
|
|
6
|
+
* `~/.gemini/config/hooks.json`) and Gemini CLI's (`BeforeTool` in
|
|
7
|
+
* `~/.gemini/settings.json`). Each reports under its own gate id
|
|
8
|
+
* (`gateIdentitiesOf` in `@intutic/shared-types`), and this says which of
|
|
9
|
+
* them to expect: the agent report registers a gate for each product found,
|
|
10
|
+
* so the silent-gate check does not wait on a gate whose product is absent,
|
|
11
|
+
* and the AI inventory lists each product with its own gate file and last
|
|
12
|
+
* event. The CLI's harness detection uses the same answer, so a machine with
|
|
13
|
+
* only Gemini CLI installed is detected too.
|
|
14
|
+
*
|
|
15
|
+
* - Antigravity: its app-data directories under `~/.gemini` (the 2.0 app, the
|
|
16
|
+
* CLI and the IDE), a project `.agents/hooks.json`, or `antigravity` on PATH.
|
|
17
|
+
* - Gemini CLI: `gemini` on PATH, a project `.gemini` directory, or a
|
|
18
|
+
* `~/.gemini/settings.json` holding a setting of its own. Intutic writes
|
|
19
|
+
* `hooks` and its own `intutic` MCP server into that file, so a file with
|
|
20
|
+
* nothing else in it is Intutic's and says nothing about Gemini CLI.
|
|
21
|
+
*
|
|
22
|
+
* @module
|
|
23
|
+
*/
|
|
24
|
+
import * as node_fs from 'node:fs/promises';
|
|
25
|
+
import * as node_path from 'node:path';
|
|
26
|
+
import { homedir } from 'node:os';
|
|
27
|
+
import { GEMINI_CLI_GATE_ID } from '@intutic/shared-types';
|
|
28
|
+
async function exists(p) {
|
|
29
|
+
try {
|
|
30
|
+
await node_fs.access(p);
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Whether an executable named `bin` is in one of PATH's directories. */
|
|
38
|
+
async function onPath(bin, pathEnv) {
|
|
39
|
+
const names = process.platform === 'win32' ? [`${bin}.cmd`, `${bin}.exe`, bin] : [bin];
|
|
40
|
+
for (const dir of pathEnv.split(node_path.delimiter)) {
|
|
41
|
+
if (!dir)
|
|
42
|
+
continue;
|
|
43
|
+
for (const name of names) {
|
|
44
|
+
try {
|
|
45
|
+
await node_fs.access(node_path.join(dir, name), node_fs.constants.X_OK);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// not here
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
/** Whether a setting is only what Intutic writes: the hooks, or an `mcpServers` holding no server but `intutic`. */
|
|
56
|
+
function intuticsOwn(key, value) {
|
|
57
|
+
if (key === 'hooks')
|
|
58
|
+
return true;
|
|
59
|
+
return key === 'mcpServers' && typeof value === 'object' && value !== null && Object.keys(value).every((name) => name === 'intutic');
|
|
60
|
+
}
|
|
61
|
+
/** Whether `~/.gemini/settings.json` holds any setting besides what Intutic writes. */
|
|
62
|
+
async function geminiSettingsInUse(home) {
|
|
63
|
+
try {
|
|
64
|
+
const parsed = JSON.parse(await node_fs.readFile(node_path.join(home, '.gemini', 'settings.json'), 'utf-8'));
|
|
65
|
+
return (typeof parsed === 'object' &&
|
|
66
|
+
parsed !== null &&
|
|
67
|
+
Object.entries(parsed).some(([key, value]) => !intuticsOwn(key, value)));
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function antigravityPresent(workspaceRoot, home, pathEnv) {
|
|
74
|
+
for (const dir of ['antigravity', 'antigravity-cli', 'antigravity-ide']) {
|
|
75
|
+
if (await exists(node_path.join(home, '.gemini', dir)))
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
return (await exists(node_path.join(workspaceRoot, '.agents', 'hooks.json'))) || onPath('antigravity', pathEnv);
|
|
79
|
+
}
|
|
80
|
+
async function geminiCliPresent(workspaceRoot, home, pathEnv) {
|
|
81
|
+
return ((await onPath('gemini', pathEnv)) ||
|
|
82
|
+
(await exists(node_path.join(workspaceRoot, '.gemini'))) ||
|
|
83
|
+
geminiSettingsInUse(home));
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The gate ids of the `antigravity` harness whose products are on this
|
|
87
|
+
* machine: `antigravity`, `gemini-cli`, both, or neither.
|
|
88
|
+
*/
|
|
89
|
+
export async function antigravityGateIdentities(workspaceRoot, opts = {}) {
|
|
90
|
+
const home = opts.home ?? homedir();
|
|
91
|
+
const pathEnv = opts.path ?? process.env.PATH ?? '';
|
|
92
|
+
const [antigravity, geminiCli] = await Promise.all([
|
|
93
|
+
antigravityPresent(workspaceRoot, home, pathEnv),
|
|
94
|
+
geminiCliPresent(workspaceRoot, home, pathEnv),
|
|
95
|
+
]);
|
|
96
|
+
return [...(antigravity ? ['antigravity'] : []), ...(geminiCli ? [GEMINI_CLI_GATE_ID] : [])];
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The gate ids a configured harness reports under on this machine: for
|
|
100
|
+
* `antigravity`, the products found, or the harness id itself when neither is
|
|
101
|
+
* (a configured harness is never dropped); for any other harness, its own id.
|
|
102
|
+
*/
|
|
103
|
+
export async function presentGateIdentities(harness, workspaceRoot, opts = {}) {
|
|
104
|
+
if (harness !== 'antigravity')
|
|
105
|
+
return [harness];
|
|
106
|
+
const found = await antigravityGateIdentities(workspaceRoot, opts);
|
|
107
|
+
return found.length > 0 ? found : [harness];
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=antigravityProducts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"antigravityProducts.js","sourceRoot":"","sources":["../../src/harness/antigravityProducts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* claudeAgentsMd.ts — whether Claude Code reads the workspace's `AGENTS.md`.
|
|
3
|
+
*
|
|
4
|
+
* Claude Code gets its rule sets and the decisions log from
|
|
5
|
+
* `.claude/rules/`, which it loads at launch whatever other instruction
|
|
6
|
+
* files exist. It also reads `AGENTS.md`, but only sometimes
|
|
7
|
+
* (https://code.claude.com/docs/en/memory#when-claude-code-reads-agentsmd):
|
|
8
|
+
*
|
|
9
|
+
* - under the default **Project instructions** setting,
|
|
10
|
+
* `claude-md-or-agents-md`, only when there is no `CLAUDE.md`,
|
|
11
|
+
* `.claude/CLAUDE.md` or `CLAUDE.local.md` in the working directory or a
|
|
12
|
+
* directory above it (`~/.claude/CLAUDE.md` does not count);
|
|
13
|
+
* - always under `claude-md-and-agents-md`, and never under `claude-md` or
|
|
14
|
+
* `managed-only`.
|
|
15
|
+
*
|
|
16
|
+
* The setting is honoured only from user, `--settings` or managed settings,
|
|
17
|
+
* under `pluginConfigs["cc-plugin-agents-md@builtin"].options.instructionFiles`
|
|
18
|
+
* (`agents-md@builtin` before v2.1.285); a project's settings cannot change
|
|
19
|
+
* it. This reads the user's `~/.claude/settings.json`.
|
|
20
|
+
*
|
|
21
|
+
* When Claude Code reads `AGENTS.md`, whatever Intutic puts there for the
|
|
22
|
+
* other harnesses reaches Claude Code too, so the writers leave it out of
|
|
23
|
+
* `.claude/rules/` to keep Claude Code from reading it twice.
|
|
24
|
+
*
|
|
25
|
+
* @module
|
|
26
|
+
*/
|
|
27
|
+
/** Whether Claude Code, started in `workspaceRoot`, reads its `AGENTS.md`. */
|
|
28
|
+
export declare function claudeCodeReadsAgentsMd(workspaceRoot: string): Promise<boolean>;
|
|
29
|
+
//# sourceMappingURL=claudeAgentsMd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claudeAgentsMd.d.ts","sourceRoot":"","sources":["../../src/harness/claudeAgentsMd.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAgDH,8EAA8E;AAC9E,wBAAsB,uBAAuB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAKrF"}
|