@archmax-ai/harness 0.0.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 (351) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +219 -0
  3. package/dist/agent.d.ts +174 -0
  4. package/dist/agent.js +140 -0
  5. package/dist/agent.js.map +1 -0
  6. package/dist/assembly/compose.d.ts +170 -0
  7. package/dist/assembly/compose.js +391 -0
  8. package/dist/assembly/compose.js.map +1 -0
  9. package/dist/assembly/delegation-registry.d.ts +5 -0
  10. package/dist/assembly/delegation-registry.js +118 -0
  11. package/dist/assembly/delegation-registry.js.map +1 -0
  12. package/dist/assembly/index.d.ts +192 -0
  13. package/dist/assembly/index.js +265 -0
  14. package/dist/assembly/index.js.map +1 -0
  15. package/dist/assembly/plain.d.ts +7 -0
  16. package/dist/assembly/plain.js +41 -0
  17. package/dist/assembly/plain.js.map +1 -0
  18. package/dist/authoring-skill/archmax-harness/README.md +76 -0
  19. package/dist/authoring-skill/archmax-harness/SKILL.md +241 -0
  20. package/dist/authoring-skill/archmax-harness/references/backend-integration.md +626 -0
  21. package/dist/authoring-skill/archmax-harness/references/cases.md +41 -0
  22. package/dist/authoring-skill/archmax-harness/references/diagnostics.md +51 -0
  23. package/dist/authoring-skill/archmax-harness/references/hook-and-test-scripts.md +1070 -0
  24. package/dist/authoring-skill/archmax-harness/references/hooks-and-scripts.md +82 -0
  25. package/dist/authoring-skill/archmax-harness/references/wiring.md +101 -0
  26. package/dist/authoring-skill/archmax-harness/references/workflow-schema.md +1631 -0
  27. package/dist/authoring-skill/archmax-harness/references/workflow-yaml.md +241 -0
  28. package/dist/behaviour/support.d.ts +232 -0
  29. package/dist/behaviour/support.js +339 -0
  30. package/dist/behaviour/support.js.map +1 -0
  31. package/dist/cli/banner.d.ts +11 -0
  32. package/dist/cli/banner.js +29 -0
  33. package/dist/cli/banner.js.map +1 -0
  34. package/dist/cli/bootstrap.d.ts +33 -0
  35. package/dist/cli/bootstrap.js +153 -0
  36. package/dist/cli/bootstrap.js.map +1 -0
  37. package/dist/cli/command.d.ts +39 -0
  38. package/dist/cli/command.js +97 -0
  39. package/dist/cli/command.js.map +1 -0
  40. package/dist/cli/state-flow.d.ts +46 -0
  41. package/dist/cli/state-flow.js +268 -0
  42. package/dist/cli/state-flow.js.map +1 -0
  43. package/dist/cli/style.d.ts +41 -0
  44. package/dist/cli/style.js +64 -0
  45. package/dist/cli/style.js.map +1 -0
  46. package/dist/cli/turn.d.ts +41 -0
  47. package/dist/cli/turn.js +161 -0
  48. package/dist/cli/turn.js.map +1 -0
  49. package/dist/cli.d.ts +10 -0
  50. package/dist/cli.js +426 -0
  51. package/dist/cli.js.map +1 -0
  52. package/dist/core/code-description.d.ts +22 -0
  53. package/dist/core/code-description.js +38 -0
  54. package/dist/core/code-description.js.map +1 -0
  55. package/dist/core/deepagents.d.ts +183 -0
  56. package/dist/core/deepagents.js +128 -0
  57. package/dist/core/deepagents.js.map +1 -0
  58. package/dist/core/events.d.ts +350 -0
  59. package/dist/core/events.js +205 -0
  60. package/dist/core/events.js.map +1 -0
  61. package/dist/core/frontmatter.d.ts +15 -0
  62. package/dist/core/frontmatter.js +32 -0
  63. package/dist/core/frontmatter.js.map +1 -0
  64. package/dist/core/listing-redact.d.ts +37 -0
  65. package/dist/core/listing-redact.js +88 -0
  66. package/dist/core/listing-redact.js.map +1 -0
  67. package/dist/core/match.d.ts +26 -0
  68. package/dist/core/match.js +75 -0
  69. package/dist/core/match.js.map +1 -0
  70. package/dist/core/message-readers.d.ts +84 -0
  71. package/dist/core/message-readers.js +159 -0
  72. package/dist/core/message-readers.js.map +1 -0
  73. package/dist/core/messages.d.ts +49 -0
  74. package/dist/core/messages.js +85 -0
  75. package/dist/core/messages.js.map +1 -0
  76. package/dist/core/mount-prompt.d.ts +28 -0
  77. package/dist/core/mount-prompt.js +55 -0
  78. package/dist/core/mount-prompt.js.map +1 -0
  79. package/dist/core/mount-redact.d.ts +28 -0
  80. package/dist/core/mount-redact.js +32 -0
  81. package/dist/core/mount-redact.js.map +1 -0
  82. package/dist/core/mounts.d.ts +88 -0
  83. package/dist/core/mounts.js +147 -0
  84. package/dist/core/mounts.js.map +1 -0
  85. package/dist/core/path-mapping.d.ts +52 -0
  86. package/dist/core/path-mapping.js +113 -0
  87. package/dist/core/path-mapping.js.map +1 -0
  88. package/dist/core/platform-prompt.generated.d.ts +2 -0
  89. package/dist/core/platform-prompt.generated.js +4 -0
  90. package/dist/core/platform-prompt.generated.js.map +1 -0
  91. package/dist/core/prompt.d.ts +42 -0
  92. package/dist/core/prompt.js +75 -0
  93. package/dist/core/prompt.js.map +1 -0
  94. package/dist/core/session-id.d.ts +38 -0
  95. package/dist/core/session-id.js +61 -0
  96. package/dist/core/session-id.js.map +1 -0
  97. package/dist/core/session-store.d.ts +85 -0
  98. package/dist/core/session-store.js +149 -0
  99. package/dist/core/session-store.js.map +1 -0
  100. package/dist/core/session-zone.d.ts +54 -0
  101. package/dist/core/session-zone.js +82 -0
  102. package/dist/core/session-zone.js.map +1 -0
  103. package/dist/core/skill-prompt.d.ts +31 -0
  104. package/dist/core/skill-prompt.js +54 -0
  105. package/dist/core/skill-prompt.js.map +1 -0
  106. package/dist/core/skill-redact.d.ts +15 -0
  107. package/dist/core/skill-redact.js +27 -0
  108. package/dist/core/skill-redact.js.map +1 -0
  109. package/dist/core/skills.d.ts +172 -0
  110. package/dist/core/skills.js +214 -0
  111. package/dist/core/skills.js.map +1 -0
  112. package/dist/core/tool-mocks.d.ts +23 -0
  113. package/dist/core/tool-mocks.js +39 -0
  114. package/dist/core/tool-mocks.js.map +1 -0
  115. package/dist/core/tool-telemetry.d.ts +16 -0
  116. package/dist/core/tool-telemetry.js +40 -0
  117. package/dist/core/tool-telemetry.js.map +1 -0
  118. package/dist/core/usage.d.ts +114 -0
  119. package/dist/core/usage.js +226 -0
  120. package/dist/core/usage.js.map +1 -0
  121. package/dist/core/workspace-context.d.ts +136 -0
  122. package/dist/core/workspace-context.js +178 -0
  123. package/dist/core/workspace-context.js.map +1 -0
  124. package/dist/core/workspace-prompt.d.ts +7 -0
  125. package/dist/core/workspace-prompt.js +102 -0
  126. package/dist/core/workspace-prompt.js.map +1 -0
  127. package/dist/core/workspace-router.d.ts +61 -0
  128. package/dist/core/workspace-router.js +145 -0
  129. package/dist/core/workspace-router.js.map +1 -0
  130. package/dist/core/workspace.d.ts +85 -0
  131. package/dist/core/workspace.js +193 -0
  132. package/dist/core/workspace.js.map +1 -0
  133. package/dist/core/zones.d.ts +181 -0
  134. package/dist/core/zones.js +202 -0
  135. package/dist/core/zones.js.map +1 -0
  136. package/dist/env.d.ts +99 -0
  137. package/dist/env.js +271 -0
  138. package/dist/env.js.map +1 -0
  139. package/dist/index.d.ts +265 -0
  140. package/dist/index.js +197 -0
  141. package/dist/index.js.map +1 -0
  142. package/dist/kernel/kernel.d.ts +192 -0
  143. package/dist/kernel/kernel.js +751 -0
  144. package/dist/kernel/kernel.js.map +1 -0
  145. package/dist/lifecycle/hook-shape.d.ts +44 -0
  146. package/dist/lifecycle/hook-shape.js +66 -0
  147. package/dist/lifecycle/hook-shape.js.map +1 -0
  148. package/dist/lifecycle/runner.d.ts +177 -0
  149. package/dist/lifecycle/runner.js +372 -0
  150. package/dist/lifecycle/runner.js.map +1 -0
  151. package/dist/lifecycle/transcript.d.ts +27 -0
  152. package/dist/lifecycle/transcript.js +43 -0
  153. package/dist/lifecycle/transcript.js.map +1 -0
  154. package/dist/machine/allow.d.ts +65 -0
  155. package/dist/machine/allow.js +107 -0
  156. package/dist/machine/allow.js.map +1 -0
  157. package/dist/machine/delegation.d.ts +9 -0
  158. package/dist/machine/delegation.js +10 -0
  159. package/dist/machine/delegation.js.map +1 -0
  160. package/dist/machine/diagnostic.d.ts +14 -0
  161. package/dist/machine/diagnostic.js +2 -0
  162. package/dist/machine/diagnostic.js.map +1 -0
  163. package/dist/machine/lint-spec.d.ts +4 -0
  164. package/dist/machine/lint-spec.js +266 -0
  165. package/dist/machine/lint-spec.js.map +1 -0
  166. package/dist/machine/load-spec.d.ts +90 -0
  167. package/dist/machine/load-spec.js +120 -0
  168. package/dist/machine/load-spec.js.map +1 -0
  169. package/dist/machine/machine.d.ts +273 -0
  170. package/dist/machine/machine.js +551 -0
  171. package/dist/machine/machine.js.map +1 -0
  172. package/dist/machine/mount-grants.d.ts +25 -0
  173. package/dist/machine/mount-grants.js +24 -0
  174. package/dist/machine/mount-grants.js.map +1 -0
  175. package/dist/machine/slug.d.ts +14 -0
  176. package/dist/machine/slug.js +17 -0
  177. package/dist/machine/slug.js.map +1 -0
  178. package/dist/machine/spec-schema.d.ts +662 -0
  179. package/dist/machine/spec-schema.js +717 -0
  180. package/dist/machine/spec-schema.js.map +1 -0
  181. package/dist/machine/tool-names.d.ts +98 -0
  182. package/dist/machine/tool-names.js +144 -0
  183. package/dist/machine/tool-names.js.map +1 -0
  184. package/dist/machine/triggers.d.ts +114 -0
  185. package/dist/machine/triggers.js +165 -0
  186. package/dist/machine/triggers.js.map +1 -0
  187. package/dist/machine/types.d.ts +186 -0
  188. package/dist/machine/types.js +12 -0
  189. package/dist/machine/types.js.map +1 -0
  190. package/dist/machine/validate-spec.d.ts +42 -0
  191. package/dist/machine/validate-spec.js +29 -0
  192. package/dist/machine/validate-spec.js.map +1 -0
  193. package/dist/machine/variables.d.ts +196 -0
  194. package/dist/machine/variables.js +415 -0
  195. package/dist/machine/variables.js.map +1 -0
  196. package/dist/public/cli.d.ts +15 -0
  197. package/dist/public/cli.js +14 -0
  198. package/dist/public/cli.js.map +1 -0
  199. package/dist/public/messages.d.ts +33 -0
  200. package/dist/public/messages.js +33 -0
  201. package/dist/public/messages.js.map +1 -0
  202. package/dist/public/sandbox.d.ts +99 -0
  203. package/dist/public/sandbox.js +32 -0
  204. package/dist/public/sandbox.js.map +1 -0
  205. package/dist/public/spec.d.ts +147 -0
  206. package/dist/public/spec.js +149 -0
  207. package/dist/public/spec.js.map +1 -0
  208. package/dist/public/testing.d.ts +71 -0
  209. package/dist/public/testing.js +39 -0
  210. package/dist/public/testing.js.map +1 -0
  211. package/dist/rubrics/rubrics.d.ts +135 -0
  212. package/dist/rubrics/rubrics.js +145 -0
  213. package/dist/rubrics/rubrics.js.map +1 -0
  214. package/dist/runtime/contract.d.ts +73 -0
  215. package/dist/runtime/contract.js +96 -0
  216. package/dist/runtime/contract.js.map +1 -0
  217. package/dist/sandbox/assets/parts/core.js +22 -0
  218. package/dist/sandbox/assets/parts/lifecycle-hook.js +47 -0
  219. package/dist/sandbox/bridge.d.ts +16 -0
  220. package/dist/sandbox/bridge.js +95 -0
  221. package/dist/sandbox/bridge.js.map +1 -0
  222. package/dist/sandbox/executor.d.ts +46 -0
  223. package/dist/sandbox/executor.js +119 -0
  224. package/dist/sandbox/executor.js.map +1 -0
  225. package/dist/sandbox/imports.d.ts +33 -0
  226. package/dist/sandbox/imports.js +67 -0
  227. package/dist/sandbox/imports.js.map +1 -0
  228. package/dist/sandbox/prelude.d.ts +12 -0
  229. package/dist/sandbox/prelude.js +51 -0
  230. package/dist/sandbox/prelude.js.map +1 -0
  231. package/dist/sandbox/ptc-gateway.d.ts +104 -0
  232. package/dist/sandbox/ptc-gateway.js +167 -0
  233. package/dist/sandbox/ptc-gateway.js.map +1 -0
  234. package/dist/sandbox/runtime.d.ts +59 -0
  235. package/dist/sandbox/runtime.js +51 -0
  236. package/dist/sandbox/runtime.js.map +1 -0
  237. package/dist/sandbox/tools.d.ts +34 -0
  238. package/dist/sandbox/tools.js +147 -0
  239. package/dist/sandbox/tools.js.map +1 -0
  240. package/dist/sessions/operations.d.ts +79 -0
  241. package/dist/sessions/operations.js +121 -0
  242. package/dist/sessions/operations.js.map +1 -0
  243. package/dist/sessions/resolve.d.ts +97 -0
  244. package/dist/sessions/resolve.js +145 -0
  245. package/dist/sessions/resolve.js.map +1 -0
  246. package/dist/sessions/resume.d.ts +242 -0
  247. package/dist/sessions/resume.js +288 -0
  248. package/dist/sessions/resume.js.map +1 -0
  249. package/dist/sessions/scope.d.ts +99 -0
  250. package/dist/sessions/scope.js +145 -0
  251. package/dist/sessions/scope.js.map +1 -0
  252. package/dist/sessions/summary.d.ts +65 -0
  253. package/dist/sessions/summary.js +56 -0
  254. package/dist/sessions/summary.js.map +1 -0
  255. package/dist/testing/assertions.d.ts +30 -0
  256. package/dist/testing/assertions.js +231 -0
  257. package/dist/testing/assertions.js.map +1 -0
  258. package/dist/testing/case-document.d.ts +141 -0
  259. package/dist/testing/case-document.js +51 -0
  260. package/dist/testing/case-document.js.map +1 -0
  261. package/dist/testing/case-schema.d.ts +29 -0
  262. package/dist/testing/case-schema.js +519 -0
  263. package/dist/testing/case-schema.js.map +1 -0
  264. package/dist/testing/discovery.d.ts +10 -0
  265. package/dist/testing/discovery.js +24 -0
  266. package/dist/testing/discovery.js.map +1 -0
  267. package/dist/testing/driver.d.ts +78 -0
  268. package/dist/testing/driver.js +117 -0
  269. package/dist/testing/driver.js.map +1 -0
  270. package/dist/testing/grade.d.ts +116 -0
  271. package/dist/testing/grade.js +261 -0
  272. package/dist/testing/grade.js.map +1 -0
  273. package/dist/testing/interpreter.d.ts +55 -0
  274. package/dist/testing/interpreter.js +103 -0
  275. package/dist/testing/interpreter.js.map +1 -0
  276. package/dist/testing/mock-middleware.d.ts +5 -0
  277. package/dist/testing/mock-middleware.js +33 -0
  278. package/dist/testing/mock-middleware.js.map +1 -0
  279. package/dist/testing/runner.d.ts +205 -0
  280. package/dist/testing/runner.js +266 -0
  281. package/dist/testing/runner.js.map +1 -0
  282. package/dist/testing/target.d.ts +27 -0
  283. package/dist/testing/target.js +21 -0
  284. package/dist/testing/target.js.map +1 -0
  285. package/dist/validate/validate.d.ts +41 -0
  286. package/dist/validate/validate.js +669 -0
  287. package/dist/validate/validate.js.map +1 -0
  288. package/dist/workflow/agent-tools.d.ts +10 -0
  289. package/dist/workflow/agent-tools.js +10 -0
  290. package/dist/workflow/agent-tools.js.map +1 -0
  291. package/dist/workflow/checkpointer.d.ts +52 -0
  292. package/dist/workflow/checkpointer.js +200 -0
  293. package/dist/workflow/checkpointer.js.map +1 -0
  294. package/dist/workflow/control-tools.d.ts +174 -0
  295. package/dist/workflow/control-tools.js +468 -0
  296. package/dist/workflow/control-tools.js.map +1 -0
  297. package/dist/workflow/governance.d.ts +104 -0
  298. package/dist/workflow/governance.js +546 -0
  299. package/dist/workflow/governance.js.map +1 -0
  300. package/dist/workflow/middleware.d.ts +85 -0
  301. package/dist/workflow/middleware.js +283 -0
  302. package/dist/workflow/middleware.js.map +1 -0
  303. package/dist/workflow/on-error.d.ts +25 -0
  304. package/dist/workflow/on-error.js +58 -0
  305. package/dist/workflow/on-error.js.map +1 -0
  306. package/dist/workflow/parks.d.ts +46 -0
  307. package/dist/workflow/parks.js +513 -0
  308. package/dist/workflow/parks.js.map +1 -0
  309. package/dist/workflow/paths.d.ts +67 -0
  310. package/dist/workflow/paths.js +108 -0
  311. package/dist/workflow/paths.js.map +1 -0
  312. package/dist/workflow/prompt-cache.d.ts +70 -0
  313. package/dist/workflow/prompt-cache.js +103 -0
  314. package/dist/workflow/prompt-cache.js.map +1 -0
  315. package/dist/workflow/prompt-pruning.d.ts +20 -0
  316. package/dist/workflow/prompt-pruning.js +83 -0
  317. package/dist/workflow/prompt-pruning.js.map +1 -0
  318. package/dist/workflow/render-prompt.d.ts +45 -0
  319. package/dist/workflow/render-prompt.js +140 -0
  320. package/dist/workflow/render-prompt.js.map +1 -0
  321. package/dist/workflow/runtime-config.d.ts +7 -0
  322. package/dist/workflow/runtime-config.js +9 -0
  323. package/dist/workflow/runtime-config.js.map +1 -0
  324. package/dist/workflow/session-artifacts.d.ts +90 -0
  325. package/dist/workflow/session-artifacts.js +134 -0
  326. package/dist/workflow/session-artifacts.js.map +1 -0
  327. package/dist/workflow/session-view.d.ts +31 -0
  328. package/dist/workflow/session-view.js +94 -0
  329. package/dist/workflow/session-view.js.map +1 -0
  330. package/dist/workflow/snapshot.d.ts +14 -0
  331. package/dist/workflow/snapshot.js +97 -0
  332. package/dist/workflow/snapshot.js.map +1 -0
  333. package/dist/workflow/state.d.ts +347 -0
  334. package/dist/workflow/state.js +322 -0
  335. package/dist/workflow/state.js.map +1 -0
  336. package/dist/workflow/sub-workflow.d.ts +174 -0
  337. package/dist/workflow/sub-workflow.js +392 -0
  338. package/dist/workflow/sub-workflow.js.map +1 -0
  339. package/dist/workflow/tool-service.d.ts +48 -0
  340. package/dist/workflow/tool-service.js +291 -0
  341. package/dist/workflow/tool-service.js.map +1 -0
  342. package/dist/workflow/turn-boundary.d.ts +39 -0
  343. package/dist/workflow/turn-boundary.js +128 -0
  344. package/dist/workflow/turn-boundary.js.map +1 -0
  345. package/dist/workflow/turn-runner.d.ts +40 -0
  346. package/dist/workflow/turn-runner.js +122 -0
  347. package/dist/workflow/turn-runner.js.map +1 -0
  348. package/dist/workflow/workflow-tools.d.ts +46 -0
  349. package/dist/workflow/workflow-tools.js +90 -0
  350. package/dist/workflow/workflow-tools.js.map +1 -0
  351. package/package.json +119 -0
@@ -0,0 +1,55 @@
1
+ /**
2
+ * The model-facing account of the governed mounts a state may reach — the mount
3
+ * twin of `renderSkillsSection`, and in the **volatile** system block for the
4
+ * same reason: what varies with the state cannot live in the cacheable prefix.
5
+ *
6
+ * The static "Workspace zones" section therefore names ungoverned mounts only
7
+ * (see {@link renderWorkspaceZones}), and this names what this state was given.
8
+ * A state that reaches none gets no heading rather than an empty one, and
9
+ * therefore no invitation to go looking.
10
+ */
11
+ /** Heading of the rendered section, also the marker tests assert on. */
12
+ export const MOUNTS_SECTION_HEADING = "Mounts available in this state";
13
+ /**
14
+ * Render the section for one state's enabled governed mounts, or `null` when the
15
+ * set is empty.
16
+ *
17
+ * `enabled` is the resolved name order (see `WorkflowMachine.enabledMounts`),
18
+ * sorted here so the text is stable under a spec edit that only reorders a
19
+ * list — a prompt section that reordered itself would churn the transcript for
20
+ * no reason. Each name is printed as the agent addresses it: a directory mount
21
+ * with a trailing slash, a file mount by its exact path, read-only or read/write
22
+ * per `writable` — the state's own posture (`WorkflowMachine.mountWritable`),
23
+ * which a grant's `access: read` may have narrowed below the host's. A mount the
24
+ * host declared unsearchable gets a browse-only note, so the model lists and
25
+ * reads it rather than searching it; every other line is unchanged.
26
+ */
27
+ export function renderMountsSection(enabled, mounts, writable) {
28
+ const files = new Set(mounts.files);
29
+ const bullets = [...enabled].sort().map((name) => {
30
+ const address = files.has(name) ? name : `${name}/`;
31
+ // The state's own posture, not the table's: a grant may narrow a writable
32
+ // mount to reads here, and the prompt has to say what this state can do.
33
+ const posture = writable(name)
34
+ ? "read/write — write there directly when the work belongs there, no less " +
35
+ "freely than in your own working area; the write is checked against this " +
36
+ "state's tool rules like any other"
37
+ : "read-only — read it freely, writes there are blocked";
38
+ const browse = mounts.unsearchable.includes(name)
39
+ ? " Browse only: list and read it directly. Searches from the root leave it out, " +
40
+ "and a search addressed at it is answered by the mount itself."
41
+ : "";
42
+ return `- **\`${address}\`** — ${posture}.${browse}`;
43
+ });
44
+ if (bullets.length === 0)
45
+ return null;
46
+ return [
47
+ `## ${MOUNTS_SECTION_HEADING}`,
48
+ "",
49
+ ...bullets,
50
+ "",
51
+ `Only these mounts are reachable from this state: every other mount's files are blocked ` +
52
+ `here, whatever an earlier state could read.`,
53
+ ].join("\n");
54
+ }
55
+ //# sourceMappingURL=mount-prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount-prompt.js","sourceRoot":"","sources":["../../src/core/mount-prompt.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,wEAAwE;AACxE,MAAM,CAAC,MAAM,sBAAsB,GAAG,gCAAgC,CAAC;AAEvE;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAA0B,EAC1B,MAAqB,EACrB,QAAmC;IAEnC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC;QACpD,0EAA0E;QAC1E,yEAAyE;QACzE,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC;YAC5B,CAAC,CAAC,yEAAyE;gBACzE,0EAA0E;gBAC1E,mCAAmC;YACrC,CAAC,CAAC,sDAAsD,CAAC;QAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC;YAC/C,CAAC,CAAC,gFAAgF;gBAChF,+DAA+D;YACjE,CAAC,CAAC,EAAE,CAAC;QACP,OAAO,SAAS,OAAO,UAAU,OAAO,IAAI,MAAM,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;IACH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO;QACL,MAAM,sBAAsB,EAAE;QAC9B,EAAE;QACF,GAAG,OAAO;QACV,EAAE;QACF,yFAAyF;YACvF,6CAA6C;KAChD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { type MountPrefixes } from "./zones.js";
2
+ /**
3
+ * Keep a mount the state cannot reach out of a *listing* — the mounts half of
4
+ * the shared listing filter (`core/listing-redact.ts`, which carries the
5
+ * reasoning and the line shapes), and the twin of `redactDisabledSkills`.
6
+ *
7
+ * The workspace root listing is the case that matters most: a governed mount the
8
+ * state does not have would otherwise appear at the root as a directory the
9
+ * agent then cannot read, which reads to a model as a broken workspace rather
10
+ * than as a capability it was not given.
11
+ */
12
+ /** What a state may see of the mount table: the kernel's decision, as data. */
13
+ export interface MountVisibility {
14
+ /** The **governed** mounts this state enables (`WorkflowMachine.enabledMounts`). */
15
+ readonly enabled: readonly string[];
16
+ /** Every mount name denied here, governed or not (`forbiddenMounts`). */
17
+ readonly forbidden: readonly string[];
18
+ }
19
+ /**
20
+ * Drop from `text` every line under a mount this state cannot see: a governed
21
+ * mount no list enabled, or any mount a `forbid` names. A path under no mount,
22
+ * and a path under an ungoverned mount nothing denies, is kept — that mount is
23
+ * visible in every state.
24
+ *
25
+ * Returns the text unchanged when nothing was hidden, so a result the filter has
26
+ * no opinion about is passed through by identity rather than rebuilt.
27
+ */
28
+ export declare function redactHiddenMounts(text: string, visibility: MountVisibility, mounts: MountPrefixes): string;
@@ -0,0 +1,32 @@
1
+ import { redactListing } from "./listing-redact.js";
2
+ import { mountNameOf } from "./zones.js";
3
+ /**
4
+ * Drop from `text` every line under a mount this state cannot see: a governed
5
+ * mount no list enabled, or any mount a `forbid` names. A path under no mount,
6
+ * and a path under an ungoverned mount nothing denies, is kept — that mount is
7
+ * visible in every state.
8
+ *
9
+ * Returns the text unchanged when nothing was hidden, so a result the filter has
10
+ * no opinion about is passed through by identity rather than rebuilt.
11
+ */
12
+ export function redactHiddenMounts(text, visibility, mounts) {
13
+ if (!text)
14
+ return text;
15
+ const enabled = new Set(visibility.enabled);
16
+ const forbidden = new Set(visibility.forbidden);
17
+ const hidden = (name) => forbidden.has(name) || (mounts.governed.includes(name) && !enabled.has(name));
18
+ // Nothing to hide: every mount the table serves is reachable from here.
19
+ const names = [...mounts.dirs, ...mounts.files];
20
+ if (!names.some(hidden))
21
+ return text;
22
+ return redactListing(text, (path) => mountNameOf(canonical(path), mounts), hidden);
23
+ }
24
+ /**
25
+ * A result line's path in the form `mountNameOf` classifies: leading slashes
26
+ * stripped, the shape the tools print (`/catalogs/eu/skus.csv`) reduced to the
27
+ * shape the mount table holds.
28
+ */
29
+ function canonical(path) {
30
+ return path.replace(/^\/+/, "").replace(/\/+$/, "");
31
+ }
32
+ //# sourceMappingURL=mount-redact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount-redact.js","sourceRoot":"","sources":["../../src/core/mount-redact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAsB,MAAM,YAAY,CAAC;AAqB7D;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,UAA2B,EAC3B,MAAqB;IAErB,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE,CAC9B,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAChF,wEAAwE;IACxE,MAAM,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,aAAa,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;AACrF,CAAC;AAED;;;;GAIG;AACH,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,88 @@
1
+ import { type BackendProtocolV2 } from "deepagents";
2
+ import { AUTHORING_PREFIXES, authoringPlanePrefix, describeAuthoringPrefix, isAuthoringPrefix, NO_MOUNTS, type AuthoringPrefix, type MountPrefixes } from "./zones.js";
3
+ /**
4
+ * Authored mounts, expressed in the framework's own vocabulary: a
5
+ * {@link CompositeBackend}-style route table of ordinary backends the consumer
6
+ * composes. The runtime owns only the **default route** — the session store, which
7
+ * must catch the runtime's fixed offload paths — and mounts this table beside it.
8
+ *
9
+ * A backend rooted *at* the mounted directory needs no path adaptation: the
10
+ * composite strips the route prefix before delegating and re-applies it to result
11
+ * paths. A consumer serving several mounts from one backend rebases with
12
+ * `mountSubtree` (exported from `core/path-mapping.ts`).
13
+ */
14
+ /**
15
+ * A mount: a backend (read-only), or a backend with its write posture and its
16
+ * governance declared.
17
+ *
18
+ * `governed: true` says the spec decides which **states** may see this mount:
19
+ * it is closed by default and reachable only where a `mounts` list enables it,
20
+ * exactly as a skill bundle is. An ungoverned mount (the default, and every
21
+ * existing table) is visible in every state, and only a `mounts.forbid` takes
22
+ * it away. The consumer owns which backend serves a mount, its write posture
23
+ * and whether it is governed; the spec owns which states enable it, and neither
24
+ * is inferred from the other.
25
+ *
26
+ * `searchable: false` says the runtime must never search this mount on its own
27
+ * initiative: a root-wide `grep` or `glob` leaves it out, so a backend that
28
+ * refuses searches (a remote folder a search would download) cannot fail every
29
+ * root-wide search. A search the agent addresses at the mount still reaches the
30
+ * backend, whose own answer — matches or refusal — is returned verbatim. The
31
+ * flag is inert on a file mount, which is never searched as a tree.
32
+ */
33
+ export type MountSpec = BackendProtocolV2 | {
34
+ backend: BackendProtocolV2;
35
+ readOnly?: boolean;
36
+ governed?: boolean;
37
+ searchable?: boolean;
38
+ };
39
+ /** One resolved mount: its normalized key, backend, write posture and governance. */
40
+ export interface ResolvedMount {
41
+ /** Directory mounts keep their trailing slash; file mounts have none. */
42
+ key: string;
43
+ /** Key without leading slash or trailing slash — the reserved root name. */
44
+ name: string;
45
+ backend: BackendProtocolV2;
46
+ readOnly: boolean;
47
+ isDir: boolean;
48
+ /** Whether the spec's `mounts` lists decide which states may reach it. */
49
+ governed: boolean;
50
+ /** Whether a root-wide search may fan out into it (`true` unless declared otherwise). */
51
+ searchable: boolean;
52
+ }
53
+ export { NO_MOUNTS, type MountPrefixes };
54
+ /**
55
+ * Thrown when a declared mount key would shadow a run area or serve an
56
+ * authoring-plane prefix to the agent. A declared route is the consumer's wiring
57
+ * rather than incidental noise, so it fails loudly instead of being skipped.
58
+ */
59
+ export declare class MountCollisionError extends Error {
60
+ readonly key: string;
61
+ constructor(key: string);
62
+ }
63
+ export { AUTHORING_PREFIXES, authoringPlanePrefix, describeAuthoringPrefix, isAuthoringPrefix, type AuthoringPrefix, };
64
+ /**
65
+ * Canonical mount key: one leading slash, collapsed separators, trailing slash
66
+ * preserved (it is what distinguishes a directory mount from a file mount).
67
+ */
68
+ export declare function normalizeMountKey(key: string): string;
69
+ /**
70
+ * Resolve a consumer's mount table into the composite routes and the prefixes
71
+ * governance classifies against. Throws {@link MountCollisionError} when a key
72
+ * would shadow a run area or name an {@link AUTHORING_PREFIXES} prefix.
73
+ */
74
+ export declare function resolveMounts(table?: Record<string, MountSpec>): {
75
+ mounts: ResolvedMount[];
76
+ prefixes: MountPrefixes;
77
+ };
78
+ /**
79
+ * The conventional mount table for a filesystem workspace: each authored
80
+ * directory as a {@link FilesystemBackend} rooted at itself, plus `AGENTS.md`
81
+ * served from the workspace root by exact path.
82
+ *
83
+ * This is a **default value**, applied only when the consumer supplies no table
84
+ * on the default backend — not framework law. Nothing in the framework
85
+ * classifies, validates, or enforces against these names; spread it to extend
86
+ * (`{ ...defaultMounts(root), "/templates/": … }`) or ignore it entirely.
87
+ */
88
+ export declare function defaultMounts(rootDir: string): Record<string, MountSpec>;
@@ -0,0 +1,147 @@
1
+ import { join } from "node:path";
2
+ import { FilesystemBackend } from "deepagents";
3
+ import { normalizeRelPath } from "./workspace.js";
4
+ import { PLATFORM_PROMPT_PATH } from "../workflow/paths.js";
5
+ import { AUTHORING_PREFIXES, authoringPlanePrefix, describeAuthoringPrefix, isAuthoringPrefix, NO_MOUNTS, sessionAreaNames, } from "./zones.js";
6
+ // The classification input type lives with the classifier (`core/zones.ts`);
7
+ // re-exported here so consumers reach the whole mount vocabulary from one module.
8
+ export { NO_MOUNTS };
9
+ /**
10
+ * Thrown when a declared mount key would shadow a run area or serve an
11
+ * authoring-plane prefix to the agent. A declared route is the consumer's wiring
12
+ * rather than incidental noise, so it fails loudly instead of being skipped.
13
+ */
14
+ export class MountCollisionError extends Error {
15
+ key;
16
+ constructor(key) {
17
+ const name = key.replace(/^\/+|\/+$/g, "");
18
+ // The collision is with the key's *first* segment, so a nested key
19
+ // (`/workflows/order-lookup/`) is named for the prefix it reaches into.
20
+ const top = name.split("/")[0] ?? "";
21
+ const plane = isAuthoringPrefix(top) ? top : null;
22
+ super(plane
23
+ ? `Mount '${key}' would serve the authoring plane to the agent. ` +
24
+ `'${plane}/' holds ${describeAuthoringPrefix(plane)}; the runtime ` +
25
+ `reads them through the authoring backend, and no agent tool may address them. ` +
26
+ `Configure them with the 'authoring' option instead of mounting them.`
27
+ : `Mount '${key}' collides with the run area '${top}/', which the ` +
28
+ `session store owns at the workspace root. Mount it under a different key.`);
29
+ this.key = key;
30
+ this.name = "MountCollisionError";
31
+ }
32
+ }
33
+ const SESSION_AREA_SET = new Set(sessionAreaNames());
34
+ // The authoring prefixes are root-namespace vocabulary and live with the rest of
35
+ // it in `core/zones.ts`; re-exported here so consumers reach the whole mount
36
+ // vocabulary from one module.
37
+ export { AUTHORING_PREFIXES, authoringPlanePrefix, describeAuthoringPrefix, isAuthoringPrefix, };
38
+ /**
39
+ * Canonical mount key: one leading slash, collapsed separators, trailing slash
40
+ * preserved (it is what distinguishes a directory mount from a file mount).
41
+ */
42
+ export function normalizeMountKey(key) {
43
+ const isDir = /\/\s*$/.test(key);
44
+ const rel = normalizeRelPath(key).replace(/\/+$/, "");
45
+ return `/${rel}${isDir ? "/" : ""}`;
46
+ }
47
+ function specParts(spec) {
48
+ if (typeof spec === "object" && spec !== null && "backend" in spec) {
49
+ return {
50
+ backend: spec.backend,
51
+ readOnly: spec.readOnly ?? true,
52
+ governed: spec.governed ?? false,
53
+ searchable: spec.searchable ?? true,
54
+ };
55
+ }
56
+ return { backend: spec, readOnly: true, governed: false, searchable: true };
57
+ }
58
+ /**
59
+ * Resolve a consumer's mount table into the composite routes and the prefixes
60
+ * governance classifies against. Throws {@link MountCollisionError} when a key
61
+ * would shadow a run area or name an {@link AUTHORING_PREFIXES} prefix.
62
+ */
63
+ export function resolveMounts(table = {}) {
64
+ const mounts = [];
65
+ for (const [rawKey, spec] of Object.entries(table)) {
66
+ const key = normalizeMountKey(rawKey);
67
+ const name = key.replace(/^\/+|\/+$/g, "");
68
+ if (name === "")
69
+ continue;
70
+ // The *first* segment decides: a key several levels down the reserved
71
+ // prefix is the same exposure as the prefix itself, so `/workflows/x/`
72
+ // fails exactly as `/workflows/` does.
73
+ const [top = ""] = name.split("/");
74
+ if (SESSION_AREA_SET.has(top) || isAuthoringPrefix(top)) {
75
+ throw new MountCollisionError(key);
76
+ }
77
+ const { backend, readOnly, governed, searchable } = specParts(spec);
78
+ mounts.push({
79
+ key,
80
+ name,
81
+ backend,
82
+ readOnly,
83
+ isDir: key.endsWith("/"),
84
+ governed,
85
+ searchable,
86
+ });
87
+ }
88
+ return {
89
+ mounts,
90
+ prefixes: {
91
+ dirs: mounts.filter((m) => m.isDir).map((m) => m.name),
92
+ files: mounts.filter((m) => !m.isDir).map((m) => m.name),
93
+ writable: mounts.filter((m) => !m.readOnly).map((m) => m.name),
94
+ governed: mounts.filter((m) => m.governed).map((m) => m.name),
95
+ // Only a directory is ever searched as a tree, so the flag on a file
96
+ // mount is recorded on the resolved mount but classifies nothing.
97
+ unsearchable: mounts.filter((m) => m.isDir && !m.searchable).map((m) => m.name),
98
+ },
99
+ };
100
+ }
101
+ /**
102
+ * Conventional authored directories — a default value, never a constraint.
103
+ *
104
+ * Deliberately short, and deliberately missing every {@link AUTHORING_PREFIXES}
105
+ * prefix. That plane is not workspace furniture the agent browses: it is what the
106
+ * runtime enforces the run *with*, served by the authoring backend and reachable by
107
+ * no tool call. `workflows/` holds the spec — its grading rubrics included, so a run
108
+ * cannot read the criteria it is judged against — plus the prose addendum, the hook
109
+ * scripts, and the cases grading the run.
110
+ *
111
+ * What ships in a skill bundle is the other kind of script — the ones the *agent*
112
+ * runs with `archmax_run` — together with the data a state reads
113
+ * (`skills/<name>/scripts/…`, `skills/<name>/assets/…`), reaching the agent through
114
+ * the `skills/` mount, which also lets a state scope execution to one capability
115
+ * (`skills/triage/scripts/**`).
116
+ *
117
+ * None of the conventional mounts is `governed`: a zero-config workspace's
118
+ * content is visible in every state, exactly as it was before the `mounts`
119
+ * block existed.
120
+ */
121
+ const CONVENTIONAL_DIRS = [
122
+ "skills",
123
+ PLATFORM_PROMPT_PATH.split("/")[0], // `.platform` — the runtime reads its prompt from here
124
+ ];
125
+ /** Conventional authored root files, mounted by exact path. */
126
+ const CONVENTIONAL_FILES = ["AGENTS.md"];
127
+ /**
128
+ * The conventional mount table for a filesystem workspace: each authored
129
+ * directory as a {@link FilesystemBackend} rooted at itself, plus `AGENTS.md`
130
+ * served from the workspace root by exact path.
131
+ *
132
+ * This is a **default value**, applied only when the consumer supplies no table
133
+ * on the default backend — not framework law. Nothing in the framework
134
+ * classifies, validates, or enforces against these names; spread it to extend
135
+ * (`{ ...defaultMounts(root), "/templates/": … }`) or ignore it entirely.
136
+ */
137
+ export function defaultMounts(rootDir) {
138
+ const fs = (dir) => new FilesystemBackend({ rootDir: dir, virtualMode: true });
139
+ const table = {};
140
+ for (const dir of CONVENTIONAL_DIRS)
141
+ table[`/${dir}/`] = fs(join(rootDir, dir));
142
+ // Root files live in the workspace root itself, addressed by their exact key.
143
+ for (const file of CONVENTIONAL_FILES)
144
+ table[`/${file}`] = fs(rootDir);
145
+ return table;
146
+ }
147
+ //# sourceMappingURL=mounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mounts.js","sourceRoot":"","sources":["../../src/core/mounts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import type { BackendProtocolV2 } from "deepagents";
2
+ /**
3
+ * Bidirectional path mapping for a backend served under a prefix.
4
+ *
5
+ * Three places in the runtime delegate to a backend whose paths are shifted by
6
+ * a prefix, and all three need the *same* two-way mapping:
7
+ *
8
+ * - **Authored mounts** — `CompositeBackend` strips the route prefix before
9
+ * delegating (`/skills/x` → `/x`) and re-prepends it to the paths it returns.
10
+ * A one-way prepending wrapper therefore double-prefixes every listed path
11
+ * (`/skills/skills/x`); the outbound half is what keeps the round trip honest.
12
+ * - **The session store's tenancy prefix** — consumer-owned layout that must never
13
+ * appear in an SDK-visible or agent-visible path, including result paths.
14
+ * - **The session zone's session binding** — the bound session id must not appear in
15
+ * agent-visible listings, so it is stripped on the way out.
16
+ *
17
+ * Inbound: `/x` → `/<prefix>/x`. Outbound: every `path` a result carries
18
+ * (`ls`/`glob` entries, `grep` matches, `write`/`edit` results) is mapped back.
19
+ * A result path that does not start with the prefix is left untouched — the
20
+ * inner backend is free to report paths we did not ask about.
21
+ */
22
+ /** The prefix in effect for a call: a fixed string, or resolved per call. */
23
+ export type PrefixResolver = () => string | undefined;
24
+ /**
25
+ * Wrap `backend` so it is addressed under `prefix` from the outside, mapping
26
+ * paths in both directions. `prefix` may be a resolver, returning `undefined`
27
+ * when no prefix applies for this call (the session zone outside a bound session) —
28
+ * in which case paths pass through unchanged.
29
+ *
30
+ * `passthrough` marks inbound paths that are already expressed in the inner
31
+ * backend's terms and must not be prefixed (e.g. runtime-internal
32
+ * session-qualified paths, cross-session `_specs/…`). Their result paths are left
33
+ * unmapped as well, since they were never shifted.
34
+ */
35
+ export declare function mountSubtree(backend: BackendProtocolV2, prefix: string | PrefixResolver, options?: {
36
+ passthrough?: (relPath: string, prefix: string) => boolean;
37
+ /**
38
+ * Refuse `write`/`edit` at the mount instead of delegating. Read-only is a
39
+ * property of the mount, so an authored mount cannot be written through even
40
+ * by a caller that bypasses governance — the kernel's `zone.read-only` rule
41
+ * remains the agent-facing diagnostic, not the only enforcement.
42
+ */
43
+ readOnly?: boolean;
44
+ /**
45
+ * Route prefix a composite stripped before delegating, re-applied when a
46
+ * read-only refusal names the rejected path. Without it the refusal reports
47
+ * the stripped key (`/orders.json`) rather than the path the caller sent
48
+ * (`data/orders.json`) — pointing an agent at a path it never asked about,
49
+ * which is exactly the confusion that makes it retry with invented paths.
50
+ */
51
+ displayPrefix?: string;
52
+ }): BackendProtocolV2;
@@ -0,0 +1,113 @@
1
+ import { normalizeRelPath } from "./workspace.js";
2
+ function relPrefix(prefix) {
3
+ return normalizeRelPath(prefix).replace(/\/+$/, "");
4
+ }
5
+ /**
6
+ * Wrap `backend` so it is addressed under `prefix` from the outside, mapping
7
+ * paths in both directions. `prefix` may be a resolver, returning `undefined`
8
+ * when no prefix applies for this call (the session zone outside a bound session) —
9
+ * in which case paths pass through unchanged.
10
+ *
11
+ * `passthrough` marks inbound paths that are already expressed in the inner
12
+ * backend's terms and must not be prefixed (e.g. runtime-internal
13
+ * session-qualified paths, cross-session `_specs/…`). Their result paths are left
14
+ * unmapped as well, since they were never shifted.
15
+ */
16
+ export function mountSubtree(backend, prefix, options = {}) {
17
+ const resolvePrefix = typeof prefix === "function" ? () => optionalRel(prefix()) : () => relPrefix(prefix);
18
+ const passthrough = options.passthrough;
19
+ /**
20
+ * The refused path in workspace terms — the spelling the caller would use to
21
+ * address it — so the diagnostic names the path that was actually rejected.
22
+ */
23
+ const displayPath = (path) => {
24
+ const rel = normalizeRelPath(path);
25
+ const prefix = relPrefix(options.displayPrefix ?? "");
26
+ if (!prefix)
27
+ return rel === "" ? path : rel;
28
+ return rel === "" ? prefix : `${prefix}/${rel}`;
29
+ };
30
+ const readOnlyError = (op, path) => ({
31
+ error: `Cannot ${op} '${displayPath(path)}': it is served by a read-only mount. ` +
32
+ `Only run state is writable in this workspace.`,
33
+ });
34
+ /** The prefix to apply to `path`, or `undefined` when it passes through. */
35
+ const prefixFor = (path) => {
36
+ const active = resolvePrefix();
37
+ if (!active)
38
+ return undefined;
39
+ if (passthrough?.(normalizeRelPath(path), active))
40
+ return undefined;
41
+ return active;
42
+ };
43
+ const mapIn = (path, active) => {
44
+ if (!active)
45
+ return path;
46
+ const hadSlash = path.startsWith("/");
47
+ const rel = normalizeRelPath(path);
48
+ const joined = rel === "" ? active : `${active}/${rel}`;
49
+ return hadSlash || path === "" ? `/${joined}` : joined;
50
+ };
51
+ const mapOut = (path, active) => {
52
+ if (!active)
53
+ return path;
54
+ const hadSlash = path.startsWith("/");
55
+ const rel = normalizeRelPath(path);
56
+ if (rel !== active && !rel.startsWith(`${active}/`))
57
+ return path;
58
+ const stripped = rel === active ? "" : rel.slice(active.length + 1);
59
+ return hadSlash ? `/${stripped}` : stripped;
60
+ };
61
+ const mapFiles = (files, active) => files?.map((file) => ({ ...file, path: mapOut(file.path, active) }));
62
+ return {
63
+ async ls(path) {
64
+ const active = prefixFor(path);
65
+ const res = await backend.ls(mapIn(path, active));
66
+ const files = mapFiles(res.files, active);
67
+ return files ? { ...res, files } : res;
68
+ },
69
+ read(filePath, offset, limit) {
70
+ return backend.read(mapIn(filePath, prefixFor(filePath)), offset, limit);
71
+ },
72
+ readRaw(filePath) {
73
+ return backend.readRaw(mapIn(filePath, prefixFor(filePath)));
74
+ },
75
+ async grep(pattern, path, glob) {
76
+ const target = path ?? "";
77
+ const active = prefixFor(target);
78
+ const searchPath = path == null && !active ? path : mapIn(target, active);
79
+ const res = await backend.grep(pattern, searchPath, glob);
80
+ const matches = res.matches?.map((match) => ({ ...match, path: mapOut(match.path, active) }));
81
+ return matches ? { ...res, matches } : res;
82
+ },
83
+ async glob(pattern, path) {
84
+ const target = path ?? "";
85
+ const active = prefixFor(target);
86
+ const searchPath = path === undefined && !active ? undefined : mapIn(target, active);
87
+ const res = await backend.glob(pattern, searchPath);
88
+ const files = mapFiles(res.files, active);
89
+ return files ? { ...res, files } : res;
90
+ },
91
+ async write(filePath, content) {
92
+ if (options.readOnly)
93
+ return readOnlyError("write", filePath);
94
+ const active = prefixFor(filePath);
95
+ const res = await backend.write(mapIn(filePath, active), content);
96
+ return res.path === undefined ? res : { ...res, path: mapOut(res.path, active) };
97
+ },
98
+ async edit(filePath, oldString, newString, replaceAll) {
99
+ if (options.readOnly)
100
+ return readOnlyError("edit", filePath);
101
+ const active = prefixFor(filePath);
102
+ const res = await backend.edit(mapIn(filePath, active), oldString, newString, replaceAll);
103
+ return res.path === undefined ? res : { ...res, path: mapOut(res.path, active) };
104
+ },
105
+ };
106
+ }
107
+ function optionalRel(prefix) {
108
+ if (prefix == null)
109
+ return undefined;
110
+ const rel = relPrefix(prefix);
111
+ return rel === "" ? undefined : rel;
112
+ }
113
+ //# sourceMappingURL=path-mapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-mapping.js","sourceRoot":"","sources":["../../src/core/path-mapping.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ /** The bundled platform prompt: how to move through the graph and which tools are the runtime's. */
2
+ export declare const PLATFORM_PROMPT: string;
@@ -0,0 +1,4 @@
1
+ // Generated from platform-prompt.md by scripts/generate-platform-prompt.mjs. Do not edit.
2
+ /** The bundled platform prompt: how to move through the graph and which tools are the runtime's. */
3
+ export const PLATFORM_PROMPT = "# Graph state execution\n\nYou run inside a **declarative workflow graph**: you occupy one **state** at a\ntime, and that state's spec governs which tools you may call and which files you\nmay read or write.\n\n## How you move\n\n1. **Name the run first.** Before anything else in your first turn, call\n **`archmax_set_variables({ \"variables\": { \"title\": \"<a few words>\" } })`** — see\n \"Naming the run\" below.\n2. Do the current state's work. `scratchpad/` is always open, so it is where a\n file goes when nothing else was named — but it is a default, not a limit: when\n the state's instructions or its listed mounts name a writable place, write\n there instead of copying into `scratchpad/`.\n3. Call **`archmax_advance({ \"to\": \"<next>\", \"reason\": \"<one sentence>\" })`**,\n choosing `to` from the transitions listed under \"Current state\" and using\n their descriptions to decide. `to` takes the target's **slug** — the\n backticked token on the transition line. A parenthesized note carries the\n edge's declared type (`approve`, `reject`, `refine`), whether the target is a\n **human decision node**, and whether it is **terminal**. A state with no\n transitions says so: that is where the run ends, so finish its work and stop.\n4. The runtime validates the edge, runs this state's `after` hook and then the\n target's `before` hook — either may send you back to correct or veto the\n move — and only then unlocks the next state's tools.\n\n**One transition per message.** A second `archmax_advance` alongside the first is\nrefused. Chain states over successive turns, never in a single message.\n\n**A conversation keeps its position.** A message arriving after your last turn\nleaves you in the state that turn ended in, not at the beginning. When that state\ncannot serve what was asked — no transition from here reaches it, or an earlier\nturn took a wrong path — call **`archmax_reset({ \"reason\": \"<one sentence>\" })`**\nto return to the state the conversation began in. It is available in every state\nand moves the state machine, not the history: the conversation and everything\nwritten so far are kept.\n\n**A terminal state never serves a follow-up.** A reply, a correction or a new\nrequest landing on a run that was *already sitting* in a terminal state is work\nthis run has no path to do: reset **before** answering it, or you skip every state\nthe answer depends on. Two things are not follow-ups — a run you parked with\n`archmax_wait`, which resumes where it was on purpose, and a terminal state you\nwere routed into *this turn*, by your own `archmax_advance` or by a person's\ndecision, which is the work you were sent there to do: do it, then stop. Never\nreset out of a state you just arrived in, and never `archmax_wait` for the runtime\nto move you — it already has.\n\n### Waiting for something to arrive\n\nIf this state cannot continue without something from **outside the run** — an\nevent, a callback, a webhook, a reply someone sends in their own time — call\n**`archmax_wait({ \"reason\": \"<what you are waiting for>\" })`** and stop, instead of\nending your turn. You resume in **this same state**, with what arrived in your\ntranscript and any values it carried in the variables. Waiting for a *time*\nrather than an event? Add `\"until\": \"1d\"` (a duration or an ISO-8601 instant) so\nwhoever wakes you knows when; an earlier event still resumes you.\n\n`archmax_wait` holds you where you are and moves nothing, so it is never how you\nget a person to decide, approve, sign off, review, or choose between options.\nThat belongs to a **human decision node** — a state the author declared for it,\nwhich you reach the ordinary way with `archmax_advance`. The runtime parks the run\nthere and presents the options by itself: do the work that state's transitions\nrequire, advance into the node, and stop. Never advance out of one yourself, and\nnever `archmax_wait` in front of one to ask for the decision the node exists to\ncollect.\n\nSo: something has to **come to this state** → `archmax_wait`. Someone has to\n**decide** → `archmax_advance` into the human node.\n\n### The state you are in\n\nThe active state's **`instructions`** arrive under a \"Current state\" heading —\nfollow them; the transitions listed there are for choosing where to go next. You\nare shown the edges leading out of the state you are in and nothing else of the\ngraph: there is no map of the workflow to consult, and a state you cannot advance\nto is one you cannot name. Do not guess at slugs, and do not treat a state named\nanywhere else — in a message, a file, or your own earlier turns — as somewhere you\ncan move to. When the state may use skills, they are listed under \"Skills\navailable in this state\", each naming the `SKILL.md` to read first.\n\n**`before`/`after` hooks** run on their own, without you calling them. They may\napprove, ask you to correct your answer, or block the run: fix the work rather\nthan arguing with it.\n\n## Tools\n\nTool access is **closed by default**: you see exactly the active state's surface,\nand a state's entry may also narrow a tool's permitted *arguments* (e.g.\n`write_file` to one path). Tools whose names start with `archmax_` are the\nruntime's own controls — movement, reset, waiting, the sandbox, and the run's\nvariables (`archmax_get_variables` / `archmax_set_variables`); everything else acts\non the workspace or on the systems this workspace integrates. A blocked call names\nthe tool, the state, and the policy — fix the call, or advance if you are done.\n\n**Write code instead of many calls.** **`archmax_eval({ \"code\": \"…\" })`** —\navailable in every state — evaluates JavaScript in a sandbox where `tools.*`\ncalls the same tools you have, governed exactly as your own calls are. Reach for\nit by default whenever the work is a loop, a filter, arithmetic, or more than\nabout two calls whose results feed each other: it is one round trip instead of\nmany, and **only your last expression and whatever you `console.log` come back to\nyou**, so the bulk of what those tools returned never enters the conversation and\nis never re-sent on later calls. The REPL keeps its state between calls, so a\nvalue or helper from one is still in scope in the next. Your code cannot read the\nrun's variables: interpolate a scalar one into it with `${{name}}` (below), and\nuse **`archmax_run({ \"file_path\": \"…\" })`** — also in every state — when the code\nneeds whole structured values, which an authored script receives as\n`args.variables`. It runs the same way, subject to any path constraint the state\nplaces on it.\n\n**Naming the run.** `title` is a reserved run variable holding a short label for\nthe task you are doing — one line, a handful of words, enough that someone\nscanning a list of runs knows which one this is:\n\n```\narchmax_set_variables({ \"variables\": { \"title\": \"Refund for order A-1042\" } })\n```\n\nThis is step 1 above, and it is not optional. Write it from whatever the request\nalready tells you, **before** the current state's own work and before any other\ntool call — it is a label, not a plan, so never investigate or read anything to\nproduce one, and it still goes first when the state's instructions tell you to do\nsomething else first. Update it with the same call whenever the task turns into\nsomething the old title no longer describes; a small refinement of the same task\ndoes not need one. Never pass `lock` with it: the title has to stay correctable\nfor the whole run, so that call is refused.\n\n**Reference a run variable instead of retyping it.** Anywhere a tool argument is\ntext, `${{name}}` (or `${{name.path.to.value}}`) is replaced with that variable's\nvalue before the call runs. A reference may sit **inside** a longer string and\nrepeat:\n\n```\n\"Thanks — your refund is on its way.\n\n--- Original message ---\n\n${{inbound.text}}\"\n```\n\nPrefer the reference to writing the value out. It is what you spend tokens on and\nwhat stays in the transcript — the full value goes to the tool and no further —\nand unlike a retyped copy it cannot paraphrase, truncate or mistype.\n`archmax_get_variables` shows what is set; a reference that does not resolve\nrefuses the call and tells you why, so fix it and retry. To write the characters\n`${{…}}` literally, double the dollar: `$${{name}}`.\n";
4
+ //# sourceMappingURL=platform-prompt.generated.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-prompt.generated.js","sourceRoot":"","sources":["../../src/core/platform-prompt.generated.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAE1F,oGAAoG;AACpG,MAAM,CAAC,MAAM,eAAe,GAAW,qsQAAqsQ,CAAC"}
@@ -0,0 +1,42 @@
1
+ import type { Workspace } from "./workspace.js";
2
+ import { type MountPrefixes } from "./zones.js";
3
+ export interface ResolveSystemPromptOptions {
4
+ /** Workspace-relative path to AGENTS.md (default: `AGENTS.md`). */
5
+ agentsPath?: string;
6
+ /**
7
+ * Where a workspace may override the platform prompt (normally
8
+ * `PLATFORM_PROMPT_PATH`); the bundled prompt applies when nothing is served
9
+ * there. `null` leaves the platform layer out — a plain agent has no machine
10
+ * for it to explain.
11
+ */
12
+ platformBackendPath: string | null;
13
+ /**
14
+ * Pre-assembled workflow prompt text: the spec-rendered workflow header
15
+ * followed by any `WORKFLOW.md` prose addendum (the caller composes both —
16
+ * see `renderWorkflowPrompt` — because it already holds the loaded spec and
17
+ * body; this module never re-reads the workflow files). Carries no state of
18
+ * the graph; `renderStateGraph` renders that per model call.
19
+ */
20
+ workflowPrompt?: string | null;
21
+ /**
22
+ * The assembly's resolved mount keys. The workspace-zones section is rendered
23
+ * from these, so what the prompt says the agent has cannot drift from what the
24
+ * workspace serves. Omitted: no mounts are described.
25
+ */
26
+ mountPrefixes?: MountPrefixes;
27
+ /** Extra text appended after AGENTS.md. */
28
+ extra?: string;
29
+ }
30
+ /** The layers `buildSystemPrompt` joins, in the order listed at the top of this module. */
31
+ export interface SystemPromptParts {
32
+ agents?: string | null;
33
+ extra?: string;
34
+ platform?: string | null;
35
+ /** The workspace-zones section, rendered from the resolved mount table. */
36
+ workspace?: string | null;
37
+ workflow?: string | null;
38
+ }
39
+ /** Join the prompt layers, skipping absent ones. */
40
+ export declare function buildSystemPrompt(parts: SystemPromptParts): string;
41
+ /** Load the prompt layers from the backend and merge them. */
42
+ export declare function resolveSystemPrompt(workspace: Workspace, opts: ResolveSystemPromptOptions): Promise<string>;