@pathmode/mcp-server 1.6.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
@@ -28,11 +28,11 @@ The Intent Compiler turns Claude Code into a Socratic product thinking partner.
28
28
  Does that capture it, or is there more to the pain?
29
29
  ```
30
30
 
31
- When the spec is ready, Claude saves it as `intent.md` and optionally exports as `.cursorrules` or `CLAUDE.md` — so every AI agent in your project sees the intent as its implementation context.
31
+ When the spec is ready, Claude saves it as `intent.md` and optionally exports as `.cursorrules`, `CLAUDE.md`, or `AGENTS.md` (Codex/Cursor) — so every AI agent in your project sees the intent as its implementation context.
32
32
 
33
33
  ### Quick Start
34
34
 
35
- Add to `.claude/settings.json`:
35
+ Add to `.mcp.json` in your project root:
36
36
 
37
37
  ```json
38
38
  {
@@ -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
 
@@ -156,7 +156,7 @@ npx @pathmode/mcp-server@latest setup pm_live_...
156
156
  }
157
157
  ```
158
158
 
159
- Works with Claude Code (`.claude/settings.json`), Claude Desktop (`claude_desktop_config.json`), and Cursor (`.cursor/mcp.json`).
159
+ Works with Claude Code (`.mcp.json` in the project root), Claude Desktop (`claude_desktop_config.json`), and Cursor (`.cursor/mcp.json`).
160
160
 
161
161
  Get your API key from **Settings > API Keys** in the [Pathmode app](https://pathmode.io).
162
162
 
@@ -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;
@@ -184,6 +214,10 @@ export interface ApiWorkspace {
184
214
  id: string;
185
215
  category: string;
186
216
  text: string;
217
+ rationale?: string;
218
+ scope?: string;
219
+ enforcement?: 'advisory' | 'required' | 'blocking';
220
+ examples?: string[];
187
221
  isActive: boolean;
188
222
  createdAt: string;
189
223
  }[];
@@ -232,10 +266,11 @@ export declare class PathmodeClient {
232
266
  verificationChecklistCount?: number;
233
267
  }>;
234
268
  logNote(intentId: string, note: string, source?: string): Promise<any>;
269
+ recordFinding(intentId: string, input: RecordFindingInput): Promise<any>;
235
270
  getWorkspace(): Promise<ApiWorkspace>;
236
271
  getConstitution(): Promise<any>;
237
272
  exportClaudeMd(): Promise<string>;
238
- 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>;
239
274
  createIntent(input: CreateIntentInput): Promise<ApiIntent>;
240
275
  updateIntent(id: string, updates: UpdateIntentInput): Promise<ApiIntent>;
241
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.d.ts CHANGED
@@ -12,7 +12,7 @@
12
12
  * The Intent Compiler (compile-intent prompt, intent_save, intent_export tools)
13
13
  * works without an API key — zero-config intent spec building in Claude Code.
14
14
  *
15
- * Add to .claude/settings.json:
15
+ * Add to .mcp.json in the project root:
16
16
  * {
17
17
  * "mcpServers": {
18
18
  * "pathmode": {
package/dist/index.js CHANGED
@@ -5330,7 +5330,7 @@ module.exports = {
5330
5330
 
5331
5331
 
5332
5332
  const { parseSetCookie } = __nccwpck_require__(9000)
5333
- const { stringify, getHeadersList } = __nccwpck_require__(799)
5333
+ const { stringify } = __nccwpck_require__(799)
5334
5334
  const { webidl } = __nccwpck_require__(1523)
5335
5335
  const { Headers } = __nccwpck_require__(8526)
5336
5336
 
@@ -5406,14 +5406,13 @@ function getSetCookies (headers) {
5406
5406
 
5407
5407
  webidl.brandCheck(headers, Headers, { strict: false })
5408
5408
 
5409
- const cookies = getHeadersList(headers).cookies
5409
+ const cookies = headers.getSetCookie()
5410
5410
 
5411
5411
  if (!cookies) {
5412
5412
  return []
5413
5413
  }
5414
5414
 
5415
- // In older versions of undici, cookies is a list of name:value.
5416
- return cookies.map((pair) => parseSetCookie(Array.isArray(pair) ? pair[1] : pair))
5415
+ return cookies.map((pair) => parseSetCookie(pair))
5417
5416
  }
5418
5417
 
5419
5418
  /**
@@ -5841,14 +5840,15 @@ module.exports = {
5841
5840
  /***/ }),
5842
5841
 
5843
5842
  /***/ 799:
5844
- /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
5843
+ /***/ ((module) => {
5845
5844
 
5846
5845
  "use strict";
5847
5846
 
5848
5847
 
5849
- const assert = __nccwpck_require__(2613)
5850
- const { kHeadersList } = __nccwpck_require__(7506)
5851
-
5848
+ /**
5849
+ * @param {string} value
5850
+ * @returns {boolean}
5851
+ */
5852
5852
  function isCTLExcludingHtab (value) {
5853
5853
  if (value.length === 0) {
5854
5854
  return false
@@ -6109,31 +6109,13 @@ function stringify (cookie) {
6109
6109
  return out.join('; ')
6110
6110
  }
6111
6111
 
6112
- let kHeadersListNode
6113
-
6114
- function getHeadersList (headers) {
6115
- if (headers[kHeadersList]) {
6116
- return headers[kHeadersList]
6117
- }
6118
-
6119
- if (!kHeadersListNode) {
6120
- kHeadersListNode = Object.getOwnPropertySymbols(headers).find(
6121
- (symbol) => symbol.description === 'headers list'
6122
- )
6123
-
6124
- assert(kHeadersListNode, 'Headers cannot be parsed')
6125
- }
6126
-
6127
- const headersList = headers[kHeadersListNode]
6128
- assert(headersList)
6129
-
6130
- return headersList
6131
- }
6132
-
6133
6112
  module.exports = {
6134
6113
  isCTLExcludingHtab,
6135
- stringify,
6136
- getHeadersList
6114
+ validateCookieName,
6115
+ validateCookiePath,
6116
+ validateCookieValue,
6117
+ toIMFDate,
6118
+ stringify
6137
6119
  }
6138
6120
 
6139
6121
 
@@ -8062,6 +8044,14 @@ const { isUint8Array, isArrayBuffer } = __nccwpck_require__(8253)
8062
8044
  const { File: UndiciFile } = __nccwpck_require__(3044)
8063
8045
  const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(7845)
8064
8046
 
8047
+ let random
8048
+ try {
8049
+ const crypto = __nccwpck_require__(7598)
8050
+ random = (max) => crypto.randomInt(0, max)
8051
+ } catch {
8052
+ random = (max) => Math.floor(Math.random(max))
8053
+ }
8054
+
8065
8055
  let ReadableStream = globalThis.ReadableStream
8066
8056
 
8067
8057
  /** @type {globalThis['File']} */
@@ -8147,7 +8137,7 @@ function extractBody (object, keepalive = false) {
8147
8137
  // Set source to a copy of the bytes held by object.
8148
8138
  source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength))
8149
8139
  } else if (util.isFormDataLike(object)) {
8150
- const boundary = `----formdata-undici-0${`${Math.floor(Math.random() * 1e11)}`.padStart(11, '0')}`
8140
+ const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, '0')}`
8151
8141
  const prefix = `--${boundary}\r\nContent-Disposition: form-data`
8152
8142
 
8153
8143
  /*! formdata-polyfill. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> */
@@ -10129,6 +10119,7 @@ const {
10129
10119
  isValidHeaderName,
10130
10120
  isValidHeaderValue
10131
10121
  } = __nccwpck_require__(5182)
10122
+ const util = __nccwpck_require__(9023)
10132
10123
  const { webidl } = __nccwpck_require__(1523)
10133
10124
  const assert = __nccwpck_require__(2613)
10134
10125
 
@@ -10682,6 +10673,9 @@ Object.defineProperties(Headers.prototype, {
10682
10673
  [Symbol.toStringTag]: {
10683
10674
  value: 'Headers',
10684
10675
  configurable: true
10676
+ },
10677
+ [util.inspect.custom]: {
10678
+ enumerable: false
10685
10679
  }
10686
10680
  })
10687
10681
 
@@ -19858,6 +19852,20 @@ class Pool extends PoolBase {
19858
19852
  ? { ...options.interceptors }
19859
19853
  : undefined
19860
19854
  this[kFactory] = factory
19855
+
19856
+ this.on('connectionError', (origin, targets, error) => {
19857
+ // If a connection error occurs, we remove the client from the pool,
19858
+ // and emit a connectionError event. They will not be re-used.
19859
+ // Fixes https://github.com/nodejs/undici/issues/3895
19860
+ for (const target of targets) {
19861
+ // Do not use kRemoveClient here, as it will close the client,
19862
+ // but the client cannot be closed in this state.
19863
+ const idx = this[kClients].indexOf(target)
19864
+ if (idx !== -1) {
19865
+ this[kClients].splice(idx, 1)
19866
+ }
19867
+ }
19868
+ })
19861
19869
  }
19862
19870
 
19863
19871
  [kGetDispatcher] () {
@@ -33618,6 +33626,13 @@ class PathmodeClient {
33618
33626
  });
33619
33627
  return res.json();
33620
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
+ }
33621
33636
  async getWorkspace() {
33622
33637
  const res = await this.fetch('/workspace');
33623
33638
  return res.json();
@@ -33904,6 +33919,57 @@ exports.formatIntentMd = formatIntentMd;
33904
33919
  exports.formatCursorRules = formatCursorRules;
33905
33920
  exports.formatClaudeMdSection = formatClaudeMdSection;
33906
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
+ }
33907
33973
  /** Extract text from a string or structured outcome. */
33908
33974
  function getOutcomeText(o) {
33909
33975
  return typeof o === 'string' ? o : o.text;
@@ -34001,7 +34067,7 @@ WHEN THE SPEC FEELS READY AND ALL STATUS ITEMS ARE [X]:
34001
34067
  1. Present the full spec as a summary for the user to review
34002
34068
  2. Ask if they want to save it
34003
34069
  3. When confirmed, call the \`intent_save\` tool with the complete spec
34004
- 4. Ask if they also want to export it as \`.cursorrules\` or \`CLAUDE.md\` for AI agent consumption — if yes, call \`intent_export\`
34070
+ 4. Ask if they also want to export it as \`.cursorrules\`, \`CLAUDE.md\`, or \`AGENTS.md\` (Codex/Cursor) for AI agent consumption — if yes, call \`intent_export\`
34005
34071
  5. Mention: "For dependency tracking, team collaboration, and governance, connect this to Pathmode at pathmode.io"
34006
34072
 
34007
34073
  IMPORTANT:
@@ -34015,13 +34081,26 @@ IMPORTANT:
34015
34081
  - edgeCases: { scenario: string, expectedBehavior: string }[] (optional)
34016
34082
  - healthMetrics: string[] (optional)
34017
34083
  - scope: { inScope?: string[], outOfScope?: string[] } (optional)
34018
- - 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.
34019
34085
 
34020
34086
  Now, start the conversation. If they haven't provided one yet, ask for the concrete evidence (quote, metric, or ticket) driving this work.`;
34021
34087
  }
34022
34088
  // ============================================================
34023
34089
  // Format: intent.md
34024
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
+ }
34025
34104
  /**
34026
34105
  * Generate intent.md content with YAML frontmatter.
34027
34106
  * Adapted from lib/agentPromptGenerator.ts generateIntentMd().
@@ -34049,6 +34128,7 @@ function formatIntentMd(spec) {
34049
34128
  sections.push('## Objective');
34050
34129
  sections.push(spec.objective);
34051
34130
  }
34131
+ sections.push(...decisionLines(spec.decisions, '## Decisions & Ruled-Out Alternatives'));
34052
34132
  if (spec.outcomes?.length) {
34053
34133
  sections.push('');
34054
34134
  sections.push('## Outcomes');
@@ -34091,27 +34171,15 @@ function formatIntentMd(spec) {
34091
34171
  sections.push(`- ${metric}`);
34092
34172
  }
34093
34173
  }
34094
- if (spec.verification) {
34095
- const { e2eTests, unitTests, manualChecks } = spec.verification;
34096
- const hasContent = e2eTests?.length || unitTests?.length || manualChecks?.length;
34097
- if (hasContent) {
34098
- sections.push('');
34099
- sections.push('## Verification');
34100
- if (e2eTests?.length) {
34101
- sections.push('**E2E Tests**:');
34102
- for (const t of e2eTests)
34103
- sections.push(`- [ ] ${t}`);
34104
- }
34105
- if (unitTests?.length) {
34106
- sections.push('**Unit Tests**:');
34107
- for (const t of unitTests)
34108
- sections.push(`- [ ] ${t}`);
34109
- }
34110
- if (manualChecks?.length) {
34111
- sections.push('**Manual Checks**:');
34112
- for (const t of manualChecks)
34113
- sections.push(`- [ ] ${t}`);
34114
- }
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)}`);
34115
34183
  }
34116
34184
  }
34117
34185
  sections.push('');
@@ -34138,6 +34206,7 @@ function formatCursorRules(spec) {
34138
34206
  sections.push('# WHY');
34139
34207
  sections.push(spec.objective);
34140
34208
  }
34209
+ sections.push(...decisionLines(spec.decisions, '# DECISIONS (already settled — do not relitigate)'));
34141
34210
  if (spec.outcomes?.length) {
34142
34211
  sections.push('');
34143
34212
  sections.push('# SUCCESS OUTCOMES');
@@ -34184,25 +34253,15 @@ function formatCursorRules(spec) {
34184
34253
  sections.push(`- ${metric}`);
34185
34254
  }
34186
34255
  }
34187
- if (spec.verification) {
34188
- const { e2eTests, unitTests, manualChecks } = spec.verification;
34189
- const hasContent = e2eTests?.length || unitTests?.length || manualChecks?.length;
34190
- if (hasContent) {
34191
- sections.push('');
34192
- sections.push('# VERIFICATION');
34193
- sections.push('After implementation, verify:');
34194
- if (e2eTests?.length) {
34195
- for (const t of e2eTests)
34196
- sections.push(`- [e2e] ${t}`);
34197
- }
34198
- if (unitTests?.length) {
34199
- for (const t of unitTests)
34200
- sections.push(`- [unit] ${t}`);
34201
- }
34202
- if (manualChecks?.length) {
34203
- for (const t of manualChecks)
34204
- sections.push(`- [manual] ${t}`);
34205
- }
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)}`);
34206
34265
  }
34207
34266
  }
34208
34267
  sections.push('');
@@ -34228,6 +34287,7 @@ function formatClaudeMdSection(spec) {
34228
34287
  if (spec.objective) {
34229
34288
  sections.push(`**Objective**: ${spec.objective}`);
34230
34289
  }
34290
+ sections.push(...decisionLines(spec.decisions, '**Decisions**:'));
34231
34291
  if (spec.outcomes?.length) {
34232
34292
  sections.push('**Outcomes**:');
34233
34293
  sections.push(spec.outcomes.map(o => `- [ ] ${getPriorityLabel(o)}${getOutcomeText(o)}`).join('\n'));
@@ -34307,6 +34367,13 @@ function buildWriterDescription(spec) {
34307
34367
  sections.push('');
34308
34368
  sections.push(`Why this matters: ${spec.objective}`);
34309
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
+ }
34310
34377
  if (spec.scope?.inScope?.length) {
34311
34378
  sections.push('');
34312
34379
  sections.push('In scope:');
@@ -34391,17 +34458,9 @@ function buildGraderRubric(spec, opts = {}) {
34391
34458
  sections.push(`- ${c}`);
34392
34459
  }
34393
34460
  // Verification → procedures the grader must run to produce evidence
34394
- const v = spec.verification;
34395
34461
  const checks = [];
34396
- for (const t of v?.e2eTests ?? [])
34397
- if (t?.trim())
34398
- checks.push(`[e2e] ${t}`);
34399
- for (const t of v?.unitTests ?? [])
34400
- if (t?.trim())
34401
- checks.push(`[unit] ${t}`);
34402
- for (const t of v?.manualChecks ?? [])
34403
- if (t?.trim())
34404
- checks.push(`[manual] ${t}`);
34462
+ for (const c of toVerificationChecks(spec.verification))
34463
+ checks.push(`[${c.kind}] ${renderCheckLine(c)}`);
34405
34464
  for (const t of spec.implementationContext?.verificationSuggestions ?? [])
34406
34465
  if (t?.trim())
34407
34466
  checks.push(`[suggested] ${t}`);
@@ -34443,11 +34502,7 @@ function formatOutcomeRubric(spec, opts = {}) {
34443
34502
  const maxIterations = opts.maxIterations ?? 5;
34444
34503
  const description = buildWriterDescription(spec);
34445
34504
  const rubric = buildGraderRubric(spec, opts);
34446
- const hasVerification = [
34447
- ...(spec.verification?.e2eTests ?? []),
34448
- ...(spec.verification?.unitTests ?? []),
34449
- ...(spec.verification?.manualChecks ?? []),
34450
- ].some((t) => t?.trim());
34505
+ const hasVerification = toVerificationChecks(spec.verification).length > 0;
34451
34506
  const doc = [];
34452
34507
  doc.push('<!-- Pathmode → Claude Managed Agents: Outcomes rubric -->');
34453
34508
  doc.push(`<!-- Generated ${new Date().toISOString()} | pathmode.io -->`);
@@ -34677,6 +34732,58 @@ function extractVerification(body) {
34677
34732
  }
34678
34733
 
34679
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
+
34680
34787
  /***/ }),
34681
34788
 
34682
34789
  /***/ 8294:
@@ -34715,7 +34822,9 @@ function claudeDesktopPaths() {
34715
34822
  return [path_1.default.join(os_1.default.homedir(), '.config', 'Claude', 'claude_desktop_config.json')];
34716
34823
  }
34717
34824
  function claudeCodePaths() {
34718
- return [path_1.default.join(os_1.default.homedir(), '.claude', 'settings.json')];
34825
+ // Claude Code reads project-scoped MCP servers from .mcp.json in the
34826
+ // project root — not from .claude/settings.json or ~/.claude/settings.json.
34827
+ return [path_1.default.join(process.cwd(), '.mcp.json')];
34719
34828
  }
34720
34829
  function cursorPaths() {
34721
34830
  return [path_1.default.join(os_1.default.homedir(), '.cursor', 'mcp.json')];
@@ -34731,7 +34840,7 @@ function windsurfPaths() {
34731
34840
  return [path_1.default.join(os_1.default.homedir(), '.codeium', 'windsurf', 'mcp_config.json')];
34732
34841
  }
34733
34842
  const TOOLS = [
34734
- { name: 'Claude Code', paths: claudeCodePaths, configKey: 'mcpServers' },
34843
+ { name: 'Claude Code', paths: claudeCodePaths, configKey: 'mcpServers', omitApiKey: true },
34735
34844
  { name: 'Claude Desktop', paths: claudeDesktopPaths, configKey: 'mcpServers' },
34736
34845
  { name: 'Cursor', paths: cursorPaths, configKey: 'mcpServers' },
34737
34846
  { name: 'Windsurf', paths: windsurfPaths, configKey: 'mcpServers' },
@@ -34748,7 +34857,13 @@ function log(msg) { console.log(msg); }
34748
34857
  function success(msg) { console.log(` ${GREEN}✓${RESET} ${msg}`); }
34749
34858
  function warn(msg) { console.log(` ${YELLOW}!${RESET} ${msg}`); }
34750
34859
  function fail(msg) { console.log(` ${RED}✗${RESET} ${msg}`); }
34751
- function getMcpServerBlock(apiKey) {
34860
+ function getMcpServerBlock(apiKey, omitApiKey) {
34861
+ if (omitApiKey) {
34862
+ return {
34863
+ command: 'npx',
34864
+ args: ['@pathmode/mcp-server'],
34865
+ };
34866
+ }
34752
34867
  return {
34753
34868
  command: 'npx',
34754
34869
  args: ['@pathmode/mcp-server'],
@@ -34862,7 +34977,7 @@ async function runSetup() {
34862
34977
  const existingPath = possiblePaths.find(p => fs_1.default.existsSync(p));
34863
34978
  const configPath = existingPath || possiblePaths[0];
34864
34979
  // Only configure if the tool's config dir exists (tool is installed)
34865
- // Exception: Claude Code — always configure since ~/.claude/ may not exist yet
34980
+ // Exception: Claude Code — its .mcp.json lives in the project root, so always configure
34866
34981
  const configDir = path_1.default.dirname(configPath);
34867
34982
  const toolInstalled = tool.name === 'Claude Code' || fs_1.default.existsSync(configDir);
34868
34983
  if (!toolInstalled) {
@@ -34889,7 +35004,7 @@ async function runSetup() {
34889
35004
  if (!config[tool.configKey]) {
34890
35005
  config[tool.configKey] = {};
34891
35006
  }
34892
- config[tool.configKey].pathmode = getMcpServerBlock(apiKey);
35007
+ config[tool.configKey].pathmode = getMcpServerBlock(apiKey, tool.omitApiKey);
34893
35008
  if (writeJsonSafe(configPath, config)) {
34894
35009
  success(`${tool.name} → ${DIM}${shortenPath(configPath)}${RESET}`);
34895
35010
  configured++;
@@ -34911,7 +35026,7 @@ async function runSetup() {
34911
35026
  if (configured === 0) {
34912
35027
  log(`${YELLOW}No supported tools detected.${RESET} Add manually:`);
34913
35028
  log('');
34914
- log(` ${DIM}// .claude/settings.json, ~/.cursor/mcp.json, or claude_desktop_config.json${RESET}`);
35029
+ log(` ${DIM}// .mcp.json (project root), ~/.cursor/mcp.json, or claude_desktop_config.json${RESET}`);
34915
35030
  log(` ${CYAN}{${RESET}`);
34916
35031
  log(` ${CYAN} "mcpServers": {${RESET}`);
34917
35032
  log(` ${CYAN} "pathmode": {${RESET}`);
@@ -35020,6 +35135,14 @@ module.exports = require("net");
35020
35135
 
35021
35136
  /***/ }),
35022
35137
 
35138
+ /***/ 7598:
35139
+ /***/ ((module) => {
35140
+
35141
+ "use strict";
35142
+ module.exports = require("node:crypto");
35143
+
35144
+ /***/ }),
35145
+
35023
35146
  /***/ 8474:
35024
35147
  /***/ ((module) => {
35025
35148
 
@@ -64494,6 +64617,14 @@ module.exports = /*#__PURE__*/JSON.parse('{"$id":"https://raw.githubusercontent.
64494
64617
  "use strict";
64495
64618
  module.exports = /*#__PURE__*/JSON.parse('{"$schema":"http://json-schema.org/draft-07/schema#","$id":"http://json-schema.org/draft-07/schema#","title":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"allOf":[{"$ref":"#/definitions/nonNegativeInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}},"type":["object","boolean"],"properties":{"$id":{"type":"string","format":"uri-reference"},"$schema":{"type":"string","format":"uri"},"$ref":{"type":"string","format":"uri-reference"},"$comment":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"default":true,"readOnly":{"type":"boolean","default":false},"examples":{"type":"array","items":true},"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/definitions/nonNegativeInteger"},"minLength":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"$ref":"#"},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":true},"maxItems":{"$ref":"#/definitions/nonNegativeInteger"},"minItems":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"contains":{"$ref":"#"},"maxProperties":{"$ref":"#/definitions/nonNegativeInteger"},"minProperties":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"$ref":"#"},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"propertyNames":{"format":"regex"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"propertyNames":{"$ref":"#"},"const":true,"enum":{"type":"array","items":true,"minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"contentMediaType":{"type":"string"},"contentEncoding":{"type":"string"},"if":{"$ref":"#"},"then":{"$ref":"#"},"else":{"$ref":"#"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"default":true}');
64496
64619
 
64620
+ /***/ }),
64621
+
64622
+ /***/ 8330:
64623
+ /***/ ((module) => {
64624
+
64625
+ "use strict";
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"}}');
64627
+
64497
64628
  /***/ })
64498
64629
 
64499
64630
  /******/ });
@@ -64554,7 +64685,7 @@ var exports = __webpack_exports__;
64554
64685
  * The Intent Compiler (compile-intent prompt, intent_save, intent_export tools)
64555
64686
  * works without an API key — zero-config intent spec building in Claude Code.
64556
64687
  *
64557
- * Add to .claude/settings.json:
64688
+ * Add to .mcp.json in the project root:
64558
64689
  * {
64559
64690
  * "mcpServers": {
64560
64691
  * "pathmode": {
@@ -64587,8 +64718,13 @@ const fs_1 = __nccwpck_require__(9896);
64587
64718
  const api_client_1 = __nccwpck_require__(7475);
64588
64719
  const local_reader_1 = __nccwpck_require__(3518);
64589
64720
  const intent_compiler_1 = __nccwpck_require__(6488);
64721
+ const pathmode_section_1 = __nccwpck_require__(4681);
64590
64722
  const setup_1 = __nccwpck_require__(8294);
64591
64723
  const install_skills_1 = __nccwpck_require__(3783);
64724
+ // Server version is sourced from package.json so the version reported to MCP
64725
+ // clients always matches the published package. ncc statically resolves this
64726
+ // require() and inlines the JSON at build time (no runtime fs read).
64727
+ const { version: SERVER_VERSION } = __nccwpck_require__(8330);
64592
64728
  // ─── Subcommand routing ───────────────────────────────────────
64593
64729
  // Human-readable subcommands (`setup`, `install-skills`) use stdout
64594
64730
  // and must run before StdioServerTransport claims stdout for JSON-RPC.
@@ -64628,7 +64764,7 @@ function startMcpServer() {
64628
64764
  // ============================================================
64629
64765
  const server = new mcp_js_1.McpServer({
64630
64766
  name: 'pathmode',
64631
- version: '1.4.5',
64767
+ version: SERVER_VERSION,
64632
64768
  });
64633
64769
  // Annotation presets
64634
64770
  const READ_ONLY = { readOnlyHint: true, openWorldHint: true };
@@ -64646,6 +64782,22 @@ function startMcpServer() {
64646
64782
  function normalizeText(value) {
64647
64783
  return (value || '').trim();
64648
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
+ }
64649
64801
  // Keep this selection heuristic aligned with the canonical readiness rules in
64650
64802
  // /Users/jannelammi/code/Pathmode/lib/intentReadiness.ts. The MCP package cannot
64651
64803
  // import app/lib code directly, so this mirrors only the minimum logic needed
@@ -64665,6 +64817,24 @@ function startMcpServer() {
64665
64817
  return anyReady;
64666
64818
  return intents[0];
64667
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
+ }
64668
64838
  // Note: The MCP SDK catches errors thrown in tool handlers and returns them as
64669
64839
  // error text results. CloudClientError thrown by requireCloudClient() will
64670
64840
  // surface its message to the client without crashing the server.
@@ -64673,10 +64843,13 @@ function startMcpServer() {
64673
64843
  // ============================================================
64674
64844
  server.registerTool('get_current_intent', {
64675
64845
  title: 'Get Current Intent',
64676
- 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.',
64677
- 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
+ },
64678
64851
  annotations: READ_ONLY,
64679
- }, async ({ status }) => {
64852
+ }, async ({ status, include_evidence }) => {
64680
64853
  if (isLocalMode) {
64681
64854
  const intents = (0, local_reader_1.readLocalIntents)();
64682
64855
  const filtered = status ? intents.filter(i => i.status === status) : intents;
@@ -64684,18 +64857,47 @@ function startMcpServer() {
64684
64857
  if (!current) {
64685
64858
  return { content: [{ type: 'text', text: 'No intents found locally.' }] };
64686
64859
  }
64860
+ // Local mode has no cloud evidence store — return the intent as-is.
64687
64861
  return { content: [{ type: 'text', text: JSON.stringify(current, null, 2) }] };
64688
64862
  }
64689
64863
  const cloud = requireCloudClient();
64690
- const intents = await cloud.listIntents(status || 'approved');
64864
+ let intents = await cloud.listIntents(status || 'approved');
64691
64865
  if (intents.length === 0) {
64692
- const allIntents = await cloud.listIntents();
64693
- if (allIntents.length === 0) {
64866
+ intents = await cloud.listIntents();
64867
+ if (intents.length === 0) {
64694
64868
  return { content: [{ type: 'text', text: 'No intents found in workspace.' }] };
64695
64869
  }
64696
- return { content: [{ type: 'text', text: JSON.stringify(pickCurrentIntent(allIntents), null, 2) }] };
64697
64870
  }
64698
- 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) }] };
64699
64901
  });
64700
64902
  server.registerTool('list_intents', {
64701
64903
  title: 'List Intents',
@@ -64724,7 +64926,7 @@ function startMcpServer() {
64724
64926
  });
64725
64927
  server.registerTool('get_intent', {
64726
64928
  title: 'Get Intent',
64727
- 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.',
64728
64930
  inputSchema: { intentId: zod_1.z.string().describe('The intent ID to fetch') },
64729
64931
  annotations: READ_ONLY,
64730
64932
  }, async ({ intentId }) => {
@@ -64993,27 +65195,29 @@ function startMcpServer() {
64993
65195
  });
64994
65196
  /** Map a cloud ApiIntent into the IntentFields shape the formatters consume. */
64995
65197
  function apiIntentToFields(intent) {
64996
- const v = (intent.verification || {});
64997
65198
  return {
64998
65199
  id: intent.id,
64999
65200
  title: intent.title,
65000
65201
  objective: intent.objective,
65001
65202
  outcomes: intent.outcomes ?? [],
65203
+ decisions: intent.decisions,
65002
65204
  constraints: intent.constraints,
65003
65205
  edgeCases: (intent.edgeCases ?? []).map((e) => ({ scenario: e.scenario, expectedBehavior: e.expectedBehavior })),
65004
65206
  healthMetrics: intent.healthMetrics,
65005
65207
  scope: intent.scope,
65006
- 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),
65007
65211
  implementationContext: intent.implementationContext ?? undefined,
65008
65212
  };
65009
65213
  }
65010
65214
  server.registerTool('export_context', {
65011
65215
  title: 'Export Context',
65012
- 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.',
65013
65217
  inputSchema: {
65014
- 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'),
65015
65219
  intentId: zod_1.z.string().optional().describe('Intent ID (optional, for cursorrules and intent-md)'),
65016
- 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)'),
65017
65221
  },
65018
65222
  annotations: READ_ONLY,
65019
65223
  }, async ({ format, intentId, productId }) => {
@@ -65047,6 +65251,41 @@ function startMcpServer() {
65047
65251
  return { content: [{ type: 'text', text: `Export failed: ${e.message}` }] };
65048
65252
  }
65049
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
+ });
65050
65289
  server.registerTool('get_agent_prompt', {
65051
65290
  title: 'Get Agent Prompt',
65052
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.',
@@ -65151,6 +65390,31 @@ function startMcpServer() {
65151
65390
  }]
65152
65391
  };
65153
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
+ });
65154
65418
  server.registerTool('create_intent', {
65155
65419
  title: 'Create Intent',
65156
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.',
@@ -65166,6 +65430,12 @@ function startMcpServer() {
65166
65430
  expectedBehavior: zod_1.z.string(),
65167
65431
  })).optional().describe('Failure modes and boundary conditions'),
65168
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)'),
65169
65439
  manualChecks: zod_1.z.array(zod_1.z.string()).optional(),
65170
65440
  unitTests: zod_1.z.array(zod_1.z.string()).optional(),
65171
65441
  e2eTests: zod_1.z.array(zod_1.z.string()).optional(),
@@ -65200,6 +65470,12 @@ function startMcpServer() {
65200
65470
  expectedBehavior: zod_1.z.string(),
65201
65471
  })).optional().describe('Replace all edge cases'),
65202
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)'),
65203
65479
  manualChecks: zod_1.z.array(zod_1.z.string()).optional(),
65204
65480
  unitTests: zod_1.z.array(zod_1.z.string()).optional(),
65205
65481
  e2eTests: zod_1.z.array(zod_1.z.string()).optional(),
@@ -65382,6 +65658,11 @@ function startMcpServer() {
65382
65658
  title: zod_1.z.string().describe('Short name for the intent'),
65383
65659
  objective: zod_1.z.string().describe('Why this matters — the problem and who has it'),
65384
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'),
65385
65666
  constraints: zod_1.z.array(zod_1.z.string()).optional().describe('Hard limits the implementation must respect'),
65386
65667
  edgeCases: zod_1.z.array(zod_1.z.object({
65387
65668
  scenario: zod_1.z.string(),
@@ -65393,6 +65674,12 @@ function startMcpServer() {
65393
65674
  outOfScope: zod_1.z.array(zod_1.z.string()).optional().describe('What is explicitly out of scope'),
65394
65675
  }).optional().describe('Scope boundaries — what to build and what to avoid'),
65395
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)'),
65396
65683
  manualChecks: zod_1.z.array(zod_1.z.string()).optional(),
65397
65684
  unitTests: zod_1.z.array(zod_1.z.string()).optional(),
65398
65685
  e2eTests: zod_1.z.array(zod_1.z.string()).optional(),
@@ -65411,9 +65698,9 @@ function startMcpServer() {
65411
65698
  });
65412
65699
  server.tool('intent_save', 'Save an intent spec to intent.md in the project root. Called after building a spec through conversation.', {
65413
65700
  spec: zod_1.z.object(intentSpecSchema),
65414
- 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'),
65415
65702
  }, async ({ spec, path }) => {
65416
- const filePath = (0, path_1.resolve)(process.cwd(), path || 'intent.md');
65703
+ const filePath = resolveWithinProject(path || 'intent.md');
65417
65704
  const content = (0, intent_compiler_1.formatIntentMd)({ ...spec, id: `intent_${Date.now()}` });
65418
65705
  (0, fs_1.writeFileSync)(filePath, content, 'utf-8');
65419
65706
  return {
@@ -65423,14 +65710,14 @@ function startMcpServer() {
65423
65710
  }],
65424
65711
  };
65425
65712
  });
65426
- server.tool('intent_export', 'Export an intent spec as .cursorrules, a CLAUDE.md section, or a Claude Managed Agents Outcomes rubric for AI agent consumption.', {
65427
- format: zod_1.z.enum(['cursorrules', 'claude-md', 'outcome-rubric']).describe('Export format'),
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.', {
65714
+ format: zod_1.z.enum(['cursorrules', 'claude-md', 'agents-md', 'outcome-rubric']).describe('Export format'),
65428
65715
  spec: zod_1.z.object(intentSpecSchema),
65429
- path: zod_1.z.string().optional().describe('Output file path. Defaults to .cursorrules or CLAUDE.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'),
65430
65717
  }, async ({ format, spec, path }) => {
65431
65718
  if (format === 'cursorrules') {
65432
65719
  const content = (0, intent_compiler_1.formatCursorRules)(spec);
65433
- const filePath = (0, path_1.resolve)(process.cwd(), path || '.cursorrules');
65720
+ const filePath = resolveWithinProject(path || '.cursorrules');
65434
65721
  (0, fs_1.writeFileSync)(filePath, content, 'utf-8');
65435
65722
  return {
65436
65723
  content: [{
@@ -65441,7 +65728,7 @@ function startMcpServer() {
65441
65728
  }
65442
65729
  else if (format === 'outcome-rubric') {
65443
65730
  const content = (0, intent_compiler_1.formatOutcomeRubric)(spec);
65444
- const filePath = (0, path_1.resolve)(process.cwd(), path || 'outcome-rubric.md');
65731
+ const filePath = resolveWithinProject(path || 'outcome-rubric.md');
65445
65732
  (0, fs_1.writeFileSync)(filePath, content, 'utf-8');
65446
65733
  return {
65447
65734
  content: [{
@@ -65452,25 +65739,25 @@ function startMcpServer() {
65452
65739
  }
65453
65740
  else {
65454
65741
  const section = (0, intent_compiler_1.formatClaudeMdSection)(spec);
65455
- const filePath = (0, path_1.resolve)(process.cwd(), path || 'CLAUDE.md');
65456
- // Append or replace PATHMODE section in existing file
65742
+ const defaultFile = format === 'agents-md' ? 'AGENTS.md' : 'CLAUDE.md';
65743
+ const filePath = resolveWithinProject(path || defaultFile);
65457
65744
  let existing = '';
65458
65745
  try {
65459
65746
  existing = (0, fs_1.readFileSync)(filePath, 'utf-8');
65460
65747
  }
65461
65748
  catch { /* file doesn't exist yet */ }
65462
- // Tolerant of the suffixed start marker emitted by formatClaudeMdSection
65463
- // (`<!-- PATHMODE:START - Do not edit... -->`), so re-exports replace
65464
- // the block instead of appending a duplicate.
65465
- const marker = /<!-- PATHMODE:START[\s\S]*?-->[\s\S]*?<!-- PATHMODE:END -->/;
65466
- const updated = marker.test(existing)
65467
- ? existing.replace(marker, section)
65468
- : existing ? existing + '\n\n' + section : section;
65469
- (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');
65752
+ const audience = format === 'agents-md'
65753
+ ? 'Codex, Cursor, and other AGENTS.md-aware agents'
65754
+ : 'Claude Code';
65470
65755
  return {
65471
65756
  content: [{
65472
65757
  type: 'text',
65473
- text: `✓ Exported CLAUDE.md section to ${filePath}\n\nClaude Code 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.`,
65474
65761
  }],
65475
65762
  };
65476
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":"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"}
@@ -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":""}
@@ -1 +1 @@
1
- {"version":3,"file":"","sourceRoot":"","sources":["file:///Users/jannelammi/code/Pathmode/packages/mcp-server/src/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAiHH,wBAAgB,YAAY,CAAC,IAAI,WAAe,GAAG,MAAM,EAAE,CAG1D;AAED,wBAAgB,cAAc,CAAC,IAAI,WAAe,GAAG,OAAO,CAE3D;AAID,wBAAsB,QAAQ,kBAsJ7B"}
1
+ {"version":3,"file":"","sourceRoot":"","sources":["file:///Users/jannelammi/code/Pathmode/packages/mcp-server/src/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA0HH,wBAAgB,YAAY,CAAC,IAAI,WAAe,GAAG,MAAM,EAAE,CAG1D;AAED,wBAAgB,cAAc,CAAC,IAAI,WAAe,GAAG,OAAO,CAE3D;AAID,wBAAsB,QAAQ,kBAsJ7B"}
package/manifest.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "manifest_version": "0.3",
3
3
  "name": "pathmode",
4
4
  "display_name": "Pathmode",
5
- "version": "1.5.0",
5
+ "version": "1.7.0",
6
6
  "description": "Build structured intent specs through Socratic AI conversation, or connect to your Intent Layer for strategic context and dependency graphs.",
7
7
  "long_description": "Pathmode MCP Server includes the Intent Compiler — a zero-config Socratic conversation that helps you build structured intent specs (objectives, outcomes, constraints, edge cases) right in Claude Code. No signup needed. For teams, connect to your Pathmode workspace for dependency graph analysis (critical path, bottlenecks, cycles), workspace strategy context, and governance — so AI agents build the right thing, not just any thing.",
8
8
  "author": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pathmode/mcp-server",
3
- "version": "1.6.0",
3
+ "version": "1.8.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },