@intutic/sync-daemon 2.1.0 → 2.2.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/dist/agentReporter.d.ts +1 -0
- package/dist/agentReporter.d.ts.map +1 -1
- package/dist/configReader.d.ts +44 -22
- package/dist/configReader.d.ts.map +1 -1
- package/dist/configReader.js +70 -44
- package/dist/configReader.js.map +1 -1
- package/dist/configWriter.d.ts +29 -41
- package/dist/configWriter.d.ts.map +1 -1
- package/dist/configWriter.js +26 -637
- package/dist/configWriter.js.map +1 -1
- package/dist/disconnect/harnesses.d.ts +31 -0
- package/dist/disconnect/harnesses.d.ts.map +1 -0
- package/dist/disconnect/harnesses.js +728 -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 +82 -0
- package/dist/disconnect/index.js.map +1 -0
- package/dist/disconnect/mcp.d.ts +60 -0
- package/dist/disconnect/mcp.d.ts.map +1 -0
- package/dist/disconnect/mcp.js +283 -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 +98 -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 +1 -0
- package/dist/harness/aiderConfigMerger.d.ts.map +1 -1
- package/dist/harness/aiderConfigMerger.js +4 -1
- package/dist/harness/aiderConfigMerger.js.map +1 -1
- package/dist/harness/antigravityHooks.d.ts.map +1 -1
- package/dist/harness/antigravityHooks.js +2 -0
- package/dist/harness/antigravityHooks.js.map +1 -1
- package/dist/harness/claudeCodeHooks.d.ts +1 -2
- package/dist/harness/claudeCodeHooks.d.ts.map +1 -1
- package/dist/harness/claudeCodeHooks.js +19 -6
- package/dist/harness/claudeCodeHooks.js.map +1 -1
- package/dist/harness/claudeDesktopHooks.d.ts +3 -0
- package/dist/harness/claudeDesktopHooks.d.ts.map +1 -1
- package/dist/harness/claudeDesktopHooks.js +3 -1
- package/dist/harness/claudeDesktopHooks.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.map +1 -1
- package/dist/harness/clineHooks.js +3 -0
- 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.map +1 -1
- package/dist/harness/codexHooks.js +3 -0
- 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/continueHooks.d.ts.map +1 -1
- package/dist/harness/continueHooks.js +3 -0
- package/dist/harness/continueHooks.js.map +1 -1
- package/dist/harness/cursorHooks.d.ts.map +1 -1
- package/dist/harness/cursorHooks.js +3 -0
- package/dist/harness/cursorHooks.js.map +1 -1
- package/dist/harness/dshHooks.d.ts.map +1 -1
- package/dist/harness/dshHooks.js +7 -0
- package/dist/harness/dshHooks.js.map +1 -1
- package/dist/harness/gateBody.d.ts +11 -2
- package/dist/harness/gateBody.d.ts.map +1 -1
- package/dist/harness/gateBody.js +33 -6
- package/dist/harness/gateBody.js.map +1 -1
- package/dist/harness/githubCopilotHooks.d.ts.map +1 -1
- package/dist/harness/githubCopilotHooks.js +4 -9
- package/dist/harness/githubCopilotHooks.js.map +1 -1
- package/dist/harness/gooseHooks.d.ts +15 -0
- package/dist/harness/gooseHooks.d.ts.map +1 -1
- package/dist/harness/gooseHooks.js +55 -43
- package/dist/harness/gooseHooks.js.map +1 -1
- package/dist/harness/grokHooks.d.ts.map +1 -1
- package/dist/harness/grokHooks.js +9 -12
- package/dist/harness/grokHooks.js.map +1 -1
- package/dist/harness/hermesHooks.d.ts.map +1 -1
- package/dist/harness/hermesHooks.js +7 -2
- 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 +39 -17
- package/dist/harness/mcpAutoWrite.d.ts.map +1 -1
- package/dist/harness/mcpAutoWrite.js +189 -71
- package/dist/harness/mcpAutoWrite.js.map +1 -1
- package/dist/harness/museHooks.d.ts.map +1 -1
- package/dist/harness/museHooks.js +6 -2
- package/dist/harness/museHooks.js.map +1 -1
- package/dist/harness/openCodeHooks.d.ts.map +1 -1
- package/dist/harness/openCodeHooks.js +2 -5
- package/dist/harness/openCodeHooks.js.map +1 -1
- package/dist/harness/openWebuiHooks.d.ts.map +1 -1
- package/dist/harness/openWebuiHooks.js +6 -2
- package/dist/harness/openWebuiHooks.js.map +1 -1
- package/dist/harness/openclawHooks.d.ts +5 -0
- package/dist/harness/openclawHooks.d.ts.map +1 -1
- package/dist/harness/openclawHooks.js +3 -1
- package/dist/harness/openclawHooks.js.map +1 -1
- package/dist/harness/openhandsHooks.d.ts +13 -1
- package/dist/harness/openhandsHooks.d.ts.map +1 -1
- package/dist/harness/openhandsHooks.js +106 -56
- package/dist/harness/openhandsHooks.js.map +1 -1
- package/dist/harness/piHooks.d.ts.map +1 -1
- package/dist/harness/piHooks.js +3 -0
- package/dist/harness/piHooks.js.map +1 -1
- package/dist/harness/rooCodeHooks.d.ts.map +1 -1
- package/dist/harness/rooCodeHooks.js +5 -10
- package/dist/harness/rooCodeHooks.js.map +1 -1
- package/dist/harness/windsurfHooks.d.ts +18 -2
- package/dist/harness/windsurfHooks.d.ts.map +1 -1
- package/dist/harness/windsurfHooks.js +37 -7
- 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 +9 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -10
- package/dist/index.js.map +1 -1
- package/dist/lib/decisionsDigest.d.ts +1 -1
- package/dist/lib/decisionsDigest.js +1 -1
- package/dist/lib/policySnapshot.d.ts +18 -0
- package/dist/lib/policySnapshot.d.ts.map +1 -1
- package/dist/lib/policySnapshot.js +142 -7
- package/dist/lib/policySnapshot.js.map +1 -1
- package/dist/sessionReporter.d.ts +2 -2
- package/dist/sessionReporter.js +2 -2
- package/dist/syncCycle.d.ts +142 -0
- package/dist/syncCycle.d.ts.map +1 -0
- package/dist/syncCycle.js +315 -0
- package/dist/syncCycle.js.map +1 -0
- package/dist/trajectoryMonitor.d.ts +1 -1
- package/dist/trajectoryMonitor.d.ts.map +1 -1
- package/dist/trajectoryMonitor.js +1 -1
- package/dist/trajectoryMonitor.js.map +1 -1
- package/dist/watcher/settingsGuard.d.ts +4 -1
- package/dist/watcher/settingsGuard.d.ts.map +1 -1
- package/dist/watcher/settingsGuard.js +28 -3
- package/dist/watcher/settingsGuard.js.map +1 -1
- package/package.json +5 -5
- package/dist/hashReporter.d.ts +0 -33
- package/dist/hashReporter.d.ts.map +0 -1
- package/dist/hashReporter.js +0 -69
- package/dist/hashReporter.js.map +0 -1
- package/dist/integrityStore.d.ts +0 -35
- package/dist/integrityStore.d.ts.map +0 -1
- package/dist/integrityStore.js +0 -71
- package/dist/integrityStore.js.map +0 -1
- package/dist/lib/gitWorktrees.d.ts +0 -140
- package/dist/lib/gitWorktrees.d.ts.map +0 -1
- package/dist/lib/gitWorktrees.js +0 -191
- package/dist/lib/gitWorktrees.js.map +0 -1
- package/dist/syncLoop.d.ts +0 -172
- package/dist/syncLoop.d.ts.map +0 -1
- package/dist/syncLoop.js +0 -878
- package/dist/syncLoop.js.map +0 -1
package/dist/lib/gitWorktrees.js
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* gitWorktrees.ts — discovers every `git worktree` checkout of a repo the
|
|
3
|
-
* sync daemon is watching, so project-tier governance files can be written
|
|
4
|
-
* into each one, not just the main checkout.
|
|
5
|
-
*
|
|
6
|
-
* # The gap this closes
|
|
7
|
-
*
|
|
8
|
-
* `git worktree add <path>` creates a second, fully independent WORKING
|
|
9
|
-
* TREE that shares the main checkout's `.git` object store (via a `.git`
|
|
10
|
-
* FILE pointing back at `<main>/.git/worktrees/<name>`) but has its own
|
|
11
|
-
* untracked files. Every project-tier governance file this product writes
|
|
12
|
-
* — `.claude/settings.json`, `.cursor/hooks.json`, `.intutic/hooks/*`,
|
|
13
|
-
* `AGENTS.md`'s sibling hook registrations, the wrapped `.mcp.json` entries,
|
|
14
|
-
* etc. — is untracked by convention (SOP content is workspace-specific and
|
|
15
|
-
* synced from the control plane, not committed). That means none of it
|
|
16
|
-
* exists in a worktree's working tree by default: `writeConfigFiles`/
|
|
17
|
-
* `injectMcpServer` running against only the main checkout's `workspaceRoot`
|
|
18
|
-
* leaves every OTHER worktree of that same repo completely ungoverned,
|
|
19
|
-
* regardless of what the main checkout has configured.
|
|
20
|
-
*
|
|
21
|
-
* This was already true for any hand-rolled `git worktree` workflow before
|
|
22
|
-
* this module existed — Xirp (an orchestrator that spawns CLI agents each
|
|
23
|
-
* inside its own tmux session + git worktree, see `tools/cli/src/harness/
|
|
24
|
-
* xirp.ts`) is what surfaced it, but the fix here is general: it benefits
|
|
25
|
-
* ANY worktree-based workflow, Xirp-managed or not. See TD-390.
|
|
26
|
-
*
|
|
27
|
-
* # Verifying the mechanics for real
|
|
28
|
-
*
|
|
29
|
-
* Confirmed against a real throwaway repo during this module's development
|
|
30
|
-
* (not asserted from memory of git's docs): an untracked file written into
|
|
31
|
-
* a main checkout is NOT visible from a `git worktree add`-created sibling
|
|
32
|
-
* checkout's directory. `git worktree list --porcelain`'s block format,
|
|
33
|
-
* including `locked`/`prunable`/`bare`/`detached` fields, was captured from
|
|
34
|
-
* a real `git worktree list --porcelain` run (this module's own test suite
|
|
35
|
-
* builds the same kind of fixture, in an isolated temp directory, rather
|
|
36
|
-
* than relying on this description alone).
|
|
37
|
-
*
|
|
38
|
-
* @module
|
|
39
|
-
*/
|
|
40
|
-
import { execFile as _execFile } from 'node:child_process';
|
|
41
|
-
import { promisify } from 'node:util';
|
|
42
|
-
const execFile = promisify(_execFile);
|
|
43
|
-
/**
|
|
44
|
-
* Parses `git worktree list --porcelain` output.
|
|
45
|
-
*
|
|
46
|
-
* Real format (verified against a live `git worktree list --porcelain` run,
|
|
47
|
-
* git 2.x): one block per worktree, separated by a blank line, each line a
|
|
48
|
-
* bare keyword or `<keyword> <value>`:
|
|
49
|
-
*
|
|
50
|
-
* ```
|
|
51
|
-
* worktree /path/to/main
|
|
52
|
-
* HEAD 56bdba0a04f83da4e821a0a3e7a6208d43fcaec5
|
|
53
|
-
* branch refs/heads/master
|
|
54
|
-
*
|
|
55
|
-
* worktree /path/to/locked-wt
|
|
56
|
-
* HEAD 56bdba0a04f83da4e821a0a3e7a6208d43fcaec5
|
|
57
|
-
* branch refs/heads/feature2
|
|
58
|
-
* locked testing lock
|
|
59
|
-
*
|
|
60
|
-
* worktree /path/to/detached-wt
|
|
61
|
-
* HEAD 56bdba0a04f83da4e821a0a3e7a6208d43fcaec5
|
|
62
|
-
* detached
|
|
63
|
-
* ```
|
|
64
|
-
*
|
|
65
|
-
* Deliberately implemented with plain string methods (`startsWith`/`slice`)
|
|
66
|
-
* rather than a line-matching regex — this parses `git`-controlled, not
|
|
67
|
-
* attacker-controlled, input, but a sibling Wave 1 phase shipped a
|
|
68
|
-
* CodeQL-flagged polynomial-regex bug from exactly this kind of "just trim
|
|
69
|
-
* a path" text handling, so the same class of construct is avoided here on
|
|
70
|
-
* principle even though the input source differs.
|
|
71
|
-
*/
|
|
72
|
-
export function parseWorktreeListPorcelain(output) {
|
|
73
|
-
const blocks = output.split('\n\n');
|
|
74
|
-
const worktrees = [];
|
|
75
|
-
for (const block of blocks) {
|
|
76
|
-
const trimmedBlock = block.trim();
|
|
77
|
-
if (!trimmedBlock)
|
|
78
|
-
continue;
|
|
79
|
-
let path = '';
|
|
80
|
-
let head = null;
|
|
81
|
-
let branch = null;
|
|
82
|
-
let detached = false;
|
|
83
|
-
let bare = false;
|
|
84
|
-
let locked = false;
|
|
85
|
-
let lockedReason = null;
|
|
86
|
-
let prunable = false;
|
|
87
|
-
let prunableReason = null;
|
|
88
|
-
for (const rawLine of trimmedBlock.split('\n')) {
|
|
89
|
-
const line = rawLine.trim();
|
|
90
|
-
if (!line)
|
|
91
|
-
continue;
|
|
92
|
-
if (line === 'bare') {
|
|
93
|
-
bare = true;
|
|
94
|
-
}
|
|
95
|
-
else if (line === 'detached') {
|
|
96
|
-
detached = true;
|
|
97
|
-
}
|
|
98
|
-
else if (line.startsWith('worktree ')) {
|
|
99
|
-
path = line.slice('worktree '.length).trim();
|
|
100
|
-
}
|
|
101
|
-
else if (line.startsWith('HEAD ')) {
|
|
102
|
-
head = line.slice('HEAD '.length).trim();
|
|
103
|
-
}
|
|
104
|
-
else if (line.startsWith('branch ')) {
|
|
105
|
-
branch = line.slice('branch '.length).trim();
|
|
106
|
-
}
|
|
107
|
-
else if (line === 'locked') {
|
|
108
|
-
locked = true;
|
|
109
|
-
}
|
|
110
|
-
else if (line.startsWith('locked ')) {
|
|
111
|
-
locked = true;
|
|
112
|
-
lockedReason = line.slice('locked '.length).trim() || null;
|
|
113
|
-
}
|
|
114
|
-
else if (line === 'prunable') {
|
|
115
|
-
prunable = true;
|
|
116
|
-
}
|
|
117
|
-
else if (line.startsWith('prunable ')) {
|
|
118
|
-
prunable = true;
|
|
119
|
-
prunableReason = line.slice('prunable '.length).trim() || null;
|
|
120
|
-
}
|
|
121
|
-
// Any other line is a porcelain field this parser does not know about
|
|
122
|
-
// yet (git has added a few over the years) — ignored rather than
|
|
123
|
-
// treated as an error, so a future git version adding a new field
|
|
124
|
-
// degrades gracefully instead of breaking discovery entirely.
|
|
125
|
-
}
|
|
126
|
-
if (path) {
|
|
127
|
-
worktrees.push({ path, head, branch, detached, bare, locked, lockedReason, prunable, prunableReason });
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
return worktrees;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Discovers every worktree of the git repository containing `repoRoot`,
|
|
134
|
-
* returning the absolute paths that should be treated as additional
|
|
135
|
-
* project-tier workspace roots.
|
|
136
|
-
*
|
|
137
|
-
* Filtering decisions, made explicit rather than left implicit:
|
|
138
|
-
*
|
|
139
|
-
* - **The main checkout is included.** `git worktree list` always lists it
|
|
140
|
-
* first (confirmed against a live run) — it needs no special-casing by
|
|
141
|
-
* callers; a caller that already writes to `repoRoot` directly can simply
|
|
142
|
-
* skip a returned path equal to `repoRoot` if it wants to avoid a
|
|
143
|
-
* redundant duplicate write, but the list is uniformly correct either way.
|
|
144
|
-
* - **Locked worktrees are included.** `git worktree lock` only prevents
|
|
145
|
-
* git's own pruning of a worktree it cannot otherwise verify still
|
|
146
|
-
* exists (e.g. on removable storage) — it says nothing about whether the
|
|
147
|
-
* directory is currently present and writable, which it normally is.
|
|
148
|
-
* Excluding locked worktrees would silently under-cover a workflow (like
|
|
149
|
-
* Xirp's) that locks worktrees deliberately to protect them from being
|
|
150
|
-
* pruned out from under a long-running session — exactly the worktrees
|
|
151
|
-
* most worth covering.
|
|
152
|
-
* - **Prunable worktrees are EXCLUDED.** `prunable` means git itself has
|
|
153
|
-
* flagged the worktree's directory as missing or otherwise administratively
|
|
154
|
-
* invalid. Writing into that path would either fail or (via this
|
|
155
|
-
* codebase's `mkdir(dir, { recursive: true })` write convention) silently
|
|
156
|
-
* RECREATE a directory git considers gone — resurrecting a deleted
|
|
157
|
-
* worktree's folder with governance files nobody asked for. Skipping it
|
|
158
|
-
* is what "don't write into a directory git says isn't really there"
|
|
159
|
-
* means in practice.
|
|
160
|
-
* - **Bare-repository entries are EXCLUDED.** A bare repo's own `worktree`
|
|
161
|
-
* porcelain entry names its root path but has no working tree of ordinary
|
|
162
|
-
* files to write project-tier config into.
|
|
163
|
-
*
|
|
164
|
-
* Best-effort by design: returns `[]` (never throws) if `repoRoot` is not
|
|
165
|
-
* inside a git repository, if `git` is not on `PATH`, or on any other
|
|
166
|
-
* failure — this is additive coverage on top of the existing single-root
|
|
167
|
-
* write path, so a git failure here must not break the sync cycle that
|
|
168
|
-
* already succeeds for the main `workspaceRoot`. This also means a
|
|
169
|
-
* non-worktree, single-checkout project (the common case) is a harmless
|
|
170
|
-
* no-extra-work path: `git worktree list` still runs, still succeeds, and
|
|
171
|
-
* returns exactly one entry (the main checkout itself).
|
|
172
|
-
*/
|
|
173
|
-
export async function discoverWorktrees(repoRoot) {
|
|
174
|
-
try {
|
|
175
|
-
const { stdout } = await execFile('git', ['worktree', 'list', '--porcelain'], {
|
|
176
|
-
cwd: repoRoot,
|
|
177
|
-
encoding: 'utf-8',
|
|
178
|
-
timeout: 5000,
|
|
179
|
-
});
|
|
180
|
-
return parseWorktreeListPorcelain(stdout)
|
|
181
|
-
.filter((wt) => !wt.bare && !wt.prunable)
|
|
182
|
-
.map((wt) => wt.path);
|
|
183
|
-
}
|
|
184
|
-
catch {
|
|
185
|
-
// Not a git repo, git not installed, or a transient failure — additive
|
|
186
|
-
// coverage, so this degrades to "no extra worktrees found", not a
|
|
187
|
-
// thrown error the caller must handle.
|
|
188
|
-
return [];
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
//# sourceMappingURL=gitWorktrees.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gitWorktrees.js","sourceRoot":"","sources":["../../src/lib/gitWorktrees.ts"],"names":[],"mappings":"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"}
|
package/dist/syncLoop.d.ts
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* syncLoop.ts — Core bidirectional sync loop.
|
|
3
|
-
*
|
|
4
|
-
* The sync loop is the heartbeat of the daemon. Each iteration:
|
|
5
|
-
* 1. Fetches config from the control plane (POST /api/v1/sync/config)
|
|
6
|
-
* 2. If configVersion > local → writes SOP content to harness files
|
|
7
|
-
* 3. Computes SHA-256 hashes of local config files
|
|
8
|
-
* 4. Reports hashes + status back to the control plane
|
|
9
|
-
* 5. Calls the onSync callback with the result
|
|
10
|
-
* 6. Sleeps for pollIntervalMs (AbortSignal-aware)
|
|
11
|
-
* 7. Repeats until signal.aborted
|
|
12
|
-
*
|
|
13
|
-
* Design: never crash on a single iteration failure. Errors are
|
|
14
|
-
* caught per-iteration, logged, and the loop continues.
|
|
15
|
-
*
|
|
16
|
-
* HLD §3.14 — Real-Time State Mirroring
|
|
17
|
-
* LLD #8 — Sync Daemon / CLI
|
|
18
|
-
*
|
|
19
|
-
* @module
|
|
20
|
-
*/
|
|
21
|
-
import type { HarnessType, SyncConfigPayload, WorkspaceSettings, SyncSopEntry } from '@intutic/shared-types';
|
|
22
|
-
import { type GovernanceCoverageInputs } from './configReader.js';
|
|
23
|
-
import { type AgentReport } from './agentReporter.js';
|
|
24
|
-
/**
|
|
25
|
-
* Turns a non-clean `scanSkillContent` result — already computed as part of
|
|
26
|
-
* `collectAgentReport`'s `facets.skills` — into a `skill_flagged` hook event
|
|
27
|
-
* (TD-358).
|
|
28
|
-
*
|
|
29
|
-
* Deliberately reuses the report the daemon already built for this cycle
|
|
30
|
-
* rather than re-scanning: `agentReporter.ts`'s `collectSkills` runs
|
|
31
|
-
* `scanSkillContent` on every `.agents/skills/**\/SKILL.md` as part of
|
|
32
|
-
* building `facets.skills` already, so this only turns a result the daemon
|
|
33
|
-
* already has into a visible signal — it does not add a second scan pass.
|
|
34
|
-
*
|
|
35
|
-
* Appends directly to `.intutic/events/hook-events.jsonl`, the SAME file
|
|
36
|
-
* every emitted PreToolUse gate's `log_event`/`logEvent` writes to and the
|
|
37
|
-
* SAME mechanism `onDriftDetected` below already uses for `config_tamper` —
|
|
38
|
-
* not a new event pipeline. `drainHookEvents` (`claudeCodeHooks.ts`) picks
|
|
39
|
-
* this line up on its next pass exactly like a gate-written one, because it
|
|
40
|
-
* only ever reads the file; it does not care who appended a given line.
|
|
41
|
-
*
|
|
42
|
-
* Report-only, per `scanSkillContent`'s own doc comment on the unmeasured
|
|
43
|
-
* false-positive rate against real, benign skill markdown: this NEVER
|
|
44
|
-
* blocks, mutates, or removes a skill. `hookEvents.ts`'s
|
|
45
|
-
* `HookEventSchema.event` enum (control plane) counts `skill_flagged`
|
|
46
|
-
* exactly like `tool_flagged` — advisory telemetry, not an incident.
|
|
47
|
-
*
|
|
48
|
-
* A failure to append is caught and warned, never thrown: a governance
|
|
49
|
-
* telemetry write must not be able to abort the sync cycle it rides in on.
|
|
50
|
-
*/
|
|
51
|
-
export declare function emitSkillFlaggedEvents(opts: {
|
|
52
|
-
workspaceRoot: string;
|
|
53
|
-
workspaceId: string;
|
|
54
|
-
harnessType: HarnessType;
|
|
55
|
-
skills: AgentReport['facets']['skills'];
|
|
56
|
-
/** Skills already emitted in this cycle, keyed `source:name`, mutated in
|
|
57
|
-
* place. A skill is not harness-specific, and the caller invokes this
|
|
58
|
-
* once per harness in the workspace — without a shared set, a workspace
|
|
59
|
-
* with two active harnesses would double-emit every flagged skill. */
|
|
60
|
-
alreadyEmitted: Set<string>;
|
|
61
|
-
}): void;
|
|
62
|
-
/** Configuration for the sync loop. */
|
|
63
|
-
export interface SyncLoopOptions {
|
|
64
|
-
/** Control plane base URL (e.g., `https://api.intutic.ai`). */
|
|
65
|
-
controlPlaneUrl: string;
|
|
66
|
-
/** API key for authentication (vk_* or JWT). */
|
|
67
|
-
apiKey: string;
|
|
68
|
-
/** Workspace identifier. */
|
|
69
|
-
workspaceId: string;
|
|
70
|
-
/** Absolute path to the workspace root directory. */
|
|
71
|
-
workspaceRoot: string;
|
|
72
|
-
/** Poll interval in milliseconds (default: 30000). */
|
|
73
|
-
pollIntervalMs?: number;
|
|
74
|
-
/** Enable dev mode (relaxed checks, verbose logging). */
|
|
75
|
-
devMode?: boolean;
|
|
76
|
-
/** Callback invoked after each successful sync iteration. */
|
|
77
|
-
onSync?: (result: SyncResult) => void;
|
|
78
|
-
/** AbortSignal to gracefully stop the loop. */
|
|
79
|
-
signal?: AbortSignal;
|
|
80
|
-
}
|
|
81
|
-
/** Result of a single sync iteration. */
|
|
82
|
-
export interface SyncResult {
|
|
83
|
-
/** Config version from the control plane. */
|
|
84
|
-
configVersion: number;
|
|
85
|
-
/** Number of harness config files written. */
|
|
86
|
-
sopsWritten: number;
|
|
87
|
-
/** Number of files with hash drift. */
|
|
88
|
-
driftCount: number;
|
|
89
|
-
/** ISO timestamp of this sync. */
|
|
90
|
-
timestamp: string;
|
|
91
|
-
/** Resolved workspace settings from the control plane. WS-5. */
|
|
92
|
-
settings?: WorkspaceSettings;
|
|
93
|
-
/** All active SOP rules. */
|
|
94
|
-
sops?: SyncConfigPayload['sops'];
|
|
95
|
-
/** Proxy URL. */
|
|
96
|
-
proxyUrl?: string;
|
|
97
|
-
/** Active harnesses. */
|
|
98
|
-
harnesses?: HarnessType[];
|
|
99
|
-
/**
|
|
100
|
-
* This cycle's per-harness governance-coverage enforcement signals, derived
|
|
101
|
-
* from the same `collectAgentReport` facets step 5b already computes for
|
|
102
|
-
* `POST /api/v1/agents/report` — see that step's inline derivation for the
|
|
103
|
-
* mapping. Consumed by the outer loop's config-capture step to fire
|
|
104
|
-
* `POST /api/v1/governance-coverage/snapshot` once per harness whose rules
|
|
105
|
-
* file content actually changed this cycle.
|
|
106
|
-
*/
|
|
107
|
-
harnessGovernanceInputs?: Partial<Record<HarnessType, GovernanceCoverageInputs>>;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Start the sync loop. This function runs indefinitely until the
|
|
111
|
-
* AbortSignal is triggered or the process exits.
|
|
112
|
-
*
|
|
113
|
-
* @param options - Sync loop configuration.
|
|
114
|
-
*/
|
|
115
|
-
/** The credentials every gate-side refresh takes. */
|
|
116
|
-
export interface GateCacheRefreshOptions {
|
|
117
|
-
controlPlaneUrl: string;
|
|
118
|
-
apiKey: string;
|
|
119
|
-
workspaceId: string;
|
|
120
|
-
/** See {@link PolicySnapshotOptions.localHoldTokens}. */
|
|
121
|
-
localHoldTokens?: readonly string[];
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* The `review_before:` tokens the snapshot compiles into hold rules: from the
|
|
125
|
-
* synced SOPs' front matter and JSON blocks, the workspace settings, and the
|
|
126
|
-
* local `.intutic/sops`. The same parse the Claude Code writer runs for its
|
|
127
|
-
* pattern blacklist, so the two cannot disagree about what is held.
|
|
128
|
-
*/
|
|
129
|
-
export declare function localHoldTokensFor(workspaceRoot: string, sops: SyncSopEntry[], settings: Record<string, unknown> | undefined, harnesses?: HarnessType[]): Promise<string[]>;
|
|
130
|
-
/**
|
|
131
|
-
* Refresh the three gate-side caches every hook reads: the policy snapshot
|
|
132
|
-
* (`~/.intutic/hooks/policy-snapshot.rules`), the approved review-hold
|
|
133
|
-
* bypasses and the central egress policy. Called on EVERY sync cycle by both
|
|
134
|
-
* loops — this one and `intutic connect`'s — never only when the config
|
|
135
|
-
* version moved: policy changes without the version changing, and before
|
|
136
|
-
* this helper existed `connect` refreshed once at startup and never again, so
|
|
137
|
-
* a guardrail promoted mid-session reached a connected machine only on
|
|
138
|
-
* restart (TD-488). None of the three throw; the return says which of them
|
|
139
|
-
* landed.
|
|
140
|
-
*/
|
|
141
|
-
export declare function refreshGateCaches(opts: GateCacheRefreshOptions): Promise<{
|
|
142
|
-
snapshot: boolean;
|
|
143
|
-
bypasses: boolean;
|
|
144
|
-
egress: boolean;
|
|
145
|
-
}>;
|
|
146
|
-
export declare function startSyncLoop(options: SyncLoopOptions): Promise<void>;
|
|
147
|
-
export interface IterationContext {
|
|
148
|
-
controlPlaneUrl: string;
|
|
149
|
-
apiKey: string;
|
|
150
|
-
workspaceId: string;
|
|
151
|
-
workspaceRoot: string;
|
|
152
|
-
onSync?: (result: SyncResult) => void;
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Execute a single sync iteration:
|
|
156
|
-
* 1. Fetch config from control plane
|
|
157
|
-
* 2. Write config files if version is newer
|
|
158
|
-
* 3. Compute file hashes
|
|
159
|
-
* 4. Report status back to control plane
|
|
160
|
-
* 5. Update local integrity store
|
|
161
|
-
* 6. Call onSync callback
|
|
162
|
-
*
|
|
163
|
-
* Exported (in addition to being used internally by `startSyncLoop`'s
|
|
164
|
-
* polling loop) as a test seam — it is the unit that exercises exactly one
|
|
165
|
-
* cycle's worth of work, including the injectMcpServer call (step 3c),
|
|
166
|
-
* without the surrounding while-loop's extra one-time/Nth-iteration network
|
|
167
|
-
* calls (policy snapshot, approved bypasses, egress policy, compliance
|
|
168
|
-
* probes, drift watcher, decisions digest, config capture).
|
|
169
|
-
*/
|
|
170
|
-
export declare function runSyncIteration(ctx: IterationContext): Promise<SyncResult>;
|
|
171
|
-
export declare function syncOfflineTraces(controlPlaneUrl: string, apiKey: string): Promise<void>;
|
|
172
|
-
//# sourceMappingURL=syncLoop.d.ts.map
|
package/dist/syncLoop.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"syncLoop.d.ts","sourceRoot":"","sources":["../src/syncLoop.ts"],"names":[],"mappings":"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"}
|