@martinloop/mcp 0.5.5 → 0.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/resources.js CHANGED
@@ -760,173 +760,173 @@ function inferAgentNextStep(loop, verification) {
760
760
  }
761
761
  function buildMcpUsageGuide(runsRoot) {
762
762
  const metadata = buildMartinDiscoveryMetadata(MARTIN_MCP_PACKAGE_VERSION);
763
- return `# Martin Loop MCP Usage
764
-
765
- Discovery revision: \`${metadata.discoveryRevision}\`
766
- Server version: \`${metadata.serverVersion}\`
767
- Runs root: \`${runsRoot}\`
768
-
769
- Martin Loop exposes governed coding workflows over MCP. Use the server health and run-store views to decide when to preflight, execute, inspect, or escalate.
770
-
771
- ## Recommended Flow
772
-
773
- 1. Read \`${MARTIN_STATIC_RESOURCE_URIS.serverHealth}\` or call \`martin_doctor\` to confirm the environment and run-store visibility.
774
- 2. Use the \`martin_governed_coding_kickoff\` prompt to frame a governed coding request.
775
- 3. Call \`martin_preflight\` before \`martin_run\` when the task or safety envelope is non-trivial.
776
- 4. After execution, inspect \`${MARTIN_STATIC_RESOURCE_URIS.recentRuns}\`, \`martin://runs/{loopId}\`, and \`martin://runs/{loopId}/verification\`.
777
- 5. For low-context agents, read \`${MARTIN_STATIC_RESOURCE_URIS.agentNextStep}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestSummary}\`, or \`${MARTIN_STATIC_RESOURCE_URIS.latestProofCard}\` before asking for full JSON.
778
- 6. Read \`${MARTIN_STATIC_RESOURCE_URIS.triage}\` or call \`martin_triage_runs\` to prioritize which run needs attention first.
779
- 7. Use \`martin_debug_failed_run\` when a loop exits failed, budget-bound, or escalated.
780
-
781
- ## Current Martin MCP Surface
782
-
783
- - Tools: \`martin_run\`, \`martin_inspect\`, \`martin_status\`, \`martin_doctor\`, \`martin_preflight\`, \`martin_list_runs\`, \`martin_triage_runs\`, \`martin_get_run\`, \`martin_get_attempt\`, \`martin_get_verification_results\`, \`martin_run_dossier\`
784
- - Static resources: \`${MARTIN_STATIC_RESOURCE_URIS.serverHealth}\`, \`${MARTIN_STATIC_RESOURCE_URIS.recentRuns}\`, \`${MARTIN_STATIC_RESOURCE_URIS.triage}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestSummary}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestProofCard}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestBudgetStatus}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestVerifierEvidence}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestRollbackEvidence}\`, \`${MARTIN_STATIC_RESOURCE_URIS.agentNextStep}\`, \`${MARTIN_STATIC_RESOURCE_URIS.governanceStatus}\`, \`${MARTIN_STATIC_RESOURCE_URIS.modeStatus}\`, \`${MARTIN_STATIC_RESOURCE_URIS.memorySummary}\`, \`${MARTIN_STATIC_RESOURCE_URIS.mcpUsageGuide}\`, \`${MARTIN_STATIC_RESOURCE_URIS.agentStartGuide}\`, \`${MARTIN_STATIC_RESOURCE_URIS.publishReadinessGuide}\`
785
- - Resource templates: \`martin://runs/{loopId}\`, \`martin://runs/{loopId}/attempts/{attemptIndex}\`, \`martin://runs/{loopId}/verification\`
786
- - Prompts: \`martin_start\`, \`martin_preflight\`, \`martin_triage\`, \`martin_resume\`, \`martin_prove\`, \`martin_release_check\`, \`martin_governed_coding_kickoff\`, \`martin_debug_failed_run\`, \`martin_publish_readiness_review\`, \`martin_triage_run_store\`
787
-
788
- ## Notes
789
-
790
- - Discovery helpers read the existing Martin run-store; they do not create new schema.
791
- - Verification history is derived from persisted \`verification.completed\` evidence in loop records and ledgers.
792
- - Attempt inspection stays aligned with the same loop selectors used by \`martin_status\` and \`martin_inspect\`.
763
+ return `# Martin Loop MCP Usage
764
+
765
+ Discovery revision: \`${metadata.discoveryRevision}\`
766
+ Server version: \`${metadata.serverVersion}\`
767
+ Runs root: \`${runsRoot}\`
768
+
769
+ Martin Loop exposes governed coding workflows over MCP. Use the server health and run-store views to decide when to preflight, execute, inspect, or escalate.
770
+
771
+ ## Recommended Flow
772
+
773
+ 1. Read \`${MARTIN_STATIC_RESOURCE_URIS.serverHealth}\` or call \`martin_doctor\` to confirm the environment and run-store visibility.
774
+ 2. Use the \`martin_governed_coding_kickoff\` prompt to frame a governed coding request.
775
+ 3. Call \`martin_preflight\` before \`martin_run\` when the task or safety envelope is non-trivial.
776
+ 4. After execution, inspect \`${MARTIN_STATIC_RESOURCE_URIS.recentRuns}\`, \`martin://runs/{loopId}\`, and \`martin://runs/{loopId}/verification\`.
777
+ 5. For low-context agents, read \`${MARTIN_STATIC_RESOURCE_URIS.agentNextStep}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestSummary}\`, or \`${MARTIN_STATIC_RESOURCE_URIS.latestProofCard}\` before asking for full JSON.
778
+ 6. Read \`${MARTIN_STATIC_RESOURCE_URIS.triage}\` or call \`martin_triage_runs\` to prioritize which run needs attention first.
779
+ 7. Use \`martin_debug_failed_run\` when a loop exits failed, budget-bound, or escalated.
780
+
781
+ ## Current Martin MCP Surface
782
+
783
+ - Tools: \`martin_run\`, \`martin_inspect\`, \`martin_status\`, \`martin_doctor\`, \`martin_preflight\`, \`martin_list_runs\`, \`martin_triage_runs\`, \`martin_get_run\`, \`martin_get_attempt\`, \`martin_get_verification_results\`, \`martin_run_dossier\`
784
+ - Static resources: \`${MARTIN_STATIC_RESOURCE_URIS.serverHealth}\`, \`${MARTIN_STATIC_RESOURCE_URIS.recentRuns}\`, \`${MARTIN_STATIC_RESOURCE_URIS.triage}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestSummary}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestProofCard}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestBudgetStatus}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestVerifierEvidence}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestRollbackEvidence}\`, \`${MARTIN_STATIC_RESOURCE_URIS.agentNextStep}\`, \`${MARTIN_STATIC_RESOURCE_URIS.governanceStatus}\`, \`${MARTIN_STATIC_RESOURCE_URIS.modeStatus}\`, \`${MARTIN_STATIC_RESOURCE_URIS.memorySummary}\`, \`${MARTIN_STATIC_RESOURCE_URIS.mcpUsageGuide}\`, \`${MARTIN_STATIC_RESOURCE_URIS.agentStartGuide}\`, \`${MARTIN_STATIC_RESOURCE_URIS.publishReadinessGuide}\`
785
+ - Resource templates: \`martin://runs/{loopId}\`, \`martin://runs/{loopId}/attempts/{attemptIndex}\`, \`martin://runs/{loopId}/verification\`
786
+ - Prompts: \`martin_start\`, \`martin_preflight\`, \`martin_triage\`, \`martin_resume\`, \`martin_prove\`, \`martin_release_check\`, \`martin_governed_coding_kickoff\`, \`martin_debug_failed_run\`, \`martin_publish_readiness_review\`, \`martin_triage_run_store\`
787
+
788
+ ## Notes
789
+
790
+ - Discovery helpers read the existing Martin run-store; they do not create new schema.
791
+ - Verification history is derived from persisted \`verification.completed\` evidence in loop records and ledgers.
792
+ - Attempt inspection stays aligned with the same loop selectors used by \`martin_status\` and \`martin_inspect\`.
793
793
  `;
794
794
  }
795
795
  function buildAgentStartGuide(runsRoot) {
796
796
  const metadata = buildMartinDiscoveryMetadata(MARTIN_MCP_PACKAGE_VERSION);
797
- return `# Agent Start Here
798
-
799
- Discovery revision: \`${metadata.discoveryRevision}\`
800
- Server version: \`${metadata.serverVersion}\`
801
- Runs root: \`${runsRoot}\`
802
-
803
- Use Martin Loop as the local governor before you spend agent tokens or retry a failed coding loop.
804
-
805
- ## Cheap Default Flow
806
-
807
- 1. Read \`${MARTIN_STATIC_RESOURCE_URIS.agentNextStep}\` first. It is the smallest "what should I do now?" payload.
808
- 2. If no runs exist, call \`martin_doctor\`, then \`martin_preflight\`.
809
- 3. If a run exists, read \`${MARTIN_STATIC_RESOURCE_URIS.latestSummary}\` before reading full run JSON.
810
- 4. If the verifier failed, use prompt \`martin_debug_failed_run\` or \`martin_triage\`.
811
- 5. If you need a shareable receipt, read \`${MARTIN_STATIC_RESOURCE_URIS.latestProofCard}\`.
812
-
813
- ## Install Profiles
814
-
815
- - \`minimal\` (default): doctor, preflight, list, triage, dossier. Good for low tool bloat.
816
- - \`diagnostic\`: read-only inspection tools for debugging without execution.
817
- - \`full-local\`: all local tools, including \`martin_run\`.
818
- - \`github-review\`: review-oriented local profile for PR drafting and reviewer evidence.
819
- - \`starter\` and \`full\`: compatibility aliases.
820
-
821
- ## Copy-Paste Agent Rule
822
-
823
- Before running or retrying an autonomous coding task, call Martin. Prefer compact resources first, then full dossiers only when the compact receipt says more evidence is needed. Never claim success unless Martin shows verifier-backed completion or a clear blocked reason.
797
+ return `# Agent Start Here
798
+
799
+ Discovery revision: \`${metadata.discoveryRevision}\`
800
+ Server version: \`${metadata.serverVersion}\`
801
+ Runs root: \`${runsRoot}\`
802
+
803
+ Use Martin Loop as the local governor before you spend agent tokens or retry a failed coding loop.
804
+
805
+ ## Cheap Default Flow
806
+
807
+ 1. Read \`${MARTIN_STATIC_RESOURCE_URIS.agentNextStep}\` first. It is the smallest "what should I do now?" payload.
808
+ 2. If no runs exist, call \`martin_doctor\`, then \`martin_preflight\`.
809
+ 3. If a run exists, read \`${MARTIN_STATIC_RESOURCE_URIS.latestSummary}\` before reading full run JSON.
810
+ 4. If the verifier failed, use prompt \`martin_debug_failed_run\` or \`martin_triage\`.
811
+ 5. If you need a shareable receipt, read \`${MARTIN_STATIC_RESOURCE_URIS.latestProofCard}\`.
812
+
813
+ ## Install Profiles
814
+
815
+ - \`minimal\` (default): doctor, preflight, list, triage, dossier. Good for low tool bloat.
816
+ - \`diagnostic\`: read-only inspection tools for debugging without execution.
817
+ - \`full-local\`: all local tools, including \`martin_run\`.
818
+ - \`github-review\`: review-oriented local profile for PR drafting and reviewer evidence.
819
+ - \`starter\` and \`full\`: compatibility aliases.
820
+
821
+ ## Copy-Paste Agent Rule
822
+
823
+ Before running or retrying an autonomous coding task, call Martin. Prefer compact resources first, then full dossiers only when the compact receipt says more evidence is needed. Never claim success unless Martin shows verifier-backed completion or a clear blocked reason.
824
824
  `;
825
825
  }
826
826
  function buildCommandMapGuide(runsRoot) {
827
827
  const metadata = buildMartinDiscoveryMetadata(MARTIN_MCP_PACKAGE_VERSION);
828
- return `# Martin Command Map
829
-
830
- Discovery revision: \`${metadata.discoveryRevision}\`
831
- Server version: \`${metadata.serverVersion}\`
832
- Runs root: \`${runsRoot}\`
833
-
834
- Use this guide when an IDE or agent needs to know which Martin surface to call next.
835
-
836
- ## Default Governed Sequence
837
-
838
- 1. \`martin_doctor\` — confirm environment and visibility.
839
- 2. \`martin_plan\` — propose the bounded approach without spending a run.
840
- 3. \`martin_preflight\` — turn the plan into an explicit contract.
841
- 4. \`martin_run\` — execute only after the contract is safe.
842
- 5. \`martin_dossier\` — inspect what happened and what Martin prevented.
843
- 6. \`martin_eval\` — convert the result into review posture when needed.
844
-
845
- ## When To Use Which Surface
846
-
847
- - Need the smallest next action: \`${MARTIN_STATIC_RESOURCE_URIS.agentNextStep}\`
848
- - Need a quick receipt: \`${MARTIN_STATIC_RESOURCE_URIS.latestSummary}\`
849
- - Need a shareable proof object: \`${MARTIN_STATIC_RESOURCE_URIS.latestProofCard}\`
850
- - Need a full run review: \`martin_dossier\`
851
- - Need to decide whether to retry: \`martin_triage_runs\`
852
- - Need IDE setup guidance: \`${MARTIN_STATIC_RESOURCE_URIS.ideOnboardingGuide}\`
828
+ return `# Martin Command Map
829
+
830
+ Discovery revision: \`${metadata.discoveryRevision}\`
831
+ Server version: \`${metadata.serverVersion}\`
832
+ Runs root: \`${runsRoot}\`
833
+
834
+ Use this guide when an IDE or agent needs to know which Martin surface to call next.
835
+
836
+ ## Default Governed Sequence
837
+
838
+ 1. \`martin_doctor\` — confirm environment and visibility.
839
+ 2. \`martin_plan\` — propose the bounded approach without spending a run.
840
+ 3. \`martin_preflight\` — turn the plan into an explicit contract.
841
+ 4. \`martin_run\` — execute only after the contract is safe.
842
+ 5. \`martin_dossier\` — inspect what happened and what Martin prevented.
843
+ 6. \`martin_eval\` — convert the result into review posture when needed.
844
+
845
+ ## When To Use Which Surface
846
+
847
+ - Need the smallest next action: \`${MARTIN_STATIC_RESOURCE_URIS.agentNextStep}\`
848
+ - Need a quick receipt: \`${MARTIN_STATIC_RESOURCE_URIS.latestSummary}\`
849
+ - Need a shareable proof object: \`${MARTIN_STATIC_RESOURCE_URIS.latestProofCard}\`
850
+ - Need a full run review: \`martin_dossier\`
851
+ - Need to decide whether to retry: \`martin_triage_runs\`
852
+ - Need IDE setup guidance: \`${MARTIN_STATIC_RESOURCE_URIS.ideOnboardingGuide}\`
853
853
  `;
854
854
  }
855
855
  function buildIdeOnboardingGuide(runsRoot) {
856
856
  const metadata = buildMartinDiscoveryMetadata(MARTIN_MCP_PACKAGE_VERSION);
857
- return `# Martin IDE Onboarding
858
-
859
- Discovery revision: \`${metadata.discoveryRevision}\`
860
- Server version: \`${metadata.serverVersion}\`
861
- Runs root: \`${runsRoot}\`
862
-
863
- Use this guide after the MCP server is installed so the host naturally uses MartinLoop during real work.
864
-
865
- ## IDE Default Flow
866
-
867
- 1. Read \`${MARTIN_STATIC_RESOURCE_URIS.agentStartGuide}\`
868
- 2. Read \`${MARTIN_STATIC_RESOURCE_URIS.operatingRulesGuide}\`
869
- 3. Use prompt \`martin_start\` or \`martin_governed_coding_kickoff\`
870
- 4. Call \`martin_doctor\`
871
- 5. Call \`martin_plan\`
872
- 6. Call \`martin_preflight\`
873
- 7. Only then call \`martin_run\`
874
-
875
- ## Goal
876
-
877
- MartinLoop should become the normal path for coding work in the host, not a manual extra step the human has to remember.
857
+ return `# Martin IDE Onboarding
858
+
859
+ Discovery revision: \`${metadata.discoveryRevision}\`
860
+ Server version: \`${metadata.serverVersion}\`
861
+ Runs root: \`${runsRoot}\`
862
+
863
+ Use this guide after the MCP server is installed so the host naturally uses MartinLoop during real work.
864
+
865
+ ## IDE Default Flow
866
+
867
+ 1. Read \`${MARTIN_STATIC_RESOURCE_URIS.agentStartGuide}\`
868
+ 2. Read \`${MARTIN_STATIC_RESOURCE_URIS.operatingRulesGuide}\`
869
+ 3. Use prompt \`martin_start\` or \`martin_governed_coding_kickoff\`
870
+ 4. Call \`martin_doctor\`
871
+ 5. Call \`martin_plan\`
872
+ 6. Call \`martin_preflight\`
873
+ 7. Only then call \`martin_run\`
874
+
875
+ ## Goal
876
+
877
+ MartinLoop should become the normal path for coding work in the host, not a manual extra step the human has to remember.
878
878
  `;
879
879
  }
880
880
  function buildOperatingRulesGuide(runsRoot) {
881
881
  const metadata = buildMartinDiscoveryMetadata(MARTIN_MCP_PACKAGE_VERSION);
882
- return `# Martin Operating Rules
883
-
884
- Discovery revision: \`${metadata.discoveryRevision}\`
885
- Server version: \`${metadata.serverVersion}\`
886
- Runs root: \`${runsRoot}\`
887
-
888
- Use these rules inside the IDE or MCP host as the default MartinLoop operating posture.
889
-
890
- ## Required Sequence Before Real Work
891
-
892
- 1. \`martin_doctor\`
893
- 2. \`martin_plan\`
894
- 3. \`martin_preflight\`
895
- 4. \`martin_run\`
896
- 5. \`martin_dossier\`
897
-
898
- ## Enforcement Rule
899
-
900
- Do not execute real coding work through MartinLoop until doctor and preflight have both been used for the current task.
901
-
902
- ## Completion Rule
903
-
904
- Do not claim success until MartinLoop shows verifier-backed completion or an explicit blocked reason backed by evidence.
882
+ return `# Martin Operating Rules
883
+
884
+ Discovery revision: \`${metadata.discoveryRevision}\`
885
+ Server version: \`${metadata.serverVersion}\`
886
+ Runs root: \`${runsRoot}\`
887
+
888
+ Use these rules inside the IDE or MCP host as the default MartinLoop operating posture.
889
+
890
+ ## Required Sequence Before Real Work
891
+
892
+ 1. \`martin_doctor\`
893
+ 2. \`martin_plan\`
894
+ 3. \`martin_preflight\`
895
+ 4. \`martin_run\`
896
+ 5. \`martin_dossier\`
897
+
898
+ ## Enforcement Rule
899
+
900
+ Do not execute real coding work through MartinLoop until doctor and preflight have both been used for the current task.
901
+
902
+ ## Completion Rule
903
+
904
+ Do not claim success until MartinLoop shows verifier-backed completion or an explicit blocked reason backed by evidence.
905
905
  `;
906
906
  }
907
907
  function buildPublishReadinessGuide(runsRoot) {
908
908
  const metadata = buildMartinDiscoveryMetadata(MARTIN_MCP_PACKAGE_VERSION);
909
- return `# Martin MCP Publish Readiness
910
-
911
- Discovery revision: \`${metadata.discoveryRevision}\`
912
- Server version: \`${metadata.serverVersion}\`
913
- Runs root: \`${runsRoot}\`
914
-
915
- Use this guide when reviewing whether the public MCP package is ready to publish, promote, or hand off for registry submission.
916
-
917
- ## Review Areas
918
-
919
- 1. Environment health: confirm \`${MARTIN_STATIC_RESOURCE_URIS.serverHealth}\` shows a sane working directory, runs root, and engine availability for the target mode.
920
- 2. Discovery surface: verify tools, prompts, static resources, and resource templates are all discoverable and named consistently.
921
- 3. Run evidence: inspect \`${MARTIN_STATIC_RESOURCE_URIS.recentRuns}\` and, when relevant, \`martin://runs/{loopId}/verification\` to confirm verification outcomes are explainable from persisted data.
922
- 4. Packaging lane: run the MCP package test, build, and smoke-pack commands before calling the package publish-ready.
923
- 5. Findings-first reporting: call out missing schema, integration gaps, triage-critical runs, and verification blockers before summarizing strengths.
924
-
925
- ## Evidence Expectations
926
-
927
- - Prefer concrete run IDs, attempt indices, and verification summaries over vague statements.
928
- - Distinguish local package validation from live registry readiness.
929
- - If a discovery helper exists but is not yet wired into the server, report that as an integration gap instead of treating the capability as fully shipped.
909
+ return `# Martin MCP Publish Readiness
910
+
911
+ Discovery revision: \`${metadata.discoveryRevision}\`
912
+ Server version: \`${metadata.serverVersion}\`
913
+ Runs root: \`${runsRoot}\`
914
+
915
+ Use this guide when reviewing whether the public MCP package is ready to publish, promote, or hand off for registry submission.
916
+
917
+ ## Review Areas
918
+
919
+ 1. Environment health: confirm \`${MARTIN_STATIC_RESOURCE_URIS.serverHealth}\` shows a sane working directory, runs root, and engine availability for the target mode.
920
+ 2. Discovery surface: verify tools, prompts, static resources, and resource templates are all discoverable and named consistently.
921
+ 3. Run evidence: inspect \`${MARTIN_STATIC_RESOURCE_URIS.recentRuns}\` and, when relevant, \`martin://runs/{loopId}/verification\` to confirm verification outcomes are explainable from persisted data.
922
+ 4. Packaging lane: run the MCP package test, build, and smoke-pack commands before calling the package publish-ready.
923
+ 5. Findings-first reporting: call out missing schema, integration gaps, triage-critical runs, and verification blockers before summarizing strengths.
924
+
925
+ ## Evidence Expectations
926
+
927
+ - Prefer concrete run IDs, attempt indices, and verification summaries over vague statements.
928
+ - Distinguish local package validation from live registry readiness.
929
+ - If a discovery helper exists but is not yet wired into the server, report that as an integration gap instead of treating the capability as fully shipped.
930
930
  `;
931
931
  }
932
932
  function withDiscoveryMetadata(value, runsRoot) {
package/dist/server.js CHANGED
@@ -26,6 +26,9 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
26
26
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
27
27
  import { CallToolRequestSchema, GetPromptRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListResourceTemplatesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema } from "@modelcontextprotocol/sdk/types.js";
28
28
  import { MARTIN_MCP_PACKAGE_VERSION } from "./package-version.js";
29
+ import { MARTIN_ARCADE_FALLBACK_TEXT, MARTIN_ARCADE_MIME_TYPE, MARTIN_ARCADE_RESOURCE_URI, MARTIN_ARCADE_UI_EXTENSION_ID, buildArcadeToolDefinitions, supportsMartinArcadeApp } from "./arcade/capabilities.js";
30
+ import { listArcadeResources, readArcadeResource } from "./arcade/resource.js";
31
+ import { readArcadeStatus } from "./arcade/status.js";
29
32
  import { getMartinPrompt, listMartinPrompts } from "./prompts.js";
30
33
  import { listMartinResources, listMartinResourceTemplates, readMartinResource } from "./resources.js";
31
34
  import { martinDoctorTool } from "./tools/doctor.js";
@@ -56,15 +59,6 @@ const stringArraySchema = {
56
59
  type: "array",
57
60
  items: { type: "string" }
58
61
  };
59
- function describeCostProvenance(provenance) {
60
- if (provenance === "actual")
61
- return "provider-settled actual";
62
- if (provenance === "calculated")
63
- return "calculated from observed usage";
64
- if (provenance === "estimated")
65
- return "estimated";
66
- return "unavailable";
67
- }
68
62
  const loopPreviewSchema = {
69
63
  type: "object",
70
64
  additionalProperties: true,
@@ -78,10 +72,6 @@ const loopPreviewSchema = {
78
72
  updatedAt: { type: "string" },
79
73
  attempts: { type: "integer" },
80
74
  costUsd: { type: "number" },
81
- costProvenance: {
82
- type: "string",
83
- enum: ["actual", "calculated", "estimated", "unavailable"]
84
- },
85
75
  avoidedUsd: { type: "number" },
86
76
  pressure: { type: "string" },
87
77
  shouldStop: { type: "boolean" },
@@ -101,7 +91,6 @@ const loopPreviewSchema = {
101
91
  "lifecycleState",
102
92
  "attempts",
103
93
  "costUsd",
104
- "costProvenance",
105
94
  "avoidedUsd",
106
95
  "pressure",
107
96
  "shouldStop",
@@ -267,10 +256,6 @@ const runOutputSchema = {
267
256
  reason: { type: "string" },
268
257
  attempts: { type: "integer" },
269
258
  costUsd: { type: "number" },
270
- costProvenance: {
271
- type: "string",
272
- enum: ["actual", "calculated", "estimated", "unavailable"]
273
- },
274
259
  verificationPassed: { type: "boolean" },
275
260
  loopId: { type: "string" },
276
261
  pressure: { type: "string" },
@@ -302,7 +287,6 @@ const runOutputSchema = {
302
287
  "reason",
303
288
  "attempts",
304
289
  "costUsd",
305
- "costProvenance",
306
290
  "verificationPassed",
307
291
  "loopId",
308
292
  "pressure",
@@ -370,10 +354,6 @@ const statusOutputSchema = {
370
354
  lifecycleState: { type: "string" },
371
355
  attempts: { type: "integer" },
372
356
  costUsd: { type: "number" },
373
- costProvenance: {
374
- type: "string",
375
- enum: ["actual", "calculated", "estimated", "unavailable"]
376
- },
377
357
  avoidedUsd: { type: "number" },
378
358
  pressure: { type: "string" },
379
359
  shouldStop: { type: "boolean" },
@@ -397,7 +377,6 @@ const statusOutputSchema = {
397
377
  "lifecycleState",
398
378
  "attempts",
399
379
  "costUsd",
400
- "costProvenance",
401
380
  "avoidedUsd",
402
381
  "pressure",
403
382
  "shouldStop",
@@ -747,7 +726,16 @@ export function createMartinMcpServer(serverInfo) {
747
726
  const server = new Server({
748
727
  name: serverInfo?.name ?? "martin-loop",
749
728
  version: serverInfo?.version ?? MARTIN_MCP_PACKAGE_VERSION
750
- }, { capabilities: { tools: {}, resources: {}, prompts: {} } });
729
+ }, {
730
+ capabilities: {
731
+ tools: {},
732
+ resources: {},
733
+ prompts: {},
734
+ extensions: {
735
+ [MARTIN_ARCADE_UI_EXTENSION_ID]: { mimeTypes: [MARTIN_ARCADE_MIME_TYPE] }
736
+ }
737
+ }
738
+ });
751
739
  server.setRequestHandler(ListToolsRequestSchema, () => ({
752
740
  tools: [
753
741
  {
@@ -1469,17 +1457,23 @@ export function createMartinMcpServer(serverInfo) {
1469
1457
  },
1470
1458
  required: ["objective", "engine", "budgetUsd", "selectedMode", "confidence", "expectedCostUsd", "expectedPreworkBurnPct", "reason"]
1471
1459
  }
1472
- }
1460
+ },
1461
+ ...buildArcadeToolDefinitions(server.getClientCapabilities())
1473
1462
  ]
1474
1463
  }));
1475
- server.setRequestHandler(ListResourcesRequestSchema, () => ({
1476
- ...listMartinResources()
1477
- }));
1464
+ server.setRequestHandler(ListResourcesRequestSchema, () => {
1465
+ const listed = listMartinResources();
1466
+ const arcade = listArcadeResources(server.getClientCapabilities());
1467
+ return { resources: [...listed.resources, ...arcade.resources] };
1468
+ });
1478
1469
  server.setRequestHandler(ListResourceTemplatesRequestSchema, () => ({
1479
1470
  ...listMartinResourceTemplates()
1480
1471
  }));
1481
1472
  server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
1482
1473
  try {
1474
+ if (request.params.uri === MARTIN_ARCADE_RESOURCE_URI) {
1475
+ return await readArcadeResource(request.params.uri);
1476
+ }
1483
1477
  return await readMartinResource({ uri: request.params.uri });
1484
1478
  }
1485
1479
  catch (error) {
@@ -1509,6 +1503,29 @@ export function createMartinMcpServer(serverInfo) {
1509
1503
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
1510
1504
  const { name, arguments: args } = request.params;
1511
1505
  try {
1506
+ if (name === "martin_arcade") {
1507
+ const available = supportsMartinArcadeApp(server.getClientCapabilities());
1508
+ return createToolSuccessResult({
1509
+ available,
1510
+ resourceUri: available ? MARTIN_ARCADE_RESOURCE_URI : null
1511
+ }, MARTIN_ARCADE_FALLBACK_TEXT, { human: MARTIN_ARCADE_FALLBACK_TEXT });
1512
+ }
1513
+ if (name === "martin_arcade_status") {
1514
+ const input = args ?? {};
1515
+ if (!input || typeof input !== "object" || Array.isArray(input)) {
1516
+ throw new MartinToolError("invalid_arguments", "Arcade status input must be an object.", {
1517
+ category: "invalid_input"
1518
+ });
1519
+ }
1520
+ const keys = Object.keys(input);
1521
+ if (keys.some((key) => key !== "loopId") || ("loopId" in input && typeof input.loopId !== "string")) {
1522
+ throw new MartinToolError("invalid_arguments", "Arcade status accepts only an optional loopId.", {
1523
+ category: "invalid_input"
1524
+ });
1525
+ }
1526
+ const output = await readArcadeStatus(input);
1527
+ return createToolSuccessResult(output, `MartinLoop Arcade status for ${output.loopId}: ${output.displayOutcome ?? output.lifecycleState}.`);
1528
+ }
1512
1529
  if (name === "martin_run") {
1513
1530
  const input = validateToolInput("martin_run", args);
1514
1531
  const runsRoot = resolveRunsRoot(process.env);
@@ -1544,7 +1561,7 @@ export function createMartinMcpServer(serverInfo) {
1544
1561
  const output = await runLoopTool(input);
1545
1562
  return createToolSuccessResult(output, [
1546
1563
  `Run ${output.loopId} is ${output.status}/${output.lifecycleState}`,
1547
- `after ${output.attempts} attempt(s); recorded cost ${output.costUsd.toFixed(2)} USD (${describeCostProvenance(output.costProvenance)}).`,
1564
+ `after ${output.attempts} attempt(s); spend ${output.costUsd.toFixed(2)} USD.`,
1548
1565
  `Execution mode: ${output.executionMode}; governance claim eligible:`,
1549
1566
  `${output.governanceClaimEligible ? "yes" : "no"}.`
1550
1567
  ].join(" "));
@@ -1552,12 +1569,12 @@ export function createMartinMcpServer(serverInfo) {
1552
1569
  if (name === "martin_inspect") {
1553
1570
  const input = validateToolInput("martin_inspect", args);
1554
1571
  const output = await inspectLoopTool(input);
1555
- return createToolSuccessResult(output, `Inspected ${output.loopCount} run(s) from ${output.source}; total recorded cost ${output.portfolio.totalActualUsd.toFixed(2)} USD.`);
1572
+ return createToolSuccessResult(output, `Inspected ${output.loopCount} run(s) from ${output.source}; total actual spend ${output.portfolio.totalActualUsd.toFixed(2)} USD.`);
1556
1573
  }
1557
1574
  if (name === "martin_status") {
1558
1575
  const input = validateToolInput("martin_status", args);
1559
1576
  const output = await getStatusTool(input);
1560
- return createToolSuccessResult(output, `Loop ${output.loopId} is ${output.status}/${output.lifecycleState}; recorded cost is ${output.costUsd.toFixed(2)} USD (${describeCostProvenance(output.costProvenance)}), and pressure is ${output.pressure} with ${output.remainingBudgetUsd.toFixed(2)} USD remaining.`);
1577
+ return createToolSuccessResult(output, `Loop ${output.loopId} is ${output.status}/${output.lifecycleState}; pressure is ${output.pressure} with ${output.remainingBudgetUsd.toFixed(2)} USD remaining.`);
1561
1578
  }
1562
1579
  if (name === "martin_doctor") {
1563
1580
  const input = validateToolInput("martin_doctor", args);
@@ -1,6 +1,6 @@
1
1
  import { type SpawnLike } from "../vendor/adapters/index.js";
2
2
  import { type RunStore } from "../vendor/core/index.js";
3
- import type { CostProvenance, ExecutionMode, LoopBudget, ReceiptScope } from "../vendor/contracts/index.js";
3
+ import type { ExecutionMode, LoopBudget, ReceiptScope } from "../vendor/contracts/index.js";
4
4
  import { buildArtifactSummary, buildVerificationSummary, buildLoopPreview, type MartinEngine } from "./tool-support.js";
5
5
  export interface RunLoopInput {
6
6
  objective: string;
@@ -24,7 +24,6 @@ export interface RunLoopOutput {
24
24
  reason: string;
25
25
  attempts: number;
26
26
  costUsd: number;
27
- costProvenance: CostProvenance;
28
27
  verificationPassed: boolean;
29
28
  executionMode: ExecutionMode;
30
29
  governanceClaimEligible: boolean;
@@ -1,4 +1,4 @@
1
- import { createClaudeCliAdapter, createCodexCliAdapter, createGeminiCliAdapter, createVerifierOnlyAdapter, probeCodexLaunch, resolveCliCommandAvailability } from "../vendor/adapters/index.js";
1
+ import { createClaudeCliAdapter, createCodexCliAdapter, createGeminiCliAdapter, probeCodexLaunch, resolveCliCommandAvailability, createVerifierOnlyAdapter } from "../vendor/adapters/index.js";
2
2
  import { createFileRunStore, evaluateCostGovernor, resolveRunsRoot, runMartin } from "../vendor/core/index.js";
3
3
  import { normalizeSafePathPatterns, resolveSafeRepoRoot } from "../server-validation.js";
4
4
  import { MartinToolError } from "./tool-errors.js";
@@ -166,7 +166,6 @@ export async function runLoopTool(input) {
166
166
  reason: result.decision.reason,
167
167
  attempts: result.loop.attempts.length,
168
168
  costUsd: result.loop.cost.actualUsd,
169
- costProvenance: result.loop.cost.provenance ?? "unavailable",
170
169
  verificationPassed,
171
170
  executionMode: evidenceExecutionMode,
172
171
  governanceClaimEligible: evidenceExecutionMode === "governed",
@@ -749,6 +749,7 @@ export function createAgentCliAdapter(options) {
749
749
  workspaceId: request.workspaceId,
750
750
  cwd: workingDirectory,
751
751
  });
752
+ const verificationConfigured = verification.binding.commands.length > 0;
752
753
  // Check for zero-diff (agent ran but made no file changes)
753
754
  const postRunChangedFiles = gitRepoRoot
754
755
  ? await readGitChangedFiles(gitRepoRoot, 5_000, options.spawnImpl)
@@ -791,7 +792,7 @@ export function createAgentCliAdapter(options) {
791
792
  }
792
793
  // Derive structural classHint from evidence, not keyword scanning
793
794
  const structuralHint = inferStructuralClassHint(agentText, verification.summary, agentResult.exitCode, request.context.objective);
794
- if (verification.passed) {
795
+ if (verification.passed || !verificationConfigured) {
795
796
  return {
796
797
  status: "completed",
797
798
  summary,
@@ -154,7 +154,13 @@ export async function runVerification(commands, cwd, timeoutMs, verificationStac
154
154
  commands: steps.map((step) => step.command),
155
155
  };
156
156
  if (steps.length === 0) {
157
- return { passed: true, summary: "No verification commands specified.", steps: [], binding: executionBinding };
157
+ return {
158
+ passed: false,
159
+ summary: "No verification commands specified; execution is not VERIFIED.",
160
+ steps: [],
161
+ warnings: ["Execution completed without verifier evidence."],
162
+ binding: executionBinding,
163
+ };
158
164
  }
159
165
  const failedSteps = [];
160
166
  const stepOutcomes = [];
@@ -4,5 +4,6 @@ export { createCodexCliAdapter, type CodexCliAdapterOptions } from "./codex-cli.
4
4
  export { createOpenAiCompatibleAdapter, resolveOpenAiCompatibleRuntimeConfig, type OpenAiCompatibleAdapterOptions } from "./openai-compatible.js";
5
5
  export { createVerifierOnlyAdapter, type VerifierOnlyAdapterOptions } from "./verifier-only.js";
6
6
  /** @internal Test-only compatibility export. Public package builders strip this surface. */
7
+ export { createStubAgentCliAdapter, type StubAgentCliAdapterOptions, createStubDirectProviderAdapter, type StubDirectProviderAdapterOptions } from "./stub-agent-cli.js";
7
8
  export { buildCodexExecArgs, buildCodexStdin, clearCodexCapabilityCacheForTests, detectCodexHostPlatform, diagnoseCodexHost, probeCodexCapabilities, probeCodexLaunch, resolveCliCommandAvailability, type CliCommandAvailability, type CodexApprovalCapability, type CodexAutonomyResolution, type CodexCapabilityFlag, type CodexCapabilityProfile, type CodexFlagScope, type CodexHostDiagnosis, type CodexHostPlatform, type CodexLaunchProbeResult, type CodexPromptTransport, type CodexSandboxCapability, checkCodexSandboxPreflight, probeFilesystemWriteCapability, type CodexSandboxPreflightOk, type CodexSandboxPreflightOutcome, type CodexSandboxPreflightReadOnly } from "./codex-launcher.js";
8
9
  export { createSpawnPlan, type SpawnLike, type SpawnPlan, type SubprocessResult, type VerificationOutcome } from "./cli-bridge.js";
@@ -4,5 +4,6 @@ export { createCodexCliAdapter } from "./codex-cli.js";
4
4
  export { createOpenAiCompatibleAdapter, resolveOpenAiCompatibleRuntimeConfig } from "./openai-compatible.js";
5
5
  export { createVerifierOnlyAdapter } from "./verifier-only.js";
6
6
  /** @internal Test-only compatibility export. Public package builders strip this surface. */
7
+ export { createStubAgentCliAdapter, createStubDirectProviderAdapter } from "./stub-agent-cli.js";
7
8
  export { buildCodexExecArgs, buildCodexStdin, clearCodexCapabilityCacheForTests, detectCodexHostPlatform, diagnoseCodexHost, probeCodexCapabilities, probeCodexLaunch, resolveCliCommandAvailability, checkCodexSandboxPreflight, probeFilesystemWriteCapability } from "./codex-launcher.js";
8
9
  export { createSpawnPlan } from "./cli-bridge.js";
@@ -103,12 +103,12 @@ function normalizeOpenAiCompatibleUsage(input) {
103
103
  // ---------------------------------------------------------------------------
104
104
  // Prompt builder
105
105
  // ---------------------------------------------------------------------------
106
- const DEFAULT_SYSTEM_PROMPT = `You are an expert software engineer executing a governed coding task.
107
- Follow these rules exactly:
108
- - Read the task description carefully and implement only what is asked.
109
- - Do not add features, refactors, or improvements beyond the stated task.
110
- - If the task asks you to write or modify code, output the complete file content with changes applied.
111
- - Be precise, minimal, and test-backed in all changes.
106
+ const DEFAULT_SYSTEM_PROMPT = `You are an expert software engineer executing a governed coding task.
107
+ Follow these rules exactly:
108
+ - Read the task description carefully and implement only what is asked.
109
+ - Do not add features, refactors, or improvements beyond the stated task.
110
+ - If the task asks you to write or modify code, output the complete file content with changes applied.
111
+ - Be precise, minimal, and test-backed in all changes.
112
112
  - State what you changed and why at the end of your response.`;
113
113
  export const DEFAULT_OPENAI_BASE_URL = "https://api.openai.com";
114
114
  export function resolveOpenAiCompatibleRuntimeConfig(env = process.env) {
@@ -347,11 +347,14 @@ export function createOpenAiCompatibleAdapter(options) {
347
347
  ? (await readGitChangedFiles(workingDirectory, 5_000)).filter((file) => !baselineChangedFiles.has(file))
348
348
  : []
349
349
  };
350
+ const verificationConfigured = verification.binding.commands.length > 0;
350
351
  return {
351
- status: verification.passed ? "completed" : "failed",
352
+ status: verification.passed || !verificationConfigured ? "completed" : "failed",
352
353
  summary: verification.passed
353
354
  ? `${model} completed the task. Verifier passed.`
354
- : `${model} completed but verifier failed: ${verification.summary}`,
355
+ : !verificationConfigured
356
+ ? `${model} completed the task without verifier evidence; outcome is not VERIFIED.`
357
+ : `${model} completed but verifier failed: ${verification.summary}`,
355
358
  usage: normalizeOpenAiCompatibleUsage({
356
359
  model,
357
360
  tokensIn,
@@ -362,7 +365,7 @@ export function createOpenAiCompatibleAdapter(options) {
362
365
  }),
363
366
  verification,
364
367
  execution,
365
- ...(verification.passed ? {} : {
368
+ ...(verification.passed || !verificationConfigured ? {} : {
366
369
  failure: { message: verification.summary }
367
370
  })
368
371
  };
@@ -0,0 +1,9 @@
1
+ import type { MartinAdapter, MartinAdapterRequest, MartinAdapterResult } from "../core/index.js";
2
+ export interface StubAgentCliAdapterOptions {
3
+ command: string[];
4
+ profile?: string;
5
+ label?: string;
6
+ responder?: (request: MartinAdapterRequest) => Promise<MartinAdapterResult> | MartinAdapterResult;
7
+ }
8
+ export declare function createStubAgentCliAdapter(options: StubAgentCliAdapterOptions): MartinAdapter;
9
+ export { createStubDirectProviderAdapter, type StubDirectProviderAdapterOptions } from "./stub-direct-provider.js";