🎉 init: 小龙的工作空间

This commit is contained in:
大海
2026-06-06 10:40:48 +08:00
commit a188ee1426
3201 changed files with 231817 additions and 0 deletions
+347
View File
@@ -0,0 +1,347 @@
#!/usr/bin/env node
/**
* audit-governance.mjs — GOVERNANCE.md Execution Governance Audit
*
* Checks:
* 1. All task states are legal (7-state machine)
* 2. State transitions are legal (no skipping)
* 3. Stale task detection rules exist
* 4. Blocker management (blocker.md template + schema)
* 5. Execution audit exists (execution-audit.md template)
* 6. Project Health Score formula defined
* 7. Auto-Stop Rule defined
* 8. Governance Quality Gate defined
*
* Usage:
* node scripts/audit-governance.mjs ← standalone
* import { runGovernanceAudit } from './audit-governance.mjs' ← via orchestrator
*/
import { fileURLToPath } from 'url';
import path from 'path';
import fs from 'fs';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const WORKSPACE = path.resolve(__dirname, '..');
const SELF = process.argv[1].replace(/\\/g, '/');
/**
* @typedef {Object} CheckResult
* @property {string} id
* @property {string} name
* @property {'PASS'|'WARN'|'FAIL'} status
* @property {string} evidence
* @property {string} [suggestion]
*/
/** @returns {CheckResult[]} */
export function runGovernanceAudit(workspaceDir) {
const root = workspaceDir || WORKSPACE;
const checks = [];
// ---- Helpers ----
function readFile(rel) {
const p = path.join(root, rel);
if (!fs.existsSync(p)) return null;
return fs.readFileSync(p, 'utf8');
}
function check(prefix, id, name, ok, passEv, failEv, suggestion) {
checks.push({
id: `${prefix}-${id}`,
name,
status: ok ? 'PASS' : 'FAIL',
evidence: ok ? passEv : failEv,
...(ok ? {} : { suggestion: suggestion || `Implement ${id} in GOVERNANCE.md` }),
});
}
function warn(prefix, id, name, evidence, suggestion) {
checks.push({ id: `${prefix}-${id}`, name, status: 'WARN', evidence, suggestion });
}
// ---- Read protocol file ----
const gov = readFile('GOVERNANCE.md');
if (!gov) {
checks.push({
id: 'GV-001',
name: 'GOVERNANCE.md exists',
status: 'FAIL',
evidence: 'GOVERNANCE.md not found in workspace root',
suggestion: 'Create GOVERNANCE.md with the Execution Governance Protocol',
});
return checks;
}
checks.push({
id: 'GV-001',
name: 'GOVERNANCE.md exists',
status: 'PASS',
evidence: `GOVERNANCE.md found (${gov.length} bytes)`,
});
// ---- §1 State Machine ----
const hasStateMachine = /§1 State Machine/.test(gov);
check('GV', '1', '§1 State Machine defined', hasStateMachine,
'Found "§1 State Machine" section',
'Add §1 State Machine section');
// 7 states
const states = ['NOT_STARTED', 'IN_PROGRESS', 'BLOCKED', 'WAITING_DEPENDENCY', 'READY_FOR_REVIEW', 'VERIFIED', 'FAILED', 'ARCHIVED'];
const foundStates = states.filter(s => gov.includes(s));
check('GV', '1a', `§1a ${states.length} states defined (found ${foundStates.length})`, foundStates.length >= states.length,
`All ${states.length} states present: ${foundStates.join(', ')}`,
`Missing states: ${states.filter(s => !gov.includes(s)).join(', ')}`,
'Add missing states to §1.1 Allowed States');
// Mermaid diagram
const hasMermaid = /stateDiagram-v2/.test(gov);
check('GV', '1b', '§1b State transition diagram (mermaid)', hasMermaid,
'Found mermaid stateDiagram-v2 with all legal transitions',
'Add a mermaid stateDiagram-v2 for the state machine');
// Transition table
const hasTransitionTable = /Transition Table/.test(gov) || /§1\.3/.test(gov);
check('GV', '1c', '§1c Transition table (From/To/Condition)', hasTransitionTable,
'Found Transition Table with From/To/Condition columns',
'Add Transition Table (From | To | Condition)');
// Prohibited transitions
const hasProhibited = /Prohibited Transitions/.test(gov) || /§1\.4/.test(gov);
check('GV', '1d', '§1d Prohibited transitions defined', hasProhibited,
'Found "Prohibited Transitions" with ❌ markers for illegal jumps',
'Add "Prohibited Transitions" with explicit ❌ transition violations');
// ---- §2 Heartbeat Rule ----
const hasHeartbeat = /§2 Heartbeat Rule/.test(gov);
check('GV', '2', '§2 Heartbeat Rule defined', hasHeartbeat,
'Found "§2 Heartbeat Rule" section',
'Add §2 Heartbeat Rule section');
// Heartbeat format defined
const hasHeartbeatFormat = /"ts".*"status".*"completed".*"remaining".*"next_action"/.test(gov);
check('GV', '2a', '§2a Heartbeat JSON format defined (ts/status/completed/remaining/next_action)',
hasHeartbeatFormat,
'Heartbeat JSON format found with ts, status, completed, remaining, next_action fields',
'Define heartbeat format as JSON with ts/status/completed/remaining/next_action');
// Stale thresholds
const hasStaleThresholds = /Small[\s\S]*3[0][\s\S]*Medium[\s\S]*2[\s\S]*Large[\s\S]*8/.test(gov);
check('GV', '2b', '§2b Stale thresholds defined (Small=30m, Medium=2h, Large=8h)',
hasStaleThresholds,
'Found stale thresholds: Small=30min/30分钟, Medium=2h/2小时, Large=8h/8小时',
'Add Stale thresholds: Small=30min, Medium=2h, Large=8h');
// progress.log template exists
const progressTmpl = readFile('scripts/templates/progress.log.template');
check('GV', '2c', 'progress.log.template exists', progressTmpl !== null,
'Found scripts/templates/progress.log.template',
'Create scripts/templates/progress.log.template');
// ---- §3 Blocker Management ----
const hasBlockerMgmt = /§3 Blocker Management/.test(gov);
check('GV', '3', '§3 Blocker Management defined', hasBlockerMgmt,
'Found "§3 Blocker Management" section',
'Add §3 Blocker Management section');
// Blocker schema
const hasBlockerSchema = /blocker[\s\S]*root_cause[\s\S]*owner[\s\S]*mitigation[\s\S]*dependency[\s\S]*created_at/.test(gov) || /protocol-reference\/templates\.md[\s\S]*blocker/.test(gov);
check('GV', '3a', '§3a Blocker schema (blocker/root_cause/owner/mitigation/dependency/created_at)',
hasBlockerSchema,
'Blocker schema found in GOVERNANCE.md or protocol-reference/templates.md',
'Define blocker md schema in protocol-reference/templates.md');
// Blocker escalation
const hasBlockerEsc = /Blocker Escalation/.test(gov) || /escalated/.test(gov);
check('GV', '3b', '§3b Blocker escalation defined', hasBlockerEsc,
'Found Blocker Escalation mechanism with escalated: YES/NO',
'Add Blocker Escalation: if escalated=YES, notify user and stop AP');
// blocker.md template exists
const blockerTmpl = readFile('scripts/templates/blocker.md.template');
check('GV', '3c', 'blocker.md.template exists', blockerTmpl !== null,
'Found scripts/templates/blocker.md.template',
'Create scripts/templates/blocker.md.template');
// ---- §4 Replanning Trigger ----
const hasReplan = /§4 Replanning Trigger/.test(gov);
check('GV', '4', '§4 Replanning Trigger defined', hasReplan,
'Found "§4 Replanning Trigger" with R1-R8 conditions',
'Add §4 Replanning Trigger with R1-R8 conditions');
// 8 trigger conditions
const triggerCount = (gov.match(/R\d /g) || []).length;
warn('GV', '4a', `§4a Replan triggers: ${triggerCount} (target: ≥8)`,
`Found ${triggerCount} replan trigger conditions (R1-R? )`,
'Ensure all 8 replan triggers (R1-R8) are defined');
// Replan log entry format
const hasReplanLog = /Replan.*#N/.test(gov) || /replan.*evidence/.test(gov);
check('GV', '4b', '§4b Replan log entry format defined', hasReplanLog,
'Found Replan log entry format with trigger/cause/before/after/impact',
'Define Replan log entry format (trigger, cause, before, after, impact)');
// ---- §5 Scope Explosion ----
const hasScope = /§5 Scope Explosion/.test(gov);
check('GV', '5', '§5 Scope Explosion Detector defined', hasScope,
'Found "§5 Scope Explosion Detector" with S1-S4 detection rules',
'Add §5 Scope Explosion Detector with S1-S4 detection rules');
// ---- §6 Execution Audit ----
const hasAudit = /§6 Execution Audit/.test(gov);
check('GV', '6', '§6 Execution Audit defined', hasAudit,
'Found "§6 Execution Audit" section',
'Add §6 Execution Audit section');
// execution-audit.md template exists
const auditTmpl = readFile('scripts/templates/execution-audit.md.template');
check('GV', '6a', 'execution-audit.md.template exists', auditTmpl !== null,
'Found scripts/templates/execution-audit.md.template',
'Create scripts/templates/execution-audit.md.template');
// ---- §7 Health Score ----
const hasHealth = /§7 Project Health Score/.test(gov);
check('GV', '7', '§7 Project Health Score defined', hasHealth,
'Found "§7 Project Health Score" with 5 dimensions (Delivery/Quality/Parallelism/Dependency/Learning)',
'Add §7 Project Health Score with 5 dimensions');
// All 5 sub-scores
const hasDelivery = /Delivery Score/.test(gov);
const hasQuality = /Quality Score/.test(gov);
const hasParallelism = /Parallelism Score/.test(gov);
const hasDependency = /Dependency Score/.test(gov);
const hasLearning = /Learning Score/.test(gov);
const all5 = hasDelivery && hasQuality && hasParallelism && hasDependency && hasLearning;
check('GV', '7a', '§7a All 5 Health Score dimensions defined (Delivery/Quality/Parallelism/Dependency/Learning)',
all5,
'All 5 dimensions found with formulas',
'Ensure all 5 dimensions: Delivery, Quality, Parallelism, Dependency, Learning');
// Weighted formula
const hasWeighted = /Health Score\s?=\s?Delivery\s*[×x]\s*0\.\d+/.test(gov);
check('GV', '7b', '§7b Weighted final formula defined', hasWeighted,
'Found weighted formula: Health Score = Delivery×0.30 + Quality×0.25 + Parallelism×0.15 + Dependency×0.15 + Learning×0.15',
'Define the weighted sum formula for final Health Score');
// Rating
const hasRating = /EXCELLENT[\s\S]*GOOD[\s\S]*ACCEPTABLE[\s\S]*AT RISK[\s\S]*CRITICAL/.test(gov) || /protocol-reference\/metrics\.md/.test(gov);
check('GV', '7c', '§7c Health Score rating defined (EXCELLENT/GOOD/ACCEPTABLE/AT RISK/CRITICAL)',
hasRating,
'Found 5-level rating in GOVERNANCE.md or protocol-reference/metrics.md',
'Add 5-level rating to protocol-reference/metrics.md');
// ---- §8 Auto-Stop ----
const hasAutoStop = /§8 Auto-Stop/.test(gov);
check('GV', '8', '§8 Auto-Stop Rule defined', hasAutoStop,
'Found "§8 Auto-Stop Rule" with A1-A3 conditions and RECOVERY MODE',
'Add §8 Auto-Stop Rule with A1(>3 failures), A2(Health<60), A3(Critical dep failed)');
// Recovery mode
const hasRecoveryMode = /RECOVERY MODE/.test(gov);
check('GV', '8a', '§8a RECOVERY MODE defined', hasRecoveryMode,
'Found RECOVERY MODE with recovery steps and user approval requirement',
'Add RECOVERY MODE procedure (stop, analyze, plan, user approval)');
// ---- §9 Quality Gate ----
const hasGovGate = /§9 Governance Quality Gate/.test(gov);
check('GV', '9', '§9 Governance Quality Gate defined', hasGovGate,
'Found "§9 Governance Quality Gate" with 8-item checklist',
'Add §9 Governance Quality Gate with 8 pre-output checks');
// ---- §10 State Initialization ----
const hasInit = /§10 Governance State Initialization/.test(gov);
check('GV', '10', '§10 Governance State Initialization defined', hasInit,
'Found "§10 Governance State Initialization" with project start/handoff/override',
'Add §10 Governance State Initialization section');
// ---- §11 Integration ----
const hasIntegration = /§11 Integration Summary/.test(gov);
check('GV', '11', '§11 Integration Summary defined', hasIntegration,
'Found "§11 Integration Summary" with raw diagram and lifecycle',
'Add §11 Integration Summary');
// ---- §11 Integration Summary (re-numbered — §12 was deleted) ----
const hasInt11 = /§11 Integration Summary/.test(gov);
check('GV', '11b', '§11 Integration Summary includes Portfolio ref', hasInt11,
'Found §11 Integration Summary (with governance→portfolio data flow)',
'Portfolio Integration reference is covered by §11 Integration Summary');
// ---- Runtime artifacts scan ----
// Scan for actual progress.log files
const progressLogs = findFiles(root, 'progress.log');
const blockerFiles = findFiles(root, 'blocker.md');
const execAudits = findFiles(root, 'execution-audit.md');
warn('GV', 'RA-progress', `Progress logs found: ${progressLogs.length}`,
progressLogs.length > 0
? `Found ${progressLogs.length} progress.log file(s): ${progressLogs.join(', ')}`
: 'No progress.log files found (expected during active project execution)',
progressLogs.length === 0 ? 'Active projects should have progress.log heartbeat entries' : undefined);
warn('GV', 'RA-blocker', `Blocker files found: ${blockerFiles.length}`,
blockerFiles.length > 0
? `Found ${blockerFiles.length} blocker.md file(s): ${blockerFiles.join(', ')}`
: 'No blocker.md files found',
blockerFiles.length === 0 ? '(no active blockers — good)' : undefined);
warn('GV', 'RA-audit', `Execution audits found: ${execAudits.length}`,
execAudits.length > 0
? `Found ${execAudits.length} execution-audit.md file(s): ${execAudits.join(', ')}`
: 'No execution-audit.md found (expected after first project execution)',
execAudits.length === 0 ? 'Run first project and generate execution-audit.md' : undefined);
// ---- Health Score calculation (from available data) ----
// Without actual project data, report N/A
checks.push({
id: 'GV-HS',
name: 'Project Health Score calculated',
status: 'WARN',
evidence: 'No active project data available for health score calculation. Formula is defined in GOVERNANCE.md §7.',
suggestion: 'Health Score will be calculated during/after project execution',
});
// ---- Summary ----
const passCount = checks.filter(c => c.status === 'PASS').length;
const warnCount = checks.filter(c => c.status === 'WARN').length;
const failCount = checks.filter(c => c.status === 'FAIL').length;
checks.push({
id: 'GV-SUMMARY',
name: `Summary — ${passCount} PASS / ${warnCount} WARN / ${failCount} FAIL`,
status: failCount > 0 ? 'FAIL' : warnCount > 0 ? 'WARN' : 'PASS',
evidence: `${passCount} passed, ${warnCount} warnings, ${failCount} failures`,
});
return checks;
}
/** Recursively find files by name (limited depth) */
function findFiles(dir, filename, depth = 3) {
const results = [];
if (depth <= 0) return results;
try {
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
if (entry.name === filename) {
results.push(path.relative(WORKSPACE, path.join(dir, entry.name)));
}
if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {
results.push(...findFiles(path.join(dir, entry.name), filename, depth - 1));
}
}
} catch { /* skip */ }
return results;
}
// ---- Standalone runner ----
if (SELF.endsWith('/audit-governance.mjs') || SELF.endsWith('\\audit-governance.mjs')) {
const results = runGovernanceAudit(WORKSPACE);
console.log(`\n=== GOVERNANCE.md Audit ===\n`);
for (const r of results) {
const icon = r.status === 'PASS' ? '✅' : r.status === 'WARN' ? '⚠️' : '❌';
console.log(` ${icon} [${r.id}] ${r.name}`);
console.log(` ${r.evidence}`);
if (r.suggestion) console.log(`${r.suggestion}`);
console.log();
}
}