ctxr-cli 0.4.0 → 0.4.1
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/adapters/harness/claude-code.d.ts +0 -6
- package/dist/adapters/harness/claude-code.d.ts.map +1 -1
- package/dist/adapters/harness/claude-code.js +44 -25
- package/dist/adapters/harness/claude-code.js.map +1 -1
- package/dist/adapters/types.d.ts +28 -9
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/commands/adapters-generate.d.ts.map +1 -1
- package/dist/commands/adapters-generate.js +15 -3
- package/dist/commands/adapters-generate.js.map +1 -1
- package/dist/commands/adapters-write-gate.d.ts +20 -0
- package/dist/commands/adapters-write-gate.d.ts.map +1 -0
- package/dist/commands/adapters-write-gate.js +77 -0
- package/dist/commands/adapters-write-gate.js.map +1 -0
- package/dist/commands/init.js +6 -6
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/session-land.d.ts.map +1 -1
- package/dist/commands/session-land.js +55 -24
- package/dist/commands/session-land.js.map +1 -1
- package/dist/commands/verify.js +17 -17
- package/dist/commands/verify.js.map +1 -1
- package/dist/config/defaults.d.ts +2 -2
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +2 -2
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/schema.d.ts +18 -4
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +36 -4
- package/dist/config/schema.js.map +1 -1
- package/dist/core/agents-doc.d.ts +13 -9
- package/dist/core/agents-doc.d.ts.map +1 -1
- package/dist/core/agents-doc.js +55 -124
- package/dist/core/agents-doc.js.map +1 -1
- package/dist/core/conventions.d.ts +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +2 -1
- package/dist/core/errors.js.map +1 -1
- package/dist/core/git/repo.d.ts +10 -0
- package/dist/core/git/repo.d.ts.map +1 -1
- package/dist/core/git/repo.js +28 -0
- package/dist/core/git/repo.js.map +1 -1
- package/dist/core/git/worktree.d.ts +8 -0
- package/dist/core/git/worktree.d.ts.map +1 -1
- package/dist/core/git/worktree.js +11 -0
- package/dist/core/git/worktree.js.map +1 -1
- package/dist/core/hooks.d.ts +10 -0
- package/dist/core/hooks.d.ts.map +1 -1
- package/dist/core/hooks.js +37 -10
- package/dist/core/hooks.js.map +1 -1
- package/dist/core/json-config-merge.d.ts +26 -2
- package/dist/core/json-config-merge.d.ts.map +1 -1
- package/dist/core/json-config-merge.js +61 -7
- package/dist/core/json-config-merge.js.map +1 -1
- package/dist/core/migrations/registry.d.ts.map +1 -1
- package/dist/core/migrations/registry.js +2 -1
- package/dist/core/migrations/registry.js.map +1 -1
- package/dist/core/migrations/rename-procedures-path.d.ts +17 -0
- package/dist/core/migrations/rename-procedures-path.d.ts.map +1 -0
- package/dist/core/migrations/rename-procedures-path.js +45 -0
- package/dist/core/migrations/rename-procedures-path.js.map +1 -0
- package/dist/core/notes/list.js +3 -3
- package/dist/core/notes/list.js.map +1 -1
- package/dist/core/reconcile.js +2 -2
- package/dist/core/reconcile.js.map +1 -1
- package/dist/core/{procedures.d.ts → skills.d.ts} +12 -12
- package/dist/core/skills.d.ts.map +1 -0
- package/dist/core/{procedures.js → skills.js} +25 -41
- package/dist/core/skills.js.map +1 -0
- package/dist/core/templates.d.ts +20 -0
- package/dist/core/templates.d.ts.map +1 -0
- package/dist/core/templates.js +68 -0
- package/dist/core/templates.js.map +1 -0
- package/dist/core/write-lifecycle/path-gate.d.ts +28 -0
- package/dist/core/write-lifecycle/path-gate.d.ts.map +1 -1
- package/dist/core/write-lifecycle/path-gate.js +78 -22
- package/dist/core/write-lifecycle/path-gate.js.map +1 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +12 -1
- package/dist/run.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/templates/agents/canonical.md +26 -0
- package/templates/agents/capture-and-ingest.md +17 -0
- package/templates/agents/placement-no-layers.md +5 -0
- package/templates/agents/placement.md +7 -0
- package/templates/agents/retrieval-leg-routing.md +14 -0
- package/templates/agents/store-conventions-empty.md +7 -0
- package/templates/agents/store-conventions.md +7 -0
- package/templates/hooks/claude-code-write-gate.sh +15 -0
- package/templates/skills/ctxr-connection-finding.md +1 -1
- package/templates/skills/ctxr-ingest-orchestration.md +1 -1
- package/templates/skills/ctxr-land.md +11 -6
- package/dist/core/procedures.d.ts.map +0 -1
- package/dist/core/procedures.js.map +0 -1
|
@@ -1,9 +1,3 @@
|
|
|
1
1
|
import type { HarnessGenerationAdapter } from '../types.js';
|
|
2
|
-
/**
|
|
3
|
-
* The reference harness-generation adapter. Claude Code loads `@path`
|
|
4
|
-
* references in its memory files, so the generated entry file's whole job
|
|
5
|
-
* is one `@AGENTS.md` line — no convention text is duplicated here, only
|
|
6
|
-
* imported (harness-portability spec's "entry file only imports" rule).
|
|
7
|
-
*/
|
|
8
2
|
export declare const claudeCodeHarnessAdapter: HarnessGenerationAdapter;
|
|
9
3
|
//# sourceMappingURL=claude-code.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../../src/adapters/harness/claude-code.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,
|
|
1
|
+
{"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../../src/adapters/harness/claude-code.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAyB,MAAM,aAAa,CAAC;AAYnF,eAAO,MAAM,wBAAwB,EAAE,wBAwEtC,CAAC"}
|
|
@@ -5,6 +5,8 @@ import path from 'node:path';
|
|
|
5
5
|
* is one `@AGENTS.md` line — no convention text is duplicated here, only
|
|
6
6
|
* imported (harness-portability spec's "entry file only imports" rule).
|
|
7
7
|
*/
|
|
8
|
+
/** Store-relative — where the generated write-gate hook script lands. */
|
|
9
|
+
const HOOK_TARGET_PATH = '.claude/hooks/claude-code-write-gate.sh';
|
|
8
10
|
export const claudeCodeHarnessAdapter = {
|
|
9
11
|
id: 'claude-code',
|
|
10
12
|
kind: 'harness-generation',
|
|
@@ -15,41 +17,58 @@ export const claudeCodeHarnessAdapter = {
|
|
|
15
17
|
},
|
|
16
18
|
permissionConfig: {
|
|
17
19
|
path: '.claude/settings.json',
|
|
20
|
+
hookFile: {
|
|
21
|
+
templateFileName: 'claude-code-write-gate.sh',
|
|
22
|
+
targetPath: HOOK_TARGET_PATH,
|
|
23
|
+
},
|
|
18
24
|
/**
|
|
19
|
-
* task 8.4: deny
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* PATH varies per session, but its PARENT prefix (worktreesPath) does
|
|
23
|
-
* not, so an allow-rule scoped to that whole prefix covers "the active
|
|
24
|
-
* session worktree" generically without needing to know which one is
|
|
25
|
-
* currently checked out.
|
|
25
|
+
* task 8.4 (revised): deny raw `git push`/`git commit`, and deny an
|
|
26
|
+
* edit anywhere under the store root except the active session
|
|
27
|
+
* worktree via a PreToolUse hook rather than a permission rule.
|
|
26
28
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* anything, since there is no nested worktrees directory inside a
|
|
35
|
-
* worktree. An absolute anchor matches the real target path regardless
|
|
36
|
-
* of launch cwd, correctly covering both conventions.
|
|
29
|
+
* A permission rule cannot express that carve-out: Claude Code
|
|
30
|
+
* evaluates deny before allow with no exception mechanism ("a deny rule
|
|
31
|
+
* can't carry allowlist exceptions"), and the default session worktree
|
|
32
|
+
* path is nested INSIDE the store root, so a tree-wide deny would also
|
|
33
|
+
* cover the worktree an allow rule was meant to carve back out — which
|
|
34
|
+
* is exactly the bug this replaces (see proposal.md). A hook resolves
|
|
35
|
+
* the real target path at call time instead, so it has no such gap.
|
|
37
36
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
37
|
+
* `ctxr adapters write-gate` (the hook's target) does the actual
|
|
38
|
+
* decision, reusing `sanctionedPath`'s path resolution via
|
|
39
|
+
* `isWriteInScope` (write-lifecycle/path-gate.ts) so this and the
|
|
40
|
+
* pre-commit path allowlist can never disagree about what counts as an
|
|
41
|
+
* escape.
|
|
42
|
+
*/
|
|
43
|
+
render({ root }) {
|
|
44
|
+
return {
|
|
45
|
+
permissions: {
|
|
46
|
+
deny: ['Bash(git push:*)', 'Bash(git commit:*)'],
|
|
47
|
+
},
|
|
48
|
+
hooks: {
|
|
49
|
+
PreToolUse: [
|
|
50
|
+
{
|
|
51
|
+
matcher: 'Edit|Write|NotebookEdit',
|
|
52
|
+
hooks: [{ type: 'command', command: path.join(root, HOOK_TARGET_PATH) }],
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
/**
|
|
59
|
+
* The deny/allow pair a previous release emitted for the same
|
|
60
|
+
* `{root, worktreesPath}` — reconstructed here (not read back off disk)
|
|
61
|
+
* so `mergeJsonArrayLists` can remove it by exact match, repairing a
|
|
62
|
+
* store whose config was generated before this fix.
|
|
41
63
|
*/
|
|
42
|
-
|
|
43
|
-
// Claude Code's `//` absolute-path marker stands in for the path's own
|
|
44
|
-
// leading slash — strip it here so the result is `//abs/path`, not
|
|
45
|
-
// `///abs/path`.
|
|
64
|
+
retiredRules({ root, worktreesPath }) {
|
|
46
65
|
const absRoot = root.replace(/^\/+/, '').replace(/\/+$/, '');
|
|
47
66
|
const worktreesSegment = worktreesPath.replace(/^\/+|\/+$/g, '');
|
|
48
67
|
const rootGlob = `//${absRoot}/**`;
|
|
49
68
|
const worktreeGlob = `//${absRoot}/${worktreesSegment}/**`;
|
|
50
69
|
return {
|
|
51
70
|
permissions: {
|
|
52
|
-
deny: [`Write(${rootGlob})`, `Edit(${rootGlob})
|
|
71
|
+
deny: [`Write(${rootGlob})`, `Edit(${rootGlob})`],
|
|
53
72
|
allow: [`Write(${worktreeGlob})`, `Edit(${worktreeGlob})`],
|
|
54
73
|
},
|
|
55
74
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../../src/adapters/harness/claude-code.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../../src/adapters/harness/claude-code.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B;;;;;GAKG;AAEH,yEAAyE;AACzE,MAAM,gBAAgB,GAAG,yCAAyC,CAAC;AAEnE,MAAM,CAAC,MAAM,wBAAwB,GAA6B;IAChE,EAAE,EAAE,aAAa;IACjB,IAAI,EAAE,oBAAoB;IAC1B,gBAAgB,EAAE,CAAC;IACnB,aAAa,EAAE,WAAW;IAE1B,MAAM,CAAC,YAAoB;QACzB,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,gBAAgB,EAAE;QAChB,IAAI,EAAE,uBAAuB;QAE7B,QAAQ,EAAE;YACR,gBAAgB,EAAE,2BAA2B;YAC7C,UAAU,EAAE,gBAAgB;SAC7B;QAED;;;;;;;;;;;;;;;;;;WAkBG;QACH,MAAM,CAAC,EAAE,IAAI,EAAyB;YACpC,OAAO;gBACL,WAAW,EAAE;oBACX,IAAI,EAAE,CAAC,kBAAkB,EAAE,oBAAoB,CAAC;iBACjD;gBACD,KAAK,EAAE;oBACL,UAAU,EAAE;wBACV;4BACE,OAAO,EAAE,yBAAyB;4BAClC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC,EAAE,CAAC;yBACzE;qBACF;iBACF;aACF,CAAC;QACJ,CAAC;QAED;;;;;WAKG;QACH,YAAY,CAAC,EAAE,IAAI,EAAE,aAAa,EAAyB;YACzD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC7D,MAAM,gBAAgB,GAAG,aAAa,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YACjE,MAAM,QAAQ,GAAG,KAAK,OAAO,KAAK,CAAC;YACnC,MAAM,YAAY,GAAG,KAAK,OAAO,IAAI,gBAAgB,KAAK,CAAC;YAC3D,OAAO;gBACL,WAAW,EAAE;oBACX,IAAI,EAAE,CAAC,SAAS,QAAQ,GAAG,EAAE,QAAQ,QAAQ,GAAG,CAAC;oBACjD,KAAK,EAAE,CAAC,SAAS,YAAY,GAAG,EAAE,QAAQ,YAAY,GAAG,CAAC;iBAC3D;aACF,CAAC;QACJ,CAAC;KACF;CACF,CAAC"}
|
package/dist/adapters/types.d.ts
CHANGED
|
@@ -28,6 +28,20 @@ export declare const SUPPORTED_ADAPTER_INTERFACE_VERSION: Record<AdapterKind, nu
|
|
|
28
28
|
* placed inside contexture's managed fenced region in that file — never the
|
|
29
29
|
* whole file, so a hand-authored preamble outside the fence survives.
|
|
30
30
|
*/
|
|
31
|
+
/**
|
|
32
|
+
* `root` is the store's absolute filesystem path. Permission-rule paths are
|
|
33
|
+
* anchored there (not written cwd-relative) because a session may be
|
|
34
|
+
* launched with its cwd already inside a worktree rather than at the store
|
|
35
|
+
* root — a cwd-relative rule would then resolve against the wrong directory.
|
|
36
|
+
* `binPath` is this installation's own resolved CLI entrypoint, for a
|
|
37
|
+
* harness whose config needs to shell out back to `ctxr` (a generated hook
|
|
38
|
+
* script). See claude-code.ts's permissionConfig for the concrete case.
|
|
39
|
+
*/
|
|
40
|
+
export interface PermissionConfigInput {
|
|
41
|
+
root: string;
|
|
42
|
+
worktreesPath: string;
|
|
43
|
+
binPath: string;
|
|
44
|
+
}
|
|
31
45
|
export interface HarnessGenerationAdapter extends Adapter<'harness-generation'> {
|
|
32
46
|
/** The harness-specific file this adapter writes, relative to the store root (e.g. "CLAUDE.md"). */
|
|
33
47
|
entryFileName: string;
|
|
@@ -36,17 +50,22 @@ export interface HarnessGenerationAdapter extends Adapter<'harness-generation'>
|
|
|
36
50
|
permissionConfig?: {
|
|
37
51
|
/** Relative to the store root (e.g. ".claude/settings.json"). */
|
|
38
52
|
path: string;
|
|
53
|
+
render(input: PermissionConfigInput): Record<string, unknown>;
|
|
39
54
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
55
|
+
* Rules a previous release of this adapter emitted that the current
|
|
56
|
+
* `render()` no longer does — removed by exact match before the current
|
|
57
|
+
* rules are merged in, so a store whose config was generated by an
|
|
58
|
+
* earlier version converges to the corrected shape. Never touches a rule
|
|
59
|
+
* this adapter has never emitted, including one an operator added by hand.
|
|
45
60
|
*/
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
61
|
+
retiredRules(input: PermissionConfigInput): Record<string, unknown>;
|
|
62
|
+
/** Optional: an additional generated script this harness's config depends on (e.g. a PreToolUse hook). */
|
|
63
|
+
hookFile?: {
|
|
64
|
+
/** Filename under templates/hooks/. */
|
|
65
|
+
templateFileName: string;
|
|
66
|
+
/** Relative to the store root — where the rendered script is installed. */
|
|
67
|
+
targetPath: string;
|
|
68
|
+
};
|
|
50
69
|
};
|
|
51
70
|
}
|
|
52
71
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/adapters/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,MAAM,WAAW,GAAG,oBAAoB,GAAG,OAAO,CAAC;AAEzD,MAAM,WAAW,OAAO,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW;IAC1D,IAAI,EAAE,CAAC,CAAC;IACR,EAAE,EAAE,MAAM,CAAC;IACX,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,eAAO,MAAM,mCAAmC,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAI3E,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,WAAW,wBAAyB,SAAQ,OAAO,CAAC,oBAAoB,CAAC;IAC7E,oGAAoG;IACpG,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACvC,kFAAkF;IAClF,gBAAgB,CAAC,EAAE;QACjB,iEAAiE;QACjE,IAAI,EAAE,MAAM,CAAC;QACb
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/adapters/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,MAAM,WAAW,GAAG,oBAAoB,GAAG,OAAO,CAAC;AAEzD,MAAM,WAAW,OAAO,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW;IAC1D,IAAI,EAAE,CAAC,CAAC;IACR,EAAE,EAAE,MAAM,CAAC;IACX,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,eAAO,MAAM,mCAAmC,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAI3E,CAAC;AAEF;;;;;;GAMG;AACH;;;;;;;;GAQG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,wBAAyB,SAAQ,OAAO,CAAC,oBAAoB,CAAC;IAC7E,oGAAoG;IACpG,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACvC,kFAAkF;IAClF,gBAAgB,CAAC,EAAE;QACjB,iEAAiE;QACjE,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9D;;;;;;WAMG;QACH,YAAY,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpE,0GAA0G;QAC1G,QAAQ,CAAC,EAAE;YACT,uCAAuC;YACvC,gBAAgB,EAAE,MAAM,CAAC;YACzB,2EAA2E;YAC3E,UAAU,EAAE,MAAM,CAAC;SACpB,CAAC;KACH,CAAC;CACH;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,oBAAoB,EAAE,wBAAwB,CAAC;IAC/C,KAAK,EAAE,OAAO,kBAAkB,EAAE,YAAY,CAAC;CAChD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapters-generate.d.ts","sourceRoot":"","sources":["../../src/commands/adapters-generate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"adapters-generate.d.ts","sourceRoot":"","sources":["../../src/commands/adapters-generate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAQ1E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,eAAO,MAAM,QAAQ,EAAE,eAAuC,CAAC;AAE/D,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,0BAA0B,EAAE,CAAC;CACrC;AAED;;;;;;GAMG;AACH,wDAAwD;AACxD,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,0BAA0B,EAAE,CAAC,CA2ChG;AAED,wBAAsB,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,cAAc,CAAC,oBAAoB,CAAC,CAAC,CAWzF"}
|
|
@@ -3,6 +3,7 @@ import { configuredAdapters } from '../adapters/registry.js';
|
|
|
3
3
|
import { agentsMdPath } from '../core/agents-doc.js';
|
|
4
4
|
import { ExitCode } from '../core/exit-codes.js';
|
|
5
5
|
import { upsertFencedRegionInFile } from '../core/fs/fenced-region.js';
|
|
6
|
+
import { installTemplatedHookScript, resolveOwnBinPath } from '../core/hooks.js';
|
|
6
7
|
import { mergeJsonArrayLists } from '../core/json-config-merge.js';
|
|
7
8
|
import { harnessEntryFence } from '../core/markers.js';
|
|
8
9
|
export const requires = { store: 'required' };
|
|
@@ -21,12 +22,23 @@ export async function generateAdapterOutputs(store) {
|
|
|
21
22
|
const { changed } = await upsertFencedRegionInFile(entryPath, harnessEntryFence(adapter.id), adapter.render(agentsMdPath(store.root)));
|
|
22
23
|
files.push({ path: adapter.entryFileName, changed });
|
|
23
24
|
if (adapter.permissionConfig) {
|
|
24
|
-
const
|
|
25
|
-
const rules = adapter.permissionConfig.render({
|
|
25
|
+
const input = {
|
|
26
26
|
root: store.root,
|
|
27
27
|
worktreesPath: store.config.session.worktrees_path,
|
|
28
|
+
binPath: resolveOwnBinPath(),
|
|
29
|
+
};
|
|
30
|
+
let permChanged = false;
|
|
31
|
+
if (adapter.permissionConfig.hookFile) {
|
|
32
|
+
const { changed: hookScriptChanged } = await installTemplatedHookScript(store.root, adapter.permissionConfig.hookFile.targetPath, adapter.permissionConfig.hookFile.templateFileName, { __CONTEXTURE_BIN__: input.binPath });
|
|
33
|
+
permChanged = permChanged || hookScriptChanged;
|
|
34
|
+
}
|
|
35
|
+
const permPath = path.join(store.root, adapter.permissionConfig.path);
|
|
36
|
+
const rules = adapter.permissionConfig.render(input);
|
|
37
|
+
const retired = adapter.permissionConfig.retiredRules(input);
|
|
38
|
+
const { changed: rulesChanged } = await mergeJsonArrayLists(permPath, rules, {
|
|
39
|
+
remove: retired,
|
|
28
40
|
});
|
|
29
|
-
|
|
41
|
+
permChanged = permChanged || rulesChanged;
|
|
30
42
|
files.push({ path: adapter.permissionConfig.path, changed: permChanged });
|
|
31
43
|
}
|
|
32
44
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapters-generate.js","sourceRoot":"","sources":["../../src/commands/adapters-generate.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"adapters-generate.js","sourceRoot":"","sources":["../../src/commands/adapters-generate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { RunEnv } from '../core/env.js';
|
|
2
|
+
import { ExitCode } from '../core/exit-codes.js';
|
|
3
|
+
/**
|
|
4
|
+
* `ctxr adapters write-gate`: the target of the generated Claude Code
|
|
5
|
+
* PreToolUse hook (claude-code.ts's permissionConfig). This is deliberately
|
|
6
|
+
* NOT a normal contexture command — it bypasses the --json envelope
|
|
7
|
+
* entirely and speaks Claude Code's own hook protocol on stdout/exit code,
|
|
8
|
+
* because that protocol is what the harness parses:
|
|
9
|
+
*
|
|
10
|
+
* - deny: a `permissionDecision: "deny"` JSON body on stdout, exit 0.
|
|
11
|
+
* - let normal permission flow apply: exit 0, no output.
|
|
12
|
+
* - the gate's own error (unparseable stdin, no resolvable store): a
|
|
13
|
+
* nonzero exit that is never 2 — exit 2 hard-blocks the tool call
|
|
14
|
+
* regardless of output, and a bug in this gate must never do that; it
|
|
15
|
+
* degrades to "normal permission flow applies" instead.
|
|
16
|
+
*/
|
|
17
|
+
export declare function execute(env: RunEnv, flags?: {
|
|
18
|
+
root?: string;
|
|
19
|
+
}): Promise<ExitCode>;
|
|
20
|
+
//# sourceMappingURL=adapters-write-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters-write-gate.d.ts","sourceRoot":"","sources":["../../src/commands/adapters-write-gate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AA2BjD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAsD3F"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { ExitCode } from '../core/exit-codes.js';
|
|
3
|
+
import { openStore } from '../core/store.js';
|
|
4
|
+
import { isWriteInScope } from '../core/write-lifecycle/path-gate.js';
|
|
5
|
+
const GATED_TOOLS = new Set(['Edit', 'Write', 'NotebookEdit']);
|
|
6
|
+
async function readStdin(stream) {
|
|
7
|
+
const chunks = [];
|
|
8
|
+
for await (const chunk of stream) {
|
|
9
|
+
chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);
|
|
10
|
+
}
|
|
11
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* `ctxr adapters write-gate`: the target of the generated Claude Code
|
|
15
|
+
* PreToolUse hook (claude-code.ts's permissionConfig). This is deliberately
|
|
16
|
+
* NOT a normal contexture command — it bypasses the --json envelope
|
|
17
|
+
* entirely and speaks Claude Code's own hook protocol on stdout/exit code,
|
|
18
|
+
* because that protocol is what the harness parses:
|
|
19
|
+
*
|
|
20
|
+
* - deny: a `permissionDecision: "deny"` JSON body on stdout, exit 0.
|
|
21
|
+
* - let normal permission flow apply: exit 0, no output.
|
|
22
|
+
* - the gate's own error (unparseable stdin, no resolvable store): a
|
|
23
|
+
* nonzero exit that is never 2 — exit 2 hard-blocks the tool call
|
|
24
|
+
* regardless of output, and a bug in this gate must never do that; it
|
|
25
|
+
* degrades to "normal permission flow applies" instead.
|
|
26
|
+
*/
|
|
27
|
+
export async function execute(env, flags = {}) {
|
|
28
|
+
let raw;
|
|
29
|
+
try {
|
|
30
|
+
raw = await readStdin(env.io.stdin);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return ExitCode.Internal;
|
|
34
|
+
}
|
|
35
|
+
let input;
|
|
36
|
+
try {
|
|
37
|
+
input = JSON.parse(raw);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return ExitCode.Internal;
|
|
41
|
+
}
|
|
42
|
+
const toolName = input.tool_name;
|
|
43
|
+
if (!toolName || !GATED_TOOLS.has(toolName)) {
|
|
44
|
+
return ExitCode.Ok;
|
|
45
|
+
}
|
|
46
|
+
const targetPath = input.tool_input?.file_path ?? input.tool_input?.notebook_path;
|
|
47
|
+
if (!targetPath) {
|
|
48
|
+
return ExitCode.Ok;
|
|
49
|
+
}
|
|
50
|
+
const cwd = input.cwd ?? env.cwd;
|
|
51
|
+
const effectiveEnv = cwd === env.cwd ? env : { ...env, cwd };
|
|
52
|
+
let root;
|
|
53
|
+
let config;
|
|
54
|
+
try {
|
|
55
|
+
({ root, config } = await openStore(effectiveEnv, flags));
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return ExitCode.Internal;
|
|
59
|
+
}
|
|
60
|
+
const relativePath = path.relative(root, path.resolve(cwd, targetPath));
|
|
61
|
+
const scope = await isWriteInScope(config, root, relativePath);
|
|
62
|
+
if (scope.inScope) {
|
|
63
|
+
return ExitCode.Ok;
|
|
64
|
+
}
|
|
65
|
+
const reason = `contexture: "${targetPath}" ${scope.reason ?? 'is outside the active session worktree'} in the store at "${root}". ` +
|
|
66
|
+
'Run "ctxr session start" and make this edit inside its worktree instead.';
|
|
67
|
+
const decision = {
|
|
68
|
+
hookSpecificOutput: {
|
|
69
|
+
hookEventName: 'PreToolUse',
|
|
70
|
+
permissionDecision: 'deny',
|
|
71
|
+
permissionDecisionReason: reason,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
env.io.stdout.write(`${JSON.stringify(decision)}\n`);
|
|
75
|
+
return ExitCode.Ok;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=adapters-write-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters-write-gate.js","sourceRoot":"","sources":["../../src/commands/adapters-write-gate.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/init.js
CHANGED
|
@@ -3,12 +3,12 @@ import { mkdir, readFile } from 'node:fs/promises';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { parse as parseYaml } from 'yaml';
|
|
5
5
|
import { z } from 'zod';
|
|
6
|
-
import { DEFAULT_ADAPTERS, DEFAULT_ARCHIVE_PATH, DEFAULT_ROLLUP_STALE_DAYS, DEFAULT_CATALOG_PATH, DEFAULT_CATALOG_SECTION_MAX_BYTES, DEFAULT_CONVENTIONS_PATH, DEFAULT_DERIVED_PATHS, DEFAULT_DIFF_SIZE_CEILING_LINES, DEFAULT_EXCLUDE_PATHS, DEFAULT_HARD_WALLS, DEFAULT_INBOX_PATH, DEFAULT_TRACKING_PARAMS, DEFAULT_INTERNAL_AUDIENCES,
|
|
6
|
+
import { DEFAULT_ADAPTERS, DEFAULT_ARCHIVE_PATH, DEFAULT_ROLLUP_STALE_DAYS, DEFAULT_CATALOG_PATH, DEFAULT_CATALOG_SECTION_MAX_BYTES, DEFAULT_CONVENTIONS_PATH, DEFAULT_DERIVED_PATHS, DEFAULT_DIFF_SIZE_CEILING_LINES, DEFAULT_EXCLUDE_PATHS, DEFAULT_HARD_WALLS, DEFAULT_INBOX_PATH, DEFAULT_TRACKING_PARAMS, DEFAULT_INTERNAL_AUDIENCES, DEFAULT_SKILLS_PATH, DEFAULT_RELATIONS, DEFAULT_GRAPH_SETTINGS, DEFAULT_SESSION_BRANCH_PREFIX, DEFAULT_VISIBILITY_CONTEXT, DEFAULT_VISIBILITY_FIELD_KEY, DEFAULT_WORKSPACES_EXTERNAL, DEFAULT_WORKTREES_PATH, } from '../config/defaults.js';
|
|
7
7
|
import { configPathFor, readConfig } from '../config/load.js';
|
|
8
8
|
import { renderStoreConfig } from '../config/render.js';
|
|
9
9
|
import { SUPPORTED_SCHEMA_VERSION, TaxonomyLayerSchema } from '../config/schema.js';
|
|
10
10
|
import { buildAgentsCanonicalSection, buildAgentsCaptureSection, buildAgentsConventionsSection, buildAgentsLegRoutingSection, buildAgentsPlacementSection, agentsMdPath, } from '../core/agents-doc.js';
|
|
11
|
-
import { syncShippedSkills } from '../core/
|
|
11
|
+
import { syncShippedSkills } from '../core/skills.js';
|
|
12
12
|
import { reconcileStore, WORKTREES_GITIGNORE_FENCE } from '../core/reconcile.js';
|
|
13
13
|
import { isInteractive } from '../core/env.js';
|
|
14
14
|
import { GitIdentityMissingError, InvalidTaxonomyFileError, TaxonomySelectionConflictError, UnknownTaxonomyProfileError, } from '../core/errors.js';
|
|
@@ -133,7 +133,7 @@ async function runInitCore(env, flags) {
|
|
|
133
133
|
disclosure: { internal_audiences: [...DEFAULT_INTERNAL_AUDIENCES], hard_walls: [...DEFAULT_HARD_WALLS], leak_markers: {} },
|
|
134
134
|
ingest: { inbox_path: DEFAULT_INBOX_PATH, tracking_params: [...DEFAULT_TRACKING_PARAMS] },
|
|
135
135
|
organize: { archive_path: DEFAULT_ARCHIVE_PATH, rollup_stale_days: DEFAULT_ROLLUP_STALE_DAYS },
|
|
136
|
-
harness: {
|
|
136
|
+
harness: { skills_path: DEFAULT_SKILLS_PATH, conventions_path: DEFAULT_CONVENTIONS_PATH },
|
|
137
137
|
adapters: [...DEFAULT_ADAPTERS],
|
|
138
138
|
};
|
|
139
139
|
// Round-trips through the schema internally; throws before any byte is written if it doesn't.
|
|
@@ -145,7 +145,7 @@ async function runInitCore(env, flags) {
|
|
|
145
145
|
await buildAgentsLegRoutingSection(root, config);
|
|
146
146
|
await buildAgentsCaptureSection(root, config);
|
|
147
147
|
await buildAgentsPlacementSection(root, config);
|
|
148
|
-
const
|
|
148
|
+
const skillFilesCreated = await syncShippedSkills(root, config);
|
|
149
149
|
await buildAgentsCanonicalSection(root, config);
|
|
150
150
|
await buildAgentsConventionsSection(root, config);
|
|
151
151
|
// One directory per configured layer with a .gitkeep — makes Zettelkasten's
|
|
@@ -165,13 +165,13 @@ async function runInitCore(env, flags) {
|
|
|
165
165
|
const { changed: hookFiles } = await installHooks(root, defaultBranch);
|
|
166
166
|
await configureHooksPath(env.git, root);
|
|
167
167
|
const relConfigPath = path.relative(root, configPath);
|
|
168
|
-
await addPaths(env.git, root, [relConfigPath, '.gitignore', path.relative(root, agentsMdPath(root)), ...layerGitkeeps, ...
|
|
168
|
+
await addPaths(env.git, root, [relConfigPath, '.gitignore', path.relative(root, agentsMdPath(root)), ...layerGitkeeps, ...skillFilesCreated, ...hookFiles]);
|
|
169
169
|
const commitSha = await commitIfStaged(env.git, root, { kind: 'bootstrap' }, 'chore: initialize contexture store');
|
|
170
170
|
return {
|
|
171
171
|
data: {
|
|
172
172
|
root,
|
|
173
173
|
already_initialized: false,
|
|
174
|
-
created: [relConfigPath, '.gitignore', path.relative(root, agentsMdPath(root)), ...layerGitkeeps, ...
|
|
174
|
+
created: [relConfigPath, '.gitignore', path.relative(root, agentsMdPath(root)), ...layerGitkeeps, ...skillFilesCreated, ...hookFiles],
|
|
175
175
|
unchanged: [],
|
|
176
176
|
git: { repository_created: !repositoryAlreadyExists, commit: commitSha, default_branch: defaultBranch },
|
|
177
177
|
taxonomy: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,EACpB,iCAAiC,EACjC,wBAAwB,EACxB,qBAAqB,EACrB,+BAA+B,EAC/B,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,0BAA0B,EAC1B,
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-land.d.ts","sourceRoot":"","sources":["../../src/commands/session-land.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAoB,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAGhF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAe5D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,eAAO,MAAM,QAAQ,EAAE,eAAuC,CAAC;AAE/D,MAAM,WAAW,gBAAgB;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACrF,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,cAAc,CAAC;IAChD,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,WAAW,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAC3B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,gBAAgB,EACvB,QAAQ,GAAE,SAAS,OAAO,EAAqB,GAC9C,OAAO,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"session-land.d.ts","sourceRoot":"","sources":["../../src/commands/session-land.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAoB,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAGhF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAe5D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,eAAO,MAAM,QAAQ,EAAE,eAAuC,CAAC;AAE/D,MAAM,WAAW,gBAAgB;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACrF,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,cAAc,CAAC;IAChD,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,WAAW,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAC3B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,gBAAgB,EACvB,QAAQ,GAAE,SAAS,OAAO,EAAqB,GAC9C,OAAO,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC,CAwE1C"}
|
|
@@ -5,7 +5,7 @@ import { isInteractive } from '../core/env.js';
|
|
|
5
5
|
import { MergeNotConfirmedError, NoForgeConfiguredError, PullRequestClosedError, PullRequestHeadMismatchError, PullRequestNotMergeableError, SessionLandConsentRequiredError, SessionLandOnDefaultBranchError, } from '../core/errors.js';
|
|
6
6
|
import { ExitCode } from '../core/exit-codes.js';
|
|
7
7
|
import { currentBranch } from '../core/git/repo.js';
|
|
8
|
-
import { fetchOrigin, listWorktrees, removeWorktree, deleteBranch, hasRemote } from '../core/git/worktree.js';
|
|
8
|
+
import { fetchOrigin, listWorktrees, mainWorktreePath, removeWorktree, deleteBranch, hasRemote } from '../core/git/worktree.js';
|
|
9
9
|
import { isWorkingTreeClean } from '../core/git/repo.js';
|
|
10
10
|
import { isSessionBranch, isSessionWorktreePath } from '../core/session.js';
|
|
11
11
|
export const requires = { store: 'required' };
|
|
@@ -23,19 +23,31 @@ export async function execute(env, store, flags, registry = BUILTIN_ADAPTERS) {
|
|
|
23
23
|
throw new SessionLandConsentRequiredError();
|
|
24
24
|
}
|
|
25
25
|
const defaultBranch = store.config.git.default_branch;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
// The target comes from exactly one source: --branch names it outright,
|
|
27
|
+
// --pr defers to the pull request's head branch, and with neither it is the
|
|
28
|
+
// branch checked out where the command was invoked. Only the first two are
|
|
29
|
+
// knowable without the forge, so only they can be refused before contacting it.
|
|
30
|
+
const requested = flags.branch ?? (flags.pr === undefined ? await currentBranch(env.git, store.root) : undefined);
|
|
31
|
+
if (requested === defaultBranch) {
|
|
32
|
+
throw new SessionLandOnDefaultBranchError(requested);
|
|
29
33
|
}
|
|
30
34
|
const [forgeAdapter] = configuredAdapters(store.config, 'forge', registry);
|
|
31
35
|
if (!forgeAdapter || !(await forgeAdapter.isAvailable(store.root))) {
|
|
32
36
|
throw new NoForgeConfiguredError();
|
|
33
37
|
}
|
|
34
|
-
const ref = flags.pr !== undefined ? String(flags.pr) :
|
|
38
|
+
const ref = flags.pr !== undefined ? String(flags.pr) : requested;
|
|
35
39
|
let pr = await forgeAdapter.pullRequest(store.root, ref);
|
|
36
|
-
if (
|
|
37
|
-
|
|
40
|
+
if (requested === undefined) {
|
|
41
|
+
// The target IS the head branch, so there is nothing to mismatch — but the
|
|
42
|
+
// default branch is still refused, now on the branch the forge reported.
|
|
43
|
+
if (pr.headBranch === defaultBranch) {
|
|
44
|
+
throw new SessionLandOnDefaultBranchError(pr.headBranch);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else if (pr.headBranch !== requested) {
|
|
48
|
+
throw new PullRequestHeadMismatchError(requested, pr.headBranch);
|
|
38
49
|
}
|
|
50
|
+
const branch = requested ?? pr.headBranch;
|
|
39
51
|
let merged = pr.state === 'merged';
|
|
40
52
|
let gate = 'not_required';
|
|
41
53
|
if (pr.state === 'closed') {
|
|
@@ -62,38 +74,43 @@ export async function execute(env, store, flags, registry = BUILTIN_ADAPTERS) {
|
|
|
62
74
|
pr = after;
|
|
63
75
|
merged = true;
|
|
64
76
|
}
|
|
65
|
-
const
|
|
66
|
-
const
|
|
77
|
+
const clone = await mainWorktreePath(env.git, store.root);
|
|
78
|
+
const sync = await syncCanonicalClone(env, clone, defaultBranch);
|
|
79
|
+
const reap = await reapWorktree(env, store, clone, branch, flags.reap ?? false);
|
|
67
80
|
return outcome(store, branch, pr, gate, merged, sync, reap);
|
|
68
81
|
}
|
|
69
82
|
function gateMessage(pr) {
|
|
70
83
|
return `PR #${pr.number} "${pr.title}" (${pr.url}) — OPEN, MERGEABLE. Merge?`;
|
|
71
84
|
}
|
|
72
|
-
/**
|
|
73
|
-
|
|
74
|
-
|
|
85
|
+
/**
|
|
86
|
+
* D2: fast-forward only, in the store's canonical clone — the checkout the
|
|
87
|
+
* default branch lives in, whichever checkout the command was invoked from
|
|
88
|
+
* (a session worktree, most often). Never checked out, reset, or discarded.
|
|
89
|
+
*/
|
|
90
|
+
async function syncCanonicalClone(env, clone, defaultBranch) {
|
|
91
|
+
const branch = await currentBranch(env.git, clone);
|
|
75
92
|
if (branch !== defaultBranch) {
|
|
76
|
-
return { attempted: false, synced: false, reason:
|
|
93
|
+
return { attempted: false, synced: false, reason: `the canonical clone (${clone}) is not on the default branch` };
|
|
77
94
|
}
|
|
78
|
-
if (!(await hasRemote(env.git,
|
|
95
|
+
if (!(await hasRemote(env.git, clone))) {
|
|
79
96
|
return { attempted: false, synced: false, reason: 'no remote configured' };
|
|
80
97
|
}
|
|
81
|
-
const fetched = await fetchOrigin(env.git,
|
|
98
|
+
const fetched = await fetchOrigin(env.git, clone, defaultBranch);
|
|
82
99
|
if (!fetched) {
|
|
83
100
|
return { attempted: true, synced: false, reason: 'fetch failed' };
|
|
84
101
|
}
|
|
85
|
-
const merge = await env.git.run(['merge', '--ff-only', `origin/${defaultBranch}`], { cwd:
|
|
102
|
+
const merge = await env.git.run(['merge', '--ff-only', `origin/${defaultBranch}`], { cwd: clone, allowFailure: true });
|
|
86
103
|
if (merge.exitCode !== 0) {
|
|
87
104
|
return { attempted: true, synced: false, reason: 'cannot fast-forward (diverged from origin)' };
|
|
88
105
|
}
|
|
89
106
|
return { attempted: true, synced: true };
|
|
90
107
|
}
|
|
91
108
|
/** D3: opt-in, and scoped to a worktree `session start` made — never the one this command is currently running from. */
|
|
92
|
-
async function reapWorktree(env, store, branch, requested) {
|
|
109
|
+
async function reapWorktree(env, store, clone, branch, requested) {
|
|
93
110
|
if (!requested) {
|
|
94
111
|
return { attempted: false, reaped: false, reason: 'pass --reap, or run `ctxr session reap`' };
|
|
95
112
|
}
|
|
96
|
-
const worktrees = await listWorktrees(env.git,
|
|
113
|
+
const worktrees = await listWorktrees(env.git, clone);
|
|
97
114
|
const target = worktrees.find((w) => w.branch === branch);
|
|
98
115
|
if (!target) {
|
|
99
116
|
return { attempted: true, reaped: false, reason: 'no worktree found for this branch' };
|
|
@@ -101,26 +118,40 @@ async function reapWorktree(env, store, branch, requested) {
|
|
|
101
118
|
if (!isSessionBranch(store.config, branch) && !isSessionWorktreePath(store.config, target.path)) {
|
|
102
119
|
return { attempted: true, reaped: false, reason: 'not a session worktree' };
|
|
103
120
|
}
|
|
104
|
-
|
|
121
|
+
// The hazard is the INVOKING directory, not the resolved store root: removing
|
|
122
|
+
// the worktree this process stands in pulls the caller's cwd out from under it.
|
|
123
|
+
if (isInside(env.cwd, target.path)) {
|
|
105
124
|
return {
|
|
106
125
|
attempted: true,
|
|
107
126
|
reaped: false,
|
|
108
|
-
reason:
|
|
127
|
+
reason: `cannot remove the worktree this command is running from; re-run from the canonical clone (${clone}), or run \`ctxr session reap\` there`,
|
|
109
128
|
};
|
|
110
129
|
}
|
|
111
130
|
if (!(await isWorkingTreeClean(env.git, target.path))) {
|
|
112
131
|
return { attempted: true, reaped: false, reason: 'worktree has uncommitted changes' };
|
|
113
132
|
}
|
|
114
|
-
await removeWorktree(env.git,
|
|
115
|
-
await deleteBranch(env.git,
|
|
133
|
+
await removeWorktree(env.git, clone, target.path);
|
|
134
|
+
await deleteBranch(env.git, clone, branch);
|
|
116
135
|
return { attempted: true, reaped: true };
|
|
117
136
|
}
|
|
137
|
+
/** True when `dir` IS `parent` or lies anywhere beneath it. */
|
|
138
|
+
function isInside(dir, parent) {
|
|
139
|
+
const resolved = path.resolve(dir);
|
|
140
|
+
const root = path.resolve(parent);
|
|
141
|
+
return resolved === root || resolved.startsWith(root + path.sep);
|
|
142
|
+
}
|
|
143
|
+
/** A step that did not happen names why, whether or not it was attempted — `attempted` stays on the JSON outcome for callers that distinguish the two. */
|
|
144
|
+
function stepSummary(done, reason) {
|
|
145
|
+
if (done)
|
|
146
|
+
return 'ok';
|
|
147
|
+
return reason ? `skipped: ${reason}` : 'not attempted';
|
|
148
|
+
}
|
|
118
149
|
function outcome(store, branch, pr, gate, merged, sync, reap) {
|
|
119
150
|
const summary = gate === 'declined'
|
|
120
151
|
? `Merge declined for PR #${pr.number}; nothing landed.`
|
|
121
152
|
: `PR #${pr.number} ${merged ? 'merged' : 'not merged'}` +
|
|
122
|
-
`; sync ${sync.synced
|
|
123
|
-
`; reap ${reap.reaped
|
|
153
|
+
`; sync ${stepSummary(sync.synced, sync.reason)}` +
|
|
154
|
+
`; reap ${stepSummary(reap.reaped, reap.reason)}.`;
|
|
124
155
|
return {
|
|
125
156
|
exitCode: ExitCode.Ok,
|
|
126
157
|
data: {
|