@interf/compiler 0.33.0 → 0.50.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 (234) hide show
  1. package/README.md +122 -226
  2. package/dist/cli/commands/agents.js +1 -32
  3. package/dist/cli/commands/benchmark.d.ts +2 -3
  4. package/dist/cli/commands/benchmark.js +1 -31
  5. package/dist/cli/commands/build-plan.js +26 -50
  6. package/dist/cli/commands/build.d.ts +2 -3
  7. package/dist/cli/commands/build.js +1 -31
  8. package/dist/cli/commands/graphs.js +177 -32
  9. package/dist/cli/commands/mcp.d.ts +1 -0
  10. package/dist/cli/commands/mcp.js +223 -126
  11. package/dist/cli/commands/project.js +10 -36
  12. package/dist/cli/commands/reset.d.ts +2 -3
  13. package/dist/cli/commands/reset.js +1 -22
  14. package/dist/cli/commands/runs.js +86 -33
  15. package/dist/cli/commands/status.js +3 -24
  16. package/dist/cli/commands/traces.js +1 -29
  17. package/dist/cli/commands/wizard.js +17 -29
  18. package/dist/cli/lib/http-client.d.ts +39 -0
  19. package/dist/cli/lib/http-client.js +73 -0
  20. package/dist/packages/build-plans/authoring/brief.d.ts +25 -4
  21. package/dist/packages/build-plans/authoring/build-plan-authoring.d.ts +42 -1
  22. package/dist/packages/build-plans/authoring/build-plan-authoring.js +470 -63
  23. package/dist/packages/build-plans/authoring/build-plan-edit-session.d.ts +9 -0
  24. package/dist/packages/build-plans/authoring/build-plan-edit-session.js +27 -10
  25. package/dist/packages/build-plans/authoring/build-plan-improvement.js +62 -8
  26. package/dist/packages/build-plans/authoring/lib/build-plan-edit-utils.d.ts +1 -0
  27. package/dist/packages/build-plans/package/build-plan-definitions.d.ts +0 -1
  28. package/dist/packages/build-plans/package/build-plan-definitions.js +5 -3
  29. package/dist/packages/build-plans/package/build-plan-stage-runner.d.ts +1 -0
  30. package/dist/packages/build-plans/package/build-plan-stage-runner.js +2 -1
  31. package/dist/packages/build-plans/package/builtin-build-plan.d.ts +2 -2
  32. package/dist/packages/build-plans/package/builtin-build-plan.js +3 -3
  33. package/dist/packages/build-plans/package/context-interface.d.ts +3 -0
  34. package/dist/packages/build-plans/package/context-interface.js +5 -5
  35. package/dist/packages/build-plans/package/interf-build-plan-package.js +22 -22
  36. package/dist/packages/build-plans/package/local-build-plans.d.ts +10 -5
  37. package/dist/packages/build-plans/package/local-build-plans.js +57 -32
  38. package/dist/packages/contracts/index.d.ts +4 -3
  39. package/dist/packages/contracts/index.js +2 -1
  40. package/dist/packages/contracts/lib/context-graph-layer.d.ts +161 -0
  41. package/dist/packages/contracts/lib/context-graph-layer.js +216 -0
  42. package/dist/packages/contracts/lib/project-paths.d.ts +7 -0
  43. package/dist/packages/contracts/lib/project-paths.js +9 -0
  44. package/dist/packages/contracts/lib/project-schema.d.ts +264 -1
  45. package/dist/packages/contracts/lib/project-schema.js +38 -13
  46. package/dist/packages/contracts/lib/schema.d.ts +556 -23
  47. package/dist/packages/contracts/lib/schema.js +279 -18
  48. package/dist/packages/contracts/utils/filesystem.d.ts +1 -0
  49. package/dist/packages/contracts/utils/filesystem.js +29 -1
  50. package/dist/packages/projects/lib/schema.d.ts +6 -8
  51. package/dist/packages/projects/lib/schema.js +3 -1
  52. package/dist/packages/projects/source-config.d.ts +0 -5
  53. package/dist/packages/projects/source-config.js +9 -22
  54. package/dist/packages/runtime/actions/fields.d.ts +4 -0
  55. package/dist/packages/runtime/actions/form-builders.js +79 -31
  56. package/dist/packages/runtime/actions/form-validators.js +9 -3
  57. package/dist/packages/runtime/actions/helpers.js +3 -3
  58. package/dist/packages/runtime/actions/registry.d.ts +1 -1
  59. package/dist/packages/runtime/actions/registry.js +1 -1
  60. package/dist/packages/runtime/actions/requests.d.ts +1 -1
  61. package/dist/packages/runtime/actions/requests.js +12 -6
  62. package/dist/packages/runtime/actions/schemas.d.ts +7 -0
  63. package/dist/packages/runtime/actions/schemas.js +1 -0
  64. package/dist/packages/runtime/agent-handoff.js +8 -7
  65. package/dist/packages/runtime/agents/lib/execution-profile.d.ts +14 -0
  66. package/dist/packages/runtime/agents/lib/execution-profile.js +23 -0
  67. package/dist/packages/runtime/agents/lib/execution.js +14 -8
  68. package/dist/packages/runtime/agents/lib/executors.d.ts +1 -0
  69. package/dist/packages/runtime/agents/lib/executors.js +11 -2
  70. package/dist/packages/runtime/agents/lib/logs.d.ts +10 -0
  71. package/dist/packages/runtime/agents/lib/logs.js +32 -8
  72. package/dist/packages/runtime/agents/lib/preflight.js +4 -1
  73. package/dist/packages/runtime/agents/lib/render.d.ts +18 -0
  74. package/dist/packages/runtime/agents/lib/render.js +44 -18
  75. package/dist/packages/runtime/agents/lib/shell-templates.js +105 -63
  76. package/dist/packages/runtime/agents/lib/shells.d.ts +29 -0
  77. package/dist/packages/runtime/agents/lib/shells.js +158 -32
  78. package/dist/packages/runtime/agents/lib/source-context-scan.d.ts +10 -0
  79. package/dist/packages/runtime/agents/lib/source-context-scan.js +388 -0
  80. package/dist/packages/runtime/agents/lib/status.js +1 -14
  81. package/dist/packages/runtime/agents/lib/string-utils.d.ts +16 -0
  82. package/dist/packages/runtime/agents/lib/string-utils.js +36 -0
  83. package/dist/packages/runtime/agents/lib/types.d.ts +1 -0
  84. package/dist/packages/runtime/agents/providers/codex.js +2 -0
  85. package/dist/packages/runtime/agents/role-executors.js +2 -1
  86. package/dist/packages/runtime/auth/session-store.js +11 -3
  87. package/dist/packages/runtime/benchmark-question-draft.d.ts +3 -0
  88. package/dist/packages/runtime/benchmark-question-draft.js +57 -28
  89. package/dist/packages/runtime/build/artifact-status.d.ts +1 -1
  90. package/dist/packages/runtime/build/artifact-status.js +1 -1
  91. package/dist/packages/runtime/build/build-evidence.d.ts +2 -1
  92. package/dist/packages/runtime/build/build-evidence.js +11 -5
  93. package/dist/packages/runtime/build/build-pipeline.js +89 -5
  94. package/dist/packages/runtime/build/build-stage-plan.js +3 -1
  95. package/dist/packages/runtime/build/build-stage-runner.js +169 -32
  96. package/dist/packages/runtime/build/build-target.d.ts +3 -0
  97. package/dist/packages/runtime/build/build-target.js +25 -1
  98. package/dist/packages/runtime/build/check-evaluator.d.ts +1 -1
  99. package/dist/packages/runtime/build/check-evaluator.js +655 -4
  100. package/dist/packages/runtime/build/context-graph-paths.d.ts +13 -0
  101. package/dist/packages/runtime/build/context-graph-paths.js +27 -0
  102. package/dist/packages/runtime/build/index.d.ts +2 -2
  103. package/dist/packages/runtime/build/index.js +2 -2
  104. package/dist/packages/runtime/build/inspect-map.d.ts +10 -0
  105. package/dist/packages/runtime/build/inspect-map.js +270 -0
  106. package/dist/packages/runtime/build/lib/schema.d.ts +246 -53
  107. package/dist/packages/runtime/build/lib/schema.js +173 -15
  108. package/dist/packages/runtime/build/native-entrypoint.d.ts +2 -0
  109. package/dist/packages/runtime/build/native-entrypoint.js +286 -0
  110. package/dist/packages/runtime/build/runtime-contracts.js +9 -3
  111. package/dist/packages/runtime/build/runtime-log-paths.d.ts +3 -0
  112. package/dist/packages/runtime/build/runtime-log-paths.js +16 -0
  113. package/dist/packages/runtime/build/runtime-prompt.js +6 -4
  114. package/dist/packages/runtime/build/runtime-runs.js +63 -10
  115. package/dist/packages/runtime/build/runtime-types.d.ts +4 -1
  116. package/dist/packages/runtime/build/runtime.d.ts +3 -1
  117. package/dist/packages/runtime/build/runtime.js +3 -1
  118. package/dist/packages/runtime/build/source-files.js +11 -2
  119. package/dist/packages/runtime/build/source-inventory.d.ts +1 -0
  120. package/dist/packages/runtime/build/source-inventory.js +246 -7
  121. package/dist/packages/runtime/build/source-manifest.d.ts +11 -0
  122. package/dist/packages/runtime/build/source-manifest.js +30 -2
  123. package/dist/packages/runtime/build/stage-evidence.js +80 -11
  124. package/dist/packages/runtime/build/stage-manifest.d.ts +45 -0
  125. package/dist/packages/runtime/build/stage-manifest.js +1125 -0
  126. package/dist/packages/runtime/build/stage-reuse.js +12 -0
  127. package/dist/packages/runtime/build/stage-session.d.ts +81 -0
  128. package/dist/packages/runtime/build/stage-session.js +308 -0
  129. package/dist/packages/runtime/build/state-io.js +10 -11
  130. package/dist/packages/runtime/build/state-view.js +1 -1
  131. package/dist/packages/runtime/build/state.d.ts +1 -1
  132. package/dist/packages/runtime/build/state.js +1 -1
  133. package/dist/packages/runtime/build/summary-coverage-index.d.ts +21 -0
  134. package/dist/packages/runtime/build/summary-coverage-index.js +189 -0
  135. package/dist/packages/runtime/build/traces.js +3 -3
  136. package/dist/packages/runtime/build/validate-context-graph.d.ts +1 -1
  137. package/dist/packages/runtime/build/validate-context-graph.js +5 -5
  138. package/dist/packages/runtime/build/validate.d.ts +1 -1
  139. package/dist/packages/runtime/build/validate.js +1 -1
  140. package/dist/packages/runtime/client.d.ts +3 -3
  141. package/dist/packages/runtime/client.js +8 -13
  142. package/dist/packages/runtime/context-checks.js +13 -0
  143. package/dist/packages/runtime/context-graph-scaffold.js +2 -1
  144. package/dist/packages/runtime/context-graph-semantic-graph.d.ts +9 -0
  145. package/dist/packages/runtime/context-graph-semantic-graph.js +416 -0
  146. package/dist/packages/runtime/execution/lib/schema.d.ts +34 -31
  147. package/dist/packages/runtime/index.d.ts +2 -2
  148. package/dist/packages/runtime/index.js +1 -1
  149. package/dist/packages/runtime/native-run-handlers.d.ts +38 -0
  150. package/dist/packages/runtime/native-run-handlers.js +52 -33
  151. package/dist/packages/runtime/plan-artifact-contract.js +1 -1
  152. package/dist/packages/runtime/project-source-state.d.ts +4 -4
  153. package/dist/packages/runtime/project-source-state.js +5 -2
  154. package/dist/packages/runtime/project-store.d.ts +5 -0
  155. package/dist/packages/runtime/project-store.js +30 -3
  156. package/dist/packages/runtime/requested-artifacts.js +1 -1
  157. package/dist/packages/runtime/run-observability.js +9 -4
  158. package/dist/packages/runtime/runtime-action-proposals.js +3 -3
  159. package/dist/packages/runtime/runtime-build-plans.js +47 -3
  160. package/dist/packages/runtime/runtime-build-runs.js +9 -16
  161. package/dist/packages/runtime/runtime-caches.d.ts +26 -0
  162. package/dist/packages/runtime/runtime-caches.js +47 -0
  163. package/dist/packages/runtime/runtime-jobs.js +6 -6
  164. package/dist/packages/runtime/runtime-project-mutations.js +1 -0
  165. package/dist/packages/runtime/runtime-project-reads.d.ts +4 -1
  166. package/dist/packages/runtime/runtime-project-reads.js +229 -36
  167. package/dist/packages/runtime/runtime-proposal-helpers.js +6 -6
  168. package/dist/packages/runtime/runtime-resource-builders.d.ts +4 -2
  169. package/dist/packages/runtime/runtime-resource-builders.js +16 -14
  170. package/dist/packages/runtime/runtime-status.d.ts +14 -0
  171. package/dist/packages/runtime/runtime-status.js +15 -0
  172. package/dist/packages/runtime/runtime-verify-runs.js +6 -5
  173. package/dist/packages/runtime/runtime.d.ts +439 -22
  174. package/dist/packages/runtime/runtime.js +16 -2
  175. package/dist/packages/runtime/schemas/actions.d.ts +24 -0
  176. package/dist/packages/runtime/schemas/agents.d.ts +28 -0
  177. package/dist/packages/runtime/schemas/agents.js +33 -0
  178. package/dist/packages/runtime/schemas/build-plans.d.ts +181 -8
  179. package/dist/packages/runtime/schemas/build-plans.js +36 -2
  180. package/dist/packages/runtime/schemas/context-graphs.d.ts +1522 -0
  181. package/dist/packages/runtime/schemas/context-graphs.js +110 -0
  182. package/dist/packages/runtime/schemas/files.d.ts +7 -347
  183. package/dist/packages/runtime/schemas/files.js +1 -24
  184. package/dist/packages/runtime/schemas/index.d.ts +1 -0
  185. package/dist/packages/runtime/schemas/index.js +1 -0
  186. package/dist/packages/runtime/schemas/jobs.js +4 -0
  187. package/dist/packages/runtime/schemas/projects.d.ts +48 -21
  188. package/dist/packages/runtime/schemas/projects.js +34 -10
  189. package/dist/packages/runtime/schemas/runs.d.ts +1009 -240
  190. package/dist/packages/runtime/schemas/runs.js +17 -0
  191. package/dist/packages/runtime/service/openapi.js +1 -0
  192. package/dist/packages/runtime/service/operations.d.ts +1666 -145
  193. package/dist/packages/runtime/service/operations.js +147 -17
  194. package/dist/packages/runtime/service/routes.d.ts +11 -3
  195. package/dist/packages/runtime/service/routes.js +11 -3
  196. package/dist/packages/runtime/service/server-app-boot.js +2 -2
  197. package/dist/packages/runtime/service/server-helpers.d.ts +11 -0
  198. package/dist/packages/runtime/service/server-helpers.js +19 -0
  199. package/dist/packages/runtime/service/server-routes-action-proposals.js +4 -2
  200. package/dist/packages/runtime/service/server-routes-agents.js +19 -85
  201. package/dist/packages/runtime/service/server-routes-build-plans.js +14 -11
  202. package/dist/packages/runtime/service/server-routes-project-context.js +102 -7
  203. package/dist/packages/runtime/service/server-routes-project-jobs.js +19 -12
  204. package/dist/packages/runtime/service/server-routes-project-runs.js +5 -2
  205. package/dist/packages/runtime/service/server-routes-projects.js +6 -2
  206. package/dist/packages/runtime/service/server-routes-runs.js +11 -4
  207. package/dist/packages/runtime/verify/lib/schema.js +12 -0
  208. package/dist/packages/runtime/verify/test-file-guard.d.ts +2 -0
  209. package/dist/packages/runtime/verify/test-file-guard.js +29 -0
  210. package/dist/packages/runtime/verify/verify-execution.d.ts +7 -0
  211. package/dist/packages/runtime/verify/verify-execution.js +109 -35
  212. package/dist/packages/runtime/verify/verify-paths.d.ts +1 -0
  213. package/dist/packages/runtime/verify/verify-paths.js +4 -0
  214. package/dist/packages/runtime/verify/verify-specs.js +49 -39
  215. package/dist/packages/runtime/wire-schemas.d.ts +1 -1
  216. package/dist/packages/runtime/wire-schemas.js +1 -1
  217. package/package.json +2 -8
  218. package/public-repo/CONTRIBUTING.md +10 -3
  219. package/public-repo/README.md +122 -226
  220. package/public-repo/build-plans/interf-default/README.md +15 -12
  221. package/public-repo/build-plans/interf-default/build/stages/entrypoint/SKILL.md +74 -0
  222. package/public-repo/build-plans/interf-default/build/stages/knowledge/SKILL.md +95 -0
  223. package/public-repo/build-plans/interf-default/build/stages/summarize/SKILL.md +38 -5
  224. package/public-repo/build-plans/interf-default/build-plan.json +27 -23
  225. package/public-repo/build-plans/interf-default/build-plan.schema.json +24 -20
  226. package/public-repo/build-plans/interf-default/use/query/SKILL.md +8 -7
  227. package/public-repo/openapi/local-service.openapi.json +11637 -4213
  228. package/public-repo/skills/interf/SKILL.md +174 -134
  229. package/dist/packages/runtime/build/runtime-paths.d.ts +0 -8
  230. package/dist/packages/runtime/build/runtime-paths.js +0 -26
  231. package/dist/packages/runtime/build/state-paths.d.ts +0 -7
  232. package/dist/packages/runtime/build/state-paths.js +0 -22
  233. package/public-repo/build-plans/interf-default/build/stages/shape/SKILL.md +0 -34
  234. package/public-repo/build-plans/interf-default/build/stages/structure/SKILL.md +0 -28
@@ -25,12 +25,15 @@
25
25
  * runtime_status shell out to `interf runtime status`
26
26
  * Desktop app profile tools:
27
27
  * create_project, prepare_build_plan, run_build
28
- * get_instance_status, get_project, get_run_status, get_run_artifacts
29
- * get_latest_context_graph, read_context_graph_file
30
- * get_context_graph_traces, get_build_evidence
28
+ * get_instance_status, get_project, get_run_status, get_run_events, get_run_artifacts
29
+ * get_latest_context_graph, get_context_graph_entrypoint, read_context_graph_file
30
+ * get_context_graph_traces, get_context_graph_sessions, get_context_graph_session,
31
+ * get_build_evidence
31
32
  *
32
33
  * Headless developer profile additionally exposes runtime lifecycle,
33
- * inventory, Build Plan library, benchmark, cancel, and admin tools.
34
+ * inventory, Build Plan library, benchmark, cancel, admin, full run event
35
+ * log (runs_events), and execution-session reads (context_graph_sessions,
36
+ * context_graph_session).
34
37
  */
35
38
  import { spawn } from "node:child_process";
36
39
  import { readFileSync } from "node:fs";
@@ -39,26 +42,51 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
39
42
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
40
43
  import { CONNECT_OR_ERROR_HINT, readActiveConnection, } from "../../packages/runtime/connection-config.js";
41
44
  import { readServiceRegistry, } from "../../packages/runtime/service/service-registry.js";
45
+ import { callJson, } from "../lib/http-client.js";
46
+ import { slugify } from "../../packages/contracts/utils/naming.js";
42
47
  import { LOCAL_SERVICE_ROUTES, buildPlanResourcePath, buildPlanSubresourcePath, projectResourcePath, projectSubresourcePath, runResourcePath, runSubresourcePath, } from "../../packages/runtime/service/routes.js";
43
48
  import { BuildPlanAuthoringArtifactRequirementSchema, BuildPlanContextCheckDraftSchema, RequestedArtifactSchema, } from "../../packages/runtime/schemas/index.js";
49
+ import { ArtifactIdSchema, BuildPlanIdSchema, ProjectIdSchema, } from "../../packages/contracts/lib/schema.js";
44
50
  import { SourceContextSchema, } from "../../packages/projects/lib/schema.js";
51
+ // ───────────────────────────────────────────────────────────────────────────
52
+ // MCP id input schemas. These reuse the contract ID schemas so the MCP surface
53
+ // accepts exactly the ids the runtime accepts — instead of a looser inline
54
+ // `z.string().min(1)` that would let MCP pass ids the runtime then rejects.
55
+ // `project_id`/`build_plan_id`/`artifact_id` carry the contract regex +
56
+ // reserved-id rules; `run_id`s are opaque underscore-bearing tokens the runtime
57
+ // mints (e.g. `build_<base36>_<base36>`), so there is no stricter contract
58
+ // schema for them — they stay `z.string().min(1)`, defined once here.
59
+ // ───────────────────────────────────────────────────────────────────────────
60
+ const McpProjectIdSchema = ProjectIdSchema.describe("Project id (kebab-case).");
61
+ const McpBuildPlanIdSchema = BuildPlanIdSchema.describe("Build Plan id (kebab-case).");
62
+ const McpArtifactIdSchema = ArtifactIdSchema.describe("Requested output id (kebab-case).");
63
+ const McpRunIdSchema = z.string().min(1).describe("Run id.");
45
64
  const INTERF_MCP_INSTRUCTIONS = [
46
- "Interf prepares data for agents. It is not a search engine and not a general RAG index.",
47
- "Interf MCP is how this host talks to Interf. Agents listed inside Interf are executors that run Build Plan stages. Do not treat MCP setup as executor setup.",
48
- "App MCP exposes three core workflow tools: create_project, prepare_build_plan, and run_build. Other tools are read-only inspection helpers.",
49
- "Default workflow for a user question over files: create a fresh Project for the current Source, propose Context Checks and requested Artifacts, prepare the Build Plan after the user approves those checks and Artifacts, stop for Build Plan approval, run_build only after that approval, then answer from the prepared Context Graph and its source-backed traces.",
50
- "Source scope default: if Interf Desktop, the MCP host, or the user context already provides a Source locator or file set, use that whole Source. Do not ask the user to choose individual files or a subset unless they explicitly ask to narrow scope.",
51
- "Do not answer by browsing existing Projects as if they were a corpus. In the Desktop app profile, always create a fresh Project for the current Source unless the user explicitly names an existing Project id.",
52
- "Use existing Projects or Context Graphs only when the user explicitly selected or named them and they bind the same Source and task.",
53
- "If no usable Source locator is available, ask for one Source locator. In the local Desktop path this may be a folder path. Do not present a file-selection menu or ask which files inside the Source to use.",
54
- "Project creation is allowed when the user asks Interf to use a Source. Project ids are generated internally. Do not ask for existing Project ids. Approval gates are for Build Plan preparation and Build execution.",
55
- "Before building, show the user the Context Checks, requested Artifacts, and drafted Build Plan in chat. Wait for approval unless the user has explicitly granted end-to-end autonomy.",
56
- "No automatic retries: if prepare_build_plan, run_build, or a polled Run reaches failed/cancelled, report the failure and ask the user before starting another draft or Build run.",
57
- "After a Build succeeds, read the task handoff under artifacts/ first. Treat home.md as a graph index, summaries/ as source coverage proof, and knowledge/ as navigation/drilldown.",
58
- "A Context Graph is a knowledge map over the Source, not the answer source. Use it to understand what exists and where evidence lives; follow source references and traces when exact values, chart reads, tables, or provenance matter.",
59
- "If a Context Graph artifact is too coarse or missing the needed evidence, improve the Build Plan and rebuild instead of giving a weak answer.",
65
+ "WHAT INTERF IS",
66
+ "Interf prepares data for agents. It builds a task-specific Context Graph from a Source (the user's files) — claim nodes, entities, comparison nodes, timelines, coverage indexes — that any agent can read to answer. Source-of-truth stays in the user's files. Interf does NOT answer the user's question; it prepares the structured graph the agent reasons over.",
67
+ "",
68
+ "WHAT YOU PASS, WHAT YOU GET",
69
+ "You pass: the user's intent (the task the graph is for) and optional graph areas you want prepared. You get: a Context Graph the agent reads home.md as entrypoint, knowledge/ for drilldown, summaries/ as source coverage, source-backed traces for exact values.",
70
+ "",
71
+ "THE WORKFLOW",
72
+ "1. create_project bind the Source + intent.",
73
+ "2. prepare_build_plan name the graph areas to prepare (e.g. 'NY rent forecast claim nodes', 'cost comparison nodes', 'decision timeline'). Show the draft to the user. Stop for approval unless they granted end-to-end autonomy.",
74
+ "3. run_build only after approval. Wait for terminal state; do not auto-retry.",
75
+ "4. get_latest_context_graph read primary_metrics + home.md, follow traces for exact values, then answer.",
76
+ "",
77
+ "REQUESTED OUTPUTS ARE GRAPH AREAS, NOT ANSWERS",
78
+ "Each requested output is a region of the Context Graph the next agent will traverse (claim nodes, comparison nodes, a timeline, a coverage index). Never name an output 'the answer markdown', 'final report', 'forecast summary', or 'recommended decision' — those replace agent thinking. The agent still reasons; Interf only prepares.",
79
+ "",
80
+ "SOURCING",
81
+ "If the host/user already provides a Source locator, use the whole Source. Don't ask the user to pick files. Don't browse existing Projects like a corpus — create a fresh Project per task unless the user explicitly names one. Project ids are auto-generated.",
82
+ "",
83
+ "EXECUTORS VS MCP",
84
+ "Interf MCP is how this host talks to Interf. The agents listed inside Interf are EXECUTORS that run Build Plan stages; that is a separate setup from this MCP connection.",
85
+ "",
86
+ "FAILURE HANDLING",
87
+ "If any Run fails with 'executor preflight' in the error, the active execution agent CLI is broken on this machine. Tell the user to switch with `interf agents use claude-code` (or another available executor). Do not retry, do not create a new Project. For any other failure, report it and ask before starting another draft or Build.",
60
88
  ].join("\n");
61
- const McpRequestedArtifactSchema = RequestedArtifactSchema.describe("Requested Artifact the user approved. Use a short title, optional id, description/purpose, and plain-English checks.");
89
+ const McpRequestedArtifactSchema = RequestedArtifactSchema.describe("A graph area Interf should prepare in the Context Graph — claim nodes, comparison nodes, a timeline, a coverage index. NOT the user's final answer and NOT a finished report. Each requested output is structured prepared data the NEXT agent will read and reason over. Good titles: 'NY rent forecast claims', 'Bristol vs London cost comparison nodes', 'Q3 decision-timeline signals'. Bad titles: 'NY rent growth answer', 'Final report', 'Forecast summary' — those replace agent thinking instead of preparing data for it. Source-of-truth stays in the user's files; Interf builds the task-specific Context Graph the agent reads.");
62
90
  function normalizeRequestedArtifacts(artifacts) {
63
91
  if (!artifacts)
64
92
  return undefined;
@@ -96,16 +124,12 @@ function encodeRelativePath(value) {
96
124
  function contextGraphFilePath(projectId, filePath) {
97
125
  return `${projectSubresourcePath(projectId, "contextGraphFile")}?path=${encodeURIComponent(filePath)}`;
98
126
  }
99
- function slugifyMcpId(input) {
100
- return input
101
- .toLowerCase()
102
- .trim()
103
- .replace(/[^a-z0-9]+/g, "-")
104
- .replace(/^-+|-+$/g, "")
105
- .slice(0, 48);
106
- }
107
- function generatedMcpId(prefix) {
108
- const base = slugifyMcpId(prefix).slice(0, 18) || "item";
127
+ // Exported for the slugify-equivalence regression test. The 18-char clamp keeps
128
+ // the generated base well inside `slugify`'s own 80-char cap, so swapping the
129
+ // former local `slugifyMcpId` (48-char cap) for the shared `slugify` is
130
+ // behavior-preserving for every input.
131
+ export function generatedMcpId(prefix) {
132
+ const base = slugify(prefix).slice(0, 18) || "item";
109
133
  const suffix = `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`;
110
134
  return `${base}-${suffix}`;
111
135
  }
@@ -120,6 +144,15 @@ function packageVersionFromManifest() {
120
144
  return "0.0.0";
121
145
  }
122
146
  }
147
+ // MCP intentionally does NOT use http-client's `resolveConnection`. That helper
148
+ // is the CLI contract: it `process.exit(1)`s when no connection is found, which
149
+ // is correct for a one-shot CLI command but fatal for a long-lived MCP server
150
+ // that must instead return a structured `CONNECT_OR_ERROR_HINT` tool error and
151
+ // stay up. MCP also adds a `--url`-override token discovery step (services.json
152
+ // registry, then the active connection) that the plain CLI override path does
153
+ // not perform. Until http-client exports a shared null-returning variant, this
154
+ // resolution stays here; the underlying `readActiveConnection` precedence is
155
+ // still single-sourced in connection-config.
123
156
  function resolveConnectionOrNull(args) {
124
157
  const urlOverride = args.url?.trim();
125
158
  const currentLocalToken = urlOverride
@@ -174,25 +207,12 @@ function runInterfCli(args) {
174
207
  });
175
208
  });
176
209
  }
177
- async function callApi(conn, path, init = {}) {
178
- const headers = new Headers(init.headers ?? {});
179
- if (conn.token)
180
- headers.set("authorization", `Bearer ${conn.token}`);
181
- if (init.body && !headers.has("content-type")) {
182
- headers.set("content-type", "application/json");
183
- }
184
- const response = await fetch(`${conn.url}${path}`, { ...init, headers });
185
- const raw = await response.text();
186
- let body = null;
187
- if (raw.length > 0) {
188
- try {
189
- body = JSON.parse(raw);
190
- }
191
- catch {
192
- body = raw;
193
- }
194
- }
195
- return { status: response.status, body, raw };
210
+ // MCP issues every API call through the shared CLI `callJson` (header-setting +
211
+ // JSON parsing live solely in http-client). `callJson` yields `body: null` on a
212
+ // non-JSON body (vs the former local `callApi`'s `body = raw`); every read site
213
+ // goes through `body ?? raw` or an `isRecord(body)` guard, so behavior holds.
214
+ function mcpApi(conn, path, init = {}) {
215
+ return callJson(`${conn.url}${path}`, conn.token, init);
196
216
  }
197
217
  function toolResultJson(payload) {
198
218
  const text = typeof payload === "string"
@@ -224,7 +244,7 @@ async function callAndReturn(args, path, init = {}) {
224
244
  const conn = resolveConnectionOrNull(args);
225
245
  if (!conn)
226
246
  return toolErrorJson(CONNECT_OR_ERROR_HINT);
227
- const response = await callApi(conn, path, init);
247
+ const response = await mcpApi(conn, path, init);
228
248
  if (response.status >= 200 && response.status < 300) {
229
249
  return toolResultJson(response.body ?? response.raw);
230
250
  }
@@ -234,7 +254,7 @@ async function callAndProject(args, path, project, init = {}) {
234
254
  const conn = resolveConnectionOrNull(args);
235
255
  if (!conn)
236
256
  return toolErrorJson(CONNECT_OR_ERROR_HINT);
237
- const response = await callApi(conn, path, init);
257
+ const response = await mcpApi(conn, path, init);
238
258
  if (response.status >= 200 && response.status < 300) {
239
259
  return toolResultJson(project(response.body, response.raw));
240
260
  }
@@ -387,7 +407,7 @@ function compactRunEvents(payload, options) {
387
407
  };
388
408
  }
389
409
  async function currentSourcePathForApp(conn) {
390
- const response = await callApi(conn, LOCAL_SERVICE_ROUTES.health);
410
+ const response = await mcpApi(conn, LOCAL_SERVICE_ROUTES.health);
391
411
  if (response.status >= 200 && response.status < 300 && isRecord(response.body)) {
392
412
  const sourcePath = readString(response.body, "source_folder_path");
393
413
  if (sourcePath)
@@ -397,7 +417,7 @@ async function currentSourcePathForApp(conn) {
397
417
  return sourceCandidates.length === 1 ? sourceCandidates[0]?.source_path ?? null : null;
398
418
  }
399
419
  async function sourceCandidatesForApp(conn) {
400
- const response = await callApi(conn, LOCAL_SERVICE_ROUTES.projects);
420
+ const response = await mcpApi(conn, LOCAL_SERVICE_ROUTES.projects);
401
421
  if (response.status < 200 || response.status >= 300 || !isRecord(response.body))
402
422
  return [];
403
423
  const bySource = new Map();
@@ -431,10 +451,12 @@ async function callAppCreateProject(args, request) {
431
451
  return toolErrorJson("No unambiguous current Source locator is exposed by Interf. If source_candidates contains a Source that clearly matches the user's task, call create_project again with that source_path. Otherwise ask for one Source locator. Do not ask for an existing Project id or ask the user to choose individual files.", { source_candidates: sourceCandidates });
432
452
  }
433
453
  const id = generatedMcpId("project");
434
- const response = await callApi(conn, LOCAL_SERVICE_ROUTES.projects, {
454
+ const intent = request.intent.trim();
455
+ const response = await mcpApi(conn, LOCAL_SERVICE_ROUTES.projects, {
435
456
  method: "POST",
436
457
  body: JSON.stringify({
437
458
  id,
459
+ intent,
438
460
  source: { kind: "local-folder", locator: sourcePath },
439
461
  }),
440
462
  });
@@ -446,34 +468,35 @@ async function callAppCreateProject(args, request) {
446
468
  function registerAppProfileTools(server, connectionArgs) {
447
469
  server.registerTool("create_project", {
448
470
  title: "Create Project",
449
- description: "Core step 1. Create a fresh Project for this task and the whole current Source. The Project id is generated internally; do not ask for or provide one.",
471
+ description: "Workflow step 1. Bind the current Source + the user's intent (the task the Context Graph is for). Project id is auto-generated.",
450
472
  inputSchema: {
451
- source_path: z.string().min(1).optional().describe("Fallback Source locator. In the local Desktop path this is an absolute folder path. Use only when Interf does not expose a current Source; do not pass individual files or a subset selection."),
473
+ intent: z.string().min(1).describe("The task the Context Graph must support e.g. 'compare NY effective vs blended rent growth for 2026'."),
474
+ source_path: z.string().min(1).optional().describe("Fallback Source locator (absolute folder path on local Desktop). Pass only when Interf does not expose a current Source."),
452
475
  },
453
476
  }, async (args) => callAppCreateProject(connectionArgs, args));
454
477
  server.registerTool("prepare_build_plan", {
455
478
  title: "Prepare Build Plan",
456
- description: "Core step 2. Draft the approved Build Plan for the Project. Use after the user approves checks and requested Artifacts. Stop after this tool and ask for Build Plan approval before building. If it fails, report the failure; do not retry without explicit user approval.",
479
+ description: "Workflow step 2. Draft the Build Plan from the Project intent + requested graph areas. Stop after this tool and show the draft for user approval (see top-level instructions for failure handling).",
457
480
  inputSchema: {
458
- project_id: z.string().min(1).describe("Project id from create_project."),
459
- build_plan_id: z.string().min(1).optional().describe("Optional Build Plan id. Omit to auto-generate."),
481
+ project_id: McpProjectIdSchema.describe("Project id from create_project."),
482
+ build_plan_id: McpBuildPlanIdSchema.optional().describe("Optional Build Plan id. Omit to auto-generate."),
460
483
  label: z.string().min(1).optional().describe("Optional short human label."),
461
484
  hint: z.string().min(1).optional().describe("Optional one-line plan hint."),
462
- intent: z.string().min(1).describe("Question/task the Context Graph must support."),
463
- context_checks: z.array(BuildPlanContextCheckDraftSchema).optional().describe("Plain-English checks the user approved."),
464
- requested_artifacts: z.array(McpRequestedArtifactSchema).optional().describe("Requested Artifacts the user approved."),
485
+ intent: z.string().min(1).optional().describe("Question/task the Context Graph must support. Omit to use the Project intent."),
486
+ context_checks: z.array(BuildPlanContextCheckDraftSchema).optional().describe("Optional legacy plain-English checks. Prefer Project intent plus requested outputs and coverage expectations."),
487
+ requested_artifacts: z.array(McpRequestedArtifactSchema).optional().describe("Requested outputs the user approved."),
465
488
  source_context: SourceContextSchema.nullable().optional(),
466
489
  },
467
490
  }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.project_id, "buildPlanDraftRuns"), {
468
491
  method: "POST",
469
492
  body: JSON.stringify((() => {
470
- const intent = args.intent.trim();
493
+ const intent = args.intent?.trim();
471
494
  const buildPlanId = args.build_plan_id?.trim() || generatedMcpId("plan");
472
495
  return {
473
496
  build_plan_id: buildPlanId,
474
497
  label: args.label?.trim() || buildPlanId,
475
- hint: args.hint?.trim() || intent,
476
- intent,
498
+ hint: args.hint?.trim() || intent || `Build Plan for Project ${args.project_id}`,
499
+ ...(intent ? { intent } : {}),
477
500
  ...(args.context_checks ? { checks: args.context_checks } : {}),
478
501
  ...(args.requested_artifacts ? { requested_artifacts: normalizeRequestedArtifacts(args.requested_artifacts) } : {}),
479
502
  ...(args.source_context !== undefined ? { source_context: args.source_context } : {}),
@@ -482,9 +505,9 @@ function registerAppProfileTools(server, connectionArgs) {
482
505
  }));
483
506
  server.registerTool("run_build", {
484
507
  title: "Run Build",
485
- description: "Core step 3. Run the selected Build Plan and create the Context Graph. Never call immediately after prepare_build_plan; use only after explicit Build Plan approval or explicit end-to-end autonomy. If it fails, report the failure; do not retry without explicit user approval.",
508
+ description: "Workflow step 3. Run the approved Build Plan and build the Context Graph. Only call after explicit Build Plan approval or explicit end-to-end autonomy. See top-level instructions for failure handling.",
486
509
  inputSchema: {
487
- project_id: z.string().min(1).describe("Project id from create_project."),
510
+ project_id: McpProjectIdSchema.describe("Project id from create_project."),
488
511
  },
489
512
  }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.project_id, "buildRuns"), { method: "POST", body: "{}" }));
490
513
  server.registerTool("get_instance_status", {
@@ -496,8 +519,8 @@ function registerAppProfileTools(server, connectionArgs) {
496
519
  if (!conn)
497
520
  return toolErrorJson(CONNECT_OR_ERROR_HINT);
498
521
  const [health, instance, sourceCandidates] = await Promise.all([
499
- callApi(conn, LOCAL_SERVICE_ROUTES.health),
500
- callApi(conn, LOCAL_SERVICE_ROUTES.instance),
522
+ mcpApi(conn, LOCAL_SERVICE_ROUTES.health),
523
+ mcpApi(conn, LOCAL_SERVICE_ROUTES.instance),
501
524
  sourceCandidatesForApp(conn),
502
525
  ]);
503
526
  if (health.status < 200 || health.status >= 300) {
@@ -520,42 +543,56 @@ function registerAppProfileTools(server, connectionArgs) {
520
543
  agent_count: readNumber(instanceBody, "agent_count"),
521
544
  default_agent: readString(instanceBody, "default_agent"),
522
545
  source_candidates: sourceCandidates,
523
- instruction: "For a new file question: use the whole current Source, create_project -> ask user to approve checks/Artifacts -> prepare_build_plan -> ask user to approve the Build Plan -> run_build. If source_path is null but source_candidates has a Source that clearly matches the user's task, pass that source_path to create_project. Do not ask which files inside the Source to use unless the user explicitly narrows scope.",
546
+ instruction: "For a new file question: use the whole current Source, create_project -> prepare_build_plan -> ask user to review/approve the Build Plan -> run_build -> get_latest_context_graph. If source_path is null but source_candidates has a Source that clearly matches the user's task, pass that source_path to create_project. Do not ask which files inside the Source to use unless the user explicitly narrows scope.",
524
547
  });
525
548
  });
526
549
  server.registerTool("get_project", {
527
550
  title: "Get Project",
528
551
  description: "Read-only helper. Confirm one Project's Source binding, selected Build Plan, readiness, and latest Context Graph.",
529
552
  inputSchema: {
530
- project_id: z.string().min(1).describe("Project id."),
553
+ project_id: McpProjectIdSchema,
531
554
  },
532
555
  }, async (args) => callAndReturn(connectionArgs, projectResourcePath(args.project_id)));
556
+ server.registerTool("get_project_readiness", {
557
+ title: "Get Project Readiness",
558
+ description: "Read-only helper. Return ready/not ready for the latest Context Graph against the Project intent.",
559
+ inputSchema: {
560
+ project_id: McpProjectIdSchema,
561
+ },
562
+ }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.project_id, "readiness")));
533
563
  server.registerTool("get_run_status", {
534
564
  title: "Get Run Status",
535
565
  description: "Read-only helper. Compact polling receipt for one Run. Use this for repeated status checks.",
536
566
  inputSchema: {
537
- run_id: z.string().min(1).describe("Run id."),
567
+ run_id: McpRunIdSchema,
538
568
  },
539
569
  }, async (args) => callAndProject(connectionArgs, runSubresourcePath(args.run_id, "status"), compactRunStatus));
540
570
  server.registerTool("get_run_artifacts", {
541
- title: "Get Run Artifacts",
571
+ title: "Get Run Outputs",
542
572
  description: "Read-only helper. Fetch a finished Run's artifact manifest only when status is terminal or when reviewing a completed Build Plan draft.",
543
573
  inputSchema: {
544
- run_id: z.string().min(1).describe("Run id."),
574
+ run_id: McpRunIdSchema,
545
575
  },
546
576
  }, async (args) => callAndReturn(connectionArgs, `${LOCAL_SERVICE_ROUTES.runs}/${encodeURIComponent(args.run_id)}/artifacts`));
547
577
  server.registerTool("get_latest_context_graph", {
548
578
  title: "Get Latest Context Graph",
549
- description: "Read-only helper. Show the latest Context Graph locator for a Project. This is a locator/status read, not the answer surface; read artifacts/ handoff files next.",
579
+ description: "Read-only helper. Show the latest Context Graph locator, GraphManifest, primary metrics, entrypoints, and readiness for a Project. Start from home.md next.",
550
580
  inputSchema: {
551
- project_id: z.string().min(1).describe("Project id."),
581
+ project_id: McpProjectIdSchema,
552
582
  },
553
583
  }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.project_id, "contextGraph")));
584
+ server.registerTool("get_context_graph_entrypoint", {
585
+ title: "Get Graph Entrypoint",
586
+ description: "Read-only helper. Return the downstream agent entrypoint for the latest Context Graph. Start from home.md, then follow entrypoint links when useful.",
587
+ inputSchema: {
588
+ project_id: McpProjectIdSchema,
589
+ },
590
+ }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.project_id, "contextGraphEntrypoint")));
554
591
  server.registerTool("read_context_graph_file", {
555
592
  title: "Read Context Graph File",
556
- description: "Read one prepared Context Graph file by relative path. Start with artifacts/ task handoffs; use summaries/ for coverage and knowledge/ for drilldown.",
593
+ description: "Read one prepared Context Graph file by relative path. Start with home.md; use summaries/ for coverage and knowledge/ for drilldown.",
557
594
  inputSchema: {
558
- project_id: z.string().min(1).describe("Project id."),
595
+ project_id: McpProjectIdSchema,
559
596
  path: z.string().min(1).describe("Relative path inside the Context Graph."),
560
597
  },
561
598
  }, async (args) => callAndReturn(connectionArgs, contextGraphFilePath(args.project_id, args.path)));
@@ -563,14 +600,36 @@ function registerAppProfileTools(server, connectionArgs) {
563
600
  title: "Get Context Graph Traces",
564
601
  description: "Read-only helper. Read source-backed traces for exact values and provenance.",
565
602
  inputSchema: {
566
- project_id: z.string().min(1).describe("Project id."),
603
+ project_id: McpProjectIdSchema,
567
604
  },
568
605
  }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.project_id, "traces")));
606
+ server.registerTool("get_context_graph_sessions", {
607
+ title: "Get Context Graph Execution Sessions",
608
+ description: "Read-only helper. List the per-stage execution shell sessions for the latest Build run — executor + model, status, attempt, validation attempts, and replay readiness. Pull these to drive the next self-improvement iteration when a stage was weak or failed.",
609
+ inputSchema: {
610
+ project_id: McpProjectIdSchema,
611
+ },
612
+ }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.project_id, "contextGraphSessions")));
613
+ server.registerTool("get_context_graph_session", {
614
+ title: "Get One Context Graph Execution Session",
615
+ description: "Read-only helper. Return one preserved execution shell session by stage_run_id — prompt, event/status log paths, runtime files, artifact mounts, validation attempts, and the terminal verdict. Use it to inspect or replay exactly what a stage attempt did.",
616
+ inputSchema: {
617
+ project_id: McpProjectIdSchema,
618
+ stage_run_id: z.string().min(1).describe("Stage execution session id (stage_run_id) from get_context_graph_sessions."),
619
+ },
620
+ }, async (args) => callAndReturn(connectionArgs, `${projectSubresourcePath(args.project_id, "contextGraphSessions")}/${encodeURIComponent(args.stage_run_id)}`));
621
+ server.registerTool("get_run_events", {
622
+ title: "Get Run Events",
623
+ description: "Read-only helper. Read the durable event log for a Build run: stage start/pass/fail, files processed, artifacts written, evidence, checks, and readiness. Poll get_run_status for progress; read events to inspect or replay what happened.",
624
+ inputSchema: {
625
+ run_id: McpRunIdSchema,
626
+ },
627
+ }, async (args) => callAndReturn(connectionArgs, runSubresourcePath(args.run_id, "events")));
569
628
  server.registerTool("get_build_evidence", {
570
- title: "Get Build Evidence",
571
- description: "Read-only helper. Read checks, Artifact diagnostics, and readiness evidence.",
629
+ title: "Get Supplemental Build Diagnostics",
630
+ description: "Read-only helper. Read supplemental diagnostics. Prefer get_latest_context_graph for primary coverage metrics and readiness.",
572
631
  inputSchema: {
573
- project_id: z.string().min(1).describe("Project id."),
632
+ project_id: McpProjectIdSchema,
574
633
  },
575
634
  }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.project_id, "buildEvidence")));
576
635
  }
@@ -651,11 +710,12 @@ function registerTools(server, connectionArgs) {
651
710
  description: "Create a Project for the user's current Source. In the Desktop app profile, this is normally "
652
711
  + "the first Interf action for a new user question over files.",
653
712
  inputSchema: {
654
- id: z.string().min(1).describe("Project id (kebab-case)."),
713
+ id: McpProjectIdSchema,
714
+ intent: z.string().min(1).describe("Agent task this Project's Context Graph should support."),
655
715
  source_path: z.string().min(1).describe("Source path visible to the connected instance."),
656
716
  ...(!appProfile
657
717
  ? {
658
- build_plan_id: z.string().min(1).optional().describe("Optional Build Plan id to select."),
718
+ build_plan_id: McpBuildPlanIdSchema.optional().describe("Optional Build Plan id to select."),
659
719
  }
660
720
  : {}),
661
721
  },
@@ -663,6 +723,7 @@ function registerTools(server, connectionArgs) {
663
723
  method: "POST",
664
724
  body: JSON.stringify({
665
725
  id: args.id,
726
+ intent: args.intent,
666
727
  source: { kind: "local-folder", locator: args.source_path },
667
728
  ...(args.build_plan_id ? { build_plan_id: args.build_plan_id } : {}),
668
729
  }),
@@ -672,17 +733,24 @@ function registerTools(server, connectionArgs) {
672
733
  description: "Return one Project resource to confirm its Source binding, selected Build Plan, readiness, "
673
734
  + "and latest Context Graph before deciding whether it matches the current task.",
674
735
  inputSchema: {
675
- id: z.string().min(1).describe("Project id."),
736
+ id: McpProjectIdSchema,
676
737
  },
677
738
  }, async (args) => callAndReturn(connectionArgs, projectResourcePath(args.id)));
739
+ server.registerTool("project_readiness", {
740
+ title: "Read Project readiness",
741
+ description: "Return the ready/not ready status for this Project's latest Context Graph against the Project intent.",
742
+ inputSchema: {
743
+ id: McpProjectIdSchema,
744
+ },
745
+ }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.id, "readiness")));
678
746
  if (!appProfile) {
679
747
  server.registerTool("project_select_build_plan", {
680
748
  title: "Select a Build Plan for a Project",
681
749
  description: "Developer/admin tool. Update the selected Build Plan on a Project. "
682
750
  + "Build Plan draft/improve runs select their resulting Plan automatically.",
683
751
  inputSchema: {
684
- id: z.string().min(1).describe("Project id."),
685
- build_plan_id: z.string().min(1).describe("Build Plan id to use."),
752
+ id: McpProjectIdSchema,
753
+ build_plan_id: McpBuildPlanIdSchema.describe("Build Plan id to use."),
686
754
  },
687
755
  }, async (args) => callAndReturn(connectionArgs, projectResourcePath(args.id), {
688
756
  method: "PATCH",
@@ -692,7 +760,7 @@ function registerTools(server, connectionArgs) {
692
760
  title: "Remove a Project",
693
761
  description: "Developer/admin tool. Delete a Project and its Context Graph.",
694
762
  inputSchema: {
695
- id: z.string().min(1).describe("Project id."),
763
+ id: McpProjectIdSchema,
696
764
  },
697
765
  }, async (args) => callAndReturn(connectionArgs, projectResourcePath(args.id), {
698
766
  method: "DELETE",
@@ -702,10 +770,10 @@ function registerTools(server, connectionArgs) {
702
770
  server.registerTool("project_build", {
703
771
  title: "Build Context Graph",
704
772
  description: "Run the selected Build Plan for a Project and write a task-specific Context Graph. "
705
- + "Use this only after the user has approved the checks/requested Artifacts and Build Plan, "
773
+ + "Use this only after the user has approved the coverage expectations, requested outputs, and Build Plan, "
706
774
  + "unless they explicitly granted autonomy. Returns immediately; poll with runs_status.",
707
775
  inputSchema: {
708
- id: z.string().min(1).describe("Project id."),
776
+ id: McpProjectIdSchema,
709
777
  },
710
778
  }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.id, "buildRuns"), { method: "POST", body: "{}" }));
711
779
  if (!appProfile) {
@@ -713,7 +781,7 @@ function registerTools(server, connectionArgs) {
713
781
  title: "Run benchmark/evaluation",
714
782
  description: "Developer/evaluation tool. Run the Project's Q&A / fact-check benchmark against the latest Context Graph.",
715
783
  inputSchema: {
716
- id: z.string().min(1).describe("Project id."),
784
+ id: McpProjectIdSchema,
717
785
  },
718
786
  }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.id, "verifyRuns"), {
719
787
  method: "POST",
@@ -725,23 +793,30 @@ function registerTools(server, connectionArgs) {
725
793
  description: "List the Source files bound to a Project to confirm coverage scope. "
726
794
  + "This is not an answer source by itself; prepare or inspect a Context Graph before answering.",
727
795
  inputSchema: {
728
- id: z.string().min(1).describe("Project id."),
796
+ id: McpProjectIdSchema,
729
797
  },
730
798
  }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.id, "sourceFiles")));
731
799
  server.registerTool("context_graph_show", {
732
800
  title: "Show latest Context Graph",
733
801
  description: "Inspect the latest Context Graph locator/status for a Project. Reuse it only if it was built for the same Source "
734
- + "and task-relevant checks/artifacts; otherwise improve or draft a Build Plan and rebuild. Read artifacts/ handoffs before answering.",
802
+ + "and task intent; otherwise improve or draft a Build Plan and rebuild. Read home.md before answering.",
735
803
  inputSchema: {
736
- project_id: z.string().min(1).describe("Project id."),
804
+ project_id: McpProjectIdSchema,
737
805
  },
738
806
  }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.project_id, "contextGraph")));
807
+ server.registerTool("context_graph_entrypoint", {
808
+ title: "Read Context Graph entrypoint",
809
+ description: "Return the downstream entrypoint for the latest Context Graph. Start from home.md before summaries/ or knowledge/.",
810
+ inputSchema: {
811
+ project_id: McpProjectIdSchema,
812
+ },
813
+ }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.project_id, "contextGraphEntrypoint")));
739
814
  server.registerTool("context_graph_file_read", {
740
815
  title: "Read a Context Graph file",
741
- description: "Read one prepared Context Graph file by relative path. Start with artifacts/ task handoffs, "
816
+ description: "Read one prepared Context Graph file by relative path. Start with home.md, "
742
817
  + "then use summaries/ for coverage and knowledge/ for drilldown. Do not use this to search unrelated Projects for answers.",
743
818
  inputSchema: {
744
- project_id: z.string().min(1).describe("Project id."),
819
+ project_id: McpProjectIdSchema,
745
820
  path: z.string().min(1).describe("Relative path inside the Context Graph root."),
746
821
  },
747
822
  }, async (args) => callAndReturn(connectionArgs, contextGraphFilePath(args.project_id, args.path)));
@@ -750,23 +825,37 @@ function registerTools(server, connectionArgs) {
750
825
  description: "Read source-backed traces for the latest Context Graph. Use traces to follow prepared context "
751
826
  + "back to the Source for exact values, chart reads, tables, and provenance-sensitive claims.",
752
827
  inputSchema: {
753
- project_id: z.string().min(1).describe("Project id."),
828
+ project_id: McpProjectIdSchema,
754
829
  },
755
830
  }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.project_id, "traces")));
831
+ server.registerTool("context_graph_sessions", {
832
+ title: "List Context Graph execution sessions",
833
+ description: "List the per-stage execution shell sessions for the latest Build run — executor + model, status, attempt, validation attempts, and replay readiness. Pull these to drive the next self-improvement iteration when a stage was weak or failed.",
834
+ inputSchema: {
835
+ project_id: McpProjectIdSchema,
836
+ },
837
+ }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.project_id, "contextGraphSessions")));
838
+ server.registerTool("context_graph_session", {
839
+ title: "Get one Context Graph execution session",
840
+ description: "Return one preserved execution shell session by stage_run_id — prompt, event/status log paths, runtime files, artifact mounts, validation attempts, and terminal verdict. Use it to inspect or replay exactly what a stage attempt did.",
841
+ inputSchema: {
842
+ project_id: McpProjectIdSchema,
843
+ stage_run_id: z.string().min(1).describe("Stage execution session id (stage_run_id) from context_graph_sessions."),
844
+ },
845
+ }, async (args) => callAndReturn(connectionArgs, `${projectSubresourcePath(args.project_id, "contextGraphSessions")}/${encodeURIComponent(args.stage_run_id)}`));
756
846
  server.registerTool("project_build_evidence", {
757
- title: "Read Build evidence",
758
- description: "Read the latest Build evidence resource for a Project: check rows, Artifact diagnostics, "
759
- + "and readiness backing. If evidence is weak or missing, improve the Build Plan instead of answering.",
847
+ title: "Read Supplemental Build Diagnostics",
848
+ description: "Read the latest supplemental diagnostics resource for a Project. Prefer context_graph_show for primary metrics; if coverage is weak or missing, improve the Build Plan instead of answering.",
760
849
  inputSchema: {
761
- project_id: z.string().min(1).describe("Project id."),
850
+ project_id: McpProjectIdSchema,
762
851
  },
763
852
  }, async (args) => callAndReturn(connectionArgs, projectSubresourcePath(args.project_id, "buildEvidence")));
764
853
  server.registerTool("project_artifact_show", {
765
- title: "Show Project Artifact",
766
- description: "Return latest status and contributing evidence for one Build Plan-declared Artifact.",
854
+ title: "Show Requested Output",
855
+ description: "Return latest status and contributing evidence for one Build Plan-declared requested output.",
767
856
  inputSchema: {
768
- project_id: z.string().min(1).describe("Project id."),
769
- artifact_id: z.string().min(1).describe("Artifact id."),
857
+ project_id: McpProjectIdSchema,
858
+ artifact_id: McpArtifactIdSchema.describe("Requested output id."),
770
859
  },
771
860
  }, async (args) => callAndReturn(connectionArgs, `${projectSubresourcePath(args.project_id, "artifacts")}/${encodeURIComponent(args.artifact_id)}`));
772
861
  // ── Build Plans ────────────────────────────────────────────────────────
@@ -778,9 +867,9 @@ function registerTools(server, connectionArgs) {
778
867
  }, async () => callAndReturn(connectionArgs, LOCAL_SERVICE_ROUTES.buildPlans));
779
868
  server.registerTool("build_plan_show", {
780
869
  title: "Show one Build Plan",
781
- description: "Developer/library tool. Return one Build Plan resource, including requested Artifacts, stages, and checks.",
870
+ description: "Developer/library tool. Return one Build Plan resource, including requested outputs, stages, and coverage checks.",
782
871
  inputSchema: {
783
- build_plan_id: z.string().min(1).describe("Build Plan id."),
872
+ build_plan_id: McpBuildPlanIdSchema,
784
873
  },
785
874
  }, async (args) => callAndReturn(connectionArgs, buildPlanResourcePath(args.build_plan_id)));
786
875
  server.registerTool("build_plan_file_read", {
@@ -788,23 +877,22 @@ function registerTools(server, connectionArgs) {
788
877
  description: "Developer/library tool. Read one file inside a Build Plan package by relative path, such as "
789
878
  + "build-plan.json, build-plan.schema.json, or a stage SKILL.md.",
790
879
  inputSchema: {
791
- build_plan_id: z.string().min(1).describe("Build Plan id."),
880
+ build_plan_id: McpBuildPlanIdSchema,
792
881
  path: z.string().min(1).describe("Relative path inside the Build Plan package."),
793
882
  },
794
883
  }, async (args) => callAndReturn(connectionArgs, `${buildPlanSubresourcePath(args.build_plan_id, "files")}/${encodeRelativePath(args.path)}`));
795
884
  }
796
885
  server.registerTool("build_plan_draft", {
797
886
  title: "Draft a Build Plan",
798
- description: "Draft the task-specific Build Plan after the user approves the proposed Context Checks "
799
- + "and requested Artifacts. This is the main Interf preparation action before building.",
887
+ description: "Draft the task-specific Build Plan from the Project intent, requested outputs, and optional coverage expectations. This is the main Interf preparation action before building.",
800
888
  inputSchema: {
801
- project_id: z.string().min(1).describe("Project id."),
802
- build_plan_id: z.string().min(1).describe("Build Plan id to create."),
889
+ project_id: McpProjectIdSchema,
890
+ build_plan_id: McpBuildPlanIdSchema.describe("Build Plan id to create."),
803
891
  label: z.string().min(1).describe("Human-readable Build Plan label."),
804
892
  hint: z.string().min(1).describe("Short Build Plan hint."),
805
- intent: z.string().min(1).describe("Agent task this Build Plan should support."),
806
- context_checks: z.array(BuildPlanContextCheckDraftSchema).optional().describe("Plain-English Context Checks the user approved before drafting."),
807
- requested_artifacts: z.array(McpRequestedArtifactSchema).optional().describe("Requested Artifacts the user approved before drafting. Use simple titles, descriptions, and plain-English checks."),
893
+ intent: z.string().min(1).optional().describe("Agent task this Build Plan should support. Omit to use the Project intent."),
894
+ context_checks: z.array(BuildPlanContextCheckDraftSchema).optional().describe("Optional legacy plain-English checks. Prefer Project intent plus requested outputs and coverage expectations."),
895
+ requested_artifacts: z.array(McpRequestedArtifactSchema).optional().describe("Requested outputs the user approved before drafting. Use simple titles, descriptions, and coverage expectations."),
808
896
  source_context: SourceContextSchema.nullable().optional(),
809
897
  ...(!appProfile
810
898
  ? {
@@ -819,7 +907,7 @@ function registerTools(server, connectionArgs) {
819
907
  build_plan_id: args.build_plan_id,
820
908
  label: args.label,
821
909
  hint: args.hint,
822
- intent: args.intent,
910
+ ...(args.intent ? { intent: args.intent } : {}),
823
911
  ...(args.context_checks ? { checks: args.context_checks } : {}),
824
912
  ...(args.requested_artifacts ? { requested_artifacts: normalizeRequestedArtifacts(args.requested_artifacts) } : {}),
825
913
  ...(args.source_context !== undefined ? { source_context: args.source_context } : {}),
@@ -829,15 +917,15 @@ function registerTools(server, connectionArgs) {
829
917
  server.registerTool("build_plan_improve", {
830
918
  title: "Improve a Build Plan",
831
919
  description: "Improve the selected Build Plan when the current Context Graph is not ready for the user's task, "
832
- + "for example when an Artifact is too coarse, a chart/table was under-extracted, or evidence is missing.",
920
+ + "for example when coverage is missing, an entrypoint is too coarse, a chart/table was under-extracted, or evidence is missing.",
833
921
  inputSchema: {
834
- project_id: z.string().min(1).describe("Project id."),
835
- build_plan_id: z.string().min(1).describe("Selected Build Plan id to improve."),
922
+ project_id: McpProjectIdSchema,
923
+ build_plan_id: McpBuildPlanIdSchema.describe("Selected Build Plan id to improve."),
836
924
  label: z.string().min(1).describe("Human-readable Build Plan label."),
837
925
  hint: z.string().min(1).describe("Short Build Plan hint."),
838
- intent: z.string().min(1).describe("Change request or improvement goal."),
839
- context_checks: z.array(BuildPlanContextCheckDraftSchema).optional().describe("Plain-English Context Checks the improved Plan must satisfy."),
840
- requested_artifacts: z.array(McpRequestedArtifactSchema).optional().describe("Requested Artifacts for the improved Plan. Use simple titles, descriptions, and plain-English checks."),
926
+ intent: z.string().min(1).optional().describe("Change request or improvement goal. Omit to use the Project intent."),
927
+ context_checks: z.array(BuildPlanContextCheckDraftSchema).optional().describe("Optional legacy plain-English checks. Prefer missing coverage and requested output changes."),
928
+ requested_artifacts: z.array(McpRequestedArtifactSchema).optional().describe("Requested outputs for the improved Plan. Use simple titles, descriptions, and coverage expectations."),
841
929
  source_context: SourceContextSchema.nullable().optional(),
842
930
  ...(!appProfile
843
931
  ? {
@@ -853,7 +941,7 @@ function registerTools(server, connectionArgs) {
853
941
  reference_build_plan_id: args.build_plan_id,
854
942
  label: args.label,
855
943
  hint: args.hint,
856
- intent: args.intent,
944
+ ...(args.intent ? { intent: args.intent } : {}),
857
945
  ...(args.context_checks ? { checks: args.context_checks } : {}),
858
946
  ...(args.requested_artifacts ? { requested_artifacts: normalizeRequestedArtifacts(args.requested_artifacts) } : {}),
859
947
  ...(args.source_context !== undefined ? { source_context: args.source_context } : {}),
@@ -866,7 +954,7 @@ function registerTools(server, connectionArgs) {
866
954
  description: "Return a compact run-status receipt for polling. This intentionally omits full trace events, "
867
955
  + "stream logs, and artifact manifests so repeated polls do not fill the agent context window.",
868
956
  inputSchema: {
869
- run_id: z.string().min(1).describe("Run id."),
957
+ run_id: McpRunIdSchema,
870
958
  },
871
959
  }, async (args) => callAndProject(connectionArgs, runSubresourcePath(args.run_id, "status"), compactRunStatus));
872
960
  server.registerTool("runs_watch", {
@@ -874,7 +962,7 @@ function registerTools(server, connectionArgs) {
874
962
  description: "Read a bounded tail of run events for debugging or progress detail. Do not use this for polling; "
875
963
  + "poll runs_status until the run reaches a terminal state.",
876
964
  inputSchema: {
877
- run_id: z.string().min(1).describe("Run id."),
965
+ run_id: McpRunIdSchema,
878
966
  limit: z.number().int().min(1).max(50).default(10).describe("Maximum recent events to return. Defaults to 10; max 50."),
879
967
  include_streams: z.boolean().default(false).describe("Include recent log stream chunks. Defaults to false because logs can be verbose."),
880
968
  stream_limit: z.number().int().min(1).max(20).default(5).describe("Maximum recent log stream chunks to return when include_streams is true. Defaults to 5; max 20."),
@@ -889,16 +977,25 @@ function registerTools(server, connectionArgs) {
889
977
  title: "Cancel a run",
890
978
  description: "Developer/admin tool. Request cancellation of an in-flight run.",
891
979
  inputSchema: {
892
- run_id: z.string().min(1).describe("Run id."),
980
+ run_id: McpRunIdSchema,
893
981
  },
894
982
  }, async (args) => callAndReturn(connectionArgs, `${LOCAL_SERVICE_ROUTES.runs}/${encodeURIComponent(args.run_id)}/cancel`, { method: "POST", body: "{}" }));
895
983
  }
984
+ server.registerTool("runs_events", {
985
+ title: "Read full run event log",
986
+ description: "Return the full durable event log for a Build run: stage start/pass/fail, files processed, "
987
+ + "artifacts written, evidence, checks, and readiness. Use runs_status for polling and runs_watch "
988
+ + "for a bounded tail; use this to inspect or replay the complete sequence.",
989
+ inputSchema: {
990
+ run_id: McpRunIdSchema,
991
+ },
992
+ }, async (args) => callAndReturn(connectionArgs, runSubresourcePath(args.run_id, "events")));
896
993
  server.registerTool("runs_fetch", {
897
994
  title: "Fetch run artifacts",
898
995
  description: "Return the artifact manifest for a finished run (Context Graph, "
899
996
  + "evidence records, logs, run-scoped audit trail).",
900
997
  inputSchema: {
901
- run_id: z.string().min(1).describe("Run id."),
998
+ run_id: McpRunIdSchema,
902
999
  },
903
1000
  }, async (args) => callAndReturn(connectionArgs, `${LOCAL_SERVICE_ROUTES.runs}/${encodeURIComponent(args.run_id)}/artifacts`));
904
1001
  // ── Instance ────────────────────────────────────────────────────────────