diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index ef33763..4fbb41d 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "pathmode", "displayName": "Pathmode", - "version": "0.1.43", + "version": "0.1.44", "description": "Run a deterministic preflight on your intent before an agent builds: /preflight scores six calibrated gates and names the exact blockers, no model call, no key. Pathmode also interrogates the intent behind a request (compile-intent), writes it to intent.md in your repo, and checks the code that comes back against the outcomes and constraints you agreed to. Free: uses the models you already have access to in Claude Code. Connect a Pathmode workspace to sync intent and evidence across a team.", "author": { "name": "Pathmode", diff --git a/.mcp.json b/.mcp.json index 70ed615..b656d42 100644 --- a/.mcp.json +++ b/.mcp.json @@ -2,7 +2,7 @@ "mcpServers": { "pathmode": { "command": "npx", - "args": ["-y", "@pathmode/mcp-server@1.36.1"], + "args": ["-y", "@pathmode/mcp-server@1.37.0"], "env": { "PATHMODE_API_KEY": "${user_config.api_key}" } diff --git a/CALIBRATION.md b/CALIBRATION.md index 7e47114..c2e4413 100644 --- a/CALIBRATION.md +++ b/CALIBRATION.md @@ -77,6 +77,7 @@ Each case records **where its defect actually shipped**, and they are not all eq |---|---| | prose sections are content, not absence | shipped in `<= 1.26.3`, fixed in `1.27.0` | | non-English is unconfirmed, never absent | the known limitation the four-state verdict reports honestly | +| `## Why` is the objective, `## What` is not the outcomes | shipped in `<= 1.36.1`, fixed in `1.37.0` | | italic text the author wrote is content | never released; introduced and fixed between two commits | | a subsection heading is not a verification check | never released; same | | a hard-wrapped bullet is one item | never released; same | diff --git a/README.md b/README.md index da1486b..787550e 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ For workspace API access without a local intent, you can still create an API key ## What's bundled -**MCP server** — `@pathmode/mcp-server@1.36.1`, pinned so the plugin skills and server tool contract update together. Local mode with no key; cloud mode with one. +**MCP server** — `@pathmode/mcp-server@1.37.0`, pinned so the plugin skills and server tool contract update together. Local mode with no key; cloud mode with one. **Check the gate yourself** — `node scripts/readiness-suite.mjs` runs the pinned server's preflight over 111 labelled field fixtures and a set of whole `intent.md` documents, and prints where it disagrees. Read [CALIBRATION.md](CALIBRATION.md) first: the field score is a regression baseline, not an accuracy claim. diff --git a/fixtures/documents.json b/fixtures/documents.json index 4ce97d3..db94388 100644 --- a/fixtures/documents.json +++ b/fixtures/documents.json @@ -73,5 +73,12 @@ "why": "The gates match a fixed English vocabulary, so they cannot confirm this objective or constraint. That is a limit of the gate, and the verdict has to say so: 'unconfirmed' means it read the text and its word lists could not confirm it, which is different from claiming nothing was written. An audit of real specs found this class of failure is usually ours, not the author's.", "provenance": "the known limitation the four-state verdict exists to report honestly", "expect": { "objective": "unconfirmed", "constraints": "unconfirmed" } + }, + { + "name": "## Why is the objective, ## What is not the outcomes", + "file": "adlc-what-why.md", + "why": "The What/Why sample from a widely shared ADLC explainer. The gate reported the objective as nothing found and then called it too vague, about text it never read. `## Why` is now an objective alias and is judged on its words; `## What` usually states the solution, so it is named in a hint and never graded as outcomes.", + "provenance": "shipped in `<= 1.36.1`, fixed in `1.37.0`", + "expect": { "objective": "unconfirmed", "outcomes": "absent" } } ] diff --git a/fixtures/documents/adlc-what-why.md b/fixtures/documents/adlc-what-why.md new file mode 100644 index 0000000..69793df --- /dev/null +++ b/fixtures/documents/adlc-what-why.md @@ -0,0 +1,12 @@ +# Feature: Customer Insights + +## What +Build a dashboard for customer insights. + +## Why +Help teams make faster decisions. + +## Constraints +- Use existing data pipelines +- Keep within current infrastructure +- No PII exposure diff --git a/scripts/readiness-suite.mjs b/scripts/readiness-suite.mjs index 8f4b17a..ded0e83 100644 --- a/scripts/readiness-suite.mjs +++ b/scripts/readiness-suite.mjs @@ -178,12 +178,14 @@ const LABEL_TO_GATE = { /** * Blocker sentence -> gate, so a quoted extraction can be attributed to the dimension it came * from. Best-effort by design: the strip is the authoritative source of STATE, and this only - * decides which failure a quote is printed under. `outcomes` has two sentences because the gate - * fails two ways, on count and on measurability. + * decides which failure a quote is printed under. `objective` and `outcomes` have two sentences + * each because each gate fails two ways: objective as absent or vague, outcomes on count or on + * measurability. */ const BLOCKER_TO_GATE = [ [/^Title is missing or generic/, 'goal'], [/^Objective is too vague/, 'objective'], + [/^No objective found/, 'objective'], [/^Outcomes are not all measurable/, 'outcomes'], [/^Fewer than two outcomes/, 'outcomes'], [/^No hard constraint/, 'constraints'],