tribunal-kit 6.0.0 → 7.0.0
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/.agent/.manifest.json +78 -0
- package/.agent/ARCHITECTURE.md +19 -241
- package/.agent/agents/accessibility-reviewer.md +23 -16
- package/.agent/agents/ai-code-reviewer.md +25 -21
- package/.agent/agents/anti-pattern-reviewer.md +12 -7
- package/.agent/agents/api-architect.md +1 -0
- package/.agent/agents/backend-specialist.md +23 -22
- package/.agent/agents/cloud-engineer.md +1 -0
- package/.agent/agents/code-archaeologist.md +1 -0
- package/.agent/agents/complexity-reviewer.md +10 -7
- package/.agent/agents/database-architect.md +3 -2
- package/.agent/agents/db-latency-auditor.md +6 -2
- package/.agent/agents/debugger.md +3 -2
- package/.agent/agents/dependency-reviewer.md +1 -0
- package/.agent/agents/devops-engineer.md +9 -8
- package/.agent/agents/documentation-writer.md +6 -5
- package/.agent/agents/explorer-agent.md +1 -0
- package/.agent/agents/frontend-reviewer.md +21 -17
- package/.agent/agents/frontend-specialist.md +23 -20
- package/.agent/agents/game-developer.md +1 -0
- package/.agent/agents/interaction-reviewer.md +10 -5
- package/.agent/agents/logic-reviewer.md +3 -0
- package/.agent/agents/minimalist-reviewer.md +6 -0
- package/.agent/agents/mobile-developer.md +7 -6
- package/.agent/agents/mobile-reviewer.md +14 -13
- package/.agent/agents/orchestrator.md +3 -0
- package/.agent/agents/penetration-tester.md +1 -0
- package/.agent/agents/performance-optimizer.md +6 -5
- package/.agent/agents/performance-reviewer.md +6 -6
- package/.agent/agents/pipeline-reviewer.md +144 -0
- package/.agent/agents/precedence-reviewer.md +1 -0
- package/.agent/agents/product-manager.md +1 -0
- package/.agent/agents/product-owner.md +1 -0
- package/.agent/agents/product-reviewer.md +12 -7
- package/.agent/agents/project-planner.md +3 -0
- package/.agent/agents/qa-automation-engineer.md +50 -43
- package/.agent/agents/resilience-reviewer.md +1 -0
- package/.agent/agents/schema-reviewer.md +1 -0
- package/.agent/agents/security-auditor.md +24 -24
- package/.agent/agents/seo-specialist.md +33 -23
- package/.agent/agents/sql-reviewer.md +5 -4
- package/.agent/agents/supervisor-agent.md +12 -2
- package/.agent/agents/swarm-worker-contracts.md +13 -13
- package/.agent/agents/swarm-worker-registry.md +51 -51
- package/.agent/agents/system-architect.md +1 -0
- package/.agent/agents/test-coverage-reviewer.md +25 -22
- package/.agent/agents/test-engineer.md +12 -11
- package/.agent/agents/throughput-optimizer.md +45 -40
- package/.agent/agents/type-safety-reviewer.md +5 -4
- package/.agent/agents/ui-ux-auditor.md +6 -4
- package/.agent/agents/ui-visual-auditor.md +3 -0
- package/.agent/agents/ux-reviewer.md +11 -6
- package/.agent/agents/visual-reviewer.md +11 -6
- package/.agent/agents/vitals-reviewer.md +5 -4
- package/.agent/history/memory/.memory.idx +3716 -1
- package/.agent/history/memory/MEMORY.md +246 -1
- package/.agent/mcp_config.json +1 -6
- package/.agent/routing_index.json +2034 -263
- package/.agent/rules/GEMINI.md +12 -10
- package/.agent/rules/GEMINI_PLANNER.md +19 -21
- package/.agent/scripts/_colors.js +52 -54
- package/.agent/scripts/_utils.js +52 -53
- package/.agent/scripts/auto_preview.js +39 -43
- package/.agent/scripts/bundle_analyzer.js +47 -60
- package/.agent/scripts/case_law_manager.js +200 -294
- package/.agent/scripts/checklist.js +73 -94
- package/.agent/scripts/cicd_validator.js +305 -0
- package/.agent/scripts/compile_router.py +4 -111
- package/.agent/scripts/context_broker.js +317 -412
- package/.agent/scripts/contract_engine.js +402 -0
- package/.agent/scripts/dependency_analyzer.js +112 -124
- package/.agent/scripts/graph_builder.js +75 -103
- package/.agent/scripts/graph_visualizer.js +10 -12
- package/.agent/scripts/graph_zoom.js +38 -55
- package/.agent/scripts/guardrail_engine.js +195 -145
- package/.agent/scripts/impact_classifier.js +55 -30
- package/.agent/scripts/inner_loop_validator.js +108 -159
- package/.agent/scripts/integrity_manifest.js +59 -67
- package/.agent/scripts/lint_runner.js +65 -75
- package/.agent/scripts/marathon_harness.js +131 -208
- package/.agent/scripts/migrate_skills_frontmatter.py +4 -63
- package/.agent/scripts/minify_context.js +29 -33
- package/.agent/scripts/minimal_change_engine.js +95 -87
- package/.agent/scripts/mutation_runner.js +46 -62
- package/.agent/scripts/pipeline_engine.js +320 -209
- package/.agent/scripts/prompt_compiler.js +118 -93
- package/.agent/scripts/schema_validator.js +73 -121
- package/.agent/scripts/security_scan.js +88 -117
- package/.agent/scripts/session_manager.js +52 -69
- package/.agent/scripts/signal_detector.js +24 -22
- package/.agent/scripts/skill_evolution.js +184 -245
- package/.agent/scripts/skill_integrator.js +35 -48
- package/.agent/scripts/socratic_gate_policy.js +15 -12
- package/.agent/scripts/strengthen_skills.js +29 -33
- package/.agent/scripts/swarm_dispatcher.js +120 -151
- package/.agent/scripts/test_runner.js +54 -56
- package/.agent/scripts/token_budget_broker.js +9 -7
- package/.agent/scripts/trace_engine.js +126 -0
- package/.agent/scripts/verify_all.js +76 -93
- package/.agent/scripts/visual_audit.js +16 -21
- package/.agent/skill_topic_map.json +237 -0
- package/.agent/skills/12-principles-of-animation/SKILL.md +7 -0
- package/.agent/skills/60fps-animation/SKILL.md +7 -0
- package/.agent/skills/accessible-animation/SKILL.md +5 -1
- package/.agent/skills/adapt/SKILL.md +7 -1
- package/.agent/skills/advanced-rag-pipelines/SKILL.md +1 -0
- package/.agent/skills/agent-organizer/SKILL.md +1 -0
- package/.agent/skills/agentic-patterns/SKILL.md +33 -25
- package/.agent/skills/agentic-workflows-2026/SKILL.md +80 -0
- package/.agent/skills/ai-app-hardening/SKILL.md +59 -0
- package/.agent/skills/ai-prompt-injection-defense/SKILL.md +7 -6
- package/.agent/skills/animation-on-scroll/SKILL.md +24 -15
- package/.agent/skills/animation-systems/SKILL.md +11 -10
- package/.agent/skills/antfu-conventions/SKILL.md +7 -2
- package/.agent/skills/api-patterns/SKILL.md +14 -10
- package/.agent/skills/api-security-auditor/SKILL.md +15 -14
- package/.agent/skills/app-builder/SKILL.md +1 -0
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +2 -2
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +12 -12
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +3 -3
- package/.agent/skills/apple-design/SKILL.md +8 -7
- package/.agent/skills/architecture/SKILL.md +3 -2
- package/.agent/skills/audit-and-fix/SKILL.md +8 -5
- package/.agent/skills/authentication-best-practices/SKILL.md +9 -8
- package/.agent/skills/backend-security-expert/SKILL.md +1 -0
- package/.agent/skills/baseline-ui/SKILL.md +8 -7
- package/.agent/skills/bash-linux/SKILL.md +1 -0
- package/.agent/skills/behavioral-modes/SKILL.md +1 -0
- package/.agent/skills/better-colors/SKILL.md +11 -7
- package/.agent/skills/better-typography/SKILL.md +30 -16
- package/.agent/skills/better-ui/SKILL.md +17 -10
- package/.agent/skills/bolder/SKILL.md +6 -0
- package/.agent/skills/brainstorming/SKILL.md +6 -4
- package/.agent/skills/browser-native-ai/SKILL.md +5 -4
- package/.agent/skills/build-primitive/SKILL.md +5 -0
- package/.agent/skills/building-native-ui/SKILL.md +1 -0
- package/.agent/skills/cicd-pro/SKILL.md +2 -1
- package/.agent/skills/clarify/SKILL.md +19 -14
- package/.agent/skills/clean-code/SKILL.md +16 -15
- package/.agent/skills/cloud-architect/SKILL.md +1 -0
- package/.agent/skills/cobejs/SKILL.md +7 -9
- package/.agent/skills/code-review-checklist/SKILL.md +1 -0
- package/.agent/skills/codebase-design/SKILL.md +7 -2
- package/.agent/skills/colorize/SKILL.md +8 -3
- package/.agent/skills/compact-landing/SKILL.md +8 -3
- package/.agent/skills/company-logos/SKILL.md +6 -0
- package/.agent/skills/config-validator/SKILL.md +10 -9
- package/.agent/skills/containerization-pro/SKILL.md +6 -5
- package/.agent/skills/context-engineering-pro/SKILL.md +70 -0
- package/.agent/skills/create-design-md/SKILL.md +13 -5
- package/.agent/skills/critique/SKILL.md +10 -8
- package/.agent/skills/csharp-developer/SKILL.md +1 -0
- package/.agent/skills/data-validation-schemas/SKILL.md +28 -23
- package/.agent/skills/database-design/SKILL.md +2 -1
- package/.agent/skills/delight/SKILL.md +6 -0
- package/.agent/skills/deployment-procedures/SKILL.md +2 -1
- package/.agent/skills/design-lab/SKILL.md +5 -0
- package/.agent/skills/devops-engineer/SKILL.md +3 -2
- package/.agent/skills/devops-incident-responder/SKILL.md +2 -1
- package/.agent/skills/diagnosing-bugs/SKILL.md +12 -2
- package/.agent/skills/distill/SKILL.md +7 -2
- package/.agent/skills/documentation-templates/SKILL.md +3 -2
- package/.agent/skills/domain-modeling/SKILL.md +12 -4
- package/.agent/skills/duckdb-analytical-sql/SKILL.md +59 -0
- package/.agent/skills/edge-ai-mobile/SKILL.md +50 -0
- package/.agent/skills/edge-computing/SKILL.md +9 -8
- package/.agent/skills/emil-design-eng/SKILL.md +43 -27
- package/.agent/skills/error-resilience/SKILL.md +34 -16
- package/.agent/skills/expo-router-v4/SKILL.md +81 -0
- package/.agent/skills/extract-design-system/SKILL.md +12 -11
- package/.agent/skills/fabel-protocol/SKILL.md +24 -17
- package/.agent/skills/fixing-accessibility/SKILL.md +23 -16
- package/.agent/skills/fixing-metadata/SKILL.md +24 -13
- package/.agent/skills/fixing-motion-performance/SKILL.md +7 -5
- package/.agent/skills/framer-motion-expert/SKILL.md +29 -15
- package/.agent/skills/frontend-design/SKILL.md +21 -13
- package/.agent/skills/frontend-security-expert/SKILL.md +1 -0
- package/.agent/skills/game-design-expert/SKILL.md +1 -0
- package/.agent/skills/game-engineering-expert/SKILL.md +1 -0
- package/.agent/skills/generative-ui-expert/SKILL.md +3 -2
- package/.agent/skills/geo-fundamentals/SKILL.md +2 -1
- package/.agent/skills/git-pro/SKILL.md +10 -9
- package/.agent/skills/github-operations/SKILL.md +2 -1
- package/.agent/skills/gpt-taste/SKILL.md +7 -0
- package/.agent/skills/gsap-core/SKILL.md +26 -22
- package/.agent/skills/gsap-frameworks/SKILL.md +6 -5
- package/.agent/skills/gsap-performance/SKILL.md +4 -3
- package/.agent/skills/gsap-plugins/SKILL.md +34 -33
- package/.agent/skills/gsap-react/SKILL.md +9 -8
- package/.agent/skills/gsap-scrolltrigger/SKILL.md +34 -33
- package/.agent/skills/gsap-timeline/SKILL.md +18 -15
- package/.agent/skills/gsap-utils/SKILL.md +25 -24
- package/.agent/skills/harden/SKILL.md +9 -3
- package/.agent/skills/harness-protocol/SKILL.md +1 -0
- package/.agent/skills/i18n-localization/SKILL.md +10 -9
- package/.agent/skills/impeccable/SKILL.md +5 -0
- package/.agent/skills/improve-codebase-architecture/SKILL.md +10 -5
- package/.agent/skills/improve-ui/SKILL.md +12 -5
- package/.agent/skills/intelligent-routing/SKILL.md +7 -6
- package/.agent/skills/knowledge-graph/SKILL.md +1 -0
- package/.agent/skills/landing-page/SKILL.md +1 -0
- package/.agent/skills/lint-and-validate/SKILL.md +9 -4
- package/.agent/skills/llm-engineering/SKILL.md +55 -54
- package/.agent/skills/local-first/SKILL.md +20 -19
- package/.agent/skills/local-first-architecture/SKILL.md +6 -1
- package/.agent/skills/lottie-animation/SKILL.md +7 -3
- package/.agent/skills/marquee-loop/SKILL.md +1 -0
- package/.agent/skills/masked-reveal/SKILL.md +17 -4
- package/.agent/skills/mcp-builder/SKILL.md +13 -10
- package/.agent/skills/micro-interaction/SKILL.md +20 -5
- package/.agent/skills/mobile-design/SKILL.md +26 -15
- package/.agent/skills/monorepo-management/SKILL.md +3 -2
- package/.agent/skills/morphing-icons/SKILL.md +16 -6
- package/.agent/skills/motion-engineering/SKILL.md +19 -15
- package/.agent/skills/nextjs-react-expert/SKILL.md +26 -21
- package/.agent/skills/nodejs-best-practices/SKILL.md +89 -76
- package/.agent/skills/observability/SKILL.md +45 -44
- package/.agent/skills/opentelemetry-observability/SKILL.md +59 -0
- package/.agent/skills/page-transition-animation/SKILL.md +6 -3
- package/.agent/skills/parallel-agents/SKILL.md +7 -2
- package/.agent/skills/performance-profiling/SKILL.md +24 -13
- package/.agent/skills/plan-writing/SKILL.md +1 -0
- package/.agent/skills/platform-engineer/SKILL.md +3 -2
- package/.agent/skills/platform-engineering-opentofu/SKILL.md +68 -0
- package/.agent/skills/playwright-ai-e2e/SKILL.md +60 -0
- package/.agent/skills/playwright-best-practices/SKILL.md +29 -28
- package/.agent/skills/polish/SKILL.md +13 -12
- package/.agent/skills/powershell-windows/SKILL.md +1 -0
- package/.agent/skills/pricing-page/SKILL.md +8 -3
- package/.agent/skills/product-aware-heuristics/SKILL.md +122 -72
- package/.agent/skills/progressive-blur/SKILL.md +9 -4
- package/.agent/skills/project-idioms/SKILL.md +1 -0
- package/.agent/skills/property-based-testing/SKILL.md +58 -0
- package/.agent/skills/python-patterns/SKILL.md +1 -0
- package/.agent/skills/python-pro/SKILL.md +1 -0
- package/.agent/skills/quieter/SKILL.md +6 -0
- package/.agent/skills/react-doctor/SKILL.md +6 -0
- package/.agent/skills/react-specialist/SKILL.md +32 -28
- package/.agent/skills/readme-builder/SKILL.md +1 -0
- package/.agent/skills/realtime-patterns/SKILL.md +34 -33
- package/.agent/skills/red-team-tactics/SKILL.md +1 -0
- package/.agent/skills/redesign-skill/SKILL.md +6 -0
- package/.agent/skills/review-animations/SKILL.md +5 -2
- package/.agent/skills/review-animations/STANDARDS.md +37 -23
- package/.agent/skills/rust-pro/SKILL.md +1 -0
- package/.agent/skills/seo-fundamentals/SKILL.md +4 -3
- package/.agent/skills/server-management/SKILL.md +1 -0
- package/.agent/skills/shadcn-ui-expert/SKILL.md +28 -22
- package/.agent/skills/shape/SKILL.md +9 -2
- package/.agent/skills/skill-creator/SKILL.md +1 -0
- package/.agent/skills/soft-skill/SKILL.md +6 -0
- package/.agent/skills/sounds-on-the-web/SKILL.md +1 -0
- package/.agent/skills/sql-pro/SKILL.md +1 -0
- package/.agent/skills/supabase-postgres-best-practices/SKILL.md +1 -0
- package/.agent/skills/svg-animation/SKILL.md +16 -7
- package/.agent/skills/swiftui-expert/SKILL.md +1 -0
- package/.agent/skills/swiss-design/SKILL.md +5 -0
- package/.agent/skills/system-design-pro/SKILL.md +1 -0
- package/.agent/skills/systematic-debugging/SKILL.md +1 -0
- package/.agent/skills/tailwind-patterns/SKILL.md +25 -11
- package/.agent/skills/taste-skill/SKILL.md +6 -0
- package/.agent/skills/tdd-workflow/SKILL.md +5 -0
- package/.agent/skills/test-result-analyzer/SKILL.md +1 -0
- package/.agent/skills/testing-patterns/SKILL.md +123 -115
- package/.agent/skills/thermo-nuclear-code-quality-review/SKILL.md +5 -0
- package/.agent/skills/thinking-protocol/SKILL.md +3 -0
- package/.agent/skills/to-spring-or-not-to-spring/SKILL.md +9 -8
- package/.agent/skills/transitions-dev/SKILL.md +19 -6
- package/.agent/skills/trend-researcher/SKILL.md +1 -0
- package/.agent/skills/typescript-advanced/SKILL.md +23 -18
- package/.agent/skills/typeset/SKILL.md +10 -1
- package/.agent/skills/ui-reasoning-engine/SKILL.md +67 -48
- package/.agent/skills/ui-skill-packs/SKILL.md +6 -1
- package/.agent/skills/ui-skills-root/SKILL.md +39 -38
- package/.agent/skills/ui-ux-pro-max/SKILL.md +34 -26
- package/.agent/skills/ui-ux-researcher/SKILL.md +1 -0
- package/.agent/skills/vector-search-pgvector/SKILL.md +78 -0
- package/.agent/skills/vue-expert/SKILL.md +22 -19
- package/.agent/skills/vulnerability-scanner/SKILL.md +22 -21
- package/.agent/skills/web-accessibility-auditor/SKILL.md +2 -1
- package/.agent/skills/web-design-guidelines/SKILL.md +16 -10
- package/.agent/skills/web-quality-audit/SKILL.md +5 -0
- package/.agent/skills/webapp-testing/SKILL.md +14 -13
- package/.agent/skills/webgpu-performance/SKILL.md +1 -0
- package/.agent/skills/whimsy-injector/SKILL.md +9 -5
- package/.agent/skills/workflow-optimizer/SKILL.md +1 -0
- package/.agent/skills/zero-trust-passkeys/SKILL.md +90 -0
- package/.agent/templates/DESIGN.md +119 -110
- package/.agent/templates/design-tokens.json +9 -6
- package/.agent/workflows/acf.md +1 -0
- package/.agent/workflows/api-tester.md +1 -0
- package/.agent/workflows/audit.md +1 -0
- package/.agent/workflows/brainstorm.md +1 -0
- package/.agent/workflows/changelog.md +1 -0
- package/.agent/workflows/contract.md +60 -0
- package/.agent/workflows/create.md +1 -0
- package/.agent/workflows/debug.md +1 -0
- package/.agent/workflows/deploy.md +1 -0
- package/.agent/workflows/enhance.md +1 -0
- package/.agent/workflows/fix-ci.md +89 -0
- package/.agent/workflows/fix.md +1 -0
- package/.agent/workflows/generate.md +1 -0
- package/.agent/workflows/marathon.md +1 -0
- package/.agent/workflows/migrate.md +1 -0
- package/.agent/workflows/minimal.md +9 -7
- package/.agent/workflows/orchestrate.md +1 -0
- package/.agent/workflows/performance-benchmarker.md +1 -0
- package/.agent/workflows/pipeline.md +26 -21
- package/.agent/workflows/plan.md +1 -0
- package/.agent/workflows/preview.md +1 -0
- package/.agent/workflows/refactor.md +3 -2
- package/.agent/workflows/review-ai.md +4 -3
- package/.agent/workflows/review.md +1 -0
- package/.agent/workflows/session.md +1 -0
- package/.agent/workflows/status.md +1 -0
- package/.agent/workflows/strengthen-skills.md +1 -0
- package/.agent/workflows/super-prompt.md +1 -0
- package/.agent/workflows/swarm.md +15 -3
- package/.agent/workflows/test.md +8 -7
- package/.agent/workflows/tribunal-backend.md +3 -2
- package/.agent/workflows/tribunal-cicd.md +104 -0
- package/.agent/workflows/tribunal-database.md +1 -0
- package/.agent/workflows/tribunal-frontend.md +8 -6
- package/.agent/workflows/tribunal-full.md +15 -14
- package/.agent/workflows/tribunal-mobile.md +6 -5
- package/.agent/workflows/tribunal-performance.md +1 -0
- package/.agent/workflows/tribunal-speed.md +1 -0
- package/.agent/workflows/tribunal-ui.md +29 -21
- package/.agent/workflows/ui-ux-pro-max.md +19 -15
- package/CONTRIBUTING.md +3 -3
- package/README.md +160 -88
- package/SECURITY.md +11 -11
- package/bin/mcp-server.js +512 -233
- package/bin/tribunal-kit.js +29 -30
- package/bin/wrapper.js +45 -48
- package/dist/cli.js +26 -0
- package/dist/commands/case.js +2 -0
- package/dist/commands/contract.js +440 -0
- package/dist/commands/memory.js +3 -2
- package/dist/commands/native.js +36 -0
- package/dist/commands/status.js +6 -0
- package/dist/esm/index.mjs +32 -0
- package/dist/index.d.ts +58 -3
- package/package.json +20 -16
- package/scripts/benchmark.js +62 -86
- package/scripts/changelog.js +67 -73
- package/scripts/fix-vbc.js +13 -15
- package/scripts/fix-vbc.ps1 +2 -118
- package/scripts/stress_benchmark.js +358 -0
- package/scripts/sync-version.js +71 -41
- package/scripts/validate-payload.js +23 -30
- package/scripts/visual_audit.js +23 -13
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
* const result = validate(text, manifest, options);
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
'use strict';
|
|
26
26
|
|
|
27
|
-
const fs = require(
|
|
28
|
-
const path = require(
|
|
27
|
+
const fs = require('fs');
|
|
28
|
+
const path = require('path');
|
|
29
29
|
|
|
30
30
|
// ── Rule Definitions ──────────────────────────────────────────────────────────
|
|
31
31
|
|
|
@@ -35,20 +35,30 @@ const path = require("path");
|
|
|
35
35
|
*/
|
|
36
36
|
function ruleFileExists(content, manifest, _ctx) {
|
|
37
37
|
const violations = [];
|
|
38
|
-
if (
|
|
38
|
+
if (
|
|
39
|
+
_ctx &&
|
|
40
|
+
_ctx.filePath &&
|
|
41
|
+
(_ctx.filePath.endsWith('.js') ||
|
|
42
|
+
_ctx.filePath.endsWith('.py') ||
|
|
43
|
+
_ctx.filePath.endsWith('.json'))
|
|
44
|
+
) {
|
|
39
45
|
return violations;
|
|
40
46
|
}
|
|
41
47
|
const refs = manifest.cross_references || [];
|
|
42
48
|
|
|
43
|
-
const agentDir = path.join(_ctx.projectRoot,
|
|
44
|
-
const currentRelSource = _ctx.filePath
|
|
49
|
+
const agentDir = path.join(_ctx.projectRoot, '.agent');
|
|
50
|
+
const currentRelSource = _ctx.filePath
|
|
51
|
+
? path.relative(agentDir, _ctx.filePath).replace(/\\/g, '/')
|
|
52
|
+
: null;
|
|
45
53
|
|
|
46
54
|
// Check phantom references from the manifest
|
|
47
|
-
const phantoms = refs.filter(
|
|
55
|
+
const phantoms = refs.filter(
|
|
56
|
+
r => !r.exists && (!currentRelSource || r.source === currentRelSource),
|
|
57
|
+
);
|
|
48
58
|
for (const p of phantoms) {
|
|
49
59
|
violations.push({
|
|
50
|
-
rule:
|
|
51
|
-
severity:
|
|
60
|
+
rule: 'file-exists',
|
|
61
|
+
severity: 'critical',
|
|
52
62
|
location: p.source,
|
|
53
63
|
message: `Phantom reference: "${p.ref}" does not exist`,
|
|
54
64
|
suggestion: null,
|
|
@@ -79,13 +89,13 @@ function ruleScriptExtension(content, manifest, _ctx) {
|
|
|
79
89
|
if (scriptFiles[referencedFile]) continue; // exact match — fine
|
|
80
90
|
|
|
81
91
|
// Check if the OTHER extension exists
|
|
82
|
-
const altExt = referencedExt ===
|
|
92
|
+
const altExt = referencedExt === 'js' ? 'py' : 'js';
|
|
83
93
|
const altFile = `${baseName}.${altExt}`;
|
|
84
94
|
|
|
85
95
|
if (scriptFiles[altFile]) {
|
|
86
96
|
violations.push({
|
|
87
|
-
rule:
|
|
88
|
-
severity:
|
|
97
|
+
rule: 'script-extension',
|
|
98
|
+
severity: 'warning',
|
|
89
99
|
location: `content match: scripts/${referencedFile}`,
|
|
90
100
|
message: `Script "scripts/${referencedFile}" does not exist, but "scripts/${altFile}" does`,
|
|
91
101
|
suggestion: `Replace "scripts/${referencedFile}" with "scripts/${altFile}"`,
|
|
@@ -107,7 +117,8 @@ function ruleReviewerCount(content, manifest, _ctx) {
|
|
|
107
117
|
const actualCount = manifest.agents ? manifest.agents.reviewer_count : null;
|
|
108
118
|
if (actualCount === null) return violations;
|
|
109
119
|
|
|
110
|
-
const countRegex =
|
|
120
|
+
const countRegex =
|
|
121
|
+
/(\d+)\s*(?:-\s*)?(?:(?:parallel|domain(?:-specific)?|tribunal|code)\s+)*reviewers?\b/gi;
|
|
111
122
|
let match;
|
|
112
123
|
while ((match = countRegex.exec(content)) !== null) {
|
|
113
124
|
const claimed = parseInt(match[1], 10);
|
|
@@ -115,8 +126,8 @@ function ruleReviewerCount(content, manifest, _ctx) {
|
|
|
115
126
|
|
|
116
127
|
if (claimed !== actualCount) {
|
|
117
128
|
violations.push({
|
|
118
|
-
rule:
|
|
119
|
-
severity:
|
|
129
|
+
rule: 'reviewer-count',
|
|
130
|
+
severity: 'warning',
|
|
120
131
|
location: `content match: "${match[0]}"`,
|
|
121
132
|
message: `Claims ${claimed} reviewers, but manifest reports ${actualCount}`,
|
|
122
133
|
suggestion: `Replace "${match[0]}" with "${actualCount} reviewers"`,
|
|
@@ -135,7 +146,13 @@ function ruleReviewerCount(content, manifest, _ctx) {
|
|
|
135
146
|
*/
|
|
136
147
|
function ruleSkillExists(content, manifest, _ctx) {
|
|
137
148
|
const violations = [];
|
|
138
|
-
if (
|
|
149
|
+
if (
|
|
150
|
+
_ctx &&
|
|
151
|
+
_ctx.filePath &&
|
|
152
|
+
(_ctx.filePath.endsWith('.js') ||
|
|
153
|
+
_ctx.filePath.endsWith('.py') ||
|
|
154
|
+
_ctx.filePath.endsWith('.json'))
|
|
155
|
+
) {
|
|
139
156
|
return violations;
|
|
140
157
|
}
|
|
141
158
|
const skillNames = new Set(manifest.skills ? manifest.skills.names : []);
|
|
@@ -148,16 +165,16 @@ function ruleSkillExists(content, manifest, _ctx) {
|
|
|
148
165
|
const name = match[1];
|
|
149
166
|
|
|
150
167
|
// Only check names that look like skill names (contain a hyphen, not pure keywords)
|
|
151
|
-
if (!name.includes(
|
|
168
|
+
if (!name.includes('-')) continue;
|
|
152
169
|
// Skip common non-skill patterns
|
|
153
170
|
if (
|
|
154
|
-
name.startsWith(
|
|
155
|
-
name.endsWith(
|
|
156
|
-
name.endsWith(
|
|
157
|
-
name.endsWith(
|
|
158
|
-
name.endsWith(
|
|
159
|
-
name.startsWith(
|
|
160
|
-
name.startsWith(
|
|
171
|
+
name.startsWith('--') ||
|
|
172
|
+
name.endsWith('.md') ||
|
|
173
|
+
name.endsWith('.js') ||
|
|
174
|
+
name.endsWith('.ts') ||
|
|
175
|
+
name.endsWith('.py') ||
|
|
176
|
+
name.startsWith('npm-') ||
|
|
177
|
+
name.startsWith('git-')
|
|
161
178
|
) {
|
|
162
179
|
continue;
|
|
163
180
|
}
|
|
@@ -171,8 +188,8 @@ function ruleSkillExists(content, manifest, _ctx) {
|
|
|
171
188
|
if (!isKnownSkill && !isKnownAgent) {
|
|
172
189
|
// Only flag if it looks like it's being used as a skill/agent reference
|
|
173
190
|
// Check surrounding context for routing-table-like patterns
|
|
174
|
-
const lineStart = content.lastIndexOf(
|
|
175
|
-
const lineEnd = content.indexOf(
|
|
191
|
+
const lineStart = content.lastIndexOf('\n', match.index) + 1;
|
|
192
|
+
const lineEnd = content.indexOf('\n', match.index);
|
|
176
193
|
const line = content.substring(lineStart, lineEnd === -1 ? content.length : lineEnd);
|
|
177
194
|
|
|
178
195
|
// Flag only if the line looks like a routing/reference context
|
|
@@ -181,8 +198,8 @@ function ruleSkillExists(content, manifest, _ctx) {
|
|
|
181
198
|
!/(example|e\.g\.|sample|template|placeholder)/i.test(line)
|
|
182
199
|
) {
|
|
183
200
|
violations.push({
|
|
184
|
-
rule:
|
|
185
|
-
severity:
|
|
201
|
+
rule: 'skill-exists',
|
|
202
|
+
severity: 'info',
|
|
186
203
|
location: `content match: \`${name}\``,
|
|
187
204
|
message: `"${name}" is not a recognized skill or agent name`,
|
|
188
205
|
suggestion: `Verify that "${name}" exists in .agent/skills/ or .agent/agents/`,
|
|
@@ -201,7 +218,13 @@ function ruleSkillExists(content, manifest, _ctx) {
|
|
|
201
218
|
*/
|
|
202
219
|
function ruleAgentExists(content, manifest, _ctx) {
|
|
203
220
|
const violations = [];
|
|
204
|
-
if (
|
|
221
|
+
if (
|
|
222
|
+
_ctx &&
|
|
223
|
+
_ctx.filePath &&
|
|
224
|
+
(_ctx.filePath.endsWith('.js') ||
|
|
225
|
+
_ctx.filePath.endsWith('.py') ||
|
|
226
|
+
_ctx.filePath.endsWith('.json'))
|
|
227
|
+
) {
|
|
205
228
|
return violations;
|
|
206
229
|
}
|
|
207
230
|
const agentNames = new Set(manifest.agents ? manifest.agents.all : []);
|
|
@@ -214,8 +237,8 @@ function ruleAgentExists(content, manifest, _ctx) {
|
|
|
214
237
|
const name = match[1];
|
|
215
238
|
if (!agentNames.has(name)) {
|
|
216
239
|
violations.push({
|
|
217
|
-
rule:
|
|
218
|
-
severity:
|
|
240
|
+
rule: 'agent-exists',
|
|
241
|
+
severity: 'critical',
|
|
219
242
|
location: `content match: agents/${name}.md`,
|
|
220
243
|
message: `Agent "agents/${name}.md" is referenced but does not exist`,
|
|
221
244
|
suggestion: null,
|
|
@@ -233,10 +256,10 @@ function ruleAgentExists(content, manifest, _ctx) {
|
|
|
233
256
|
*/
|
|
234
257
|
function ruleUnresolvedVerify(content, _manifest, ctx) {
|
|
235
258
|
const violations = [];
|
|
236
|
-
|
|
259
|
+
|
|
237
260
|
// Skip this check for the internal .agent files themselves
|
|
238
261
|
// because they contain instructions/comments ABOUT the VERIFY tag.
|
|
239
|
-
if (ctx && ctx.filePath && ctx.filePath.includes(
|
|
262
|
+
if (ctx && ctx.filePath && ctx.filePath.includes('.agent')) {
|
|
240
263
|
return violations;
|
|
241
264
|
}
|
|
242
265
|
|
|
@@ -246,11 +269,11 @@ function ruleUnresolvedVerify(content, _manifest, ctx) {
|
|
|
246
269
|
const verifyMatch = lines[i].match(/\/\/\s*VERIFY:\s*(.+)/);
|
|
247
270
|
if (verifyMatch) {
|
|
248
271
|
violations.push({
|
|
249
|
-
rule:
|
|
250
|
-
severity:
|
|
272
|
+
rule: 'unresolved-verify',
|
|
273
|
+
severity: 'critical',
|
|
251
274
|
location: `line ${i + 1}`,
|
|
252
275
|
message: `Unresolved VERIFY tag: "${verifyMatch[1].trim()}"`,
|
|
253
|
-
suggestion:
|
|
276
|
+
suggestion: 'Resolve this verification before shipping',
|
|
254
277
|
autoFixable: false,
|
|
255
278
|
});
|
|
256
279
|
}
|
|
@@ -265,24 +288,25 @@ function ruleUnresolvedVerify(content, _manifest, ctx) {
|
|
|
265
288
|
*/
|
|
266
289
|
function ruleNumericConsistency(content, manifest, _ctx) {
|
|
267
290
|
const violations = [];
|
|
268
|
-
const agentDir = _ctx && _ctx.projectRoot ? path.join(_ctx.projectRoot,
|
|
269
|
-
const currentRelSource =
|
|
291
|
+
const agentDir = _ctx && _ctx.projectRoot ? path.join(_ctx.projectRoot, '.agent') : '';
|
|
292
|
+
const currentRelSource =
|
|
293
|
+
_ctx && _ctx.filePath ? path.relative(agentDir, _ctx.filePath).replace(/\\/g, '/') : null;
|
|
270
294
|
|
|
271
295
|
const invalidClaims = (manifest.numeric_claims || []).filter(
|
|
272
|
-
|
|
296
|
+
c => !c.valid && (!currentRelSource || c.source.startsWith(currentRelSource + ':')),
|
|
273
297
|
);
|
|
274
298
|
|
|
275
299
|
for (const claim of invalidClaims) {
|
|
276
300
|
violations.push({
|
|
277
|
-
rule:
|
|
278
|
-
severity:
|
|
301
|
+
rule: 'numeric-consistency',
|
|
302
|
+
severity: 'warning',
|
|
279
303
|
location: claim.source,
|
|
280
304
|
message: `Claims "${claim.claim}" but actual count is ${claim.actual}`,
|
|
281
|
-
suggestion: `Update to "${claim.actual} ${claim.claim.replace(/\d+\s*/,
|
|
305
|
+
suggestion: `Update to "${claim.actual} ${claim.claim.replace(/\d+\s*/, '')}"`,
|
|
282
306
|
autoFixable: true,
|
|
283
307
|
fix: {
|
|
284
308
|
find: claim.claim,
|
|
285
|
-
replace: `${claim.actual} ${claim.claim.replace(/\d+\s*/,
|
|
309
|
+
replace: `${claim.actual} ${claim.claim.replace(/\d+\s*/, '')}`,
|
|
286
310
|
},
|
|
287
311
|
});
|
|
288
312
|
}
|
|
@@ -297,17 +321,17 @@ function ruleNumericConsistency(content, manifest, _ctx) {
|
|
|
297
321
|
function ruleImportPhantom(content, _manifest, ctx) {
|
|
298
322
|
const violations = [];
|
|
299
323
|
const projectRoot = ctx.projectRoot;
|
|
300
|
-
const filePath = ctx.filePath ||
|
|
324
|
+
const filePath = ctx.filePath || '';
|
|
301
325
|
|
|
302
326
|
// Only check Javascript/Typescript files for phantom imports
|
|
303
|
-
if (!filePath.endsWith(
|
|
327
|
+
if (!filePath.endsWith('.js') && !filePath.endsWith('.ts')) return violations;
|
|
304
328
|
|
|
305
329
|
// Load package.json dependencies
|
|
306
330
|
let deps = new Set();
|
|
307
331
|
try {
|
|
308
|
-
const pkgPath = path.join(projectRoot,
|
|
332
|
+
const pkgPath = path.join(projectRoot, 'package.json');
|
|
309
333
|
if (fs.existsSync(pkgPath)) {
|
|
310
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath,
|
|
334
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
311
335
|
const allDeps = {
|
|
312
336
|
...(pkg.dependencies || {}),
|
|
313
337
|
...(pkg.devDependencies || {}),
|
|
@@ -324,36 +348,84 @@ function ruleImportPhantom(content, _manifest, ctx) {
|
|
|
324
348
|
|
|
325
349
|
// Node.js built-in modules
|
|
326
350
|
const builtins = new Set([
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
351
|
+
'assert',
|
|
352
|
+
'buffer',
|
|
353
|
+
'child_process',
|
|
354
|
+
'cluster',
|
|
355
|
+
'console',
|
|
356
|
+
'constants',
|
|
357
|
+
'crypto',
|
|
358
|
+
'dgram',
|
|
359
|
+
'dns',
|
|
360
|
+
'domain',
|
|
361
|
+
'events',
|
|
362
|
+
'fs',
|
|
363
|
+
'http',
|
|
364
|
+
'http2',
|
|
365
|
+
'https',
|
|
366
|
+
'module',
|
|
367
|
+
'net',
|
|
368
|
+
'os',
|
|
369
|
+
'path',
|
|
370
|
+
'perf_hooks',
|
|
371
|
+
'process',
|
|
372
|
+
'punycode',
|
|
373
|
+
'querystring',
|
|
374
|
+
'readline',
|
|
375
|
+
'repl',
|
|
376
|
+
'stream',
|
|
377
|
+
'string_decoder',
|
|
378
|
+
'sys',
|
|
379
|
+
'timers',
|
|
380
|
+
'tls',
|
|
381
|
+
'trace_events',
|
|
382
|
+
'tty',
|
|
383
|
+
'url',
|
|
384
|
+
'util',
|
|
385
|
+
'v8',
|
|
386
|
+
'vm',
|
|
387
|
+
'wasi',
|
|
388
|
+
'worker_threads',
|
|
389
|
+
'zlib',
|
|
390
|
+
'node:fs',
|
|
391
|
+
'node:path',
|
|
392
|
+
'node:crypto',
|
|
393
|
+
'node:http',
|
|
394
|
+
'node:https',
|
|
395
|
+
'node:url',
|
|
396
|
+
'node:util',
|
|
397
|
+
'node:os',
|
|
398
|
+
'node:child_process',
|
|
399
|
+
'node:stream',
|
|
400
|
+
'node:events',
|
|
401
|
+
'node:buffer',
|
|
402
|
+
'node:net',
|
|
403
|
+
'node:tls',
|
|
404
|
+
'node:worker_threads',
|
|
405
|
+
'node:readline',
|
|
406
|
+
'node:zlib',
|
|
407
|
+
'node:querystring',
|
|
408
|
+
'node:assert',
|
|
409
|
+
'node:test',
|
|
338
410
|
]);
|
|
339
411
|
|
|
340
412
|
// Find require() and import statements for external packages
|
|
341
413
|
const requireRegex = /require\s*\(\s*['"]([^'"./][^'"]*)['"]\s*\)/g;
|
|
342
414
|
const importRegex = /import\s+(?:[\s\S]*?\s+from\s+)?['"]([^'"./][^'"]*)['"]/g;
|
|
343
415
|
|
|
344
|
-
const checkPackage =
|
|
416
|
+
const checkPackage = regex => {
|
|
345
417
|
let match;
|
|
346
418
|
while ((match = regex.exec(content)) !== null) {
|
|
347
419
|
const pkg = match[1];
|
|
348
420
|
// Extract the package name (handle scoped packages like @scope/name)
|
|
349
|
-
const pkgName = pkg.startsWith(
|
|
350
|
-
? pkg.split(
|
|
351
|
-
: pkg.split(
|
|
421
|
+
const pkgName = pkg.startsWith('@')
|
|
422
|
+
? pkg.split('/').slice(0, 2).join('/')
|
|
423
|
+
: pkg.split('/')[0];
|
|
352
424
|
|
|
353
425
|
if (!builtins.has(pkgName) && !deps.has(pkgName)) {
|
|
354
426
|
violations.push({
|
|
355
|
-
rule:
|
|
356
|
-
severity:
|
|
427
|
+
rule: 'import-phantom',
|
|
428
|
+
severity: 'info',
|
|
357
429
|
location: `content match: "${match[0]}"`,
|
|
358
430
|
message: `Package "${pkgName}" is not in package.json`,
|
|
359
431
|
suggestion: `Verify "${pkgName}" is installed or add it to dependencies`,
|
|
@@ -378,16 +450,16 @@ function ruleRustModuleRegistration(content, manifest, _ctx) {
|
|
|
378
450
|
const violations = [];
|
|
379
451
|
const root = _ctx.projectRoot || process.cwd();
|
|
380
452
|
|
|
381
|
-
const modRs = path.join(root,
|
|
453
|
+
const modRs = path.join(root, 'crates', 'core', 'src', 'commands', 'mod.rs');
|
|
382
454
|
if (fs.existsSync(modRs)) {
|
|
383
|
-
const modContent = fs.readFileSync(modRs,
|
|
384
|
-
const requiredMods = [
|
|
455
|
+
const modContent = fs.readFileSync(modRs, 'utf8');
|
|
456
|
+
const requiredMods = ['context_broker', 'dag_scheduler', 'context_compress'];
|
|
385
457
|
for (const m of requiredMods) {
|
|
386
458
|
if (!modContent.includes(`pub mod ${m};`)) {
|
|
387
459
|
violations.push({
|
|
388
|
-
rule:
|
|
389
|
-
severity:
|
|
390
|
-
location:
|
|
460
|
+
rule: 'rust-module-registration',
|
|
461
|
+
severity: 'warning',
|
|
462
|
+
location: 'crates/core/src/commands/mod.rs',
|
|
391
463
|
message: `Rust command module "${m}" not declared in mod.rs`,
|
|
392
464
|
suggestion: `Add "pub mod ${m};" to crates/core/src/commands/mod.rs`,
|
|
393
465
|
autoFixable: false,
|
|
@@ -396,14 +468,14 @@ function ruleRustModuleRegistration(content, manifest, _ctx) {
|
|
|
396
468
|
}
|
|
397
469
|
}
|
|
398
470
|
|
|
399
|
-
const wrapperJs = path.join(root,
|
|
471
|
+
const wrapperJs = path.join(root, 'bin', 'wrapper.js');
|
|
400
472
|
if (fs.existsSync(wrapperJs)) {
|
|
401
|
-
const wrapperContent = fs.readFileSync(wrapperJs,
|
|
473
|
+
const wrapperContent = fs.readFileSync(wrapperJs, 'utf8');
|
|
402
474
|
if (!wrapperContent.includes('"context-broker"')) {
|
|
403
475
|
violations.push({
|
|
404
|
-
rule:
|
|
405
|
-
severity:
|
|
406
|
-
location:
|
|
476
|
+
rule: 'rust-module-registration',
|
|
477
|
+
severity: 'warning',
|
|
478
|
+
location: 'bin/wrapper.js',
|
|
407
479
|
message: 'Command "context-broker" not registered in RUST_COMMANDS in bin/wrapper.js',
|
|
408
480
|
suggestion: 'Add "context-broker" to RUST_COMMANDS set in bin/wrapper.js',
|
|
409
481
|
autoFixable: false,
|
|
@@ -417,15 +489,15 @@ function ruleRustModuleRegistration(content, manifest, _ctx) {
|
|
|
417
489
|
// ── Rule Registry ─────────────────────────────────────────────────────────────
|
|
418
490
|
|
|
419
491
|
const RULES = {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
492
|
+
'file-exists': ruleFileExists,
|
|
493
|
+
'script-extension': ruleScriptExtension,
|
|
494
|
+
'reviewer-count': ruleReviewerCount,
|
|
495
|
+
'skill-exists': ruleSkillExists,
|
|
496
|
+
'agent-exists': ruleAgentExists,
|
|
497
|
+
'unresolved-verify': ruleUnresolvedVerify,
|
|
498
|
+
'numeric-consistency': ruleNumericConsistency,
|
|
499
|
+
'import-phantom': ruleImportPhantom,
|
|
500
|
+
'rust-module-registration': ruleRustModuleRegistration,
|
|
429
501
|
};
|
|
430
502
|
|
|
431
503
|
// ── Main Validate Function ────────────────────────────────────────────────────
|
|
@@ -443,15 +515,14 @@ const RULES = {
|
|
|
443
515
|
*/
|
|
444
516
|
function validate(content, manifest, options = {}) {
|
|
445
517
|
const {
|
|
446
|
-
rules: ruleFilter = [
|
|
518
|
+
rules: ruleFilter = ['all'],
|
|
447
519
|
autoFix = false,
|
|
448
520
|
context = { projectRoot: process.cwd() },
|
|
449
521
|
} = options;
|
|
450
522
|
|
|
451
|
-
const activeRules =
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
: Object.entries(RULES).filter(([name]) => ruleFilter.includes(name));
|
|
523
|
+
const activeRules = ruleFilter.includes('all')
|
|
524
|
+
? Object.entries(RULES)
|
|
525
|
+
: Object.entries(RULES).filter(([name]) => ruleFilter.includes(name));
|
|
455
526
|
|
|
456
527
|
const allViolations = [];
|
|
457
528
|
|
|
@@ -462,8 +533,8 @@ function validate(content, manifest, options = {}) {
|
|
|
462
533
|
} catch (err) {
|
|
463
534
|
allViolations.push({
|
|
464
535
|
rule: _name,
|
|
465
|
-
severity:
|
|
466
|
-
location:
|
|
536
|
+
severity: 'info',
|
|
537
|
+
location: 'engine',
|
|
467
538
|
message: `Rule "${_name}" threw an error: ${err.message}`,
|
|
468
539
|
suggestion: null,
|
|
469
540
|
autoFixable: false,
|
|
@@ -475,29 +546,27 @@ function validate(content, manifest, options = {}) {
|
|
|
475
546
|
let autoFixedContent = null;
|
|
476
547
|
if (autoFix) {
|
|
477
548
|
autoFixedContent = content;
|
|
478
|
-
const fixableViolations = allViolations.filter(
|
|
479
|
-
(v) => v.autoFixable && v.fix,
|
|
480
|
-
);
|
|
549
|
+
const fixableViolations = allViolations.filter(v => v.autoFixable && v.fix);
|
|
481
550
|
for (const v of fixableViolations) {
|
|
482
551
|
autoFixedContent = autoFixedContent.split(v.fix.find).join(v.fix.replace);
|
|
483
552
|
}
|
|
484
553
|
}
|
|
485
554
|
|
|
486
555
|
// Compute pass/fail
|
|
487
|
-
const hasCritical = allViolations.some(
|
|
488
|
-
const hasWarning = allViolations.some(
|
|
556
|
+
const hasCritical = allViolations.some(v => v.severity === 'critical');
|
|
557
|
+
const hasWarning = allViolations.some(v => v.severity === 'warning');
|
|
489
558
|
|
|
490
559
|
return {
|
|
491
560
|
passed: !hasCritical,
|
|
492
561
|
violations: allViolations,
|
|
493
562
|
autoFixedContent,
|
|
494
563
|
summary: hasCritical
|
|
495
|
-
? `REJECTED — ${allViolations.filter(
|
|
564
|
+
? `REJECTED — ${allViolations.filter(v => v.severity === 'critical').length} critical violation(s)`
|
|
496
565
|
: hasWarning
|
|
497
|
-
? `WARNING — ${allViolations.filter(
|
|
566
|
+
? `WARNING — ${allViolations.filter(v => v.severity === 'warning').length} warning(s), no critical issues`
|
|
498
567
|
: allViolations.length > 0
|
|
499
568
|
? `PASSED — ${allViolations.length} informational note(s)`
|
|
500
|
-
:
|
|
569
|
+
: 'PASSED — clean, no violations',
|
|
501
570
|
};
|
|
502
571
|
}
|
|
503
572
|
|
|
@@ -506,34 +575,27 @@ function validate(content, manifest, options = {}) {
|
|
|
506
575
|
function main() {
|
|
507
576
|
const args = process.argv.slice(2);
|
|
508
577
|
|
|
509
|
-
const fileIdx = args.indexOf(
|
|
510
|
-
const scanMode = args.includes(
|
|
511
|
-
const fixMode = args.includes(
|
|
512
|
-
const jsonMode = args.includes(
|
|
578
|
+
const fileIdx = args.indexOf('--file');
|
|
579
|
+
const scanMode = args.includes('--scan');
|
|
580
|
+
const fixMode = args.includes('--fix');
|
|
581
|
+
const jsonMode = args.includes('--json');
|
|
513
582
|
|
|
514
583
|
// Load or generate manifest
|
|
515
584
|
const projectRoot = process.cwd();
|
|
516
585
|
let manifest;
|
|
517
586
|
|
|
518
|
-
const manifestPath = path.join(
|
|
519
|
-
projectRoot,
|
|
520
|
-
".agent",
|
|
521
|
-
"history",
|
|
522
|
-
"integrity_manifest.json",
|
|
523
|
-
);
|
|
587
|
+
const manifestPath = path.join(projectRoot, '.agent', 'history', 'integrity_manifest.json');
|
|
524
588
|
|
|
525
589
|
if (false && fs.existsSync(manifestPath)) {
|
|
526
|
-
manifest = JSON.parse(fs.readFileSync(manifestPath,
|
|
590
|
+
manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
527
591
|
} else {
|
|
528
592
|
// Generate on the fly
|
|
529
593
|
try {
|
|
530
|
-
const { generateManifest } = require(
|
|
594
|
+
const { generateManifest } = require('./integrity_manifest');
|
|
531
595
|
manifest = generateManifest(projectRoot);
|
|
532
596
|
} catch {
|
|
533
|
-
console.error(
|
|
534
|
-
console.error(
|
|
535
|
-
" Run: node .agent/scripts/integrity_manifest.js first.",
|
|
536
|
-
);
|
|
597
|
+
console.error('❌ Cannot load or generate integrity manifest.');
|
|
598
|
+
console.error(' Run: node .agent/scripts/integrity_manifest.js first.');
|
|
537
599
|
process.exit(1);
|
|
538
600
|
}
|
|
539
601
|
}
|
|
@@ -548,23 +610,19 @@ function main() {
|
|
|
548
610
|
|
|
549
611
|
if (fileIdx !== -1 && args[fileIdx + 1]) {
|
|
550
612
|
filesToCheck.push(path.resolve(args[fileIdx + 1]));
|
|
551
|
-
} else if (fixMode && args[0] && !args[0].startsWith(
|
|
613
|
+
} else if (fixMode && args[0] && !args[0].startsWith('--')) {
|
|
552
614
|
filesToCheck.push(path.resolve(args[0]));
|
|
553
615
|
} else if (scanMode) {
|
|
554
616
|
// Scan all .agent/ markdown files
|
|
555
|
-
const agentDir = path.join(projectRoot,
|
|
617
|
+
const agentDir = path.join(projectRoot, '.agent');
|
|
556
618
|
filesToCheck = walkAgentFiles(agentDir);
|
|
557
619
|
} else {
|
|
558
|
-
console.log(
|
|
559
|
-
console.log(
|
|
560
|
-
" node .agent/scripts/guardrail_engine.js --file <path> Validate a file",
|
|
561
|
-
);
|
|
562
|
-
console.log(
|
|
563
|
-
" node .agent/scripts/guardrail_engine.js --scan Scan all .agent/ files",
|
|
564
|
-
);
|
|
620
|
+
console.log('Usage:');
|
|
621
|
+
console.log(' node .agent/scripts/guardrail_engine.js --file <path> Validate a file');
|
|
565
622
|
console.log(
|
|
566
|
-
|
|
623
|
+
' node .agent/scripts/guardrail_engine.js --scan Scan all .agent/ files',
|
|
567
624
|
);
|
|
625
|
+
console.log(' node .agent/scripts/guardrail_engine.js --fix <path> Auto-fix a file');
|
|
568
626
|
process.exit(0);
|
|
569
627
|
}
|
|
570
628
|
|
|
@@ -579,16 +637,14 @@ function main() {
|
|
|
579
637
|
continue;
|
|
580
638
|
}
|
|
581
639
|
|
|
582
|
-
const content = fs.readFileSync(file,
|
|
640
|
+
const content = fs.readFileSync(file, 'utf8');
|
|
583
641
|
const result = validate(content, manifest, {
|
|
584
642
|
autoFix: fixMode,
|
|
585
643
|
context: { projectRoot, filePath: file },
|
|
586
644
|
});
|
|
587
645
|
|
|
588
646
|
totalViolations += result.violations.length;
|
|
589
|
-
totalCritical += result.violations.filter(
|
|
590
|
-
(v) => v.severity === "critical",
|
|
591
|
-
).length;
|
|
647
|
+
totalCritical += result.violations.filter(v => v.severity === 'critical').length;
|
|
592
648
|
|
|
593
649
|
if (result.violations.length > 0) {
|
|
594
650
|
allResults.push({
|
|
@@ -599,10 +655,8 @@ function main() {
|
|
|
599
655
|
|
|
600
656
|
// Apply auto-fix
|
|
601
657
|
if (fixMode && result.autoFixedContent && result.autoFixedContent !== content) {
|
|
602
|
-
fs.writeFileSync(file, result.autoFixedContent,
|
|
603
|
-
console.log(
|
|
604
|
-
` ✅ Auto-fixed: ${path.relative(projectRoot, file)}`,
|
|
605
|
-
);
|
|
658
|
+
fs.writeFileSync(file, result.autoFixedContent, 'utf8');
|
|
659
|
+
console.log(` ✅ Auto-fixed: ${path.relative(projectRoot, file)}`);
|
|
606
660
|
}
|
|
607
661
|
}
|
|
608
662
|
|
|
@@ -622,12 +676,7 @@ function main() {
|
|
|
622
676
|
for (const result of allResults) {
|
|
623
677
|
console.log(`\n 📄 ${result.file} — ${result.summary}`);
|
|
624
678
|
for (const v of result.violations) {
|
|
625
|
-
const icon =
|
|
626
|
-
v.severity === "critical"
|
|
627
|
-
? "🔴"
|
|
628
|
-
: v.severity === "warning"
|
|
629
|
-
? "🟡"
|
|
630
|
-
: "🔵";
|
|
679
|
+
const icon = v.severity === 'critical' ? '🔴' : v.severity === 'warning' ? '🟡' : '🔵';
|
|
631
680
|
console.log(` ${icon} [${v.rule}] ${v.message}`);
|
|
632
681
|
if (v.suggestion) {
|
|
633
682
|
console.log(` 💡 ${v.suggestion}`);
|
|
@@ -652,11 +701,7 @@ function walkAgentFiles(dir, fileList = []) {
|
|
|
652
701
|
const entries = fs.readdirSync(dir);
|
|
653
702
|
for (const entry of entries) {
|
|
654
703
|
const fullPath = path.join(dir, entry);
|
|
655
|
-
if (
|
|
656
|
-
["node_modules", ".git", "history", ".backups", ".shared"].includes(
|
|
657
|
-
entry,
|
|
658
|
-
)
|
|
659
|
-
) {
|
|
704
|
+
if (['node_modules', '.git', 'history', '.backups', '.shared'].includes(entry)) {
|
|
660
705
|
continue;
|
|
661
706
|
}
|
|
662
707
|
|
|
@@ -664,7 +709,12 @@ function walkAgentFiles(dir, fileList = []) {
|
|
|
664
709
|
const stat = fs.statSync(fullPath);
|
|
665
710
|
if (stat.isDirectory()) {
|
|
666
711
|
walkAgentFiles(fullPath, fileList);
|
|
667
|
-
} else if (
|
|
712
|
+
} else if (
|
|
713
|
+
entry.endsWith('.md') ||
|
|
714
|
+
entry.endsWith('.json') ||
|
|
715
|
+
entry.endsWith('.js') ||
|
|
716
|
+
entry.endsWith('.py')
|
|
717
|
+
) {
|
|
668
718
|
fileList.push(fullPath);
|
|
669
719
|
}
|
|
670
720
|
} catch {
|