@cleocode/git-shim 2026.4.154 → 2026.4.157
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 +147 -0
- package/dist/__tests__/boundary-enforcement.test.d.ts +2 -0
- package/dist/__tests__/boundary-enforcement.test.d.ts.map +1 -0
- package/dist/__tests__/boundary-enforcement.test.js +282 -0
- package/dist/__tests__/boundary-enforcement.test.js.map +1 -0
- package/dist/audit-log.d.ts +59 -0
- package/dist/audit-log.d.ts.map +1 -0
- package/dist/audit-log.js +66 -0
- package/dist/audit-log.js.map +1 -0
- package/dist/boundary.d.ts +119 -0
- package/dist/boundary.d.ts.map +1 -0
- package/dist/boundary.js +242 -0
- package/dist/boundary.js.map +1 -0
- package/dist/index.d.ts +11 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -6
- package/dist/index.js.map +1 -1
- package/dist/shim.d.ts +16 -14
- package/dist/shim.d.ts.map +1 -1
- package/dist/shim.js +138 -33
- package/dist/shim.js.map +1 -1
- package/dist/worktree-path.d.ts +69 -0
- package/dist/worktree-path.d.ts.map +1 -0
- package/dist/worktree-path.js +146 -0
- package/dist/worktree-path.js.map +1 -0
- package/package.json +2 -2
package/dist/shim.js
CHANGED
|
@@ -1,35 +1,40 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* git-shim — harness-agnostic git
|
|
3
|
+
* git-shim — harness-agnostic git fence (T1118 L2 + T1591 boundary fence).
|
|
4
4
|
*
|
|
5
5
|
* Usage: place this binary on PATH BEFORE real git, and export:
|
|
6
6
|
* CLEO_AGENT_ROLE=worker (or lead|subagent)
|
|
7
|
-
* CLEO_WORKTREE_ROOT=<path>
|
|
7
|
+
* CLEO_WORKTREE_ROOT=<path> (optional — auto-detected from cwd)
|
|
8
|
+
* CLEO_TASK_ID=T<NUM> (optional — auto-detected from worktree path)
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
10
|
+
* Layered enforcement (in order, all under restricted-role gate):
|
|
11
|
+
* 1. T1118 denylist (branch-mutation ops). Bypass: `CLEO_ALLOW_BRANCH_OPS=1`.
|
|
12
|
+
* 2. T1591 boundary fence:
|
|
13
|
+
* (a) git add path inside worktree
|
|
14
|
+
* (b) git commit subject contains T-ID
|
|
15
|
+
* (c) git merge requires CLEO_ORCHESTRATE_MERGE=1
|
|
16
|
+
* (d) git cherry-pick refuses task/T<NUM> source
|
|
17
|
+
* Bypass any of (a)-(d): `CLEO_ALLOW_GIT=1` (audited).
|
|
15
18
|
*
|
|
16
|
-
*
|
|
17
|
-
* discovered by walking PATH and skipping any entry that resolves to this
|
|
18
|
-
* shim itself (detected via CLEO_SHIM_MARKER env set by the shim installer).
|
|
19
|
+
* Audit log at `<XDG>/cleo/audit/git-shim.jsonl` (override `CLEO_AUDIT_LOG_PATH`).
|
|
19
20
|
*
|
|
20
21
|
* Exit codes:
|
|
21
|
-
* 0 — passthrough succeeded
|
|
22
|
-
* 1 —
|
|
23
|
-
* 77 —
|
|
22
|
+
* 0 — passthrough succeeded
|
|
23
|
+
* 1 — generic shim error (real git not found)
|
|
24
|
+
* 77 — CLEO_GIT_BLOCKED sentinel (legacy denylist + new boundary fence)
|
|
24
25
|
* N — real git exit code propagated
|
|
25
26
|
*
|
|
26
27
|
* @task T1118
|
|
27
28
|
* @task T1121
|
|
29
|
+
* @task T1591
|
|
28
30
|
*/
|
|
29
31
|
import { spawnSync } from 'node:child_process';
|
|
30
32
|
import { existsSync } from 'node:fs';
|
|
31
33
|
import { join } from 'node:path';
|
|
34
|
+
import { writeAuditRecord } from './audit-log.js';
|
|
35
|
+
import { validateAddPaths, validateCherryPickSource, validateCommitSubject, validateMergeAllowed, } from './boundary.js';
|
|
32
36
|
import { findDeniedOp, RESTRICTED_ROLES } from './denylist.js';
|
|
37
|
+
import { resolveActiveWorktree } from './worktree-path.js';
|
|
33
38
|
/** Sentinel exit code for a shim-blocked git operation. */
|
|
34
39
|
const BLOCKED_EXIT_CODE = 77;
|
|
35
40
|
/**
|
|
@@ -48,27 +53,24 @@ function getAgentRole() {
|
|
|
48
53
|
*
|
|
49
54
|
* Strategy:
|
|
50
55
|
* 1. If CLEO_REAL_GIT_PATH env is set, use it (override for testing).
|
|
51
|
-
* 2. Walk PATH entries, skip
|
|
56
|
+
* 2. Walk PATH entries, skip any that contain CLEO_SHIM_MARKER.
|
|
52
57
|
* 3. Fall back to /usr/bin/git, /usr/local/bin/git, /opt/homebrew/bin/git.
|
|
53
58
|
*
|
|
54
59
|
* @returns Absolute path to real git, or null if not found.
|
|
55
60
|
*/
|
|
56
61
|
function resolveRealGit() {
|
|
57
|
-
// Explicit override wins — useful for tests.
|
|
58
62
|
const override = process.env['CLEO_REAL_GIT_PATH'];
|
|
59
63
|
if (override && existsSync(override))
|
|
60
64
|
return override;
|
|
61
65
|
const shimMarker = process.env['CLEO_SHIM_MARKER'] ?? '.cleo/bin/git-shim';
|
|
62
66
|
const pathDirs = (process.env['PATH'] ?? '').split(':');
|
|
63
67
|
for (const dir of pathDirs) {
|
|
64
|
-
// Skip directories that look like the shim directory.
|
|
65
68
|
if (dir.includes(shimMarker))
|
|
66
69
|
continue;
|
|
67
70
|
const candidate = join(dir, 'git');
|
|
68
71
|
if (existsSync(candidate))
|
|
69
72
|
return candidate;
|
|
70
73
|
}
|
|
71
|
-
// Hard fallbacks for common installations.
|
|
72
74
|
const fallbacks = ['/usr/bin/git', '/usr/local/bin/git', '/opt/homebrew/bin/git'];
|
|
73
75
|
for (const fb of fallbacks) {
|
|
74
76
|
if (existsSync(fb))
|
|
@@ -86,24 +88,103 @@ function resolveRealGit() {
|
|
|
86
88
|
* @param context - Additional key/value context.
|
|
87
89
|
*/
|
|
88
90
|
function emitBlockedError(code, message, context) {
|
|
89
|
-
process.stderr.write(JSON.stringify({
|
|
91
|
+
process.stderr.write(`${JSON.stringify({
|
|
90
92
|
cleo_error: true,
|
|
91
93
|
code,
|
|
92
94
|
message,
|
|
93
95
|
...context,
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
})}\n`);
|
|
97
|
+
process.stderr.write(`[git-shim] BLOCKED: ${message}\n`);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Emit a boundary violation to stderr in a uniform format.
|
|
101
|
+
*
|
|
102
|
+
* @param violation - Predicate-emitted violation.
|
|
103
|
+
* @param subcommand - Git subcommand under inspection.
|
|
104
|
+
*/
|
|
105
|
+
function emitBoundaryViolation(violation, subcommand) {
|
|
106
|
+
emitBlockedError(violation.code, violation.message, {
|
|
107
|
+
boundary: violation.boundary,
|
|
108
|
+
subcommand,
|
|
109
|
+
...violation.context,
|
|
110
|
+
});
|
|
111
|
+
process.stderr.write(`[git-shim] FIX: ${violation.remediation}\n`);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Apply the four T1591 boundary checks for the given subcommand.
|
|
115
|
+
*
|
|
116
|
+
* @param subcommand - Git subcommand (argv[0]).
|
|
117
|
+
* @param args - Remaining argv entries.
|
|
118
|
+
* @returns A boundary violation when blocked, else null.
|
|
119
|
+
*/
|
|
120
|
+
function evaluateBoundaries(subcommand, args) {
|
|
121
|
+
const cwd = process.cwd();
|
|
122
|
+
const active = resolveActiveWorktree(cwd);
|
|
123
|
+
// Boundary (a) — git add path inside worktree (only meaningful when active).
|
|
124
|
+
if (subcommand === 'add' && active) {
|
|
125
|
+
const v = validateAddPaths(args, cwd, active.worktreePath);
|
|
126
|
+
if (v)
|
|
127
|
+
return v;
|
|
128
|
+
}
|
|
129
|
+
// Boundary (b) — commit subject contains a task ID.
|
|
130
|
+
if (subcommand === 'commit') {
|
|
131
|
+
const expected = active ? active.taskId : null;
|
|
132
|
+
const v = validateCommitSubject(args, expected);
|
|
133
|
+
if (v)
|
|
134
|
+
return v;
|
|
135
|
+
}
|
|
136
|
+
// Boundary (c) — merge gated by CLEO_ORCHESTRATE_MERGE.
|
|
137
|
+
if (subcommand === 'merge') {
|
|
138
|
+
const v = validateMergeAllowed(args, {
|
|
139
|
+
CLEO_ORCHESTRATE_MERGE: process.env['CLEO_ORCHESTRATE_MERGE'],
|
|
140
|
+
});
|
|
141
|
+
if (v)
|
|
142
|
+
return v;
|
|
143
|
+
}
|
|
144
|
+
// Boundary (d) — cherry-pick rejects task/T<NUM> sources.
|
|
145
|
+
if (subcommand === 'cherry-pick') {
|
|
146
|
+
const v = validateCherryPickSource(args);
|
|
147
|
+
if (v)
|
|
148
|
+
return v;
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Build a structured audit record for the current invocation.
|
|
154
|
+
*
|
|
155
|
+
* @param outcome - "blocked" | "bypassed-allow-git" | "bypassed-orchestrate-merge".
|
|
156
|
+
* @param boundary - Which boundary fired (a-d, or "denylist").
|
|
157
|
+
* @param code - CLEO error code.
|
|
158
|
+
* @param subcommand - Git subcommand.
|
|
159
|
+
* @param args - Argv tail.
|
|
160
|
+
* @param context - Free-form per-violation context.
|
|
161
|
+
* @returns Fully populated audit record.
|
|
162
|
+
*/
|
|
163
|
+
function buildAuditRecord(outcome, boundary, code, subcommand, args, context) {
|
|
164
|
+
const cwd = process.cwd();
|
|
165
|
+
const active = resolveActiveWorktree(cwd);
|
|
166
|
+
return {
|
|
167
|
+
ts: new Date().toISOString(),
|
|
168
|
+
outcome,
|
|
169
|
+
boundary,
|
|
170
|
+
code,
|
|
171
|
+
subcommand,
|
|
172
|
+
args,
|
|
173
|
+
cwd,
|
|
174
|
+
worktree_path: active?.worktreePath ?? null,
|
|
175
|
+
task_id: active?.taskId ?? null,
|
|
176
|
+
role: process.env['CLEO_AGENT_ROLE'] ?? null,
|
|
177
|
+
context,
|
|
178
|
+
};
|
|
98
179
|
}
|
|
99
180
|
/**
|
|
100
181
|
* Main shim entry point.
|
|
101
182
|
*
|
|
102
|
-
* Reads argv, env, applies the denylist
|
|
103
|
-
* to the real git binary.
|
|
183
|
+
* Reads argv, env, applies the denylist + the boundary fence, and either
|
|
184
|
+
* blocks or passes through to the real git binary.
|
|
104
185
|
*/
|
|
105
186
|
function main() {
|
|
106
|
-
const argv = process.argv.slice(2);
|
|
187
|
+
const argv = process.argv.slice(2);
|
|
107
188
|
const subcommand = argv[0];
|
|
108
189
|
// Fast path: no subcommand → pass through (git with no args shows usage).
|
|
109
190
|
if (!subcommand) {
|
|
@@ -128,11 +209,14 @@ function main() {
|
|
|
128
209
|
process.exit(result.status ?? 1);
|
|
129
210
|
return;
|
|
130
211
|
}
|
|
131
|
-
// Check escape hatch — operator has explicitly permitted this one invocation.
|
|
132
|
-
const allowBranchOps = process.env['CLEO_ALLOW_BRANCH_OPS'] === '1';
|
|
133
212
|
const remainingArgs = argv.slice(1);
|
|
213
|
+
const allowBranchOps = process.env['CLEO_ALLOW_BRANCH_OPS'] === '1';
|
|
214
|
+
const allowGit = process.env['CLEO_ALLOW_GIT'] === '1';
|
|
215
|
+
// ---------------------------------------------------------------------------
|
|
216
|
+
// Layer 1 — T1118 denylist (branch-mutation ops).
|
|
217
|
+
// ---------------------------------------------------------------------------
|
|
134
218
|
const denied = findDeniedOp(subcommand, remainingArgs);
|
|
135
|
-
if (denied && !allowBranchOps) {
|
|
219
|
+
if (denied && !allowBranchOps && !allowGit) {
|
|
136
220
|
const worktreeRoot = process.env['CLEO_WORKTREE_ROOT'] ?? '(unknown)';
|
|
137
221
|
emitBlockedError('E_GIT_OP_BLOCKED', `git ${subcommand}${denied.flag ? ` ${denied.flag}` : ''} is not allowed for role '${role}': ${denied.reason}`, {
|
|
138
222
|
subcommand,
|
|
@@ -140,15 +224,36 @@ function main() {
|
|
|
140
224
|
role,
|
|
141
225
|
worktree_root: worktreeRoot,
|
|
142
226
|
});
|
|
227
|
+
writeAuditRecord(buildAuditRecord('blocked', 'denylist', 'E_GIT_OP_BLOCKED', subcommand, remainingArgs, {
|
|
228
|
+
flag: denied.flag ?? '',
|
|
229
|
+
reason: denied.reason,
|
|
230
|
+
}));
|
|
231
|
+
process.exit(BLOCKED_EXIT_CODE);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (denied && (allowBranchOps || allowGit)) {
|
|
235
|
+
process.stderr.write(`[git-shim] WARNING: ${allowBranchOps ? 'CLEO_ALLOW_BRANCH_OPS' : 'CLEO_ALLOW_GIT'}=1 ` +
|
|
236
|
+
`bypassed denylist for 'git ${subcommand}' (role=${role}). This bypass is audited.\n`);
|
|
237
|
+
writeAuditRecord(buildAuditRecord('bypassed-allow-git', 'denylist', 'E_GIT_OP_BLOCKED', subcommand, remainingArgs, { flag: denied.flag ?? '', reason: denied.reason }));
|
|
238
|
+
}
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
// Layer 2 — T1591 boundary fence (a/b/c/d).
|
|
241
|
+
// ---------------------------------------------------------------------------
|
|
242
|
+
const violation = evaluateBoundaries(subcommand, remainingArgs);
|
|
243
|
+
if (violation && !allowGit) {
|
|
244
|
+
emitBoundaryViolation(violation, subcommand);
|
|
245
|
+
writeAuditRecord(buildAuditRecord('blocked', violation.boundary, violation.code, subcommand, remainingArgs, violation.context));
|
|
143
246
|
process.exit(BLOCKED_EXIT_CODE);
|
|
144
247
|
return;
|
|
145
248
|
}
|
|
146
|
-
if (
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
249
|
+
if (violation && allowGit) {
|
|
250
|
+
process.stderr.write(`[git-shim] WARNING: CLEO_ALLOW_GIT=1 bypassed boundary ${violation.boundary} ` +
|
|
251
|
+
`(${violation.code}) for 'git ${subcommand}' (role=${role}). This bypass is audited.\n`);
|
|
252
|
+
writeAuditRecord(buildAuditRecord('bypassed-allow-git', violation.boundary, violation.code, subcommand, remainingArgs, violation.context));
|
|
150
253
|
}
|
|
254
|
+
// ---------------------------------------------------------------------------
|
|
151
255
|
// Pass through to real git.
|
|
256
|
+
// ---------------------------------------------------------------------------
|
|
152
257
|
const realGit = resolveRealGit();
|
|
153
258
|
if (!realGit) {
|
|
154
259
|
process.stderr.write('[git-shim] ERROR: real git binary not found on PATH\n');
|
package/dist/shim.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shim.js","sourceRoot":"","sources":["../src/shim.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"shim.js","sourceRoot":"","sources":["../src/shim.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute the canonical worktrees-by-project root used by CLEO.
|
|
3
|
+
*
|
|
4
|
+
* @returns Absolute path to `<XDG>/cleo/worktrees/`.
|
|
5
|
+
*
|
|
6
|
+
* @task T1591
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveCleoWorktreesRoot(): string;
|
|
9
|
+
/**
|
|
10
|
+
* Compute the per-project worktree root.
|
|
11
|
+
*
|
|
12
|
+
* @param projectRoot - Absolute path to the project.
|
|
13
|
+
* @returns Absolute path to `<XDG>/cleo/worktrees/<projectHash>/`.
|
|
14
|
+
*
|
|
15
|
+
* @task T1591
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveProjectWorktreeRoot(projectRoot: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Check whether the given path is inside the canonical worktrees tree.
|
|
20
|
+
*
|
|
21
|
+
* Project-agnostic: matches the global worktrees root, not a specific project.
|
|
22
|
+
*
|
|
23
|
+
* @param cwdPath - Absolute path to check.
|
|
24
|
+
* @returns true if the path is inside `<XDG>/cleo/worktrees/`.
|
|
25
|
+
*
|
|
26
|
+
* @task T1591
|
|
27
|
+
*/
|
|
28
|
+
export declare function isInsideWorktreesRoot(cwdPath: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Extract the task ID from a worktree path.
|
|
31
|
+
*
|
|
32
|
+
* Path layout: `<XDG>/cleo/worktrees/<projectHash>/<taskId>/...`
|
|
33
|
+
* The taskId is the path segment immediately after the projectHash.
|
|
34
|
+
*
|
|
35
|
+
* @param cwdPath - Absolute path inside a worktree.
|
|
36
|
+
* @returns The task ID segment, or null if the path is not inside the worktrees root.
|
|
37
|
+
*
|
|
38
|
+
* @task T1591
|
|
39
|
+
*/
|
|
40
|
+
export declare function extractTaskIdFromWorktreePath(cwdPath: string): string | null;
|
|
41
|
+
/**
|
|
42
|
+
* Resolve the agent worktree boundary for the current shim invocation.
|
|
43
|
+
*
|
|
44
|
+
* Strategy (in order):
|
|
45
|
+
* 1. `CLEO_WORKTREE_ROOT` env — explicit worktree path injected by the spawn prompt.
|
|
46
|
+
* 2. Walk up from `cwd` until a directory under `<XDG>/cleo/worktrees/<projectHash>/<taskId>/`
|
|
47
|
+
* is found.
|
|
48
|
+
* 3. Return null when not inside any worktree.
|
|
49
|
+
*
|
|
50
|
+
* @param cwd - Working directory at shim invocation time.
|
|
51
|
+
* @returns The worktree root path + task ID, or null when not inside a worktree.
|
|
52
|
+
*
|
|
53
|
+
* @task T1591
|
|
54
|
+
*/
|
|
55
|
+
export declare function resolveActiveWorktree(cwd: string): {
|
|
56
|
+
worktreePath: string;
|
|
57
|
+
taskId: string;
|
|
58
|
+
} | null;
|
|
59
|
+
/**
|
|
60
|
+
* Check whether an absolute path lives inside the given worktree.
|
|
61
|
+
*
|
|
62
|
+
* @param targetPath - Absolute path to test.
|
|
63
|
+
* @param worktreePath - Absolute path to the worktree root.
|
|
64
|
+
* @returns true if `targetPath` is the worktree or a descendant.
|
|
65
|
+
*
|
|
66
|
+
* @task T1591
|
|
67
|
+
*/
|
|
68
|
+
export declare function isPathInsideWorktree(targetPath: string, worktreePath: string): boolean;
|
|
69
|
+
//# sourceMappingURL=worktree-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree-path.d.ts","sourceRoot":"","sources":["../src/worktree-path.ts"],"names":[],"mappings":"AAqBA;;;;;;GAMG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAGjD;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAGtE;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAS9D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe5E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,GACV;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA+BjD;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAItF"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worktree-path resolution for the git-shim (T1591 L2 boundary fence).
|
|
3
|
+
*
|
|
4
|
+
* Mirrors `@cleocode/core::resolveAgentWorktreeRoot` so the shim can decide
|
|
5
|
+
* "is this `cwd` inside an agent worktree?" without taking a runtime
|
|
6
|
+
* dependency on `@cleocode/core` (the shim must stay lean — it spawns on every
|
|
7
|
+
* git invocation).
|
|
8
|
+
*
|
|
9
|
+
* The shim resolves the worktree root via XDG env-paths convention:
|
|
10
|
+
* `$XDG_DATA_HOME/cleo/worktrees/<projectHash>/<taskId>/`
|
|
11
|
+
* fallback: `~/.local/share/cleo/worktrees/<projectHash>/<taskId>/`
|
|
12
|
+
*
|
|
13
|
+
* `<projectHash>` is sha256(projectRoot)[:16].
|
|
14
|
+
*
|
|
15
|
+
* @task T1591
|
|
16
|
+
* @adr ADR-062
|
|
17
|
+
*/
|
|
18
|
+
import { createHash } from 'node:crypto';
|
|
19
|
+
import { homedir } from 'node:os';
|
|
20
|
+
import { isAbsolute, join, normalize, resolve } from 'node:path';
|
|
21
|
+
/**
|
|
22
|
+
* Compute the canonical worktrees-by-project root used by CLEO.
|
|
23
|
+
*
|
|
24
|
+
* @returns Absolute path to `<XDG>/cleo/worktrees/`.
|
|
25
|
+
*
|
|
26
|
+
* @task T1591
|
|
27
|
+
*/
|
|
28
|
+
export function resolveCleoWorktreesRoot() {
|
|
29
|
+
const xdgData = process.env['XDG_DATA_HOME'] ?? join(homedir(), '.local', 'share');
|
|
30
|
+
return join(xdgData, 'cleo', 'worktrees');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Compute the per-project worktree root.
|
|
34
|
+
*
|
|
35
|
+
* @param projectRoot - Absolute path to the project.
|
|
36
|
+
* @returns Absolute path to `<XDG>/cleo/worktrees/<projectHash>/`.
|
|
37
|
+
*
|
|
38
|
+
* @task T1591
|
|
39
|
+
*/
|
|
40
|
+
export function resolveProjectWorktreeRoot(projectRoot) {
|
|
41
|
+
const projectHash = createHash('sha256').update(projectRoot).digest('hex').slice(0, 16);
|
|
42
|
+
return join(resolveCleoWorktreesRoot(), projectHash);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Check whether the given path is inside the canonical worktrees tree.
|
|
46
|
+
*
|
|
47
|
+
* Project-agnostic: matches the global worktrees root, not a specific project.
|
|
48
|
+
*
|
|
49
|
+
* @param cwdPath - Absolute path to check.
|
|
50
|
+
* @returns true if the path is inside `<XDG>/cleo/worktrees/`.
|
|
51
|
+
*
|
|
52
|
+
* @task T1591
|
|
53
|
+
*/
|
|
54
|
+
export function isInsideWorktreesRoot(cwdPath) {
|
|
55
|
+
const worktreesRoot = resolveCleoWorktreesRoot();
|
|
56
|
+
const normalized = resolve(cwdPath);
|
|
57
|
+
const normalizedRoot = resolve(worktreesRoot);
|
|
58
|
+
return (normalized === normalizedRoot ||
|
|
59
|
+
normalized.startsWith(`${normalizedRoot}/`) ||
|
|
60
|
+
normalized.startsWith(`${normalizedRoot}\\`));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Extract the task ID from a worktree path.
|
|
64
|
+
*
|
|
65
|
+
* Path layout: `<XDG>/cleo/worktrees/<projectHash>/<taskId>/...`
|
|
66
|
+
* The taskId is the path segment immediately after the projectHash.
|
|
67
|
+
*
|
|
68
|
+
* @param cwdPath - Absolute path inside a worktree.
|
|
69
|
+
* @returns The task ID segment, or null if the path is not inside the worktrees root.
|
|
70
|
+
*
|
|
71
|
+
* @task T1591
|
|
72
|
+
*/
|
|
73
|
+
export function extractTaskIdFromWorktreePath(cwdPath) {
|
|
74
|
+
const worktreesRoot = resolveCleoWorktreesRoot();
|
|
75
|
+
const normalized = resolve(cwdPath);
|
|
76
|
+
const normalizedRoot = resolve(worktreesRoot);
|
|
77
|
+
if (!normalized.startsWith(`${normalizedRoot}/`) &&
|
|
78
|
+
!normalized.startsWith(`${normalizedRoot}\\`)) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
const remainder = normalized.slice(normalizedRoot.length + 1);
|
|
82
|
+
const segments = remainder.split(/[/\\]/).filter(Boolean);
|
|
83
|
+
// segments = [projectHash, taskId, ...rest]
|
|
84
|
+
if (segments.length < 2)
|
|
85
|
+
return null;
|
|
86
|
+
return segments[1] ?? null;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Resolve the agent worktree boundary for the current shim invocation.
|
|
90
|
+
*
|
|
91
|
+
* Strategy (in order):
|
|
92
|
+
* 1. `CLEO_WORKTREE_ROOT` env — explicit worktree path injected by the spawn prompt.
|
|
93
|
+
* 2. Walk up from `cwd` until a directory under `<XDG>/cleo/worktrees/<projectHash>/<taskId>/`
|
|
94
|
+
* is found.
|
|
95
|
+
* 3. Return null when not inside any worktree.
|
|
96
|
+
*
|
|
97
|
+
* @param cwd - Working directory at shim invocation time.
|
|
98
|
+
* @returns The worktree root path + task ID, or null when not inside a worktree.
|
|
99
|
+
*
|
|
100
|
+
* @task T1591
|
|
101
|
+
*/
|
|
102
|
+
export function resolveActiveWorktree(cwd) {
|
|
103
|
+
// Explicit env-driven path wins.
|
|
104
|
+
const envWorktree = process.env['CLEO_WORKTREE_ROOT'];
|
|
105
|
+
if (envWorktree && isAbsolute(envWorktree)) {
|
|
106
|
+
const taskId = process.env['CLEO_TASK_ID'] ?? extractTaskIdFromWorktreePath(envWorktree);
|
|
107
|
+
if (taskId) {
|
|
108
|
+
return { worktreePath: resolve(envWorktree), taskId };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Walk up from cwd until we find a path that matches the worktree layout.
|
|
112
|
+
if (!isInsideWorktreesRoot(cwd))
|
|
113
|
+
return null;
|
|
114
|
+
const worktreesRoot = resolve(resolveCleoWorktreesRoot());
|
|
115
|
+
let candidate = resolve(cwd);
|
|
116
|
+
// Climb until parent is the projectHash directory (one level under worktreesRoot).
|
|
117
|
+
while (candidate !== '/' && candidate.length > worktreesRoot.length) {
|
|
118
|
+
const parent = normalize(join(candidate, '..'));
|
|
119
|
+
// parent should be `<worktreesRoot>/<projectHash>`.
|
|
120
|
+
if (parent.startsWith(`${worktreesRoot}/`) &&
|
|
121
|
+
parent.split(/[/\\]/).filter(Boolean).length ===
|
|
122
|
+
worktreesRoot.split(/[/\\]/).filter(Boolean).length + 1) {
|
|
123
|
+
const taskId = candidate.split(/[/\\]/).pop() ?? '';
|
|
124
|
+
return taskId ? { worktreePath: candidate, taskId } : null;
|
|
125
|
+
}
|
|
126
|
+
if (parent === candidate)
|
|
127
|
+
break;
|
|
128
|
+
candidate = parent;
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Check whether an absolute path lives inside the given worktree.
|
|
134
|
+
*
|
|
135
|
+
* @param targetPath - Absolute path to test.
|
|
136
|
+
* @param worktreePath - Absolute path to the worktree root.
|
|
137
|
+
* @returns true if `targetPath` is the worktree or a descendant.
|
|
138
|
+
*
|
|
139
|
+
* @task T1591
|
|
140
|
+
*/
|
|
141
|
+
export function isPathInsideWorktree(targetPath, worktreePath) {
|
|
142
|
+
const t = resolve(targetPath);
|
|
143
|
+
const w = resolve(worktreePath);
|
|
144
|
+
return t === w || t.startsWith(`${w}/`) || t.startsWith(`${w}\\`);
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=worktree-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree-path.js","sourceRoot":"","sources":["../src/worktree-path.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cleocode/git-shim",
|
|
3
|
-
"version": "2026.4.
|
|
3
|
+
"version": "2026.4.157",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Harness-agnostic git shim for CLEO agent branch-protection (T1118)",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"author": "CLEO Code <hello@cleocode.dev>",
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@cleocode/contracts": "2026.4.
|
|
35
|
+
"@cleocode/contracts": "2026.4.157"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/node": "^24.3.0",
|