feat: sync P20 Cross-Model Adversarial Review Gate to bstack#14
Conversation
Companion to broomva/workspace#55. Brings bstack reference consistent with workspace governance for P20. SKILL.md: - Count: nineteen -> twenty primitives; 29 -> 30 skills (cross-review) - Trigger list: P1 through P20 - Description: adds P20 one-line summary (cross-model gate, 3 strata, anti-slop >=7/10, broomva/cross-review skill) - Header subtitle: Nineteen -> Twenty / Twenty-nine -> Thirty - Primitives table: new P20 row - ROSTER: cross-review added as 2nd entry (after autonomous) scripts/doctor.sh: - EXPECTED_COUNT 19 -> 20; pattern matches Twenty/20 - Primitive-section loop iterates 1..20 - P_NAMES + REFLEXIVE_PRIMS arrays append P20 - Header comment P1-P19 -> P1-P20 references/primitives.md: - New §P20 section with Closes/How (3 strata table)/Invariant + Reflexive Trigger Rule + cross-model-agents origin Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR introduces a new primitive P20 (cross-model adversarial review gate) to the Broomva Stack, adding one primitive and one skill to the framework. The changes span the specification document, the canonical skill manifest, and the compliance validation script, updating all references to primitive enumeration to include P20 alongside P1–P19. ChangesP20 Cross-Model Adversarial Review Gate Addition
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@references/primitives.md`:
- Line 388: Add a TOC entry linking to the new section titled "P20 — Cross-Model
Adversarial Review Gate": locate the table of contents in
references/primitives.md and insert a markdown link that points to the section's
anchor text matching the exact heading "P20 — Cross-Model Adversarial Review
Gate" so the TOC item navigates to that heading.
- Around line 400-407: The P20 gate text is self-contradictory because the
header requires "verdict logged in PR comments + Linear ticket" while the P20
Reflexive Trigger Rule step 1 ("Before pushing substantive PRs — fire the
gate... Score + verdict precede push") mandates a pre-push verdict; resolve by
explicitly splitting responsibilities: require a mandatory pre-push local
score+verdict (retain the language in "Before pushing substantive PRs" and the
phrase "Score + verdict precede push") and separately require post-push PR
comment + Linear ticket logging of that pre-push verdict (or, alternatively,
move the gate to be a mandatory pre-merge check and update the header to remove
"PR-comment logging" as a prerequisite); update the P20 heading and step 1 to
mention "pre-push local verdict" and add a new step (or modify existing logging
clause) that records that verdict in PR comments + Linear ticket after push.
In `@SKILL.md`:
- Line 52: Update all occurrences in SKILL.md that reference the primitive and
skill counts so they match the new canonical wording "Twenty irreducible
primitives. Thirty curated skills." Search for variants like "Twenty / Thirty",
older numeric values, or phrases mentioning primitives/skills elsewhere in the
document (e.g., the headings and descriptive sentences that currently disagree)
and replace them with the exact canonical phrase; ensure any pluralization or
surrounding context remains grammatically correct and that cross-references or
summaries (such as counts in lists, headers, and the one-line tagline) are
normalized to the same numbers.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: fe1eaeb4-ddc7-4a3f-a078-8325151838ce
📒 Files selected for processing (3)
SKILL.mdreferences/primitives.mdscripts/doctor.sh
|
|
||
| --- | ||
|
|
||
| ## P20 — Cross-Model Adversarial Review Gate |
There was a problem hiding this comment.
Add P20 to the table of contents for discoverability.
The new section is present, but the TOC does not link to it.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@references/primitives.md` at line 388, Add a TOC entry linking to the new
section titled "P20 — Cross-Model Adversarial Review Gate": locate the table of
contents in references/primitives.md and insert a markdown link that points to
the section's anchor text matching the exact heading "P20 — Cross-Model
Adversarial Review Gate" so the TOC item navigates to that heading.
| Scoring: anti-slop ≥ 7/10 to pass; max 3 fix rounds; verdict logged in PR comments + Linear ticket. Implementation: `broomva/cross-review` skill. | ||
|
|
||
| **Invariant**: substantive PRs (>200 LOC OR public API change OR multi-file OR governance-class) cannot merge without cross-model adversarial verdict ≥ 7/10. Self-review by the writing model is forbidden as the *sole* verdict. The gate fires *before* P4 auto-merge — not after merge as code review. | ||
|
|
||
| ### P20 Reflexive Trigger Rule (binding on every agent) | ||
|
|
||
| 1. **Before pushing substantive PRs** — fire the gate (Strata A if Codex, else B+C). Score + verdict precede push. | ||
| 2. **When verdict < 7** — fix → rescore. Max 3 rounds. Round 3 failure → escalate to user. |
There was a problem hiding this comment.
Resolve P20 gate timing contradiction (pre-push vs PR-comment logging).
Line 400 requires PR-comment logging, but Line 406 requires verdict before push. Those cannot both be true without a “local pre-push score + post-push PR logging” split, or by moving the mandatory gate to pre-merge.
Proposed wording adjustment
- Scoring: anti-slop ≥ 7/10 to pass; max 3 fix rounds; verdict logged in PR comments + Linear ticket. Implementation: `broomva/cross-review` skill.
+ Scoring: anti-slop ≥ 7/10 to pass; max 3 fix rounds; verdict logged in Linear ticket and, once a PR exists, mirrored in PR comments. Implementation: `broomva/cross-review` skill.
- 1. **Before pushing substantive PRs** — fire the gate (Strata A if Codex, else B+C). Score + verdict precede push.
+ 1. **Before merging substantive PRs** — fire the gate (Strata A if Codex, else B+C). Score must pass before merge; log verdict to Linear and PR comments.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@references/primitives.md` around lines 400 - 407, The P20 gate text is
self-contradictory because the header requires "verdict logged in PR comments +
Linear ticket" while the P20 Reflexive Trigger Rule step 1 ("Before pushing
substantive PRs — fire the gate... Score + verdict precede push") mandates a
pre-push verdict; resolve by explicitly splitting responsibilities: require a
mandatory pre-push local score+verdict (retain the language in "Before pushing
substantive PRs" and the phrase "Score + verdict precede push") and separately
require post-push PR comment + Linear ticket logging of that pre-push verdict
(or, alternatively, move the gate to be a mandatory pre-merge check and update
the header to remove "PR-comment logging" as a prerequisite); update the P20
heading and step 1 to mention "pre-push local verdict" and add a new step (or
modify existing logging clause) that records that verdict in PR comments +
Linear ticket after push.
| # bstack — The Broomva Stack | ||
|
|
||
| **Nineteen irreducible primitives. Twenty-nine curated skills. One canonical operating mode. One self-operating workspace.** | ||
| **Twenty irreducible primitives. Thirty curated skills. One canonical operating mode. One self-operating workspace.** |
There was a problem hiding this comment.
Normalize stale primitive/skill counts across the rest of this document.
This update correctly sets “Twenty / Thirty,” but multiple later sections still say older values (e.g., Lines 60, 61, 74, 84, 246, 295, 302, 312, 319, 393, 395). That leaves conflicting operator guidance in one canonical file.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@SKILL.md` at line 52, Update all occurrences in SKILL.md that reference the
primitive and skill counts so they match the new canonical wording "Twenty
irreducible primitives. Thirty curated skills." Search for variants like "Twenty
/ Thirty", older numeric values, or phrases mentioning primitives/skills
elsewhere in the document (e.g., the headings and descriptive sentences that
currently disagree) and replace them with the exact canonical phrase; ensure any
pluralization or surrounding context remains grammatically correct and that
cross-references or summaries (such as counts in lists, headers, and the
one-line tagline) are normalized to the same numbers.
Companion to broomva/workspace#55 (P20 canonical), broomva/bstack#14 (bstack sync), and broomva/cross-review (new skill repo). SKILL.md: - New Step 15.5 between bookkeeping (15) and PR push (16): cross-review pre-push for substantive PRs (>200 LOC OR public API OR multi-file OR governance-class). Auto-detects strata: Codex CLI -> Strata A (true cross-vendor); else fresh Agent subagent -> Strata B; Strata C (composed existing adversarial-review skills: superpowers:constructive-dissent, devils-advocate, pr-review-toolkit:* x5, critique, premortem, plan-*-review) always parallel. Anti-slop >=7/10, max 3 fix rounds, verdict logged in PR. - Step 16 (PR push) extended to require including the cross-review verdict in the PR description or first comment. - 4 new anti-rationalization rows: 'I self-reviewed', 'small PR — skip', 'CodeRabbit will catch it', '/goal already evaluates'. - Composition table: new Step 15.5 row mapping to P20. tests/pressure-scenarios.md: - New Scenario 7: writer-self-confidence + downstream-gate-trust pressure ('I implemented it carefully, CodeRabbit catches issues, push it'). 5 specific rationalizations to resist + concrete tests that should fire. CHANGELOG.md: - [Unreleased] documents Step 15.5 + Scenario 7 + companion PRs The CI 'skill structure' regression guard checks for '20-reflex pipeline' — preserved since Step 15.5 is a sub-step between 15 and 16, not a new whole-number step. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(templates): refresh CLAUDE.md.template + AGENTS.md.template to P1–P19
Templates were stuck at "thirteen primitives" (P1–P13) while bstack
SKILL.md, scripts/doctor.sh, and references/primitives.md had moved to
nineteen (P1–P19). This scaffolded every new workspace into permanent
disagreement with the catalog — `bstack bootstrap` produced governance
files that `bstack doctor` then reported as having six missing primitive
sections.
Changes:
1. **CLAUDE.md.template** (+58/-22): rewritten to nineteen primitives
with the full table (P1–P19), short-name convention + index, Plugin
Skill Precedence section (bstack > superpowers hierarchy), updated
governance/hooks/conventions sections, Self-Documenting Standards
block.
2. **AGENTS.md.template** (+220/-14): bumped intro to nineteen, every
### P# heading renamed to "### P# — Name: …" form, short-name
convention + index added, full bodies for P14 (Dep-Chain), P15
(Snapshot), P16 (Crystallize), P17 (Lens), P18 (Audience), P19
(Orchestrate) — each with What/How/Invariant/Reflexive Trigger Rule.
Composition-loop diagram rewritten in short-name form with P14–P19
threaded at pre-flight + boundary crossings. Plugin Skill Precedence
section after composition loop documents the bstack > plugin hierarchy
and the "what this kills / what this keeps" partition.
3. **SKILL.md** (+1/-1): tiny drift fix — body said "16 primitives"
while frontmatter said "nineteen". Now consistent.
4. **tests/template_lockstep.test.sh** (new, 188 lines): asserts
primitive-count and structural consistency across the four
governance surfaces that must agree:
- SKILL.md frontmatter description (canonical count word + P19
reference + P1–P19 trigger span)
- scripts/doctor.sh EXPECTED_COUNT (the validator)
- assets/templates/CLAUDE.md.template (intro count, table rows,
short-name index entry count, Plugin Skill Precedence presence)
- assets/templates/AGENTS.md.template (intro count, composition-loop
intro, ### Pn section count, Plugin Skill Precedence presence)
- Short-name index payload identity between the two templates
13 assertions, all green at canonical count = 19. Designed to be the
guardrail that makes this kind of drift CI-visible — when the next
primitive is added (P20 in flight), this test catches any template
that didn't get updated.
Numbering uses **bstack canonical ordering**: P7=Freshness, P8=Janitor,
P9=Wait. This matches the prior template state and bstack catalog
(SKILL.md, doctor.sh, references/primitives.md). The ~/broomva workspace
itself uses P7=Wait, P8=Freshness, P9=Janitor because of historical
script + config-dir naming (BROOMVA_P8_HOME, ~/.config/broomva/p9-
janitor/); that's a workspace-specific deviation documented in
workspace#54 and is NOT a template concern — new bstack installs get
clean canonical numbering.
Companion to broomva/workspace#54 (precedence + short names + P19 in
workspace governance). Independent of bstack#14 (P20 sync) — that PR
adds P20 to the catalog; once it merges, a follow-up updates these
templates + lockstep test to canonical=20.
Follow-ups (separate PRs):
- bootstrap.sh + revamp.sh ORDERED_SKILLS divergence from SKILL.md
ROSTER (bootstrap installs persist + wealth-management + investment-
management; ROSTER instead has autonomous + role-x).
- P20 propagation to templates after bstack#14 merges.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(templates): bump to P20 (Cross-Review) after #14 merge
Companion to #14 (Cross-Model Adversarial Review Gate). bstack catalog
moved to twenty primitives via #14 (SKILL.md / doctor.sh / references/
primitives.md updated) but #14 did not touch templates. That's exactly
the drift this PR was created to close, and exactly what the new
template_lockstep.test.sh caught immediately after rebase:
--- before this commit ---
CLAUDE.md.template intro says 'twenty irreducible primitives (P1–P20)'
→ FAIL (says nineteen / P19)
AGENTS.md.template intro says 'twenty irreducible building blocks'
→ FAIL
AGENTS.md.template composition-loop intro says 'twenty primitives'
→ FAIL
AGENTS.md.template ### Pn section count
→ FAIL (19, expected 20)
CLAUDE.md.template primitive table row count
→ FAIL (19, expected 20)
CLAUDE.md.template short-name index entry count
→ FAIL (19, expected 20)
AGENTS.md.template + CLAUDE.md.template references P20
→ FAIL
--- after this commit ---
All 13 lockstep checks passed at canonical count = 20 (twenty)
Changes:
- **assets/templates/CLAUDE.md.template**: count phrase
"nineteen → twenty", "P1–P19 → P1–P20", short-name index appends
"Cross-Review (P20)", primitive table gets P20 row (mechanism: 3
strata A/B/C, anti-slop ≥7/10, ≤3 fix rounds, broomva/cross-review
skill; invariant: substantive PRs require ≥7/10 verdict before
Pipeline P4 auto-merge).
- **assets/templates/AGENTS.md.template**: count phrase nineteen→twenty
in intro + composition-loop, short-name index appends Cross-Review
(P20), new `### P20 — Cross-Review` section with full What/How
(3-strata table) / Invariant / Reflexive Trigger Rule (5 triggers).
Composition-loop diagram threads Cross-Review (P20) between
Empirical (P11) deploy verification and Pipeline (P4) auto-merge —
the exact insertion point per P20 spec ("gate fires before P4
auto-merge").
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: align P7/P8/P9 numbering to workspace canonical
Resolves the pre-existing numbering inconsistency where bstack canonical
disagreed with broomva/workspace AGENTS.md on P7/P8/P9. After this
change:
P7 = CI Watcher + Productive Wait (broomva/p9 skill — historical name)
P8 = Skill Freshness Check (SessionStart hook)
P9 = Branch + Worktree Janitor (make janitor)
This matches the workspace's renumbering documented in its naming-note
(P7's skill repo is broomva/p9 — named when it was the 9th primitive;
renaming the SKILL repo would break every npx skills add install).
Why workspace canonical wins:
- Workspace numbering is the actively-edited canonical (7 primitives
added under it in the last 3 sessions: P14, P15, P16, P17, P18, P19,
P20)
- Reverting workspace would touch many files; aligning bstack to
workspace is contained to this single repo
- The doctor (which reads workspace AGENTS.md/CLAUDE.md) now passes
73/73 against workspace — eliminates the 1 pre-existing gap reported
for several sessions
Changes:
SKILL.md:
- Frontmatter description: P7/P8/P9 sentences reordered to workspace
canonical (Productive Wait → Skill Freshness → Janitor)
- Primitives table: rows swapped (P7 = Productive Wait skill p9 historical,
P8 = Skill Freshness, P9 = Janitor)
references/primitives.md:
- Table of contents: P7/P8/P9 entries swapped to workspace order
- §P7 — now CI Watcher + Productive Wait (was Skill Freshness); skill-
name note rewritten to "broomva/p9 historical name" instead of "names
match"
- §P8 — now Skill Freshness Check (was Janitor); env vars updated to
BROOMVA_P8_THRESHOLD_DAYS with legacy P7 fallback
- §P9 — now Branch + Worktree Janitor (was Productive Wait); protected
path now ~/.config/broomva/p9-janitor/ with legacy p8 fallback
- Reflexive Trigger Rule subsection: now P7 (Productive Wait), was P9
scripts/doctor.sh:
- Header comment: reflexive list updated (P6, P7, P10..) instead of
(P6, P9, P10..); script-mapping comments updated (P7 = p9.py,
P8 = skill-freshness-hook, P9 = branch-janitor)
- P_NAMES array: P7/P8/P9 titles swapped to workspace canonical
- REFLEXIVE_PRIMS: P9 → P7 (Productive Wait is the reasoning-enforced
one; Janitor (now P9) is mechanism-only)
- SCRIPT_PATHS: reordered so labels (P1, P2, P6, P7, P8, P9, P12) map
to disk paths in the right order
- **Format-tolerant section matching**: doctor now accepts both
`### P1: Title` AND `### P1 — Label: Title` formats (workspace
AGENTS.md uses the labeled form; doctor was missing matches against
workspace files). Fixed in P_NAMES section-presence check + the
awk pattern in REFLEXIVE_PRIMS scan.
Companion fix in workspace:
- broomva/workspace/scripts/bstack-primitive-lint.py parse regex
extended to accept `### P\d+ —` (label form) in addition to
`### P\d+:` (original form)
Verified:
- bash scripts/doctor.sh against workspace → 73/73 PASSES
- G-L3-1 + G-L3-2 both green
The naming note about broomva/p9 skill being historically named is
preserved (and now consistent across workspace and bstack). The
"primitive number matches skill name" pedagogical claim in the old
§P9 is reframed in the new §P7 as "skill repo name is stable;
primitive number changed; this is intentional."
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Companion to #14 (Cross-Model Adversarial Review Gate). bstack catalog moved to twenty primitives via #14 (SKILL.md / doctor.sh / references/ primitives.md updated) but #14 did not touch templates. That's exactly the drift this PR was created to close, and exactly what the new template_lockstep.test.sh caught immediately after rebase: --- before this commit --- CLAUDE.md.template intro says 'twenty irreducible primitives (P1–P20)' → FAIL (says nineteen / P19) AGENTS.md.template intro says 'twenty irreducible building blocks' → FAIL AGENTS.md.template composition-loop intro says 'twenty primitives' → FAIL AGENTS.md.template ### Pn section count → FAIL (19, expected 20) CLAUDE.md.template primitive table row count → FAIL (19, expected 20) CLAUDE.md.template short-name index entry count → FAIL (19, expected 20) AGENTS.md.template + CLAUDE.md.template references P20 → FAIL --- after this commit --- All 13 lockstep checks passed at canonical count = 20 (twenty) Changes: - **assets/templates/CLAUDE.md.template**: count phrase "nineteen → twenty", "P1–P19 → P1–P20", short-name index appends "Cross-Review (P20)", primitive table gets P20 row (mechanism: 3 strata A/B/C, anti-slop ≥7/10, ≤3 fix rounds, broomva/cross-review skill; invariant: substantive PRs require ≥7/10 verdict before Pipeline P4 auto-merge). - **assets/templates/AGENTS.md.template**: count phrase nineteen→twenty in intro + composition-loop, short-name index appends Cross-Review (P20), new `### P20 — Cross-Review` section with full What/How (3-strata table) / Invariant / Reflexive Trigger Rule (5 triggers). Composition-loop diagram threads Cross-Review (P20) between Empirical (P11) deploy verification and Pipeline (P4) auto-merge — the exact insertion point per P20 spec ("gate fires before P4 auto-merge"). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P20 Cross-Review (Strata B fresh-context subagent) on this PR's prior HEAD scored 4/10 NEEDS-FIX. This commit addresses all blockers and high-severity findings; round 1 of max 3 per the P20 reflexive rule. ## Cross-review findings + fixes ### [BLOCKING] doctor.sh regex mismatch with new heading format Previous PR head changed AGENTS.md.template headings from `### P1: Conversation Bridge (Episodic Memory)` to `### P1 — Bridge: Conversation Bridge (Episodic Memory)`. But scripts/doctor.sh line 138 was `grep -qE "^### $prefix:"` — required colon directly after primitive number. Cross-review scaffolded a workspace from the prior templates + ran doctor.sh and got `28/70 passed, 42 gaps` — 20 missing primitive sections + 13 missing reflexive trigger rules, all caused by heading-format regression. The lockstep test (added by prior commit `c633f5c`) gave false-green because it checked `^### P[0-9]+ — ` (the NEW format the PR introduces), not what doctor.sh actually validates. Lockstep was checking the templates were consistent *with themselves* instead of with the validator. Textbook P16 substance-vs-ritual failure. Fix: scripts/doctor.sh:138 regex now `^### $prefix[: ]` — accepts both `### Pn:` (legacy) and `### Pn — Short: Long` (new short-name format). The `[: ]` character class is one char (colon OR space); for prefix=P1, matches "### P1:" and "### P1 — " but not "### P11:" (next char after P1 is '1', neither colon nor space). Same fix on doctor.sh:155 in the awk reflexive-trigger locator. Verified: scaffolded workspace now passes doctor with 0 primitive gaps + 0 reflexive gaps. ### [HIGH] SKILL.md body drift — partial fix in prior commit was misleading Prior commit `22bf59d` fixed line 60 (16→19) and claimed "now consistent" in the message. Cross-review found SKILL.md body STILL said: - L60 "the 19 primitives + 29 skills" (should be 20/30 post-#14) - L61 "19-reflex pipeline" (should be 20) - L84 "The sixteen primitives" (should be twenty) - L267-269 "P1–P16 rows" + "### P1: through ### P16:" + reflexive list ending at P16 - L319 "Primitive contract | 13/13" (should be 20/20) - L393 "full P1–P13 reference" (should be P1–P20) All six lines now corrected. Note L267 doctor-section description now explicitly documents both heading formats supported. ### [HIGH] Lockstep test missed the bug it was supposed to catch Added Section 7 to tests/template_lockstep.test.sh: "Scaffold-and-doctor compliance". The REAL guardrail: scaffold a temp workspace from the templates (mirror bootstrap.sh's scaffold_governance_file flow), run doctor.sh --quiet against it, assert 0 primitive-section gaps + 0 reflexive-trigger gaps. This is lockstep-vs-validator, not just lockstep-vs-self. Auto-discovers canonical count from doctor.sh and runs the full validation pipeline against scaffolded output. Test now has 15 assertions (was 13). All pass at canonical=20. ### [MEDIUM] P20 paraphrase dropped "Linear ticket" Per `references/primitives.md` §P20, the verdict is "logged in PR comments + Linear ticket". Templates said "logged in PR" only. Both CLAUDE.md.template and AGENTS.md.template P20 entries now say "logged in PR comments + Linear ticket (if workspace uses Linear)" — preserves spec fidelity while acknowledging workspace-optional Linear. ## Test plan - [x] `bash tests/template_lockstep.test.sh` — 15/15 PASS at canonical=20 - [x] Scaffold-and-doctor section confirms 0 primitive gaps + 0 reflexive gaps when templates are instantiated into a fresh workspace + doctor runs against it - [x] Cross-review's specific verification command reproduced locally (scaffold + doctor with BROOMVA_WORKSPACE override) — passes ## Re-fire cross-review post-push This is round 1 of 3 per P20 rule. After CI green, re-fire P20 gate (Strata B fresh subagent) to rescore. Target ≥7/10 for merge. Cross-review verdict log: stored in this PR's comments after re-run. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Companion to broomva/workspace#55. Brings bstack consistent: count 19→20, P20 row in primitives table, ROSTER adds
cross-review(29→30 skills), doctor.sh updates, §P20 section in primitives.md with the 3-strata decision matrix.🤖 Generated with Claude Code
Summary by CodeRabbit