tribunal-kit 5.8.4 → 5.8.5

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.
Files changed (46) hide show
  1. package/.agent/ARCHITECTURE.md +3 -3
  2. package/.agent/history/integrity_manifest.json +75 -7
  3. package/.agent/history/memory/.memory.idx +1065 -1
  4. package/.agent/history/memory/MEMORY.md +71 -1
  5. package/.agent/rules/GEMINI.md +1 -1
  6. package/.agent/scripts/_utils.js +28 -7
  7. package/.agent/scripts/context_broker.js +0 -19
  8. package/.agent/scripts/guardrail_engine.js +1 -1
  9. package/.agent/scripts/integrity_manifest.js +10 -4
  10. package/.agent/scripts/marathon_harness.js +10 -1
  11. package/.agent/scripts/skill_evolution.js +36 -21
  12. package/.agent/scripts/swarm_dispatcher.js +65 -6
  13. package/.agent/skills/api-patterns/scripts/__pycache__/api_validator.cpython-311.pyc +0 -0
  14. package/.agent/skills/better-colors/SKILL.md +12 -4
  15. package/.agent/skills/database-design/scripts/__pycache__/schema_validator.cpython-311.pyc +0 -0
  16. package/.agent/skills/fixing-accessibility/SKILL.md +6 -4
  17. package/.agent/skills/frontend-design/SKILL.md +80 -81
  18. package/.agent/skills/frontend-design/scripts/__pycache__/accessibility_checker.cpython-311.pyc +0 -0
  19. package/.agent/skills/frontend-design/scripts/__pycache__/ux_audit.cpython-311.pyc +0 -0
  20. package/.agent/skills/geo-fundamentals/scripts/__pycache__/geo_checker.cpython-311.pyc +0 -0
  21. package/.agent/skills/i18n-localization/scripts/__pycache__/i18n_checker.cpython-311.pyc +0 -0
  22. package/.agent/skills/impeccable/SKILL.md +2 -0
  23. package/.agent/skills/lint-and-validate/scripts/__pycache__/lint_runner.cpython-311.pyc +0 -0
  24. package/.agent/skills/lint-and-validate/scripts/__pycache__/type_coverage.cpython-311.pyc +0 -0
  25. package/.agent/skills/mobile-design/scripts/__pycache__/mobile_audit.cpython-311.pyc +0 -0
  26. package/.agent/skills/motion-engineering/SKILL.md +66 -164
  27. package/.agent/skills/nextjs-react-expert/scripts/__pycache__/convert_rules.cpython-311.pyc +0 -0
  28. package/.agent/skills/nextjs-react-expert/scripts/__pycache__/react_performance_checker.cpython-311.pyc +0 -0
  29. package/.agent/skills/performance-profiling/scripts/__pycache__/lighthouse_audit.cpython-311.pyc +0 -0
  30. package/.agent/skills/seo-fundamentals/scripts/__pycache__/seo_checker.cpython-311.pyc +0 -0
  31. package/.agent/skills/testing-patterns/scripts/__pycache__/test_runner.cpython-311.pyc +0 -0
  32. package/.agent/skills/vulnerability-scanner/scripts/__pycache__/security_scan.cpython-311.pyc +0 -0
  33. package/.agent/skills/webapp-testing/scripts/__pycache__/playwright_runner.cpython-311.pyc +0 -0
  34. package/.agent/workflows/tribunal-full.md +5 -5
  35. package/CONTRIBUTING.md +1 -1
  36. package/README.md +4 -4
  37. package/bin/mcp-server.js +45 -45
  38. package/bin/wrapper.js +50 -25
  39. package/dist/cli.js +30 -0
  40. package/dist/commands/init.js +25 -1
  41. package/dist/commands/native.js +228 -0
  42. package/dist/commands/validate.js +67 -0
  43. package/dist/mcp/server.js +4 -138
  44. package/package.json +11 -10
  45. package/scripts/benchmark.js +42 -0
  46. package/scripts/sync-version.js +129 -76
@@ -1,6 +1,6 @@
1
1
  # 🧠 Tribunal Memory Index
2
2
  > Auto-generated by `tribunal-kit memory export`. Do not edit manually.
3
- > Entries: 151 | Semantic: 121 | Procedural: 30 | Episodic: 0 | Working: 0
3
+ > Entries: 221 | Semantic: 177 | Procedural: 44 | Episodic: 0 | Working: 0
4
4
 
5
5
  ## SEMANTIC (Permanent Facts)
6
6
  | ID | Content | Tags | Source | Created |
@@ -126,6 +126,62 @@
126
126
  | 147 | [ ] Have I checked the environment for relevant existing implementations? | project-idiom, auto-learned | manual | 1784618632Z |
127
127
  | 148 | ❌ **Forbidden:** Declaring a task complete because the output "looks correct." | project-idiom, auto-learned | manual | 1784618632Z |
128
128
  | 149 | ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended. | project-idiom, auto-learned | manual | 1784618632Z |
129
+ | 152 | ❌ Overriding project idioms without explicit justification -> ✅ Idioms represent team decisions; flag deviations with reasoning | project-idiom, auto-learned | manual | 1784705972Z |
130
+ | 153 | ❌ Applying idioms from one project to a different project -> ✅ Idioms are project-specific; verify they apply to the current codebase | project-idiom, auto-learned | manual | 1784705972Z |
131
+ | 154 | ❌ **Forbidden:** Declaring a task complete because the output "looks correct." | project-idiom, auto-learned | manual | 1784705972Z |
132
+ | 155 | ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended. | project-idiom, auto-learned | manual | 1784705972Z |
133
+ | 156 | [ ] Have I reviewed the user's specific constraints and requests? | project-idiom, auto-learned | manual | 1784705972Z |
134
+ | 157 | [ ] Have I checked the environment for relevant existing implementations? | project-idiom, auto-learned | manual | 1784705972Z |
135
+ | 158 | ❌ **Forbidden:** Declaring a task complete because the output "looks correct." | project-idiom, auto-learned | manual | 1784705972Z |
136
+ | 159 | ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended. | project-idiom, auto-learned | manual | 1784705972Z |
137
+ | 162 | ❌ Overriding project idioms without explicit justification -> ✅ Idioms represent team decisions; flag deviations with reasoning | project-idiom, auto-learned | manual | 1784706426Z |
138
+ | 163 | ❌ Applying idioms from one project to a different project -> ✅ Idioms are project-specific; verify they apply to the current codebase | project-idiom, auto-learned | manual | 1784706426Z |
139
+ | 164 | ❌ **Forbidden:** Declaring a task complete because the output "looks correct." | project-idiom, auto-learned | manual | 1784706426Z |
140
+ | 165 | ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended. | project-idiom, auto-learned | manual | 1784706426Z |
141
+ | 166 | [ ] Have I reviewed the user's specific constraints and requests? | project-idiom, auto-learned | manual | 1784706426Z |
142
+ | 167 | [ ] Have I checked the environment for relevant existing implementations? | project-idiom, auto-learned | manual | 1784706426Z |
143
+ | 168 | ❌ **Forbidden:** Declaring a task complete because the output "looks correct." | project-idiom, auto-learned | manual | 1784706426Z |
144
+ | 169 | ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended. | project-idiom, auto-learned | manual | 1784706426Z |
145
+ | 172 | ❌ Overriding project idioms without explicit justification -> ✅ Idioms represent team decisions; flag deviations with reasoning | project-idiom, auto-learned | manual | 1784706433Z |
146
+ | 173 | ❌ Applying idioms from one project to a different project -> ✅ Idioms are project-specific; verify they apply to the current codebase | project-idiom, auto-learned | manual | 1784706433Z |
147
+ | 174 | ❌ **Forbidden:** Declaring a task complete because the output "looks correct." | project-idiom, auto-learned | manual | 1784706433Z |
148
+ | 175 | ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended. | project-idiom, auto-learned | manual | 1784706433Z |
149
+ | 176 | [ ] Have I reviewed the user's specific constraints and requests? | project-idiom, auto-learned | manual | 1784706433Z |
150
+ | 177 | [ ] Have I checked the environment for relevant existing implementations? | project-idiom, auto-learned | manual | 1784706433Z |
151
+ | 178 | ❌ **Forbidden:** Declaring a task complete because the output "looks correct." | project-idiom, auto-learned | manual | 1784706433Z |
152
+ | 179 | ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended. | project-idiom, auto-learned | manual | 1784706433Z |
153
+ | 182 | ❌ Overriding project idioms without explicit justification -> ✅ Idioms represent team decisions; flag deviations with reasoning | project-idiom, auto-learned | manual | 1784706809Z |
154
+ | 183 | ❌ Applying idioms from one project to a different project -> ✅ Idioms are project-specific; verify they apply to the current codebase | project-idiom, auto-learned | manual | 1784706809Z |
155
+ | 184 | ❌ **Forbidden:** Declaring a task complete because the output "looks correct." | project-idiom, auto-learned | manual | 1784706809Z |
156
+ | 185 | ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended. | project-idiom, auto-learned | manual | 1784706809Z |
157
+ | 186 | [ ] Have I reviewed the user's specific constraints and requests? | project-idiom, auto-learned | manual | 1784706809Z |
158
+ | 187 | [ ] Have I checked the environment for relevant existing implementations? | project-idiom, auto-learned | manual | 1784706809Z |
159
+ | 188 | ❌ **Forbidden:** Declaring a task complete because the output "looks correct." | project-idiom, auto-learned | manual | 1784706809Z |
160
+ | 189 | ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended. | project-idiom, auto-learned | manual | 1784706809Z |
161
+ | 192 | ❌ Overriding project idioms without explicit justification -> ✅ Idioms represent team decisions; flag deviations with reasoning | project-idiom, auto-learned | manual | 1784706814Z |
162
+ | 193 | ❌ Applying idioms from one project to a different project -> ✅ Idioms are project-specific; verify they apply to the current codebase | project-idiom, auto-learned | manual | 1784706814Z |
163
+ | 194 | ❌ **Forbidden:** Declaring a task complete because the output "looks correct." | project-idiom, auto-learned | manual | 1784706814Z |
164
+ | 195 | ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended. | project-idiom, auto-learned | manual | 1784706814Z |
165
+ | 196 | [ ] Have I reviewed the user's specific constraints and requests? | project-idiom, auto-learned | manual | 1784706814Z |
166
+ | 197 | [ ] Have I checked the environment for relevant existing implementations? | project-idiom, auto-learned | manual | 1784706814Z |
167
+ | 198 | ❌ **Forbidden:** Declaring a task complete because the output "looks correct." | project-idiom, auto-learned | manual | 1784706814Z |
168
+ | 199 | ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended. | project-idiom, auto-learned | manual | 1784706814Z |
169
+ | 202 | ❌ Overriding project idioms without explicit justification -> ✅ Idioms represent team decisions; flag deviations with reasoning | project-idiom, auto-learned | manual | 1785138690Z |
170
+ | 203 | ❌ Applying idioms from one project to a different project -> ✅ Idioms are project-specific; verify they apply to the current codebase | project-idiom, auto-learned | manual | 1785138690Z |
171
+ | 204 | ❌ **Forbidden:** Declaring a task complete because the output "looks correct." | project-idiom, auto-learned | manual | 1785138690Z |
172
+ | 205 | ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended. | project-idiom, auto-learned | manual | 1785138690Z |
173
+ | 206 | [ ] Have I reviewed the user's specific constraints and requests? | project-idiom, auto-learned | manual | 1785138690Z |
174
+ | 207 | [ ] Have I checked the environment for relevant existing implementations? | project-idiom, auto-learned | manual | 1785138690Z |
175
+ | 208 | ❌ **Forbidden:** Declaring a task complete because the output "looks correct." | project-idiom, auto-learned | manual | 1785138690Z |
176
+ | 209 | ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended. | project-idiom, auto-learned | manual | 1785138690Z |
177
+ | 212 | ❌ Overriding project idioms without explicit justification -> ✅ Idioms represent team decisions; flag deviations with reasoning | project-idiom, auto-learned | manual | 1785138695Z |
178
+ | 213 | ❌ Applying idioms from one project to a different project -> ✅ Idioms are project-specific; verify they apply to the current codebase | project-idiom, auto-learned | manual | 1785138695Z |
179
+ | 214 | ❌ **Forbidden:** Declaring a task complete because the output "looks correct." | project-idiom, auto-learned | manual | 1785138695Z |
180
+ | 215 | ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended. | project-idiom, auto-learned | manual | 1785138695Z |
181
+ | 216 | [ ] Have I reviewed the user's specific constraints and requests? | project-idiom, auto-learned | manual | 1785138695Z |
182
+ | 217 | [ ] Have I checked the environment for relevant existing implementations? | project-idiom, auto-learned | manual | 1785138695Z |
183
+ | 218 | ❌ **Forbidden:** Declaring a task complete because the output "looks correct." | project-idiom, auto-learned | manual | 1785138695Z |
184
+ | 219 | ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended. | project-idiom, auto-learned | manual | 1785138696Z |
129
185
 
130
186
  ## PROCEDURAL (How-To Recipes)
131
187
  | ID | Content | Tags | Source | Created |
@@ -160,4 +216,18 @@
160
216
  | 141 | Run `npm run validate-payload && jest --coverage` to test the project | build-script, test, auto-learned | manual | 1784396209Z |
161
217
  | 150 | Run `echo 'No build step required for this project'` to build the project | build-script, build, auto-learned | manual | 1784618632Z |
162
218
  | 151 | Run `npm run validate-payload && jest --coverage` to test the project | build-script, test, auto-learned | manual | 1784618632Z |
219
+ | 160 | Run `echo 'No build step required for this project'` to build the project | build-script, build, auto-learned | manual | 1784705972Z |
220
+ | 161 | Run `npm run validate-payload && jest --coverage` to test the project | build-script, test, auto-learned | manual | 1784705972Z |
221
+ | 170 | Run `echo 'No build step required for this project'` to build the project | build-script, build, auto-learned | manual | 1784706426Z |
222
+ | 171 | Run `npm run validate-payload && jest --coverage` to test the project | build-script, test, auto-learned | manual | 1784706426Z |
223
+ | 180 | Run `echo 'No build step required for this project'` to build the project | build-script, build, auto-learned | manual | 1784706433Z |
224
+ | 181 | Run `npm run validate-payload && jest --coverage` to test the project | build-script, test, auto-learned | manual | 1784706433Z |
225
+ | 190 | Run `echo 'No build step required for this project'` to build the project | build-script, build, auto-learned | manual | 1784706809Z |
226
+ | 191 | Run `npm run validate-payload && jest --coverage` to test the project | build-script, test, auto-learned | manual | 1784706809Z |
227
+ | 200 | Run `echo 'No build step required for this project'` to build the project | build-script, build, auto-learned | manual | 1784706814Z |
228
+ | 201 | Run `npm run validate-payload && jest --coverage` to test the project | build-script, test, auto-learned | manual | 1784706814Z |
229
+ | 210 | Run `npm run build:rust` to build the project | build-script, build, auto-learned | manual | 1785138690Z |
230
+ | 211 | Run `npm run validate-payload && jest --coverage` to test the project | build-script, test, auto-learned | manual | 1785138690Z |
231
+ | 220 | Run `npm run build:rust` to build the project | build-script, build, auto-learned | manual | 1785138696Z |
232
+ | 221 | Run `npm run validate-payload && jest --coverage` to test the project | build-script, test, auto-learned | manual | 1785138696Z |
163
233
 
@@ -222,7 +222,7 @@ The Human Gate is never skipped. No code is written to a file without explicit u
222
222
  | Database/SQL | logic + security + sql + schema + complexity-reviewer |
223
223
  | Mobile/Cross-platform | logic + security + mobile-reviewer + type-safety + complexity-reviewer |
224
224
  | Any domain | + performance (if optimization) |
225
- | Before merge | /tribunal-full (all 20) |
225
+ | Before merge | /tribunal-full (all 19 reviewers) |
226
226
 
227
227
  ---
228
228
 
@@ -226,9 +226,34 @@ function parseArgs(argv, schema = {}) {
226
226
 
227
227
  // ── Command Runner ──────────────────────────────────────────────────────────
228
228
 
229
+ const WINDOWS_CMD_SHIMS = new Set(["npm", "npx", "pnpm", "yarn", "bun", "bunx"]);
230
+
231
+ /**
232
+ * Select the executable that should be passed to spawnSync.
233
+ * Only package-manager shims need a .cmd suffix on Windows; native executables
234
+ * such as node, cargo, and git must retain their original names.
235
+ *
236
+ * @param {string} cmd - Command to run
237
+ * @param {string} [platform] - Platform override for deterministic testing
238
+ * @returns {string}
239
+ */
240
+ function normalizeCommand(cmd, platform = process.platform) {
241
+ const lowerCaseCommand = cmd.toLowerCase();
242
+ const hasPath = cmd.includes("/") || cmd.includes("\\\\");
243
+ if (
244
+ platform === "win32" &&
245
+ !hasPath &&
246
+ !lowerCaseCommand.endsWith(".cmd") &&
247
+ WINDOWS_CMD_SHIMS.has(lowerCaseCommand)
248
+ ) {
249
+ return `${cmd}.cmd`;
250
+ }
251
+ return cmd;
252
+ }
253
+
229
254
  /**
230
255
  * Run a command synchronously and return a structured result.
231
- * Handles Windows .cmd shims automatically.
256
+ * Handles known Windows package-manager shims without rewriting native tools.
232
257
  *
233
258
  * @param {string} cmd - Command to run
234
259
  * @param {string[]} args - Arguments
@@ -237,12 +262,7 @@ function parseArgs(argv, schema = {}) {
237
262
  */
238
263
  function runCommand(cmd, args = [], opts = {}) {
239
264
  const { spawnSync } = require("child_process");
240
- const executable =
241
- process.platform === "win32" &&
242
- !cmd.endsWith(".cmd") &&
243
- !cmd.includes(path.sep)
244
- ? `${cmd}.cmd`
245
- : cmd;
265
+ const executable = normalizeCommand(cmd);
246
266
 
247
267
  const result = spawnSync(executable, args, {
248
268
  encoding: "utf8",
@@ -275,5 +295,6 @@ module.exports = {
275
295
  // CLI
276
296
  parseArgs,
277
297
  // Commands
298
+ normalizeCommand,
278
299
  runCommand,
279
300
  };
@@ -355,25 +355,6 @@ const BASELINE_SKILLS = [
355
355
 
356
356
  // ── Skill catalogue (loaded from disk) ───────────────────────────────────────
357
357
 
358
- /**
359
- * Find the .agent directory by walking up from cwd.
360
- * @returns {string} path to .agent/
361
- */
362
- function findAgentDir() {
363
- let current = path.resolve(process.cwd());
364
- const root = path.parse(current).root;
365
- while (current !== root) {
366
- const candidate = path.join(current, ".agent");
367
- if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory())
368
- return candidate;
369
- current = path.dirname(current);
370
- }
371
- console.error(
372
- `${RED}✖ .agent/ not found. Run: npx tribunal-kit init${RESET}`,
373
- );
374
- process.exit(1);
375
- }
376
-
377
358
  /**
378
359
  * Parse the YAML frontmatter from a SKILL.md file.
379
360
  * Returns { name, description, ... } or null on parse failure.
@@ -104,7 +104,7 @@ function ruleReviewerCount(content, manifest, _ctx) {
104
104
  const actualCount = manifest.agents ? manifest.agents.reviewer_count : null;
105
105
  if (actualCount === null) return violations;
106
106
 
107
- const countRegex = /(\d+)[-\s]+(?:parallel\s+)?(?:reviewers?|agents?)/gi;
107
+ const countRegex = /(\d+)\s*(?:-\s*)?(?:(?:parallel|domain(?:-specific)?|tribunal|code)\s+)*reviewers?\b/gi;
108
108
  let match;
109
109
  while ((match = countRegex.exec(content)) !== null) {
110
110
  const claimed = parseInt(match[1], 10);
@@ -82,9 +82,10 @@ function crawlAgents(agentDir) {
82
82
  const content = safeReadFile(path.join(agentsDir, file));
83
83
  const fm = parseFrontmatter(content);
84
84
  const isReviewer =
85
- /reviewer|auditor|tester/i.test(name) ||
85
+ /reviewer|auditor|tester|throughput-optimizer/i.test(name) ||
86
86
  (fm.role && /reviewer/i.test(fm.role));
87
87
 
88
+
88
89
  if (isReviewer) {
89
90
  reviewers.push(name);
90
91
  } else {
@@ -239,7 +240,10 @@ function extractNumericClaims(filePath, content, agentDir, actualCounts) {
239
240
  const lines = content.split(/\r?\n/);
240
241
 
241
242
  const claimPatterns = [
242
- { regex: /(\d+)[-\s]+(?:parallel\s+)?(?:reviewers?|agents?)/gi, entity: "reviewers" },
243
+ {
244
+ regex: /(\d+)\s*(?:-\s*)?(?:(?:parallel|domain(?:-specific)?|tribunal|code)\s+)*reviewers?\b/gi,
245
+ entity: "reviewers",
246
+ },
243
247
  { regex: /(\d+)\s*(?:specialist\s+)?agents?\b/gi, entity: "agents" },
244
248
  { regex: /(\d+)\s*(?:modular\s+)?skills?\b/gi, entity: "skills" },
245
249
  { regex: /(\d+)\s*(?:slash\s+)?workflows?\b/gi, entity: "workflows" },
@@ -253,8 +257,10 @@ function extractNumericClaims(filePath, content, agentDir, actualCounts) {
253
257
  let match;
254
258
  while ((match = regex.exec(line)) !== null) {
255
259
  const claimed = parseInt(match[1], 10);
256
- // Skip tiny numbers (likely not count claims) and very large numbers
257
- if (claimed < 3 || claimed > 500) continue;
260
+ // This manifest describes the full Tribunal payload, so small local
261
+ // counts (for example, "3 skills" in one skill group) are not global
262
+ // asset claims. Skip them along with implausibly large values.
263
+ if (claimed < 5 || claimed > 500) continue;
258
264
 
259
265
  const actual = actualCounts[entity];
260
266
  if (actual !== undefined) {
@@ -24,6 +24,7 @@
24
24
  const fs = require("fs");
25
25
  const path = require("path");
26
26
  const { execSync } = require("child_process");
27
+ const { findAgentDir } = require("./_utils");
27
28
 
28
29
  const {
29
30
  GREEN,
@@ -42,7 +43,11 @@ const {
42
43
  } = require("./_colors");
43
44
 
44
45
  // ── Paths ────────────────────────────────────────────────────────────────────
45
- const MARATHON_DIR = path.resolve(".agent", "history", "marathon");
46
+ function getMarathonDir(startDir = process.cwd()) {
47
+ return path.join(findAgentDir(startDir), "history", "marathon");
48
+ }
49
+
50
+ const MARATHON_DIR = getMarathonDir();
46
51
  const FEATURE_LIST_FILE = path.join(MARATHON_DIR, "feature_list.json");
47
52
  const PROGRESS_FILE = path.join(MARATHON_DIR, "progress.json");
48
53
  const ARCHIVE_DIR = path.join(MARATHON_DIR, "archive");
@@ -1049,6 +1054,10 @@ function main() {
1049
1054
  }
1050
1055
  }
1051
1056
 
1057
+ module.exports = {
1058
+ getMarathonDir,
1059
+ };
1060
+
1052
1061
  if (require.main === module) {
1053
1062
  main();
1054
1063
  }
@@ -46,11 +46,18 @@ const {
46
46
  const { findAgentDir } = require("./_utils");
47
47
 
48
48
 
49
- const AGENT_DIR = findAgentDir();
50
- const SKILL_DIR = path.join(AGENT_DIR, "skills", "project-idioms");
51
- const SKILL_FILE = path.join(SKILL_DIR, "SKILL.md");
52
- const HISTORY_DIR = path.join(AGENT_DIR, "history", "skill-evolution");
53
- const LOG_FILE = path.join(HISTORY_DIR, "digest-log.json");
49
+ function getPaths(startDir = process.cwd()) {
50
+ const agentDir = findAgentDir(startDir);
51
+ const skillDir = path.join(agentDir, "skills", "project-idioms");
52
+ const historyDir = path.join(agentDir, "history", "skill-evolution");
53
+ return {
54
+ agentDir,
55
+ skillDir,
56
+ skillFile: path.join(skillDir, "SKILL.md"),
57
+ historyDir,
58
+ logFile: path.join(historyDir, "digest-log.json"),
59
+ };
60
+ }
54
61
 
55
62
  // ── Architectural Weight Patterns ────────────────────────────────────────────
56
63
  const HIGH_WEIGHT_PATTERNS = [
@@ -205,8 +212,9 @@ function countTokensEstimate(text) {
205
212
 
206
213
  // ── Idiom management ──────────────────────────────────────────────────────────
207
214
  function loadExistingIdioms() {
208
- if (!fs.existsSync(SKILL_FILE)) return [];
209
- const content = fs.readFileSync(SKILL_FILE, "utf8");
215
+ const { skillFile } = getPaths();
216
+ if (!fs.existsSync(skillFile)) return [];
217
+ const content = fs.readFileSync(skillFile, "utf8");
210
218
  const idioms = [];
211
219
  const pattern =
212
220
  /\|\s*(\d+)\s*\|\s*`([^`]+)`\s*\|\s*([^|]+)\|\s*([^|]+)\|\s*([^|]+)\|/g;
@@ -346,10 +354,11 @@ function parseLlmYamlResponse(response) {
346
354
 
347
355
  // ── Log helpers ────────────────────────────────────────────────────────────────
348
356
  function loadLog() {
349
- fs.mkdirSync(HISTORY_DIR, { recursive: true });
350
- if (fs.existsSync(LOG_FILE)) {
357
+ const { historyDir, logFile } = getPaths();
358
+ fs.mkdirSync(historyDir, { recursive: true });
359
+ if (fs.existsSync(logFile)) {
351
360
  try {
352
- return JSON.parse(fs.readFileSync(LOG_FILE, "utf8"));
361
+ return JSON.parse(fs.readFileSync(logFile, "utf8"));
353
362
  } catch {
354
363
  /* fallthrough */
355
364
  }
@@ -358,8 +367,9 @@ function loadLog() {
358
367
  }
359
368
 
360
369
  function saveLog(log) {
361
- fs.mkdirSync(HISTORY_DIR, { recursive: true });
362
- fs.writeFileSync(LOG_FILE, JSON.stringify(log, null, 2), "utf8");
370
+ const { historyDir, logFile } = getPaths();
371
+ fs.mkdirSync(historyDir, { recursive: true });
372
+ fs.writeFileSync(logFile, JSON.stringify(log, null, 2), "utf8");
363
373
  }
364
374
 
365
375
  // ── Auto-LLM API Integration ─────────────────────────────────────────────────
@@ -835,8 +845,9 @@ async function cmdDigest(args) {
835
845
  if (added > 0) {
836
846
  log.total_idioms = merged.length;
837
847
  const skillMd = renderSkillMd(merged, (log.cycles || []).length + 1);
838
- fs.mkdirSync(SKILL_DIR, { recursive: true });
839
- fs.writeFileSync(SKILL_FILE, skillMd, "utf8");
848
+ const { skillDir, skillFile } = getPaths();
849
+ fs.mkdirSync(skillDir, { recursive: true });
850
+ fs.writeFileSync(skillFile, skillMd, "utf8");
840
851
  console.log(` ${GREEN}✔ ${added} new idiom(s) added to SKILL.md${RESET}`);
841
852
  } else {
842
853
  console.log(` ${DIM} No new unique idioms added to SKILL.md.${RESET}`);
@@ -932,22 +943,24 @@ async function cmdDigest(args) {
932
943
  }
933
944
 
934
945
  function cmdShow() {
935
- if (!fs.existsSync(SKILL_FILE)) {
946
+ const { skillFile } = getPaths();
947
+ if (!fs.existsSync(skillFile)) {
936
948
  console.log(
937
949
  `${YELLOW}No project-idioms skill found. Run 'digest' first.${RESET}`,
938
950
  );
939
951
  return;
940
952
  }
941
- console.log(fs.readFileSync(SKILL_FILE, "utf8"));
953
+ console.log(fs.readFileSync(skillFile, "utf8"));
942
954
  }
943
955
 
944
956
  function cmdReset() {
945
- if (fs.existsSync(SKILL_FILE)) {
946
- fs.unlinkSync(SKILL_FILE);
957
+ const { skillFile, logFile } = getPaths();
958
+ if (fs.existsSync(skillFile)) {
959
+ fs.unlinkSync(skillFile);
947
960
  console.log(`${GREEN}✔ project-idioms/SKILL.md deleted.${RESET}`);
948
961
  }
949
- if (fs.existsSync(LOG_FILE)) {
950
- fs.unlinkSync(LOG_FILE);
962
+ if (fs.existsSync(logFile)) {
963
+ fs.unlinkSync(logFile);
951
964
  console.log(`${GREEN}✔ Digest log cleared.${RESET}`);
952
965
  }
953
966
  console.log(`${DIM}Run 'digest' to start a fresh evolution cycle.${RESET}`);
@@ -958,7 +971,8 @@ function cmdStatus() {
958
971
  const cycles = log.cycles || [];
959
972
  const totalSaved = log.total_tokens_saved || 0;
960
973
  const totalIdioms = log.total_idioms || 0;
961
- const idiomsExist = fs.existsSync(SKILL_FILE);
974
+ const { skillFile } = getPaths();
975
+ const idiomsExist = fs.existsSync(skillFile);
962
976
 
963
977
  console.log(
964
978
  `\n${BOLD}${CYAN}━━━ Skill Evolution Status ━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`,
@@ -1033,6 +1047,7 @@ module.exports = {
1033
1047
  architecturalWeight,
1034
1048
  parseLlmYamlResponse,
1035
1049
  loadExistingIdioms,
1050
+ getPaths,
1036
1051
  };
1037
1052
 
1038
1053
  if (require.main === module) {
@@ -52,7 +52,7 @@ class SwarmDashboard {
52
52
  }
53
53
 
54
54
  start() {
55
- console.clear();
55
+ this.render();
56
56
  this.timer = setInterval(() => this.render(), 80);
57
57
  }
58
58
 
@@ -89,12 +89,63 @@ const MAX_GOAL_LENGTH = 200;
89
89
  const MAX_CONTEXT_LENGTH = 800;
90
90
  const MAX_WORKERS_PER_SWARM = 5;
91
91
 
92
- const { findAgentDir } = require("./_utils");
92
+ function getBinaryPath() {
93
+ if (process.env.TRIBUNAL_FORCE_JS === "1") return null;
94
+ const isWindows = process.platform === "win32";
95
+ const ext = isWindows ? ".exe" : "";
96
+ const candidates = [
97
+ process.env.TRIBUNAL_CORE_PATH,
98
+ path.resolve(__dirname, "..", "..", "tribunal-kit", "target", "release", `tribunal-core${ext}`),
99
+ path.resolve(__dirname, "..", "..", "target", "release", `tribunal-core${ext}`),
100
+ path.resolve(process.cwd(), "target", "release", `tribunal-core${ext}`),
101
+ path.resolve(process.cwd(), "tribunal-kit", "target", "release", `tribunal-core${ext}`),
102
+ ];
103
+ for (const c of candidates) {
104
+ if (c && fs.existsSync(c)) return c;
105
+ }
106
+ return null;
107
+ }
93
108
 
109
+ function nativeValidate(file, schemaType) {
110
+ const bin = getBinaryPath();
111
+ if (!bin || !file || !fs.existsSync(file)) return null;
112
+ try {
113
+ const { spawnSync } = require("child_process");
114
+ const res = spawnSync(bin, ["validate", "--file", file, "--schema", schemaType], {
115
+ encoding: "utf-8",
116
+ });
117
+ if (res.status === 0) {
118
+ return true;
119
+ }
120
+ } catch {
121
+ // fallback to JS engine
122
+ }
123
+ return null;
124
+ }
125
+
126
+ function findAgentDir(startPath) {
127
+ let current = path.resolve(startPath);
128
+ const root = path.parse(current).root;
129
+ while (current !== root) {
130
+ const agentDir = path.join(current, ".agent");
131
+ if (fs.existsSync(agentDir) && fs.statSync(agentDir).isDirectory()) {
132
+ return agentDir;
133
+ }
134
+ current = path.dirname(current);
135
+ }
136
+ return null;
137
+ }
94
138
 
95
139
  // ─── Legacy mode: validate orchestrator micro-worker payloads ──────────────────
96
140
 
97
- function validatePayload(payloadData, workspaceRoot, agentsDir) {
141
+ function validatePayload(payloadData, workspaceRoot, agentsDir, payloadFile = null) {
142
+ if (payloadFile) {
143
+ const nativeResult = nativeValidate(payloadFile, "micro-worker");
144
+ if (nativeResult === true) {
145
+ return true;
146
+ }
147
+ }
148
+
98
149
  if (!payloadData.dispatch_micro_workers) {
99
150
  console.error(
100
151
  "ERROR: Payload missing required 'dispatch_micro_workers' array.",
@@ -301,7 +352,14 @@ function validateWorkerResult(res, index) {
301
352
  return errors;
302
353
  }
303
354
 
304
- function validateSwarmPayload(payloadData, agentsDir) {
355
+ function validateSwarmPayload(payloadData, agentsDir, payloadFile = null) {
356
+ if (payloadFile) {
357
+ const nativeResult = nativeValidate(payloadFile, "swarm");
358
+ if (nativeResult === true) {
359
+ return true;
360
+ }
361
+ }
362
+
305
363
  let items;
306
364
  if (typeof payloadData === "object" && payloadData !== null) {
307
365
  if (Array.isArray(payloadData)) {
@@ -417,7 +475,7 @@ function main() {
417
475
  }
418
476
 
419
477
  if (mode === "swarm") {
420
- if (!validateSwarmPayload(payloadData, agentsDir)) {
478
+ if (!validateSwarmPayload(payloadData, agentsDir, file)) {
421
479
  console.error("ERROR: Swarm payload validation failed.");
422
480
  process.exit(1);
423
481
  }
@@ -494,7 +552,7 @@ function main() {
494
552
  }
495
553
  }
496
554
  } else {
497
- if (!validatePayload(payloadData, workspaceRoot, agentsDir)) {
555
+ if (!validatePayload(payloadData, workspaceRoot, agentsDir, file)) {
498
556
  console.error("ERROR: Payload validation failed.");
499
557
  process.exit(1);
500
558
  }
@@ -536,6 +594,7 @@ function main() {
536
594
  }
537
595
 
538
596
  module.exports = {
597
+ SwarmDashboard,
539
598
  validateWorkerRequest,
540
599
  validateWorkerResult,
541
600
  validateSwarmPayload,
@@ -40,15 +40,16 @@ $$\text{Format: } \text{oklch}(L \quad C \quad H [\quad / \quad A])$$
40
40
  - `250`: Blue / Indigo
41
41
  - `300`: Purple / Violet
42
42
 
43
- ### CSS Custom Properties Setup
43
+ ### CSS Custom Properties & Relative Color Syntax
44
44
 
45
45
  ```css
46
46
  :root {
47
47
  /* Brand Primary: Vibrant Indigo */
48
48
  --color-primary: oklch(0.55 0.22 260);
49
- --color-primary-hover: oklch(0.50 0.24 260);
50
- --color-primary-active: oklch(0.45 0.25 260);
51
- --color-primary-subtle: oklch(0.94 0.04 260);
49
+ /* Modern CSS Relative Color Syntax (Modifying Lightness/Chroma dynamically) */
50
+ --color-primary-hover: oklch(from var(--color-primary) calc(l - 0.08) c h);
51
+ --color-primary-active: oklch(from var(--color-primary) calc(l - 0.14) c h);
52
+ --color-primary-subtle: oklch(from var(--color-primary) 0.95 0.04 h);
52
53
 
53
54
  /* Neutrals: Subtly Tinted (Chroma ~ 0.015) */
54
55
  --bg-surface: oklch(0.99 0.005 260);
@@ -58,6 +59,13 @@ $$\text{Format: } \text{oklch}(L \quad C \quad H [\quad / \quad A])$$
58
59
  --border-subtle: oklch(0.88 0.015 260);
59
60
  }
60
61
 
62
+ /* Native CSS light-dark() declaration mode */
63
+ :root {
64
+ color-scheme: light dark;
65
+ --surface-adaptive: light-dark(oklch(0.99 0.005 260), oklch(0.14 0.015 260));
66
+ --text-adaptive: light-dark(oklch(0.20 0.02 260), oklch(0.96 0.01 260));
67
+ }
68
+
61
69
  @media (prefers-color-scheme: dark) {
62
70
  :root {
63
71
  --bg-surface: oklch(0.14 0.015 260);
@@ -19,15 +19,17 @@ Guidelines for detecting, prioritizing, and fixing accessibility defects across
19
19
 
20
20
  ---
21
21
 
22
- ## 1. Priority Priority Matrix
22
+ ## 1. Priority Priority Matrix (WCAG 2.2 AA)
23
23
 
24
24
  | Priority | Category | Critical Requirements |
25
25
  | --- | --- | --- |
26
26
  | **P1** | **Accessible Names** | Every icon button MUST have `aria-label` or `aria-labelledby`. Decorative icons MUST have `aria-hidden="true"`. |
27
27
  | **P2** | **Keyboard Access** | All interactive controls MUST be reachable and operable via `Tab` / `Shift+Tab`, `Space`, `Enter`. NEVER use `<div>` or `<span>` as clickable elements without `role="button"`, `tabIndex={0}`, and key handlers. |
28
- | **P3** | **Focus & Dialogs** | Modals/Dialogs MUST trap focus within the dialog container while open, return focus to trigger on close, and dismiss on `Escape`. |
29
- | **P4** | **Color Contrast** | Text MUST satisfy WCAG AA 4.5:1 ratio (3.0:1 for large text). Focus rings MUST have at least 3.0:1 contrast against adjacent background. |
30
- | **P5** | **Form Validation** | Inputs MUST have explicit `<label>` or `aria-labelledby`. Errors MUST use `aria-invalid="true"` and `aria-describedby` pointing to error text. |
28
+ | **P3** | **Focus & Dialogs (SC 2.4.11)** | Modals/Dialogs MUST trap focus within the dialog container while open, return focus on close, dismiss on `Escape`, and ensure focused items are **never fully obscured by sticky headers/footers**. |
29
+ | **P4** | **Focus Appearance (SC 2.4.13)** | Focus indicators MUST be clearly visible (`:focus-visible`), achieve at least **3:1 contrast** against adjacent background, and have a min **2px thickness**. |
30
+ | **P5** | **Target Size (SC 2.5.8)** | Interactive controls MUST measure at least **24x24 CSS pixels** (min **44x44px** recommended for mobile touch targets) or have sufficient non-intersecting spacing. |
31
+ | **P6** | **Color & Contrast** | Text MUST satisfy WCAG AA 4.5:1 ratio (3.0:1 for large text). Color alone MUST NOT be the only indicator of state or error. |
32
+ | **P7** | **Form Validation** | Inputs MUST have explicit `<label>` or `aria-labelledby`. Errors MUST use `aria-invalid="true"` and `aria-describedby` pointing to error text. |
31
33
 
32
34
  ---
33
35