@iamnishankhan/opencode-kit-grok 1.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.
Files changed (198) hide show
  1. package/bin/cli.js +46 -0
  2. package/kit/.opencode/AGENTS.md +392 -0
  3. package/kit/.opencode/README.md +71 -0
  4. package/kit/.opencode/USAGE.md +405 -0
  5. package/kit/.opencode/agents/backend-specialist.md +278 -0
  6. package/kit/.opencode/agents/code-archaeologist.md +114 -0
  7. package/kit/.opencode/agents/database-architect.md +233 -0
  8. package/kit/.opencode/agents/debugger.md +234 -0
  9. package/kit/.opencode/agents/devops-engineer.md +252 -0
  10. package/kit/.opencode/agents/documentation-writer.md +111 -0
  11. package/kit/.opencode/agents/explorer-agent.md +83 -0
  12. package/kit/.opencode/agents/frontend-specialist.md +606 -0
  13. package/kit/.opencode/agents/game-developer.md +169 -0
  14. package/kit/.opencode/agents/mobile-developer.md +385 -0
  15. package/kit/.opencode/agents/orchestrator.md +213 -0
  16. package/kit/.opencode/agents/penetration-tester.md +197 -0
  17. package/kit/.opencode/agents/performance-optimizer.md +194 -0
  18. package/kit/.opencode/agents/product-manager.md +120 -0
  19. package/kit/.opencode/agents/product-owner.md +103 -0
  20. package/kit/.opencode/agents/project-planner.md +418 -0
  21. package/kit/.opencode/agents/qa-automation-engineer.md +113 -0
  22. package/kit/.opencode/agents/security-auditor.md +179 -0
  23. package/kit/.opencode/agents/seo-specialist.md +119 -0
  24. package/kit/.opencode/agents/test-engineer.md +169 -0
  25. package/kit/.opencode/commands/brainstorm.md +113 -0
  26. package/kit/.opencode/commands/coordinate.md +72 -0
  27. package/kit/.opencode/commands/create.md +63 -0
  28. package/kit/.opencode/commands/debug.md +102 -0
  29. package/kit/.opencode/commands/deploy.md +175 -0
  30. package/kit/.opencode/commands/enhance.md +62 -0
  31. package/kit/.opencode/commands/orchestrate.md +241 -0
  32. package/kit/.opencode/commands/plan.md +89 -0
  33. package/kit/.opencode/commands/preview.md +80 -0
  34. package/kit/.opencode/commands/remember.md +67 -0
  35. package/kit/.opencode/commands/status.md +86 -0
  36. package/kit/.opencode/commands/test.md +143 -0
  37. package/kit/.opencode/commands/verify.md +71 -0
  38. package/kit/.opencode/memory/MEMORY.md +6 -0
  39. package/kit/.opencode/memory/feedback-history.md +9 -0
  40. package/kit/.opencode/memory/project-conventions.md +16 -0
  41. package/kit/.opencode/memory/tech-decisions.md +10 -0
  42. package/kit/.opencode/memory/user-preferences.md +9 -0
  43. package/kit/.opencode/opencode.json +15 -0
  44. package/kit/.opencode/scripts/README.md +95 -0
  45. package/kit/.opencode/scripts/auto_preview.py +149 -0
  46. package/kit/.opencode/scripts/checklist.py +75 -0
  47. package/kit/.opencode/scripts/component_registry.py +238 -0
  48. package/kit/.opencode/scripts/dependency_graph.py +73 -0
  49. package/kit/.opencode/scripts/generate_manifest.py +44 -0
  50. package/kit/.opencode/scripts/session_manager.py +120 -0
  51. package/kit/.opencode/scripts/tests/test_toolkit.py +238 -0
  52. package/kit/.opencode/scripts/validate_kit.py +397 -0
  53. package/kit/.opencode/scripts/validation_runner.py +216 -0
  54. package/kit/.opencode/scripts/verify_all.py +85 -0
  55. package/kit/.opencode/skills/api-patterns/SKILL.md +83 -0
  56. package/kit/.opencode/skills/api-patterns/api-style.md +42 -0
  57. package/kit/.opencode/skills/api-patterns/auth.md +24 -0
  58. package/kit/.opencode/skills/api-patterns/documentation.md +26 -0
  59. package/kit/.opencode/skills/api-patterns/graphql.md +41 -0
  60. package/kit/.opencode/skills/api-patterns/rate-limiting.md +31 -0
  61. package/kit/.opencode/skills/api-patterns/response.md +37 -0
  62. package/kit/.opencode/skills/api-patterns/rest.md +40 -0
  63. package/kit/.opencode/skills/api-patterns/scripts/api_validator.py +211 -0
  64. package/kit/.opencode/skills/api-patterns/security-testing.md +122 -0
  65. package/kit/.opencode/skills/api-patterns/trpc.md +41 -0
  66. package/kit/.opencode/skills/api-patterns/versioning.md +22 -0
  67. package/kit/.opencode/skills/app-builder/SKILL.md +78 -0
  68. package/kit/.opencode/skills/app-builder/agent-coordination.md +71 -0
  69. package/kit/.opencode/skills/app-builder/feature-building.md +53 -0
  70. package/kit/.opencode/skills/app-builder/project-detection.md +45 -0
  71. package/kit/.opencode/skills/app-builder/scaffolding.md +110 -0
  72. package/kit/.opencode/skills/app-builder/tech-stack.md +41 -0
  73. package/kit/.opencode/skills/app-builder/templates/SKILL.md +39 -0
  74. package/kit/.opencode/skills/app-builder/templates/astro-static/TEMPLATE.md +78 -0
  75. package/kit/.opencode/skills/app-builder/templates/chrome-extension/TEMPLATE.md +96 -0
  76. package/kit/.opencode/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  77. package/kit/.opencode/skills/app-builder/templates/electron-desktop/TEMPLATE.md +97 -0
  78. package/kit/.opencode/skills/app-builder/templates/express-api/TEMPLATE.md +89 -0
  79. package/kit/.opencode/skills/app-builder/templates/flutter-app/TEMPLATE.md +93 -0
  80. package/kit/.opencode/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +97 -0
  81. package/kit/.opencode/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +126 -0
  82. package/kit/.opencode/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +125 -0
  83. package/kit/.opencode/skills/app-builder/templates/nextjs-static/TEMPLATE.md +174 -0
  84. package/kit/.opencode/skills/app-builder/templates/nuxt-app/TEMPLATE.md +127 -0
  85. package/kit/.opencode/skills/app-builder/templates/python-fastapi/TEMPLATE.md +94 -0
  86. package/kit/.opencode/skills/app-builder/templates/react-native-app/TEMPLATE.md +121 -0
  87. package/kit/.opencode/skills/architecture/SKILL.md +57 -0
  88. package/kit/.opencode/skills/architecture/context-discovery.md +43 -0
  89. package/kit/.opencode/skills/architecture/examples.md +94 -0
  90. package/kit/.opencode/skills/architecture/pattern-selection.md +68 -0
  91. package/kit/.opencode/skills/architecture/patterns-reference.md +50 -0
  92. package/kit/.opencode/skills/architecture/trade-off-analysis.md +77 -0
  93. package/kit/.opencode/skills/bash-linux/SKILL.md +201 -0
  94. package/kit/.opencode/skills/batch-operations/SKILL.md +105 -0
  95. package/kit/.opencode/skills/behavioral-modes/SKILL.md +253 -0
  96. package/kit/.opencode/skills/brainstorming/SKILL.md +178 -0
  97. package/kit/.opencode/skills/brainstorming/dynamic-questioning.md +350 -0
  98. package/kit/.opencode/skills/clean-code/SKILL.md +201 -0
  99. package/kit/.opencode/skills/code-review-checklist/SKILL.md +111 -0
  100. package/kit/.opencode/skills/code-review-graph/SKILL.md +305 -0
  101. package/kit/.opencode/skills/context-compression/SKILL.md +145 -0
  102. package/kit/.opencode/skills/coordinator-mode/SKILL.md +208 -0
  103. package/kit/.opencode/skills/database-design/SKILL.md +54 -0
  104. package/kit/.opencode/skills/database-design/database-selection.md +43 -0
  105. package/kit/.opencode/skills/database-design/indexing.md +39 -0
  106. package/kit/.opencode/skills/database-design/migrations.md +48 -0
  107. package/kit/.opencode/skills/database-design/optimization.md +36 -0
  108. package/kit/.opencode/skills/database-design/orm-selection.md +30 -0
  109. package/kit/.opencode/skills/database-design/schema-design.md +56 -0
  110. package/kit/.opencode/skills/database-design/scripts/schema_validator.py +172 -0
  111. package/kit/.opencode/skills/deployment-procedures/SKILL.md +243 -0
  112. package/kit/.opencode/skills/design-spec/SKILL.md +185 -0
  113. package/kit/.opencode/skills/design-spec/collection.md +106 -0
  114. package/kit/.opencode/skills/documentation-templates/SKILL.md +196 -0
  115. package/kit/.opencode/skills/frontend-architecture/SKILL.md +245 -0
  116. package/kit/.opencode/skills/frontend-design/SKILL.md +1222 -0
  117. package/kit/.opencode/skills/frontend-design/redesign.md +178 -0
  118. package/kit/.opencode/skills/frontend-design/scripts/accessibility_checker.py +145 -0
  119. package/kit/.opencode/skills/frontend-design/scripts/ux_audit.py +722 -0
  120. package/kit/.opencode/skills/frontend-design/style-brutalist.md +92 -0
  121. package/kit/.opencode/skills/frontend-design/style-minimalist.md +85 -0
  122. package/kit/.opencode/skills/game-development/2d-games/SKILL.md +118 -0
  123. package/kit/.opencode/skills/game-development/3d-games/SKILL.md +134 -0
  124. package/kit/.opencode/skills/game-development/SKILL.md +169 -0
  125. package/kit/.opencode/skills/game-development/game-art/SKILL.md +184 -0
  126. package/kit/.opencode/skills/game-development/game-audio/SKILL.md +189 -0
  127. package/kit/.opencode/skills/game-development/game-design/SKILL.md +128 -0
  128. package/kit/.opencode/skills/game-development/mobile-games/SKILL.md +107 -0
  129. package/kit/.opencode/skills/game-development/multiplayer/SKILL.md +131 -0
  130. package/kit/.opencode/skills/game-development/pc-games/SKILL.md +143 -0
  131. package/kit/.opencode/skills/game-development/vr-ar/SKILL.md +122 -0
  132. package/kit/.opencode/skills/game-development/web-games/SKILL.md +149 -0
  133. package/kit/.opencode/skills/geo-fundamentals/SKILL.md +158 -0
  134. package/kit/.opencode/skills/geo-fundamentals/scripts/geo_checker.py +273 -0
  135. package/kit/.opencode/skills/i18n-localization/SKILL.md +156 -0
  136. package/kit/.opencode/skills/i18n-localization/scripts/i18n_checker.py +223 -0
  137. package/kit/.opencode/skills/intelligent-routing/SKILL.md +337 -0
  138. package/kit/.opencode/skills/lint-and-validate/SKILL.md +47 -0
  139. package/kit/.opencode/skills/lint-and-validate/scripts/lint_runner.py +184 -0
  140. package/kit/.opencode/skills/lint-and-validate/scripts/type_coverage.py +245 -0
  141. package/kit/.opencode/skills/mcp-builder/SKILL.md +205 -0
  142. package/kit/.opencode/skills/memory-system/SKILL.md +181 -0
  143. package/kit/.opencode/skills/mobile-design/SKILL.md +396 -0
  144. package/kit/.opencode/skills/mobile-design/decision-trees.md +516 -0
  145. package/kit/.opencode/skills/mobile-design/mobile-backend.md +491 -0
  146. package/kit/.opencode/skills/mobile-design/mobile-color-system.md +420 -0
  147. package/kit/.opencode/skills/mobile-design/mobile-debugging.md +122 -0
  148. package/kit/.opencode/skills/mobile-design/mobile-design-thinking.md +357 -0
  149. package/kit/.opencode/skills/mobile-design/mobile-navigation.md +458 -0
  150. package/kit/.opencode/skills/mobile-design/mobile-performance.md +767 -0
  151. package/kit/.opencode/skills/mobile-design/mobile-testing.md +356 -0
  152. package/kit/.opencode/skills/mobile-design/mobile-typography.md +433 -0
  153. package/kit/.opencode/skills/mobile-design/platform-android.md +666 -0
  154. package/kit/.opencode/skills/mobile-design/platform-ios.md +561 -0
  155. package/kit/.opencode/skills/mobile-design/scripts/mobile_audit.py +670 -0
  156. package/kit/.opencode/skills/mobile-design/touch-psychology.md +537 -0
  157. package/kit/.opencode/skills/nextjs-react-expert/1-async-eliminating-waterfalls.md +351 -0
  158. package/kit/.opencode/skills/nextjs-react-expert/2-bundle-bundle-size-optimization.md +240 -0
  159. package/kit/.opencode/skills/nextjs-react-expert/3-server-server-side-performance.md +490 -0
  160. package/kit/.opencode/skills/nextjs-react-expert/4-client-client-side-data-fetching.md +264 -0
  161. package/kit/.opencode/skills/nextjs-react-expert/5-rerender-re-render-optimization.md +581 -0
  162. package/kit/.opencode/skills/nextjs-react-expert/6-rendering-rendering-performance.md +432 -0
  163. package/kit/.opencode/skills/nextjs-react-expert/7-js-javascript-performance.md +684 -0
  164. package/kit/.opencode/skills/nextjs-react-expert/8-advanced-advanced-patterns.md +150 -0
  165. package/kit/.opencode/skills/nextjs-react-expert/9-cache-components.md +103 -0
  166. package/kit/.opencode/skills/nextjs-react-expert/SKILL.md +293 -0
  167. package/kit/.opencode/skills/nextjs-react-expert/scripts/convert_rules.py +222 -0
  168. package/kit/.opencode/skills/nextjs-react-expert/scripts/react_performance_checker.py +281 -0
  169. package/kit/.opencode/skills/nodejs-best-practices/SKILL.md +336 -0
  170. package/kit/.opencode/skills/parallel-agents/SKILL.md +192 -0
  171. package/kit/.opencode/skills/performance-profiling/SKILL.md +145 -0
  172. package/kit/.opencode/skills/performance-profiling/scripts/bundle_analyzer.py +120 -0
  173. package/kit/.opencode/skills/performance-profiling/scripts/lighthouse_audit.py +108 -0
  174. package/kit/.opencode/skills/plan-writing/SKILL.md +153 -0
  175. package/kit/.opencode/skills/powershell-windows/SKILL.md +169 -0
  176. package/kit/.opencode/skills/python-patterns/SKILL.md +443 -0
  177. package/kit/.opencode/skills/red-team-tactics/SKILL.md +201 -0
  178. package/kit/.opencode/skills/rust-pro/SKILL.md +177 -0
  179. package/kit/.opencode/skills/seo-fundamentals/SKILL.md +131 -0
  180. package/kit/.opencode/skills/seo-fundamentals/scripts/seo_checker.py +219 -0
  181. package/kit/.opencode/skills/server-management/SKILL.md +163 -0
  182. package/kit/.opencode/skills/simplify-code/SKILL.md +131 -0
  183. package/kit/.opencode/skills/skillify/SKILL.md +115 -0
  184. package/kit/.opencode/skills/systematic-debugging/SKILL.md +111 -0
  185. package/kit/.opencode/skills/tailwind-patterns/SKILL.md +271 -0
  186. package/kit/.opencode/skills/tdd-workflow/SKILL.md +151 -0
  187. package/kit/.opencode/skills/testing-patterns/SKILL.md +180 -0
  188. package/kit/.opencode/skills/testing-patterns/scripts/test_runner.py +219 -0
  189. package/kit/.opencode/skills/verify-changes/SKILL.md +127 -0
  190. package/kit/.opencode/skills/vulnerability-scanner/SKILL.md +278 -0
  191. package/kit/.opencode/skills/vulnerability-scanner/checklists.md +124 -0
  192. package/kit/.opencode/skills/vulnerability-scanner/scripts/dependency_analyzer.py +144 -0
  193. package/kit/.opencode/skills/vulnerability-scanner/scripts/security_scan.py +410 -0
  194. package/kit/.opencode/skills/web-design-guidelines/SKILL.md +56 -0
  195. package/kit/.opencode/skills/webapp-testing/SKILL.md +189 -0
  196. package/kit/.opencode/skills/webapp-testing/scripts/playwright_runner.py +123 -0
  197. package/lib/init.js +61 -0
  198. package/package.json +21 -0
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Auto Preview - OpenCode kit
4
+ ==============================
5
+ Manages (start/stop/status) the local development server for previewing the application.
6
+
7
+ Usage:
8
+ python .opencode/scripts/auto_preview.py start [port]
9
+ python .opencode/scripts/auto_preview.py stop
10
+ python .opencode/scripts/auto_preview.py status
11
+ """
12
+
13
+ import os
14
+ import sys
15
+ import time
16
+ import json
17
+ import signal
18
+ import argparse
19
+ import subprocess
20
+ from pathlib import Path
21
+
22
+ # Detect agent directory name dynamically
23
+ AGENT_DIR = Path(".agents") if Path(".agents").exists() else Path(".agents")
24
+ PID_FILE = AGENT_DIR / "preview.pid"
25
+ LOG_FILE = AGENT_DIR / "preview.log"
26
+
27
+ def get_project_root():
28
+ return Path(".").resolve()
29
+
30
+ def is_running(pid):
31
+ try:
32
+ os.kill(pid, 0)
33
+ return True
34
+ except OSError:
35
+ return False
36
+
37
+ def get_start_command(root):
38
+ pkg_file = root / "package.json"
39
+ if not pkg_file.exists():
40
+ return None
41
+
42
+ with open(pkg_file, 'r') as f:
43
+ data = json.load(f)
44
+
45
+ scripts = data.get("scripts", {})
46
+ if "dev" in scripts:
47
+ return ["npm", "run", "dev"]
48
+ elif "start" in scripts:
49
+ return ["npm", "start"]
50
+ return None
51
+
52
+ def start_server(port=3000):
53
+ if PID_FILE.exists():
54
+ try:
55
+ pid = int(PID_FILE.read_text().strip())
56
+ if is_running(pid):
57
+ print(f"⚠️ Preview already running (PID: {pid})")
58
+ return
59
+ except:
60
+ pass # Invalid PID file
61
+
62
+ root = get_project_root()
63
+ cmd = get_start_command(root)
64
+
65
+ if not cmd:
66
+ print("❌ No 'dev' or 'start' script found in package.json")
67
+ sys.exit(1)
68
+
69
+ # Add port env var if needed (simple heuristic)
70
+ env = os.environ.copy()
71
+ env["PORT"] = str(port)
72
+
73
+ print(f"🚀 Starting preview on port {port}...")
74
+
75
+ with open(LOG_FILE, "w") as log:
76
+ process = subprocess.Popen(
77
+ cmd,
78
+ cwd=str(root),
79
+ stdout=log,
80
+ stderr=log,
81
+ env=env,
82
+ shell=True # Required for npm on windows often, or consistent path handling
83
+ )
84
+
85
+ PID_FILE.write_text(str(process.pid))
86
+ print(f"✅ Preview started! (PID: {process.pid})")
87
+ print(f" Logs: {LOG_FILE}")
88
+ print(f" URL: http://localhost:{port}")
89
+
90
+ def stop_server():
91
+ if not PID_FILE.exists():
92
+ print("ℹ️ No preview server found.")
93
+ return
94
+
95
+ try:
96
+ pid = int(PID_FILE.read_text().strip())
97
+ if is_running(pid):
98
+ # Try gentle kill first
99
+ os.kill(pid, signal.SIGTERM) if sys.platform != 'win32' else subprocess.call(['taskkill', '/F', '/T', '/PID', str(pid)])
100
+ print(f"🛑 Preview stopped (PID: {pid})")
101
+ else:
102
+ print("ℹ️ Process was not running.")
103
+ except Exception as e:
104
+ print(f"❌ Error stopping server: {e}")
105
+ finally:
106
+ if PID_FILE.exists():
107
+ PID_FILE.unlink()
108
+
109
+ def status_server():
110
+ running = False
111
+ pid = None
112
+ url = "Unknown"
113
+
114
+ if PID_FILE.exists():
115
+ try:
116
+ pid = int(PID_FILE.read_text().strip())
117
+ if is_running(pid):
118
+ running = True
119
+ # Heuristic for URL, strictly we should save it
120
+ url = "http://localhost:3000"
121
+ except:
122
+ pass
123
+
124
+ print("\n=== Preview Status ===")
125
+ if running:
126
+ print(f"✅ Status: Running")
127
+ print(f"🔢 PID: {pid}")
128
+ print(f"🌐 URL: {url} (Likely)")
129
+ print(f"📝 Logs: {LOG_FILE}")
130
+ else:
131
+ print("⚪ Status: Stopped")
132
+ print("===================\n")
133
+
134
+ def main():
135
+ parser = argparse.ArgumentParser()
136
+ parser.add_argument("action", choices=["start", "stop", "status"])
137
+ parser.add_argument("port", nargs="?", default="3000")
138
+
139
+ args = parser.parse_args()
140
+
141
+ if args.action == "start":
142
+ start_server(int(args.port))
143
+ elif args.action == "stop":
144
+ stop_server()
145
+ elif args.action == "status":
146
+ status_server()
147
+
148
+ if __name__ == "__main__":
149
+ main()
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env python3
2
+ """Run the fast OpenCode kit validation checklist."""
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ from datetime import datetime, timezone
7
+ from pathlib import Path
8
+
9
+ from validation_runner import (
10
+ CONSOLE,
11
+ CheckSpec,
12
+ execute_suite,
13
+ locate_toolkit_root,
14
+ print_summary,
15
+ write_report,
16
+ )
17
+
18
+ CORE_CHECKS = (
19
+ CheckSpec(
20
+ "Security Scan",
21
+ "skills/vulnerability-scanner/scripts/security_scan.py",
22
+ "P0 Security",
23
+ required=True,
24
+ args=("--output", "summary", "--fail-on", "high"),
25
+ ),
26
+ CheckSpec("Lint Check", "skills/lint-and-validate/scripts/lint_runner.py", "P1 Code Quality", required=True),
27
+ CheckSpec("Type Coverage", "skills/lint-and-validate/scripts/type_coverage.py", "P1 Code Quality"),
28
+ CheckSpec("Schema Validation", "skills/database-design/scripts/schema_validator.py", "P2 Data Layer"),
29
+ CheckSpec("Test Runner", "skills/testing-patterns/scripts/test_runner.py", "P3 Testing"),
30
+ CheckSpec("UX Audit", "skills/frontend-design/scripts/ux_audit.py", "P4 UX & Accessibility"),
31
+ CheckSpec("Accessibility Check", "skills/frontend-design/scripts/accessibility_checker.py", "P4 UX & Accessibility"),
32
+ CheckSpec("SEO Check", "skills/seo-fundamentals/scripts/seo_checker.py", "P5 SEO"),
33
+ )
34
+
35
+ URL_CHECKS = (
36
+ CheckSpec("Lighthouse Audit", "skills/performance-profiling/scripts/lighthouse_audit.py", "P6 Runtime Checks", target="url", required=True, timeout=180),
37
+ CheckSpec("Playwright Smoke Test", "skills/webapp-testing/scripts/playwright_runner.py", "P6 Runtime Checks", target="url", timeout=120),
38
+ )
39
+
40
+
41
+ def main() -> int:
42
+ parser = argparse.ArgumentParser(description="Run the fast OpenCode kit validation checklist")
43
+ parser.add_argument("project", nargs="?", default=".", help="Project path to validate")
44
+ parser.add_argument("--url", help="Running application URL for Lighthouse and Playwright")
45
+ parser.add_argument("--skip-runtime", action="store_true", help="Skip URL-based runtime checks")
46
+ parser.add_argument("--stop-on-fail", action="store_true", help="Stop after the first failed check")
47
+ parser.add_argument("--report", type=Path, help="Write a machine-readable JSON report")
48
+ args = parser.parse_args()
49
+
50
+ project = Path(args.project).resolve()
51
+ if not project.is_dir():
52
+ parser.error(f"Project directory does not exist: {project}")
53
+
54
+ try:
55
+ toolkit_root = locate_toolkit_root(project, __file__)
56
+ except FileNotFoundError as exc:
57
+ parser.error(str(exc))
58
+
59
+ started = datetime.now(timezone.utc)
60
+ CONSOLE.header("AG KIT - FAST CHECKLIST")
61
+ print(f"Project: {project}\nToolkit: {toolkit_root}\nURL: {args.url or 'not provided'}")
62
+
63
+ specs = list(CORE_CHECKS)
64
+ if not args.skip_runtime:
65
+ specs.extend(URL_CHECKS)
66
+ results = execute_suite(specs, toolkit_root, project, args.url, args.stop_on_fail)
67
+ success = print_summary("CHECKLIST SUMMARY", results, started)
68
+ if args.report:
69
+ write_report(args.report.resolve(), project, toolkit_root, results, started)
70
+ print(f"Report: {args.report.resolve()}")
71
+ return 0 if success else 1
72
+
73
+
74
+ if __name__ == "__main__":
75
+ raise SystemExit(main())
@@ -0,0 +1,238 @@
1
+ #!/usr/bin/env python3
2
+ """Build deterministic AG Kit component and runtime metadata."""
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import json
7
+ import re
8
+ from pathlib import Path
9
+ from typing import Any
10
+
11
+ try:
12
+ import yaml # type: ignore
13
+ except ImportError: # pragma: no cover
14
+ yaml = None
15
+
16
+ SEMVER_RE = re.compile(r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z.-]+))?(?:\+([0-9A-Za-z.-]+))?$")
17
+
18
+
19
+ def extract_frontmatter(path: Path) -> str:
20
+ text = path.read_text("utf-8", errors="replace")
21
+ if not text.startswith("---\n"):
22
+ raise ValueError(f"Missing YAML frontmatter: {path}")
23
+ end = text.find("\n---\n", 4)
24
+ if end < 0:
25
+ raise ValueError(f"Unterminated YAML frontmatter: {path}")
26
+ return text[4:end]
27
+
28
+
29
+ def _fallback_frontmatter(raw: str) -> dict[str, Any]:
30
+ data: dict[str, Any] = {}
31
+ for line in raw.splitlines():
32
+ if not line or line[0].isspace() or line.lstrip().startswith("#"):
33
+ continue
34
+ match = re.match(r"^([A-Za-z0-9_-]+):\s*(.*)$", line)
35
+ if match:
36
+ key, value = match.groups()
37
+ data[key] = value.strip().strip('"\'')
38
+ return data
39
+
40
+
41
+ def load_frontmatter(path: Path) -> dict[str, Any]:
42
+ raw = extract_frontmatter(path)
43
+ if yaml is not None:
44
+ loaded = yaml.safe_load(raw)
45
+ if not isinstance(loaded, dict):
46
+ raise ValueError(f"Frontmatter must be a mapping: {path}")
47
+ return dict(loaded)
48
+ return _fallback_frontmatter(raw)
49
+
50
+
51
+ def normalize_list(value: object) -> list[str]:
52
+ if isinstance(value, list):
53
+ return [str(item).strip() for item in value if str(item).strip()]
54
+ if isinstance(value, str):
55
+ return [item.strip() for item in value.split(",") if item.strip()]
56
+ return []
57
+
58
+
59
+ def is_semver(value: object) -> bool:
60
+ return isinstance(value, str) and SEMVER_RE.fullmatch(value) is not None
61
+
62
+
63
+ def compatible_range(version: str) -> str:
64
+ match = SEMVER_RE.fullmatch(version)
65
+ if not match:
66
+ raise ValueError(f"Invalid SemVer: {version}")
67
+ return version if int(match.group(1)) == 0 else f"^{version}"
68
+
69
+
70
+ def version_satisfies(version: str, constraint: str) -> bool:
71
+ match = SEMVER_RE.fullmatch(version)
72
+ if not match:
73
+ return False
74
+ current = tuple(int(match.group(i)) for i in range(1, 4))
75
+ if constraint.startswith("^"):
76
+ base_match = SEMVER_RE.fullmatch(constraint[1:])
77
+ if not base_match:
78
+ return False
79
+ base = tuple(int(base_match.group(i)) for i in range(1, 4))
80
+ if base[0] > 0:
81
+ return current >= base and current[0] == base[0]
82
+ if base[1] > 0:
83
+ return current >= base and current[:2] == base[:2]
84
+ return current == base
85
+ return constraint == version
86
+
87
+
88
+ def _relative(root: Path, path: Path) -> str:
89
+ return path.relative_to(root).as_posix()
90
+
91
+
92
+ def _runtime_manifest(root: Path) -> dict[str, Any]:
93
+ path = root / "antigravity.json"
94
+ if not path.is_file():
95
+ raise ValueError("Missing Antigravity runtime contract: antigravity.json")
96
+ data = json.loads(path.read_text("utf-8"))
97
+ if data.get("runtime") != "antigravity":
98
+ raise ValueError("antigravity.json runtime must be 'antigravity'")
99
+ return {
100
+ "path": "antigravity.json",
101
+ "schemaVersion": data.get("schemaVersion"),
102
+ "requiredCliCommands": data.get("requiredCliCommands", []),
103
+ "phases": data.get("phases", {}),
104
+ }
105
+
106
+
107
+ def build_manifest(root: Path) -> dict[str, Any]:
108
+ root = root.resolve()
109
+ kit_version = (root / "VERSION").read_text("utf-8").strip()
110
+
111
+ skills: dict[str, dict[str, Any]] = {}
112
+ for path in sorted((root / "skills").glob("*/SKILL.md")):
113
+ data = load_frontmatter(path)
114
+ name = path.parent.name
115
+ version = str(data.get("version", ""))
116
+ skills[name] = {
117
+ "path": _relative(root, path),
118
+ "version": version,
119
+ "allowedTools": normalize_list(data.get("allowed-tools")),
120
+ "scripts": sorted(_relative(root, item) for item in path.parent.glob("scripts/*.py")),
121
+ }
122
+
123
+ agents: dict[str, dict[str, Any]] = {}
124
+ for path in sorted((root / "agent").glob("*.md")):
125
+ data = load_frontmatter(path)
126
+ dependencies: dict[str, str] = {}
127
+ for skill_name in normalize_list(data.get("skills")):
128
+ skill_version = str(skills.get(skill_name, {}).get("version", "0.0.0"))
129
+ dependencies[skill_name] = compatible_range(skill_version) if is_semver(skill_version) else skill_version
130
+ agents[path.stem] = {
131
+ "path": _relative(root, path),
132
+ "version": str(data.get("version", "")),
133
+ "model": str(data.get("model", "inherit")),
134
+ "tools": normalize_list(data.get("tools")),
135
+ "requires": {"skills": dependencies},
136
+ }
137
+
138
+ workflows: dict[str, dict[str, Any]] = {}
139
+ for path in sorted((root / "workflows").glob("*.md")):
140
+ data = load_frontmatter(path)
141
+ workflows[path.stem] = {
142
+ "path": _relative(root, path),
143
+ "version": str(data.get("version", "")),
144
+ "requires": {
145
+ "agents": normalize_list(data.get("requires_agents")),
146
+ "skills": normalize_list(data.get("requires_skills")),
147
+ },
148
+ "artifactOutputs": normalize_list(data.get("artifact_outputs")),
149
+ }
150
+
151
+ rules: dict[str, dict[str, Any]] = {}
152
+ for path in sorted((root / "rules").glob("*.md")):
153
+ data = load_frontmatter(path)
154
+ rules[path.stem] = {
155
+ "path": _relative(root, path),
156
+ "version": str(data.get("version", "")),
157
+ "priority": str(data.get("priority", "")),
158
+ "trigger": str(data.get("trigger", "")),
159
+ }
160
+
161
+ return {
162
+ "$schema": "schemas/manifest.schema.json",
163
+ "schemaVersion": "1.0.0",
164
+ "kitVersion": kit_version,
165
+ "contracts": {
166
+ "antigravityRuntime": "1.0.0",
167
+ "componentApi": "1.0.0",
168
+ "memorySchema": "1.0.0",
169
+ "rulesApi": "1.0.0",
170
+ "workflowApi": "1.0.0",
171
+ },
172
+ "support": {
173
+ "primary": "Google Antigravity",
174
+ "official": ["Google Antigravity"],
175
+ "bestEffort": ["Gemini CLI", "other Markdown-compatible agent tools"],
176
+ "portableFormat": True,
177
+ },
178
+ "runtimes": {"antigravity": _runtime_manifest(root)},
179
+ "agents": agents,
180
+ "skills": skills,
181
+ "workflows": workflows,
182
+ "rules": rules,
183
+ }
184
+
185
+
186
+ def canonical_json(data: object) -> str:
187
+ return json.dumps(data, indent=2, ensure_ascii=False, sort_keys=True) + "\n"
188
+
189
+
190
+ def component_files(root: Path) -> list[Path]:
191
+ """Return every managed source file covered by the integrity lock."""
192
+ root = root.resolve()
193
+ files: list[Path] = []
194
+ for name in (
195
+ "VERSION",
196
+ "README.md",
197
+ "ARCHITECTURE.md",
198
+ "CHANGELOG.md",
199
+ "antigravity.json",
200
+ "hooks.json",
201
+ "mcp_config.json",
202
+ ):
203
+ path = root / name
204
+ if path.is_file():
205
+ files.append(path)
206
+ for directory in ("agent", "skills", "workflows", "rules", "memory", "hooks", "schemas", "scripts"):
207
+ base = root / directory
208
+ if not base.is_dir():
209
+ continue
210
+ for path in base.rglob("*"):
211
+ if not path.is_file() or "__pycache__" in path.parts or path.suffix == ".pyc":
212
+ continue
213
+ files.append(path)
214
+ return sorted({path.resolve() for path in files})
215
+
216
+
217
+ def sha256_file(path: Path) -> str:
218
+ digest = hashlib.sha256()
219
+ with path.open("rb") as handle:
220
+ for chunk in iter(lambda: handle.read(65536), b""):
221
+ digest.update(chunk)
222
+ return digest.hexdigest()
223
+
224
+
225
+ def build_lock(root: Path, manifest: dict[str, Any]) -> dict[str, Any]:
226
+ root = root.resolve()
227
+ hashes = {
228
+ path.relative_to(root).as_posix(): sha256_file(path)
229
+ for path in component_files(root)
230
+ if path.name != "manifest.lock.json"
231
+ }
232
+ return {
233
+ "$schema": "schemas/manifest-lock.schema.json",
234
+ "schemaVersion": "1.0.0",
235
+ "kitVersion": manifest["kitVersion"],
236
+ "manifestSha256": hashlib.sha256(canonical_json(manifest).encode("utf-8")).hexdigest(),
237
+ "components": hashes,
238
+ }
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env python3
2
+ """Generate a maintainable Mermaid dependency graph from manifest.json."""
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ from pathlib import Path
7
+
8
+ from component_registry import build_manifest
9
+
10
+
11
+ def node_id(prefix: str, name: str) -> str:
12
+ return prefix + "_" + name.replace("-", "_")
13
+
14
+
15
+ def render(root: Path) -> str:
16
+ manifest = build_manifest(root)
17
+ lines = [
18
+ "# AG Kit Dependency Graph",
19
+ "",
20
+ "> Generated by `.opencode/scripts/dependency_graph.py`. Do not edit manually.",
21
+ "",
22
+ f"Kit version: `{manifest['kitVersion']}` · {len(manifest['agents'])} agents · {len(manifest['skills'])} skills · {len(manifest['workflows'])} workflows",
23
+ "",
24
+ "```mermaid",
25
+ "flowchart LR",
26
+ " subgraph Workflows",
27
+ ]
28
+ for name in manifest["workflows"]:
29
+ lines.append(f' {node_id("W", name)}["/{name}"]')
30
+ lines.extend([" end", " subgraph Agents"])
31
+ for name in manifest["agents"]:
32
+ lines.append(f' {node_id("A", name)}["{name}"]')
33
+ lines.extend([" end", " subgraph Skills"])
34
+ for name in manifest["skills"]:
35
+ lines.append(f' {node_id("S", name)}["{name}"]')
36
+ lines.append(" end")
37
+
38
+ for workflow, data in manifest["workflows"].items():
39
+ for agent in data["requires"]["agents"]:
40
+ lines.append(f" {node_id('W', workflow)} --> {node_id('A', agent)}")
41
+ for skill in data["requires"]["skills"]:
42
+ lines.append(f" {node_id('W', workflow)} -.-> {node_id('S', skill)}")
43
+ for agent, data in manifest["agents"].items():
44
+ for skill in data["requires"]["skills"]:
45
+ lines.append(f" {node_id('A', agent)} --> {node_id('S', skill)}")
46
+ lines.extend(["```", "", "## Contracts", ""])
47
+ for key, value in manifest["contracts"].items():
48
+ lines.append(f"- `{key}`: `{value}`")
49
+ lines.append("")
50
+ return "\n".join(lines)
51
+
52
+
53
+ def main() -> int:
54
+ parser = argparse.ArgumentParser(description="Generate AG Kit dependency graph")
55
+ parser.add_argument("path", nargs="?", default=None, help="Path to .agents")
56
+ parser.add_argument("--check", action="store_true", help="Fail when DEPENDENCY_GRAPH.md is stale")
57
+ args = parser.parse_args()
58
+ root = Path(args.path).resolve() if args.path else Path(__file__).resolve().parents[1]
59
+ output = root / "DEPENDENCY_GRAPH.md"
60
+ expected = render(root)
61
+ if args.check:
62
+ if not output.is_file() or output.read_text("utf-8") != expected:
63
+ print("DEPENDENCY_GRAPH.md is stale")
64
+ return 1
65
+ print("Dependency graph is synchronized.")
66
+ return 0
67
+ output.write_text(expected, "utf-8")
68
+ print(f"Wrote {output}")
69
+ return 0
70
+
71
+
72
+ if __name__ == "__main__":
73
+ raise SystemExit(main())
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env python3
2
+ """Generate or verify the AG Kit component registry and lock file."""
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import json
7
+ from pathlib import Path
8
+
9
+ from component_registry import build_lock, build_manifest, canonical_json
10
+
11
+
12
+ def check_file(path: Path, expected: str) -> bool:
13
+ return path.is_file() and path.read_text("utf-8") == expected
14
+
15
+
16
+ def main() -> int:
17
+ parser = argparse.ArgumentParser(description="Generate AG Kit manifest.json and manifest.lock.json")
18
+ parser.add_argument("path", nargs="?", default=None, help="Path to .agents")
19
+ parser.add_argument("--check", action="store_true", help="Fail when generated files are stale")
20
+ args = parser.parse_args()
21
+
22
+ root = Path(args.path).resolve() if args.path else Path(__file__).resolve().parents[1]
23
+ manifest = build_manifest(root)
24
+ manifest_text = canonical_json(manifest)
25
+ lock = build_lock(root, manifest)
26
+ lock_text = canonical_json(lock)
27
+ outputs = [(root / "manifest.json", manifest_text), (root / "manifest.lock.json", lock_text)]
28
+
29
+ if args.check:
30
+ stale = [path.name for path, expected in outputs if not check_file(path, expected)]
31
+ if stale:
32
+ print("Stale generated registry files: " + ", ".join(stale))
33
+ return 1
34
+ print("Component registry is synchronized.")
35
+ return 0
36
+
37
+ for path, content in outputs:
38
+ path.write_text(content, "utf-8")
39
+ print(f"Wrote {path}")
40
+ return 0
41
+
42
+
43
+ if __name__ == "__main__":
44
+ raise SystemExit(main())