🎉 init: 小龙的工作空间
This commit is contained in:
@@ -0,0 +1,249 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* audit-agents.mjs — AGENTS.md Execution Protocol Audit
|
||||
*
|
||||
* Checks:
|
||||
* 1. Task Tree exists (§1)
|
||||
* 2. Agent Package isolation requirements
|
||||
* 3. No XL Package (context budget forbids it)
|
||||
* 4. Injected Risks mechanism (§1e / §3b)
|
||||
* 5. Quality Gate completeness (§5)
|
||||
*
|
||||
* Usage:
|
||||
* node scripts/audit-agents.mjs ← standalone
|
||||
* import { runAgentAudit } from './audit-agents.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 runAgentAudit(workspaceDir) {
|
||||
const root = workspaceDir || WORKSPACE;
|
||||
const checks = [];
|
||||
|
||||
// ---- Helper ----
|
||||
function readAgents() {
|
||||
const p = path.join(root, 'AGENTS.md');
|
||||
if (!fs.existsSync(p)) return null;
|
||||
return fs.readFileSync(p, 'utf8');
|
||||
}
|
||||
|
||||
function check(prefix, id, name, condition, evidence, suggestion) {
|
||||
checks.push({
|
||||
id: `${prefix}-${id}`,
|
||||
name,
|
||||
status: condition ? 'PASS' : 'FAIL',
|
||||
evidence: condition ? evidence : `File found but missing: ${evidence}`,
|
||||
...(condition ? {} : { suggestion: suggestion || `Ensure §${id} is properly defined in AGENTS.md` }),
|
||||
});
|
||||
}
|
||||
|
||||
function warn(prefix, id, name, evidence, suggestion) {
|
||||
checks.push({
|
||||
id: `${prefix}-${id}`,
|
||||
name,
|
||||
status: 'WARN',
|
||||
evidence,
|
||||
suggestion,
|
||||
});
|
||||
}
|
||||
|
||||
// ---- Read AGENTS.md ----
|
||||
const agents = readAgents();
|
||||
if (!agents) {
|
||||
checks.push({
|
||||
id: 'AG-001',
|
||||
name: 'AGENTS.md exists',
|
||||
status: 'FAIL',
|
||||
evidence: 'AGENTS.md not found in workspace root',
|
||||
suggestion: 'Create AGENTS.md with the Execution Protocol',
|
||||
});
|
||||
return checks;
|
||||
}
|
||||
checks.push({
|
||||
id: 'AG-001',
|
||||
name: 'AGENTS.md exists',
|
||||
status: 'PASS',
|
||||
evidence: `AGENTS.md found (${agents.length} bytes)`,
|
||||
});
|
||||
|
||||
// ---- §0 Complexity Classification ----
|
||||
const hasClassify = /###\s*0\.\s*Complexity Classification/.test(agents);
|
||||
check('AG', '0', '§0 Complexity Classification defined', hasClassify,
|
||||
'Found "### 0. Complexity Classification" with Simple/Complex criteria',
|
||||
'Add "### 0. Complexity Classification" with Simple→Direct / Complex→Task Tree decision rules');
|
||||
|
||||
// Detect if the "if uncertain → treat as Complex" rule exists
|
||||
const hasUncertainRule = /if uncertain → treat as Complex/i.test(agents) || /if uncertain.*complex/i.test(agents);
|
||||
check('AG', '0b', '§0 Uncertainty fallback ("if uncertain → treat as Complex")', hasUncertainRule,
|
||||
'Uncertainty fallback rule found',
|
||||
'Add decision rule: "if uncertain → treat as Complex"');
|
||||
|
||||
// ---- §1 Task Tree ----
|
||||
const hasTaskTree = /###\s*1\.\s*Task Tree/.test(agents);
|
||||
check('AG', '1', '§1 Task Tree Construction defined', hasTaskTree,
|
||||
'Found "### 1. Task Tree Construction" with Task Tree definition',
|
||||
'Add "### 1. Task Tree Construction" defining the execution tree');
|
||||
|
||||
// Task Tree Quality Gate (7 checks)
|
||||
const hasTaskTreeGate = /Task Tree Quality Gate/.test(agents);
|
||||
check('AG', '1f', '§1f Task Tree Quality Gate (7 checks)', hasTaskTreeGate,
|
||||
'Found Task Tree Quality Gate with 7 verification items',
|
||||
'Add §1f Quality Gate checklist (Root Task / No orphan / No circular / No XL / No unjust serial / Risks populated / No human dep)');
|
||||
|
||||
// ---- §2 PLAN ----
|
||||
const hasPlan = /###\s*2\.\s*Planning Protocol/.test(agents);
|
||||
check('AG', '2', '§2 Planning Protocol defined', hasPlan,
|
||||
'Found "### 2. Planning Protocol" with Goal/Subtasks/Risks/Verify',
|
||||
'Add "### 2. Planning Protocol" section');
|
||||
|
||||
// ---- §3 Pre-flight ----
|
||||
const hasPreflight = /###\s*3\.\s*Pre-flight/.test(agents);
|
||||
check('AG', '3', '§3 Pre-flight Check defined', hasPreflight,
|
||||
'Found "### 3. Pre-flight Check" with Dependency Scan / Learning Context / Domain Checklists',
|
||||
'Add "### 3. Pre-flight Check" section');
|
||||
|
||||
// 3a Dependency Scan
|
||||
const hasDepScan = /####\s*3a\.\s*Dependency Scan/.test(agents);
|
||||
check('AG', '3a', '§3a Dependency Scan defined', hasDepScan,
|
||||
'Found §3a Dependency Scan',
|
||||
'Add §3a Dependency Scan (files/tables, dependencies, blast radius)');
|
||||
|
||||
// 3b Learning Context Injector
|
||||
const hasLearningCtx = /####\s*3b\.\s*Learning Context Injector/.test(agents);
|
||||
check('AG', '3b', '§3b Learning Context Injector (3 searches)', hasLearningCtx,
|
||||
'Found §3b Learning Context Injector with 3 mandatory searches',
|
||||
'Add §3b with 3 searches: similar failures, best practices, playbooks');
|
||||
|
||||
// 3c Domain Checklists
|
||||
const hasDomainChecklists = /####\s*3c\.\s*Domain Checklist Injection/.test(agents);
|
||||
check('AG', '3c', '§3c Domain Checklists with ⚠️ Hard Rules', hasDomainChecklists,
|
||||
'Found §3c Domain Checklist Injection with SQL/JS/Next.js/Backend/Generator/Release checklists',
|
||||
'Add §3c with at least SQL, JS/TS, Next.js, Backend, Generator, Release checklists');
|
||||
|
||||
// Hard Rules exist
|
||||
const hardRuleCount = (agents.match(/⚠️\s*HARD RULE/g) || []).length;
|
||||
warn('AG', '3c-hard', `§3c Hard Rules count: ${hardRuleCount} (target: ≥5)`,
|
||||
`Found ${hardRuleCount} ⚠️ HARD RULE markers`,
|
||||
'Promote recurring patterns to Hard Rules. Target ≥5.');
|
||||
|
||||
// ---- §4 Failure Replanning ----
|
||||
const hasReplan = /###\s*4\.\s*Failure Replanning Protocol/.test(agents);
|
||||
check('AG', '4', '§4 Failure Replanning Protocol defined', hasReplan,
|
||||
'Found "### 4. Failure Replanning Protocol" with local/structural replan logic',
|
||||
'Add "### 4. Failure Replanning Protocol"');
|
||||
|
||||
// ---- §5 Verification Protocol ----
|
||||
const hasVerification = /###\s*5\.\s*Verification Protocol/.test(agents);
|
||||
check('AG', '5', '§5 Verification Protocol defined', hasVerification,
|
||||
'Found "### 5. Verification Protocol" with Build/Tests/Lint/Regression/Manual checks',
|
||||
'Add "### 5. Verification Protocol" with the verification block format');
|
||||
|
||||
// Quality Gate in Verification
|
||||
const hasQualityGate = /Pre-flight Compliance Check/.test(agents) || /Quality Gate/.test(agents);
|
||||
check('AG', '5b', '§5 Pre-flight Compliance / Quality Gate', hasQualityGate,
|
||||
'Found "Pre-flight Compliance Check" with 5 mandatory gates',
|
||||
'Add Quality Gate checklist within §5: PLAN has Injected Risks, ≥2 sources searched, domain checklist, reflection, 7-field reflection');
|
||||
|
||||
// ---- §6 Governance Compliance ----
|
||||
const hasGovernance = /###\s*6\.\s*Governance Compliance/.test(agents);
|
||||
check('AG', '6', '§6 Governance Compliance defined', hasGovernance,
|
||||
'Found "### 6. Governance Compliance" with State Machine / Heartbeat / Quality Gate',
|
||||
'Add "### 6. Governance Compliance" referencing GOVERNANCE.md');
|
||||
|
||||
// ---- §7 Auto-Capture ----
|
||||
const hasAutoCapture = /###\s*7\.\s*Auto-Capture Trigger/.test(agents);
|
||||
check('AG', '7', '§7 Auto-Capture Trigger defined', hasAutoCapture,
|
||||
'Found "### 7. Auto-Capture Trigger" with T1-T7 trigger conditions',
|
||||
'Add "### 7. Auto-Capture Trigger" with 7 trigger conditions and skip rules');
|
||||
|
||||
// ---- Learning Loop ----
|
||||
const hasLearningLoop = /## Learning Loop/.test(agents);
|
||||
check('AG', 'LL', 'Learning Loop (🔄) defined', hasLearningLoop,
|
||||
'Found "## Learning Loop 🔄" with Loop Architecture / Promotion Rules / Reflection Quality Gate / Storage Locations',
|
||||
'Add "## Learning Loop 🔄" section');
|
||||
|
||||
// Promotion Rules (1→2→3→4→5)
|
||||
const hasPromotion = /Promotion Rules/.test(agents) && /1st.*Reflection/.test(agents) && /5th.*Hard Rule/.test(agents);
|
||||
check('AG', 'LL-promo', 'Promotion Rules (1→2→3→4→5 appearances)', hasPromotion,
|
||||
'Found Promotion Rules chart with 1st=Reflection through 5th=Hard Rule',
|
||||
'Add Promotion Rules table mapping appearance count to promotion destination');
|
||||
|
||||
// ---- Context Budget ----
|
||||
const hasBudget = /## Agent Package Context Budget/.test(agents);
|
||||
check('AG', 'CB', 'Agent Package Context Budget defined', hasBudget,
|
||||
'Found "## Agent Package Context Budget ⚠️ HARD RULE" with size→token map',
|
||||
'Add "## Agent Package Context Budget" section');
|
||||
|
||||
// No XL
|
||||
const forbidsXL = /XL.*FORBIDDEN/.test(agents) || /XL.*❌/.test(agents);
|
||||
check('AG', 'CB-noxl', 'XL Package explicitly forbidden', forbidsXL,
|
||||
'Found "XL | ❌ FORBIDDEN" in Context Budget table',
|
||||
'Add "XL | ❌ FORBIDDEN" row to the Size→Token Budget Mapping table');
|
||||
|
||||
// Input Size Pre-check
|
||||
const hasPrecheck = /Input Size Pre-check/.test(agents);
|
||||
check('AG', 'CB-precheck', 'Input Size Pre-check (Context Budget Declaration)', hasPrecheck,
|
||||
'Found "Input Size Pre-check" with Context Budget Declaration template',
|
||||
'Add "Input Size Pre-check" section with file inventory / token estimate / budget check');
|
||||
|
||||
// ---- Cross-reference integrity ----
|
||||
const refsGovernance = (agents.match(/GOVERNANCE\.md/g) || []).length;
|
||||
warn('AG', 'XR-gov', `Cross-references to GOVERNANCE.md: ${refsGovernance} (target: ≥3)`,
|
||||
`Found ${refsGovernance} references to GOVERNANCE.md`,
|
||||
'Add cross-references from AGENTS.md to GOVERNANCE.md in §6');
|
||||
|
||||
const refsPortfolio = (agents.match(/PORTFOLIO\.md/g) || []).length;
|
||||
warn('AG', 'XR-port', `Cross-references to PORTFOLIO.md: ${refsPortfolio} (target: ≥1)`,
|
||||
`Found ${refsPortfolio} references to PORTFOLIO.md`,
|
||||
'Add cross-reference to PORTFOLIO.md in §6e Reference section');
|
||||
|
||||
// ---- Injected Risks (target check) ----
|
||||
const hasInjectedRisks = /Injected Risks/.test(agents);
|
||||
check('AG', 'IR', 'Injected Risks mechanism defined', hasInjectedRisks,
|
||||
'Found "### Injected Risks" / "### Per-Task Injected Risks"',
|
||||
'Add "### Injected Risks (from Learning Context)" format in §1e and §3b');
|
||||
|
||||
// ---- 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: 'AG-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;
|
||||
}
|
||||
|
||||
// ---- Standalone runner ----
|
||||
if (SELF.endsWith('/audit-agents.mjs') || SELF.endsWith('\\audit-agents.mjs')) {
|
||||
const results = runAgentAudit(WORKSPACE);
|
||||
console.log(`\n=== AGENTS.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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user