muse-commit-pilot-evidence.mjs
sha256:8915fe406161f95c1681f9469375e7bae5b28c884f00bedbdef65e4b0cd0738d
docs(flow): commit FLOW-V0-SPEC.md hygiene for 7A-INT merge
Human
1 day ago
| 1 | /** |
| 2 | * Muse commit pilot evidence validators (Phase 7A, Step 7A-14). |
| 3 | * |
| 4 | * Pure functions for seven-tier tests to assert the pilot artifacts meet the |
| 5 | * acceptance bar without re-running Muse or the full shell driver. |
| 6 | */ |
| 7 | |
| 8 | import { readFileSync, existsSync } from 'node:fs'; |
| 9 | import { join } from 'node:path'; |
| 10 | |
| 11 | /** Required paths under docs/evidence/7A-14 relative to the Knowtation repo root. */ |
| 12 | export const MUSE_COMMIT_PILOT_EVIDENCE_REL = 'docs/evidence/7A-14'; |
| 13 | |
| 14 | /** Pilot workspace filenames (projections committed via Muse). */ |
| 15 | export const PILOT_WORKSPACE_FILES = [ |
| 16 | 'overseer.AGENTS.md', |
| 17 | 'overseer.cursor.mdc', |
| 18 | ] ; |
| 19 | |
| 20 | /** Artifact filenames captured by run-pilot.sh. */ |
| 21 | export const PILOT_ARTIFACT_FILES = [ |
| 22 | 'transcript.txt', |
| 23 | 'muse-sha-before.txt', |
| 24 | 'muse-sha-after.txt', |
| 25 | 'overseer.AGENTS.v0.1.0.md', |
| 26 | 'overseer.AGENTS.v0.2.0.md', |
| 27 | 'overseer.v0.1.0.mdc', |
| 28 | 'overseer.v0.2.0.mdc', |
| 29 | 'overseer.runbook.v1-to-v2.diff', |
| 30 | 'overseer.cursor.v1-to-v2.diff', |
| 31 | 'overseer.AGENTS.handedited.md', |
| 32 | ]; |
| 33 | |
| 34 | const GENERATED_MARKER_RE = |
| 35 | /^<!-- GENERATED FROM CANONICAL FLOW flow_overseer_handover@(\d+\.\d+\.\d+) \(generator v1\)/; |
| 36 | |
| 37 | const SECRET_SCAN_RE = /\b(token|oauth|refresh_token|api_key|secret|password|bearer)\b/i; |
| 38 | |
| 39 | /** |
| 40 | * @param {string} repoRoot — absolute Knowtation repo root |
| 41 | * @returns {{ ok: true } | { ok: false; missing: string[] }} |
| 42 | */ |
| 43 | export function assertPilotEvidencePathsExist(repoRoot) { |
| 44 | const missing = []; |
| 45 | const base = join(repoRoot, MUSE_COMMIT_PILOT_EVIDENCE_REL); |
| 46 | for (const name of ['README.md', 'run-pilot.sh', ...PILOT_WORKSPACE_FILES.map((f) => `pilot-workspace/${f}`)]) { |
| 47 | if (!existsSync(join(base, name))) { |
| 48 | missing.push(join(MUSE_COMMIT_PILOT_EVIDENCE_REL, name)); |
| 49 | } |
| 50 | } |
| 51 | for (const name of PILOT_ARTIFACT_FILES) { |
| 52 | if (!existsSync(join(base, 'artifacts', name))) { |
| 53 | missing.push(join(MUSE_COMMIT_PILOT_EVIDENCE_REL, 'artifacts', name)); |
| 54 | } |
| 55 | } |
| 56 | return missing.length === 0 ? { ok: true } : { ok: false, missing }; |
| 57 | } |
| 58 | |
| 59 | /** |
| 60 | * Parse the generated marker version from a projection file. |
| 61 | * |
| 62 | * @param {string} content |
| 63 | * @returns {string | null} |
| 64 | */ |
| 65 | export function parseGeneratedMarkerVersion(content) { |
| 66 | const firstLine = content.split('\n').find((line) => line.includes('GENERATED FROM CANONICAL FLOW')); |
| 67 | if (!firstLine) return null; |
| 68 | const match = firstLine.match(GENERATED_MARKER_RE); |
| 69 | return match?.[1] ?? null; |
| 70 | } |
| 71 | |
| 72 | /** |
| 73 | * Assert anti-drift diff carries only marker version + one canonical content line change. |
| 74 | * |
| 75 | * @param {string} diffText — unified diff content |
| 76 | * @returns {{ ok: true } | { ok: false; reason: string }} |
| 77 | */ |
| 78 | export function assertCleanAntiDriftDiff(diffText) { |
| 79 | const changedLines = diffText |
| 80 | .split('\n') |
| 81 | .filter((line) => (line.startsWith('-') && !line.startsWith('---')) || (line.startsWith('+') && !line.startsWith('+++'))); |
| 82 | if (changedLines.length !== 4) { |
| 83 | return { ok: false, reason: `expected 4 changed lines (2 pairs), got ${changedLines.length}` }; |
| 84 | } |
| 85 | const minus = changedLines.filter((l) => l.startsWith('-')); |
| 86 | const plus = changedLines.filter((l) => l.startsWith('+')); |
| 87 | if (minus.length !== 2 || plus.length !== 2) { |
| 88 | return { ok: false, reason: 'expected exactly 2 removals and 2 additions' }; |
| 89 | } |
| 90 | const markerMinus = minus.find((l) => l.includes('GENERATED FROM CANONICAL FLOW')); |
| 91 | const markerPlus = plus.find((l) => l.includes('GENERATED FROM CANONICAL FLOW')); |
| 92 | if (!markerMinus || !markerPlus) { |
| 93 | return { ok: false, reason: 'marker line must change (version bump only)' }; |
| 94 | } |
| 95 | if (!markerMinus.includes('@0.1.0') || !markerPlus.includes('@0.2.0')) { |
| 96 | return { ok: false, reason: 'marker must bump 0.1.0 → 0.2.0' }; |
| 97 | } |
| 98 | return { ok: true }; |
| 99 | } |
| 100 | |
| 101 | /** |
| 102 | * Scan rendered bytes for accidental secret leakage (contract §10 security bar). |
| 103 | * |
| 104 | * @param {string} content |
| 105 | * @returns {{ ok: true } | { ok: false; matches: string[] }} |
| 106 | */ |
| 107 | export function assertNoSecretLeakageInProjection(content) { |
| 108 | const lines = content.split('\n'); |
| 109 | const bad = []; |
| 110 | for (const line of lines) { |
| 111 | if (/no secrets/i.test(line)) continue; |
| 112 | if (SECRET_SCAN_RE.test(line)) { |
| 113 | bad.push(line.trim().slice(0, 120)); |
| 114 | } |
| 115 | } |
| 116 | return bad.length === 0 ? { ok: true } : { ok: false, matches: bad }; |
| 117 | } |
| 118 | |
| 119 | /** |
| 120 | * Load pilot workspace projection and validate marker + version. |
| 121 | * |
| 122 | * @param {string} repoRoot |
| 123 | * @param {string} filename |
| 124 | * @param {string} expectedVersion |
| 125 | */ |
| 126 | export function loadAndValidatePilotProjection(repoRoot, filename, expectedVersion) { |
| 127 | const path = join(repoRoot, MUSE_COMMIT_PILOT_EVIDENCE_REL, 'pilot-workspace', filename); |
| 128 | const content = readFileSync(path, 'utf8'); |
| 129 | const version = parseGeneratedMarkerVersion(content); |
| 130 | if (version !== expectedVersion) { |
| 131 | throw new Error(`${filename}: expected marker @${expectedVersion}, got @${version}`); |
| 132 | } |
| 133 | const secretCheck = assertNoSecretLeakageInProjection(content); |
| 134 | if (!secretCheck.ok) { |
| 135 | throw new Error(`${filename}: secret scan failed: ${secretCheck.matches.join('; ')}`); |
| 136 | } |
| 137 | if (!content.includes('GENERATED FROM CANONICAL FLOW flow_overseer_handover@')) { |
| 138 | throw new Error(`${filename}: missing generated marker`); |
| 139 | } |
| 140 | return content; |
| 141 | } |
File History
1 commit
sha256:8915fe406161f95c1681f9469375e7bae5b28c884f00bedbdef65e4b0cd0738d
docs(flow): commit FLOW-V0-SPEC.md hygiene for 7A-INT merge
Human
1 day ago