@pathmode/mcp-server 1.26.3 → 1.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -39218,10 +39218,13 @@ module.exports = function(str) {
39218
39218
  * the results in as plain data.
39219
39219
  */
39220
39220
  Object.defineProperty(exports, "__esModule", ({ value: true }));
39221
+ exports.GENERATED_CAPTIONS = exports.VERIFICATION_NOT_DEFINED_CAPTION = exports.VERIFICATION_FEEDBACK_CAPTION = void 0;
39221
39222
  exports.renderOutcomeMeasurementDefinition = renderOutcomeMeasurementDefinition;
39222
39223
  exports.toSerializableChecks = toSerializableChecks;
39223
39224
  exports.renderAuthorizationGateText = renderAuthorizationGateText;
39224
39225
  exports.renderConfirmationsBody = renderConfirmationsBody;
39226
+ exports.normalizeCaption = normalizeCaption;
39227
+ exports.isGeneratedCaption = isGeneratedCaption;
39225
39228
  exports.serializeIntentMd = serializeIntentMd;
39226
39229
  // ── Small helpers ───────────────────────────────────────────────────────────
39227
39230
  const VERIFICATION_KIND_LABELS = {
@@ -39378,6 +39381,38 @@ const FRONTMATTER_ORDER = [
39378
39381
  'origin', 'authorization', 'authorizationNote', 'outcomeMeasurements',
39379
39382
  'evidence', 'space', 'severity', 'created', 'updated',
39380
39383
  ];
39384
+ /**
39385
+ * Captions this codebase writes into an intent.md, as opposed to anything an author wrote.
39386
+ *
39387
+ * A caption is prose under a heading that is NOT content: it explains the section rather than
39388
+ * recording a decision. The readers exclude exactly these strings, which is why they live here,
39389
+ * next to the code that emits them, and are imported rather than retyped. Excluding "all italic
39390
+ * prose" instead was wrong: an author writing `*Must not slow down page load.*` under
39391
+ * Constraints means it, and reporting that section as absent is the accusation the four-state
39392
+ * gate exists to stop making.
39393
+ *
39394
+ * Adding a caption anywhere means adding it here, or the reader will grade it as content.
39395
+ */
39396
+ exports.VERIFICATION_FEEDBACK_CAPTION = '_A feedback loop, not just a test list._';
39397
+ /** Written by lib/scan/draftIntentMd.ts when a pre-account draft has no verification yet. */
39398
+ exports.VERIFICATION_NOT_DEFINED_CAPTION = '_Not defined yet. Nothing in this spec has been checked against a running system._';
39399
+ exports.GENERATED_CAPTIONS = [
39400
+ exports.VERIFICATION_FEEDBACK_CAPTION,
39401
+ exports.VERIFICATION_NOT_DEFINED_CAPTION,
39402
+ ];
39403
+ /** Trim, drop one layer of surrounding `_` or `*`, casefold. Both emphasis spellings match. */
39404
+ function normalizeCaption(line) {
39405
+ return line
39406
+ .trim()
39407
+ .replace(/^([_*])(.*)\1$/s, '$2')
39408
+ .trim()
39409
+ .toLowerCase();
39410
+ }
39411
+ const NORMALIZED_CAPTIONS = new Set(exports.GENERATED_CAPTIONS.map(normalizeCaption));
39412
+ /** True only for a caption this codebase generated. Author prose, italic or not, is content. */
39413
+ function isGeneratedCaption(line) {
39414
+ return NORMALIZED_CAPTIONS.has(normalizeCaption(line));
39415
+ }
39381
39416
  function serializeIntentMd(spec, opts = {}) {
39382
39417
  const outcomeMeasurements = (spec.outcomes || [])
39383
39418
  .map(outcomeOf)
@@ -39531,7 +39566,7 @@ function serializeIntentMd(spec, opts = {}) {
39531
39566
  if (checkGroups.length) {
39532
39567
  sections.push('');
39533
39568
  sections.push('## Verification');
39534
- sections.push('_A feedback loop, not just a test list._');
39569
+ sections.push(exports.VERIFICATION_FEEDBACK_CAPTION);
39535
39570
  for (const g of checkGroups) {
39536
39571
  sections.push(`**${g.label}**:`);
39537
39572
  for (const c of g.checks)
@@ -41180,6 +41215,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
41180
41215
  return (mod && mod.__esModule) ? mod : { "default": mod };
41181
41216
  };
41182
41217
  Object.defineProperty(exports, "__esModule", ({ value: true }));
41218
+ exports.parseFrontmatter = parseFrontmatter;
41183
41219
  exports.readLocalIntents = readLocalIntents;
41184
41220
  exports.readIntentMeta = readIntentMeta;
41185
41221
  exports.readIntentFile = readIntentFile;
@@ -41189,6 +41225,58 @@ const fs_1 = __importDefault(__nccwpck_require__(9896));
41189
41225
  const path_1 = __importDefault(__nccwpck_require__(6928));
41190
41226
  const gray_matter_1 = __importDefault(__nccwpck_require__(9599));
41191
41227
  const measurement_schema_1 = __nccwpck_require__(1635);
41228
+ const serializeIntentMd_1 = __nccwpck_require__(229);
41229
+ /**
41230
+ * The ONLY front matter parser in the CLI and MCP server. Every `matter()` call routes through
41231
+ * here; do not call gray-matter directly.
41232
+ *
41233
+ * gray-matter lets the *document* pick its parser: a file opening `---js` is handed to the
41234
+ * javascript engine and **evaluated at parse time**. Both entry points read files the user does
41235
+ * not control — `pathmode preflight` runs on any repo and advertises that it only reads, and
41236
+ * `check_intent_readiness` is annotated READ_ONLY so agent clients auto-approve it. So a hostile
41237
+ * `intent.md` meant arbitrary code execution with the developer's own privileges.
41238
+ *
41239
+ * Two layers, because either alone is escapable:
41240
+ * 1. Reject the language token before gray-matter sees the document. This is an allowlist, so a
41241
+ * newly-registered engine cannot reopen the hole.
41242
+ * 2. Override the javascript engines anyway, in case a delimiter form reaches them another way.
41243
+ *
41244
+ * Non-YAML front matter throws rather than parsing as empty: silently dropping it would let a
41245
+ * crafted file blank its own identity and slip past intent_save's different-id collision guard.
41246
+ */
41247
+ const ALLOWED_FRONTMATTER_LANGUAGES = new Set(['', 'yaml', 'yml', 'json']);
41248
+ function refuseEngine() {
41249
+ throw new Error('Refusing to parse executable front matter: only YAML and JSON front matter is supported.');
41250
+ }
41251
+ /**
41252
+ * The language token on the opening delimiter, lowercased, or null when the document has no
41253
+ * front matter at all. Mirrors gray-matter's own tokenising, including the cases that surprised
41254
+ * us: a BOM still opens front matter, `\r\n` leaves a stray `\r`, and `---JS` / `---<tab>js` both
41255
+ * resolve to the javascript engine. Leading whitespace or a fourth dash do NOT open front matter.
41256
+ */
41257
+ function detectFrontmatterLanguage(content) {
41258
+ const withoutBom = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;
41259
+ if (!withoutBom.startsWith('---'))
41260
+ return null;
41261
+ // A fourth dash means this is a horizontal rule, not a delimiter. gray-matter bails on the
41262
+ // same test (index.js: `if (str.charAt(openLen) === open.slice(-1)) return file`), and the
41263
+ // guard has to agree with it: reading `----js` as the language `-js` would refuse a document
41264
+ // gray-matter parses happily, breaking valid files instead of hostile ones.
41265
+ if (withoutBom.charAt(3) === '-')
41266
+ return null;
41267
+ const lineEnd = withoutBom.indexOf('\n');
41268
+ const firstLine = lineEnd === -1 ? withoutBom : withoutBom.slice(0, lineEnd);
41269
+ return firstLine.slice(3).replace(/\r$/, '').trim().toLowerCase();
41270
+ }
41271
+ function parseFrontmatter(content) {
41272
+ const language = detectFrontmatterLanguage(content);
41273
+ if (language !== null && !ALLOWED_FRONTMATTER_LANGUAGES.has(language)) {
41274
+ throw new Error(`Refusing to parse "${language}" front matter: only YAML and JSON front matter is supported.`);
41275
+ }
41276
+ return (0, gray_matter_1.default)(content, {
41277
+ engines: { javascript: refuseEngine, js: refuseEngine },
41278
+ });
41279
+ }
41192
41280
  const CONFIRMATION_HEADER_RE = /^\*\*(objective|outcomes)\*\*\s*[—–-]\s*(confirmed|waived)\s+by\s+(agent|human)\s*$/i;
41193
41281
  const CONFIRMATION_FIELD_RE = /^\s*[-*]\s+(actor|problem|outcome|observable|reason|anchor|at)\s*:\s*(.+)$/i;
41194
41282
  /**
@@ -41258,7 +41346,7 @@ function readIntentMeta(filePath) {
41258
41346
  if (!fs_1.default.existsSync(filePath))
41259
41347
  return null;
41260
41348
  try {
41261
- const { data } = (0, gray_matter_1.default)(fs_1.default.readFileSync(filePath, 'utf-8'));
41349
+ const { data } = parseFrontmatter(fs_1.default.readFileSync(filePath, 'utf-8'));
41262
41350
  const version = Number(data.version);
41263
41351
  return {
41264
41352
  id: typeof data.id === 'string' && data.id.trim() ? data.id.trim() : null,
@@ -41359,10 +41447,9 @@ function frontmatterEdgeCases(v) {
41359
41447
  .filter((e) => e.scenario || e.expectedBehavior);
41360
41448
  }
41361
41449
  function parseIntentMarkdown(content, fallbackId = 'intent') {
41362
- const { data, content: rawBody } = (0, gray_matter_1.default)(content);
41450
+ const { data, content: rawBody } = parseFrontmatter(content);
41363
41451
  const body = stripHtmlComments(stripFencedBlocks(rawBody));
41364
41452
  const sections = splitSections(body);
41365
- const parsedVerification = extractVerification(sections);
41366
41453
  // The public schema allows verification as a flat string array; read it as manual checks
41367
41454
  // rather than silently producing {} (the same adapter normalizeSpecForReadiness applies).
41368
41455
  const frontmatterVerification = Array.isArray(data.verification)
@@ -41370,9 +41457,16 @@ function parseIntentMarkdown(content, fallbackId = 'intent') {
41370
41457
  : data.verification && typeof data.verification === 'object'
41371
41458
  ? data.verification
41372
41459
  : null;
41373
- const verification = hasVerificationContent(parsedVerification)
41374
- ? parsedVerification
41375
- : (frontmatterVerification || {});
41460
+ // Same precedence as every other section: body list, then frontmatter, then body prose.
41461
+ const verificationAll = extractVerification(sections);
41462
+ const verificationHasList = hasVerificationContent(extractVerification(sections, { includeProse: false }));
41463
+ const verification = verificationHasList
41464
+ ? verificationAll
41465
+ : frontmatterVerification && hasVerificationContent(frontmatterVerification)
41466
+ ? frontmatterVerification
41467
+ : hasVerificationContent(verificationAll)
41468
+ ? verificationAll
41469
+ : (frontmatterVerification || {});
41376
41470
  const version = Number(data.version);
41377
41471
  return {
41378
41472
  id: data.id || fallbackId,
@@ -41384,11 +41478,19 @@ function parseIntentMarkdown(content, fallbackId = 'intent') {
41384
41478
  title: data.title || data.userGoal || extractTitle(body) || 'Untitled Intent',
41385
41479
  stageName: data.stage || undefined,
41386
41480
  severity: data.severity || undefined,
41387
- outcomes: attachOutcomeMeasurements(preferSection(extractListSection(sections, 'Outcomes'), data.outcomes), data.outcomeMeasurements),
41481
+ outcomes: attachOutcomeMeasurements(preferListThenFrontmatter(sections, 'Outcomes', data.outcomes), data.outcomeMeasurements),
41388
41482
  decisions: extractDecisions(sections),
41389
- constraints: preferSection(extractListSection(sections, 'Constraints'), data.constraints),
41390
- edgeCases: (() => { const fromBody = extractEdgeCases(sections); return fromBody.length ? fromBody : frontmatterEdgeCases(data.edgeCases); })(),
41391
- healthMetrics: preferSection(extractListSection(sections, 'Health Metrics'), data.healthMetrics),
41483
+ constraints: preferListThenFrontmatter(sections, 'Constraints', data.constraints),
41484
+ edgeCases: (() => {
41485
+ const all = extractEdgeCases(sections);
41486
+ if (extractEdgeCases(sections, { includeProse: false }).length)
41487
+ return all;
41488
+ const fromFrontmatter = frontmatterEdgeCases(data.edgeCases);
41489
+ if (fromFrontmatter.length)
41490
+ return fromFrontmatter;
41491
+ return all;
41492
+ })(),
41493
+ healthMetrics: preferListThenFrontmatter(sections, 'Health Metrics', data.healthMetrics),
41392
41494
  scope: extractScope(sections) || undefined,
41393
41495
  verification,
41394
41496
  confirmations: extractConfirmations(sections),
@@ -41502,17 +41604,115 @@ function stripListMarker(line) {
41502
41604
  function isListItem(line) {
41503
41605
  return /^\s*[-*]\s/.test(line);
41504
41606
  }
41505
- function extractListSection(sections, heading) {
41506
- return sectionLines(sections, heading)
41507
- .filter(isListItem)
41508
- .map(stripListMarker)
41509
- .filter(Boolean);
41607
+ /**
41608
+ * Structure and generated captions are not content; everything else under a heading is.
41609
+ *
41610
+ * Two distinct exclusions, and they are not the same rule:
41611
+ *
41612
+ * A heading line is structure. `splitSections` only opens a section on `^## `, so a `### Regression
41613
+ * checks` subheading falls through as a body line, and treating it as prose made the HEADING an
41614
+ * executable check: a `## Verification` containing nothing but subheadings passed the gate.
41615
+ *
41616
+ * A generated caption is ours, not the author's, and the registry in serializeIntentMd.ts names
41617
+ * exactly which strings those are. This deliberately does NOT exclude all italic prose: an author
41618
+ * writing `*Must not slow down page load.*` under Constraints means it, and reporting that section
41619
+ * as absent is the accusation the four-state gate exists to stop making.
41620
+ */
41621
+ function isNotContent(line) {
41622
+ return /^#{1,6}\s/.test(line.trim()) || (0, serializeIntentMd_1.isGeneratedCaption)(line);
41623
+ }
41624
+ /**
41625
+ * Items in a section, preserving what the author actually wrote.
41626
+ *
41627
+ * List items keep their existing boundaries: one item per marker, with an indented
41628
+ * continuation line folded into the item it wraps. A run of unindented non-list lines is one
41629
+ * paragraph, and one paragraph is one item; blank lines separate paragraphs. Prose is never
41630
+ * split into sentences, so an author who writes two independently checkable outcomes as two
41631
+ * paragraphs gets two items and one who writes them as a single block gets one.
41632
+ *
41633
+ * Before this, a `.filter(isListItem)` dropped every prose line here and the gates then
41634
+ * reported the section as `absent`, which told an author who had written a constraint in prose
41635
+ * that they had written nothing. Preserving the text is what lets readiness say `unconfirmed`
41636
+ * and quote it back instead. The gates themselves are unchanged: nothing about the parse
41637
+ * relaxes a threshold, and a formatting choice never earns a pass it would not otherwise get.
41638
+ */
41639
+ function extractItemsSection(sections, heading, { includeProse = true } = {}) {
41640
+ const items = [];
41641
+ let paragraph = [];
41642
+ let lastWasListItem = false;
41643
+ const flushParagraph = () => {
41644
+ const text = paragraph.join(' ').replace(/\s+/g, ' ').trim();
41645
+ if (text)
41646
+ items.push(text);
41647
+ paragraph = [];
41648
+ };
41649
+ for (const line of sectionLines(sections, heading)) {
41650
+ if (!line.trim()) {
41651
+ flushParagraph();
41652
+ lastWasListItem = false;
41653
+ continue;
41654
+ }
41655
+ // Structure and generated captions are checked FIRST, so neither can be folded into the
41656
+ // item above it or accumulated into a paragraph. A subheading is not a wrapped bullet.
41657
+ if (isNotContent(line)) {
41658
+ flushParagraph();
41659
+ lastWasListItem = false;
41660
+ continue;
41661
+ }
41662
+ if (isListItem(line)) {
41663
+ flushParagraph();
41664
+ const text = stripListMarker(line);
41665
+ lastWasListItem = Boolean(text);
41666
+ if (text)
41667
+ items.push(text);
41668
+ continue;
41669
+ }
41670
+ // A non-blank line straight after a list item is that item's wrapped text, not a new
41671
+ // item. Markdown lazy continuation does not require indentation, and requiring it let a
41672
+ // hard-wrapped bullet split into two items: wrapping must never manufacture an outcome
41673
+ // that clears the two-outcome gate. A blank line is what ends an item. This runs
41674
+ // whatever `includeProse` says, because wrapped text belongs to the list item, not to
41675
+ // the prose the flag governs.
41676
+ if (lastWasListItem && items.length) {
41677
+ items[items.length - 1] = `${items[items.length - 1]} ${line.trim()}`.replace(/\s+/g, ' ');
41678
+ continue;
41679
+ }
41680
+ if (!includeProse) {
41681
+ flushParagraph();
41682
+ lastWasListItem = false;
41683
+ continue;
41684
+ }
41685
+ lastWasListItem = false;
41686
+ paragraph.push(line.trim());
41687
+ }
41688
+ flushParagraph();
41689
+ return items;
41510
41690
  }
41511
41691
  /**
41512
41692
  * Parse `## Decisions & Ruled-Out Alternatives` entries written by `decisionLines()`:
41513
41693
  * - **choice** (instead of: ruledOut) — reason
41514
41694
  * The separator is an em dash when written by us; a plain hyphen is accepted for hand-edited files.
41515
41695
  */
41696
+ /**
41697
+ * A section that has list items owns the field, prose included. A section that is prose only
41698
+ * yields to frontmatter, and is read only when there is no frontmatter to yield to.
41699
+ *
41700
+ * The middle step is the published normalization rule, conformance case "list fallback: a
41701
+ * section with no list items does not override frontmatter": prose under a heading must not
41702
+ * erase a structured frontmatter value. It is a rule about OVERRIDE, not about ignoring prose,
41703
+ * so a section mixing a bullet and a paragraph keeps both. The last step is the defect this
41704
+ * change exists for: with nothing in frontmatter either, prose used to vanish and the gate
41705
+ * reported the section as `absent`, telling the author they had written nothing.
41706
+ */
41707
+ function preferListThenFrontmatter(sections, heading, fromFrontmatter) {
41708
+ const all = extractItemsSection(sections, heading);
41709
+ if (extractItemsSection(sections, heading, { includeProse: false }).length)
41710
+ return all;
41711
+ const frontmatter = preferSection([], fromFrontmatter);
41712
+ if (frontmatter.length)
41713
+ return frontmatter;
41714
+ return all;
41715
+ }
41516
41716
  function extractDecisions(sections) {
41517
41717
  const out = [];
41518
41718
  for (const line of sectionLines(sections, DECISIONS_HEADING)) {
@@ -41531,12 +41731,11 @@ function extractDecisions(sections) {
41531
41731
  }
41532
41732
  return out;
41533
41733
  }
41534
- function extractEdgeCases(sections) {
41734
+ function extractEdgeCases(sections, opts = {}) {
41535
41735
  const cases = [];
41536
- for (const line of sectionLines(sections, 'Edge Cases')) {
41537
- if (!isListItem(line))
41538
- continue;
41539
- const clean = stripListMarker(line);
41736
+ // Items come from the shared reader, so a prose paragraph is an item exactly as a bullet is
41737
+ // and the pair patterns below are applied to both. Nothing here depends on the formatting.
41738
+ for (const clean of extractItemsSection(sections, 'Edge Cases', opts)) {
41540
41739
  // Pattern: **scenario**: expected behavior
41541
41740
  const match = clean.match(/^\*\*(.+?)\*\*:\s*(.+)$/);
41542
41741
  if (match) {
@@ -41550,7 +41749,13 @@ function extractEdgeCases(sections) {
41550
41749
  const arrowMatch = clean.match(/^(.+?)\s*(?:->|→|:)\s*(.+)$/);
41551
41750
  if (arrowMatch) {
41552
41751
  cases.push({ scenario: arrowMatch[1].trim(), expectedBehavior: arrowMatch[2].trim() });
41752
+ continue;
41553
41753
  }
41754
+ // No pair in it. Keep the scenario so readiness can quote it back and ask for the
41755
+ // expected behavior, and leave `expectedBehavior` empty: the gate requires both, so an
41756
+ // unpaired item cannot pass, and no behavior is invented for the author. Dropping it,
41757
+ // which is what happened before, reported the section as absent instead.
41758
+ cases.push({ scenario: clean, expectedBehavior: '' });
41554
41759
  }
41555
41760
  return cases;
41556
41761
  }
@@ -41634,7 +41839,7 @@ function parseVerificationLabel(line) {
41634
41839
  * ("E2E Tests", "Unit Tests", "Manual Checks") keep their string-array buckets, which
41635
41840
  * `toVerificationChecks()` in intent-compiler.ts adapts on read.
41636
41841
  */
41637
- function extractVerification(sections) {
41842
+ function extractVerification(sections, { includeProse = true } = {}) {
41638
41843
  const lines = sectionLines(sections, 'Verification');
41639
41844
  if (lines.length === 0)
41640
41845
  return {};
@@ -41642,9 +41847,55 @@ function extractVerification(sections) {
41642
41847
  let currentKind = null;
41643
41848
  let currentLegacy = null;
41644
41849
  let sawLabel = false;
41850
+ // Prose is preserved here on the same terms as everywhere else: a run of unindented
41851
+ // non-list lines is one paragraph and one check, attributed to the bucket it was written
41852
+ // under, and an indented wrap folds into the check above it rather than becoming a check of
41853
+ // its own. A bullet parses exactly as it did before.
41854
+ const paragraph = [];
41855
+ // A holder, not a bare `let`: TypeScript narrows a variable assigned only inside
41856
+ // closures down to its initializer, and the call below then reads as `never`.
41857
+ const last = { append: null };
41858
+ const pushText = (text) => {
41859
+ if (currentKind) {
41860
+ const { description, status, verifies } = parseCheckLine(text);
41861
+ if (!description) {
41862
+ last.append = null;
41863
+ return;
41864
+ }
41865
+ const check = { kind: currentKind, description };
41866
+ if (status)
41867
+ check.status = status;
41868
+ if (verifies)
41869
+ check.verifies = verifies;
41870
+ (result.checks ||= []).push(check);
41871
+ last.append = (extra) => { check.description = `${check.description} ${extra}`.replace(/\s+/g, ' '); };
41872
+ return;
41873
+ }
41874
+ const bucket = currentLegacy
41875
+ ? (result[currentLegacy] ||= [])
41876
+ // IntentSpec labels are optional. Treat an ungrouped item as a manual check so a
41877
+ // valid flat `## Verification` section survives adoption instead of disappearing.
41878
+ : sawLabel ? null : (result.manualChecks ||= []);
41879
+ if (!bucket) {
41880
+ last.append = null;
41881
+ return;
41882
+ }
41883
+ bucket.push(text);
41884
+ last.append = (extra) => { bucket[bucket.length - 1] = `${bucket[bucket.length - 1]} ${extra}`.replace(/\s+/g, ' '); };
41885
+ };
41886
+ const flushParagraph = () => {
41887
+ const text = paragraph.join(' ').replace(/\s+/g, ' ').trim();
41888
+ paragraph.length = 0;
41889
+ if (text)
41890
+ pushText(text);
41891
+ };
41645
41892
  for (const line of lines) {
41646
41893
  const label = parseVerificationLabel(line);
41647
41894
  if (label) {
41895
+ // Flush before switching buckets so the paragraph lands under the label it was
41896
+ // written beneath, not the next one.
41897
+ flushParagraph();
41898
+ last.append = null;
41648
41899
  sawLabel = true;
41649
41900
  const kind = VERIFICATION_LABEL_TO_KIND[label.toLowerCase()];
41650
41901
  if (kind) {
@@ -41665,31 +41916,41 @@ function extractVerification(sections) {
41665
41916
  currentLegacy = null;
41666
41917
  continue;
41667
41918
  }
41668
- if (!isListItem(line))
41919
+ if (!line.trim()) {
41920
+ flushParagraph();
41921
+ last.append = null;
41669
41922
  continue;
41670
- const text = stripListMarker(line);
41671
- if (!text)
41923
+ }
41924
+ // Structure first, so a `### Regression checks` subheading under `## Verification` can
41925
+ // neither become a check of its own nor be folded into the check above it. It used to
41926
+ // become one, and a Verification section holding nothing but subheadings passed.
41927
+ if (isNotContent(line)) {
41928
+ flushParagraph();
41929
+ last.append = null;
41672
41930
  continue;
41673
- if (currentKind) {
41674
- const { description, status, verifies } = parseCheckLine(text);
41675
- if (!description)
41931
+ }
41932
+ if (isListItem(line)) {
41933
+ flushParagraph();
41934
+ const text = stripListMarker(line);
41935
+ if (!text) {
41936
+ last.append = null;
41676
41937
  continue;
41677
- const check = { kind: currentKind, description };
41678
- if (status)
41679
- check.status = status;
41680
- if (verifies)
41681
- check.verifies = verifies;
41682
- (result.checks ||= []).push(check);
41938
+ }
41939
+ pushText(text);
41940
+ continue;
41683
41941
  }
41684
- else if (currentLegacy) {
41685
- result[currentLegacy].push(text);
41942
+ // Lazy continuation, as above: a wrapped check is one check.
41943
+ if (last.append) {
41944
+ last.append(line.trim());
41945
+ continue;
41686
41946
  }
41687
- else if (!sawLabel) {
41688
- // IntentSpec labels are optional. Treat an ungrouped list as manual checks so a valid
41689
- // flat `## Verification` section survives adoption instead of silently disappearing.
41690
- (result.manualChecks ||= []).push(text);
41947
+ if (!includeProse) {
41948
+ flushParagraph();
41949
+ continue;
41691
41950
  }
41951
+ paragraph.push(line.trim());
41692
41952
  }
41953
+ flushParagraph();
41693
41954
  return result;
41694
41955
  }
41695
41956
  function hasVerificationContent(v) {
@@ -42684,7 +42945,7 @@ async function pushSpec(input) {
42684
42945
  * https://preflight.pathmode.io, so keep it true.
42685
42946
  */
42686
42947
  Object.defineProperty(exports, "__esModule", ({ value: true }));
42687
- exports.READINESS_GATE_ORDER = exports.READINESS_BLOCKER_DESCRIPTIONS = void 0;
42948
+ exports.READINESS_GATE_ORDER = exports.READINESS_OUTCOMES_TOO_FEW_BLOCKER = exports.READINESS_BLOCKER_DESCRIPTIONS = void 0;
42688
42949
  exports.coerceText = coerceText;
42689
42950
  exports.asArray = asArray;
42690
42951
  exports.isTitleMeaningful = isTitleMeaningful;
@@ -42692,6 +42953,7 @@ exports.isConstraintConcrete = isConstraintConcrete;
42692
42953
  exports.isVerificationCheckSubstantive = isVerificationCheckSubstantive;
42693
42954
  exports.isObjectiveSpecific = isObjectiveSpecific;
42694
42955
  exports.isOutcomeMeasurable = isOutcomeMeasurable;
42956
+ exports.readinessBlockerFor = readinessBlockerFor;
42695
42957
  exports.normalizeAnchor = normalizeAnchor;
42696
42958
  exports.fieldDigest = fieldDigest;
42697
42959
  exports.computeReadinessVerdict = computeReadinessVerdict;
@@ -42811,6 +43073,18 @@ exports.READINESS_BLOCKER_DESCRIPTIONS = {
42811
43073
  edgeCases: 'No edge case with a defined expected behavior.',
42812
43074
  verification: 'No concrete verification — describe at least one check specific enough to run.',
42813
43075
  };
43076
+ /**
43077
+ * MIRROR of `OUTCOMES_TOO_FEW_BLOCKER` in lib/intentReadiness.ts; see its comment for why the
43078
+ * outcomes gate needs two messages. The threshold is unchanged.
43079
+ */
43080
+ exports.READINESS_OUTCOMES_TOO_FEW_BLOCKER = 'Fewer than two outcomes. Name at least two, one per line or paragraph, so each can be checked on its own.';
43081
+ function readinessBlockerFor(key, spec) {
43082
+ if (key !== 'outcomes')
43083
+ return exports.READINESS_BLOCKER_DESCRIPTIONS[key];
43084
+ return asArray(spec.outcomes).map(o => outcomeText(o).trim()).filter(Boolean).length < 2
43085
+ ? exports.READINESS_OUTCOMES_TOO_FEW_BLOCKER
43086
+ : exports.READINESS_BLOCKER_DESCRIPTIONS.outcomes;
43087
+ }
42814
43088
  /** Display order for the gate strip (title first, matching the Preflight page). */
42815
43089
  // ── Confirmation anchoring ──────────────────────────────────────────────────
42816
43090
  /**
@@ -42990,7 +43264,7 @@ function computeReadinessVerdict(spec) {
42990
43264
  };
42991
43265
  const failingBlockers = BLOCKER_ORDER
42992
43266
  .filter(k => !signals[k])
42993
- .map(k => exports.READINESS_BLOCKER_DESCRIPTIONS[k]);
43267
+ .map(k => readinessBlockerFor(k, spec));
42994
43268
  // What the reader read, per dimension, independent of whether the heuristic accepted it.
42995
43269
  // Placeholder text is deliberately not extracted: no path from a blank spec to confirmable.
42996
43270
  const objectiveText = coerceText(spec.objective).trim();
@@ -43008,11 +43282,14 @@ function computeReadinessVerdict(spec) {
43008
43282
  const detail = {};
43009
43283
  for (const key of exports.READINESS_GATE_ORDER) {
43010
43284
  const text = extractedBy[key] ?? '';
43285
+ // Only when it OVERRIDES the static message, so the common shape is untouched.
43286
+ const resolved = readinessBlockerFor(key, spec);
43287
+ const override = resolved && resolved !== exports.READINESS_BLOCKER_DESCRIPTIONS[key] ? { blocker: resolved } : {};
43011
43288
  detail[key] = signals[key]
43012
43289
  ? { state: 'pass', ...(text ? { extracted: text } : {}) }
43013
43290
  : text
43014
- ? { state: 'unconfirmed', extracted: text }
43015
- : { state: 'absent' };
43291
+ ? { state: 'unconfirmed', extracted: text, ...override }
43292
+ : { state: 'absent', ...override };
43016
43293
  }
43017
43294
  // Confirmations only ever move a dimension the heuristics already failed; `signals` is never
43018
43295
  // mutated, so the lexical verdict stays visible underneath.
@@ -43070,15 +43347,36 @@ function formatReadinessFrontmatter(verdict) {
43070
43347
  * The extra line an `unconfirmed` dimension earns: what was read, and an honest statement of
43071
43348
  * what the check could not find in it.
43072
43349
  *
43073
- * Only objective and outcomes appear here, and that scoping is the finding, not caution. The
43074
- * audit measured that most failures on those two are false negatives from a fixed English
43075
- * vocabulary. Verification's measured misses were all extraction failures, so quoting text
43076
- * back there would imply a confidence the evidence does not support.
43350
+ * Objective and outcomes get the SOFTENED copy, and that scoping is the finding, not caution:
43351
+ * the audit measured that most failures on those two are false negatives from a fixed English
43352
+ * vocabulary, so telling those authors the text may be fine is honest.
43353
+ *
43354
+ * Constraints, edge cases and verification get a hint too, but a plainer one. Their measured
43355
+ * misses were extraction failures, and the audit never measured their lexical recall, so the
43356
+ * copy states what was read and what is missing from it and stops there. It does not say the
43357
+ * check is probably wrong, because for these three there is no evidence that it is. They earn
43358
+ * a hint at all only because the parser now preserves prose: before that, an unread section
43359
+ * reached this code as `absent`, there was nothing extracted to quote, and the reader was told
43360
+ * it had written nothing.
43077
43361
  */
43078
43362
  const UNCONFIRMED_HINT = {
43079
43363
  objective: 'Read this, but could not confirm an affected actor and a concrete problem in it. If it already names them, this check reads a fixed vocabulary and may be missing valid phrasing:',
43080
43364
  outcomes: 'Read these, but could not confirm an observable threshold in enough of them. If they are already observable, this check reads a fixed vocabulary and may be missing valid phrasing:',
43365
+ constraints: 'Read this, but could not confirm a hard limit in it. A constraint names something that must never happen:',
43366
+ edgeCases: 'Read this, but no expected behavior was paired with it. Write the case as "situation: what should happen", one per line or paragraph:',
43367
+ verification: 'Read this, but could not confirm a check specific enough to run. A check names a command or a stated expected result:',
43081
43368
  };
43369
+ /**
43370
+ * The hint has to follow the blocker that was actually chosen. When outcomes failed on COUNT,
43371
+ * the measurability hint contradicted the line directly above it and accused wording the
43372
+ * detector had accepted.
43373
+ */
43374
+ function unconfirmedHintFor(key, d) {
43375
+ if (key === 'outcomes' && d?.blocker === exports.READINESS_OUTCOMES_TOO_FEW_BLOCKER) {
43376
+ return 'Read this. If it holds more than one outcome, separate them so each can be checked on its own:';
43377
+ }
43378
+ return UNCONFIRMED_HINT[key];
43379
+ }
43082
43380
  /** Keep a quoted extraction to one readable line; the full text is in verdict.detail. */
43083
43381
  function truncateForQuote(text, max = 160) {
43084
43382
  const flat = text.replace(/\s+/g, ' ').trim();
@@ -43130,10 +43428,11 @@ repairHint) {
43130
43428
  for (const key of BLOCKER_ORDER) {
43131
43429
  if (verdict.signals[key] || resolved(key) === 'pass' || resolved(key) === 'not_applicable')
43132
43430
  continue;
43133
- lines.push(` ✗ ${exports.READINESS_BLOCKER_DESCRIPTIONS[key]}`);
43431
+ lines.push(` ✗ ${verdict.detail?.[key]?.blocker ?? exports.READINESS_BLOCKER_DESCRIPTIONS[key]}`);
43134
43432
  const d = verdict.detail?.[key];
43135
- if (d?.state === 'unconfirmed' && d.extracted && UNCONFIRMED_HINT[key]) {
43136
- lines.push(` ↳ ${UNCONFIRMED_HINT[key]}`);
43433
+ const hint = unconfirmedHintFor(key, d);
43434
+ if (d?.state === 'unconfirmed' && d.extracted && hint) {
43435
+ lines.push(` ↳ ${hint}`);
43137
43436
  lines.push(` "${truncateForQuote(d.extracted)}"`);
43138
43437
  }
43139
43438
  }
@@ -72903,7 +73202,7 @@ module.exports = /*#__PURE__*/JSON.parse('{"$schema":"http://json-schema.org/dra
72903
73202
  /***/ ((module) => {
72904
73203
 
72905
73204
  "use strict";
72906
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@pathmode/mcp-server","version":"1.26.3","publishConfig":{"access":"public"},"mcpName":"io.github.pathmodeio/mcp-server","description":"Deterministic intent preflight before your agent builds: six calibrated gates, keyless, no model call. Draft and sharpen specs in conversation, or connect a Pathmode workspace to sync intent and evidence across a team.","main":"dist/index.js","bin":{"pathmode-mcp":"dist/index.js"},"files":["dist/","manifest.json","icon.svg","README.md","skills/"],"scripts":{"build":"rm -rf dist && 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"},"homepage":"https://pathmode.io","dependencies":{"@modelcontextprotocol/sdk":"^1.12.1","gray-matter":"^4.0.3","zod":"^3.24.0"},"overrides":{"@hono/node-server":"^1.19.17","body-parser":"^2.3.0","fast-uri":"^3.1.6","hono":"^4.13.5","ip-address":"^10.7.0","js-yaml":"^3.15.2"},"devDependencies":{"@types/node":"^25.1.0","@vercel/ncc":"^0.38.4","ts-node":"^10.9.2","typescript":"^5.9.3"}}');
73205
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@pathmode/mcp-server","version":"1.27.1","publishConfig":{"access":"public"},"mcpName":"io.github.pathmodeio/mcp-server","description":"Deterministic intent preflight before your agent builds: six calibrated gates, keyless, no model call. Draft and sharpen specs in conversation, or connect a Pathmode workspace to sync intent and evidence across a team.","main":"dist/index.js","bin":{"pathmode-mcp":"dist/index.js"},"files":["dist/","manifest.json","icon.svg","README.md","skills/"],"scripts":{"build":"rm -rf dist && 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"},"homepage":"https://pathmode.io","dependencies":{"@modelcontextprotocol/sdk":"^1.12.1","gray-matter":"^4.0.3","zod":"^3.24.0"},"overrides":{"@hono/node-server":"^1.19.17","body-parser":"^2.3.0","fast-uri":"^3.1.6","hono":"^4.13.5","ip-address":"^10.7.0","js-yaml":"^3.15.2"},"devDependencies":{"@types/node":"^25.1.0","@vercel/ncc":"^0.38.4","ts-node":"^10.9.2","typescript":"^5.9.3"}}');
72907
73206
 
72908
73207
  /***/ })
72909
73208
 
@@ -184,5 +184,25 @@ export declare function renderAuthorizationGateText(opts: {
184
184
  * so an unwaivable dimension never leaves an empty section behind.
185
185
  */
186
186
  export declare function renderConfirmationsBody(records: SerializableConfirmation[] | undefined): string;
187
+ /**
188
+ * Captions this codebase writes into an intent.md, as opposed to anything an author wrote.
189
+ *
190
+ * A caption is prose under a heading that is NOT content: it explains the section rather than
191
+ * recording a decision. The readers exclude exactly these strings, which is why they live here,
192
+ * next to the code that emits them, and are imported rather than retyped. Excluding "all italic
193
+ * prose" instead was wrong: an author writing `*Must not slow down page load.*` under
194
+ * Constraints means it, and reporting that section as absent is the accusation the four-state
195
+ * gate exists to stop making.
196
+ *
197
+ * Adding a caption anywhere means adding it here, or the reader will grade it as content.
198
+ */
199
+ export declare const VERIFICATION_FEEDBACK_CAPTION = "_A feedback loop, not just a test list._";
200
+ /** Written by lib/scan/draftIntentMd.ts when a pre-account draft has no verification yet. */
201
+ export declare const VERIFICATION_NOT_DEFINED_CAPTION = "_Not defined yet. Nothing in this spec has been checked against a running system._";
202
+ export declare const GENERATED_CAPTIONS: readonly string[];
203
+ /** Trim, drop one layer of surrounding `_` or `*`, casefold. Both emphasis spellings match. */
204
+ export declare function normalizeCaption(line: string): string;
205
+ /** True only for a caption this codebase generated. Author prose, italic or not, is content. */
206
+ export declare function isGeneratedCaption(line: string): boolean;
187
207
  export declare function serializeIntentMd(spec: SerializableIntent, opts?: SerializeIntentMdOptions): string;
188
208
  //# sourceMappingURL=serializeIntentMd.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"serializeIntentMd.d.ts","sourceRoot":"","sources":["file:///Users/jannelammi/code/Pathmode/packages/intentspec-format/serializeIntentMd.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"serializeIntentMd.d.ts","sourceRoot":"","sources":["file:///Users/jannelammi/code/Pathmode/packages/intentspec-format/serializeIntentMd.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,9 @@
8
8
  * as a single item: three outcomes read back as one, `## Scope` vanished entirely, and
9
9
  * `## Verification` produced `{}`. See round-trip.test.ts for the regression guard.
10
10
  */
11
+ import matter from 'gray-matter';
11
12
  import type { OutcomeMeasurementDefinition } from './api-client';
13
+ export declare function parseFrontmatter(content: string): matter.GrayMatterFile<string>;
12
14
  export type LocalVerificationKind = 'fastest' | 'manual' | 'shipped-signal' | 'regression-guard' | 'test';
13
15
  export interface LocalVerificationCheck {
14
16
  kind: LocalVerificationKind;
@@ -1 +1 @@
1
- {"version":3,"file":"local-reader.d.ts","sourceRoot":"","sources":["file:///Users/jannelammi/code/Pathmode/packages/mcp-server/src/local-reader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,cAAc,CAAC;AAEjE,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,QAAQ,GAAG,gBAAgB,GAAG,kBAAkB,GAAG,MAAM,CAAC;AAE1G,MAAM,WAAW,sBAAsB;IACnC,IAAI,EAAE,qBAAqB,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wGAAwG;AACxG,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAC9B,MAAM,CAAC,EAAE,sBAAsB,EAAE,CAAC;IAClC,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,kBAAkB,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;CACf;AAuCD,MAAM,WAAW,WAAW;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;iDAE6C;IAC7C,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,KAAK,CAAC,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,4BAA4B,CAAA;KAAE,CAAC,CAAC;IACtF,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5D,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACtD,YAAY,EAAE,iBAAiB,CAAC;IAChC,0EAA0E;IAC1E,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC,MAAM,EAAE,OAAO,CAAC;CACnB;AAED,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;6EACyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;oGAEgG;IAChG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;yFACqF;IACrF,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAID;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,EAAE,CAmBhD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAkBvE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAUnE;AAsED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,SAAW,GAAG,WAAW,CA0CvF;AA+CD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAItD"}
1
+ {"version":3,"file":"local-reader.d.ts","sourceRoot":"","sources":["file:///Users/jannelammi/code/Pathmode/packages/mcp-server/src/local-reader.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,12 @@ export declare function isVerificationCheckSubstantive(description: string | nul
20
20
  export declare function isObjectiveSpecific(objective: string | null | undefined): boolean;
21
21
  export declare function isOutcomeMeasurable(text: string): boolean;
22
22
  export declare const READINESS_BLOCKER_DESCRIPTIONS: Record<string, string>;
23
+ /**
24
+ * MIRROR of `OUTCOMES_TOO_FEW_BLOCKER` in lib/intentReadiness.ts; see its comment for why the
25
+ * outcomes gate needs two messages. The threshold is unchanged.
26
+ */
27
+ export declare const READINESS_OUTCOMES_TOO_FEW_BLOCKER = "Fewer than two outcomes. Name at least two, one per line or paragraph, so each can be checked on its own.";
28
+ export declare function readinessBlockerFor(key: string, spec: ReadinessSpecInput): string;
23
29
  /**
24
30
  * Fold away everything that is a rewrite of the same claim, and nothing that is a change to it.
25
31
  * NFC because one glyph has two encodings; soft hyphens because editors inject them invisibly;
@@ -86,6 +92,12 @@ export interface DimensionDetail {
86
92
  state: DimensionState;
87
93
  /** What the reader actually read for this dimension, for quoting back. */
88
94
  extracted?: string;
95
+ /**
96
+ * Set ONLY when this failure's message overrides the static one. MIRROR of
97
+ * `DimensionDetail.blocker` in lib/intentReadiness.ts: outcomes fails either on count or on
98
+ * measurability, and `formatReadinessVerdict` never receives the spec.
99
+ */
100
+ blocker?: string;
89
101
  /** Set when a confirmation or waiver moved this dimension: who vouched, and how well we know it. */
90
102
  confirmedBy?: 'agent' | 'human';
91
103
  assurance?: 'authenticated' | 'local-unverified';
@@ -1 +1 @@
1
- {"version":3,"file":"readiness.d.ts","sourceRoot":"","sources":["file:///Users/jannelammi/code/Pathmode/packages/mcp-server/src/readiness.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"readiness.d.ts","sourceRoot":"","sources":["file:///Users/jannelammi/code/Pathmode/packages/mcp-server/src/readiness.ts"],"names":[],"mappings":"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"}
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.26.3",
5
+ "version": "1.27.1",
6
6
  "description": "Deterministic preflight for the intent you hand to a coding agent: six calibrated gates, the exact blockers named, no model call, no key needed.",
7
7
  "long_description": "Pathmode MCP Server runs a deterministic preflight before your coding agent builds: check_intent_readiness scores an intent spec against six calibrated gates (title, objective, outcomes, constraints, edge cases, verification) and names the exact blockers, with no model call and no account. Keyless local mode works out of the box; specs live in intent.md in your repo, plain markdown you own, and skills for drafting, pressure-testing, and handing off intent ride along. Connect a Pathmode workspace with an API key to sync intent and evidence across a team, analyze dependency graphs, and verify pull requests against the outcomes you agreed to.",
8
8
  "author": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pathmode/mcp-server",
3
- "version": "1.26.3",
3
+ "version": "1.27.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },