tribunal-kit 4.2.0 → 4.3.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.
Files changed (182) hide show
  1. package/.agent/ARCHITECTURE.md +21 -14
  2. package/.agent/agents/swarm-worker-contracts.md +5 -5
  3. package/.agent/agents/ui-ux-auditor.md +292 -0
  4. package/.agent/rules/GEMINI.md +8 -8
  5. package/.agent/scripts/__pycache__/_colors.cpython-311.pyc +0 -0
  6. package/.agent/scripts/__pycache__/_utils.cpython-311.pyc +0 -0
  7. package/.agent/scripts/__pycache__/case_law_manager.cpython-311.pyc +0 -0
  8. package/.agent/scripts/_colors.js +18 -0
  9. package/.agent/scripts/_utils.js +42 -0
  10. package/.agent/scripts/auto_preview.js +197 -0
  11. package/.agent/scripts/bundle_analyzer.js +290 -0
  12. package/.agent/scripts/case_law_manager.js +684 -0
  13. package/.agent/scripts/checklist.js +266 -0
  14. package/.agent/scripts/colors.js +17 -0
  15. package/.agent/scripts/compress_skills.js +141 -0
  16. package/.agent/scripts/consolidate_skills.js +149 -0
  17. package/.agent/scripts/context_broker.js +609 -0
  18. package/.agent/scripts/deep_compress.js +150 -0
  19. package/.agent/scripts/dependency_analyzer.js +272 -0
  20. package/.agent/scripts/inner_loop_validator.js +465 -0
  21. package/.agent/scripts/lint_runner.js +187 -0
  22. package/.agent/scripts/minify_context.js +100 -0
  23. package/.agent/scripts/patch_skills_meta.js +156 -0
  24. package/.agent/scripts/patch_skills_output.js +244 -0
  25. package/.agent/scripts/schema_validator.js +297 -0
  26. package/.agent/scripts/security_scan.js +303 -0
  27. package/.agent/scripts/session_manager.js +276 -0
  28. package/.agent/scripts/skill_evolution.js +644 -0
  29. package/.agent/scripts/skill_integrator.js +313 -0
  30. package/.agent/scripts/strengthen_skills.js +193 -0
  31. package/.agent/scripts/strip_tribunal.js +47 -0
  32. package/.agent/scripts/swarm_dispatcher.js +360 -0
  33. package/.agent/scripts/test_runner.js +193 -0
  34. package/.agent/scripts/utils.js +32 -0
  35. package/.agent/scripts/verify_all.js +256 -0
  36. package/.agent/skills/agent-organizer/SKILL.md +3 -3
  37. package/.agent/skills/agentic-patterns/SKILL.md +3 -3
  38. package/.agent/skills/ai-prompt-injection-defense/SKILL.md +3 -3
  39. package/.agent/skills/api-patterns/SKILL.md +3 -3
  40. package/.agent/skills/api-security-auditor/SKILL.md +3 -3
  41. package/.agent/skills/app-builder/SKILL.md +3 -3
  42. package/.agent/skills/app-builder/templates/SKILL.md +1 -1
  43. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +1 -1
  44. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +1 -1
  45. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +1 -1
  46. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +1 -1
  47. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +1 -1
  48. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +1 -1
  49. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +1 -1
  50. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +1 -1
  51. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +1 -1
  52. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +1 -1
  53. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +1 -1
  54. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +1 -1
  55. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +1 -1
  56. package/.agent/skills/appflow-wireframe/SKILL.md +3 -3
  57. package/.agent/skills/architecture/SKILL.md +3 -3
  58. package/.agent/skills/authentication-best-practices/SKILL.md +3 -3
  59. package/.agent/skills/bash-linux/SKILL.md +3 -3
  60. package/.agent/skills/behavioral-modes/SKILL.md +3 -3
  61. package/.agent/skills/brainstorming/SKILL.md +3 -3
  62. package/.agent/skills/building-native-ui/SKILL.md +3 -3
  63. package/.agent/skills/clean-code/SKILL.md +3 -3
  64. package/.agent/skills/code-review-checklist/SKILL.md +3 -3
  65. package/.agent/skills/config-validator/SKILL.md +3 -3
  66. package/.agent/skills/csharp-developer/SKILL.md +3 -3
  67. package/.agent/skills/data-validation-schemas/SKILL.md +3 -3
  68. package/.agent/skills/database-design/SKILL.md +3 -3
  69. package/.agent/skills/deployment-procedures/SKILL.md +3 -3
  70. package/.agent/skills/devops-engineer/SKILL.md +3 -3
  71. package/.agent/skills/devops-incident-responder/SKILL.md +3 -3
  72. package/.agent/skills/doc.md +1 -1
  73. package/.agent/skills/documentation-templates/SKILL.md +3 -3
  74. package/.agent/skills/edge-computing/SKILL.md +3 -3
  75. package/.agent/skills/error-resilience/SKILL.md +3 -3
  76. package/.agent/skills/extract-design-system/SKILL.md +3 -3
  77. package/.agent/skills/framer-motion-expert/SKILL.md +3 -4
  78. package/.agent/skills/frontend-design/SKILL.md +3 -3
  79. package/.agent/skills/game-design-expert/SKILL.md +3 -3
  80. package/.agent/skills/game-engineering-expert/SKILL.md +3 -3
  81. package/.agent/skills/geo-fundamentals/SKILL.md +3 -3
  82. package/.agent/skills/github-operations/SKILL.md +3 -3
  83. package/.agent/skills/gsap-core/SKILL.md +0 -2
  84. package/.agent/skills/gsap-frameworks/SKILL.md +0 -2
  85. package/.agent/skills/gsap-performance/SKILL.md +0 -2
  86. package/.agent/skills/gsap-plugins/SKILL.md +0 -2
  87. package/.agent/skills/gsap-react/SKILL.md +0 -2
  88. package/.agent/skills/gsap-scrolltrigger/SKILL.md +0 -2
  89. package/.agent/skills/gsap-timeline/SKILL.md +0 -2
  90. package/.agent/skills/gsap-utils/SKILL.md +0 -2
  91. package/.agent/skills/i18n-localization/SKILL.md +3 -3
  92. package/.agent/skills/intelligent-routing/SKILL.md +3 -3
  93. package/.agent/skills/lint-and-validate/SKILL.md +3 -3
  94. package/.agent/skills/llm-engineering/SKILL.md +3 -3
  95. package/.agent/skills/local-first/SKILL.md +3 -3
  96. package/.agent/skills/mcp-builder/SKILL.md +3 -3
  97. package/.agent/skills/mobile-design/SKILL.md +3 -3
  98. package/.agent/skills/monorepo-management/SKILL.md +3 -3
  99. package/.agent/skills/motion-engineering/SKILL.md +4 -4
  100. package/.agent/skills/nextjs-react-expert/SKILL.md +3 -3
  101. package/.agent/skills/nodejs-best-practices/SKILL.md +3 -3
  102. package/.agent/skills/observability/SKILL.md +3 -3
  103. package/.agent/skills/parallel-agents/SKILL.md +3 -3
  104. package/.agent/skills/performance-profiling/SKILL.md +3 -3
  105. package/.agent/skills/plan-writing/SKILL.md +3 -3
  106. package/.agent/skills/platform-engineer/SKILL.md +3 -3
  107. package/.agent/skills/playwright-best-practices/SKILL.md +3 -3
  108. package/.agent/skills/powershell-windows/SKILL.md +3 -3
  109. package/.agent/skills/project-idioms/SKILL.md +3 -3
  110. package/.agent/skills/python-patterns/SKILL.md +3 -3
  111. package/.agent/skills/python-pro/SKILL.md +3 -3
  112. package/.agent/skills/react-specialist/SKILL.md +3 -3
  113. package/.agent/skills/readme-builder/SKILL.md +3 -3
  114. package/.agent/skills/realtime-patterns/SKILL.md +3 -3
  115. package/.agent/skills/red-team-tactics/SKILL.md +3 -3
  116. package/.agent/skills/rust-pro/SKILL.md +3 -3
  117. package/.agent/skills/seo-fundamentals/SKILL.md +3 -3
  118. package/.agent/skills/server-management/SKILL.md +3 -3
  119. package/.agent/skills/shadcn-ui-expert/SKILL.md +3 -3
  120. package/.agent/skills/skill-creator/SKILL.md +3 -3
  121. package/.agent/skills/sql-pro/SKILL.md +3 -3
  122. package/.agent/skills/supabase-postgres-best-practices/SKILL.md +3 -3
  123. package/.agent/skills/swiftui-expert/SKILL.md +3 -3
  124. package/.agent/skills/systematic-debugging/SKILL.md +3 -3
  125. package/.agent/skills/tailwind-patterns/SKILL.md +3 -3
  126. package/.agent/skills/tdd-workflow/SKILL.md +3 -3
  127. package/.agent/skills/test-result-analyzer/SKILL.md +3 -3
  128. package/.agent/skills/testing-patterns/SKILL.md +3 -3
  129. package/.agent/skills/trend-researcher/SKILL.md +3 -3
  130. package/.agent/skills/typescript-advanced/SKILL.md +3 -3
  131. package/.agent/skills/ui-ux-pro-max/SKILL.md +3 -3
  132. package/.agent/skills/ui-ux-researcher/SKILL.md +3 -3
  133. package/.agent/skills/vue-expert/SKILL.md +3 -3
  134. package/.agent/skills/vulnerability-scanner/SKILL.md +3 -3
  135. package/.agent/skills/web-accessibility-auditor/SKILL.md +3 -3
  136. package/.agent/skills/web-design-guidelines/SKILL.md +3 -3
  137. package/.agent/skills/webapp-testing/SKILL.md +3 -3
  138. package/.agent/skills/whimsy-injector/SKILL.md +3 -3
  139. package/.agent/skills/workflow-optimizer/SKILL.md +3 -3
  140. package/.agent/workflows/audit.md +6 -6
  141. package/.agent/workflows/deploy.md +1 -1
  142. package/.agent/workflows/generate.md +23 -6
  143. package/.agent/workflows/session.md +5 -5
  144. package/.agent/workflows/swarm.md +2 -2
  145. package/README.md +64 -8
  146. package/bin/tribunal-kit.js +277 -45
  147. package/package.json +9 -6
  148. package/scripts/changelog.js +167 -0
  149. package/scripts/sync-version.js +81 -0
  150. package/.agent/scripts/__pycache__/auto_preview.cpython-311.pyc +0 -0
  151. package/.agent/scripts/__pycache__/bundle_analyzer.cpython-311.pyc +0 -0
  152. package/.agent/scripts/__pycache__/checklist.cpython-311.pyc +0 -0
  153. package/.agent/scripts/__pycache__/dependency_analyzer.cpython-311.pyc +0 -0
  154. package/.agent/scripts/__pycache__/security_scan.cpython-311.pyc +0 -0
  155. package/.agent/scripts/__pycache__/session_manager.cpython-311.pyc +0 -0
  156. package/.agent/scripts/__pycache__/skill_integrator.cpython-311.pyc +0 -0
  157. package/.agent/scripts/__pycache__/swarm_dispatcher.cpython-311.pyc +0 -0
  158. package/.agent/scripts/__pycache__/test_runner.cpython-311.pyc +0 -0
  159. package/.agent/scripts/__pycache__/verify_all.cpython-311.pyc +0 -0
  160. package/.agent/scripts/auto_preview.py +0 -180
  161. package/.agent/scripts/bundle_analyzer.py +0 -259
  162. package/.agent/scripts/case_law_manager.py +0 -755
  163. package/.agent/scripts/checklist.py +0 -209
  164. package/.agent/scripts/compress_skills.py +0 -167
  165. package/.agent/scripts/consolidate_skills.py +0 -173
  166. package/.agent/scripts/deep_compress.py +0 -202
  167. package/.agent/scripts/dependency_analyzer.py +0 -247
  168. package/.agent/scripts/lint_runner.py +0 -188
  169. package/.agent/scripts/minify_context.py +0 -80
  170. package/.agent/scripts/patch_skills_meta.py +0 -177
  171. package/.agent/scripts/patch_skills_output.py +0 -285
  172. package/.agent/scripts/schema_validator.py +0 -279
  173. package/.agent/scripts/security_scan.py +0 -224
  174. package/.agent/scripts/session_manager.py +0 -261
  175. package/.agent/scripts/skill_evolution.py +0 -563
  176. package/.agent/scripts/skill_integrator.py +0 -234
  177. package/.agent/scripts/strengthen_skills.py +0 -220
  178. package/.agent/scripts/strip_tribunal.py +0 -41
  179. package/.agent/scripts/swarm_dispatcher.py +0 -350
  180. package/.agent/scripts/test_runner.py +0 -192
  181. package/.agent/scripts/test_swarm_dispatcher.py +0 -163
  182. package/.agent/scripts/verify_all.py +0 -195
@@ -1,209 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- checklist.py — Priority-based project audit runner for the Tribunal Agent Kit.
4
-
5
- Runs a tiered audit sequence:
6
- Priority 1: Security
7
- Priority 2: Lint
8
- Priority 3: Schema validation
9
- Priority 4: Tests
10
- Priority 5: UX / Accessibility
11
- Priority 6: SEO
12
- Priority 7: Lighthouse / E2E (requires --url)
13
-
14
- Usage:
15
- python .agent/scripts/checklist.py .
16
- python .agent/scripts/checklist.py . --url http://localhost:3000
17
- python .agent/scripts/checklist.py . --skip security,seo
18
- """
19
-
20
- import os
21
- import sys
22
- import subprocess
23
- import argparse
24
- from pathlib import Path
25
-
26
- # ━━━ ANSI color output ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
27
- RED = "\033[91m"
28
- GREEN = "\033[92m"
29
- YELLOW = "\033[93m"
30
- BLUE = "\033[94m"
31
- RESET = "\033[0m"
32
- BOLD = "\033[1m"
33
-
34
-
35
- def print_header(title: str) -> None:
36
- print(f"\n{BOLD}{BLUE}━━━ {title} ━━━{RESET}")
37
-
38
-
39
- def print_ok(msg: str) -> None:
40
- print(f" {GREEN}āœ… {msg}{RESET}")
41
-
42
-
43
- def print_fail(msg: str) -> None:
44
- print(f" {RED}āŒ {msg}{RESET}")
45
-
46
-
47
- def print_skip(msg: str) -> None:
48
- print(f" {YELLOW}ā­ļø Skipped: {msg}{RESET}")
49
-
50
-
51
- def run_check(label: str, cmd: list[str], cwd: str) -> bool:
52
- """Run a shell command and return True if it exits with code 0."""
53
- try:
54
- result = subprocess.run(
55
- cmd,
56
- cwd=cwd,
57
- capture_output=True,
58
- text=True,
59
- timeout=60,
60
- )
61
- if result.returncode == 0:
62
- print_ok(f"{label} passed")
63
- return True
64
- else:
65
- print_fail(f"{label} failed")
66
- if result.stdout.strip():
67
- print(f" {result.stdout.strip()[:500]}")
68
- if result.stderr.strip():
69
- print(f" {result.stderr.strip()[:500]}")
70
- return False
71
- except FileNotFoundError:
72
- print_skip(f"{label} — command not found (tool not installed)")
73
- return True # Don't block on tools that aren't installed
74
- except subprocess.TimeoutExpired:
75
- print_fail(f"{label} — timed out after 60s")
76
- return False
77
-
78
-
79
- def check_secrets(project_root: str) -> bool:
80
- """Scan for hardcoded secrets in source files."""
81
- print_header("Security — Secret Scan")
82
- dangerous_patterns = [
83
- "password=",
84
- "secret=",
85
- "api_key=",
86
- "apikey=",
87
- "AUTH_TOKEN=",
88
- "PRIVATE_KEY=",
89
- ]
90
- found_issues = False
91
- source_extensions = {".ts", ".tsx", ".js", ".jsx", ".py", ".env"}
92
-
93
- for root, dirs, files in os.walk(project_root):
94
- # Skip known-safe directories
95
- dirs[:] = [d for d in dirs if d not in {"node_modules", ".git", ".agent", "dist", "__pycache__"}]
96
- for filename in files:
97
- if not any(filename.endswith(ext) for ext in source_extensions):
98
- continue
99
- if filename.startswith(".env"):
100
- continue # .env files are allowed to have these
101
- filepath = os.path.join(root, filename)
102
- try:
103
- with open(filepath, "r", encoding="utf-8", errors="ignore") as f:
104
- for line_num, line in enumerate(f, 1):
105
- line_lower = line.lower().strip()
106
- if any(pattern in line_lower for pattern in dangerous_patterns):
107
- # Only flag if it looks like an actual value (contains = and a non-empty value)
108
- if "=" in line and not line_lower.strip().startswith("#"):
109
- rel = os.path.relpath(filepath, project_root)
110
- print_fail(f"Possible secret: {rel}:{line_num} → {line.strip()[:80]}")
111
- found_issues = True
112
- except (IOError, PermissionError):
113
- pass
114
-
115
- if not found_issues:
116
- print_ok("No hardcoded secrets detected")
117
- return not found_issues
118
-
119
-
120
- def run_all(project_root: str, url: str | None, skip: list[str]) -> int:
121
- """Run all checklist tiers. Returns number of failures."""
122
- failures = 0
123
-
124
- # Priority 1 — Security
125
- if "security" not in skip:
126
- print_header("Priority 1 — Security")
127
- if not check_secrets(project_root):
128
- failures += 1
129
- else:
130
- print_skip("Security tier")
131
-
132
- # Priority 2 — Lint
133
- if "lint" not in skip:
134
- print_header("Priority 2 — Lint")
135
- if not run_check("ESLint", ["npx", "eslint", ".", "--max-warnings=0"], project_root):
136
- failures += 1
137
- if not run_check("TypeScript", ["npx", "tsc", "--noEmit"], project_root):
138
- failures += 1
139
- else:
140
- print_skip("Lint tier")
141
-
142
- # Priority 3 — Schema
143
- if "schema" not in skip:
144
- print_header("Priority 3 — Schema")
145
- print_skip("Schema check — run manually if you have DB migrations")
146
- else:
147
- print_skip("Schema tier")
148
-
149
- # Priority 4 — Tests
150
- if "tests" not in skip:
151
- print_header("Priority 4 — Tests")
152
- if not run_check("Test suite", ["npm", "test", "--", "--passWithNoTests"], project_root):
153
- failures += 1
154
- else:
155
- print_skip("Tests tier")
156
-
157
- # Priority 5 — UX
158
- if "ux" not in skip:
159
- print_header("Priority 5 — UX / Accessibility")
160
- print_skip("UX audit — run /preview start then check manually or with Lighthouse")
161
- else:
162
- print_skip("UX tier")
163
-
164
- # Priority 6 — SEO
165
- if "seo" not in skip:
166
- print_header("Priority 6 — SEO")
167
- print_skip("SEO check — use /ui-ux-pro-max for SEO-sensitive pages")
168
- else:
169
- print_skip("SEO tier")
170
-
171
- # Priority 7 — Lighthouse / E2E
172
- if url and "e2e" not in skip:
173
- print_header("Priority 7 — Lighthouse / E2E")
174
- if not run_check("Playwright E2E", ["npx", "playwright", "test"], project_root):
175
- failures += 1
176
- elif not url:
177
- print_skip("E2E / Lighthouse — pass --url to enable")
178
-
179
- # ━━━ Summary ━━━
180
- print(f"\n{BOLD}━━━ Checklist Summary ━━━{RESET}")
181
- if failures == 0:
182
- print_ok(f"All checks passed — ready to proceed")
183
- else:
184
- print_fail(f"{failures} tier(s) failed — fix Critical issues before proceeding")
185
-
186
- return failures
187
-
188
-
189
- def main() -> None:
190
- parser = argparse.ArgumentParser(description="Tribunal project checklist runner")
191
- parser.add_argument("path", help="Project root directory")
192
- parser.add_argument("--url", help="Local server URL for Lighthouse/E2E checks", default=None)
193
- parser.add_argument("--skip", help="Comma-separated tiers to skip (security,lint,schema,tests,ux,seo,e2e)", default="")
194
- args = parser.parse_args()
195
-
196
- project_root = os.path.abspath(args.path)
197
- if not os.path.isdir(project_root):
198
- print_fail(f"Directory not found: {project_root}")
199
- sys.exit(1)
200
-
201
- skip = [s.strip().lower() for s in args.skip.split(",") if s.strip()]
202
-
203
- print(f"{BOLD}Tribunal Checklist — {project_root}{RESET}")
204
- failures = run_all(project_root, args.url, skip)
205
- sys.exit(1 if failures > 0 else 0)
206
-
207
-
208
- if __name__ == "__main__":
209
- main()
@@ -1,167 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- compress_skills.py - Aggressive token reduction for .agent/skills/**/*.md files
4
- WHAT IT DOES:
5
- 1. Strips ## šŸ›ļø Tribunal Integration sections (in GEMINI.md globally)
6
- 2. Strips ## āœ… Pre-Flight Self-Audit sections (duplication)
7
- 3. Strips ## Cross-Workflow Navigation sections
8
- 4. Strips ## Output Format sections
9
- 5. Strips inline comment blocks inside code (// Description of obvious stuff)
10
- 6. Collapses 3+ empty lines → 1
11
- 7. Removes chatty intro paragraphs (patterns like "X is Y. If you Z, you're Z.")
12
- """
13
-
14
- import os, re, sys
15
-
16
- # ─── Section strippers ──────────────────────────────────────────────────────
17
-
18
- SECTION_PATTERNS = [
19
- # Tribunal / pre-flight boilerplate (global in GEMINI.md)
20
- r'(?m)^## šŸ›ļø Tribunal Integration[\s\S]*?(?=\n## |\n# |\Z)',
21
- r'(?m)^## Tribunal Integration[\s\S]*?(?=\n## |\n# |\Z)',
22
- r'(?m)^### āœ… Pre-Flight Self-Audit[\s\S]*?(?=\n## |\n### |\n# |\Z)',
23
- r'(?m)^## Pre-Flight Self-Audit[\s\S]*?(?=\n## |\n# |\Z)',
24
- r'(?m)^## Cross-Workflow Navigation[\s\S]*?(?=\n## |\n# |\Z)',
25
- r'(?m)^## Output Format\s*\n```[\s\S]*?```\s*\n',
26
- r'(?m)^## VBC Protocol[\s\S]*?(?=\n## |\n# |\Z)',
27
- r'(?m)^## LLM Traps[\s\S]*?(?=\n## |\n# |\Z)',
28
- ]
29
-
30
- # ─── Chatty intro line patterns ───────────────────────────────────────────
31
- # e.g. "React 19 is a paradigm shift. Server Components are the default."
32
- # These are after the frontmatter H1 title — motivational filler.
33
- CHATTY_INTRO = re.compile(
34
- r'(?m)^(# .+\n)\n[A-Z][^#\n]{60,}\n[A-Z][^#\n]{40,}\n\n---',
35
- )
36
-
37
- def strip_chatty_intro(content):
38
- def replace(m):
39
- return m.group(1) + '\n---'
40
- return CHATTY_INTRO.sub(replace, content)
41
-
42
- # ─── Trim verbose inline comments in code blocks ─────────────────────────
43
- # Removes "// comment that just restates the surrounding code name"
44
- OBVIOUS_COMMENT = re.compile(
45
- r'(?m)^(\s*)(// (default for most properties|shorthand|number of repeats|default: \d+|spring tension|resistance|weight|approximate duration|deceleration rate)[^\n]*)\n'
46
- )
47
-
48
- def strip_obvious_comments(content):
49
- return OBVIOUS_COMMENT.sub('', content)
50
-
51
- # ─── Long repetitive āœ…/āŒ rule blocks that repeat main section ────────────
52
- # These are usually "Performance Rules" text blocks restating code above
53
- PERF_TEXT_BLOCK = re.compile(
54
- r'(?m)^```\n(āœ… Use \w[^\n]*\n → [^\n]*\n\n?){3,}```\n'
55
- )
56
- def compress_perf_blocks(content):
57
- def to_bullets(m):
58
- text = m.group(0)
59
- lines = text.strip('`\n').splitlines()
60
- bullets = []
61
- for line in lines:
62
- stripped = line.strip()
63
- if stripped.startswith('āœ…') or stripped.startswith('āŒ'):
64
- bullets.append(f'- {stripped}')
65
- elif stripped.startswith('→'):
66
- bullets[-1] += f' ({stripped[1:].strip()})'
67
- return '\n'.join(bullets) + '\n'
68
- return PERF_TEXT_BLOCK.sub(to_bullets, content)
69
-
70
- # ─── Collapse empty lines ────────────────────────────────────────────────
71
- def collapse_blanks(content):
72
- return re.sub(r'\n{3,}', '\n\n', content)
73
-
74
- # ─── Remove "This is X — not Y" filler sentences before the first ## ─────
75
- FILLER_BEFORE_SECTION = re.compile(
76
- r'(?m)(^# .+\n\n)([A-Z][^\n]+\n){1,4}(\n---\n)',
77
- re.MULTILINE
78
- )
79
- def remove_filler_between_title_and_hr(content):
80
- def replacement(m):
81
- return m.group(1) + m.group(3)
82
- return FILLER_BEFORE_SECTION.sub(replacement, content)
83
-
84
- # ─── Strip redundant version comment banners ────────────────────────────
85
- # e.g. "// motion.div, motion.span, motion.button, motion.svg, motion.path, etc."
86
- # "// Any HTML or SVG element can be prefixed with `motion.`" - obvious
87
- REDUNDANT_NOTE = re.compile(r'(?m)^// (motion\.\w+|Any HTML|Note:|Variant names propagate|// )[^\n]*\n')
88
-
89
- def strip_redundant_notes(content):
90
- return REDUNDANT_NOTE.sub('', content)
91
-
92
- # ─── Main pipeline ────────────────────────────────────────────────────────
93
-
94
- def compress_file(path):
95
- with open(path, 'r', encoding='utf-8', errors='ignore') as f:
96
- original = f.read()
97
-
98
- content = original
99
-
100
- # 1. Strip global boilerplate sections
101
- for pattern in SECTION_PATTERNS:
102
- content = re.sub(pattern, '', content)
103
-
104
- # 2. Remove chatty intro paragraphs
105
- content = strip_chatty_intro(content)
106
-
107
- # 3. Remove filler between title and first ---
108
- content = remove_filler_between_title_and_hr(content)
109
-
110
- # 4. Strip obvious inline comments from code
111
- content = strip_obvious_comments(content)
112
-
113
- # 5. Strip redundant notes
114
- content = strip_redundant_notes(content)
115
-
116
- # 6. Compress verbose perf rule text blocks to bullet lists
117
- content = compress_perf_blocks(content)
118
-
119
- # 7. Collapse 3+ blank lines
120
- content = collapse_blanks(content)
121
-
122
- # Write back
123
- with open(path, 'w', encoding='utf-8') as f:
124
- f.write(content.strip() + '\n')
125
-
126
- saved = len(original) - len(content)
127
- return len(original), len(content), saved
128
-
129
- def main():
130
- base = '.agent/skills'
131
- if not os.path.exists(base):
132
- print(f"ERROR: '{base}' not found. Run from tribunal-kit root.", file=sys.stderr)
133
- sys.exit(1)
134
-
135
- total_orig = 0
136
- total_new = 0
137
- results = []
138
-
139
- for root, _, files in os.walk(base):
140
- for fname in files:
141
- if fname.endswith('.md'):
142
- path = os.path.join(root, fname)
143
- orig, new, saved = compress_file(path)
144
- total_orig += orig
145
- total_new += new
146
- if saved > 0:
147
- results.append((saved, path))
148
-
149
- results.sort(reverse=True)
150
-
151
- print(f"\n{'='*55}")
152
- print(f" Skill Compression Complete")
153
- print(f"{'='*55}")
154
- print(f" Original : {total_orig:,} bytes ({total_orig//1024}KB)")
155
- print(f" After : {total_new:,} bytes ({total_new//1024}KB)")
156
- saved_total = total_orig - total_new
157
- pct = saved_total / total_orig * 100 if total_orig else 0
158
- print(f" Saved : {saved_total:,} bytes ({saved_total//1024}KB) — {pct:.1f}%")
159
- print(f"\n Top savings:")
160
- for saved, path in results[:15]:
161
- skill = os.path.basename(os.path.dirname(path))
162
- fname = os.path.basename(path)
163
- print(f" -{saved//1024:2}KB {skill}/{fname}")
164
- print()
165
-
166
- if __name__ == '__main__':
167
- main()
@@ -1,173 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- consolidate_skills.py
4
- Merges all sub-files in skill directories into the main SKILL.md.
5
- Strips: verbose intros, output format blocks, run scripts tables,
6
- mandatory read tables, empty headers, redundant boilerplate.
7
- Keeps: all code blocks, hallucination traps, checklist items.
8
-
9
- Usage:
10
- python .agent/scripts/consolidate_skills.py [skill_name]
11
- python .agent/scripts/consolidate_skills.py # all skills
12
- """
13
-
14
- import os, re, sys
15
-
16
- BASE = '.agent/skills'
17
-
18
- # These patterns are global (GEMINI.md) — strip from sub-files before merge
19
- STRIP_PATTERNS = [
20
- r'(?ms)^## šŸ›ļø Tribunal Integration.*?(?=^## |\Z)',
21
- r'(?ms)^## Tribunal Integration.*?(?=^## |\Z)',
22
- r'(?ms)^### āœ… Pre-Flight Self-Audit.*?(?=^###|^## |\Z)',
23
- r'(?ms)^## Pre-Flight Self-Audit.*?(?=^## |\Z)',
24
- r'(?ms)^## Output Format\b.*?(?=^## |\Z)',
25
- r'(?ms)^## šŸ”§ Runtime Scripts.*?(?=^## |\Z)',
26
- r'(?ms)^## šŸ”“ MANDATORY.*?(?=^## |\Z)',
27
- r'(?ms)^## āš ļø CRITICAL: ASK BEFORE ASSUMING.*?(?=^## |\Z)',
28
- r'(?ms)^## šŸ“ CHECKPOINT \(MANDATORY.*?(?=^## |\Z)',
29
- r'(?ms)^## Output Format.*?```\n[^`]*```\n?(?=^## |\Z)',
30
- r'(?ms)^\*\*Execute these for validation.*?---\n',
31
- r'(?ms)^\*\*VBC \(Verification-Before-Completion\).*?\n',
32
- # MANDATORY read tables
33
- r'(?ms)^\*\*ā›” DO NOT start.*?---\n?',
34
- r'(?ms)^> 🧠 \*\*mobile-design.*?\n',
35
- r'(?ms)^> \*\*STOP.*?\n',
36
- ]
37
-
38
- # Heading level adjustment (sub-files use H1 — convert to H2 in merged output)
39
- def adjust_headings(content, offset=1):
40
- """Promote headings by adding # chars"""
41
- lines = content.split('\n')
42
- out = []
43
- for line in lines:
44
- m = re.match(r'^(#{1,5}) ', line)
45
- if m:
46
- level = len(m.group(1))
47
- new_level = min(level + offset, 6)
48
- line = '#' * new_level + line[level:]
49
- out.append(line)
50
- return '\n'.join(out)
51
-
52
- def clean_content(content):
53
- """Apply strip patterns"""
54
- for p in STRIP_PATTERNS:
55
- content = re.sub(p, '', content)
56
- content = re.sub(r'\n{3,}', '\n\n', content)
57
- return content.strip()
58
-
59
- def extract_frontmatter(content):
60
- """Return (frontmatter_dict_str, body)"""
61
- m = re.match(r'^---\n(.*?)\n---\n', content, re.DOTALL)
62
- if m:
63
- return m.group(1), content[m.end():]
64
- return '', content
65
-
66
- def get_sub_title(content):
67
- """Get first H1 from a sub-file"""
68
- m = re.search(r'^# (.+)', content, re.MULTILINE)
69
- return m.group(1) if m else None
70
-
71
- def consolidate(skill_dir):
72
- skill_name = os.path.basename(skill_dir)
73
- main_path = os.path.join(skill_dir, 'SKILL.md')
74
- if not os.path.exists(main_path):
75
- return False
76
-
77
- # Find sub-files (non-SKILL.md markdown files)
78
- sub_files = sorted([
79
- f for f in os.listdir(skill_dir)
80
- if f.endswith('.md') and f != 'SKILL.md'
81
- ])
82
-
83
- if not sub_files:
84
- return False
85
-
86
- print(f'\n → Consolidating: {skill_name} ({len(sub_files)} sub-files)')
87
-
88
- # Read main SKILL.md
89
- main_content = open(main_path, 'r', encoding='utf-8', errors='ignore').read()
90
- frontmatter, main_body = extract_frontmatter(main_content)
91
-
92
- # Clean & update frontmatter version
93
- fm_lines = frontmatter.split('\n')
94
- new_fm = []
95
- for line in fm_lines:
96
- if line.startswith('version:'):
97
- new_fm.append('version: 3.1.0')
98
- elif line.startswith('last-updated:'):
99
- new_fm.append('last-updated: 2026-04-06')
100
- else:
101
- new_fm.append(line)
102
- frontmatter = '\n'.join(new_fm)
103
-
104
- # Clean main body
105
- main_body = clean_content(main_body)
106
-
107
- # Remove MANDATORY read table from main body
108
- # (links like [file.md](file.md) in tables)
109
- main_body = re.sub(r'\|.*?\.md.*?\|.*?\|.*?\|\n', '', main_body)
110
- main_body = re.sub(r'^\|[-| ]+\|\n', '', main_body, flags=re.MULTILINE)
111
- main_body = re.sub(r'\n{3,}', '\n\n', main_body)
112
-
113
- # Merge sub-files
114
- merged_sections = []
115
- for fname in sub_files:
116
- fpath = os.path.join(skill_dir, fname)
117
- raw = open(fpath, 'r', encoding='utf-8', errors='ignore').read()
118
- _, body = extract_frontmatter(raw)
119
- body = clean_content(body)
120
- # Adjust headings: H1→H2, H2→H3, etc.
121
- body = adjust_headings(body, offset=1)
122
- if body.strip():
123
- merged_sections.append(body.strip())
124
-
125
- # Build final output
126
- combined = f'---\n{frontmatter}\n---\n\n{main_body}'
127
- if merged_sections:
128
- combined += '\n\n---\n\n' + '\n\n---\n\n'.join(merged_sections)
129
-
130
- # Final cleanup
131
- combined = re.sub(r'\n{3,}', '\n\n', combined)
132
- combined = combined.strip() + '\n'
133
-
134
- # Measure savings
135
- total_sub_bytes = sum(os.path.getsize(os.path.join(skill_dir, f)) for f in sub_files)
136
- print(f' Sub-files total: {total_sub_bytes//1024}KB')
137
-
138
- # Write consolidated SKILL.md
139
- with open(main_path, 'w', encoding='utf-8') as f:
140
- f.write(combined)
141
-
142
- new_size = os.path.getsize(main_path)
143
- print(f' New SKILL.md: {new_size//1024}KB (from {len(main_content)//1024}KB main + {total_sub_bytes//1024}KB subs → {new_size//1024}KB)')
144
-
145
- # Delete sub-files
146
- for fname in sub_files:
147
- os.remove(os.path.join(skill_dir, fname))
148
- print(f' Deleted: {fname}')
149
-
150
- return True
151
-
152
- def main():
153
- target = sys.argv[1] if len(sys.argv) > 1 else None
154
-
155
- total_saved = 0
156
- processed = 0
157
-
158
- for skill_name in os.listdir(BASE):
159
- skill_dir = os.path.join(BASE, skill_name)
160
- if not os.path.isdir(skill_dir):
161
- continue
162
- if target and skill_name != target:
163
- continue
164
- if consolidate(skill_dir):
165
- processed += 1
166
-
167
- if processed == 0:
168
- print('No skills with sub-files found (or target not matched).')
169
- else:
170
- print(f'\nāœ… Consolidated {processed} skills.')
171
-
172
- if __name__ == '__main__':
173
- main()