valent-pipeline 0.19.50 → 0.19.52

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valent-pipeline",
3
- "version": "0.19.50",
3
+ "version": "0.19.52",
4
4
  "description": "v3 multi-agent AI pipeline for software development lifecycle",
5
5
  "type": "module",
6
6
  "bin": {
@@ -83,7 +83,10 @@
83
83
  * PRODUCES the evidence and JUDGE remains the single ship gate that rejects a bad/missing visual result.
84
84
  * `onMissingMcp` controls the no-browser-MCP case — `block` (default) records a failing/blocked evidence
85
85
  * file so JUDGE rejects the UI story; `na` records the checkpoints N/A (loudly) and proceeds. The
86
- * installer registers playwright-mcp for UI projects, so `block` is normally never hit. Non-ui stories
86
+ * installer registers the browser MCP as `playwright` (committed to .mcp.json); PMCP matches it by
87
+ * browser-tool CAPABILITY (`mcp__<server>__browser_navigate`), NOT the exact configured name, so a
88
+ * `playwright` vs `playwright-mcp` label difference is harmless. `block` is hit only when no browser MCP
89
+ * is available at all — e.g. a session predating the .mcp.json server (restart to register it). Non-ui stories
87
90
  * have no checklist => the stage is a no-op (N/A), exactly mirroring QA-A's checklist-production trigger.
88
91
  *
89
92
  * `preCriticGate` (from pipeline-config.yaml `pre_critic_gate`) is the deterministic pre-CRITIC
@@ -2796,17 +2799,22 @@ async function runStory(story) {
2796
2799
  schema: PMCP_SCHEMA,
2797
2800
  model: modelFor('PMCP'),
2798
2801
  trigger:
2799
- `Read \`stories/${sid}/output/visual-validation-checklist.md\`. FIRST confirm the browser-` +
2800
- `automation MCP (\`${visualBrowserMcp}\`) is actually available to you in this session.\n` +
2802
+ `Read \`stories/${sid}/output/visual-validation-checklist.md\`. FIRST confirm a browser-` +
2803
+ `automation MCP is actually available to you in THIS session. Match by CAPABILITY, not the ` +
2804
+ `exact server name: you have it if your tools include a \`mcp__<server>__browser_navigate\` ` +
2805
+ `(and \`browser_snapshot\`). The server is configured as \`${visualBrowserMcp}\` but may be ` +
2806
+ `registered under another name (commonly \`playwright\`) — check the tool SHAPE, not the label.\n` +
2801
2807
  (naMode
2802
- ? `• If it is NOT available: do NOT block. Write pmcp-evidence.md marking every checkpoint ` +
2803
- `N/A with a LOUD note that visual validation was SKIPPED because \`${visualBrowserMcp}\` is ` +
2804
- `not installed, set verdict "na", mcpAvailable:false, and return.\n`
2805
- : `• If it is NOT available: this is a BLOCKER (the project requires visual evidence for UI ` +
2806
- `stories). Write pmcp-evidence.md recording that visual validation COULD NOT RUN because ` +
2807
- `\`${visualBrowserMcp}\` is not installed, set verdict "fail", mcpAvailable:false, and return ` +
2808
- `— JUDGE will reject on the missing visual evidence. Install it with \`node ` +
2809
- `.valent-pipeline/bin/cli.js init --force\` (or \`claude mcp add --scope project playwright -- npx -y @playwright/mcp\`).\n`) +
2808
+ ? `• If NO such browser tool is available: do NOT block. Write pmcp-evidence.md marking every ` +
2809
+ `checkpoint N/A with a LOUD note that visual validation was SKIPPED because no browser-` +
2810
+ `automation MCP (\`${visualBrowserMcp}\`) is available, set verdict "na", mcpAvailable:false, and return.\n`
2811
+ : `• If NO such browser tool is available: this is a BLOCKER (the project requires visual ` +
2812
+ `evidence for UI stories). Write pmcp-evidence.md recording that visual validation COULD NOT ` +
2813
+ `RUN because no browser-automation MCP (\`${visualBrowserMcp}\`) is available, set verdict ` +
2814
+ `"fail", mcpAvailable:false, and return — JUDGE will reject on the missing visual evidence. ` +
2815
+ `If it IS installed (\`claude mcp list\` shows it Connected) but its tools are absent here, the ` +
2816
+ `session likely PREDATES the \`.mcp.json\` server and must be RESTARTED to register it. Install/` +
2817
+ `repair with \`node .valent-pipeline/bin/cli.js init --force\` (or \`claude mcp add --scope project playwright -- npx -y @playwright/mcp\`).\n`) +
2810
2818
  `• If it IS available (mcpAvailable:true): start the dev server yourself, then for EACH ` +
2811
2819
  `checkpoint navigate to its route, establish the required state, wait for the expected state ` +
2812
2820
  `(element/network conditions — never hard waits), capture a screenshot into the story output ` +
@@ -40,7 +40,8 @@ browser MCP is available, **start the dev server yourself**, run every checkpoin
40
40
 
41
41
  - `{story_id}`, `{story_output_dir}`
42
42
  - `{tech_stack.browser_automation_mcp}` — the browser-automation MCP to use (default: `playwright-mcp`).
43
- The orchestrator passes the exact name to look for in your task trigger.
43
+ The orchestrator passes this as a **hint**; confirm availability by tool **capability**
44
+ (`mcp__<server>__browser_navigate`), since the server is often registered under a different name (e.g. `playwright`).
44
45
 
45
46
  ## Execution Steps
46
47
 
@@ -50,7 +51,11 @@ state, AC reference, expected visual elements, setup instructions, and pass crit
50
51
  is missing, set a blocker in your output and STOP (a `ui`-profile story should always have one from QA-A).
51
52
 
52
53
  ### Step 2: Confirm MCP availability and branch
53
- Confirm the browser-automation MCP named in your trigger is actually available to you in this session.
54
+ Confirm a browser-automation MCP is actually available to you in this session — match by **capability,
55
+ not the exact server name**: you have it if your tools include `mcp__<server>__browser_navigate` /
56
+ `browser_snapshot`. The configured name in your trigger is a hint; the server is commonly registered as
57
+ `playwright`, so check the tool **shape**, not the label. If `claude mcp list` shows it Connected but the
58
+ tools are absent here, the session predates the `.mcp.json` server and must be **restarted** to register it.
54
59
  Follow the on-missing-MCP behavior the orchestrator passed in your trigger:
55
60
  - **`block`:** if the MCP is absent, write `pmcp-evidence.md` recording that visual validation could not
56
61
  run, set `verdict: fail`, `mcpAvailable: false`, and return — JUDGE rejects on the missing evidence.
@@ -492,8 +492,10 @@ export const defaults = {
492
492
  // visual-validation-checklist.md and writes pmcp-evidence.md — the artifact JUDGE's evidence pass
493
493
  // REQUIRES for UI stories. `on_missing_mcp` controls what happens when that MCP is not installed:
494
494
  // block — record a failing/blocked evidence file so JUDGE rejects the UI story (visual evidence
495
- // is mandatory). This is the default; the installer registers playwright-mcp for UI
496
- // projects, so it is normally never hit.
495
+ // is mandatory). This is the default; the installer registers the browser MCP as
496
+ // `playwright` and PMCP matches it by tool capability (mcp__*__browser_navigate), NOT the
497
+ // exact configured name, so it is hit only when no browser MCP is available at all (e.g. a
498
+ // session predating the .mcp.json server — restart to register it).
497
499
  // na — record the checkpoints as N/A (loudly) and let the story ship without visual evidence.
498
500
  visual: {
499
501
  on_missing_mcp: 'block',
@@ -370,6 +370,19 @@ export function readFlowRecord(root, story) {
370
370
  }
371
371
  }
372
372
 
373
+ // When the flow record isn't in the run context's working tree, read it from a git ref. A --from-story
374
+ // bug's git-flow.json is committed only on its own branch (evidence-on-branch — the class the .50 fixed
375
+ // for the backlog entry), so story-status run from a context that lacks it (the post-ship verify on
376
+ // build/v1) would otherwise read None. Returns null on any failure (missing path/ref) — callers fall
377
+ // back to their prior behavior.
378
+ function readFlowRecordFromRef(root, ref, story) {
379
+ try {
380
+ return JSON.parse(git(root, ['show', `${ref}:stories/${story}/evidence/git-flow.json`]));
381
+ } catch {
382
+ return null;
383
+ }
384
+ }
385
+
373
386
  function writeFlowRecord(root, story, record) {
374
387
  const dir = join(root, 'stories', story, 'evidence');
375
388
  mkdirSync(dir, { recursive: true });
@@ -629,7 +642,13 @@ export function storyStatus({ root, story, targetBranch = '', prefix = 'story/'
629
642
  if (!isRepoWithCommits(root)) return NOT_REPO;
630
643
  const branch = storyBranchName(prefix, story);
631
644
  const exists = branchExists(root, branch);
632
- const record = readFlowRecord(root, story);
645
+ // Evidence-on-branch (M-90/M-91): a --from-story bug's git-flow.json is committed on its OWN branch,
646
+ // so a story-status run from a context lacking it (the post-ship verify on build/v1) reads None and
647
+ // defaults the target to build/v1 — a bug merged --into its SOURCE then reads merged:false (a FALSE
648
+ // git-ship-failed that strands the parent's revalidation). Fall back to the branch ref so basedOnStory
649
+ // still resolves (the .49 authority can only fire if the record is readable). Mirrors the .50 backlog
650
+ // branch-resolution. The record CONTENT is identical to the local copy — only the read source differs.
651
+ const record = readFlowRecord(root, story) || (exists ? readFlowRecordFromRef(root, branch, story) : null);
633
652
  // A `--from-story` item (an inline bug fix) ships `--into` its SOURCE story branch (recorded as
634
653
  // basedOnStory), NOT the sprint target — so "did it land" is ancestry against basedOnStory. The sprint
635
654
  // `--target` that the post-ship verify passes globally (gitFlags `--target`) is the wrong base for such