@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 +5 -5
- package/dist/api-client.d.ts +36 -1
- package/dist/api-client.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +416 -129
- package/dist/intent-compiler.d.ts +22 -0
- package/dist/intent-compiler.d.ts.map +1 -1
- package/dist/pathmode-section.d.ts +22 -0
- package/dist/pathmode-section.d.ts.map +1 -0
- package/dist/pathmode-section.test.d.ts +1 -0
- package/dist/pathmode-section.test.d.ts.map +1 -0
- package/dist/setup.d.ts.map +1 -1
- package/manifest.json +1 -1
- package/package.json +1 -1
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 `
|
|
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 `.
|
|
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 `
|
|
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 (`.
|
|
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 |
|
package/dist/api-client.d.ts
CHANGED
|
@@ -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<{
|
package/dist/api-client.d.ts.map
CHANGED
|
@@ -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 .
|
|
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
|
|
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 =
|
|
5409
|
+
const cookies = headers.getSetCookie()
|
|
5410
5410
|
|
|
5411
5411
|
if (!cookies) {
|
|
5412
5412
|
return []
|
|
5413
5413
|
}
|
|
5414
5414
|
|
|
5415
|
-
|
|
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
|
|
5843
|
+
/***/ ((module) => {
|
|
5845
5844
|
|
|
5846
5845
|
"use strict";
|
|
5847
5846
|
|
|
5848
5847
|
|
|
5849
|
-
|
|
5850
|
-
|
|
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
|
-
|
|
6136
|
-
|
|
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${`${
|
|
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 \`
|
|
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: {
|
|
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
|
-
|
|
34095
|
-
|
|
34096
|
-
|
|
34097
|
-
|
|
34098
|
-
|
|
34099
|
-
|
|
34100
|
-
|
|
34101
|
-
|
|
34102
|
-
|
|
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
|
-
|
|
34188
|
-
|
|
34189
|
-
|
|
34190
|
-
|
|
34191
|
-
|
|
34192
|
-
|
|
34193
|
-
sections.push(
|
|
34194
|
-
|
|
34195
|
-
|
|
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
|
|
34397
|
-
|
|
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
|
-
|
|
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 —
|
|
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}// .
|
|
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 .
|
|
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:
|
|
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
|
|
64677
|
-
inputSchema: {
|
|
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
|
-
|
|
64864
|
+
let intents = await cloud.listIntents(status || 'approved');
|
|
64691
64865
|
if (intents.length === 0) {
|
|
64692
|
-
|
|
64693
|
-
if (
|
|
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
|
-
|
|
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
|
|
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
|
|
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 = (
|
|
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
|
|
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 = (
|
|
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 = (
|
|
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
|
|
65456
|
-
|
|
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
|
-
|
|
65463
|
-
|
|
65464
|
-
|
|
65465
|
-
const
|
|
65466
|
-
|
|
65467
|
-
|
|
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:
|
|
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;
|
|
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":""}
|
package/dist/setup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"","sourceRoot":"","sources":["file:///Users/jannelammi/code/Pathmode/packages/mcp-server/src/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
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
|
+
"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": {
|