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,40 +22,30 @@
|
|
|
22
22
|
* node .agent/scripts/skill_evolution.js status
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
'use strict';
|
|
26
26
|
|
|
27
|
-
const fs = require(
|
|
28
|
-
const path = require(
|
|
29
|
-
const https = require(
|
|
30
|
-
const { execSync } = require(
|
|
31
|
-
const readline = require(
|
|
27
|
+
const fs = require('fs');
|
|
28
|
+
const path = require('path');
|
|
29
|
+
const https = require('https');
|
|
30
|
+
const { execSync } = require('child_process');
|
|
31
|
+
const readline = require('readline');
|
|
32
32
|
|
|
33
33
|
// ── Colours ──────────────────────────────────────────────────────────────────
|
|
34
|
-
const {
|
|
35
|
-
GREEN,
|
|
36
|
-
YELLOW,
|
|
37
|
-
CYAN,
|
|
38
|
-
RED,
|
|
39
|
-
BLUE,
|
|
40
|
-
BOLD,
|
|
41
|
-
DIM,
|
|
42
|
-
RESET,
|
|
43
|
-
} = require("./_colors");
|
|
34
|
+
const { GREEN, YELLOW, CYAN, RED, BLUE, BOLD, DIM, RESET } = require('./_colors');
|
|
44
35
|
|
|
45
36
|
// ── Shared Utilities ──────────────────────────────────────────────────────────
|
|
46
|
-
const { findAgentDir } = require(
|
|
47
|
-
|
|
37
|
+
const { findAgentDir } = require('./_utils');
|
|
48
38
|
|
|
49
39
|
function getPaths(startDir = process.cwd()) {
|
|
50
40
|
const agentDir = findAgentDir(startDir);
|
|
51
|
-
const skillDir = path.join(agentDir,
|
|
52
|
-
const historyDir = path.join(agentDir,
|
|
41
|
+
const skillDir = path.join(agentDir, 'skills', 'project-idioms');
|
|
42
|
+
const historyDir = path.join(agentDir, 'history', 'skill-evolution');
|
|
53
43
|
return {
|
|
54
44
|
agentDir,
|
|
55
45
|
skillDir,
|
|
56
|
-
skillFile: path.join(skillDir,
|
|
46
|
+
skillFile: path.join(skillDir, 'SKILL.md'),
|
|
57
47
|
historyDir,
|
|
58
|
-
logFile: path.join(historyDir,
|
|
48
|
+
logFile: path.join(historyDir, 'digest-log.json'),
|
|
59
49
|
};
|
|
60
50
|
}
|
|
61
51
|
|
|
@@ -98,7 +88,7 @@ const NOISE_PATTERNS = [
|
|
|
98
88
|
];
|
|
99
89
|
|
|
100
90
|
function architecturalWeight(line) {
|
|
101
|
-
const code = line.replace(/^[+-]/,
|
|
91
|
+
const code = line.replace(/^[+-]/, '').trim();
|
|
102
92
|
for (const p of NOISE_PATTERNS) {
|
|
103
93
|
if (p.test(code)) return 0;
|
|
104
94
|
}
|
|
@@ -147,34 +137,30 @@ function normalizedSimilarity(a, b) {
|
|
|
147
137
|
*/
|
|
148
138
|
function isDuplicateIdiom(newPattern, existingIdioms, threshold = 0.8) {
|
|
149
139
|
const newLow = newPattern.toLowerCase();
|
|
150
|
-
return existingIdioms.some(
|
|
151
|
-
const exLow = (ex.pattern ||
|
|
140
|
+
return existingIdioms.some(ex => {
|
|
141
|
+
const exLow = (ex.pattern || '').toLowerCase();
|
|
152
142
|
return normalizedSimilarity(newLow, exLow) >= threshold;
|
|
153
143
|
});
|
|
154
144
|
}
|
|
155
145
|
|
|
156
146
|
function semanticDelta(diffText, minWeight = 2) {
|
|
157
|
-
const lines = diffText.split(
|
|
147
|
+
const lines = diffText.split('\n');
|
|
158
148
|
const kept = [];
|
|
159
149
|
let currentHunkHasHigh = false;
|
|
160
150
|
let hunkLines = [];
|
|
161
151
|
|
|
162
152
|
for (const line of lines) {
|
|
163
|
-
if (
|
|
164
|
-
line.startsWith("---") ||
|
|
165
|
-
line.startsWith("+++") ||
|
|
166
|
-
line.startsWith("diff --git")
|
|
167
|
-
) {
|
|
153
|
+
if (line.startsWith('---') || line.startsWith('+++') || line.startsWith('diff --git')) {
|
|
168
154
|
kept.push(line);
|
|
169
155
|
continue;
|
|
170
156
|
}
|
|
171
|
-
if (line.startsWith(
|
|
157
|
+
if (line.startsWith('@@')) {
|
|
172
158
|
if (currentHunkHasHigh) kept.push(...hunkLines);
|
|
173
159
|
currentHunkHasHigh = false;
|
|
174
160
|
hunkLines = [line];
|
|
175
161
|
continue;
|
|
176
162
|
}
|
|
177
|
-
if (line.startsWith(
|
|
163
|
+
if (line.startsWith('+') || line.startsWith('-')) {
|
|
178
164
|
const w = architecturalWeight(line);
|
|
179
165
|
hunkLines.push(line);
|
|
180
166
|
if (w >= minWeight) currentHunkHasHigh = true;
|
|
@@ -184,25 +170,25 @@ function semanticDelta(diffText, minWeight = 2) {
|
|
|
184
170
|
}
|
|
185
171
|
if (currentHunkHasHigh) kept.push(...hunkLines);
|
|
186
172
|
|
|
187
|
-
let result = kept.join(
|
|
188
|
-
result = result.replace(/\n( ?\n){3,}/g,
|
|
173
|
+
let result = kept.join('\n');
|
|
174
|
+
result = result.replace(/\n( ?\n){3,}/g, '\n\n');
|
|
189
175
|
return result.trim();
|
|
190
176
|
}
|
|
191
177
|
|
|
192
178
|
// ── Git helpers ────────────────────────────────────────────────────────────────
|
|
193
|
-
function getGitDiff(mode =
|
|
179
|
+
function getGitDiff(mode = 'staged') {
|
|
194
180
|
try {
|
|
195
181
|
let cmd;
|
|
196
|
-
if (mode ===
|
|
197
|
-
else if (mode ===
|
|
198
|
-
else cmd =
|
|
182
|
+
if (mode === 'staged') cmd = 'git diff --cached --unified=3';
|
|
183
|
+
else if (mode === 'head') cmd = 'git diff HEAD~1 HEAD --unified=3';
|
|
184
|
+
else cmd = 'git diff --unified=3';
|
|
199
185
|
return execSync(cmd, {
|
|
200
|
-
encoding:
|
|
186
|
+
encoding: 'utf8',
|
|
201
187
|
timeout: 10000,
|
|
202
|
-
stdio: [
|
|
188
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
203
189
|
});
|
|
204
190
|
} catch {
|
|
205
|
-
return
|
|
191
|
+
return '';
|
|
206
192
|
}
|
|
207
193
|
}
|
|
208
194
|
|
|
@@ -214,10 +200,9 @@ function countTokensEstimate(text) {
|
|
|
214
200
|
function loadExistingIdioms() {
|
|
215
201
|
const { skillFile } = getPaths();
|
|
216
202
|
if (!fs.existsSync(skillFile)) return [];
|
|
217
|
-
const content = fs.readFileSync(skillFile,
|
|
203
|
+
const content = fs.readFileSync(skillFile, 'utf8');
|
|
218
204
|
const idioms = [];
|
|
219
|
-
const pattern =
|
|
220
|
-
/\|\s*(\d+)\s*\|\s*`([^`]+)`\s*\|\s*([^|]+)\|\s*([^|]+)\|\s*([^|]+)\|/g;
|
|
205
|
+
const pattern = /\|\s*(\d+)\s*\|\s*`([^`]+)`\s*\|\s*([^|]+)\|\s*([^|]+)\|\s*([^|]+)\|/g;
|
|
221
206
|
let m;
|
|
222
207
|
while ((m = pattern.exec(content)) !== null) {
|
|
223
208
|
idioms.push({
|
|
@@ -233,16 +218,15 @@ function loadExistingIdioms() {
|
|
|
233
218
|
|
|
234
219
|
function nextIdiomId(idioms) {
|
|
235
220
|
if (!idioms.length) return 1;
|
|
236
|
-
return Math.max(...idioms.map(
|
|
221
|
+
return Math.max(...idioms.map(i => i.id)) + 1;
|
|
237
222
|
}
|
|
238
223
|
|
|
239
224
|
function renderSkillMd(idioms, digestCount) {
|
|
240
225
|
const now = new Date().toISOString().slice(0, 10);
|
|
241
226
|
const rows = idioms.map(
|
|
242
|
-
|
|
243
|
-
`| ${i.id} | \`${i.pattern}\` | ${i.reason} | ${i.domain} | ${i.since} |`,
|
|
227
|
+
i => `| ${i.id} | \`${i.pattern}\` | ${i.reason} | ${i.domain} | ${i.since} |`,
|
|
244
228
|
);
|
|
245
|
-
const table = rows.length ? rows.join(
|
|
229
|
+
const table = rows.length ? rows.join('\n') : '_No idioms recorded yet._';
|
|
246
230
|
|
|
247
231
|
return `---
|
|
248
232
|
name: project-idioms
|
|
@@ -330,22 +314,22 @@ function parseLlmYamlResponse(response) {
|
|
|
330
314
|
let inIdioms = false;
|
|
331
315
|
let current = {};
|
|
332
316
|
|
|
333
|
-
for (const line of response.split(
|
|
317
|
+
for (const line of response.split('\n')) {
|
|
334
318
|
const stripped = line.trim();
|
|
335
|
-
if (stripped ===
|
|
319
|
+
if (stripped === 'idioms:') {
|
|
336
320
|
inIdioms = true;
|
|
337
321
|
continue;
|
|
338
322
|
}
|
|
339
323
|
if (!inIdioms) continue;
|
|
340
|
-
if (stripped.startsWith(
|
|
324
|
+
if (stripped.startsWith('- pattern:')) {
|
|
341
325
|
if (current.pattern) idioms.push(current);
|
|
342
326
|
current = {
|
|
343
|
-
pattern: stripped.split(
|
|
327
|
+
pattern: stripped.split(':', 2)[1].trim().replace(/^"|"$/g, ''),
|
|
344
328
|
};
|
|
345
|
-
} else if (stripped.startsWith(
|
|
346
|
-
current.reason = stripped.split(
|
|
347
|
-
} else if (stripped.startsWith(
|
|
348
|
-
current.domain = stripped.split(
|
|
329
|
+
} else if (stripped.startsWith('reason:') && current.pattern) {
|
|
330
|
+
current.reason = stripped.split(':', 2)[1].trim().replace(/^"|"$/g, '');
|
|
331
|
+
} else if (stripped.startsWith('domain:') && current.pattern) {
|
|
332
|
+
current.domain = stripped.split(':', 2)[1].trim().replace(/^"|"$/g, '');
|
|
349
333
|
}
|
|
350
334
|
}
|
|
351
335
|
if (current.pattern) idioms.push(current);
|
|
@@ -358,7 +342,7 @@ function loadLog() {
|
|
|
358
342
|
fs.mkdirSync(historyDir, { recursive: true });
|
|
359
343
|
if (fs.existsSync(logFile)) {
|
|
360
344
|
try {
|
|
361
|
-
return JSON.parse(fs.readFileSync(logFile,
|
|
345
|
+
return JSON.parse(fs.readFileSync(logFile, 'utf8'));
|
|
362
346
|
} catch {
|
|
363
347
|
/* fallthrough */
|
|
364
348
|
}
|
|
@@ -369,7 +353,7 @@ function loadLog() {
|
|
|
369
353
|
function saveLog(log) {
|
|
370
354
|
const { historyDir, logFile } = getPaths();
|
|
371
355
|
fs.mkdirSync(historyDir, { recursive: true });
|
|
372
|
-
fs.writeFileSync(logFile, JSON.stringify(log, null, 2),
|
|
356
|
+
fs.writeFileSync(logFile, JSON.stringify(log, null, 2), 'utf8');
|
|
373
357
|
}
|
|
374
358
|
|
|
375
359
|
// ── Auto-LLM API Integration ─────────────────────────────────────────────────
|
|
@@ -379,11 +363,9 @@ function saveLog(log) {
|
|
|
379
363
|
|
|
380
364
|
function detectLlmProvider() {
|
|
381
365
|
if (process.env.ANTHROPIC_API_KEY)
|
|
382
|
-
return { provider:
|
|
383
|
-
if (process.env.OPENAI_API_KEY)
|
|
384
|
-
|
|
385
|
-
if (process.env.GEMINI_API_KEY)
|
|
386
|
-
return { provider: "gemini", key: process.env.GEMINI_API_KEY };
|
|
366
|
+
return { provider: 'anthropic', key: process.env.ANTHROPIC_API_KEY };
|
|
367
|
+
if (process.env.OPENAI_API_KEY) return { provider: 'openai', key: process.env.OPENAI_API_KEY };
|
|
368
|
+
if (process.env.GEMINI_API_KEY) return { provider: 'gemini', key: process.env.GEMINI_API_KEY };
|
|
387
369
|
return null;
|
|
388
370
|
}
|
|
389
371
|
|
|
@@ -404,23 +386,23 @@ async function callLlmApi(prompt, provider, apiKey) {
|
|
|
404
386
|
const data = JSON.stringify(body);
|
|
405
387
|
const req = https.request(
|
|
406
388
|
{
|
|
407
|
-
method:
|
|
389
|
+
method: 'POST',
|
|
408
390
|
hostname,
|
|
409
391
|
path,
|
|
410
|
-
headers: { ...headers,
|
|
392
|
+
headers: { ...headers, 'Content-Length': Buffer.byteLength(data) },
|
|
411
393
|
},
|
|
412
|
-
|
|
413
|
-
let raw =
|
|
414
|
-
res.on(
|
|
394
|
+
res => {
|
|
395
|
+
let raw = '';
|
|
396
|
+
res.on('data', c => {
|
|
415
397
|
raw += c;
|
|
416
398
|
});
|
|
417
|
-
res.on(
|
|
418
|
-
res.on(
|
|
399
|
+
res.on('end', () => resolve(raw));
|
|
400
|
+
res.on('error', reject);
|
|
419
401
|
},
|
|
420
402
|
);
|
|
421
|
-
req.on(
|
|
403
|
+
req.on('error', reject);
|
|
422
404
|
req.setTimeout(timeout, () => {
|
|
423
|
-
req.destroy(new Error(
|
|
405
|
+
req.destroy(new Error('LLM API timeout'));
|
|
424
406
|
});
|
|
425
407
|
req.write(data);
|
|
426
408
|
req.end();
|
|
@@ -428,37 +410,37 @@ async function callLlmApi(prompt, provider, apiKey) {
|
|
|
428
410
|
}
|
|
429
411
|
|
|
430
412
|
try {
|
|
431
|
-
if (provider ===
|
|
413
|
+
if (provider === 'anthropic') {
|
|
432
414
|
const raw = await httpsPost(
|
|
433
|
-
|
|
434
|
-
|
|
415
|
+
'api.anthropic.com',
|
|
416
|
+
'/v1/messages',
|
|
435
417
|
{
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
418
|
+
'Content-Type': 'application/json',
|
|
419
|
+
'x-api-key': apiKey,
|
|
420
|
+
'anthropic-version': '2023-06-01',
|
|
439
421
|
},
|
|
440
422
|
{
|
|
441
|
-
model:
|
|
423
|
+
model: 'claude-3-haiku-20240307', // Fastest/cheapest — idiom extraction
|
|
442
424
|
max_tokens: 512,
|
|
443
|
-
messages: [{ role:
|
|
425
|
+
messages: [{ role: 'user', content: prompt }],
|
|
444
426
|
},
|
|
445
427
|
);
|
|
446
428
|
const json = JSON.parse(raw);
|
|
447
429
|
return json?.content?.[0]?.text ?? null;
|
|
448
430
|
}
|
|
449
431
|
|
|
450
|
-
if (provider ===
|
|
432
|
+
if (provider === 'openai') {
|
|
451
433
|
const raw = await httpsPost(
|
|
452
|
-
|
|
453
|
-
|
|
434
|
+
'api.openai.com',
|
|
435
|
+
'/v1/chat/completions',
|
|
454
436
|
{
|
|
455
|
-
|
|
437
|
+
'Content-Type': 'application/json',
|
|
456
438
|
Authorization: `Bearer ${apiKey}`,
|
|
457
439
|
},
|
|
458
440
|
{
|
|
459
|
-
model:
|
|
441
|
+
model: 'gpt-4o-mini', // Cheapest capable model for YAML extraction
|
|
460
442
|
max_tokens: 512,
|
|
461
|
-
messages: [{ role:
|
|
443
|
+
messages: [{ role: 'user', content: prompt }],
|
|
462
444
|
temperature: 0.1,
|
|
463
445
|
},
|
|
464
446
|
);
|
|
@@ -466,11 +448,11 @@ async function callLlmApi(prompt, provider, apiKey) {
|
|
|
466
448
|
return json?.choices?.[0]?.message?.content ?? null;
|
|
467
449
|
}
|
|
468
450
|
|
|
469
|
-
if (provider ===
|
|
451
|
+
if (provider === 'gemini') {
|
|
470
452
|
const raw = await httpsPost(
|
|
471
|
-
|
|
453
|
+
'generativelanguage.googleapis.com',
|
|
472
454
|
`/v1beta/models/gemini-1.5-flash:generateContent?key=${apiKey}`,
|
|
473
|
-
{
|
|
455
|
+
{ 'Content-Type': 'application/json' },
|
|
474
456
|
{
|
|
475
457
|
contents: [{ parts: [{ text: prompt }] }],
|
|
476
458
|
generationConfig: { maxOutputTokens: 512, temperature: 0.1 },
|
|
@@ -488,8 +470,8 @@ async function callLlmApi(prompt, provider, apiKey) {
|
|
|
488
470
|
// ── Commands ──────────────────────────────────────────────────────────────────
|
|
489
471
|
// ── Strategy Filtering ────────────────────────────────────────────────────────
|
|
490
472
|
function applyStrategyFilter(signals, strategy) {
|
|
491
|
-
if (strategy ===
|
|
492
|
-
return signals.filter(
|
|
473
|
+
if (strategy === 'repair-only') {
|
|
474
|
+
return signals.filter(s => s.type === 'log_error');
|
|
493
475
|
}
|
|
494
476
|
return signals;
|
|
495
477
|
}
|
|
@@ -531,52 +513,64 @@ function parseEvolutionYaml(response) {
|
|
|
531
513
|
let currentSection = null; // 'idioms' | 'cases'
|
|
532
514
|
let current = null;
|
|
533
515
|
|
|
534
|
-
const lines = response.split(
|
|
516
|
+
const lines = response.split('\n');
|
|
535
517
|
for (const line of lines) {
|
|
536
518
|
const trimmed = line.trim();
|
|
537
|
-
if (trimmed ===
|
|
519
|
+
if (trimmed === 'idioms:') {
|
|
538
520
|
if (current) {
|
|
539
|
-
if (currentSection ===
|
|
540
|
-
if (currentSection ===
|
|
521
|
+
if (currentSection === 'idioms') idioms.push(current);
|
|
522
|
+
if (currentSection === 'cases') cases.push(current);
|
|
541
523
|
}
|
|
542
|
-
currentSection =
|
|
524
|
+
currentSection = 'idioms';
|
|
543
525
|
current = null;
|
|
544
526
|
continue;
|
|
545
527
|
}
|
|
546
|
-
if (trimmed ===
|
|
528
|
+
if (trimmed === 'cases:') {
|
|
547
529
|
if (current) {
|
|
548
|
-
if (currentSection ===
|
|
549
|
-
if (currentSection ===
|
|
530
|
+
if (currentSection === 'idioms') idioms.push(current);
|
|
531
|
+
if (currentSection === 'cases') cases.push(current);
|
|
550
532
|
}
|
|
551
|
-
currentSection =
|
|
533
|
+
currentSection = 'cases';
|
|
552
534
|
current = null;
|
|
553
535
|
continue;
|
|
554
536
|
}
|
|
555
537
|
|
|
556
|
-
if (
|
|
538
|
+
if (
|
|
539
|
+
trimmed.startsWith('- pattern:') ||
|
|
540
|
+
(trimmed.startsWith('- ') && trimmed.includes('pattern:'))
|
|
541
|
+
) {
|
|
557
542
|
if (current) {
|
|
558
|
-
if (currentSection ===
|
|
559
|
-
if (currentSection ===
|
|
543
|
+
if (currentSection === 'idioms') idioms.push(current);
|
|
544
|
+
if (currentSection === 'cases') cases.push(current);
|
|
560
545
|
}
|
|
561
|
-
let pat =
|
|
562
|
-
if (trimmed.startsWith(
|
|
563
|
-
pat = trimmed.substring(
|
|
546
|
+
let pat = '';
|
|
547
|
+
if (trimmed.startsWith('- pattern:')) {
|
|
548
|
+
pat = trimmed.substring('- pattern:'.length).trim();
|
|
564
549
|
} else {
|
|
565
|
-
pat = trimmed.split(
|
|
550
|
+
pat = trimmed.split('pattern:', 2)[1].trim();
|
|
566
551
|
}
|
|
567
|
-
current = { pattern: pat.replace(/^['"]|['"]$/g,
|
|
568
|
-
} else if (trimmed.startsWith(
|
|
569
|
-
current.reason = trimmed
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
552
|
+
current = { pattern: pat.replace(/^['"]|['"]$/g, '') };
|
|
553
|
+
} else if (trimmed.startsWith('reason:') && current) {
|
|
554
|
+
current.reason = trimmed
|
|
555
|
+
.substring('reason:'.length)
|
|
556
|
+
.trim()
|
|
557
|
+
.replace(/^['"]|['"]$/g, '');
|
|
558
|
+
} else if (trimmed.startsWith('domain:') && current) {
|
|
559
|
+
current.domain = trimmed
|
|
560
|
+
.substring('domain:'.length)
|
|
561
|
+
.trim()
|
|
562
|
+
.replace(/^['"]|['"]$/g, '');
|
|
563
|
+
} else if (trimmed.startsWith('verdict:') && current) {
|
|
564
|
+
current.verdict = trimmed
|
|
565
|
+
.substring('verdict:'.length)
|
|
566
|
+
.trim()
|
|
567
|
+
.replace(/^['"]|['"]$/g, '');
|
|
574
568
|
}
|
|
575
569
|
}
|
|
576
570
|
|
|
577
571
|
if (current) {
|
|
578
|
-
if (currentSection ===
|
|
579
|
-
if (currentSection ===
|
|
572
|
+
if (currentSection === 'idioms') idioms.push(current);
|
|
573
|
+
if (currentSection === 'cases') cases.push(current);
|
|
580
574
|
}
|
|
581
575
|
|
|
582
576
|
return { idioms, cases };
|
|
@@ -584,23 +578,20 @@ function parseEvolutionYaml(response) {
|
|
|
584
578
|
|
|
585
579
|
// ── Commands ──────────────────────────────────────────────────────────────────
|
|
586
580
|
async function cmdDigest(args) {
|
|
587
|
-
const dryRun = args.includes(
|
|
588
|
-
const diffMode = args.includes(
|
|
581
|
+
const dryRun = args.includes('--dry-run');
|
|
582
|
+
const diffMode = args.includes('--head') ? 'head' : 'staged';
|
|
589
583
|
|
|
590
|
-
const logArg = args.find(
|
|
591
|
-
const logFile = logArg ? logArg.split(
|
|
584
|
+
const logArg = args.find(a => a.startsWith('--log='));
|
|
585
|
+
const logFile = logArg ? logArg.split('=').slice(1).join('=') : null;
|
|
592
586
|
|
|
593
|
-
const strategyArg = args.find(
|
|
594
|
-
const strategy = strategyArg ? strategyArg.split(
|
|
587
|
+
const strategyArg = args.find(a => a.startsWith('--strategy='));
|
|
588
|
+
const strategy = strategyArg ? strategyArg.split('=').slice(1).join('=') : 'balanced';
|
|
595
589
|
|
|
596
|
-
console.log(
|
|
597
|
-
|
|
598
|
-
);
|
|
599
|
-
if (dryRun)
|
|
600
|
-
console.log(` ${YELLOW}DRY RUN — no files will be written${RESET}\n`);
|
|
590
|
+
console.log(`\n${BOLD}${CYAN}━━━ Skill Evolution — Digest Cycle ━━━━━━━━━━━━━━━━${RESET}`);
|
|
591
|
+
if (dryRun) console.log(` ${YELLOW}DRY RUN — no files will be written${RESET}\n`);
|
|
601
592
|
|
|
602
|
-
let rawDiff =
|
|
603
|
-
let delta =
|
|
593
|
+
let rawDiff = '';
|
|
594
|
+
let delta = '';
|
|
604
595
|
let rawTokens = 0;
|
|
605
596
|
let deltaTokens = 0;
|
|
606
597
|
let logSignals = [];
|
|
@@ -612,28 +603,22 @@ async function cmdDigest(args) {
|
|
|
612
603
|
console.log(` ${RED}✖ Log file not found: ${logFile}${RESET}\n`);
|
|
613
604
|
return;
|
|
614
605
|
}
|
|
615
|
-
const logText = fs.readFileSync(logFile,
|
|
606
|
+
const logText = fs.readFileSync(logFile, 'utf8');
|
|
616
607
|
rawTokens = countTokensEstimate(logText);
|
|
617
608
|
|
|
618
|
-
console.log(
|
|
619
|
-
|
|
620
|
-
);
|
|
621
|
-
const { detectSignals } = require("./signal_detector");
|
|
609
|
+
console.log(` ${DIM}[2/5] Extracting signals from log (Signal Detector)...${RESET}`);
|
|
610
|
+
const { detectSignals } = require('./signal_detector');
|
|
622
611
|
const signals = detectSignals(logText);
|
|
623
612
|
|
|
624
613
|
if (signals.length === 0) {
|
|
625
|
-
console.log(
|
|
626
|
-
` ${GREEN}✔ No errors or performance signals found in logs.${RESET}`,
|
|
627
|
-
);
|
|
614
|
+
console.log(` ${GREEN}✔ No errors or performance signals found in logs.${RESET}`);
|
|
628
615
|
console.log(` ${DIM} No self-evolution reflection needed.${RESET}\n`);
|
|
629
616
|
return;
|
|
630
617
|
}
|
|
631
618
|
|
|
632
619
|
logSignals = applyStrategyFilter(signals, strategy);
|
|
633
620
|
if (logSignals.length === 0) {
|
|
634
|
-
console.log(
|
|
635
|
-
` ${YELLOW}⚠ Strategy filter [${strategy}] filtered out all signals.${RESET}\n`,
|
|
636
|
-
);
|
|
621
|
+
console.log(` ${YELLOW}⚠ Strategy filter [${strategy}] filtered out all signals.${RESET}\n`);
|
|
637
622
|
return;
|
|
638
623
|
}
|
|
639
624
|
|
|
@@ -642,45 +627,33 @@ async function cmdDigest(args) {
|
|
|
642
627
|
);
|
|
643
628
|
|
|
644
629
|
delta = logSignals
|
|
645
|
-
.map(
|
|
630
|
+
.map(s => {
|
|
646
631
|
let chunk = `--- SIGNAL: ${s.type} ---\n`;
|
|
647
|
-
if (s.file) chunk += `File: ${s.file}${s.line ? `:${s.line}` :
|
|
632
|
+
if (s.file) chunk += `File: ${s.file}${s.line ? `:${s.line}` : ''}\n`;
|
|
648
633
|
chunk += `Message: ${s.message}\n`;
|
|
649
634
|
chunk += `Context:\n${s.context}\n`;
|
|
650
635
|
return chunk;
|
|
651
636
|
})
|
|
652
|
-
.join(
|
|
637
|
+
.join('\n\n');
|
|
653
638
|
|
|
654
639
|
deltaTokens = countTokensEstimate(delta);
|
|
655
640
|
} else {
|
|
656
641
|
console.log(` ${DIM}[1/5] Fetching git diff (${diffMode})...${RESET}`);
|
|
657
642
|
rawDiff = getGitDiff(diffMode);
|
|
658
643
|
if (!rawDiff.trim()) {
|
|
659
|
-
console.log(
|
|
660
|
-
|
|
661
|
-
);
|
|
662
|
-
console.log(
|
|
663
|
-
` ${DIM}Tip: Use --head to diff against the last commit.${RESET}\n`,
|
|
664
|
-
);
|
|
644
|
+
console.log(` ${YELLOW}⚠ No diff found. Commit or stage changes first.${RESET}`);
|
|
645
|
+
console.log(` ${DIM}Tip: Use --head to diff against the last commit.${RESET}\n`);
|
|
665
646
|
return;
|
|
666
647
|
}
|
|
667
648
|
|
|
668
649
|
rawTokens = countTokensEstimate(rawDiff);
|
|
669
|
-
console.log(
|
|
670
|
-
` ${DIM} Raw diff: ~${rawTokens} tokens (${rawDiff.length} chars)${RESET}`,
|
|
671
|
-
);
|
|
650
|
+
console.log(` ${DIM} Raw diff: ~${rawTokens} tokens (${rawDiff.length} chars)${RESET}`);
|
|
672
651
|
|
|
673
|
-
console.log(
|
|
674
|
-
` ${DIM}[2/5] Extracting architectural delta (Semantic Filter)...${RESET}`,
|
|
675
|
-
);
|
|
652
|
+
console.log(` ${DIM}[2/5] Extracting architectural delta (Semantic Filter)...${RESET}`);
|
|
676
653
|
delta = semanticDelta(rawDiff, 2);
|
|
677
654
|
if (!delta.trim()) {
|
|
678
|
-
console.log(
|
|
679
|
-
|
|
680
|
-
);
|
|
681
|
-
console.log(
|
|
682
|
-
` ${DIM} No LLM call needed. Zero tokens consumed.${RESET}\n`,
|
|
683
|
-
);
|
|
655
|
+
console.log(` ${GREEN}✔ Delta is 100% trivial (whitespace/comments/imports only).${RESET}`);
|
|
656
|
+
console.log(` ${DIM} No LLM call needed. Zero tokens consumed.${RESET}\n`);
|
|
684
657
|
return;
|
|
685
658
|
}
|
|
686
659
|
|
|
@@ -694,25 +667,21 @@ async function cmdDigest(args) {
|
|
|
694
667
|
);
|
|
695
668
|
|
|
696
669
|
console.log(`\n ${BOLD}Architectural Delta Preview:${RESET}`);
|
|
697
|
-
const previewLines = delta.split(
|
|
670
|
+
const previewLines = delta.split('\n').slice(0, 20);
|
|
698
671
|
for (const line of previewLines) {
|
|
699
|
-
if (line.startsWith(
|
|
700
|
-
else if (line.startsWith(
|
|
701
|
-
else if (line.startsWith(
|
|
672
|
+
if (line.startsWith('+')) console.log(` ${GREEN}${line}${RESET}`);
|
|
673
|
+
else if (line.startsWith('-')) console.log(` ${RED}${line}${RESET}`);
|
|
674
|
+
else if (line.startsWith('@@')) console.log(` ${BLUE}${line}${RESET}`);
|
|
702
675
|
else console.log(` ${DIM}${line}${RESET}`);
|
|
703
676
|
}
|
|
704
|
-
if (delta.split(
|
|
705
|
-
console.log(
|
|
706
|
-
` ... (${delta.split("\n").length - 20} more lines)`,
|
|
707
|
-
);
|
|
677
|
+
if (delta.split('\n').length > 20)
|
|
678
|
+
console.log(` ... (${delta.split('\n').length - 20} more lines)`);
|
|
708
679
|
|
|
709
680
|
if (dryRun) {
|
|
710
681
|
console.log(
|
|
711
682
|
`\n ${YELLOW}[DRY RUN] Would send ${deltaTokens} tokens to LLM for reflection.${RESET}`,
|
|
712
683
|
);
|
|
713
|
-
console.log(
|
|
714
|
-
` ${DIM}Run without --dry-run to complete the digest.${RESET}\n`,
|
|
715
|
-
);
|
|
684
|
+
console.log(` ${DIM}Run without --dry-run to complete the digest.${RESET}\n`);
|
|
716
685
|
return;
|
|
717
686
|
}
|
|
718
687
|
|
|
@@ -720,27 +689,19 @@ async function cmdDigest(args) {
|
|
|
720
689
|
const reflectionPrompt = isLogMode
|
|
721
690
|
? generateLogReflectionPrompt(delta)
|
|
722
691
|
: generateReflectionPrompt(delta);
|
|
723
|
-
let llmResponse =
|
|
692
|
+
let llmResponse = '';
|
|
724
693
|
|
|
725
694
|
let llmCreds = detectLlmProvider();
|
|
726
695
|
if (llmCreds) {
|
|
727
|
-
console.log(
|
|
728
|
-
|
|
729
|
-
);
|
|
730
|
-
const autoResponse = await callLlmApi(
|
|
731
|
-
reflectionPrompt,
|
|
732
|
-
llmCreds.provider,
|
|
733
|
-
llmCreds.key,
|
|
734
|
-
);
|
|
696
|
+
console.log(` ${DIM}[3/5] LLM Reflection — auto-calling ${llmCreds.provider} API...${RESET}`);
|
|
697
|
+
const autoResponse = await callLlmApi(reflectionPrompt, llmCreds.provider, llmCreds.key);
|
|
735
698
|
if (autoResponse) {
|
|
736
699
|
llmResponse = autoResponse;
|
|
737
700
|
console.log(
|
|
738
|
-
` ${GREEN}✔ Auto-response received (${llmCreds.provider}) — ${llmResponse.split(
|
|
701
|
+
` ${GREEN}✔ Auto-response received (${llmCreds.provider}) — ${llmResponse.split('\n').length} lines${RESET}`,
|
|
739
702
|
);
|
|
740
703
|
} else {
|
|
741
|
-
console.log(
|
|
742
|
-
` ${YELLOW}⚠ API call failed — falling back to manual mode${RESET}`,
|
|
743
|
-
);
|
|
704
|
+
console.log(` ${YELLOW}⚠ API call failed — falling back to manual mode${RESET}`);
|
|
744
705
|
llmCreds = null;
|
|
745
706
|
}
|
|
746
707
|
}
|
|
@@ -753,29 +714,27 @@ async function cmdDigest(args) {
|
|
|
753
714
|
console.log(
|
|
754
715
|
` ${DIM} Tip: Set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GEMINI_API_KEY to automate this step.${RESET}`,
|
|
755
716
|
);
|
|
756
|
-
console.log(`\n ${BOLD}${
|
|
717
|
+
console.log(`\n ${BOLD}${'─'.repeat(60)}${RESET}`);
|
|
757
718
|
console.log(reflectionPrompt);
|
|
758
|
-
console.log(` ${BOLD}${
|
|
759
|
-
console.log(
|
|
760
|
-
`\n ${BOLD}Paste LLM response below (type END_RESPONSE when done):${RESET}`,
|
|
761
|
-
);
|
|
719
|
+
console.log(` ${BOLD}${'─'.repeat(60)}${RESET}`);
|
|
720
|
+
console.log(`\n ${BOLD}Paste LLM response below (type END_RESPONSE when done):${RESET}`);
|
|
762
721
|
|
|
763
722
|
const rl = readline.createInterface({
|
|
764
723
|
input: process.stdin,
|
|
765
724
|
output: process.stdout,
|
|
766
725
|
});
|
|
767
726
|
const responseLines = [];
|
|
768
|
-
await new Promise(
|
|
769
|
-
const listener =
|
|
770
|
-
if (line.trim() ===
|
|
771
|
-
rl.removeListener(
|
|
727
|
+
await new Promise(resolve => {
|
|
728
|
+
const listener = line => {
|
|
729
|
+
if (line.trim() === 'END_RESPONSE') {
|
|
730
|
+
rl.removeListener('line', listener);
|
|
772
731
|
resolve();
|
|
773
732
|
} else responseLines.push(line);
|
|
774
733
|
};
|
|
775
|
-
rl.on(
|
|
734
|
+
rl.on('line', listener);
|
|
776
735
|
});
|
|
777
736
|
rl.close();
|
|
778
|
-
llmResponse = responseLines.join(
|
|
737
|
+
llmResponse = responseLines.join('\n');
|
|
779
738
|
}
|
|
780
739
|
|
|
781
740
|
console.log(`\n ${DIM}[4/5] Parsing idioms/cases...${RESET}`);
|
|
@@ -791,9 +750,7 @@ async function cmdDigest(args) {
|
|
|
791
750
|
}
|
|
792
751
|
|
|
793
752
|
if (!newIdioms.length && !newCases.length) {
|
|
794
|
-
console.log(
|
|
795
|
-
` ${YELLOW}⚠ No idioms or cases extracted from LLM response.${RESET}`,
|
|
796
|
-
);
|
|
753
|
+
console.log(` ${YELLOW}⚠ No idioms or cases extracted from LLM response.${RESET}`);
|
|
797
754
|
console.log(`\n`);
|
|
798
755
|
return;
|
|
799
756
|
}
|
|
@@ -801,24 +758,18 @@ async function cmdDigest(args) {
|
|
|
801
758
|
if (newIdioms.length > 0) {
|
|
802
759
|
console.log(` ${GREEN}✔ Extracted ${newIdioms.length} idiom(s)${RESET}`);
|
|
803
760
|
for (const idiom of newIdioms) {
|
|
804
|
-
console.log(
|
|
805
|
-
` ${CYAN}• ${idiom.pattern || "?"}${RESET} — ${idiom.reason || ""}`,
|
|
806
|
-
);
|
|
761
|
+
console.log(` ${CYAN}• ${idiom.pattern || '?'}${RESET} — ${idiom.reason || ''}`);
|
|
807
762
|
}
|
|
808
763
|
}
|
|
809
764
|
|
|
810
765
|
if (newCases.length > 0) {
|
|
811
766
|
console.log(` ${GREEN}✔ Extracted ${newCases.length} case precedent(s)${RESET}`);
|
|
812
767
|
for (const c of newCases) {
|
|
813
|
-
console.log(
|
|
814
|
-
` ${RED}• ${c.pattern || "?"}${RESET} — ${c.reason || ""}`,
|
|
815
|
-
);
|
|
768
|
+
console.log(` ${RED}• ${c.pattern || '?'}${RESET} — ${c.reason || ''}`);
|
|
816
769
|
}
|
|
817
770
|
}
|
|
818
771
|
|
|
819
|
-
console.log(
|
|
820
|
-
`\n ${DIM}[5/5] Merging into project-idioms/SKILL.md...${RESET}`,
|
|
821
|
-
);
|
|
772
|
+
console.log(`\n ${DIM}[5/5] Merging into project-idioms/SKILL.md...${RESET}`);
|
|
822
773
|
const existing = loadExistingIdioms();
|
|
823
774
|
const log = loadLog();
|
|
824
775
|
let nextId = nextIdiomId(existing);
|
|
@@ -827,15 +778,15 @@ async function cmdDigest(args) {
|
|
|
827
778
|
let added = 0;
|
|
828
779
|
|
|
829
780
|
for (const idiom of newIdioms) {
|
|
830
|
-
if (isDuplicateIdiom(idiom.pattern ||
|
|
781
|
+
if (isDuplicateIdiom(idiom.pattern || '', existing)) {
|
|
831
782
|
console.log(` ${DIM} Skipped near-duplicate idiom: ${idiom.pattern}${RESET}`);
|
|
832
783
|
continue;
|
|
833
784
|
}
|
|
834
785
|
merged.push({
|
|
835
786
|
id: nextId,
|
|
836
|
-
pattern: idiom.pattern ||
|
|
837
|
-
reason: idiom.reason ||
|
|
838
|
-
domain: idiom.domain ||
|
|
787
|
+
pattern: idiom.pattern || '?',
|
|
788
|
+
reason: idiom.reason || 'No reason provided.',
|
|
789
|
+
domain: idiom.domain || 'general',
|
|
839
790
|
since: today,
|
|
840
791
|
});
|
|
841
792
|
nextId++;
|
|
@@ -847,7 +798,7 @@ async function cmdDigest(args) {
|
|
|
847
798
|
const skillMd = renderSkillMd(merged, (log.cycles || []).length + 1);
|
|
848
799
|
const { skillDir, skillFile } = getPaths();
|
|
849
800
|
fs.mkdirSync(skillDir, { recursive: true });
|
|
850
|
-
fs.writeFileSync(skillFile, skillMd,
|
|
801
|
+
fs.writeFileSync(skillFile, skillMd, 'utf8');
|
|
851
802
|
console.log(` ${GREEN}✔ ${added} new idiom(s) added to SKILL.md${RESET}`);
|
|
852
803
|
} else {
|
|
853
804
|
console.log(` ${DIM} No new unique idioms added to SKILL.md.${RESET}`);
|
|
@@ -856,16 +807,16 @@ async function cmdDigest(args) {
|
|
|
856
807
|
// Record Case Precedents if present
|
|
857
808
|
if (newCases && newCases.length > 0) {
|
|
858
809
|
console.log(`\n ${DIM}Merging into Case Law precedents...${RESET}`);
|
|
859
|
-
const caseLawManager = require(
|
|
810
|
+
const caseLawManager = require('./case_law_manager');
|
|
860
811
|
const clIndex = caseLawManager.loadIndex();
|
|
861
812
|
let clNextId = clIndex.next_id;
|
|
862
813
|
let clAdded = 0;
|
|
863
814
|
|
|
864
815
|
for (const c of newCases) {
|
|
865
|
-
const diffText = c.pattern ||
|
|
866
|
-
const reason = c.reason ||
|
|
867
|
-
const domain = c.domain ||
|
|
868
|
-
const verdict = c.verdict ||
|
|
816
|
+
const diffText = c.pattern || '';
|
|
817
|
+
const reason = c.reason || '';
|
|
818
|
+
const domain = c.domain || 'general';
|
|
819
|
+
const verdict = c.verdict || 'REJECTED';
|
|
869
820
|
const fingerprint = caseLawManager.contentHash(diffText);
|
|
870
821
|
|
|
871
822
|
let isDup = false;
|
|
@@ -876,14 +827,12 @@ async function cmdDigest(args) {
|
|
|
876
827
|
}
|
|
877
828
|
}
|
|
878
829
|
if (isDup) {
|
|
879
|
-
console.log(
|
|
880
|
-
` ${DIM} Skipped duplicate case: ${reason.slice(0, 50)}...${RESET}`,
|
|
881
|
-
);
|
|
830
|
+
console.log(` ${DIM} Skipped duplicate case: ${reason.slice(0, 50)}...${RESET}`);
|
|
882
831
|
continue;
|
|
883
832
|
}
|
|
884
833
|
|
|
885
834
|
const deltaCase = caseLawManager.semanticDelta(diffText);
|
|
886
|
-
const tags = caseLawManager.extractTags(diffText +
|
|
835
|
+
const tags = caseLawManager.extractTags(diffText + ' ' + reason);
|
|
887
836
|
const caseRecord = {
|
|
888
837
|
id: clNextId,
|
|
889
838
|
fingerprint,
|
|
@@ -891,8 +840,8 @@ async function cmdDigest(args) {
|
|
|
891
840
|
domain,
|
|
892
841
|
verdict,
|
|
893
842
|
reason: reason.trim(),
|
|
894
|
-
pr_ref:
|
|
895
|
-
reviewer:
|
|
843
|
+
pr_ref: 'auto-evolution',
|
|
844
|
+
reviewer: 'skill-evolution',
|
|
896
845
|
tags,
|
|
897
846
|
stack_version: null,
|
|
898
847
|
diff_raw: diffText.trim(),
|
|
@@ -937,20 +886,16 @@ async function cmdDigest(args) {
|
|
|
937
886
|
|
|
938
887
|
console.log(`\n ${GREEN}✔ Learn cycle complete.${RESET}`);
|
|
939
888
|
console.log(` ${DIM} Total idioms: ${merged.length}${RESET}`);
|
|
940
|
-
console.log(
|
|
941
|
-
` ${DIM} Lifetime tokens saved: ${log.total_tokens_saved}${RESET}\n`,
|
|
942
|
-
);
|
|
889
|
+
console.log(` ${DIM} Lifetime tokens saved: ${log.total_tokens_saved}${RESET}\n`);
|
|
943
890
|
}
|
|
944
891
|
|
|
945
892
|
function cmdShow() {
|
|
946
893
|
const { skillFile } = getPaths();
|
|
947
894
|
if (!fs.existsSync(skillFile)) {
|
|
948
|
-
console.log(
|
|
949
|
-
`${YELLOW}No project-idioms skill found. Run 'digest' first.${RESET}`,
|
|
950
|
-
);
|
|
895
|
+
console.log(`${YELLOW}No project-idioms skill found. Run 'digest' first.${RESET}`);
|
|
951
896
|
return;
|
|
952
897
|
}
|
|
953
|
-
console.log(fs.readFileSync(skillFile,
|
|
898
|
+
console.log(fs.readFileSync(skillFile, 'utf8'));
|
|
954
899
|
}
|
|
955
900
|
|
|
956
901
|
function cmdReset() {
|
|
@@ -974,34 +919,28 @@ function cmdStatus() {
|
|
|
974
919
|
const { skillFile } = getPaths();
|
|
975
920
|
const idiomsExist = fs.existsSync(skillFile);
|
|
976
921
|
|
|
977
|
-
console.log(
|
|
978
|
-
`\n${BOLD}${CYAN}━━━ Skill Evolution Status ━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`,
|
|
979
|
-
);
|
|
922
|
+
console.log(`\n${BOLD}${CYAN}━━━ Skill Evolution Status ━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`);
|
|
980
923
|
console.log(` Digest cycles : ${BOLD}${cycles.length}${RESET}`);
|
|
981
924
|
console.log(` Total idioms : ${BOLD}${totalIdioms}${RESET}`);
|
|
982
925
|
console.log(
|
|
983
926
|
` Tokens saved : ${GREEN}${totalSaved.toLocaleString()} tokens${RESET} (≈ $${((totalSaved / 1_000_000) * 3).toFixed(4)} at $3/M)`,
|
|
984
927
|
);
|
|
985
|
-
console.log(` SKILL.md exists : ${idiomsExist ?
|
|
928
|
+
console.log(` SKILL.md exists : ${idiomsExist ? '✔' : '✗'}`);
|
|
986
929
|
|
|
987
930
|
if (cycles.length) {
|
|
988
931
|
console.log(`\n ${BOLD}Last 5 digest cycles:${RESET}`);
|
|
989
932
|
for (const cycle of cycles.slice(-5).reverse()) {
|
|
990
|
-
const ts = (cycle.timestamp ||
|
|
933
|
+
const ts = (cycle.timestamp || '?').slice(0, 16);
|
|
991
934
|
const deltaT = cycle.delta_tokens || 0;
|
|
992
935
|
const saved = cycle.tokens_saved || 0;
|
|
993
936
|
const addedCount = cycle.idioms_added || 0;
|
|
994
|
-
const pct = Math.floor(
|
|
995
|
-
(saved / Math.max(cycle.raw_tokens || 1, 1)) * 100,
|
|
996
|
-
);
|
|
937
|
+
const pct = Math.floor((saved / Math.max(cycle.raw_tokens || 1, 1)) * 100);
|
|
997
938
|
console.log(
|
|
998
939
|
` ${DIM}${ts}${RESET} delta=${deltaT}tok saved=${saved}tok (${pct}%) idioms+=${addedCount}`,
|
|
999
940
|
);
|
|
1000
941
|
}
|
|
1001
942
|
}
|
|
1002
|
-
console.log(
|
|
1003
|
-
`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n`,
|
|
1004
|
-
);
|
|
943
|
+
console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n`);
|
|
1005
944
|
}
|
|
1006
945
|
|
|
1007
946
|
// ── Main ──────────────────────────────────────────────────────────────────────
|
|
@@ -1014,7 +953,7 @@ const COMMANDS = {
|
|
|
1014
953
|
|
|
1015
954
|
async function main() {
|
|
1016
955
|
const argv = process.argv.slice(2);
|
|
1017
|
-
if (!argv.length || [
|
|
956
|
+
if (!argv.length || ['-h', '--help', 'help'].includes(argv[0])) {
|
|
1018
957
|
console.log(`
|
|
1019
958
|
${BOLD}skill_evolution.js${RESET} — Tribunal Skill Evolution Forge
|
|
1020
959
|
|
|
@@ -1051,7 +990,7 @@ module.exports = {
|
|
|
1051
990
|
};
|
|
1052
991
|
|
|
1053
992
|
if (require.main === module) {
|
|
1054
|
-
main().catch(
|
|
993
|
+
main().catch(err => {
|
|
1055
994
|
console.error(err);
|
|
1056
995
|
process.exit(1);
|
|
1057
996
|
});
|