tribunal-kit 5.8.4 → 6.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/ARCHITECTURE.md +219 -215
- package/.agent/agents/accessibility-reviewer.md +66 -151
- package/.agent/agents/ai-code-reviewer.md +22 -2
- package/.agent/agents/anti-pattern-reviewer.md +99 -0
- package/.agent/agents/api-architect.md +19 -2
- package/.agent/agents/backend-specialist.md +25 -3
- package/.agent/agents/cloud-engineer.md +21 -0
- package/.agent/agents/code-archaeologist.md +20 -3
- package/.agent/agents/complexity-reviewer.md +22 -2
- package/.agent/agents/database-architect.md +24 -3
- package/.agent/agents/db-latency-auditor.md +22 -2
- package/.agent/agents/debugger.md +19 -3
- package/.agent/agents/dependency-reviewer.md +19 -2
- package/.agent/agents/devops-engineer.md +24 -3
- package/.agent/agents/documentation-writer.md +21 -3
- package/.agent/agents/explorer-agent.md +21 -3
- package/.agent/agents/frontend-reviewer.md +19 -3
- package/.agent/agents/frontend-specialist.md +72 -224
- package/.agent/agents/game-developer.md +22 -3
- package/.agent/agents/interaction-reviewer.md +118 -0
- package/.agent/agents/logic-reviewer.md +18 -3
- package/.agent/agents/minimalist-reviewer.md +98 -0
- package/.agent/agents/mobile-developer.md +21 -3
- package/.agent/agents/mobile-reviewer.md +22 -2
- package/.agent/agents/orchestrator.md +19 -3
- package/.agent/agents/penetration-tester.md +22 -3
- package/.agent/agents/performance-optimizer.md +21 -3
- package/.agent/agents/performance-reviewer.md +2 -0
- package/.agent/agents/precedence-reviewer.md +19 -5
- package/.agent/agents/product-manager.md +20 -3
- package/.agent/agents/product-owner.md +22 -1
- package/.agent/agents/product-reviewer.md +98 -0
- package/.agent/agents/project-planner.md +19 -3
- package/.agent/agents/qa-automation-engineer.md +24 -3
- package/.agent/agents/resilience-reviewer.md +21 -2
- package/.agent/agents/schema-reviewer.md +21 -2
- package/.agent/agents/security-auditor.md +7 -1
- package/.agent/agents/seo-specialist.md +18 -3
- package/.agent/agents/sql-reviewer.md +22 -2
- package/.agent/agents/supervisor-agent.md +22 -3
- package/.agent/agents/swarm-worker-registry.md +7 -0
- package/.agent/agents/system-architect.md +19 -0
- package/.agent/agents/test-coverage-reviewer.md +22 -2
- package/.agent/agents/test-engineer.md +21 -2
- package/.agent/agents/throughput-optimizer.md +22 -2
- package/.agent/agents/type-safety-reviewer.md +21 -2
- package/.agent/agents/ui-ux-auditor.md +44 -242
- package/.agent/agents/ui-visual-auditor.md +99 -0
- package/.agent/agents/ux-reviewer.md +104 -0
- package/.agent/agents/visual-reviewer.md +98 -0
- package/.agent/agents/vitals-reviewer.md +23 -2
- package/.agent/history/README.md +53 -0
- package/.agent/history/case-law/cases/template-case.json +19 -0
- package/.agent/history/integrity_manifest.json +131 -33
- package/.agent/history/memory/.memory.idx +1581 -1
- package/.agent/history/memory/MEMORY.md +105 -1
- package/.agent/routing_index.json +272 -690
- package/.agent/rules/GEMINI.md +10 -12
- package/.agent/rules/GEMINI_PLANNER.md +84 -0
- package/.agent/scripts/_utils.js +28 -7
- package/.agent/scripts/case_law_manager.js +2 -0
- package/.agent/scripts/context_broker.js +152 -19
- package/.agent/scripts/guardrail_engine.js +60 -5
- package/.agent/scripts/impact_classifier.js +167 -0
- package/.agent/scripts/integrity_manifest.js +10 -4
- package/.agent/scripts/marathon_harness.js +10 -1
- package/.agent/scripts/minimal_change_engine.js +437 -0
- package/.agent/scripts/pipeline_engine.js +856 -0
- package/.agent/scripts/skill_evolution.js +36 -21
- package/.agent/scripts/socratic_gate_policy.js +60 -0
- package/.agent/scripts/swarm_dispatcher.js +65 -6
- package/.agent/scripts/token_budget_broker.js +52 -0
- package/.agent/scripts/verify_all.js +13 -0
- package/.agent/scripts/visual_audit.js +92 -0
- package/.agent/skills/12-principles-of-animation/SKILL.md +19 -10
- package/.agent/skills/60fps-animation/SKILL.md +19 -10
- package/.agent/skills/accessible-animation/SKILL.md +19 -10
- package/.agent/skills/adapt/SKILL.md +19 -10
- package/.agent/skills/advanced-rag-pipelines/SKILL.md +21 -3
- package/.agent/skills/agent-organizer/SKILL.md +21 -7
- package/.agent/skills/agentic-patterns/SKILL.md +19 -7
- package/.agent/skills/ai-prompt-injection-defense/SKILL.md +21 -7
- package/.agent/skills/animation-on-scroll/SKILL.md +19 -10
- package/.agent/skills/animation-systems/SKILL.md +19 -10
- package/.agent/skills/antfu-conventions/SKILL.md +21 -10
- package/.agent/skills/api-patterns/SKILL.md +21 -7
- package/.agent/skills/api-patterns/scripts/__pycache__/api_validator.cpython-311.pyc +0 -0
- package/.agent/skills/api-security-auditor/SKILL.md +21 -7
- package/.agent/skills/app-builder/SKILL.md +21 -7
- package/.agent/skills/apple-design/SKILL.md +19 -10
- package/.agent/skills/architecture/SKILL.md +21 -7
- package/.agent/skills/audit-and-fix/SKILL.md +19 -10
- package/.agent/skills/authentication-best-practices/SKILL.md +21 -7
- package/.agent/skills/backend-security-expert/SKILL.md +21 -7
- package/.agent/skills/baseline-ui/SKILL.md +19 -10
- package/.agent/skills/bash-linux/SKILL.md +21 -7
- package/.agent/skills/behavioral-modes/SKILL.md +19 -7
- package/.agent/skills/better-colors/SKILL.md +31 -14
- package/.agent/skills/better-ui/SKILL.md +19 -10
- package/.agent/skills/bolder/SKILL.md +19 -10
- package/.agent/skills/brainstorming/SKILL.md +17 -7
- package/.agent/skills/browser-native-ai/SKILL.md +19 -3
- package/.agent/skills/build-primitive/SKILL.md +19 -10
- package/.agent/skills/building-native-ui/SKILL.md +21 -7
- package/.agent/skills/cicd-pro/SKILL.md +21 -10
- package/.agent/skills/clarify/SKILL.md +19 -10
- package/.agent/skills/clean-code/SKILL.md +21 -7
- package/.agent/skills/cloud-architect/SKILL.md +21 -10
- package/.agent/skills/cobejs/SKILL.md +19 -10
- package/.agent/skills/code-review-checklist/SKILL.md +21 -7
- package/.agent/skills/codebase-design/SKILL.md +21 -10
- package/.agent/skills/colorize/SKILL.md +19 -10
- package/.agent/skills/compact-landing/SKILL.md +19 -10
- package/.agent/skills/company-logos/SKILL.md +19 -10
- package/.agent/skills/config-validator/SKILL.md +21 -7
- package/.agent/skills/containerization-pro/SKILL.md +21 -10
- package/.agent/skills/create-design-md/SKILL.md +19 -10
- package/.agent/skills/critique/SKILL.md +19 -10
- package/.agent/skills/csharp-developer/SKILL.md +21 -7
- package/.agent/skills/data-validation-schemas/SKILL.md +21 -7
- package/.agent/skills/database-design/SKILL.md +21 -7
- package/.agent/skills/database-design/scripts/__pycache__/schema_validator.cpython-311.pyc +0 -0
- package/.agent/skills/delight/SKILL.md +19 -10
- package/.agent/skills/deployment-procedures/SKILL.md +21 -7
- package/.agent/skills/design-lab/SKILL.md +21 -10
- package/.agent/skills/devops-engineer/SKILL.md +21 -7
- package/.agent/skills/devops-incident-responder/SKILL.md +21 -7
- package/.agent/skills/diagnosing-bugs/SKILL.md +21 -10
- package/.agent/skills/distill/SKILL.md +19 -10
- package/.agent/skills/documentation-templates/SKILL.md +21 -7
- package/.agent/skills/domain-modeling/SKILL.md +21 -10
- package/.agent/skills/edge-computing/SKILL.md +21 -7
- package/.agent/skills/emil-design-eng/SKILL.md +19 -10
- package/.agent/skills/error-resilience/SKILL.md +21 -7
- package/.agent/skills/extract-design-system/SKILL.md +21 -7
- package/.agent/skills/fabel-protocol/SKILL.md +19 -2
- package/.agent/skills/fixing-accessibility/SKILL.md +25 -14
- package/.agent/skills/fixing-metadata/SKILL.md +19 -10
- package/.agent/skills/fixing-motion-performance/SKILL.md +19 -10
- package/.agent/skills/framer-motion-expert/SKILL.md +19 -6
- package/.agent/skills/frontend-design/SKILL.md +66 -204
- package/.agent/skills/frontend-design/scripts/__pycache__/accessibility_checker.cpython-311.pyc +0 -0
- package/.agent/skills/frontend-design/scripts/__pycache__/ux_audit.cpython-311.pyc +0 -0
- package/.agent/skills/frontend-security-expert/SKILL.md +21 -7
- package/.agent/skills/game-design-expert/SKILL.md +21 -7
- package/.agent/skills/game-engineering-expert/SKILL.md +21 -7
- package/.agent/skills/generative-ui-expert/SKILL.md +19 -3
- package/.agent/skills/geo-fundamentals/SKILL.md +21 -7
- package/.agent/skills/geo-fundamentals/scripts/__pycache__/geo_checker.cpython-311.pyc +0 -0
- package/.agent/skills/git-pro/SKILL.md +21 -10
- package/.agent/skills/github-operations/SKILL.md +21 -7
- package/.agent/skills/gpt-taste/SKILL.md +19 -10
- package/.agent/skills/gsap-core/SKILL.md +21 -4
- package/.agent/skills/gsap-frameworks/SKILL.md +21 -4
- package/.agent/skills/gsap-performance/SKILL.md +20 -5
- package/.agent/skills/gsap-plugins/SKILL.md +20 -5
- package/.agent/skills/gsap-react/SKILL.md +20 -5
- package/.agent/skills/gsap-scrolltrigger/SKILL.md +21 -4
- package/.agent/skills/gsap-timeline/SKILL.md +20 -5
- package/.agent/skills/gsap-utils/SKILL.md +20 -5
- package/.agent/skills/harden/SKILL.md +19 -10
- package/.agent/skills/harness-protocol/SKILL.md +20 -4
- package/.agent/skills/i18n-localization/SKILL.md +21 -7
- package/.agent/skills/i18n-localization/scripts/__pycache__/i18n_checker.cpython-311.pyc +0 -0
- package/.agent/skills/impeccable/SKILL.md +21 -10
- package/.agent/skills/improve-codebase-architecture/SKILL.md +21 -10
- package/.agent/skills/improve-ui/SKILL.md +19 -10
- package/.agent/skills/intelligent-routing/SKILL.md +19 -7
- package/.agent/skills/knowledge-graph/SKILL.md +20 -4
- package/.agent/skills/landing-page/SKILL.md +20 -10
- package/.agent/skills/lint-and-validate/SKILL.md +21 -7
- package/.agent/skills/lint-and-validate/scripts/__pycache__/lint_runner.cpython-311.pyc +0 -0
- package/.agent/skills/lint-and-validate/scripts/__pycache__/type_coverage.cpython-311.pyc +0 -0
- package/.agent/skills/llm-engineering/SKILL.md +21 -7
- package/.agent/skills/local-first/SKILL.md +21 -7
- package/.agent/skills/local-first-architecture/SKILL.md +19 -10
- package/.agent/skills/lottie-animation/SKILL.md +19 -10
- package/.agent/skills/marquee-loop/SKILL.md +19 -10
- package/.agent/skills/masked-reveal/SKILL.md +19 -10
- package/.agent/skills/mcp-builder/SKILL.md +21 -7
- package/.agent/skills/micro-interaction/SKILL.md +19 -10
- package/.agent/skills/mobile-design/SKILL.md +21 -6
- package/.agent/skills/mobile-design/scripts/__pycache__/mobile_audit.cpython-311.pyc +0 -0
- package/.agent/skills/monorepo-management/SKILL.md +21 -7
- package/.agent/skills/morphing-icons/SKILL.md +19 -10
- package/.agent/skills/motion-engineering/SKILL.md +86 -171
- package/.agent/skills/nextjs-react-expert/SKILL.md +19 -7
- package/.agent/skills/nextjs-react-expert/scripts/__pycache__/convert_rules.cpython-311.pyc +0 -0
- package/.agent/skills/nextjs-react-expert/scripts/__pycache__/react_performance_checker.cpython-311.pyc +0 -0
- package/.agent/skills/nodejs-best-practices/SKILL.md +21 -7
- package/.agent/skills/observability/SKILL.md +21 -7
- package/.agent/skills/page-transition-animation/SKILL.md +19 -10
- package/.agent/skills/parallel-agents/SKILL.md +23 -7
- package/.agent/skills/performance-profiling/SKILL.md +21 -7
- package/.agent/skills/performance-profiling/scripts/__pycache__/lighthouse_audit.cpython-311.pyc +0 -0
- package/.agent/skills/plan-writing/SKILL.md +21 -7
- package/.agent/skills/platform-engineer/SKILL.md +21 -7
- package/.agent/skills/playwright-best-practices/SKILL.md +21 -7
- package/.agent/skills/polish/SKILL.md +19 -10
- package/.agent/skills/powershell-windows/SKILL.md +21 -7
- package/.agent/skills/pricing-page/SKILL.md +19 -10
- package/.agent/skills/product-aware-heuristics/SKILL.md +358 -0
- package/.agent/skills/progressive-blur/SKILL.md +19 -10
- package/.agent/skills/project-idioms/SKILL.md +20 -8
- package/.agent/skills/python-patterns/SKILL.md +21 -7
- package/.agent/skills/python-pro/SKILL.md +21 -6
- package/.agent/skills/quieter/SKILL.md +19 -10
- package/.agent/skills/react-doctor/SKILL.md +19 -10
- package/.agent/skills/react-specialist/SKILL.md +19 -6
- package/.agent/skills/readme-builder/SKILL.md +21 -7
- package/.agent/skills/realtime-patterns/SKILL.md +21 -7
- package/.agent/skills/red-team-tactics/SKILL.md +21 -7
- package/.agent/skills/redesign-skill/SKILL.md +19 -10
- package/.agent/skills/review-animations/SKILL.md +21 -10
- package/.agent/skills/rust-pro/SKILL.md +21 -7
- package/.agent/skills/seo-fundamentals/SKILL.md +21 -7
- package/.agent/skills/seo-fundamentals/scripts/__pycache__/seo_checker.cpython-311.pyc +0 -0
- package/.agent/skills/server-management/SKILL.md +21 -7
- package/.agent/skills/shadcn-ui-expert/SKILL.md +21 -7
- package/.agent/skills/shape/SKILL.md +19 -10
- package/.agent/skills/skill-creator/SKILL.md +21 -7
- package/.agent/skills/soft-skill/SKILL.md +19 -10
- package/.agent/skills/sounds-on-the-web/SKILL.md +19 -10
- package/.agent/skills/sql-pro/SKILL.md +21 -7
- package/.agent/skills/supabase-postgres-best-practices/SKILL.md +21 -7
- package/.agent/skills/svg-animation/SKILL.md +19 -10
- package/.agent/skills/swiftui-expert/SKILL.md +21 -7
- package/.agent/skills/swiss-design/SKILL.md +19 -10
- package/.agent/skills/system-design-pro/SKILL.md +21 -9
- package/.agent/skills/systematic-debugging/SKILL.md +21 -7
- package/.agent/skills/tailwind-patterns/SKILL.md +21 -7
- package/.agent/skills/taste-skill/SKILL.md +19 -10
- package/.agent/skills/tdd-workflow/SKILL.md +21 -10
- package/.agent/skills/test-result-analyzer/SKILL.md +18 -6
- package/.agent/skills/testing-patterns/SKILL.md +21 -7
- package/.agent/skills/testing-patterns/scripts/__pycache__/test_runner.cpython-311.pyc +0 -0
- package/.agent/skills/thermo-nuclear-code-quality-review/SKILL.md +21 -10
- package/.agent/skills/thinking-protocol/SKILL.md +20 -8
- package/.agent/skills/to-spring-or-not-to-spring/SKILL.md +19 -10
- package/.agent/skills/transitions-dev/SKILL.md +19 -10
- package/.agent/skills/trend-researcher/SKILL.md +17 -6
- package/.agent/skills/typescript-advanced/SKILL.md +21 -7
- package/.agent/skills/typeset/SKILL.md +19 -10
- package/.agent/skills/ui-reasoning-engine/SKILL.md +154 -0
- package/.agent/skills/ui-skill-packs/SKILL.md +77 -0
- package/.agent/skills/ui-skills-root/SKILL.md +21 -9
- package/.agent/skills/ui-ux-pro-max/SKILL.md +62 -583
- package/.agent/skills/ui-ux-researcher/SKILL.md +17 -6
- package/.agent/skills/vue-expert/SKILL.md +19 -6
- package/.agent/skills/vulnerability-scanner/SKILL.md +21 -7
- package/.agent/skills/vulnerability-scanner/scripts/__pycache__/security_scan.cpython-311.pyc +0 -0
- package/.agent/skills/web-accessibility-auditor/SKILL.md +21 -7
- package/.agent/skills/web-design-guidelines/SKILL.md +32 -206
- package/.agent/skills/web-quality-audit/SKILL.md +19 -10
- package/.agent/skills/webapp-testing/SKILL.md +21 -7
- package/.agent/skills/webapp-testing/scripts/__pycache__/playwright_runner.cpython-311.pyc +0 -0
- package/.agent/skills/webgpu-performance/SKILL.md +19 -3
- package/.agent/skills/whimsy-injector/SKILL.md +20 -10
- package/.agent/skills/workflow-optimizer/SKILL.md +16 -6
- package/.agent/templates/DESIGN.md +292 -0
- package/.agent/templates/design-tokens.json +137 -0
- package/.agent/workflows/acf.md +13 -6
- package/.agent/workflows/api-tester.md +15 -8
- package/.agent/workflows/audit.md +19 -8
- package/.agent/workflows/brainstorm.md +14 -9
- package/.agent/workflows/changelog.md +14 -8
- package/.agent/workflows/create.md +16 -8
- package/.agent/workflows/debug.md +15 -10
- package/.agent/workflows/deploy.md +16 -8
- package/.agent/workflows/enhance.md +15 -10
- package/.agent/workflows/fix.md +15 -8
- package/.agent/workflows/generate.md +17 -11
- package/.agent/workflows/marathon.md +15 -8
- package/.agent/workflows/migrate.md +16 -8
- package/.agent/workflows/minimal.md +94 -0
- package/.agent/workflows/orchestrate.md +15 -8
- package/.agent/workflows/performance-benchmarker.md +15 -8
- package/.agent/workflows/pipeline.md +155 -0
- package/.agent/workflows/plan.md +14 -10
- package/.agent/workflows/preview.md +14 -7
- package/.agent/workflows/refactor.md +16 -8
- package/.agent/workflows/review-ai.md +15 -7
- package/.agent/workflows/review.md +15 -7
- package/.agent/workflows/session.md +14 -7
- package/.agent/workflows/status.md +13 -7
- package/.agent/workflows/strengthen-skills.md +15 -6
- package/.agent/workflows/super-prompt.md +19 -10
- package/.agent/workflows/swarm.md +15 -7
- package/.agent/workflows/test.md +15 -8
- package/.agent/workflows/tribunal-backend.md +16 -9
- package/.agent/workflows/tribunal-database.md +15 -8
- package/.agent/workflows/tribunal-frontend.md +26 -11
- package/.agent/workflows/tribunal-full.md +29 -14
- package/.agent/workflows/tribunal-mobile.md +15 -8
- package/.agent/workflows/tribunal-performance.md +15 -8
- package/.agent/workflows/tribunal-speed.md +16 -9
- package/.agent/workflows/tribunal-ui.md +82 -0
- package/.agent/workflows/ui-ux-pro-max.md +51 -107
- package/CONTRIBUTING.md +2 -2
- package/README.md +5 -5
- package/bin/mcp-server.js +126 -76
- package/bin/wrapper.js +67 -31
- package/dist/cli.js +39 -1
- package/dist/commands/compile.js +7 -0
- package/dist/commands/context.js +8 -3
- package/dist/commands/graph.js +8 -2
- package/dist/commands/init.js +37 -2
- package/dist/commands/memory.js +119 -68
- package/dist/commands/minimal.js +71 -0
- package/dist/commands/native.js +228 -0
- package/dist/commands/optimize.js +15 -5
- package/dist/commands/validate.js +67 -0
- package/dist/esm/index.mjs +26 -32
- package/dist/mcp/server.js +4 -138
- package/dist/utils/fs.js +10 -4
- package/dist/utils/helpers.js +10 -1
- package/dist/utils/version.js +9 -2
- package/mcp_config.json +10 -1
- package/package.json +19 -15
- package/scripts/benchmark.js +58 -0
- package/scripts/sync-version.js +129 -76
- package/scripts/visual_audit.js +126 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* impact_classifier.js — Adaptive Governance Impact Classifier
|
|
4
|
+
* ===============================================================
|
|
5
|
+
* Analyzes diffs, file extensions, and structural changes to classify
|
|
6
|
+
* tasks into Governance Impact Tiers (Tier 0 to Tier 3).
|
|
7
|
+
*
|
|
8
|
+
* Impact Tiers:
|
|
9
|
+
* Tier 0 (Fast-Pass): Score < 0.15. Typo, pure CSS, markdown, comments, <10 lines.
|
|
10
|
+
* 0 LLM calls, 0 Socratic gate, <10ms execution.
|
|
11
|
+
* Tier 1 (Express Pass): Score 0.15 - 0.35. Single file logic change.
|
|
12
|
+
* 1 domain specialist reviewer, 0 Socratic gate.
|
|
13
|
+
* Tier 2 (Targeted Audit): Score 0.35 - 0.70. Multi-file edits, non-critical domain logic.
|
|
14
|
+
* 2 reviewers, Socratic gate if ambiguity > 0.5.
|
|
15
|
+
* Tier 3 (Full Gauntlet): Score > 0.70 or critical paths (auth, schema, security, payment).
|
|
16
|
+
* Full multi-agent gauntlet + strict Human Gate.
|
|
17
|
+
*
|
|
18
|
+
* Usage:
|
|
19
|
+
* node .agent/scripts/impact_classifier.js --files "src/app.css" --diff "+color: red;"
|
|
20
|
+
* node .agent/scripts/impact_classifier.js --task "Fix typo in comment"
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
"use strict";
|
|
24
|
+
|
|
25
|
+
const path = require("path");
|
|
26
|
+
const { parseArgs } = require("./_utils");
|
|
27
|
+
|
|
28
|
+
// Critical file patterns that automatically force Tier 3
|
|
29
|
+
const CRITICAL_PATTERNS = [
|
|
30
|
+
/auth/i,
|
|
31
|
+
/security/i,
|
|
32
|
+
/payment/i,
|
|
33
|
+
/billing/i,
|
|
34
|
+
/schema/i,
|
|
35
|
+
/migration/i,
|
|
36
|
+
/permission/i,
|
|
37
|
+
/jwt/i,
|
|
38
|
+
/crypto/i,
|
|
39
|
+
/secret/i,
|
|
40
|
+
/eval/i
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
// Low-impact extensions / patterns for Tier 0
|
|
44
|
+
const FAST_PASS_EXTENSIONS = [".css", ".scss", ".less", ".md", ".txt", ".json", ".svg", ".png", ".jpg"];
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Classify impact based on files, diff content, and task description
|
|
48
|
+
* @param {Object} opts - Options { files, diff, task, lineCount }
|
|
49
|
+
* @returns {Object} Tier payload { tier, score, reasoning, maxReviewers, requireGate }
|
|
50
|
+
*/
|
|
51
|
+
function classifyImpact(opts = {}) {
|
|
52
|
+
if (!opts || typeof opts !== "object") opts = {};
|
|
53
|
+
const rawFiles = opts.files;
|
|
54
|
+
const files = Array.isArray(rawFiles)
|
|
55
|
+
? rawFiles.filter(f => typeof f === "string" && f.length > 0)
|
|
56
|
+
: (typeof rawFiles === "string" && rawFiles.length > 0 ? [rawFiles] : []);
|
|
57
|
+
const diff = typeof opts.diff === "string" ? opts.diff : "";
|
|
58
|
+
const task = typeof opts.task === "string" ? opts.task : "";
|
|
59
|
+
const lineCount = typeof opts.lineCount === "number" && Number.isFinite(opts.lineCount) && opts.lineCount >= 0
|
|
60
|
+
? opts.lineCount
|
|
61
|
+
: (diff.length > 0 ? diff.split("\n").length : 0);
|
|
62
|
+
|
|
63
|
+
let score = 0.2; // Base baseline score
|
|
64
|
+
const reasoning = [];
|
|
65
|
+
|
|
66
|
+
// Check 1: Critical File Patterns
|
|
67
|
+
const isCriticalFile = files.some(file => CRITICAL_PATTERNS.some(pat => pat.test(file)));
|
|
68
|
+
const isCriticalTask = CRITICAL_PATTERNS.some(pat => pat.test(task));
|
|
69
|
+
|
|
70
|
+
if (isCriticalFile || isCriticalTask) {
|
|
71
|
+
score += 0.6;
|
|
72
|
+
reasoning.push("Critical path detected (auth/security/schema/payment)");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Check 2: File Extensions & Types
|
|
76
|
+
if (files.length > 0) {
|
|
77
|
+
const allFastPass = files.every(f => FAST_PASS_EXTENSIONS.includes(path.extname(f).toLowerCase()));
|
|
78
|
+
if (allFastPass) {
|
|
79
|
+
score -= 0.25;
|
|
80
|
+
reasoning.push("All modified files are low-risk assets (styles/docs/assets)");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Check 3: Line Count & Diff Size
|
|
85
|
+
if (lineCount <= 10) {
|
|
86
|
+
score -= 0.15;
|
|
87
|
+
reasoning.push("Small diff size (<= 10 lines)");
|
|
88
|
+
} else if (lineCount > 100) {
|
|
89
|
+
score += 0.3;
|
|
90
|
+
reasoning.push("Large diff size (> 100 lines)");
|
|
91
|
+
} else if (lineCount > 30) {
|
|
92
|
+
score += 0.15;
|
|
93
|
+
reasoning.push("Medium diff size (30-100 lines)");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Check 4: Task Keywords
|
|
97
|
+
const taskLower = task.toLowerCase();
|
|
98
|
+
if (/typo|fix comment|format|lint|rename|css|style|docs|readme/i.test(taskLower)) {
|
|
99
|
+
score -= 0.2;
|
|
100
|
+
reasoning.push("Task signals simple edit or formatting");
|
|
101
|
+
}
|
|
102
|
+
if (/refactor|rewrite|architecture|redesign|migration|overhaul|security/i.test(taskLower)) {
|
|
103
|
+
score += 0.35;
|
|
104
|
+
reasoning.push("Task signals structural refactor or security review");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Clamp score between 0.0 and 1.0
|
|
108
|
+
score = Math.max(0.0, Math.min(1.0, score));
|
|
109
|
+
|
|
110
|
+
// Determine Impact Tier
|
|
111
|
+
let tier = 1;
|
|
112
|
+
let maxReviewers = 1;
|
|
113
|
+
let requireGate = false;
|
|
114
|
+
|
|
115
|
+
if (score < 0.15 && !isCriticalFile && !isCriticalTask) {
|
|
116
|
+
tier = 0;
|
|
117
|
+
maxReviewers = 0;
|
|
118
|
+
requireGate = false;
|
|
119
|
+
} else if (score < 0.35 && !isCriticalFile && !isCriticalTask) {
|
|
120
|
+
tier = 1;
|
|
121
|
+
maxReviewers = 1;
|
|
122
|
+
requireGate = false;
|
|
123
|
+
} else if (score < 0.70 && !isCriticalFile) {
|
|
124
|
+
tier = 2;
|
|
125
|
+
maxReviewers = 2;
|
|
126
|
+
requireGate = true; // Conditional gate
|
|
127
|
+
} else {
|
|
128
|
+
tier = 3;
|
|
129
|
+
maxReviewers = 8;
|
|
130
|
+
requireGate = true;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
tier,
|
|
135
|
+
score: parseFloat(score.toFixed(2)),
|
|
136
|
+
maxReviewers,
|
|
137
|
+
requireGate,
|
|
138
|
+
reasoning,
|
|
139
|
+
fastPass: tier === 0
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Direct CLI Execution
|
|
144
|
+
if (require.main === module) {
|
|
145
|
+
const args = parseArgs(process.argv);
|
|
146
|
+
const files = args.files ? args.files.split(",") : [];
|
|
147
|
+
const result = classifyImpact({
|
|
148
|
+
files,
|
|
149
|
+
diff: args.diff || "",
|
|
150
|
+
task: args.task || "",
|
|
151
|
+
lineCount: args.lines ? parseInt(args.lines, 10) : undefined
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
if (args.json) {
|
|
155
|
+
console.log(JSON.stringify(result, null, 2));
|
|
156
|
+
} else {
|
|
157
|
+
console.log(`\n━━━ Adaptive Governance Impact Tier ━━━━━━━━━━━━━`);
|
|
158
|
+
console.log(` Tier: Tier ${result.tier} (${result.fastPass ? "FAST-PASS" : result.tier === 1 ? "EXPRESS" : result.tier === 2 ? "TARGETED" : "GAUNTLET"})`);
|
|
159
|
+
console.log(` Score: ${result.score}`);
|
|
160
|
+
console.log(` Max Reviewers:${result.maxReviewers}`);
|
|
161
|
+
console.log(` Require Gate: ${result.requireGate}`);
|
|
162
|
+
console.log(` Reasoning: ${result.reasoning.join(" | ") || "Baseline assessment"}`);
|
|
163
|
+
console.log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
module.exports = { classifyImpact };
|
|
@@ -82,9 +82,10 @@ function crawlAgents(agentDir) {
|
|
|
82
82
|
const content = safeReadFile(path.join(agentsDir, file));
|
|
83
83
|
const fm = parseFrontmatter(content);
|
|
84
84
|
const isReviewer =
|
|
85
|
-
/reviewer|auditor|tester/i.test(name) ||
|
|
85
|
+
/reviewer|auditor|tester|throughput-optimizer/i.test(name) ||
|
|
86
86
|
(fm.role && /reviewer/i.test(fm.role));
|
|
87
87
|
|
|
88
|
+
|
|
88
89
|
if (isReviewer) {
|
|
89
90
|
reviewers.push(name);
|
|
90
91
|
} else {
|
|
@@ -239,7 +240,10 @@ function extractNumericClaims(filePath, content, agentDir, actualCounts) {
|
|
|
239
240
|
const lines = content.split(/\r?\n/);
|
|
240
241
|
|
|
241
242
|
const claimPatterns = [
|
|
242
|
-
{
|
|
243
|
+
{
|
|
244
|
+
regex: /(\d+)\s*(?:-\s*)?(?:(?:parallel|domain(?:-specific)?|tribunal|code)\s+)*reviewers?\b/gi,
|
|
245
|
+
entity: "reviewers",
|
|
246
|
+
},
|
|
243
247
|
{ regex: /(\d+)\s*(?:specialist\s+)?agents?\b/gi, entity: "agents" },
|
|
244
248
|
{ regex: /(\d+)\s*(?:modular\s+)?skills?\b/gi, entity: "skills" },
|
|
245
249
|
{ regex: /(\d+)\s*(?:slash\s+)?workflows?\b/gi, entity: "workflows" },
|
|
@@ -253,8 +257,10 @@ function extractNumericClaims(filePath, content, agentDir, actualCounts) {
|
|
|
253
257
|
let match;
|
|
254
258
|
while ((match = regex.exec(line)) !== null) {
|
|
255
259
|
const claimed = parseInt(match[1], 10);
|
|
256
|
-
//
|
|
257
|
-
|
|
260
|
+
// This manifest describes the full Tribunal payload, so small local
|
|
261
|
+
// counts (for example, "3 skills" in one skill group) are not global
|
|
262
|
+
// asset claims. Skip them along with implausibly large values.
|
|
263
|
+
if (claimed < 5 || claimed > 500) continue;
|
|
258
264
|
|
|
259
265
|
const actual = actualCounts[entity];
|
|
260
266
|
if (actual !== undefined) {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
const fs = require("fs");
|
|
25
25
|
const path = require("path");
|
|
26
26
|
const { execSync } = require("child_process");
|
|
27
|
+
const { findAgentDir } = require("./_utils");
|
|
27
28
|
|
|
28
29
|
const {
|
|
29
30
|
GREEN,
|
|
@@ -42,7 +43,11 @@ const {
|
|
|
42
43
|
} = require("./_colors");
|
|
43
44
|
|
|
44
45
|
// ── Paths ────────────────────────────────────────────────────────────────────
|
|
45
|
-
|
|
46
|
+
function getMarathonDir(startDir = process.cwd()) {
|
|
47
|
+
return path.join(findAgentDir(startDir), "history", "marathon");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const MARATHON_DIR = getMarathonDir();
|
|
46
51
|
const FEATURE_LIST_FILE = path.join(MARATHON_DIR, "feature_list.json");
|
|
47
52
|
const PROGRESS_FILE = path.join(MARATHON_DIR, "progress.json");
|
|
48
53
|
const ARCHIVE_DIR = path.join(MARATHON_DIR, "archive");
|
|
@@ -1049,6 +1054,10 @@ function main() {
|
|
|
1049
1054
|
}
|
|
1050
1055
|
}
|
|
1051
1056
|
|
|
1057
|
+
module.exports = {
|
|
1058
|
+
getMarathonDir,
|
|
1059
|
+
};
|
|
1060
|
+
|
|
1052
1061
|
if (require.main === module) {
|
|
1053
1062
|
main();
|
|
1054
1063
|
}
|
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* minimal_change_engine.js — Minimal Change Governance Engine for Tribunal-Kit
|
|
4
|
+
* ==============================================================================
|
|
5
|
+
* Stops AI coding agents from overengineering, creating unnecessary files,
|
|
6
|
+
* introducing unneeded abstractions, adding unjustified dependencies, or
|
|
7
|
+
* duplicating existing repository functionality.
|
|
8
|
+
*
|
|
9
|
+
* Core Principle & Evaluation Order:
|
|
10
|
+
* 1. NO_CHANGE — Requested behavior exists or no modification is justified
|
|
11
|
+
* 2. REUSE — Existing repository functionality solves the requirement
|
|
12
|
+
* 3. CONFIGURE — Configuration, flags, metadata, or existing APIs solve it
|
|
13
|
+
* 4. DELETE — Removing unnecessary code solves the underlying issue
|
|
14
|
+
* 5. MODIFY — Small modification to existing code solves the requirement
|
|
15
|
+
* 6. EXTEND — Existing architecture requires limited extension
|
|
16
|
+
* 7. CREATE — New implementation is justified (highest burden of proof)
|
|
17
|
+
*
|
|
18
|
+
* Capabilities:
|
|
19
|
+
* - Change Budget Estimation & Auditing
|
|
20
|
+
* - Minimality Score Calculation (0-100)
|
|
21
|
+
* - Complexity Flags Detection (14 Standardized Types)
|
|
22
|
+
* - Repository Capability & Symbol Search
|
|
23
|
+
* - Strictness Modes (relaxed | balanced | strict)
|
|
24
|
+
*
|
|
25
|
+
* Usage:
|
|
26
|
+
* node .agent/scripts/minimal_change_engine.js evaluate --task "add retry logic"
|
|
27
|
+
* node .agent/scripts/minimal_change_engine.js budget --spec spec.json
|
|
28
|
+
* node .agent/scripts/minimal_change_engine.js audit --diff diff.txt
|
|
29
|
+
* node .agent/scripts/minimal_change_engine.js search --query "fetchRetry"
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
"use strict";
|
|
33
|
+
|
|
34
|
+
const fs = require("fs");
|
|
35
|
+
const path = require("path");
|
|
36
|
+
|
|
37
|
+
// ── Shared Utilities & Colors ────────────────────────────────────────────────
|
|
38
|
+
const { GREEN, YELLOW, CYAN, RED, BOLD, DIM, RESET } = require("./_colors");
|
|
39
|
+
const { findAgentDir, loadJson, walkDir, DEFAULT_SKIP_DIRS } = require("./_utils");
|
|
40
|
+
|
|
41
|
+
// ── Decision Order Hierarchy ─────────────────────────────────────────────────
|
|
42
|
+
const DECISION_HIERARCHY = [
|
|
43
|
+
"NO_CHANGE",
|
|
44
|
+
"REUSE",
|
|
45
|
+
"CONFIGURE",
|
|
46
|
+
"DELETE",
|
|
47
|
+
"MODIFY",
|
|
48
|
+
"EXTEND",
|
|
49
|
+
"CREATE",
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
// ── 14 Standardized Complexity Flag Types ────────────────────────────────────
|
|
53
|
+
const COMPLEXITY_FLAG_TYPES = [
|
|
54
|
+
"UNNECESSARY_ABSTRACTION",
|
|
55
|
+
"DUPLICATE_FUNCTIONALITY",
|
|
56
|
+
"DEPENDENCY_BLOAT",
|
|
57
|
+
"FILE_PROLIFERATION",
|
|
58
|
+
"PREMATURE_GENERALIZATION",
|
|
59
|
+
"SCOPE_EXPANSION",
|
|
60
|
+
"UNNECESSARY_REWRITE",
|
|
61
|
+
"FRAMEWORK_REINVENTION",
|
|
62
|
+
"STANDARD_LIBRARY_REINVENTION",
|
|
63
|
+
"EXCESSIVE_BOILERPLATE",
|
|
64
|
+
"SPECULATIVE_FEATURE",
|
|
65
|
+
"UNJUSTIFIED_INFRASTRUCTURE",
|
|
66
|
+
"UNNECESSARY_CONFIGURATION",
|
|
67
|
+
"DEAD_CODE_INTRODUCTION",
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
// ── Strictness Configurations ────────────────────────────────────────────────
|
|
71
|
+
const STRICTNESS_CONFIGS = {
|
|
72
|
+
relaxed: {
|
|
73
|
+
max_files_added_warn: 4,
|
|
74
|
+
max_deps_warn: 2,
|
|
75
|
+
max_abstractions_warn: 3,
|
|
76
|
+
min_score_pass: 60,
|
|
77
|
+
},
|
|
78
|
+
balanced: {
|
|
79
|
+
max_files_added_warn: 2,
|
|
80
|
+
max_deps_warn: 1,
|
|
81
|
+
max_abstractions_warn: 1,
|
|
82
|
+
min_score_pass: 75,
|
|
83
|
+
},
|
|
84
|
+
strict: {
|
|
85
|
+
max_files_added_warn: 1,
|
|
86
|
+
max_deps_warn: 0,
|
|
87
|
+
max_abstractions_warn: 0,
|
|
88
|
+
min_score_pass: 85,
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Calculates Change Budget based on spec / file diff proposal.
|
|
94
|
+
*/
|
|
95
|
+
function calculateChangeBudget(proposal = {}) {
|
|
96
|
+
return {
|
|
97
|
+
files_added: proposal.files_added || 0,
|
|
98
|
+
files_modified: proposal.files_modified || 0,
|
|
99
|
+
files_deleted: proposal.files_deleted || 0,
|
|
100
|
+
dependencies_added: proposal.dependencies_added || 0,
|
|
101
|
+
dependencies_removed: proposal.dependencies_removed || 0,
|
|
102
|
+
new_abstractions: proposal.new_abstractions || 0,
|
|
103
|
+
public_api_changes: proposal.public_api_changes || 0,
|
|
104
|
+
estimated_lines_added: proposal.estimated_lines_added || 0,
|
|
105
|
+
estimated_lines_removed: proposal.estimated_lines_removed || 0,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Computes Minimality Score (0 to 100) based on proposed change footprint.
|
|
111
|
+
*/
|
|
112
|
+
function calculateMinimalityScore(budget, classification, flags = []) {
|
|
113
|
+
let score = 100;
|
|
114
|
+
|
|
115
|
+
// Penalties for file proliferation
|
|
116
|
+
if (budget.files_added > 0) {
|
|
117
|
+
score -= budget.files_added * 8;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Penalties for unnecessary dependencies
|
|
121
|
+
if (budget.dependencies_added > 0) {
|
|
122
|
+
score -= budget.dependencies_added * 15;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Penalties for excessive new abstractions
|
|
126
|
+
if (budget.new_abstractions > 0) {
|
|
127
|
+
score -= budget.new_abstractions * 10;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Penalties for massive line expansions
|
|
131
|
+
if (budget.estimated_lines_added > 100) {
|
|
132
|
+
score -= Math.floor((budget.estimated_lines_added - 100) / 20);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Penalties for complexity flags based on severity
|
|
136
|
+
flags.forEach((flag) => {
|
|
137
|
+
if (flag.severity === "high" || flag.severity === "critical") {
|
|
138
|
+
score -= 15;
|
|
139
|
+
} else if (flag.severity === "medium") {
|
|
140
|
+
score -= 8;
|
|
141
|
+
} else {
|
|
142
|
+
score -= 4;
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Classification weighting: reward simpler classifications
|
|
147
|
+
const classWeights = {
|
|
148
|
+
NO_CHANGE: +10,
|
|
149
|
+
REUSE: +15,
|
|
150
|
+
CONFIGURE: +10,
|
|
151
|
+
DELETE: +10,
|
|
152
|
+
MODIFY: 0,
|
|
153
|
+
EXTEND: -5,
|
|
154
|
+
CREATE: -15,
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
score += classWeights[classification] || 0;
|
|
158
|
+
|
|
159
|
+
// Clamp between 0 and 100
|
|
160
|
+
return Math.max(0, Math.min(100, Math.round(score)));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Detects potential complexity flags within a proposed change or spec.
|
|
165
|
+
*/
|
|
166
|
+
function detectComplexityFlags(proposal = {}, existingSymbols = [], mode = "balanced") {
|
|
167
|
+
const flags = [];
|
|
168
|
+
const limits = STRICTNESS_CONFIGS[mode] || STRICTNESS_CONFIGS.balanced;
|
|
169
|
+
|
|
170
|
+
// Check 1: Dependency Bloat
|
|
171
|
+
if (proposal.dependencies_added > limits.max_deps_warn) {
|
|
172
|
+
flags.push({
|
|
173
|
+
type: "DEPENDENCY_BLOAT",
|
|
174
|
+
severity: proposal.dependencies_added > 1 ? "high" : "medium",
|
|
175
|
+
evidence: `${proposal.dependencies_added} new dependency/dependencies proposed.`,
|
|
176
|
+
location: proposal.target_file || "package.json",
|
|
177
|
+
reason: "Adding dependencies increases security attack surface and maintenance overhead.",
|
|
178
|
+
recommended_action: "Use standard library or existing codebase utilities.",
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Check 2: File Proliferation
|
|
183
|
+
if (proposal.files_added > limits.max_files_added_warn) {
|
|
184
|
+
flags.push({
|
|
185
|
+
type: "FILE_PROLIFERATION",
|
|
186
|
+
severity: proposal.files_added > 3 ? "high" : "medium",
|
|
187
|
+
evidence: `${proposal.files_added} new files proposed for creation.`,
|
|
188
|
+
location: proposal.target_file || "workspace",
|
|
189
|
+
reason: "Creating multiple new files increases architectural noise and fragmentation.",
|
|
190
|
+
recommended_action: "Modify or extend existing files instead of creating new ones.",
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Check 3: Unnecessary Abstraction
|
|
195
|
+
if (proposal.new_abstractions > limits.max_abstractions_warn) {
|
|
196
|
+
flags.push({
|
|
197
|
+
type: "UNNECESSARY_ABSTRACTION",
|
|
198
|
+
severity: "medium",
|
|
199
|
+
evidence: `${proposal.new_abstractions} new abstraction layer(s) proposed.`,
|
|
200
|
+
location: proposal.target_file || "codebase",
|
|
201
|
+
reason: "Adding wrappers or single-consumer interfaces increases complexity without benefit.",
|
|
202
|
+
recommended_action: "Implement concrete logic directly without extra abstraction.",
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Check 4: Duplicate Functionality
|
|
207
|
+
if (proposal.duplicate_candidates && proposal.duplicate_candidates.length > 0) {
|
|
208
|
+
proposal.duplicate_candidates.forEach((cand) => {
|
|
209
|
+
flags.push({
|
|
210
|
+
type: "DUPLICATE_FUNCTIONALITY",
|
|
211
|
+
severity: "high",
|
|
212
|
+
evidence: `Existing equivalent symbol '${cand.name}' found in ${cand.file}`,
|
|
213
|
+
location: cand.file,
|
|
214
|
+
reason: "Duplicate functionality leads to fragmented state and maintenance confusion.",
|
|
215
|
+
recommended_action: `Reuse '${cand.name}' from ${cand.file}`,
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Check 5: Framework/Stdlib Reinvention
|
|
221
|
+
if (proposal.reinventing_stdlib) {
|
|
222
|
+
flags.push({
|
|
223
|
+
type: "STANDARD_LIBRARY_REINVENTION",
|
|
224
|
+
severity: "medium",
|
|
225
|
+
evidence: `Proposed custom utility '${proposal.reinventing_stdlib.name}'`,
|
|
226
|
+
location: proposal.target_file || "utils",
|
|
227
|
+
reason: "Language standard library already provides built-in methods for this.",
|
|
228
|
+
recommended_action: `Use native JS/TS methods (e.g., Array.prototype, URL, crypto).`,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return flags;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Inspects repository files to search for symbols, utilities, exports, and config.
|
|
237
|
+
*/
|
|
238
|
+
function searchRepositoryForCapability(query, searchDir) {
|
|
239
|
+
const matches = [];
|
|
240
|
+
|
|
241
|
+
if (!query || typeof query !== "string") return matches;
|
|
242
|
+
|
|
243
|
+
let agentDir = null;
|
|
244
|
+
let current = path.resolve(searchDir || process.cwd());
|
|
245
|
+
const rootPath = path.parse(current).root;
|
|
246
|
+
while (current !== rootPath) {
|
|
247
|
+
const candidate = path.join(current, ".agent");
|
|
248
|
+
if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
|
|
249
|
+
agentDir = candidate;
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
current = path.dirname(current);
|
|
253
|
+
}
|
|
254
|
+
const repoRoot = agentDir ? path.dirname(agentDir) : (searchDir || process.cwd());
|
|
255
|
+
|
|
256
|
+
const normalizedQuery = query.toLowerCase();
|
|
257
|
+
const searchKeywords = normalizedQuery.split(/\s+/).filter((k) => k.length > 2);
|
|
258
|
+
|
|
259
|
+
// Search package.json dependencies
|
|
260
|
+
const pkgPath = path.join(repoRoot, "package.json");
|
|
261
|
+
if (fs.existsSync(pkgPath)) {
|
|
262
|
+
const pkg = loadJson(pkgPath);
|
|
263
|
+
if (pkg) {
|
|
264
|
+
const allDeps = {
|
|
265
|
+
...pkg.dependencies,
|
|
266
|
+
...pkg.devDependencies,
|
|
267
|
+
};
|
|
268
|
+
Object.keys(allDeps).forEach((dep) => {
|
|
269
|
+
if (dep.toLowerCase().includes(normalizedQuery)) {
|
|
270
|
+
matches.push({
|
|
271
|
+
type: "dependency",
|
|
272
|
+
name: dep,
|
|
273
|
+
file: "package.json",
|
|
274
|
+
snippet: `Version: ${allDeps[dep]}`,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Helper: recursive file scanner
|
|
282
|
+
function scan(dir) {
|
|
283
|
+
if (!fs.existsSync(dir)) return;
|
|
284
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
285
|
+
|
|
286
|
+
for (const entry of entries) {
|
|
287
|
+
const fullPath = path.join(dir, entry.name);
|
|
288
|
+
if (entry.isDirectory()) {
|
|
289
|
+
if (DEFAULT_SKIP_DIRS.has(entry.name) || entry.name === "target") {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
scan(fullPath);
|
|
293
|
+
} else if (entry.isFile() && /\.(js|ts|tsx|jsx|json|md)$/.test(entry.name)) {
|
|
294
|
+
try {
|
|
295
|
+
const content = fs.readFileSync(fullPath, "utf8");
|
|
296
|
+
const lower = content.toLowerCase();
|
|
297
|
+
|
|
298
|
+
const hasMatch = searchKeywords.some((kw) => lower.includes(kw));
|
|
299
|
+
if (hasMatch) {
|
|
300
|
+
const relPath = path.relative(repoRoot, fullPath);
|
|
301
|
+
// Extract function/class exports
|
|
302
|
+
const symbolRegex = /(?:export\s+(?:function|class|const|let|var|type|interface)|module\.exports\s*=)\s+([A-Za-z0-9_]+)/g;
|
|
303
|
+
let m;
|
|
304
|
+
while ((m = symbolRegex.exec(content)) !== null) {
|
|
305
|
+
if (m[1].toLowerCase().includes(normalizedQuery)) {
|
|
306
|
+
matches.push({
|
|
307
|
+
type: "symbol",
|
|
308
|
+
name: m[1],
|
|
309
|
+
file: relPath,
|
|
310
|
+
snippet: content.substring(Math.max(0, m.index - 40), m.index + 80).replace(/\n/g, " "),
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
} catch {
|
|
316
|
+
// Ignore unreadable files
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
scan(repoRoot);
|
|
323
|
+
return matches;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Classifies an implementation proposal into the 7-level Decision Order.
|
|
328
|
+
*/
|
|
329
|
+
function classifyProposal(taskDescription, proposal = {}, repoMatches = []) {
|
|
330
|
+
const filesAdded = proposal.files_added || 0;
|
|
331
|
+
const filesModified = proposal.files_modified || 0;
|
|
332
|
+
const filesDeleted = proposal.files_deleted || 0;
|
|
333
|
+
const newAbstractions = proposal.new_abstractions || 0;
|
|
334
|
+
const estimatedLinesAdded = proposal.estimated_lines_added || 0;
|
|
335
|
+
|
|
336
|
+
if (repoMatches.length > 0 && filesAdded === 0) {
|
|
337
|
+
return "REUSE";
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (filesAdded === 0 && filesModified === 0 && filesDeleted === 0) {
|
|
341
|
+
return "NO_CHANGE";
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (proposal.is_config_only) {
|
|
345
|
+
return "CONFIGURE";
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (filesDeleted > 0 && filesAdded === 0 && estimatedLinesAdded === 0) {
|
|
349
|
+
return "DELETE";
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (filesAdded === 0 && filesModified <= 2 && newAbstractions === 0) {
|
|
353
|
+
return "MODIFY";
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (filesAdded <= 2 && newAbstractions <= 1) {
|
|
357
|
+
return "EXTEND";
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return "CREATE";
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Evaluates an implementation proposal completely.
|
|
365
|
+
*/
|
|
366
|
+
function evaluateMinimalChange(taskDescription, proposal = {}, options = {}) {
|
|
367
|
+
const mode = options.mode || "balanced";
|
|
368
|
+
const searchDir = options.cwd || process.cwd();
|
|
369
|
+
|
|
370
|
+
const budget = calculateChangeBudget(proposal);
|
|
371
|
+
let repoMatches = [];
|
|
372
|
+
try {
|
|
373
|
+
repoMatches = searchRepositoryForCapability(taskDescription, searchDir);
|
|
374
|
+
} catch {
|
|
375
|
+
repoMatches = [];
|
|
376
|
+
}
|
|
377
|
+
const classification = classifyProposal(taskDescription, proposal, repoMatches);
|
|
378
|
+
const flags = detectComplexityFlags(proposal, repoMatches, mode);
|
|
379
|
+
const score = calculateMinimalityScore(budget, classification, flags);
|
|
380
|
+
|
|
381
|
+
const reuseOpportunities = repoMatches.map(
|
|
382
|
+
(m) => `Reuse existing ${m.type} '${m.name}' in ${m.file}`,
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
const recommendedReductions = [];
|
|
386
|
+
if (budget.dependencies_added > 0) {
|
|
387
|
+
recommendedReductions.push("Avoid introducing new npm dependencies; leverage existing utilities.");
|
|
388
|
+
}
|
|
389
|
+
if (budget.files_added > 1) {
|
|
390
|
+
recommendedReductions.push("Combine proposed new files into existing module structure.");
|
|
391
|
+
}
|
|
392
|
+
if (budget.new_abstractions > 0) {
|
|
393
|
+
recommendedReductions.push("Remove single-use interface/class abstractions.");
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return {
|
|
397
|
+
minimality_classification: classification,
|
|
398
|
+
minimality_score: score,
|
|
399
|
+
change_budget: budget,
|
|
400
|
+
complexity_flags: flags,
|
|
401
|
+
reuse_opportunities: reuseOpportunities,
|
|
402
|
+
unnecessary_changes: flags.map((f) => f.evidence),
|
|
403
|
+
recommended_reductions: recommendedReductions,
|
|
404
|
+
decision_order: DECISION_HIERARCHY,
|
|
405
|
+
passed: score >= (STRICTNESS_CONFIGS[mode]?.min_score_pass || 75),
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// ── CLI Main Entry Point ────────────────────────────────────────────────────
|
|
410
|
+
if (require.main === module) {
|
|
411
|
+
const args = process.argv.slice(2);
|
|
412
|
+
const command = args[0] || "evaluate";
|
|
413
|
+
const taskArg = args.find((a) => a.startsWith("--task="))?.split("=")[1] || "Default Task";
|
|
414
|
+
const modeArg = args.find((a) => a.startsWith("--mode="))?.split("=")[1] || "balanced";
|
|
415
|
+
|
|
416
|
+
if (command === "evaluate" || command === "audit") {
|
|
417
|
+
const result = evaluateMinimalChange(taskArg, { files_modified: 1, estimated_lines_added: 12 }, { mode: modeArg });
|
|
418
|
+
console.log(JSON.stringify(result, null, 2));
|
|
419
|
+
} else if (command === "search") {
|
|
420
|
+
const matches = searchRepositoryForCapability(taskArg);
|
|
421
|
+
console.log(JSON.stringify(matches, null, 2));
|
|
422
|
+
} else {
|
|
423
|
+
console.log(`Minimal Change Engine CLI — Mode: ${modeArg}`);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
module.exports = {
|
|
428
|
+
DECISION_HIERARCHY,
|
|
429
|
+
COMPLEXITY_FLAG_TYPES,
|
|
430
|
+
STRICTNESS_CONFIGS,
|
|
431
|
+
calculateChangeBudget,
|
|
432
|
+
calculateMinimalityScore,
|
|
433
|
+
detectComplexityFlags,
|
|
434
|
+
searchRepositoryForCapability,
|
|
435
|
+
classifyProposal,
|
|
436
|
+
evaluateMinimalChange,
|
|
437
|
+
};
|