ctxr-cli 0.34.0 → 0.36.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.
Files changed (204) hide show
  1. package/README.md +50 -7
  2. package/dist/commands/land.d.ts +1 -1
  3. package/dist/commands/land.d.ts.map +1 -1
  4. package/dist/commands/land.js +8 -4
  5. package/dist/commands/land.js.map +1 -1
  6. package/dist/commands/plugin-build.d.ts +33 -0
  7. package/dist/commands/plugin-build.d.ts.map +1 -0
  8. package/dist/commands/plugin-build.js +51 -0
  9. package/dist/commands/plugin-build.js.map +1 -0
  10. package/dist/commands/publish-check.d.ts.map +1 -1
  11. package/dist/commands/publish-check.js +35 -4
  12. package/dist/commands/publish-check.js.map +1 -1
  13. package/dist/commands/serve.d.ts +3 -0
  14. package/dist/commands/serve.d.ts.map +1 -1
  15. package/dist/commands/serve.js +129 -23
  16. package/dist/commands/serve.js.map +1 -1
  17. package/dist/commands/session-start.d.ts.map +1 -1
  18. package/dist/commands/session-start.js +12 -38
  19. package/dist/commands/session-start.js.map +1 -1
  20. package/dist/commands/session-submit.d.ts.map +1 -1
  21. package/dist/commands/session-submit.js +2 -0
  22. package/dist/commands/session-submit.js.map +1 -1
  23. package/dist/commands/sync.d.ts +50 -0
  24. package/dist/commands/sync.d.ts.map +1 -0
  25. package/dist/commands/sync.js +186 -0
  26. package/dist/commands/sync.js.map +1 -0
  27. package/dist/commands/version.d.ts.map +1 -1
  28. package/dist/commands/version.js +6 -3
  29. package/dist/commands/version.js.map +1 -1
  30. package/dist/config/defaults.d.ts +13 -0
  31. package/dist/config/defaults.d.ts.map +1 -1
  32. package/dist/config/defaults.js +11 -0
  33. package/dist/config/defaults.js.map +1 -1
  34. package/dist/config/schema.d.ts +1 -0
  35. package/dist/config/schema.d.ts.map +1 -1
  36. package/dist/config/schema.js +7 -0
  37. package/dist/config/schema.js.map +1 -1
  38. package/dist/core/approval/sessions.d.ts.map +1 -1
  39. package/dist/core/approval/sessions.js +4 -2
  40. package/dist/core/approval/sessions.js.map +1 -1
  41. package/dist/core/browse/approve.d.ts.map +1 -1
  42. package/dist/core/browse/approve.js +12 -2
  43. package/dist/core/browse/approve.js.map +1 -1
  44. package/dist/core/browse/page-url.d.ts +13 -0
  45. package/dist/core/browse/page-url.d.ts.map +1 -1
  46. package/dist/core/browse/page-url.js +17 -0
  47. package/dist/core/browse/page-url.js.map +1 -1
  48. package/dist/core/browse/pull-preview.d.ts +67 -0
  49. package/dist/core/browse/pull-preview.d.ts.map +1 -0
  50. package/dist/core/browse/pull-preview.js +154 -0
  51. package/dist/core/browse/pull-preview.js.map +1 -0
  52. package/dist/core/browse/webhook.d.ts +38 -0
  53. package/dist/core/browse/webhook.d.ts.map +1 -0
  54. package/dist/core/browse/webhook.js +102 -0
  55. package/dist/core/browse/webhook.js.map +1 -0
  56. package/dist/core/errors.d.ts +16 -0
  57. package/dist/core/errors.d.ts.map +1 -1
  58. package/dist/core/errors.js +27 -0
  59. package/dist/core/errors.js.map +1 -1
  60. package/dist/core/fs/atomic.d.ts +3 -2
  61. package/dist/core/fs/atomic.d.ts.map +1 -1
  62. package/dist/core/fs/atomic.js +3 -2
  63. package/dist/core/fs/atomic.js.map +1 -1
  64. package/dist/core/git/exec.d.ts +16 -1
  65. package/dist/core/git/exec.d.ts.map +1 -1
  66. package/dist/core/git/exec.js +15 -4
  67. package/dist/core/git/exec.js.map +1 -1
  68. package/dist/core/git/fast-forward.d.ts +23 -0
  69. package/dist/core/git/fast-forward.d.ts.map +1 -1
  70. package/dist/core/git/fast-forward.js +24 -0
  71. package/dist/core/git/fast-forward.js.map +1 -1
  72. package/dist/core/git/hardened.d.ts +15 -0
  73. package/dist/core/git/hardened.d.ts.map +1 -0
  74. package/dist/core/git/hardened.js +123 -0
  75. package/dist/core/git/hardened.js.map +1 -0
  76. package/dist/core/install-kind.d.ts +10 -3
  77. package/dist/core/install-kind.d.ts.map +1 -1
  78. package/dist/core/install-kind.js +48 -14
  79. package/dist/core/install-kind.js.map +1 -1
  80. package/dist/core/mcp/cli-runner.d.ts +41 -0
  81. package/dist/core/mcp/cli-runner.d.ts.map +1 -0
  82. package/dist/core/mcp/cli-runner.js +81 -0
  83. package/dist/core/mcp/cli-runner.js.map +1 -0
  84. package/dist/core/mcp/jsonrpc.d.ts +13 -1
  85. package/dist/core/mcp/jsonrpc.d.ts.map +1 -1
  86. package/dist/core/mcp/jsonrpc.js +1 -1
  87. package/dist/core/mcp/jsonrpc.js.map +1 -1
  88. package/dist/core/mcp/member-sessions.d.ts +48 -0
  89. package/dist/core/mcp/member-sessions.d.ts.map +1 -0
  90. package/dist/core/mcp/member-sessions.js +85 -0
  91. package/dist/core/mcp/member-sessions.js.map +1 -0
  92. package/dist/core/mcp/ownership.d.ts +51 -0
  93. package/dist/core/mcp/ownership.d.ts.map +1 -0
  94. package/dist/core/mcp/ownership.js +101 -0
  95. package/dist/core/mcp/ownership.js.map +1 -0
  96. package/dist/core/mcp/paths.d.ts +48 -0
  97. package/dist/core/mcp/paths.d.ts.map +1 -0
  98. package/dist/core/mcp/paths.js +111 -0
  99. package/dist/core/mcp/paths.js.map +1 -0
  100. package/dist/core/mcp/sessions.d.ts +24 -46
  101. package/dist/core/mcp/sessions.d.ts.map +1 -1
  102. package/dist/core/mcp/sessions.js +31 -103
  103. package/dist/core/mcp/sessions.js.map +1 -1
  104. package/dist/core/mcp/tool-map.d.ts +94 -0
  105. package/dist/core/mcp/tool-map.d.ts.map +1 -0
  106. package/dist/core/mcp/tool-map.js +211 -0
  107. package/dist/core/mcp/tool-map.js.map +1 -0
  108. package/dist/core/mcp/tools/capture.d.ts +7 -2
  109. package/dist/core/mcp/tools/capture.d.ts.map +1 -1
  110. package/dist/core/mcp/tools/capture.js +69 -18
  111. package/dist/core/mcp/tools/capture.js.map +1 -1
  112. package/dist/core/mcp/tools/cli.d.ts +97 -0
  113. package/dist/core/mcp/tools/cli.d.ts.map +1 -0
  114. package/dist/core/mcp/tools/cli.js +271 -0
  115. package/dist/core/mcp/tools/cli.js.map +1 -0
  116. package/dist/core/mcp/tools/edit.d.ts +62 -28
  117. package/dist/core/mcp/tools/edit.d.ts.map +1 -1
  118. package/dist/core/mcp/tools/edit.js +182 -153
  119. package/dist/core/mcp/tools/edit.js.map +1 -1
  120. package/dist/core/mcp/tools/files.d.ts +37 -11
  121. package/dist/core/mcp/tools/files.d.ts.map +1 -1
  122. package/dist/core/mcp/tools/files.js +122 -100
  123. package/dist/core/mcp/tools/files.js.map +1 -1
  124. package/dist/core/mcp/tools/index.d.ts +12 -3
  125. package/dist/core/mcp/tools/index.d.ts.map +1 -1
  126. package/dist/core/mcp/tools/index.js +161 -58
  127. package/dist/core/mcp/tools/index.js.map +1 -1
  128. package/dist/core/mcp/tools/sessions.d.ts +145 -0
  129. package/dist/core/mcp/tools/sessions.d.ts.map +1 -0
  130. package/dist/core/mcp/tools/sessions.js +226 -0
  131. package/dist/core/mcp/tools/sessions.js.map +1 -0
  132. package/dist/core/npm-prefix.d.ts +10 -0
  133. package/dist/core/npm-prefix.d.ts.map +1 -0
  134. package/dist/core/npm-prefix.js +11 -0
  135. package/dist/core/npm-prefix.js.map +1 -0
  136. package/dist/core/plugin/build.d.ts +70 -0
  137. package/dist/core/plugin/build.d.ts.map +1 -0
  138. package/dist/core/plugin/build.js +159 -0
  139. package/dist/core/plugin/build.js.map +1 -0
  140. package/dist/core/plugin/routes.d.ts +35 -0
  141. package/dist/core/plugin/routes.d.ts.map +1 -0
  142. package/dist/core/plugin/routes.js +77 -0
  143. package/dist/core/plugin/routes.js.map +1 -0
  144. package/dist/core/plugin/zip.d.ts +17 -0
  145. package/dist/core/plugin/zip.d.ts.map +1 -0
  146. package/dist/core/plugin/zip.js +75 -0
  147. package/dist/core/plugin/zip.js.map +1 -0
  148. package/dist/core/session/start.d.ts +46 -0
  149. package/dist/core/session/start.d.ts.map +1 -0
  150. package/dist/core/session/start.js +33 -0
  151. package/dist/core/session/start.js.map +1 -0
  152. package/dist/core/session/submit.d.ts +7 -0
  153. package/dist/core/session/submit.d.ts.map +1 -1
  154. package/dist/core/session/submit.js +8 -0
  155. package/dist/core/session/submit.js.map +1 -1
  156. package/dist/core/skills.d.ts +20 -2
  157. package/dist/core/skills.d.ts.map +1 -1
  158. package/dist/core/skills.js +56 -3
  159. package/dist/core/skills.js.map +1 -1
  160. package/dist/core/store-update-runner.d.ts +57 -0
  161. package/dist/core/store-update-runner.d.ts.map +1 -0
  162. package/dist/core/{approval/lander.js → store-update-runner.js} +41 -17
  163. package/dist/core/store-update-runner.js.map +1 -0
  164. package/dist/run.d.ts +12 -0
  165. package/dist/run.d.ts.map +1 -1
  166. package/dist/run.js +93 -58
  167. package/dist/run.js.map +1 -1
  168. package/dist/version.d.ts +1 -1
  169. package/dist/version.js +1 -1
  170. package/package.json +1 -1
  171. package/templates/approve/pages-note-pull.md +1 -0
  172. package/templates/conventions/baseline-conventions.md +5 -0
  173. package/templates/mcp/Delete.md +6 -0
  174. package/templates/mcp/Edit.md +6 -5
  175. package/templates/mcp/Glob.md +2 -2
  176. package/templates/mcp/Grep.md +2 -1
  177. package/templates/mcp/Move.md +7 -0
  178. package/templates/mcp/Read.md +4 -4
  179. package/templates/mcp/Write.md +4 -4
  180. package/templates/mcp/ctxr.md +7 -0
  181. package/templates/mcp/ctxr_write.md +8 -0
  182. package/templates/mcp/server-instructions.md +11 -3
  183. package/templates/mcp/session_discard.md +4 -0
  184. package/templates/mcp/session_list.md +7 -0
  185. package/templates/mcp/session_rebase.md +5 -0
  186. package/templates/mcp/session_start.md +7 -0
  187. package/templates/mcp/session_status.md +3 -0
  188. package/templates/mcp/session_submit.md +8 -0
  189. package/templates/plugin/README.md +13 -0
  190. package/templates/plugin/chatgpt-mcp.json +19 -0
  191. package/templates/plugin/chatgpt-plugin.json +13 -0
  192. package/templates/plugin/claude-mcp.json +8 -0
  193. package/templates/plugin/claude-plugin.json +6 -0
  194. package/templates/plugin/page.html +47 -0
  195. package/templates/skills/ctxr-publish.md +2 -1
  196. package/templates/skills/ctxr-upgrade.md +5 -5
  197. package/templates/skills/mcp/_preamble.md +44 -0
  198. package/dist/core/approval/lander.d.ts +0 -38
  199. package/dist/core/approval/lander.d.ts.map +0 -1
  200. package/dist/core/approval/lander.js.map +0 -1
  201. package/dist/core/mcp/drafts.d.ts +0 -30
  202. package/dist/core/mcp/drafts.d.ts.map +0 -1
  203. package/dist/core/mcp/drafts.js +0 -52
  204. package/dist/core/mcp/drafts.js.map +0 -1
@@ -0,0 +1,101 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { existsSync } from 'node:fs';
3
+ import { mkdir, readFile } from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import { writeFileAtomic } from '../fs/atomic.js';
6
+ import { listSessionWorktreeDirs, sessionLabelFromDirName } from '../session.js';
7
+ import { slugifySegment } from '../slug.js';
8
+ /**
9
+ * serve-the-session-lifecycle-to-chat-apps D3 (remote-access spec, *A member
10
+ * works in named sessions of their own*): who started each session over MCP.
11
+ * One JSON file under the canonical checkout's derived cache, keyed by the
12
+ * worktree's directory name, written atomically and only under the surface's
13
+ * write mutex. A record whose worktree is gone — landed, or discarded locally —
14
+ * is dropped on read, and the next write persists the drop. Sessions started
15
+ * locally have no record and are never visible over MCP.
16
+ *
17
+ * A worktree left by the per-member draft of `2026-10-23-serve-the-store-over-mcp`
18
+ * carries no record; it is adopted for the member whose email its label was
19
+ * derived from, so its pull request stays the member's to answer.
20
+ */
21
+ export const OWNERSHIP_VERSION = 1;
22
+ /** D3: the open sessions a member may hold from `session_start`; a capture's session does not count (revision 8). */
23
+ export const MAX_OPEN_SESSIONS = 20;
24
+ const DRAFT_LABEL_PREFIX = 'mcp-draft-';
25
+ /** The ownership record's path under the canonical checkout, beside the read view. */
26
+ export function ownershipFile(canonicalRoot) {
27
+ return path.join(canonicalRoot, '.contexture', 'cache', 'mcp', 'sessions.json');
28
+ }
29
+ /** The label the earlier per-member draft carried: `mcp-draft-<local part>-<8 hex of the email>`. */
30
+ export function draftLabel(email) {
31
+ const local = slugifySegment(email.split('@')[0] ?? 'member').slice(0, 20).replace(/-+$/, '') || 'member';
32
+ const digest = createHash('sha256').update(email.toLowerCase()).digest('hex').slice(0, 8);
33
+ return `${DRAFT_LABEL_PREFIX}${local}-${digest}`;
34
+ }
35
+ export class Ownership {
36
+ canonicalRoot;
37
+ config;
38
+ constructor(canonicalRoot, config) {
39
+ this.canonicalRoot = canonicalRoot;
40
+ this.config = config;
41
+ }
42
+ worktreeExists(name) {
43
+ return existsSync(path.join(this.canonicalRoot, this.config.session.worktrees_path, name));
44
+ }
45
+ /** Every record whose worktree still exists. */
46
+ async read() {
47
+ let parsed = null;
48
+ try {
49
+ parsed = JSON.parse(await readFile(ownershipFile(this.canonicalRoot), 'utf8'));
50
+ }
51
+ catch (err) {
52
+ if (err.code !== 'ENOENT' && !(err instanceof SyntaxError))
53
+ throw err;
54
+ }
55
+ const sessions = {};
56
+ for (const [name, record] of Object.entries(parsed?.sessions ?? {})) {
57
+ if (typeof record?.owner === 'string' && this.worktreeExists(name))
58
+ sessions[name] = record;
59
+ }
60
+ return sessions;
61
+ }
62
+ async persist(sessions) {
63
+ const file = ownershipFile(this.canonicalRoot);
64
+ await mkdir(path.dirname(file), { recursive: true });
65
+ await writeFileAtomic(file, `${JSON.stringify({ version: OWNERSHIP_VERSION, sessions }, null, 2)}\n`);
66
+ }
67
+ /** Under the write mutex. */
68
+ async record(name, record) {
69
+ const sessions = await this.read();
70
+ sessions[name] = { ...record, owner: record.owner.toLowerCase() };
71
+ await this.persist(sessions);
72
+ }
73
+ /** Under the write mutex. */
74
+ async forget(name) {
75
+ const sessions = await this.read();
76
+ delete sessions[name];
77
+ await this.persist(sessions);
78
+ }
79
+ /** The member's sessions on disk, recorded or adopted, by directory name. */
80
+ async ownedBy(email) {
81
+ const who = email.toLowerCase();
82
+ const sessions = await this.read();
83
+ const owned = Object.entries(sessions)
84
+ .filter(([, record]) => record.owner === who)
85
+ .map(([name, record]) => ({ name, record }));
86
+ const draft = draftLabel(who);
87
+ for (const name of await listSessionWorktreeDirs(this.canonicalRoot, this.config)) {
88
+ if (sessions[name] === undefined && sessionLabelFromDirName(this.config, name) === draft)
89
+ owned.push({ name, record: { owner: who, kind: 'session', started_at: null } });
90
+ }
91
+ return owned.sort((a, b) => (a.name < b.name ? -1 : 1));
92
+ }
93
+ /** Every capture session on disk, whoever started it. */
94
+ async captures() {
95
+ return Object.entries(await this.read())
96
+ .filter(([, record]) => record.kind === 'capture')
97
+ .map(([name, record]) => ({ name, record }))
98
+ .sort((a, b) => (a.name < b.name ? -1 : 1));
99
+ }
100
+ }
101
+ //# sourceMappingURL=ownership.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ownership.js","sourceRoot":"","sources":["../../../src/core/mcp/ownership.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;;;;;;;;GAYG;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AACnC,qHAAqH;AACrH,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AACpC,MAAM,kBAAkB,GAAG,YAAY,CAAC;AAgBxC,sFAAsF;AACtF,MAAM,UAAU,aAAa,CAAC,aAAqB;IACjD,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;AAClF,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC;IAC1G,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1F,OAAO,GAAG,kBAAkB,GAAG,KAAK,IAAI,MAAM,EAAE,CAAC;AACnD,CAAC;AAQD,MAAM,OAAO,SAAS;IAED,aAAa;IACb,MAAM;IAFzB,YACmB,aAAqB,EACrB,MAAmB;6BADnB,aAAa;sBACb,MAAM;IACtB,CAAC;IAEI,cAAc,CAAC,IAAY;QACjC,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,CAAC;IAC7F,CAAC;IAED,gDAAgD;IAChD,KAAK,CAAC,IAAI;QACR,IAAI,MAAM,GAAyB,IAAI,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC,CAAkB,CAAC;QAClG,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG,YAAY,WAAW,CAAC;gBAAE,MAAM,GAAG,CAAC;QACnG,CAAC;QACD,MAAM,QAAQ,GAAoC,EAAE,CAAC;QACrD,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,IAAI,EAAE,CAAC,EAAE,CAAC;YACpE,IAAI,OAAO,MAAM,EAAE,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;QAC9F,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,QAAyC;QAC7D,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC/C,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,MAAM,eAAe,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAA0B,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAChI,CAAC;IAED,6BAA6B;IAC7B,KAAK,CAAC,MAAM,CAAC,IAAY,EAAE,MAAuB;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QACnC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QAClE,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAED,6BAA6B;IAC7B,KAAK,CAAC,MAAM,CAAC,IAAY;QACvB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QACnC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtB,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAED,6EAA6E;IAC7E,KAAK,CAAC,OAAO,CAAC,KAAa;QACzB,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,KAAK,GAAiB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;aACjD,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,KAAK,GAAG,CAAC;aAC5C,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QAC/C,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QAC9B,KAAK,MAAM,IAAI,IAAI,MAAM,uBAAuB,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAClF,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,SAAS,IAAI,uBAAuB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,KAAK;gBAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QAC5K,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,yDAAyD;IACzD,KAAK,CAAC,QAAQ;QACZ,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;aACrC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC;aACjD,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;aAC3C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;CACF"}
@@ -0,0 +1,48 @@
1
+ import type { StoreConfig } from '../../config/schema.js';
2
+ import { ToolRefusal } from './jsonrpc.js';
3
+ /**
4
+ * serve-the-session-lifecycle-to-chat-apps D5: what the file tools and the
5
+ * command runners may read and change, as predicates over a store-relative,
6
+ * `/`-separated path. Kept free of any session or snapshot, so the file tools
7
+ * over the served commit, the same tools inside a session, and `ctxr_write`'s
8
+ * before- and after-run checks all ask the same question.
9
+ */
10
+ /** The store's entry document, readable though it is not a note. */
11
+ export declare const ENTRY_DOCUMENT = "AGENTS.md";
12
+ export type ProtectedReason = 'configuration' | 'git' | 'derived' | 'worktrees' | 'skills';
13
+ /**
14
+ * D5, revision 7: the one protected-path predicate. Inside a session a member
15
+ * may change what a local session may change except these: the configuration
16
+ * (it grants MCP scopes), anything whose first segment begins with `.git` —
17
+ * the hooks directory among them, because a commit in a session worktree runs
18
+ * that worktree's hooks on the server — derived and cache paths, the
19
+ * worktrees path, and the managed skills path, which `ctxr update` owns.
20
+ * Null when the path may be changed.
21
+ */
22
+ export declare function protectedReason(rel: string, config: StoreConfig): ProtectedReason | null;
23
+ export declare function protectedRefusal(rel: string, reason: ProtectedReason): ToolRefusal;
24
+ /** D5: the paths the owned skills read that are not notes: templates, house conventions, the mission, the log and the skills. */
25
+ export declare function widenedReadablePrefixes(config: StoreConfig): string[];
26
+ /** Never read or returned, whatever else applies: configuration, `.git`, derived paths and the worktrees path. */
27
+ export declare function neverReadablePrefixes(config: StoreConfig): string[];
28
+ /**
29
+ * D5: hidden from the file tools. `retrieval.exclude_paths` stays hidden — it
30
+ * is the operator's declared intent — except the capture tier, which `Read`
31
+ * marks, and the widened readable set, which the skills need.
32
+ */
33
+ export declare function hiddenPrefixes(config: StoreConfig): string[];
34
+ /** Whether `rel` is a path the file tools may name at all (a file or a directory to search). */
35
+ export declare function nameablePath(rel: string, config: StoreConfig): boolean;
36
+ /** What `Read` answers for, as one predicate: a note, a markdown capture, the entry document, or the widened set. Grep and Glob return nothing else. */
37
+ export declare function readablePath(rel: string, config: StoreConfig): boolean;
38
+ /**
39
+ * The exclusions ripgrep is given: the hidden prefixes that contain nothing in
40
+ * the widened set. A hidden prefix that does contain some (the default
41
+ * `.contexture/` holds the templates) is searched and filtered by
42
+ * `readablePath` afterwards, because a later positive glob would turn
43
+ * ripgrep's exclusions into an allowlist.
44
+ */
45
+ export declare function searchExclusions(config: StoreConfig): string[];
46
+ /** A caller's path as a normalized store-relative one (a leading `/` names the store root); refused when it leaves the store. `''` is the root. */
47
+ export declare function normalizeStorePath(input: string): string;
48
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/paths.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAK1D,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C;;;;;;GAMG;AAEH,oEAAoE;AACpE,eAAO,MAAM,cAAc,cAAc,CAAC;AAE1C,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG,KAAK,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE3F;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,eAAe,GAAG,IAAI,CAOxF;AAUD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,WAAW,CAElF;AAED,iIAAiI;AACjI,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,EAAE,CAQrE;AAED,kHAAkH;AAClH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,EAAE,CAEnE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,EAAE,CAG5D;AAED,gGAAgG;AAChG,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAKtE;AAED,wJAAwJ;AACxJ,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAKtE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,EAAE,CAG9D;AAED,mJAAmJ;AACnJ,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOxD"}
@@ -0,0 +1,111 @@
1
+ import path from 'node:path';
2
+ import { DEFAULT_LOG_PATH } from '../../config/defaults.js';
3
+ import { isUnderAnyPrefix, isUnderPrefix } from '../fs/prefix.js';
4
+ import { admitsNotePath } from '../notes/list.js';
5
+ import { CONFIG_FILE_NAME } from '../root.js';
6
+ import { ToolRefusal } from './jsonrpc.js';
7
+ /**
8
+ * serve-the-session-lifecycle-to-chat-apps D5: what the file tools and the
9
+ * command runners may read and change, as predicates over a store-relative,
10
+ * `/`-separated path. Kept free of any session or snapshot, so the file tools
11
+ * over the served commit, the same tools inside a session, and `ctxr_write`'s
12
+ * before- and after-run checks all ask the same question.
13
+ */
14
+ /** The store's entry document, readable though it is not a note. */
15
+ export const ENTRY_DOCUMENT = 'AGENTS.md';
16
+ /**
17
+ * D5, revision 7: the one protected-path predicate. Inside a session a member
18
+ * may change what a local session may change except these: the configuration
19
+ * (it grants MCP scopes), anything whose first segment begins with `.git` —
20
+ * the hooks directory among them, because a commit in a session worktree runs
21
+ * that worktree's hooks on the server — derived and cache paths, the
22
+ * worktrees path, and the managed skills path, which `ctxr update` owns.
23
+ * Null when the path may be changed.
24
+ */
25
+ export function protectedReason(rel, config) {
26
+ if (rel === CONFIG_FILE_NAME)
27
+ return 'configuration';
28
+ if ((rel.split('/')[0] ?? '').startsWith('.git'))
29
+ return 'git';
30
+ if (isUnderAnyPrefix(rel, config.derived.paths))
31
+ return 'derived';
32
+ if (isUnderPrefix(rel, config.session.worktrees_path))
33
+ return 'worktrees';
34
+ if (isUnderPrefix(rel, config.harness.skills_path))
35
+ return 'skills';
36
+ return null;
37
+ }
38
+ const PROTECTED_WORDS = {
39
+ configuration: 'the store configuration',
40
+ git: "git's own files and the hooks directory, which a commit on the server would run",
41
+ derived: 'a derived or cache path',
42
+ worktrees: 'the session worktrees path',
43
+ skills: 'the managed skills path',
44
+ };
45
+ export function protectedRefusal(rel, reason) {
46
+ return new ToolRefusal('mcp.path_protected', `"${rel}" is ${PROTECTED_WORDS[reason]}, which cannot be changed from here; change it in a local session.`, { path: rel, reason });
47
+ }
48
+ /** D5: the paths the owned skills read that are not notes: templates, house conventions, the mission, the log and the skills. */
49
+ export function widenedReadablePrefixes(config) {
50
+ return [
51
+ config.templates.path,
52
+ config.harness.guidance_path,
53
+ config.harness.skills_path,
54
+ config.organize.log_path ?? DEFAULT_LOG_PATH,
55
+ ...(config.organize.mission_path !== undefined ? [config.organize.mission_path] : []),
56
+ ];
57
+ }
58
+ /** Never read or returned, whatever else applies: configuration, `.git`, derived paths and the worktrees path. */
59
+ export function neverReadablePrefixes(config) {
60
+ return [CONFIG_FILE_NAME, '.git', ...config.derived.paths, config.session.worktrees_path];
61
+ }
62
+ /**
63
+ * D5: hidden from the file tools. `retrieval.exclude_paths` stays hidden — it
64
+ * is the operator's declared intent — except the capture tier, which `Read`
65
+ * marks, and the widened readable set, which the skills need.
66
+ */
67
+ export function hiddenPrefixes(config) {
68
+ const captureRoot = config.ingest.capture_root.replace(/\/+$/, '');
69
+ return [...config.retrieval.exclude_paths.filter((p) => p.replace(/\/+$/, '') !== captureRoot), ...neverReadablePrefixes(config)];
70
+ }
71
+ /** Whether `rel` is a path the file tools may name at all (a file or a directory to search). */
72
+ export function nameablePath(rel, config) {
73
+ if (rel === '')
74
+ return true;
75
+ if (isUnderAnyPrefix(rel, neverReadablePrefixes(config)))
76
+ return false;
77
+ if (isUnderAnyPrefix(rel, widenedReadablePrefixes(config)))
78
+ return true;
79
+ return !isUnderAnyPrefix(rel, hiddenPrefixes(config));
80
+ }
81
+ /** What `Read` answers for, as one predicate: a note, a markdown capture, the entry document, or the widened set. Grep and Glob return nothing else. */
82
+ export function readablePath(rel, config) {
83
+ if (!nameablePath(rel, config) || rel === '')
84
+ return false;
85
+ if (isUnderAnyPrefix(rel, widenedReadablePrefixes(config)))
86
+ return true;
87
+ if (admitsNotePath(rel, config) || rel === ENTRY_DOCUMENT)
88
+ return true;
89
+ return rel.endsWith('.md') && isUnderAnyPrefix(rel, [config.ingest.capture_root]);
90
+ }
91
+ /**
92
+ * The exclusions ripgrep is given: the hidden prefixes that contain nothing in
93
+ * the widened set. A hidden prefix that does contain some (the default
94
+ * `.contexture/` holds the templates) is searched and filtered by
95
+ * `readablePath` afterwards, because a later positive glob would turn
96
+ * ripgrep's exclusions into an allowlist.
97
+ */
98
+ export function searchExclusions(config) {
99
+ const widened = widenedReadablePrefixes(config).map((p) => p.replace(/\/+$/, ''));
100
+ return hiddenPrefixes(config).filter((hidden) => !widened.some((w) => isUnderPrefix(w, hidden)) || isUnderAnyPrefix(hidden, neverReadablePrefixes(config)));
101
+ }
102
+ /** A caller's path as a normalized store-relative one (a leading `/` names the store root); refused when it leaves the store. `''` is the root. */
103
+ export function normalizeStorePath(input) {
104
+ const cleaned = input.trim().replace(/\\/g, '/');
105
+ const normalized = path.posix.normalize(`/${cleaned}`).replace(/^\/+/, '').replace(/\/+$/, '');
106
+ if (normalized === '..' || normalized.startsWith('../') || cleaned.split('/').includes('..')) {
107
+ throw new ToolRefusal('mcp.path_outside_store', `"${input}" is outside the store.`);
108
+ }
109
+ return normalized;
110
+ }
111
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/core/mcp/paths.ts"],"names":[],"mappings":"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"}
@@ -1,19 +1,22 @@
1
1
  import type { StoreConfig } from '../../config/schema.js';
2
2
  import { type ForgeCredentials } from '../forge/credentials.js';
3
- import type { ForgeClient, PullRequest } from '../forge/github.js';
3
+ import type { ForgeClient } from '../forge/github.js';
4
4
  import type { GitRunner } from '../git/exec.js';
5
- import { type PullState } from '../session/remote.js';
5
+ import type { CommitOptions } from '../session/commit.js';
6
+ import { type StartedSession } from '../session/start.js';
6
7
  /**
7
8
  * serve-the-store-over-mcp design.md D9, D13: the write side the MCP surface
8
- * shares between `capture` and the member drafts. Everything it writes is an
9
- * ordinary session — a worktree under the configured worktrees path, on a
10
- * branch under the session prefix, with a pull request — so the approval page
11
- * lists it and `ctxr land` lands it with no MCP-specific path anywhere.
9
+ * shares between its tools. Everything it writes is an ordinary session — a
10
+ * worktree under the configured worktrees path, on a branch under the session
11
+ * prefix, with a pull request — so the approval page lists it and `ctxr land`
12
+ * lands it with no MCP-specific path anywhere.
12
13
  *
13
- * bring-the-session-lifecycle-into-the-cli (Migration Plan, step 2): push,
14
- * publish, remove and the commit call itself are `src/core/session/`'s, shared
15
- * with `ctxr session submit` and `discard`; what stays here is the MCP
16
- * surface's own wording of their failures.
14
+ * serve-the-session-lifecycle-to-chat-apps D3: starting, submitting,
15
+ * rebasing and discarding are `src/core/session/`'s, the same calls
16
+ * `ctxr session <verb>` makes. What stays here is what the MCP layer adds:
17
+ * the server's forge credential on every remote step, the member as commit
18
+ * author, and the surface's wording of a refusal. The per-member draft's
19
+ * helpers are gone with the draft.
17
20
  */
18
21
  export interface WriteDeps {
19
22
  git: GitRunner;
@@ -31,51 +34,26 @@ export interface WriteDeps {
31
34
  /** The store root's path inside its repository, when the caller has already resolved it; asked of git otherwise. */
32
35
  repoPrefix?: string;
33
36
  }
34
- export interface Session {
35
- /** The worktree directory's name: the key the approval page addresses it by. */
36
- name: string;
37
- path: string;
38
- branch: string;
39
- label: string | null;
40
- }
41
- export type { PullState };
42
37
  export declare class WriteRefusal extends Error {
43
38
  readonly code: string;
44
39
  readonly details?: Record<string, unknown> | undefined;
45
40
  constructor(code: string, message: string, details?: Record<string, unknown> | undefined);
46
41
  }
47
- /** One write at a time across `capture`, `Edit` and `Write` (design.md D9, D13). */
42
+ /** One write at a time across every tool that changes a worktree, the ownership record or the forge (design.md D9, D13). */
48
43
  export declare class Mutex {
49
44
  private tail;
50
45
  run<T>(fn: () => Promise<T>): Promise<T>;
51
46
  }
52
- export declare function approvalUrl(deps: WriteDeps, session: Session): string;
53
- /** The session worktrees on disk whose label starts with `labelPrefix`, with their branches. */
54
- export declare function sessionsLabelled(deps: WriteDeps, labelPrefix: string): Promise<Session[]>;
55
- /** What the forge says about the pull requests for `branch`: the open one, else merged, else closed, else none. */
56
- export declare function pullStateFor(deps: WriteDeps, branch: string): Promise<PullState>;
57
- /** A session whose pull request was closed without merging is removed: worktree and local branch (D9, D13). */
58
- export declare function removeSession(deps: WriteDeps, session: Session): Promise<void>;
59
- /** A new session from the freshly fetched default branch, exactly as `ctxr session start` names and places one. */
60
- export declare function startSession(deps: WriteDeps, label: string): Promise<Session>;
61
- /** The store-relative path's location inside the repository, for `git show <branch>:<path>`. */
62
- export declare function repoPathOf(deps: WriteDeps, storeRelative: string): Promise<string>;
63
- /**
64
- * Stages `paths` and commits them authored by the member, with the store's
65
- * hooks running as for any commit. On a refusal the worktree is restored to
66
- * its tip — a draft never keeps a change its pull request does not carry —
67
- * and the hook's output is the refusal (design.md D13).
68
- */
69
- export declare function commitAs(deps: WriteDeps, session: Session, email: string, paths: readonly string[], subject: string, trailer: string): Promise<string>;
70
- export declare function restore(deps: WriteDeps, session: Session): Promise<void>;
47
+ /** The approval page for a session, at the server's own address. */
48
+ export declare function approvalUrl(deps: WriteDeps, sessionName: string): string;
71
49
  /**
72
- * Publishes whatever the session holds that the forge does not, through the
73
- * shared core's idempotent publish, so a retry after any partial failure
74
- * converges on exactly one pull request (design.md D9, D13). An open pull
75
- * request is found, never rewritten: its body is the draft's own.
50
+ * A new session from the freshly fetched default branch, through the core
51
+ * `ctxr session start` calls. A closed pull request's branch stays on the
52
+ * remote, so a generated name the remote already carries is stepped past.
76
53
  */
77
- export declare function publish(deps: WriteDeps, session: Session, pull: {
78
- title: string;
79
- body: string;
80
- }): Promise<PullRequest>;
54
+ export declare function startSession(deps: WriteDeps, label: string | undefined): Promise<StartedSession>;
55
+ /** D3: the member as the commit's author, with a trailer naming them; the recording login commits when the host has no identity. */
56
+ export declare function memberCommit(deps: WriteDeps, email: string, trailer: string): Omit<CommitOptions, 'message'>;
57
+ /** A WriteRefusal or a core refusal, as a refusal the client model can read rather than a protocol error. */
58
+ export declare function asToolRefusal(err: unknown): unknown;
81
59
  //# sourceMappingURL=sessions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/sessions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,EAAoC,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG5F;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,SAAS,CAAC;IACf,8GAA8G;IAC9G,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,gBAAgB,CAAC;IAC9B,KAAK,EAAE,WAAW,CAAC;IACnB,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAClD,GAAG,IAAI,IAAI,CAAC;IACZ,+GAA+G;IAC/G,cAAc,EAAE,MAAM,CAAC;IACvB,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,oHAAoH;IACpH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,YAAa,SAAQ,KAAK;IAEnC,QAAQ,CAAC,IAAI,EAAE,MAAM;IAErB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAH5C,YACW,IAAI,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACN,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA,EAI3C;CACF;AAED,4HAA4H;AAC5H,qBAAa,KAAK;IAChB,OAAO,CAAC,IAAI,CAAuC;IAEnD,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAIvC;CACF;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAExE;AASD;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,cAAc,CAAC,CAYtG;AAED,oIAAoI;AACpI,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,CAE5G;AAED,6GAA6G;AAC7G,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAInD"}
@@ -1,9 +1,8 @@
1
- import path from 'node:path';
1
+ import { ContextureError } from '../errors.js';
2
2
  import { runRemoteGit } from '../forge/credentials.js';
3
- import { addWorktree } from '../git/worktree.js';
4
- import { generateSessionBranchName, listSessionWorktreeDirs, sessionLabelFromDirName, sessionLabelSlug, worktreePathFor } from '../session.js';
5
- import { commitStaged } from '../session/commit.js';
6
- import { firstLines, publishSession, pullStateFor as forgePullState, removeSession as removeSessionWorktree, SessionRemoteError } from '../session/remote.js';
3
+ import { fetchDefaultBranch } from '../session/status.js';
4
+ import { startSession as startCoreSession } from '../session/start.js';
5
+ import { ToolRefusal } from './jsonrpc.js';
7
6
  export class WriteRefusal extends Error {
8
7
  code;
9
8
  details;
@@ -14,7 +13,7 @@ export class WriteRefusal extends Error {
14
13
  this.name = 'WriteRefusal';
15
14
  }
16
15
  }
17
- /** One write at a time across `capture`, `Edit` and `Write` (design.md D9, D13). */
16
+ /** One write at a time across every tool that changes a worktree, the ownership record or the forge (design.md D9, D13). */
18
17
  export class Mutex {
19
18
  tail = Promise.resolve();
20
19
  run(fn) {
@@ -23,52 +22,9 @@ export class Mutex {
23
22
  return next;
24
23
  }
25
24
  }
26
- export function approvalUrl(deps, session) {
27
- return `${deps.baseUrl.replace(/\/+$/, '')}/approve/${encodeURIComponent(session.name)}`;
28
- }
29
- /** The session worktrees on disk whose label starts with `labelPrefix`, with their branches. */
30
- export async function sessionsLabelled(deps, labelPrefix) {
31
- const root = path.join(deps.canonicalRoot, deps.config.session.worktrees_path);
32
- const sessions = [];
33
- for (const name of await listSessionWorktreeDirs(deps.canonicalRoot, deps.config)) {
34
- const label = sessionLabelFromDirName(deps.config, name);
35
- if (label === null || !label.startsWith(labelPrefix))
36
- continue;
37
- const dir = path.join(root, name);
38
- const branch = (await deps.git.run(['symbolic-ref', '--short', 'HEAD'], { cwd: dir, allowFailure: true })).stdout.trim();
39
- if (branch === '')
40
- continue;
41
- sessions.push({ name, path: dir, branch, label });
42
- }
43
- return sessions.sort((a, b) => (a.name < b.name ? -1 : 1));
44
- }
45
- /** What the forge says about the pull requests for `branch`: the open one, else merged, else closed, else none. */
46
- export async function pullStateFor(deps, branch) {
47
- return forgePullState(deps.forge, branch);
48
- }
49
- /** A session whose pull request was closed without merging is removed: worktree and local branch (D9, D13). */
50
- export async function removeSession(deps, session) {
51
- await removeSessionWorktree(deps.git, deps.canonicalRoot, session);
52
- }
53
- /** A new session from the freshly fetched default branch, exactly as `ctxr session start` names and places one. */
54
- export async function startSession(deps, label) {
55
- const slug = sessionLabelSlug(label);
56
- const defaultBranch = deps.config.git.default_branch;
57
- await runRemoteGit(deps.git, deps.credentials, deps.env, ['fetch', '--quiet', 'origin', `+refs/heads/${defaultBranch}:refs/remotes/origin/${defaultBranch}`], {
58
- cwd: deps.canonicalRoot,
59
- allowFailure: true,
60
- });
61
- const hasRemote = (await deps.git.run(['rev-parse', '--verify', '--quiet', `refs/remotes/origin/${defaultBranch}`], { cwd: deps.canonicalRoot, allowFailure: true })).exitCode === 0;
62
- // Names carry a timestamp to the second, and a closed pull request's branch stays on the remote: step past any taken name.
63
- let branch = generateSessionBranchName(deps.config, deps.now(), slug);
64
- for (let step = 1; step <= 60 && (await branchTaken(deps, branch)); step += 1) {
65
- branch = generateSessionBranchName(deps.config, new Date(deps.now().getTime() + step * 1000), slug);
66
- }
67
- const dir = worktreePathFor({ root: deps.canonicalRoot, config: deps.config }, branch);
68
- const added = await addWorktree(deps.git, deps.canonicalRoot, dir, branch, hasRemote ? `origin/${defaultBranch}` : defaultBranch, { allowFailure: true });
69
- if (added.exitCode !== 0)
70
- throw new WriteRefusal('mcp.session_not_started', `A session could not be started: ${firstLines(added.stderr)}`);
71
- return { name: path.basename(dir), path: dir, branch, label: slug };
25
+ /** The approval page for a session, at the server's own address. */
26
+ export function approvalUrl(deps, sessionName) {
27
+ return `${deps.baseUrl.replace(/\/+$/, '')}/approve/${encodeURIComponent(sessionName)}`;
72
28
  }
73
29
  async function branchTaken(deps, branch) {
74
30
  const local = await deps.git.run(['rev-parse', '--verify', '--quiet', `refs/heads/${branch}`], { cwd: deps.canonicalRoot, allowFailure: true });
@@ -77,58 +33,30 @@ async function branchTaken(deps, branch) {
77
33
  const remote = await runRemoteGit(deps.git, deps.credentials, deps.env, ['ls-remote', '--exit-code', 'origin', `refs/heads/${branch}`], { cwd: deps.canonicalRoot, allowFailure: true });
78
34
  return remote.exitCode === 0;
79
35
  }
80
- /** The store-relative path's location inside the repository, for `git show <branch>:<path>`. */
81
- export async function repoPathOf(deps, storeRelative) {
82
- const prefix = deps.repoPrefix ?? (await deps.git.run(['rev-parse', '--show-prefix'], { cwd: deps.canonicalRoot, allowFailure: true })).stdout.trim();
83
- return `${prefix}${storeRelative}`;
84
- }
85
36
  /**
86
- * Stages `paths` and commits them authored by the member, with the store's
87
- * hooks running as for any commit. On a refusal the worktree is restored to
88
- * its tip — a draft never keeps a change its pull request does not carry —
89
- * and the hook's output is the refusal (design.md D13).
37
+ * A new session from the freshly fetched default branch, through the core
38
+ * `ctxr session start` calls. A closed pull request's branch stays on the
39
+ * remote, so a generated name the remote already carries is stepped past.
90
40
  */
91
- export async function commitAs(deps, session, email, paths, subject, trailer) {
92
- const run = (args) => deps.git.run(args, { cwd: session.path, allowFailure: true });
93
- const added = await run(['add', '--', ...paths]);
94
- if (added.exitCode !== 0) {
95
- await restore(deps, session);
96
- throw new WriteRefusal('mcp.commit_refused', `The change could not be staged: ${firstLines(added.stderr)}`);
97
- }
98
- const name = email.split('@')[0] ?? email;
99
- const committed = await commitStaged(deps.git, session.path, deps.env, {
100
- message: subject,
101
- author: { name, email },
102
- trailer: { key: trailer, value: email },
103
- fallbackCommitter: deps.recordingLogin,
104
- });
105
- if (committed.exitCode !== 0) {
106
- await restore(deps, session);
107
- throw new WriteRefusal('mcp.commit_refused', `The store refused the change: ${firstLines(`${committed.stdout}\n${committed.stderr}`, 12)}`);
108
- }
109
- return (await run(['rev-parse', 'HEAD'])).stdout.trim();
110
- }
111
- export async function restore(deps, session) {
112
- await deps.git.run(['reset', '--quiet', '--hard', 'HEAD'], { cwd: session.path, allowFailure: true });
113
- await deps.git.run(['clean', '-fdq'], { cwd: session.path, allowFailure: true });
114
- }
115
- /**
116
- * Publishes whatever the session holds that the forge does not, through the
117
- * shared core's idempotent publish, so a retry after any partial failure
118
- * converges on exactly one pull request (design.md D9, D13). An open pull
119
- * request is found, never rewritten: its body is the draft's own.
120
- */
121
- export async function publish(deps, session, pull) {
122
- try {
123
- return (await publishSession(deps, session, pull)).pull;
124
- }
125
- catch (err) {
126
- if (!(err instanceof SessionRemoteError))
127
- throw err;
128
- if (err.step === 'push') {
129
- throw new WriteRefusal('mcp.push_failed', `The change is saved in its session but could not be pushed yet (${err.detail}). Retry the same call to publish it.`, { session: session.name });
130
- }
131
- throw new WriteRefusal('mcp.pull_request_failed', `The change is pushed but its pull request could not be opened yet (${err.detail}). Retry the same call to open it.`, { session: session.name });
132
- }
41
+ export async function startSession(deps, label) {
42
+ return startCoreSession({
43
+ git: deps.git,
44
+ config: deps.config,
45
+ fetch: (cwd) => fetchDefaultBranch({ git: deps.git, config: deps.config, env: deps.env, credentials: deps.credentials }, cwd),
46
+ now: deps.now,
47
+ branchTaken: (branch) => branchTaken(deps, branch),
48
+ }, deps.canonicalRoot, label);
49
+ }
50
+ /** D3: the member as the commit's author, with a trailer naming them; the recording login commits when the host has no identity. */
51
+ export function memberCommit(deps, email, trailer) {
52
+ return { author: { name: email.split('@')[0] ?? email, email }, trailer: { key: trailer, value: email }, fallbackCommitter: deps.recordingLogin };
53
+ }
54
+ /** A WriteRefusal or a core refusal, as a refusal the client model can read rather than a protocol error. */
55
+ export function asToolRefusal(err) {
56
+ if (err instanceof WriteRefusal)
57
+ return new ToolRefusal(err.code, err.message, err.details);
58
+ if (err instanceof ContextureError)
59
+ return new ToolRefusal(err.finding.code, err.finding.message, err.finding.details);
60
+ return err;
133
61
  }
134
62
  //# sourceMappingURL=sessions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../../src/core/mcp/sessions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../../src/core/mcp/sessions.ts"],"names":[],"mappings":"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"}