tribunal-kit 6.0.1 → 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/ARCHITECTURE.md +9 -6
- 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 +1532 -1
- package/.agent/history/memory/MEMORY.md +102 -1
- package/.agent/mcp_config.json +1 -6
- package/.agent/routing_index.json +2033 -263
- package/.agent/rules/GEMINI.md +11 -9
- 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 +22 -3
- 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 +6 -2
- package/.agent/skills/ai-app-hardening/SKILL.md +9 -8
- 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 +5 -4
- 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 +7 -3
- package/.agent/skills/edge-ai-mobile/SKILL.md +5 -1
- 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 +2 -1
- 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 +2 -1
- 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 +1 -0
- package/.agent/skills/playwright-ai-e2e/SKILL.md +3 -2
- 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 +10 -12
- 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 +3 -2
- 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 +11 -6
- 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 +2 -1
- 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 +94 -44
- package/SECURITY.md +10 -10
- package/bin/mcp-server.js +385 -252
- package/bin/tribunal-kit.js +29 -30
- package/bin/wrapper.js +40 -46
- package/dist/cli.js +6 -0
- package/dist/commands/case.js +2 -0
- package/dist/commands/contract.js +440 -0
- package/dist/commands/status.js +6 -0
- package/dist/index.d.ts +8 -1
- package/package.json +13 -12
- 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
|
@@ -45,37 +45,41 @@
|
|
|
45
45
|
* prompt — full injected prompt text ready for an LLM
|
|
46
46
|
*/
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
'use strict';
|
|
49
49
|
|
|
50
|
-
const fs = require(
|
|
51
|
-
const path = require(
|
|
52
|
-
const { execFileSync } = require(
|
|
50
|
+
const fs = require('fs');
|
|
51
|
+
const path = require('path');
|
|
52
|
+
const { execFileSync } = require('child_process');
|
|
53
53
|
|
|
54
54
|
// ── Colours & Shared Utilities ────────────────────────────────────────────────
|
|
55
|
-
const { GREEN, YELLOW, CYAN, RED, BOLD, DIM, RESET } = require(
|
|
56
|
-
const { findAgentDir } = require(
|
|
55
|
+
const { GREEN, YELLOW, CYAN, RED, BOLD, DIM, RESET } = require('./_colors');
|
|
56
|
+
const { findAgentDir } = require('./_utils');
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
59
|
* Attempt native Rust context resolution for sub-15ms execution
|
|
60
60
|
*/
|
|
61
61
|
function tryNativeContextBroker(repoPath, targetFile) {
|
|
62
|
-
if (process.env.TK_DISABLE_RUST ===
|
|
62
|
+
if (process.env.TK_DISABLE_RUST === '1') return null;
|
|
63
63
|
|
|
64
64
|
const candidates = [
|
|
65
|
-
path.join(__dirname,
|
|
66
|
-
path.join(__dirname,
|
|
67
|
-
path.join(__dirname,
|
|
68
|
-
path.join(__dirname,
|
|
69
|
-
|
|
65
|
+
path.join(__dirname, '../../target/release/tribunal-core.exe'),
|
|
66
|
+
path.join(__dirname, '../../target/release/tribunal-core'),
|
|
67
|
+
path.join(__dirname, '../../target/debug/tribunal-core.exe'),
|
|
68
|
+
path.join(__dirname, '../../target/debug/tribunal-core'),
|
|
69
|
+
'tribunal-core',
|
|
70
70
|
];
|
|
71
71
|
|
|
72
72
|
for (const bin of candidates) {
|
|
73
73
|
try {
|
|
74
74
|
if (bin.includes(path.sep) && !fs.existsSync(bin)) continue;
|
|
75
|
-
const args = [
|
|
76
|
-
if (targetFile) args.push(
|
|
77
|
-
const out = execFileSync(bin, args, {
|
|
78
|
-
|
|
75
|
+
const args = ['context-broker', '--repo-path', repoPath];
|
|
76
|
+
if (targetFile) args.push('--target-file', targetFile);
|
|
77
|
+
const out = execFileSync(bin, args, {
|
|
78
|
+
encoding: 'utf8',
|
|
79
|
+
timeout: 2000,
|
|
80
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
81
|
+
});
|
|
82
|
+
if (out && out.trim().startsWith('{')) {
|
|
79
83
|
return JSON.parse(out);
|
|
80
84
|
}
|
|
81
85
|
} catch (_) {
|
|
@@ -85,305 +89,187 @@ function tryNativeContextBroker(repoPath, targetFile) {
|
|
|
85
89
|
return null;
|
|
86
90
|
}
|
|
87
91
|
|
|
88
|
-
|
|
89
|
-
|
|
90
92
|
// ── Domain → Skill affinity map ───────────────────────────────────────────────
|
|
91
93
|
// Keywords in the user's task that strongly indicate specific skills.
|
|
92
94
|
// Higher weight = stronger signal.
|
|
93
95
|
const DOMAIN_AFFINITIES = [
|
|
94
96
|
// Backend / API
|
|
95
97
|
{
|
|
96
|
-
keywords: [
|
|
97
|
-
|
|
98
|
-
"rest",
|
|
99
|
-
"route",
|
|
100
|
-
"endpoint",
|
|
101
|
-
"handler",
|
|
102
|
-
"express",
|
|
103
|
-
"fastapi",
|
|
104
|
-
"hono",
|
|
105
|
-
],
|
|
106
|
-
skills: [
|
|
107
|
-
"api-patterns",
|
|
108
|
-
"nodejs-best-practices",
|
|
109
|
-
"backend-specialist",
|
|
110
|
-
"error-resilience",
|
|
111
|
-
],
|
|
98
|
+
keywords: ['api', 'rest', 'route', 'endpoint', 'handler', 'express', 'fastapi', 'hono'],
|
|
99
|
+
skills: ['api-patterns', 'nodejs-best-practices', 'backend-specialist', 'error-resilience'],
|
|
112
100
|
weight: 3,
|
|
113
101
|
},
|
|
114
102
|
// Database
|
|
115
103
|
{
|
|
116
104
|
keywords: [
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
105
|
+
'sql',
|
|
106
|
+
'query',
|
|
107
|
+
'database',
|
|
108
|
+
'prisma',
|
|
109
|
+
'drizzle',
|
|
110
|
+
'orm',
|
|
111
|
+
'postgres',
|
|
112
|
+
'mysql',
|
|
113
|
+
'schema',
|
|
126
114
|
],
|
|
127
|
-
skills: [
|
|
115
|
+
skills: ['database-design', 'sql-pro', 'supabase-postgres-best-practices'],
|
|
128
116
|
weight: 3,
|
|
129
117
|
},
|
|
130
118
|
// Authentication
|
|
131
119
|
{
|
|
132
|
-
keywords: [
|
|
133
|
-
|
|
134
|
-
"jwt",
|
|
135
|
-
"login",
|
|
136
|
-
"oauth",
|
|
137
|
-
"session",
|
|
138
|
-
"password",
|
|
139
|
-
"token",
|
|
140
|
-
"rbac",
|
|
141
|
-
],
|
|
142
|
-
skills: [
|
|
143
|
-
"authentication-best-practices",
|
|
144
|
-
"vulnerability-scanner",
|
|
145
|
-
"api-security-auditor",
|
|
146
|
-
],
|
|
120
|
+
keywords: ['auth', 'jwt', 'login', 'oauth', 'session', 'password', 'token', 'rbac'],
|
|
121
|
+
skills: ['authentication-best-practices', 'vulnerability-scanner', 'api-security-auditor'],
|
|
147
122
|
weight: 3,
|
|
148
123
|
},
|
|
149
124
|
// React / Next.js
|
|
150
125
|
{
|
|
151
126
|
keywords: [
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
127
|
+
'react',
|
|
128
|
+
'next',
|
|
129
|
+
'nextjs',
|
|
130
|
+
'component',
|
|
131
|
+
'hook',
|
|
132
|
+
'jsx',
|
|
133
|
+
'tsx',
|
|
134
|
+
'server component',
|
|
135
|
+
'server action',
|
|
161
136
|
],
|
|
162
|
-
skills: [
|
|
137
|
+
skills: ['react-specialist', 'nextjs-react-expert', 'frontend-design'],
|
|
163
138
|
weight: 3,
|
|
164
139
|
},
|
|
165
140
|
// Frontend / UI
|
|
166
141
|
{
|
|
167
142
|
keywords: [
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
],
|
|
178
|
-
skills: [
|
|
179
|
-
"frontend-design",
|
|
180
|
-
"ui-ux-pro-max",
|
|
181
|
-
"tailwind-patterns",
|
|
182
|
-
"web-design-guidelines",
|
|
143
|
+
'ui',
|
|
144
|
+
'design',
|
|
145
|
+
'landing',
|
|
146
|
+
'page',
|
|
147
|
+
'layout',
|
|
148
|
+
'responsive',
|
|
149
|
+
'tailwind',
|
|
150
|
+
'css',
|
|
151
|
+
'style',
|
|
183
152
|
],
|
|
153
|
+
skills: ['frontend-design', 'ui-ux-pro-max', 'tailwind-patterns', 'web-design-guidelines'],
|
|
184
154
|
weight: 2,
|
|
185
155
|
},
|
|
186
156
|
// Animation / Motion
|
|
187
157
|
{
|
|
188
|
-
keywords: [
|
|
189
|
-
|
|
190
|
-
"gsap",
|
|
191
|
-
"framer",
|
|
192
|
-
"motion",
|
|
193
|
-
"scroll",
|
|
194
|
-
"transition",
|
|
195
|
-
"parallax",
|
|
196
|
-
],
|
|
197
|
-
skills: [
|
|
198
|
-
"motion-engineering",
|
|
199
|
-
"framer-motion-expert",
|
|
200
|
-
"gsap-core",
|
|
201
|
-
"gsap-scrolltrigger",
|
|
202
|
-
],
|
|
158
|
+
keywords: ['animation', 'gsap', 'framer', 'motion', 'scroll', 'transition', 'parallax'],
|
|
159
|
+
skills: ['motion-engineering', 'framer-motion-expert', 'gsap-core', 'gsap-scrolltrigger'],
|
|
203
160
|
weight: 3,
|
|
204
161
|
},
|
|
205
162
|
// AI / LLM
|
|
206
163
|
{
|
|
207
164
|
keywords: [
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
],
|
|
219
|
-
skills: [
|
|
220
|
-
"llm-engineering",
|
|
221
|
-
"ai-prompt-injection-defense",
|
|
222
|
-
"agentic-patterns",
|
|
165
|
+
'llm',
|
|
166
|
+
'openai',
|
|
167
|
+
'anthropic',
|
|
168
|
+
'gemini',
|
|
169
|
+
'embedding',
|
|
170
|
+
'ai',
|
|
171
|
+
'rag',
|
|
172
|
+
'vector',
|
|
173
|
+
'chat',
|
|
174
|
+
'prompt',
|
|
223
175
|
],
|
|
176
|
+
skills: ['llm-engineering', 'ai-prompt-injection-defense', 'agentic-patterns'],
|
|
224
177
|
weight: 3,
|
|
225
178
|
},
|
|
226
179
|
// Security
|
|
227
180
|
{
|
|
228
181
|
keywords: [
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
],
|
|
238
|
-
skills: [
|
|
239
|
-
"vulnerability-scanner",
|
|
240
|
-
"api-security-auditor",
|
|
241
|
-
"authentication-best-practices",
|
|
182
|
+
'security',
|
|
183
|
+
'xss',
|
|
184
|
+
'injection',
|
|
185
|
+
'owasp',
|
|
186
|
+
'vulnerability',
|
|
187
|
+
'csrf',
|
|
188
|
+
'sanitize',
|
|
189
|
+
'audit',
|
|
242
190
|
],
|
|
191
|
+
skills: ['vulnerability-scanner', 'api-security-auditor', 'authentication-best-practices'],
|
|
243
192
|
weight: 3,
|
|
244
193
|
},
|
|
245
194
|
// Testing
|
|
246
195
|
{
|
|
247
|
-
keywords: [
|
|
248
|
-
|
|
249
|
-
"spec",
|
|
250
|
-
"jest",
|
|
251
|
-
"vitest",
|
|
252
|
-
"playwright",
|
|
253
|
-
"unit test",
|
|
254
|
-
"e2e",
|
|
255
|
-
"mock",
|
|
256
|
-
],
|
|
257
|
-
skills: ["testing-patterns", "playwright-best-practices", "tdd-workflow"],
|
|
196
|
+
keywords: ['test', 'spec', 'jest', 'vitest', 'playwright', 'unit test', 'e2e', 'mock'],
|
|
197
|
+
skills: ['testing-patterns', 'playwright-best-practices', 'tdd-workflow'],
|
|
258
198
|
weight: 3,
|
|
259
199
|
},
|
|
260
200
|
// Performance
|
|
261
201
|
{
|
|
262
|
-
keywords: [
|
|
263
|
-
|
|
264
|
-
"optimize",
|
|
265
|
-
"bundle",
|
|
266
|
-
"cache",
|
|
267
|
-
"speed",
|
|
268
|
-
"slow",
|
|
269
|
-
"lighthouse",
|
|
270
|
-
"cwv",
|
|
271
|
-
],
|
|
272
|
-
skills: ["performance-profiling", "motion-engineering", "edge-computing"],
|
|
202
|
+
keywords: ['performance', 'optimize', 'bundle', 'cache', 'speed', 'slow', 'lighthouse', 'cwv'],
|
|
203
|
+
skills: ['performance-profiling', 'motion-engineering', 'edge-computing'],
|
|
273
204
|
weight: 2,
|
|
274
205
|
},
|
|
275
206
|
// Mobile
|
|
276
207
|
{
|
|
277
|
-
keywords: [
|
|
278
|
-
|
|
279
|
-
"react native",
|
|
280
|
-
"expo",
|
|
281
|
-
"ios",
|
|
282
|
-
"android",
|
|
283
|
-
"gesture",
|
|
284
|
-
"haptic",
|
|
285
|
-
],
|
|
286
|
-
skills: ["building-native-ui", "mobile-design", "agentic-patterns"],
|
|
208
|
+
keywords: ['mobile', 'react native', 'expo', 'ios', 'android', 'gesture', 'haptic'],
|
|
209
|
+
skills: ['building-native-ui', 'mobile-design', 'agentic-patterns'],
|
|
287
210
|
weight: 3,
|
|
288
211
|
},
|
|
289
212
|
// DevOps / CI
|
|
290
213
|
{
|
|
291
|
-
keywords: [
|
|
292
|
-
|
|
293
|
-
"ci",
|
|
294
|
-
"cd",
|
|
295
|
-
"deploy",
|
|
296
|
-
"pipeline",
|
|
297
|
-
"k8s",
|
|
298
|
-
"kubernetes",
|
|
299
|
-
"github actions",
|
|
300
|
-
],
|
|
301
|
-
skills: ["devops-engineer", "deployment-procedures", "observability"],
|
|
214
|
+
keywords: ['docker', 'ci', 'cd', 'deploy', 'pipeline', 'k8s', 'kubernetes', 'github actions'],
|
|
215
|
+
skills: ['devops-engineer', 'deployment-procedures', 'observability'],
|
|
302
216
|
weight: 2,
|
|
303
217
|
},
|
|
304
218
|
// Real-time
|
|
305
219
|
{
|
|
306
|
-
keywords: [
|
|
307
|
-
|
|
308
|
-
"websocket",
|
|
309
|
-
"sse",
|
|
310
|
-
"socket",
|
|
311
|
-
"live",
|
|
312
|
-
"multiplayer",
|
|
313
|
-
"collaborative",
|
|
314
|
-
],
|
|
315
|
-
skills: ["realtime-patterns", "error-resilience"],
|
|
220
|
+
keywords: ['realtime', 'websocket', 'sse', 'socket', 'live', 'multiplayer', 'collaborative'],
|
|
221
|
+
skills: ['realtime-patterns', 'error-resilience'],
|
|
316
222
|
weight: 3,
|
|
317
223
|
},
|
|
318
224
|
// TypeScript
|
|
319
225
|
{
|
|
320
|
-
keywords: [
|
|
321
|
-
|
|
322
|
-
"type",
|
|
323
|
-
"generic",
|
|
324
|
-
"interface",
|
|
325
|
-
"satisfies",
|
|
326
|
-
"zod",
|
|
327
|
-
"pydantic",
|
|
328
|
-
],
|
|
329
|
-
skills: ["typescript-advanced", "data-validation-schemas"],
|
|
226
|
+
keywords: ['typescript', 'type', 'generic', 'interface', 'satisfies', 'zod', 'pydantic'],
|
|
227
|
+
skills: ['typescript-advanced', 'data-validation-schemas'],
|
|
330
228
|
weight: 2,
|
|
331
229
|
},
|
|
332
230
|
// Python
|
|
333
231
|
{
|
|
334
|
-
keywords: [
|
|
335
|
-
skills: [
|
|
232
|
+
keywords: ['python', 'fastapi', 'django', 'flask', 'pydantic', 'asyncio'],
|
|
233
|
+
skills: ['python-pro', 'python-patterns'],
|
|
336
234
|
weight: 3,
|
|
337
235
|
},
|
|
338
236
|
// Architecture
|
|
339
237
|
{
|
|
340
238
|
keywords: [
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
239
|
+
'architecture',
|
|
240
|
+
'refactor',
|
|
241
|
+
'clean',
|
|
242
|
+
'solid',
|
|
243
|
+
'design pattern',
|
|
244
|
+
'monorepo',
|
|
245
|
+
'microservice',
|
|
348
246
|
],
|
|
349
|
-
skills: [
|
|
247
|
+
skills: ['architecture', 'clean-code', 'monorepo-management'],
|
|
350
248
|
weight: 2,
|
|
351
249
|
},
|
|
352
250
|
// C# / .NET
|
|
353
251
|
{
|
|
354
|
-
keywords: [
|
|
355
|
-
|
|
356
|
-
"c#",
|
|
357
|
-
"dotnet",
|
|
358
|
-
".net",
|
|
359
|
-
"blazor",
|
|
360
|
-
"aspnet",
|
|
361
|
-
"entity framework",
|
|
362
|
-
],
|
|
363
|
-
skills: ["csharp-developer"],
|
|
252
|
+
keywords: ['csharp', 'c#', 'dotnet', '.net', 'blazor', 'aspnet', 'entity framework'],
|
|
253
|
+
skills: ['csharp-developer'],
|
|
364
254
|
weight: 3,
|
|
365
255
|
},
|
|
366
256
|
];
|
|
367
257
|
|
|
368
258
|
// ── File extension → skill boost map ─────────────────────────────────────────
|
|
369
259
|
const EXT_AFFINITIES = {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
260
|
+
'.tsx': ['react-specialist', 'nextjs-react-expert', 'typescript-advanced'],
|
|
261
|
+
'.jsx': ['react-specialist', 'frontend-design'],
|
|
262
|
+
'.ts': ['typescript-advanced', 'nodejs-best-practices'],
|
|
263
|
+
'.vue': ['vue-expert'],
|
|
264
|
+
'.py': ['python-pro', 'python-patterns'],
|
|
265
|
+
'.cs': ['csharp-developer'],
|
|
266
|
+
'.sql': ['sql-pro', 'database-design'],
|
|
267
|
+
'.css': ['tailwind-patterns', 'frontend-design'],
|
|
378
268
|
};
|
|
379
269
|
|
|
380
270
|
// ── Core baseline skills — always available to all model sizes ────────────────
|
|
381
271
|
// These are injected for every request at a condensed level.
|
|
382
|
-
const BASELINE_SKILLS = [
|
|
383
|
-
"clean-code",
|
|
384
|
-
"systematic-debugging",
|
|
385
|
-
"error-resilience",
|
|
386
|
-
];
|
|
272
|
+
const BASELINE_SKILLS = ['clean-code', 'systematic-debugging', 'error-resilience'];
|
|
387
273
|
|
|
388
274
|
// ── Skill catalogue (loaded from disk) ───────────────────────────────────────
|
|
389
275
|
|
|
@@ -397,14 +283,14 @@ function parseFrontmatter(content) {
|
|
|
397
283
|
if (!match) return null;
|
|
398
284
|
const yaml = match[1];
|
|
399
285
|
const obj = {};
|
|
400
|
-
for (const line of yaml.split(
|
|
401
|
-
const sep = line.indexOf(
|
|
286
|
+
for (const line of yaml.split('\n')) {
|
|
287
|
+
const sep = line.indexOf(':');
|
|
402
288
|
if (sep === -1) continue;
|
|
403
289
|
const key = line.slice(0, sep).trim();
|
|
404
290
|
const val = line
|
|
405
291
|
.slice(sep + 1)
|
|
406
292
|
.trim()
|
|
407
|
-
.replace(/^["']|["']$/g,
|
|
293
|
+
.replace(/^["']|["']$/g, '');
|
|
408
294
|
obj[key] = val;
|
|
409
295
|
}
|
|
410
296
|
return obj;
|
|
@@ -422,18 +308,25 @@ function extractKeyRules(content) {
|
|
|
422
308
|
);
|
|
423
309
|
if (sectionMatch) return sectionMatch[1].trim().slice(0, 1200);
|
|
424
310
|
// Fallback: strip frontmatter and take first 800 chars
|
|
425
|
-
const bodyStart = content.indexOf(
|
|
311
|
+
const bodyStart = content.indexOf('---', 3);
|
|
426
312
|
const body = bodyStart !== -1 ? content.slice(bodyStart + 3).trim() : content;
|
|
427
313
|
return body.slice(0, 800).trim();
|
|
428
314
|
}
|
|
429
315
|
|
|
316
|
+
let _loadedSkillsCache = null;
|
|
317
|
+
let _loadedSkillsAgentDir = null;
|
|
318
|
+
|
|
430
319
|
/**
|
|
431
320
|
* Load all skills from .agent/skills/ directory.
|
|
432
|
-
* Returns an array of { name, file, frontmatter, content, keyRules } objects.
|
|
321
|
+
* Returns an array of { name, file, frontmatter, content, keyRules, tokens } objects.
|
|
433
322
|
* @param {string} agentDir
|
|
434
323
|
*/
|
|
435
324
|
function loadSkills(agentDir) {
|
|
436
|
-
|
|
325
|
+
if (_loadedSkillsCache && _loadedSkillsAgentDir === agentDir) {
|
|
326
|
+
return _loadedSkillsCache;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const skillsDir = path.join(agentDir, 'skills');
|
|
437
330
|
if (!fs.existsSync(skillsDir)) return [];
|
|
438
331
|
|
|
439
332
|
const skills = [];
|
|
@@ -441,33 +334,44 @@ function loadSkills(agentDir) {
|
|
|
441
334
|
|
|
442
335
|
for (const entry of entries) {
|
|
443
336
|
if (!entry.isDirectory()) continue;
|
|
444
|
-
const skillFile = path.join(skillsDir, entry.name,
|
|
337
|
+
const skillFile = path.join(skillsDir, entry.name, 'SKILL.md');
|
|
445
338
|
if (!fs.existsSync(skillFile)) continue;
|
|
446
339
|
|
|
447
340
|
try {
|
|
448
|
-
let content = fs.readFileSync(skillFile,
|
|
449
|
-
|
|
341
|
+
let content = fs.readFileSync(skillFile, 'utf8');
|
|
342
|
+
|
|
450
343
|
// Strip duplicated global boilerplate sections
|
|
451
|
-
content = content.replace(
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
344
|
+
content = content.replace(
|
|
345
|
+
/AI coding assistants often fall into specific bad habits[\s\S]*$/g,
|
|
346
|
+
'',
|
|
347
|
+
);
|
|
348
|
+
content = content.replace(/## 🤖 LLM-Specific Traps[\s\S]*$/g, '');
|
|
349
|
+
content = content.replace(/## 🏛️ Tribunal Integration[\s\S]*$/g, '');
|
|
350
|
+
content = content.replace(/## Pre-Flight Checklist[\s\S]*$/g, '');
|
|
455
351
|
content = content.trim();
|
|
456
352
|
|
|
457
353
|
const frontmatter = parseFrontmatter(content) || {};
|
|
458
354
|
const keyRules = extractKeyRules(content);
|
|
355
|
+
const description = frontmatter.description || '';
|
|
356
|
+
const skillText = (entry.name + ' ' + description).toLowerCase();
|
|
357
|
+
const tokens = new Set(tokenize(skillText));
|
|
358
|
+
|
|
459
359
|
skills.push({
|
|
460
360
|
name: entry.name,
|
|
461
361
|
file: skillFile,
|
|
462
362
|
frontmatter,
|
|
463
363
|
content,
|
|
464
364
|
keyRules,
|
|
465
|
-
description
|
|
365
|
+
description,
|
|
366
|
+
tokens,
|
|
466
367
|
});
|
|
467
368
|
} catch {
|
|
468
369
|
// Skip unreadable skills silently
|
|
469
370
|
}
|
|
470
371
|
}
|
|
372
|
+
|
|
373
|
+
_loadedSkillsCache = skills;
|
|
374
|
+
_loadedSkillsAgentDir = agentDir;
|
|
471
375
|
return skills;
|
|
472
376
|
}
|
|
473
377
|
|
|
@@ -479,9 +383,13 @@ function loadSkills(agentDir) {
|
|
|
479
383
|
* @returns {string[]}
|
|
480
384
|
*/
|
|
481
385
|
function tokenize(text) {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
386
|
+
const str =
|
|
387
|
+
typeof text === 'string'
|
|
388
|
+
? text
|
|
389
|
+
: text && typeof text === 'object'
|
|
390
|
+
? text.task || text.spec || JSON.stringify(text)
|
|
391
|
+
: String(text || '');
|
|
392
|
+
return (str.match(/\b[a-zA-Z_][a-zA-Z0-9_]{2,}\b/g) || []).map(t => t.toLowerCase());
|
|
485
393
|
}
|
|
486
394
|
|
|
487
395
|
/**
|
|
@@ -493,7 +401,7 @@ function tokenize(text) {
|
|
|
493
401
|
* - File extension affinity: +2 per match
|
|
494
402
|
* - Baseline skill bonus: +1 (always present)
|
|
495
403
|
*
|
|
496
|
-
* @param {{ name, description, content }} skill
|
|
404
|
+
* @param {{ name, description, content, tokens }} skill
|
|
497
405
|
* @param {string} task - Raw task text from the user
|
|
498
406
|
* @param {string[]} fileExts - File extensions being touched
|
|
499
407
|
* @param {string[]} taskTokens - Pre-tokenized task
|
|
@@ -501,19 +409,24 @@ function tokenize(text) {
|
|
|
501
409
|
*/
|
|
502
410
|
function scoreSkill(skill, task, fileExts, taskTokens) {
|
|
503
411
|
let score = 0;
|
|
504
|
-
const
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
412
|
+
const taskStr =
|
|
413
|
+
typeof task === 'string'
|
|
414
|
+
? task
|
|
415
|
+
: task && typeof task === 'object'
|
|
416
|
+
? task.task || task.spec || ''
|
|
417
|
+
: String(task || '');
|
|
418
|
+
const taskLower = taskStr.toLowerCase();
|
|
419
|
+
|
|
420
|
+
// 1. Token overlap (lightweight TF match using pre-built Set)
|
|
421
|
+
const skillSet =
|
|
422
|
+
skill.tokens || new Set(tokenize((skill.name + ' ' + skill.description).toLowerCase()));
|
|
510
423
|
for (const token of taskTokens) {
|
|
511
424
|
if (skillSet.has(token)) score += 1;
|
|
512
425
|
}
|
|
513
426
|
|
|
514
427
|
// 2. Domain affinity boost
|
|
515
428
|
for (const affinity of DOMAIN_AFFINITIES) {
|
|
516
|
-
const keywordMatch = affinity.keywords.some(
|
|
429
|
+
const keywordMatch = affinity.keywords.some(k => taskLower.includes(k));
|
|
517
430
|
if (!keywordMatch) continue;
|
|
518
431
|
if (affinity.skills.includes(skill.name)) {
|
|
519
432
|
score += affinity.weight;
|
|
@@ -541,16 +454,22 @@ function scoreSkill(skill, task, fileExts, taskTokens) {
|
|
|
541
454
|
* @param {object[]} skills - Loaded skills array from loadSkills()
|
|
542
455
|
* @returns {{ essential: object[], supplementary: object[], available: object[], scores: Map }}
|
|
543
456
|
*/
|
|
544
|
-
function selectSkills(task, files, model, skills) {
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
|
|
457
|
+
function selectSkills(task, files = [], model = 'large', skills = []) {
|
|
458
|
+
const taskStr =
|
|
459
|
+
typeof task === 'string'
|
|
460
|
+
? task
|
|
461
|
+
: task && typeof task === 'object'
|
|
462
|
+
? task.task || task.spec || ''
|
|
463
|
+
: String(task || '');
|
|
464
|
+
const taskTokens = tokenize(taskStr);
|
|
465
|
+
const fileExts = (Array.isArray(files) ? files : [])
|
|
466
|
+
.map(f => path.extname(f).toLowerCase())
|
|
548
467
|
.filter(Boolean);
|
|
549
468
|
|
|
550
469
|
// Score every available skill
|
|
551
|
-
const scored = skills.map(
|
|
470
|
+
const scored = skills.map(skill => ({
|
|
552
471
|
...skill,
|
|
553
|
-
score: scoreSkill(skill,
|
|
472
|
+
score: scoreSkill(skill, taskStr, fileExts, taskTokens),
|
|
554
473
|
}));
|
|
555
474
|
scored.sort((a, b) => b.score - a.score);
|
|
556
475
|
|
|
@@ -559,26 +478,22 @@ function selectSkills(task, files, model, skills) {
|
|
|
559
478
|
const tier0Cut = Math.max(maxScore * 0.65, 2); // Essential: top 65%+ of max score
|
|
560
479
|
const tier1Cut = Math.max(maxScore * 0.3, 1); // Supplementary: 30–65%
|
|
561
480
|
|
|
562
|
-
const essential = scored.filter(
|
|
563
|
-
const supplementary = scored
|
|
564
|
-
|
|
565
|
-
.slice(0, 8);
|
|
566
|
-
const available = scored
|
|
567
|
-
.filter((s) => s.score < tier1Cut && s.score > 0)
|
|
568
|
-
.slice(0, 10);
|
|
481
|
+
const essential = scored.filter(s => s.score >= tier0Cut).slice(0, 10);
|
|
482
|
+
const supplementary = scored.filter(s => s.score < tier0Cut && s.score >= tier1Cut).slice(0, 8);
|
|
483
|
+
const available = scored.filter(s => s.score < tier1Cut && s.score > 0).slice(0, 10);
|
|
569
484
|
|
|
570
485
|
// Ensure baseline skills always appear at minimum in supplementary
|
|
571
486
|
for (const base of BASELINE_SKILLS) {
|
|
572
|
-
const inEssential = essential.find(
|
|
573
|
-
const inSupplementary = supplementary.find(
|
|
487
|
+
const inEssential = essential.find(s => s.name === base);
|
|
488
|
+
const inSupplementary = supplementary.find(s => s.name === base);
|
|
574
489
|
if (!inEssential && !inSupplementary) {
|
|
575
|
-
const baseSkill = skills.find(
|
|
490
|
+
const baseSkill = skills.find(s => s.name === base);
|
|
576
491
|
if (baseSkill) supplementary.push({ ...baseSkill, score: 0.5 });
|
|
577
492
|
}
|
|
578
493
|
}
|
|
579
494
|
|
|
580
495
|
// For small models: collapse supplementary into available
|
|
581
|
-
if (model ===
|
|
496
|
+
if (model === 'small') {
|
|
582
497
|
return {
|
|
583
498
|
essential: essential.slice(0, 6),
|
|
584
499
|
supplementary: [],
|
|
@@ -602,14 +517,10 @@ function formatReport(task, model, selection, elapsed) {
|
|
|
602
517
|
const { essential, supplementary, available } = selection;
|
|
603
518
|
const total = essential.length + supplementary.length + available.length;
|
|
604
519
|
|
|
520
|
+
console.log(`\n${BOLD}${CYAN}━━━ Context Broker — Skill Selection ━━━━━━━━━━━━━━━${RESET}`);
|
|
521
|
+
console.log(` Task : ${BOLD}${task.slice(0, 80)}${task.length > 80 ? '...' : ''}${RESET}`);
|
|
605
522
|
console.log(
|
|
606
|
-
|
|
607
|
-
);
|
|
608
|
-
console.log(
|
|
609
|
-
` Task : ${BOLD}${task.slice(0, 80)}${task.length > 80 ? "..." : ""}${RESET}`,
|
|
610
|
-
);
|
|
611
|
-
console.log(
|
|
612
|
-
` Model : ${model === "large" ? GREEN : YELLOW}${model}${RESET} ${DIM}(Focus without Compromise)${RESET}`,
|
|
523
|
+
` Model : ${model === 'large' ? GREEN : YELLOW}${model}${RESET} ${DIM}(Focus without Compromise)${RESET}`,
|
|
613
524
|
);
|
|
614
525
|
console.log(
|
|
615
526
|
` Skills : ${GREEN}${essential.length} essential${RESET} + ${YELLOW}${supplementary.length} supplementary${RESET} + ${DIM}${available.length} available${RESET} of ${total} matched`,
|
|
@@ -617,47 +528,36 @@ function formatReport(task, model, selection, elapsed) {
|
|
|
617
528
|
console.log(` Time : ${elapsed}ms\n`);
|
|
618
529
|
|
|
619
530
|
if (essential.length) {
|
|
620
|
-
console.log(
|
|
621
|
-
` ${GREEN}${BOLD}▶ Level 0 — Essential (Full Context, Top Priority):${RESET}`,
|
|
622
|
-
);
|
|
531
|
+
console.log(` ${GREEN}${BOLD}▶ Level 0 — Essential (Full Context, Top Priority):${RESET}`);
|
|
623
532
|
for (const s of essential) {
|
|
624
533
|
const score = selection.scores.get(s.name) || 0;
|
|
625
534
|
console.log(
|
|
626
535
|
` ${GREEN}✦${RESET} ${BOLD}${s.name}${RESET} ${DIM}score=${score.toFixed(1)}${RESET}`,
|
|
627
536
|
);
|
|
628
|
-
if (s.description)
|
|
629
|
-
console.log(` ${DIM}${s.description.slice(0, 90)}${RESET}`);
|
|
537
|
+
if (s.description) console.log(` ${DIM}${s.description.slice(0, 90)}${RESET}`);
|
|
630
538
|
}
|
|
631
539
|
}
|
|
632
540
|
|
|
633
541
|
if (supplementary.length) {
|
|
634
|
-
console.log(
|
|
635
|
-
`\n ${YELLOW}${BOLD}▶ Level 1 — Supplementary (Key Rules Only):${RESET}`,
|
|
636
|
-
);
|
|
542
|
+
console.log(`\n ${YELLOW}${BOLD}▶ Level 1 — Supplementary (Key Rules Only):${RESET}`);
|
|
637
543
|
for (const s of supplementary) {
|
|
638
544
|
const score = selection.scores.get(s.name) || 0;
|
|
639
|
-
console.log(
|
|
640
|
-
` ${YELLOW}◆${RESET} ${s.name} ${DIM}score=${score.toFixed(1)}${RESET}`,
|
|
641
|
-
);
|
|
545
|
+
console.log(` ${YELLOW}◆${RESET} ${s.name} ${DIM}score=${score.toFixed(1)}${RESET}`);
|
|
642
546
|
}
|
|
643
547
|
}
|
|
644
548
|
|
|
645
549
|
if (available.length) {
|
|
646
|
-
console.log(
|
|
647
|
-
|
|
648
|
-
);
|
|
649
|
-
console.log(` ${DIM}${available.map((s) => s.name).join(", ")}${RESET}`);
|
|
550
|
+
console.log(`\n ${DIM}▶ Level 2 — Available (Name Reference Only):${RESET}`);
|
|
551
|
+
console.log(` ${DIM}${available.map(s => s.name).join(', ')}${RESET}`);
|
|
650
552
|
}
|
|
651
553
|
|
|
652
|
-
if (model ===
|
|
554
|
+
if (model === 'small') {
|
|
653
555
|
console.log(
|
|
654
556
|
`\n ${YELLOW}⚡ Small model mode: supplementary collapsed. Essential only injected.${RESET}`,
|
|
655
557
|
);
|
|
656
558
|
}
|
|
657
559
|
|
|
658
|
-
console.log(
|
|
659
|
-
`\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n`,
|
|
660
|
-
);
|
|
560
|
+
console.log(`\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n`);
|
|
661
561
|
}
|
|
662
562
|
|
|
663
563
|
function formatJson(task, model, selection) {
|
|
@@ -666,16 +566,16 @@ function formatJson(task, model, selection) {
|
|
|
666
566
|
task,
|
|
667
567
|
model,
|
|
668
568
|
timestamp: new Date().toISOString(),
|
|
669
|
-
essential: selection.essential.map(
|
|
569
|
+
essential: selection.essential.map(s => ({
|
|
670
570
|
name: s.name,
|
|
671
571
|
score: selection.scores.get(s.name),
|
|
672
572
|
description: s.description,
|
|
673
573
|
})),
|
|
674
|
-
supplementary: selection.supplementary.map(
|
|
574
|
+
supplementary: selection.supplementary.map(s => ({
|
|
675
575
|
name: s.name,
|
|
676
576
|
score: selection.scores.get(s.name),
|
|
677
577
|
})),
|
|
678
|
-
available: selection.available.map(
|
|
578
|
+
available: selection.available.map(s => s.name),
|
|
679
579
|
},
|
|
680
580
|
null,
|
|
681
581
|
2,
|
|
@@ -684,10 +584,8 @@ function formatJson(task, model, selection) {
|
|
|
684
584
|
|
|
685
585
|
function formatNames(selection, model) {
|
|
686
586
|
const all =
|
|
687
|
-
model ===
|
|
688
|
-
|
|
689
|
-
: selection.essential;
|
|
690
|
-
return all.map((s) => s.name).join("\n");
|
|
587
|
+
model === 'large' ? [...selection.essential, ...selection.supplementary] : selection.essential;
|
|
588
|
+
return all.map(s => s.name).join('\n');
|
|
691
589
|
}
|
|
692
590
|
|
|
693
591
|
/**
|
|
@@ -708,60 +606,57 @@ function formatPrompt(task, model, selection) {
|
|
|
708
606
|
`# Task: ${task}`,
|
|
709
607
|
`# Model tier: ${model}`,
|
|
710
608
|
`# Generated: ${new Date().toISOString()}`,
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
609
|
+
'',
|
|
610
|
+
'## Instructions for the AI',
|
|
611
|
+
'The following skills are ordered by relevance to the current task.',
|
|
612
|
+
'Level 0 skills contain full rule sets. Level 1 skills contain key rules only.',
|
|
613
|
+
'Treat ALL injected rules as mandatory constraints, not suggestions.',
|
|
614
|
+
'',
|
|
615
|
+
'---',
|
|
616
|
+
'',
|
|
719
617
|
];
|
|
720
618
|
|
|
721
619
|
if (selection.essential.length) {
|
|
722
|
-
lines.push(
|
|
723
|
-
lines.push(
|
|
620
|
+
lines.push('## Level 0 — Essential Skills (Full Context)');
|
|
621
|
+
lines.push('');
|
|
724
622
|
for (const s of selection.essential) {
|
|
725
623
|
lines.push(`### Skill: ${s.name}`);
|
|
726
|
-
lines.push(
|
|
727
|
-
if (model ===
|
|
624
|
+
lines.push('');
|
|
625
|
+
if (model === 'large') {
|
|
728
626
|
lines.push(s.content || s.keyRules);
|
|
729
627
|
} else {
|
|
730
628
|
lines.push(s.keyRules);
|
|
731
629
|
}
|
|
732
|
-
lines.push(
|
|
733
|
-
lines.push(
|
|
734
|
-
lines.push(
|
|
630
|
+
lines.push('');
|
|
631
|
+
lines.push('---');
|
|
632
|
+
lines.push('');
|
|
735
633
|
}
|
|
736
634
|
}
|
|
737
635
|
|
|
738
|
-
if (model ===
|
|
739
|
-
lines.push(
|
|
740
|
-
lines.push(
|
|
636
|
+
if (model === 'large' && selection.supplementary.length) {
|
|
637
|
+
lines.push('## Level 1 — Supplementary Skills (Key Rules)');
|
|
638
|
+
lines.push('');
|
|
741
639
|
for (const s of selection.supplementary) {
|
|
742
640
|
lines.push(`### Skill: ${s.name} (condensed)`);
|
|
743
|
-
lines.push(
|
|
641
|
+
lines.push('');
|
|
744
642
|
lines.push(s.keyRules);
|
|
745
|
-
lines.push(
|
|
746
|
-
lines.push(
|
|
747
|
-
lines.push(
|
|
643
|
+
lines.push('');
|
|
644
|
+
lines.push('---');
|
|
645
|
+
lines.push('');
|
|
748
646
|
}
|
|
749
647
|
}
|
|
750
648
|
|
|
751
649
|
if (selection.available.length) {
|
|
752
|
-
lines.push(
|
|
753
|
-
lines.push(
|
|
650
|
+
lines.push('## Level 2 — Available Skills (Reference Names Only)');
|
|
651
|
+
lines.push('');
|
|
652
|
+
lines.push('The following skills are relevant but not injected to maintain context density.');
|
|
754
653
|
lines.push(
|
|
755
|
-
|
|
654
|
+
'Request their full content if needed: ' + selection.available.map(s => s.name).join(', '),
|
|
756
655
|
);
|
|
757
|
-
lines.push(
|
|
758
|
-
"Request their full content if needed: " +
|
|
759
|
-
selection.available.map((s) => s.name).join(", "),
|
|
760
|
-
);
|
|
761
|
-
lines.push("");
|
|
656
|
+
lines.push('');
|
|
762
657
|
}
|
|
763
658
|
|
|
764
|
-
return lines.join(
|
|
659
|
+
return lines.join('\n');
|
|
765
660
|
}
|
|
766
661
|
|
|
767
662
|
// ── Built-in demo ─────────────────────────────────────────────────────────────
|
|
@@ -771,58 +666,49 @@ function runDemo(agentDir) {
|
|
|
771
666
|
|
|
772
667
|
const scenarios = [
|
|
773
668
|
{
|
|
774
|
-
task:
|
|
775
|
-
file:
|
|
776
|
-
model:
|
|
669
|
+
task: 'Build a JWT authentication API with Express.js and Zod validation',
|
|
670
|
+
file: 'auth.ts',
|
|
671
|
+
model: 'large',
|
|
777
672
|
},
|
|
778
673
|
{
|
|
779
|
-
task:
|
|
780
|
-
file:
|
|
781
|
-
model:
|
|
674
|
+
task: 'Design a premium landing page with GSAP scroll animations',
|
|
675
|
+
file: 'Hero.tsx',
|
|
676
|
+
model: 'large',
|
|
782
677
|
},
|
|
783
678
|
{
|
|
784
|
-
task:
|
|
785
|
-
file:
|
|
786
|
-
model:
|
|
679
|
+
task: 'Write a Prisma query for paginated user orders',
|
|
680
|
+
file: 'orders.ts',
|
|
681
|
+
model: 'small',
|
|
787
682
|
},
|
|
788
683
|
{
|
|
789
|
-
task:
|
|
790
|
-
file:
|
|
791
|
-
model:
|
|
684
|
+
task: 'Add RAG pipeline to an OpenAI-powered chat interface',
|
|
685
|
+
file: 'chat.ts',
|
|
686
|
+
model: 'large',
|
|
792
687
|
},
|
|
793
688
|
];
|
|
794
689
|
|
|
795
|
-
console.log(
|
|
796
|
-
`\n${BOLD}${CYAN}━━━ Context Broker — Demo Mode ━━━━━━━━━━━━━━━━━━━━━${RESET}`,
|
|
797
|
-
);
|
|
690
|
+
console.log(`\n${BOLD}${CYAN}━━━ Context Broker — Demo Mode ━━━━━━━━━━━━━━━━━━━━━${RESET}`);
|
|
798
691
|
console.log(` Loaded ${skills.length} skills from .agent/skills/\n`);
|
|
799
692
|
|
|
800
693
|
for (const scenario of scenarios) {
|
|
801
694
|
const t0 = Date.now();
|
|
802
695
|
const model = scenario.model;
|
|
803
|
-
const selection = selectSkills(
|
|
804
|
-
scenario.task,
|
|
805
|
-
[scenario.file],
|
|
806
|
-
model,
|
|
807
|
-
skills,
|
|
808
|
-
);
|
|
696
|
+
const selection = selectSkills(scenario.task, [scenario.file], model, skills);
|
|
809
697
|
const elapsed = Date.now() - t0;
|
|
810
698
|
|
|
811
699
|
console.log(
|
|
812
700
|
`\n ${BOLD}Task: "${scenario.task.slice(0, 70)}"${RESET} ${DIM}[${model} model]${RESET}`,
|
|
813
701
|
);
|
|
814
702
|
console.log(
|
|
815
|
-
` Essential : ${GREEN}${selection.essential.map(
|
|
703
|
+
` Essential : ${GREEN}${selection.essential.map(s => s.name).join(', ')}${RESET}`,
|
|
816
704
|
);
|
|
817
705
|
console.log(
|
|
818
|
-
` Supplementary : ${YELLOW}${selection.supplementary.map(
|
|
706
|
+
` Supplementary : ${YELLOW}${selection.supplementary.map(s => s.name).join(', ') || '(small mode)'}${RESET}`,
|
|
819
707
|
);
|
|
820
708
|
console.log(` Time : ${DIM}${elapsed}ms${RESET}`);
|
|
821
709
|
}
|
|
822
710
|
|
|
823
|
-
console.log(
|
|
824
|
-
`\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n`,
|
|
825
|
-
);
|
|
711
|
+
console.log(`\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n`);
|
|
826
712
|
}
|
|
827
713
|
|
|
828
714
|
// ── Public API ────────────────────────────────────────────────────────────────
|
|
@@ -836,11 +722,22 @@ function runDemo(agentDir) {
|
|
|
836
722
|
* @param {string} agentDir - Path to .agent/ directory
|
|
837
723
|
* @returns {{ essential, supplementary, available, promptText }}
|
|
838
724
|
*/
|
|
839
|
-
function broker(task, files = [], model =
|
|
725
|
+
function broker(task, files = [], model = 'large', agentDir = null) {
|
|
726
|
+
let taskStr = task;
|
|
727
|
+
let filesArr = files;
|
|
728
|
+
let modelStr = model;
|
|
729
|
+
|
|
730
|
+
if (typeof task === 'object' && task !== null) {
|
|
731
|
+
taskStr = task.task || task.spec || '';
|
|
732
|
+
if (task.files) filesArr = task.files;
|
|
733
|
+
if (task.file) filesArr = [task.file];
|
|
734
|
+
if (task.model) modelStr = task.model;
|
|
735
|
+
}
|
|
736
|
+
|
|
840
737
|
const resolvedAgentDir = agentDir || findAgentDir();
|
|
841
738
|
const skills = loadSkills(resolvedAgentDir);
|
|
842
|
-
const selection = selectSkills(
|
|
843
|
-
const promptText = formatPrompt(
|
|
739
|
+
const selection = selectSkills(taskStr, filesArr, modelStr, skills);
|
|
740
|
+
const promptText = formatPrompt(taskStr, modelStr, selection);
|
|
844
741
|
return { ...selection, promptText };
|
|
845
742
|
}
|
|
846
743
|
|
|
@@ -857,16 +754,16 @@ function broker(task, files = [], model = "large", agentDir = null) {
|
|
|
857
754
|
* @param {string} agentDir - Path to .agent/ directory
|
|
858
755
|
* @returns {object} Phase-specific context
|
|
859
756
|
*/
|
|
860
|
-
function brokerForPipeline(task, files = [], phase =
|
|
757
|
+
function brokerForPipeline(task, files = [], phase = 'build', agentDir = null) {
|
|
861
758
|
const resolvedAgentDir = agentDir || findAgentDir();
|
|
862
759
|
const skills = loadSkills(resolvedAgentDir);
|
|
863
760
|
// Always use "small" model tier for aggressive pruning in pipeline mode
|
|
864
|
-
const selection = selectSkills(task, files,
|
|
761
|
+
const selection = selectSkills(task, files, 'small', skills);
|
|
865
762
|
|
|
866
|
-
if (phase ===
|
|
763
|
+
if (phase === 'plan') {
|
|
867
764
|
// Plan phase: skill names and descriptions only — no content, no keyRules
|
|
868
765
|
return {
|
|
869
|
-
phase:
|
|
766
|
+
phase: 'plan',
|
|
870
767
|
skills: selection.essential.slice(0, 6).map(s => ({
|
|
871
768
|
name: s.name,
|
|
872
769
|
description: s.description,
|
|
@@ -876,23 +773,23 @@ function brokerForPipeline(task, files = [], phase = "build", agentDir = null) {
|
|
|
876
773
|
};
|
|
877
774
|
}
|
|
878
775
|
|
|
879
|
-
if (phase ===
|
|
776
|
+
if (phase === 'build') {
|
|
880
777
|
// Build phase: top 3 essential keyRules — maximum density, minimum tokens
|
|
881
778
|
return {
|
|
882
|
-
phase:
|
|
779
|
+
phase: 'build',
|
|
883
780
|
skills: selection.essential.slice(0, 3).map(s => ({
|
|
884
781
|
name: s.name,
|
|
885
|
-
keyRules: s.keyRules ||
|
|
782
|
+
keyRules: s.keyRules || '',
|
|
886
783
|
score: selection.scores.get(s.name) || 0,
|
|
887
784
|
})),
|
|
888
785
|
};
|
|
889
786
|
}
|
|
890
787
|
|
|
891
|
-
if (phase ===
|
|
788
|
+
if (phase === 'validate') {
|
|
892
789
|
// Validate phase: return detected stack for targeted pattern matching
|
|
893
790
|
const fileExts = files.map(f => path.extname(f).toLowerCase()).filter(Boolean);
|
|
894
791
|
return {
|
|
895
|
-
phase:
|
|
792
|
+
phase: 'validate',
|
|
896
793
|
detectedExtensions: fileExts,
|
|
897
794
|
essentialSkillNames: selection.essential.slice(0, 3).map(s => s.name),
|
|
898
795
|
};
|
|
@@ -910,18 +807,20 @@ function brokerForPipeline(task, files = [], phase = "build", agentDir = null) {
|
|
|
910
807
|
*/
|
|
911
808
|
function formatPipelinePlan(task, pipelineResult) {
|
|
912
809
|
const lines = [
|
|
913
|
-
|
|
810
|
+
'# Pipeline Planner Context',
|
|
914
811
|
`# Task: ${task}`,
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
812
|
+
'',
|
|
813
|
+
'## Matched Skills (by relevance)',
|
|
814
|
+
'',
|
|
918
815
|
];
|
|
919
816
|
for (const s of pipelineResult.skills) {
|
|
920
|
-
lines.push(
|
|
817
|
+
lines.push(
|
|
818
|
+
`- **${s.name}** (score: ${s.score.toFixed(1)}): ${(s.description || '').slice(0, 120)}`,
|
|
819
|
+
);
|
|
921
820
|
}
|
|
922
|
-
lines.push(
|
|
821
|
+
lines.push('');
|
|
923
822
|
lines.push(`Total matched: ${pipelineResult.total_matched}`);
|
|
924
|
-
return lines.join(
|
|
823
|
+
return lines.join('\n');
|
|
925
824
|
}
|
|
926
825
|
|
|
927
826
|
/**
|
|
@@ -931,24 +830,38 @@ function formatPipelinePlan(task, pipelineResult) {
|
|
|
931
830
|
* @returns {string}
|
|
932
831
|
*/
|
|
933
832
|
function formatPipelineBuild(task, pipelineResult) {
|
|
934
|
-
const lines = [
|
|
935
|
-
"# Builder Context — Essential Rules Only",
|
|
936
|
-
`# Task: ${task}`,
|
|
937
|
-
"",
|
|
938
|
-
];
|
|
833
|
+
const lines = ['# Builder Context — Essential Rules Only', `# Task: ${task}`, ''];
|
|
939
834
|
for (const s of pipelineResult.skills) {
|
|
940
835
|
lines.push(`## ${s.name}`);
|
|
941
|
-
lines.push(
|
|
942
|
-
lines.push(s.keyRules ||
|
|
943
|
-
lines.push(
|
|
944
|
-
lines.push(
|
|
945
|
-
lines.push(
|
|
836
|
+
lines.push('');
|
|
837
|
+
lines.push(s.keyRules || '(no key rules extracted)');
|
|
838
|
+
lines.push('');
|
|
839
|
+
lines.push('---');
|
|
840
|
+
lines.push('');
|
|
946
841
|
}
|
|
947
|
-
return lines.join(
|
|
842
|
+
return lines.join('\n');
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
function resolveContext(opts = {}) {
|
|
846
|
+
let task = '';
|
|
847
|
+
let files = [];
|
|
848
|
+
let model = 'large';
|
|
849
|
+
let agentDir = null;
|
|
850
|
+
|
|
851
|
+
if (typeof opts === 'string') {
|
|
852
|
+
task = opts;
|
|
853
|
+
} else if (opts && typeof opts === 'object') {
|
|
854
|
+
task = opts.task || opts.spec || '';
|
|
855
|
+
files = opts.files || (opts.file ? [opts.file] : []);
|
|
856
|
+
model = opts.model || 'large';
|
|
857
|
+
agentDir = opts.agentDir || null;
|
|
858
|
+
}
|
|
859
|
+
return broker(task, files, model, agentDir);
|
|
948
860
|
}
|
|
949
861
|
|
|
950
862
|
module.exports = {
|
|
951
863
|
broker,
|
|
864
|
+
resolveContext,
|
|
952
865
|
brokerForPipeline,
|
|
953
866
|
selectSkills,
|
|
954
867
|
loadSkills,
|
|
@@ -964,7 +877,7 @@ module.exports = {
|
|
|
964
877
|
if (require.main === module) {
|
|
965
878
|
const argv = process.argv.slice(2);
|
|
966
879
|
|
|
967
|
-
if (!argv.length || argv.includes(
|
|
880
|
+
if (!argv.length || argv.includes('--help') || argv.includes('-h')) {
|
|
968
881
|
console.log(`
|
|
969
882
|
${BOLD}context_broker.js${RESET} — Tribunal Focus-without-Compromise Context Engine
|
|
970
883
|
|
|
@@ -993,21 +906,19 @@ ${BOLD}Examples:${RESET}
|
|
|
993
906
|
|
|
994
907
|
const agentDir = findAgentDir();
|
|
995
908
|
|
|
996
|
-
if (argv[0] ===
|
|
909
|
+
if (argv[0] === 'demo') {
|
|
997
910
|
runDemo(agentDir);
|
|
998
911
|
process.exit(0);
|
|
999
912
|
}
|
|
1000
913
|
|
|
1001
914
|
// Parse args
|
|
1002
|
-
const taskIdx = argv.indexOf(
|
|
1003
|
-
const modelIdx = argv.indexOf(
|
|
1004
|
-
const outputIdx = argv.indexOf(
|
|
915
|
+
const taskIdx = argv.indexOf('--task');
|
|
916
|
+
const modelIdx = argv.indexOf('--model');
|
|
917
|
+
const outputIdx = argv.indexOf('--output');
|
|
1005
918
|
|
|
1006
|
-
const task = taskIdx !== -1 && argv[taskIdx + 1] ? argv[taskIdx + 1] :
|
|
1007
|
-
const model =
|
|
1008
|
-
|
|
1009
|
-
const output =
|
|
1010
|
-
outputIdx !== -1 && argv[outputIdx + 1] ? argv[outputIdx + 1] : "report";
|
|
919
|
+
const task = taskIdx !== -1 && argv[taskIdx + 1] ? argv[taskIdx + 1] : '';
|
|
920
|
+
const model = modelIdx !== -1 && argv[modelIdx + 1] ? argv[modelIdx + 1] : 'large';
|
|
921
|
+
const output = outputIdx !== -1 && argv[outputIdx + 1] ? argv[outputIdx + 1] : 'report';
|
|
1011
922
|
|
|
1012
923
|
if (!task) {
|
|
1013
924
|
console.error(`${RED}✖ --task is required${RESET}`);
|
|
@@ -1017,16 +928,14 @@ ${BOLD}Examples:${RESET}
|
|
|
1017
928
|
// Collect --file arguments (may appear multiple times)
|
|
1018
929
|
const files = [];
|
|
1019
930
|
for (let i = 0; i < argv.length; i++) {
|
|
1020
|
-
if (argv[i] ===
|
|
931
|
+
if (argv[i] === '--file' && argv[i + 1]) files.push(argv[i + 1]);
|
|
1021
932
|
}
|
|
1022
933
|
|
|
1023
|
-
const validModels = [
|
|
934
|
+
const validModels = ['large', 'small'];
|
|
1024
935
|
let effectiveModel = model;
|
|
1025
936
|
if (!validModels.includes(model)) {
|
|
1026
|
-
console.error(
|
|
1027
|
-
|
|
1028
|
-
);
|
|
1029
|
-
effectiveModel = "large";
|
|
937
|
+
console.error(`${YELLOW}⚠ Unknown model tier "${model}" — defaulting to "large"${RESET}`);
|
|
938
|
+
effectiveModel = 'large';
|
|
1030
939
|
}
|
|
1031
940
|
|
|
1032
941
|
const t0 = Date.now();
|
|
@@ -1035,22 +944,22 @@ ${BOLD}Examples:${RESET}
|
|
|
1035
944
|
const elapsed = Date.now() - t0;
|
|
1036
945
|
|
|
1037
946
|
switch (output) {
|
|
1038
|
-
case
|
|
947
|
+
case 'json':
|
|
1039
948
|
console.log(formatJson(task, effectiveModel, selection));
|
|
1040
949
|
break;
|
|
1041
|
-
case
|
|
950
|
+
case 'names':
|
|
1042
951
|
console.log(formatNames(selection, effectiveModel));
|
|
1043
952
|
break;
|
|
1044
|
-
case
|
|
953
|
+
case 'prompt':
|
|
1045
954
|
console.log(formatPrompt(task, effectiveModel, selection));
|
|
1046
955
|
break;
|
|
1047
|
-
case
|
|
1048
|
-
const pipelinePlan = brokerForPipeline(task, files,
|
|
956
|
+
case 'pipeline-plan': {
|
|
957
|
+
const pipelinePlan = brokerForPipeline(task, files, 'plan', agentDir);
|
|
1049
958
|
console.log(formatPipelinePlan(task, pipelinePlan));
|
|
1050
959
|
break;
|
|
1051
960
|
}
|
|
1052
|
-
case
|
|
1053
|
-
const pipelineBuild = brokerForPipeline(task, files,
|
|
961
|
+
case 'pipeline-build': {
|
|
962
|
+
const pipelineBuild = brokerForPipeline(task, files, 'build', agentDir);
|
|
1054
963
|
console.log(formatPipelineBuild(task, pipelineBuild));
|
|
1055
964
|
break;
|
|
1056
965
|
}
|
|
@@ -1059,7 +968,3 @@ ${BOLD}Examples:${RESET}
|
|
|
1059
968
|
break;
|
|
1060
969
|
}
|
|
1061
970
|
}
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|