@pathmode/mcp-server 1.7.0 → 1.8.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.
package/README.md CHANGED
@@ -120,7 +120,7 @@ Restart Claude Code. The skills register at session start and auto-invoke when y
120
120
  | Tool | Description |
121
121
  |------|-------------|
122
122
  | `intent_save` | Save an intent spec to `intent.md` in the project root |
123
- | `intent_export` | Export as `.cursorrules` or `CLAUDE.md` section |
123
+ | `intent_export` | Export as `.cursorrules`, a `CLAUDE.md` or `AGENTS.md` section, or an Outcomes rubric |
124
124
 
125
125
  ### Intent Compiler Prompt
126
126
 
@@ -208,7 +208,7 @@ Read `intent.md` files from your project directory without an API key:
208
208
 
209
209
  | Tool | Description |
210
210
  |------|-------------|
211
- | `export_context` | Generate CLAUDE.md, .cursorrules, or intent.md files. For claude-md, optionally pass a product ID; for cursorrules/intent-md, product is derived from the resolved intent |
211
+ | `export_context` | Generate CLAUDE.md, AGENTS.md (Codex/modern Cursor), .cursorrules, or intent.md files. For claude-md/agents-md, optionally pass a product ID; for cursorrules/intent-md, product is derived from the resolved intent |
212
212
  | `get_agent_prompt` | Get a structured execution prompt for an intent |
213
213
  | `get_workspace` | Get workspace details including strategy, active products, and constitution |
214
214
  | `get_constitution` | Get mandatory constraint rules for the workspace |
@@ -12,6 +12,14 @@ export interface ApiStructuredOutcome {
12
12
  text: string;
13
13
  priority?: 'must' | 'should' | 'could';
14
14
  }
15
+ export interface IntentDecision {
16
+ id: string;
17
+ choice: string;
18
+ ruledOut?: string;
19
+ reason: string;
20
+ evidenceIds?: string[];
21
+ resolvedAt: number;
22
+ }
15
23
  export interface ApiIntent {
16
24
  id: string;
17
25
  workspaceId: string;
@@ -35,6 +43,7 @@ export interface ApiIntent {
35
43
  verification: Record<string, any>;
36
44
  externalLinks: any[];
37
45
  evidenceAnchors: Record<string, string[]>;
46
+ decisions?: IntentDecision[];
38
47
  implementationContext?: {
39
48
  relevantAreas: {
40
49
  path: string;
@@ -83,6 +92,13 @@ export interface CreateIntentInput {
83
92
  expectedBehavior: string;
84
93
  }[];
85
94
  verification?: {
95
+ checks?: {
96
+ id?: string;
97
+ kind?: string;
98
+ description: string;
99
+ status?: string;
100
+ verifies?: string;
101
+ }[];
86
102
  manualChecks?: string[];
87
103
  unitTests?: string[];
88
104
  e2eTests?: string[];
@@ -107,6 +123,13 @@ export interface UpdateIntentInput {
107
123
  expectedBehavior: string;
108
124
  }[];
109
125
  verification?: {
126
+ checks?: {
127
+ id?: string;
128
+ kind?: string;
129
+ description: string;
130
+ status?: string;
131
+ verifies?: string;
132
+ }[];
110
133
  manualChecks?: string[];
111
134
  unitTests?: string[];
112
135
  e2eTests?: string[];
@@ -141,6 +164,13 @@ export interface LinkEvidenceInput {
141
164
  link?: string[];
142
165
  unlink?: string[];
143
166
  }
167
+ export interface RecordFindingInput {
168
+ assumption: string;
169
+ finding: string;
170
+ target?: string;
171
+ correction?: string;
172
+ source?: string;
173
+ }
144
174
  export interface ApiVerificationResult {
145
175
  pass: boolean;
146
176
  score: number;
@@ -236,10 +266,11 @@ export declare class PathmodeClient {
236
266
  verificationChecklistCount?: number;
237
267
  }>;
238
268
  logNote(intentId: string, note: string, source?: string): Promise<any>;
269
+ recordFinding(intentId: string, input: RecordFindingInput): Promise<any>;
239
270
  getWorkspace(): Promise<ApiWorkspace>;
240
271
  getConstitution(): Promise<any>;
241
272
  exportClaudeMd(): Promise<string>;
242
- exportContext(format: 'claude-md' | 'cursorrules' | 'intent-md', intentId?: string, productId?: string): Promise<string>;
273
+ exportContext(format: 'claude-md' | 'agents-md' | 'cursorrules' | 'intent-md', intentId?: string, productId?: string): Promise<string>;
243
274
  createIntent(input: CreateIntentInput): Promise<ApiIntent>;
244
275
  updateIntent(id: string, updates: UpdateIntentInput): Promise<ApiIntent>;
245
276
  queryEvidence(filters?: EvidenceQuery): Promise<{
@@ -1 +1 @@
1
- {"version":3,"file":"","sourceRoot":"","sources":["file:///Users/jannelammi/code/Pathmode/packages/mcp-server/src/api-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"","sourceRoot":"","sources":["file:///Users/jannelammi/code/Pathmode/packages/mcp-server/src/api-client.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -33626,6 +33626,13 @@ class PathmodeClient {
33626
33626
  });
33627
33627
  return res.json();
33628
33628
  }
33629
+ async recordFinding(intentId, input) {
33630
+ const res = await this.fetch(`/intents/${intentId}/findings`, {
33631
+ method: 'POST',
33632
+ body: JSON.stringify(input),
33633
+ });
33634
+ return res.json();
33635
+ }
33629
33636
  async getWorkspace() {
33630
33637
  const res = await this.fetch('/workspace');
33631
33638
  return res.json();
@@ -33912,6 +33919,57 @@ exports.formatIntentMd = formatIntentMd;
33912
33919
  exports.formatCursorRules = formatCursorRules;
33913
33920
  exports.formatClaudeMdSection = formatClaudeMdSection;
33914
33921
  exports.formatOutcomeRubric = formatOutcomeRubric;
33922
+ const VERIFICATION_KIND_LABELS = {
33923
+ fastest: 'Fastest check',
33924
+ 'shipped-signal': 'Shipped signal',
33925
+ 'regression-guard': 'Regression guard',
33926
+ manual: 'Manual check',
33927
+ test: 'Automated test',
33928
+ };
33929
+ const VERIFICATION_KIND_ORDER = ['fastest', 'shipped-signal', 'regression-guard', 'manual', 'test'];
33930
+ const VERIFICATION_KIND_SET = new Set(VERIFICATION_KIND_ORDER);
33931
+ /** Read verification uniformly as a check collection: canonical checks[] + adapted legacy buckets. */
33932
+ function toVerificationChecks(v) {
33933
+ if (!v || typeof v !== 'object')
33934
+ return [];
33935
+ const out = [];
33936
+ for (const c of Array.isArray(v.checks) ? v.checks : []) {
33937
+ const description = typeof c?.description === 'string' ? c.description.trim() : '';
33938
+ if (!description)
33939
+ continue;
33940
+ out.push({
33941
+ kind: VERIFICATION_KIND_SET.has(c.kind) ? c.kind : 'test',
33942
+ description,
33943
+ status: c.status,
33944
+ verifies: typeof c.verifies === 'string' && c.verifies.trim()
33945
+ ? c.verifies.trim()
33946
+ : undefined,
33947
+ });
33948
+ }
33949
+ const legacy = [
33950
+ [v.e2eTests, 'test'], [v.unitTests, 'test'], [v.manualChecks, 'manual'],
33951
+ ];
33952
+ for (const [arr, kind] of legacy) {
33953
+ for (const s of arr ?? []) {
33954
+ if (typeof s === 'string' && s.trim())
33955
+ out.push({ kind, description: s.trim() });
33956
+ }
33957
+ }
33958
+ return out;
33959
+ }
33960
+ /** Group verification into ordered, non-empty kind groups for rendering. */
33961
+ function groupVerificationChecks(v) {
33962
+ const checks = toVerificationChecks(v);
33963
+ return VERIFICATION_KIND_ORDER
33964
+ .map((kind) => ({ kind, label: VERIFICATION_KIND_LABELS[kind], checks: checks.filter((c) => c.kind === kind) }))
33965
+ .filter((g) => g.checks.length > 0);
33966
+ }
33967
+ /** A single check rendered as agent-facing text, annotated with its verdict and verifies target. */
33968
+ function renderCheckLine(c) {
33969
+ const verifies = c.verifies ? ` (verifies: ${c.verifies})` : '';
33970
+ const status = c.status && c.status !== 'unknown' ? ` [${c.status}]` : '';
33971
+ return `${c.description}${verifies}${status}`;
33972
+ }
33915
33973
  /** Extract text from a string or structured outcome. */
33916
33974
  function getOutcomeText(o) {
33917
33975
  return typeof o === 'string' ? o : o.text;
@@ -34023,13 +34081,26 @@ IMPORTANT:
34023
34081
  - edgeCases: { scenario: string, expectedBehavior: string }[] (optional)
34024
34082
  - healthMetrics: string[] (optional)
34025
34083
  - scope: { inScope?: string[], outOfScope?: string[] } (optional)
34026
- - verification: { manualChecks?: string[], unitTests?: string[], e2eTests?: string[] } (optional)
34084
+ - verification: { checks?: { kind: 'fastest'|'shipped-signal'|'regression-guard'|'manual'|'test', description: string }[] } (optional) — verification is a feedback loop, not just tests: a fastest check (quickest signal it works), a shipped-signal (observable production signal it landed), a regression-guard (what must not break), plus manual/test as needed. Legacy { manualChecks?, unitTests?, e2eTests? } string arrays are still accepted.
34027
34085
 
34028
34086
  Now, start the conversation. If they haven't provided one yet, ask for the concrete evidence (quote, metric, or ticket) driving this work.`;
34029
34087
  }
34030
34088
  // ============================================================
34031
34089
  // Format: intent.md
34032
34090
  // ============================================================
34091
+ /** Text-only decisions lines for the local file formatters (local mode has no evidence store).
34092
+ * Defensive: skips entries missing a string choice/reason. Returns [] when none (incl. a leading
34093
+ * blank line for section spacing when present). */
34094
+ function decisionLines(decisions, heading) {
34095
+ const valid = (decisions || []).filter(d => d && typeof d.choice === 'string' && d.choice.length > 0 && typeof d.reason === 'string');
34096
+ if (valid.length === 0)
34097
+ return [];
34098
+ const lines = ['', heading];
34099
+ for (const d of valid) {
34100
+ lines.push(`- **${d.choice}**${d.ruledOut ? ` (instead of: ${d.ruledOut})` : ''} — ${d.reason}`);
34101
+ }
34102
+ return lines;
34103
+ }
34033
34104
  /**
34034
34105
  * Generate intent.md content with YAML frontmatter.
34035
34106
  * Adapted from lib/agentPromptGenerator.ts generateIntentMd().
@@ -34057,6 +34128,7 @@ function formatIntentMd(spec) {
34057
34128
  sections.push('## Objective');
34058
34129
  sections.push(spec.objective);
34059
34130
  }
34131
+ sections.push(...decisionLines(spec.decisions, '## Decisions & Ruled-Out Alternatives'));
34060
34132
  if (spec.outcomes?.length) {
34061
34133
  sections.push('');
34062
34134
  sections.push('## Outcomes');
@@ -34099,27 +34171,15 @@ function formatIntentMd(spec) {
34099
34171
  sections.push(`- ${metric}`);
34100
34172
  }
34101
34173
  }
34102
- if (spec.verification) {
34103
- const { e2eTests, unitTests, manualChecks } = spec.verification;
34104
- const hasContent = e2eTests?.length || unitTests?.length || manualChecks?.length;
34105
- if (hasContent) {
34106
- sections.push('');
34107
- sections.push('## Verification');
34108
- if (e2eTests?.length) {
34109
- sections.push('**E2E Tests**:');
34110
- for (const t of e2eTests)
34111
- sections.push(`- [ ] ${t}`);
34112
- }
34113
- if (unitTests?.length) {
34114
- sections.push('**Unit Tests**:');
34115
- for (const t of unitTests)
34116
- sections.push(`- [ ] ${t}`);
34117
- }
34118
- if (manualChecks?.length) {
34119
- sections.push('**Manual Checks**:');
34120
- for (const t of manualChecks)
34121
- sections.push(`- [ ] ${t}`);
34122
- }
34174
+ const intentMdChecks = groupVerificationChecks(spec.verification);
34175
+ if (intentMdChecks.length) {
34176
+ sections.push('');
34177
+ sections.push('## Verification');
34178
+ sections.push('_A feedback loop, not just a test list._');
34179
+ for (const g of intentMdChecks) {
34180
+ sections.push(`**${g.label}**:`);
34181
+ for (const c of g.checks)
34182
+ sections.push(`- [ ] ${renderCheckLine(c)}`);
34123
34183
  }
34124
34184
  }
34125
34185
  sections.push('');
@@ -34146,6 +34206,7 @@ function formatCursorRules(spec) {
34146
34206
  sections.push('# WHY');
34147
34207
  sections.push(spec.objective);
34148
34208
  }
34209
+ sections.push(...decisionLines(spec.decisions, '# DECISIONS (already settled — do not relitigate)'));
34149
34210
  if (spec.outcomes?.length) {
34150
34211
  sections.push('');
34151
34212
  sections.push('# SUCCESS OUTCOMES');
@@ -34192,25 +34253,15 @@ function formatCursorRules(spec) {
34192
34253
  sections.push(`- ${metric}`);
34193
34254
  }
34194
34255
  }
34195
- if (spec.verification) {
34196
- const { e2eTests, unitTests, manualChecks } = spec.verification;
34197
- const hasContent = e2eTests?.length || unitTests?.length || manualChecks?.length;
34198
- if (hasContent) {
34199
- sections.push('');
34200
- sections.push('# VERIFICATION');
34201
- sections.push('After implementation, verify:');
34202
- if (e2eTests?.length) {
34203
- for (const t of e2eTests)
34204
- sections.push(`- [e2e] ${t}`);
34205
- }
34206
- if (unitTests?.length) {
34207
- for (const t of unitTests)
34208
- sections.push(`- [unit] ${t}`);
34209
- }
34210
- if (manualChecks?.length) {
34211
- for (const t of manualChecks)
34212
- sections.push(`- [manual] ${t}`);
34213
- }
34256
+ const cursorChecks = groupVerificationChecks(spec.verification);
34257
+ if (cursorChecks.length) {
34258
+ sections.push('');
34259
+ sections.push('# VERIFICATION');
34260
+ sections.push('After implementation, verify (a feedback loop, not just tests):');
34261
+ for (const g of cursorChecks) {
34262
+ sections.push(`**${g.label}**:`);
34263
+ for (const c of g.checks)
34264
+ sections.push(`- ${renderCheckLine(c)}`);
34214
34265
  }
34215
34266
  }
34216
34267
  sections.push('');
@@ -34236,6 +34287,7 @@ function formatClaudeMdSection(spec) {
34236
34287
  if (spec.objective) {
34237
34288
  sections.push(`**Objective**: ${spec.objective}`);
34238
34289
  }
34290
+ sections.push(...decisionLines(spec.decisions, '**Decisions**:'));
34239
34291
  if (spec.outcomes?.length) {
34240
34292
  sections.push('**Outcomes**:');
34241
34293
  sections.push(spec.outcomes.map(o => `- [ ] ${getPriorityLabel(o)}${getOutcomeText(o)}`).join('\n'));
@@ -34315,6 +34367,13 @@ function buildWriterDescription(spec) {
34315
34367
  sections.push('');
34316
34368
  sections.push(`Why this matters: ${spec.objective}`);
34317
34369
  }
34370
+ const decisions = (spec.decisions || []).filter(d => d && typeof d.choice === 'string' && d.choice.length > 0 && typeof d.reason === 'string');
34371
+ if (decisions.length > 0) {
34372
+ sections.push('');
34373
+ sections.push('Decisions already made (do not relitigate):');
34374
+ for (const d of decisions)
34375
+ sections.push(`- ${d.choice}${d.ruledOut ? ` (instead of: ${d.ruledOut})` : ''} — ${d.reason}`);
34376
+ }
34318
34377
  if (spec.scope?.inScope?.length) {
34319
34378
  sections.push('');
34320
34379
  sections.push('In scope:');
@@ -34399,17 +34458,9 @@ function buildGraderRubric(spec, opts = {}) {
34399
34458
  sections.push(`- ${c}`);
34400
34459
  }
34401
34460
  // Verification → procedures the grader must run to produce evidence
34402
- const v = spec.verification;
34403
34461
  const checks = [];
34404
- for (const t of v?.e2eTests ?? [])
34405
- if (t?.trim())
34406
- checks.push(`[e2e] ${t}`);
34407
- for (const t of v?.unitTests ?? [])
34408
- if (t?.trim())
34409
- checks.push(`[unit] ${t}`);
34410
- for (const t of v?.manualChecks ?? [])
34411
- if (t?.trim())
34412
- checks.push(`[manual] ${t}`);
34462
+ for (const c of toVerificationChecks(spec.verification))
34463
+ checks.push(`[${c.kind}] ${renderCheckLine(c)}`);
34413
34464
  for (const t of spec.implementationContext?.verificationSuggestions ?? [])
34414
34465
  if (t?.trim())
34415
34466
  checks.push(`[suggested] ${t}`);
@@ -34451,11 +34502,7 @@ function formatOutcomeRubric(spec, opts = {}) {
34451
34502
  const maxIterations = opts.maxIterations ?? 5;
34452
34503
  const description = buildWriterDescription(spec);
34453
34504
  const rubric = buildGraderRubric(spec, opts);
34454
- const hasVerification = [
34455
- ...(spec.verification?.e2eTests ?? []),
34456
- ...(spec.verification?.unitTests ?? []),
34457
- ...(spec.verification?.manualChecks ?? []),
34458
- ].some((t) => t?.trim());
34505
+ const hasVerification = toVerificationChecks(spec.verification).length > 0;
34459
34506
  const doc = [];
34460
34507
  doc.push('<!-- Pathmode → Claude Managed Agents: Outcomes rubric -->');
34461
34508
  doc.push(`<!-- Generated ${new Date().toISOString()} | pathmode.io -->`);
@@ -34685,6 +34732,58 @@ function extractVerification(body) {
34685
34732
  }
34686
34733
 
34687
34734
 
34735
+ /***/ }),
34736
+
34737
+ /***/ 4681:
34738
+ /***/ ((__unused_webpack_module, exports) => {
34739
+
34740
+ "use strict";
34741
+
34742
+ /**
34743
+ * Idempotent merge of a Pathmode-generated section into an existing agent-instructions file
34744
+ * (CLAUDE.md / AGENTS.md). The section is wrapped in <!-- PATHMODE:START ... --> / <!-- PATHMODE:END -->
34745
+ * markers (both the local formatClaudeMdSection and the cloud generateClaudeMdContent emit them),
34746
+ * so re-running replaces the marked block in place instead of appending a duplicate. This is the
34747
+ * no-drift guarantee of the round-trip: the repo's Pathmode context is regenerated from the
34748
+ * canonical source, never hand-maintained.
34749
+ */
34750
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
34751
+ exports.mergePathmodeSection = mergePathmodeSection;
34752
+ /** Matches the whole PATHMODE block, tolerant of the suffixed start marker
34753
+ * (`<!-- PATHMODE:START - Do not edit... -->`). Not global — there is one block per file. */
34754
+ const PATHMODE_SECTION_RE = /<!-- PATHMODE:START[\s\S]*?-->[\s\S]*?<!-- PATHMODE:END -->/;
34755
+ /** The section embeds a volatile `_Generated at <timestamp>_` line. Strip it so a re-generated
34756
+ * section that differs ONLY by a fresher timestamp still compares equal (reports 'unchanged' →
34757
+ * caller skips the write → no noisy timestamp-only diff that would mask real drift). */
34758
+ const GENERATED_AT_RE = /^_Generated at .*$/m;
34759
+ const withoutTimestamp = (s) => s.replace(GENERATED_AT_RE, '');
34760
+ /**
34761
+ * Merge `section` (a marker-wrapped Pathmode block) into `existing` file content.
34762
+ * - empty file -> the section becomes the whole file ('created')
34763
+ * - has a PATHMODE block, byte-identical to `section` -> no change ('unchanged' — proven no drift)
34764
+ * - has a PATHMODE block, different -> replace it in place ('replaced')
34765
+ * - no PATHMODE block -> append it after the existing content ('appended')
34766
+ * Pure; callers decide whether to actually write (skip the write when 'unchanged').
34767
+ */
34768
+ function mergePathmodeSection(existing, section) {
34769
+ if (!existing)
34770
+ return { content: section, action: 'created' };
34771
+ const match = existing.match(PATHMODE_SECTION_RE);
34772
+ if (match) {
34773
+ if (withoutTimestamp(match[0]) === withoutTimestamp(section)) {
34774
+ return { content: existing, action: 'unchanged' };
34775
+ }
34776
+ // Replacer FUNCTION, not a string: `section` may contain `$&`, `$$`, `` $` ``, `$'`, `$1`
34777
+ // (a user's spec text), which String.replace would otherwise interpret as special patterns
34778
+ // and corrupt the merged file. The function form substitutes `section` verbatim.
34779
+ return { content: existing.replace(PATHMODE_SECTION_RE, () => section), action: 'replaced' };
34780
+ }
34781
+ // No existing block: append, separated by a blank line, normalizing trailing whitespace so
34782
+ // re-runs stay stable (the next run finds the marker and replaces in place).
34783
+ return { content: `${existing.replace(/\s*$/, '')}\n\n${section}\n`, action: 'appended' };
34784
+ }
34785
+
34786
+
34688
34787
  /***/ }),
34689
34788
 
34690
34789
  /***/ 8294:
@@ -64524,7 +64623,7 @@ module.exports = /*#__PURE__*/JSON.parse('{"$schema":"http://json-schema.org/dra
64524
64623
  /***/ ((module) => {
64525
64624
 
64526
64625
  "use strict";
64527
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@pathmode/mcp-server","version":"1.7.0","publishConfig":{"access":"public"},"mcpName":"io.github.pathmodeio/mcp-server","description":"Pathmode MCP Server — Build structured intent specs through Socratic AI conversation (zero-config), or connect to your Intent Layer for strategic context, dependency graphs, and implementation prompts.","main":"dist/index.js","bin":{"pathmode-mcp":"dist/index.js"},"files":["dist/","manifest.json","icon.svg","README.md","skills/"],"scripts":{"build":"ncc build src/index.ts -o dist","dev":"ts-node src/index.ts","prepublishOnly":"npm run build"},"keywords":["pathmode","mcp","model-context-protocol","claude-code","claude-code-skills","agent-skills","cursor","windsurf","intent-engineering","intent-compiler","ai-agents","product-development","dependency-graph","strategic-planning"],"author":"Pathmode","license":"MIT","type":"commonjs","engines":{"node":">=18.0.0"},"repository":{"type":"git","url":"git+https://github.com/pathmodeio/mcp-server.git","directory":"packages/mcp-server"},"homepage":"https://pathmode.io","dependencies":{"@modelcontextprotocol/sdk":"^1.12.1","gray-matter":"^4.0.3","zod":"^3.24.0"},"devDependencies":{"@types/node":"^25.1.0","@vercel/ncc":"^0.38.4","ts-node":"^10.9.2","typescript":"^5.9.3"}}');
64626
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@pathmode/mcp-server","version":"1.8.0","publishConfig":{"access":"public"},"mcpName":"io.github.pathmodeio/mcp-server","description":"Pathmode MCP Server — Build structured intent specs through Socratic AI conversation (zero-config), or connect to your Intent Layer for strategic context, dependency graphs, and implementation prompts.","main":"dist/index.js","bin":{"pathmode-mcp":"dist/index.js"},"files":["dist/","manifest.json","icon.svg","README.md","skills/"],"scripts":{"build":"ncc build src/index.ts -o dist","dev":"ts-node src/index.ts","prepublishOnly":"npm run build"},"keywords":["pathmode","mcp","model-context-protocol","claude-code","claude-code-skills","agent-skills","cursor","windsurf","intent-engineering","intent-compiler","ai-agents","product-development","dependency-graph","strategic-planning"],"author":"Pathmode","license":"MIT","type":"commonjs","engines":{"node":">=18.0.0"},"repository":{"type":"git","url":"git+https://github.com/pathmodeio/mcp-server.git","directory":"packages/mcp-server"},"homepage":"https://pathmode.io","dependencies":{"@modelcontextprotocol/sdk":"^1.12.1","gray-matter":"^4.0.3","zod":"^3.24.0"},"devDependencies":{"@types/node":"^25.1.0","@vercel/ncc":"^0.38.4","ts-node":"^10.9.2","typescript":"^5.9.3"}}');
64528
64627
 
64529
64628
  /***/ })
64530
64629
 
@@ -64619,6 +64718,7 @@ const fs_1 = __nccwpck_require__(9896);
64619
64718
  const api_client_1 = __nccwpck_require__(7475);
64620
64719
  const local_reader_1 = __nccwpck_require__(3518);
64621
64720
  const intent_compiler_1 = __nccwpck_require__(6488);
64721
+ const pathmode_section_1 = __nccwpck_require__(4681);
64622
64722
  const setup_1 = __nccwpck_require__(8294);
64623
64723
  const install_skills_1 = __nccwpck_require__(3783);
64624
64724
  // Server version is sourced from package.json so the version reported to MCP
@@ -64682,6 +64782,22 @@ function startMcpServer() {
64682
64782
  function normalizeText(value) {
64683
64783
  return (value || '').trim();
64684
64784
  }
64785
+ // Clamp a caller-supplied write path to the project root (process.cwd()).
64786
+ // The optional `path` argument on intent_save / intent_export is influenced by
64787
+ // the MCP client, so an absolute path or `..` segments could otherwise land a
64788
+ // file outside the intended project folder. Reject those before any fs write.
64789
+ function resolveWithinProject(requestedPath) {
64790
+ const root = process.cwd();
64791
+ if ((0, path_1.isAbsolute)(requestedPath)) {
64792
+ throw new Error(`Refusing to write outside the project: "${requestedPath}" is an absolute path. Pass a path relative to the project root.`);
64793
+ }
64794
+ const resolved = (0, path_1.resolve)(root, requestedPath);
64795
+ const rel = (0, path_1.relative)(root, resolved);
64796
+ if (rel === '' || rel.startsWith('..') || (0, path_1.isAbsolute)(rel)) {
64797
+ throw new Error(`Refusing to write outside the project: "${requestedPath}" resolves outside the project root.`);
64798
+ }
64799
+ return resolved;
64800
+ }
64685
64801
  // Keep this selection heuristic aligned with the canonical readiness rules in
64686
64802
  // /Users/jannelammi/code/Pathmode/lib/intentReadiness.ts. The MCP package cannot
64687
64803
  // import app/lib code directly, so this mirrors only the minimum logic needed
@@ -64701,6 +64817,24 @@ function startMcpServer() {
64701
64817
  return anyReady;
64702
64818
  return intents[0];
64703
64819
  }
64820
+ /** The union of evidence IDs an intent cites: directly linked + section anchors + decision-cited.
64821
+ * Mirrors lib/intentSpecHelpers.collectSpecEvidenceIds (the MCP package can't import app/lib). */
64822
+ function collectCitedEvidenceIds(intent) {
64823
+ const anchorIds = Object.values((intent?.evidenceAnchors || {})).flat();
64824
+ const decisionIds = (intent?.decisions || []).flatMap((d) => d?.evidenceIds || []);
64825
+ const all = [...(intent?.evidenceIds || []), ...anchorIds, ...decisionIds];
64826
+ return Array.from(new Set(all.filter((id) => typeof id === 'string' && id.length > 0)));
64827
+ }
64828
+ /** Cheap, fetch-free coverage summary from the intent's own fields. Tells an agent how much
64829
+ * evidence backs the intent and where to get the full text, without bloating the default call. */
64830
+ function summarizeCitedEvidence(intent) {
64831
+ return {
64832
+ citedCount: collectCitedEvidenceIds(intent).length,
64833
+ linkedCount: (intent?.evidenceIds || []).length,
64834
+ anchoredSections: Object.keys(intent?.evidenceAnchors || {}).length,
64835
+ note: 'Evidence is referenced by ID. Call get_agent_prompt for the full evidence-backed execution prompt, or re-call get_current_intent with include_evidence=true to inline the evidence content.',
64836
+ };
64837
+ }
64704
64838
  // Note: The MCP SDK catches errors thrown in tool handlers and returns them as
64705
64839
  // error text results. CloudClientError thrown by requireCloudClient() will
64706
64840
  // surface its message to the client without crashing the server.
@@ -64709,10 +64843,13 @@ function startMcpServer() {
64709
64843
  // ============================================================
64710
64844
  server.registerTool('get_current_intent', {
64711
64845
  title: 'Get Current Intent',
64712
- description: 'Get the currently active intent, preferring approved intents with real objective/outcome content over empty stubs. Returns the full IntentSpec with objective, outcomes, constraints, and edge cases.',
64713
- inputSchema: { status: zod_1.z.string().optional().describe('Filter by status: draft, validated, approved, shipped, verified') },
64846
+ description: 'Get the currently active intent, preferring approved intents with real objective/outcome content over empty stubs. Returns the full IntentSpec plus an evidenceSummary (how much user evidence backs it). Evidence is referenced by ID; pass include_evidence=true to inline the evidence content, or call get_agent_prompt for the full evidence-backed execution prompt.',
64847
+ inputSchema: {
64848
+ status: zod_1.z.string().optional().describe('Filter by status: draft, validated, approved, shipped, verified'),
64849
+ include_evidence: zod_1.z.boolean().optional().describe('Inline the actual evidence items (truncated) this intent cites. Default false — the default response carries only a fetch-free evidenceSummary to keep casual calls cheap.'),
64850
+ },
64714
64851
  annotations: READ_ONLY,
64715
- }, async ({ status }) => {
64852
+ }, async ({ status, include_evidence }) => {
64716
64853
  if (isLocalMode) {
64717
64854
  const intents = (0, local_reader_1.readLocalIntents)();
64718
64855
  const filtered = status ? intents.filter(i => i.status === status) : intents;
@@ -64720,18 +64857,47 @@ function startMcpServer() {
64720
64857
  if (!current) {
64721
64858
  return { content: [{ type: 'text', text: 'No intents found locally.' }] };
64722
64859
  }
64860
+ // Local mode has no cloud evidence store — return the intent as-is.
64723
64861
  return { content: [{ type: 'text', text: JSON.stringify(current, null, 2) }] };
64724
64862
  }
64725
64863
  const cloud = requireCloudClient();
64726
- const intents = await cloud.listIntents(status || 'approved');
64864
+ let intents = await cloud.listIntents(status || 'approved');
64727
64865
  if (intents.length === 0) {
64728
- const allIntents = await cloud.listIntents();
64729
- if (allIntents.length === 0) {
64866
+ intents = await cloud.listIntents();
64867
+ if (intents.length === 0) {
64730
64868
  return { content: [{ type: 'text', text: 'No intents found in workspace.' }] };
64731
64869
  }
64732
- return { content: [{ type: 'text', text: JSON.stringify(pickCurrentIntent(allIntents), null, 2) }] };
64733
64870
  }
64734
- return { content: [{ type: 'text', text: JSON.stringify(pickCurrentIntent(intents), null, 2) }] };
64871
+ const current = pickCurrentIntent(intents);
64872
+ // Default: a fetch-free coverage summary (no extra API call). On request: the cited
64873
+ // evidence content, fetched once for the product and filtered to this intent's citations.
64874
+ const evidenceSummary = summarizeCitedEvidence(current);
64875
+ let evidence;
64876
+ let unresolvedEvidenceIds;
64877
+ if (include_evidence && current?.productId) {
64878
+ const cited = collectCitedEvidenceIds(current);
64879
+ if (cited.length > 0) {
64880
+ // Pull up to the API max (200) and filter to this intent's citations. A cited item
64881
+ // older than that page won't resolve — surface it as unresolvedEvidenceIds rather
64882
+ // than silently returning an incomplete evidence block.
64883
+ const { evidence: pool } = await cloud.queryEvidence({ productId: current.productId, limit: 200 });
64884
+ const found = new Map(pool.map(e => [e.id, e]));
64885
+ evidence = cited
64886
+ .map(id => found.get(id))
64887
+ .filter((e) => !!e)
64888
+ .map(e => ({
64889
+ id: e.id,
64890
+ type: e.type,
64891
+ content: e.content.length > 200 ? `${e.content.slice(0, 200)}…` : e.content,
64892
+ source: e.source,
64893
+ severity: e.severity,
64894
+ }));
64895
+ const missing = cited.filter(id => !found.has(id));
64896
+ if (missing.length > 0)
64897
+ unresolvedEvidenceIds = missing;
64898
+ }
64899
+ }
64900
+ return { content: [{ type: 'text', text: JSON.stringify({ ...current, evidenceSummary, ...(evidence ? { evidence } : {}), ...(unresolvedEvidenceIds ? { unresolvedEvidenceIds } : {}) }, null, 2) }] };
64735
64901
  });
64736
64902
  server.registerTool('list_intents', {
64737
64903
  title: 'List Intents',
@@ -64760,7 +64926,7 @@ function startMcpServer() {
64760
64926
  });
64761
64927
  server.registerTool('get_intent', {
64762
64928
  title: 'Get Intent',
64763
- description: 'Get a single intent by ID with full details including objective, outcomes, constraints, edge cases, and relations.',
64929
+ description: 'Get a single intent by ID with full details including objective, outcomes, constraints, edge cases, and relations. Evidence is referenced by ID; call get_agent_prompt for the full evidence-backed execution prompt.',
64764
64930
  inputSchema: { intentId: zod_1.z.string().describe('The intent ID to fetch') },
64765
64931
  annotations: READ_ONLY,
64766
64932
  }, async ({ intentId }) => {
@@ -65029,27 +65195,29 @@ function startMcpServer() {
65029
65195
  });
65030
65196
  /** Map a cloud ApiIntent into the IntentFields shape the formatters consume. */
65031
65197
  function apiIntentToFields(intent) {
65032
- const v = (intent.verification || {});
65033
65198
  return {
65034
65199
  id: intent.id,
65035
65200
  title: intent.title,
65036
65201
  objective: intent.objective,
65037
65202
  outcomes: intent.outcomes ?? [],
65203
+ decisions: intent.decisions,
65038
65204
  constraints: intent.constraints,
65039
65205
  edgeCases: (intent.edgeCases ?? []).map((e) => ({ scenario: e.scenario, expectedBehavior: e.expectedBehavior })),
65040
65206
  healthMetrics: intent.healthMetrics,
65041
65207
  scope: intent.scope,
65042
- verification: { manualChecks: v.manualChecks, unitTests: v.unitTests, e2eTests: v.e2eTests },
65208
+ // Pass the whole verification through (checks[] + legacy buckets) so feedback-loop checks
65209
+ // survive the cloud→local bridge; the formatters adapt both shapes uniformly.
65210
+ verification: (intent.verification || undefined),
65043
65211
  implementationContext: intent.implementationContext ?? undefined,
65044
65212
  };
65045
65213
  }
65046
65214
  server.registerTool('export_context', {
65047
65215
  title: 'Export Context',
65048
- description: 'Export workspace context as a formatted file. Use "claude-md" for CLAUDE.md (full workspace context), "cursorrules" for Cursor AI rules, "intent-md" for a single intent specification file, or "outcome-rubric" for a Claude Managed Agents Outcomes rubric (writer description + evidence-forcing grader rubric) derived from the resolved intent, its implementation context, and the workspace constitution. For cursorrules/intent-md/outcome-rubric, product context is always derived from the resolved intent. For claude-md, pass productId to select a specific product, otherwise the first active product is used.',
65216
+ description: 'Export workspace context as a formatted file. Use "claude-md" for CLAUDE.md (full workspace context), "agents-md" for the same workspace context written for AGENTS.md (the native instruction file for OpenAI Codex and modern Cursor), "cursorrules" for Cursor AI rules, "intent-md" for a single intent specification file, or "outcome-rubric" for a Claude Managed Agents Outcomes rubric (writer description + evidence-forcing grader rubric) derived from the resolved intent, its implementation context, and the workspace constitution. claude-md and agents-md produce identical, agent-agnostic content (the difference is only the target filename). For cursorrules/intent-md/outcome-rubric, product context is always derived from the resolved intent. For claude-md/agents-md, pass productId to select a specific product, otherwise the first active product is used.',
65049
65217
  inputSchema: {
65050
- format: zod_1.z.enum(['claude-md', 'cursorrules', 'intent-md', 'outcome-rubric']).describe('Export format'),
65218
+ format: zod_1.z.enum(['claude-md', 'agents-md', 'cursorrules', 'intent-md', 'outcome-rubric']).describe('Export format'),
65051
65219
  intentId: zod_1.z.string().optional().describe('Intent ID (optional, for cursorrules and intent-md)'),
65052
- productId: zod_1.z.string().optional().describe('Product ID (optional, only used for claude-md format to select a specific product)'),
65220
+ productId: zod_1.z.string().optional().describe('Product ID (optional, only used for claude-md/agents-md format to select a specific product)'),
65053
65221
  },
65054
65222
  annotations: READ_ONLY,
65055
65223
  }, async ({ format, intentId, productId }) => {
@@ -65083,6 +65251,41 @@ function startMcpServer() {
65083
65251
  return { content: [{ type: 'text', text: `Export failed: ${e.message}` }] };
65084
65252
  }
65085
65253
  });
65254
+ server.tool('sync_context', 'Write this workspace\'s canonical Pathmode context into the repo\'s CLAUDE.md (or AGENTS.md), idempotently — the round-trip. Pulls the latest from Pathmode and replaces the PATHMODE-marked section in place, so the repo\'s agent instructions never drift from the source of truth. Unlike export_context (which returns the text for you to read), this writes the file; re-running when nothing changed reports "no drift". Run it after the canonical context changes in Pathmode.', {
65255
+ format: zod_1.z.enum(['claude-md', 'agents-md']).optional().describe('Target file: claude-md → CLAUDE.md (default), agents-md → AGENTS.md (Codex and other AGENTS.md-aware agents).'),
65256
+ productId: zod_1.z.string().optional().describe('Product ID (optional; defaults to the first active product).'),
65257
+ path: zod_1.z.string().optional().describe('Output file path relative to the project root. Must stay inside the project (absolute paths and ".." are rejected). Defaults to CLAUDE.md / AGENTS.md.'),
65258
+ }, async ({ format, productId, path }) => {
65259
+ if (isLocalMode) {
65260
+ return { content: [{ type: 'text', text: 'Sync requires cloud mode. Use PATHMODE_API_KEY to connect.' }] };
65261
+ }
65262
+ const fmt = format || 'claude-md';
65263
+ try {
65264
+ // Pull the canonical, marker-wrapped section from the cloud (generateClaudeMdContent emits
65265
+ // the same <!-- PATHMODE:START/END --> markers the merge keys on).
65266
+ const section = await requireCloudClient().exportContext(fmt, undefined, productId);
65267
+ const defaultFile = fmt === 'agents-md' ? 'AGENTS.md' : 'CLAUDE.md';
65268
+ const filePath = resolveWithinProject(path || defaultFile);
65269
+ let existing = '';
65270
+ try {
65271
+ existing = (0, fs_1.readFileSync)(filePath, 'utf-8');
65272
+ }
65273
+ catch { /* file doesn't exist yet */ }
65274
+ const merged = (0, pathmode_section_1.mergePathmodeSection)(existing, section);
65275
+ if (merged.action !== 'unchanged')
65276
+ (0, fs_1.writeFileSync)(filePath, merged.content, 'utf-8');
65277
+ const msg = {
65278
+ unchanged: `✓ ${filePath} is already in sync with Pathmode — no drift.`,
65279
+ created: `✓ Created ${filePath} from your Pathmode context.`,
65280
+ appended: `✓ Added the Pathmode context section to ${filePath}.`,
65281
+ replaced: `✓ Synced ${filePath} — refreshed the Pathmode context section from canonical.`,
65282
+ };
65283
+ return { content: [{ type: 'text', text: msg[merged.action] }] };
65284
+ }
65285
+ catch (e) {
65286
+ return { content: [{ type: 'text', text: `Sync failed: ${e.message}` }] };
65287
+ }
65288
+ });
65086
65289
  server.registerTool('get_agent_prompt', {
65087
65290
  title: 'Get Agent Prompt',
65088
65291
  description: 'Get a formatted execution prompt for a specific intent. This is the full structured prompt including objective, outcomes, constraints, edge cases, and verification steps.',
@@ -65187,6 +65390,31 @@ function startMcpServer() {
65187
65390
  }]
65188
65391
  };
65189
65392
  });
65393
+ server.registerTool('record_implementation_finding', {
65394
+ title: 'Record Implementation Finding',
65395
+ description: 'Write a correction back to an intent when BUILDING it revealed the spec was wrong. Use this the moment you discover the spec assumed something the implementation contradicts — instead of only fixing it in your head or this chat, record it so the NEXT agent or person inherits the correction. This is the inverse of a decision: it closes the refinement loop so the same stale premise is not rebuilt. Open findings ride into future agent prompts until a human reconciles them into the spec.',
65396
+ inputSchema: {
65397
+ intentId: zod_1.z.string().describe('The intent ID whose spec the finding is about'),
65398
+ assumption: zod_1.z.string().describe('What the spec assumed or said before you built it'),
65399
+ finding: zod_1.z.string().describe('What building it actually revealed — the fact that contradicts the assumption'),
65400
+ target: zod_1.z.string().optional().describe('Which part of the spec this contradicts: "objective", "outcome:<id>", "constraint:<index>", "edgeCase:<id>", "check:<id>" (a verification check — recording this flips that check to failing), or plain prose'),
65401
+ correction: zod_1.z.string().optional().describe('Your proposed correction to the intent, if you have one'),
65402
+ source: zod_1.z.string().optional().describe('Where this came from, e.g. "claude-code @ owner/repo" — provenance for the audit trail'),
65403
+ },
65404
+ annotations: WRITE_OP,
65405
+ }, async ({ intentId, assumption, finding, target, correction, source }) => {
65406
+ if (isLocalMode) {
65407
+ return { content: [{ type: 'text', text: 'Recording findings requires cloud mode. Use PATHMODE_API_KEY to connect.' }] };
65408
+ }
65409
+ const result = await requireCloudClient().recordFinding(intentId, { assumption, finding, target, correction, source });
65410
+ const openCount = result?.openCount;
65411
+ return {
65412
+ content: [{
65413
+ type: 'text',
65414
+ text: `Finding recorded for intent ${intentId}. The next agent that pulls this intent will see it flagged as unreconciled until a human folds it into the spec.${typeof openCount === 'number' ? ` Open findings now: ${openCount}.` : ''}`
65415
+ }]
65416
+ };
65417
+ });
65190
65418
  server.registerTool('create_intent', {
65191
65419
  title: 'Create Intent',
65192
65420
  description: 'Create a new intent spec in the workspace. Requires at minimum a title, objective, and productId. Returns the created intent with its ID. Use list_intents first to see existing intents and avoid duplicates.',
@@ -65202,6 +65430,12 @@ function startMcpServer() {
65202
65430
  expectedBehavior: zod_1.z.string(),
65203
65431
  })).optional().describe('Failure modes and boundary conditions'),
65204
65432
  verification: zod_1.z.object({
65433
+ checks: zod_1.z.array(zod_1.z.object({
65434
+ kind: zod_1.z.enum(['fastest', 'manual', 'shipped-signal', 'regression-guard', 'test']),
65435
+ description: zod_1.z.string(),
65436
+ status: zod_1.z.enum(['unknown', 'passing', 'failing']).optional(),
65437
+ verifies: zod_1.z.string().optional(),
65438
+ })).optional().describe('Feedback-loop checks (preferred over the legacy test buckets)'),
65205
65439
  manualChecks: zod_1.z.array(zod_1.z.string()).optional(),
65206
65440
  unitTests: zod_1.z.array(zod_1.z.string()).optional(),
65207
65441
  e2eTests: zod_1.z.array(zod_1.z.string()).optional(),
@@ -65236,6 +65470,12 @@ function startMcpServer() {
65236
65470
  expectedBehavior: zod_1.z.string(),
65237
65471
  })).optional().describe('Replace all edge cases'),
65238
65472
  verification: zod_1.z.object({
65473
+ checks: zod_1.z.array(zod_1.z.object({
65474
+ kind: zod_1.z.enum(['fastest', 'manual', 'shipped-signal', 'regression-guard', 'test']),
65475
+ description: zod_1.z.string(),
65476
+ status: zod_1.z.enum(['unknown', 'passing', 'failing']).optional(),
65477
+ verifies: zod_1.z.string().optional(),
65478
+ })).optional().describe('Feedback-loop checks (preferred over the legacy test buckets)'),
65239
65479
  manualChecks: zod_1.z.array(zod_1.z.string()).optional(),
65240
65480
  unitTests: zod_1.z.array(zod_1.z.string()).optional(),
65241
65481
  e2eTests: zod_1.z.array(zod_1.z.string()).optional(),
@@ -65418,6 +65658,11 @@ function startMcpServer() {
65418
65658
  title: zod_1.z.string().describe('Short name for the intent'),
65419
65659
  objective: zod_1.z.string().describe('Why this matters — the problem and who has it'),
65420
65660
  outcomes: zod_1.z.array(zod_1.z.string()).describe('Observable, testable state changes'),
65661
+ decisions: zod_1.z.array(zod_1.z.object({
65662
+ choice: zod_1.z.string(),
65663
+ ruledOut: zod_1.z.string().optional(),
65664
+ reason: zod_1.z.string(),
65665
+ })).optional().describe('Decisions settled during design + the alternatives ruled out, so the agent does not relitigate them'),
65421
65666
  constraints: zod_1.z.array(zod_1.z.string()).optional().describe('Hard limits the implementation must respect'),
65422
65667
  edgeCases: zod_1.z.array(zod_1.z.object({
65423
65668
  scenario: zod_1.z.string(),
@@ -65429,6 +65674,12 @@ function startMcpServer() {
65429
65674
  outOfScope: zod_1.z.array(zod_1.z.string()).optional().describe('What is explicitly out of scope'),
65430
65675
  }).optional().describe('Scope boundaries — what to build and what to avoid'),
65431
65676
  verification: zod_1.z.object({
65677
+ checks: zod_1.z.array(zod_1.z.object({
65678
+ kind: zod_1.z.enum(['fastest', 'manual', 'shipped-signal', 'regression-guard', 'test']),
65679
+ description: zod_1.z.string(),
65680
+ status: zod_1.z.enum(['unknown', 'passing', 'failing']).optional(),
65681
+ verifies: zod_1.z.string().optional(),
65682
+ })).optional().describe('Feedback-loop checks (preferred over the legacy test buckets)'),
65432
65683
  manualChecks: zod_1.z.array(zod_1.z.string()).optional(),
65433
65684
  unitTests: zod_1.z.array(zod_1.z.string()).optional(),
65434
65685
  e2eTests: zod_1.z.array(zod_1.z.string()).optional(),
@@ -65447,9 +65698,9 @@ function startMcpServer() {
65447
65698
  });
65448
65699
  server.tool('intent_save', 'Save an intent spec to intent.md in the project root. Called after building a spec through conversation.', {
65449
65700
  spec: zod_1.z.object(intentSpecSchema),
65450
- path: zod_1.z.string().optional().describe('File path relative to cwd. Defaults to intent.md'),
65701
+ path: zod_1.z.string().optional().describe('File path relative to the project root. Must stay inside the project (absolute paths and ".." are rejected). Defaults to intent.md'),
65451
65702
  }, async ({ spec, path }) => {
65452
- const filePath = (0, path_1.resolve)(process.cwd(), path || 'intent.md');
65703
+ const filePath = resolveWithinProject(path || 'intent.md');
65453
65704
  const content = (0, intent_compiler_1.formatIntentMd)({ ...spec, id: `intent_${Date.now()}` });
65454
65705
  (0, fs_1.writeFileSync)(filePath, content, 'utf-8');
65455
65706
  return {
@@ -65462,11 +65713,11 @@ function startMcpServer() {
65462
65713
  server.tool('intent_export', 'Export an intent spec as .cursorrules, a CLAUDE.md or AGENTS.md section, or a Claude Managed Agents Outcomes rubric for AI agent consumption. Use agents-md for Codex, Cursor, and other AGENTS.md-aware agents.', {
65463
65714
  format: zod_1.z.enum(['cursorrules', 'claude-md', 'agents-md', 'outcome-rubric']).describe('Export format'),
65464
65715
  spec: zod_1.z.object(intentSpecSchema),
65465
- path: zod_1.z.string().optional().describe('Output file path. Defaults to .cursorrules, CLAUDE.md, or AGENTS.md'),
65716
+ path: zod_1.z.string().optional().describe('Output file path relative to the project root. Must stay inside the project (absolute paths and ".." are rejected). Defaults to .cursorrules, CLAUDE.md, or AGENTS.md'),
65466
65717
  }, async ({ format, spec, path }) => {
65467
65718
  if (format === 'cursorrules') {
65468
65719
  const content = (0, intent_compiler_1.formatCursorRules)(spec);
65469
- const filePath = (0, path_1.resolve)(process.cwd(), path || '.cursorrules');
65720
+ const filePath = resolveWithinProject(path || '.cursorrules');
65470
65721
  (0, fs_1.writeFileSync)(filePath, content, 'utf-8');
65471
65722
  return {
65472
65723
  content: [{
@@ -65477,7 +65728,7 @@ function startMcpServer() {
65477
65728
  }
65478
65729
  else if (format === 'outcome-rubric') {
65479
65730
  const content = (0, intent_compiler_1.formatOutcomeRubric)(spec);
65480
- const filePath = (0, path_1.resolve)(process.cwd(), path || 'outcome-rubric.md');
65731
+ const filePath = resolveWithinProject(path || 'outcome-rubric.md');
65481
65732
  (0, fs_1.writeFileSync)(filePath, content, 'utf-8');
65482
65733
  return {
65483
65734
  content: [{
@@ -65489,28 +65740,24 @@ function startMcpServer() {
65489
65740
  else {
65490
65741
  const section = (0, intent_compiler_1.formatClaudeMdSection)(spec);
65491
65742
  const defaultFile = format === 'agents-md' ? 'AGENTS.md' : 'CLAUDE.md';
65492
- const filePath = (0, path_1.resolve)(process.cwd(), path || defaultFile);
65493
- // Append or replace PATHMODE section in existing file
65743
+ const filePath = resolveWithinProject(path || defaultFile);
65494
65744
  let existing = '';
65495
65745
  try {
65496
65746
  existing = (0, fs_1.readFileSync)(filePath, 'utf-8');
65497
65747
  }
65498
65748
  catch { /* file doesn't exist yet */ }
65499
- // Tolerant of the suffixed start marker emitted by formatClaudeMdSection
65500
- // (`<!-- PATHMODE:START - Do not edit... -->`), so re-exports replace
65501
- // the block instead of appending a duplicate.
65502
- const marker = /<!-- PATHMODE:START[\s\S]*?-->[\s\S]*?<!-- PATHMODE:END -->/;
65503
- const updated = marker.test(existing)
65504
- ? existing.replace(marker, section)
65505
- : existing ? existing + '\n\n' + section : section;
65506
- (0, fs_1.writeFileSync)(filePath, updated, 'utf-8');
65749
+ const merged = (0, pathmode_section_1.mergePathmodeSection)(existing, section);
65750
+ if (merged.action !== 'unchanged')
65751
+ (0, fs_1.writeFileSync)(filePath, merged.content, 'utf-8');
65507
65752
  const audience = format === 'agents-md'
65508
65753
  ? 'Codex, Cursor, and other AGENTS.md-aware agents'
65509
65754
  : 'Claude Code';
65510
65755
  return {
65511
65756
  content: [{
65512
65757
  type: 'text',
65513
- text: `✓ Exported ${defaultFile} section to ${filePath}\n\n${audience} will now see this intent as context in every conversation.`,
65758
+ text: merged.action === 'unchanged'
65759
+ ? `✓ ${filePath} already has this intent's context — no change.`
65760
+ : `✓ Exported ${defaultFile} section to ${filePath}\n\n${audience} will now see this intent as context in every conversation.`,
65514
65761
  }],
65515
65762
  };
65516
65763
  }
@@ -8,6 +8,23 @@
8
8
  * Architecture: Claude Code IS the conversation engine. This module only provides
9
9
  * the personality prompt and file format generators. No AI API calls happen here.
10
10
  */
11
+ export interface IntentDecision {
12
+ id?: string;
13
+ choice: string;
14
+ ruledOut?: string;
15
+ reason: string;
16
+ evidenceIds?: string[];
17
+ resolvedAt?: number;
18
+ }
19
+ export type VerificationCheckKind = 'fastest' | 'manual' | 'shipped-signal' | 'regression-guard' | 'test';
20
+ export type VerificationCheckStatus = 'unknown' | 'passing' | 'failing';
21
+ export interface VerificationCheck {
22
+ id?: string;
23
+ kind: VerificationCheckKind;
24
+ description: string;
25
+ status?: VerificationCheckStatus;
26
+ verifies?: string;
27
+ }
11
28
  export interface IntentFields {
12
29
  id?: string;
13
30
  title: string;
@@ -17,6 +34,8 @@ export interface IntentFields {
17
34
  text: string;
18
35
  priority?: 'must' | 'should' | 'could';
19
36
  })[];
37
+ /** Decision log — choices settled + alternatives ruled out (text only; local mode has no evidence store). */
38
+ decisions?: IntentDecision[];
20
39
  constraints?: string[];
21
40
  edgeCases?: {
22
41
  scenario: string;
@@ -28,6 +47,9 @@ export interface IntentFields {
28
47
  outOfScope?: string[];
29
48
  };
30
49
  verification?: {
50
+ /** Canonical feedback-loop check collection (fastest / shipped-signal / regression-guard / manual / test). */
51
+ checks?: VerificationCheck[];
52
+ /** Legacy buckets — adapted to checks on read. */
31
53
  manualChecks?: string[];
32
54
  unitTests?: string[];
33
55
  e2eTests?: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"","sourceRoot":"","sources":["file:///Users/jannelammi/code/Pathmode/packages/mcp-server/src/intent-compiler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,MAAM,WAAW,YAAY;IACzB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,CAAC,MAAM,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAA;KAAE,CAAC,EAAE,CAAC;IAC7F,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACtD,YAAY,CAAC,EAAE;QACX,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;IACF;sFACkF;IAClF,qBAAqB,CAAC,EAAE;QACpB,aAAa,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QACnD,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACjB,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;KACtC,GAAG,IAAI,CAAC;CACZ;AAwDD;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CA2D/C;AAOD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CA+FzD;AAOD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAwF5D;AAOD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAsDhE;AAOD,MAAM,WAAW,oBAAoB;IACjC;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,0EAA0E;IAC1E,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AA6KD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,GAAE,oBAAyB,GAAG,MAAM,CAuC/F"}
1
+ {"version":3,"file":"","sourceRoot":"","sources":["file:///Users/jannelammi/code/Pathmode/packages/mcp-server/src/intent-compiler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,MAAM,WAAW,cAAc;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAMD,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,QAAQ,GAAG,gBAAgB,GAAG,kBAAkB,GAAG,MAAM,CAAC;AAC1G,MAAM,MAAM,uBAAuB,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AACxE,MAAM,WAAW,iBAAiB;IAC9B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,qBAAqB,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAsDD,MAAM,WAAW,YAAY;IACzB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,CAAC,MAAM,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAA;KAAE,CAAC,EAAE,CAAC;IAC7F,6GAA6G;IAC7G,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACtD,YAAY,CAAC,EAAE;QACX,8GAA8G;QAC9G,MAAM,CAAC,EAAE,iBAAiB,EAAE,CAAC;QAC7B,kDAAkD;QAClD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;IACF;sFACkF;IAClF,qBAAqB,CAAC,EAAE;QACpB,aAAa,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QACnD,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACjB,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;KACtC,GAAG,IAAI,CAAC;CACZ;AAwDD;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CA2D/C;AAoBD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAuFzD;AAOD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAkF5D;AAOD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAwDhE;AAOD,MAAM,WAAW,oBAAoB;IACjC;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,0EAA0E;IAC1E,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAiLD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,GAAE,oBAAyB,GAAG,MAAM,CAmC/F"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Idempotent merge of a Pathmode-generated section into an existing agent-instructions file
3
+ * (CLAUDE.md / AGENTS.md). The section is wrapped in <!-- PATHMODE:START ... --> / <!-- PATHMODE:END -->
4
+ * markers (both the local formatClaudeMdSection and the cloud generateClaudeMdContent emit them),
5
+ * so re-running replaces the marked block in place instead of appending a duplicate. This is the
6
+ * no-drift guarantee of the round-trip: the repo's Pathmode context is regenerated from the
7
+ * canonical source, never hand-maintained.
8
+ */
9
+ export type PathmodeMergeAction = 'created' | 'replaced' | 'appended' | 'unchanged';
10
+ export interface PathmodeMergeResult {
11
+ content: string;
12
+ action: PathmodeMergeAction;
13
+ }
14
+ /**
15
+ * Merge `section` (a marker-wrapped Pathmode block) into `existing` file content.
16
+ * - empty file -> the section becomes the whole file ('created')
17
+ * - has a PATHMODE block, byte-identical to `section` -> no change ('unchanged' — proven no drift)
18
+ * - has a PATHMODE block, different -> replace it in place ('replaced')
19
+ * - no PATHMODE block -> append it after the existing content ('appended')
20
+ * Pure; callers decide whether to actually write (skip the write when 'unchanged').
21
+ */
22
+ export declare function mergePathmodeSection(existing: string, section: string): PathmodeMergeResult;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"","sourceRoot":"","sources":["file:///Users/jannelammi/code/Pathmode/packages/mcp-server/src/pathmode-section.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAYH,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,WAAW,CAAC;AAEpF,MAAM,WAAW,mBAAmB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,mBAAmB,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAiB3F"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"","sourceRoot":"","sources":["file:///Users/jannelammi/code/Pathmode/packages/mcp-server/src/pathmode-section.test.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pathmode/mcp-server",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },