@automagik/genie 3.260323.2 → 3.260403.1

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 (497) hide show
  1. package/.claude/commands/level-up.md +2 -2
  2. package/.claude/settings.json +44 -0
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/.genie/agents/metrics-updater/AGENT.md +29 -0
  5. package/.genie/agents/metrics-updater/runs.jsonl +17 -0
  6. package/.genie/agents/metrics-updater/state.json +10 -0
  7. package/.genie/agents/metrics-updater/tools/batch-commit.sh +38 -0
  8. package/.genie/agents/metrics-updater/tools/cached-fetch.sh +86 -0
  9. package/.genie/agents/metrics-updater/tools/commit-formatter.sh +27 -0
  10. package/.genie/agents/metrics-updater/tools/fast-parse.py +92 -0
  11. package/.genie/agents/metrics-updater/tools/generate-tools.py +419 -0
  12. package/.genie/agents/metrics-updater/tools/github-api.sh +100 -0
  13. package/.genie/agents/metrics-updater/tools/parse-metrics.py +195 -0
  14. package/.genie/agents/metrics-updater/tools/perf-analyzer.py +248 -0
  15. package/.genie/agents/metrics-updater/tools/run-metrics.sh +326 -0
  16. package/.genie/agents/metrics-updater/tools/self-refine.sh +133 -0
  17. package/.genie/agents/metrics-updater/tools/update-readme.py +106 -0
  18. package/.genie/qa/framework/cross-repo-specs.md +12 -0
  19. package/.genie/qa/framework/domain-discovery.md +14 -0
  20. package/.genie/qa/framework/results-isolation.md +13 -0
  21. package/.genie/qa/lifecycle/agent-lifecycle.md +13 -0
  22. package/.genie/qa/lifecycle/idle-detection.md +13 -0
  23. package/.genie/qa/messaging/mailbox-delivery.md +12 -0
  24. package/.genie/qa/messaging/multi-agent-comm.md +14 -0
  25. package/.genie/qa/messaging/round-trip-response.md +13 -0
  26. package/.genie/qa/messaging/send-full-id.md +12 -0
  27. package/.genie/qa/observability/log-filter-type.md +14 -0
  28. package/.genie/qa/observability/log-follow-events.md +13 -0
  29. package/.genie/qa/observability/log-static.md +13 -0
  30. package/.genie/qa/observability/nats-streaming.md +13 -0
  31. package/.genie/snapshot.sql.gz +0 -0
  32. package/.github/workflows/ci.yml +2 -2
  33. package/.github/workflows/version.yml +23 -6
  34. package/.rlmx/CRITERIA.md +15 -0
  35. package/.rlmx/SYSTEM.md +89 -0
  36. package/.rlmx/TOOLS.md +27 -0
  37. package/.rlmx/rlmx.yaml +99 -0
  38. package/CLAUDE.md +102 -10
  39. package/Makefile +10 -1
  40. package/README.md +108 -234
  41. package/dist/genie.js +2728 -216
  42. package/git-cliff/CHANGELOG.md +7 -0
  43. package/install.sh +19 -8
  44. package/knip.json +31 -3
  45. package/package.json +21 -10
  46. package/packages/genie-app/bun.lock +260 -0
  47. package/packages/genie-app/components.ts +16 -0
  48. package/packages/genie-app/index.html +28 -0
  49. package/packages/genie-app/lib/StatusBar.tsx +141 -0
  50. package/packages/genie-app/lib/ipc.ts +44 -0
  51. package/packages/genie-app/lib/keyboard.ts +91 -0
  52. package/packages/genie-app/lib/theme.ts +70 -0
  53. package/packages/genie-app/lib/types.ts +186 -0
  54. package/packages/genie-app/lib/useKeyboardNav.ts +57 -0
  55. package/packages/genie-app/manifest.ts +99 -0
  56. package/packages/genie-app/package.json +32 -0
  57. package/packages/genie-app/src/App.tsx +98 -0
  58. package/packages/genie-app/src/main.tsx +11 -0
  59. package/packages/genie-app/src-backend/index.ts +146 -0
  60. package/packages/genie-app/src-backend/ipc.ts +153 -0
  61. package/packages/genie-app/src-backend/pg-bridge.ts +380 -0
  62. package/packages/genie-app/src-backend/pty.ts +339 -0
  63. package/packages/genie-app/src-backend/workspace.ts +124 -0
  64. package/packages/genie-app/src-tauri/Cargo.lock +5111 -0
  65. package/packages/genie-app/src-tauri/Cargo.toml +20 -0
  66. package/packages/genie-app/src-tauri/build.rs +3 -0
  67. package/packages/genie-app/src-tauri/capabilities/default.json +6 -0
  68. package/packages/genie-app/src-tauri/icons/128x128.png +0 -0
  69. package/packages/genie-app/src-tauri/icons/128x128@2x.png +0 -0
  70. package/packages/genie-app/src-tauri/icons/32x32.png +0 -0
  71. package/packages/genie-app/src-tauri/icons/64x64.png +0 -0
  72. package/packages/genie-app/src-tauri/icons/Square107x107Logo.png +0 -0
  73. package/packages/genie-app/src-tauri/icons/Square142x142Logo.png +0 -0
  74. package/packages/genie-app/src-tauri/icons/Square150x150Logo.png +0 -0
  75. package/packages/genie-app/src-tauri/icons/Square284x284Logo.png +0 -0
  76. package/packages/genie-app/src-tauri/icons/Square30x30Logo.png +0 -0
  77. package/packages/genie-app/src-tauri/icons/Square310x310Logo.png +0 -0
  78. package/packages/genie-app/src-tauri/icons/Square44x44Logo.png +0 -0
  79. package/packages/genie-app/src-tauri/icons/Square71x71Logo.png +0 -0
  80. package/packages/genie-app/src-tauri/icons/Square89x89Logo.png +0 -0
  81. package/packages/genie-app/src-tauri/icons/StoreLogo.png +0 -0
  82. package/packages/genie-app/src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml +5 -0
  83. package/packages/genie-app/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png +0 -0
  84. package/packages/genie-app/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png +0 -0
  85. package/packages/genie-app/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png +0 -0
  86. package/packages/genie-app/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png +0 -0
  87. package/packages/genie-app/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png +0 -0
  88. package/packages/genie-app/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png +0 -0
  89. package/packages/genie-app/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png +0 -0
  90. package/packages/genie-app/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png +0 -0
  91. package/packages/genie-app/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png +0 -0
  92. package/packages/genie-app/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png +0 -0
  93. package/packages/genie-app/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png +0 -0
  94. package/packages/genie-app/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  95. package/packages/genie-app/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png +0 -0
  96. package/packages/genie-app/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png +0 -0
  97. package/packages/genie-app/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  98. package/packages/genie-app/src-tauri/icons/android/values/ic_launcher_background.xml +4 -0
  99. package/packages/genie-app/src-tauri/icons/icon.icns +0 -0
  100. package/packages/genie-app/src-tauri/icons/icon.ico +0 -0
  101. package/packages/genie-app/src-tauri/icons/icon.png +0 -0
  102. package/packages/genie-app/src-tauri/icons/ios/AppIcon-20x20@1x.png +0 -0
  103. package/packages/genie-app/src-tauri/icons/ios/AppIcon-20x20@2x-1.png +0 -0
  104. package/packages/genie-app/src-tauri/icons/ios/AppIcon-20x20@2x.png +0 -0
  105. package/packages/genie-app/src-tauri/icons/ios/AppIcon-20x20@3x.png +0 -0
  106. package/packages/genie-app/src-tauri/icons/ios/AppIcon-29x29@1x.png +0 -0
  107. package/packages/genie-app/src-tauri/icons/ios/AppIcon-29x29@2x-1.png +0 -0
  108. package/packages/genie-app/src-tauri/icons/ios/AppIcon-29x29@2x.png +0 -0
  109. package/packages/genie-app/src-tauri/icons/ios/AppIcon-29x29@3x.png +0 -0
  110. package/packages/genie-app/src-tauri/icons/ios/AppIcon-40x40@1x.png +0 -0
  111. package/packages/genie-app/src-tauri/icons/ios/AppIcon-40x40@2x-1.png +0 -0
  112. package/packages/genie-app/src-tauri/icons/ios/AppIcon-40x40@2x.png +0 -0
  113. package/packages/genie-app/src-tauri/icons/ios/AppIcon-40x40@3x.png +0 -0
  114. package/packages/genie-app/src-tauri/icons/ios/AppIcon-512@2x.png +0 -0
  115. package/packages/genie-app/src-tauri/icons/ios/AppIcon-60x60@2x.png +0 -0
  116. package/packages/genie-app/src-tauri/icons/ios/AppIcon-60x60@3x.png +0 -0
  117. package/packages/genie-app/src-tauri/icons/ios/AppIcon-76x76@1x.png +0 -0
  118. package/packages/genie-app/src-tauri/icons/ios/AppIcon-76x76@2x.png +0 -0
  119. package/packages/genie-app/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png +0 -0
  120. package/packages/genie-app/src-tauri/src/main.rs +165 -0
  121. package/packages/genie-app/src-tauri/tauri.conf.json +32 -0
  122. package/packages/genie-app/tsconfig.json +20 -0
  123. package/packages/genie-app/views/activity/ui/ActivityView.tsx +429 -0
  124. package/packages/genie-app/views/agents/ui/AgentsView.tsx +536 -0
  125. package/packages/genie-app/views/dashboard/ui/DashboardView.tsx +371 -0
  126. package/packages/genie-app/views/shared/EmptyState.tsx +25 -0
  127. package/packages/genie-app/views/shared/ErrorBoundary.tsx +76 -0
  128. package/packages/genie-app/views/shared/LoadingState.tsx +23 -0
  129. package/packages/genie-app/views/shared/StatusBar.tsx +94 -0
  130. package/packages/genie-app/views/tasks/ui/TasksView.tsx +404 -0
  131. package/packages/genie-app/views/terminal/ui/TerminalPane.tsx +123 -0
  132. package/packages/genie-app/views/terminal/ui/TerminalView.tsx +244 -0
  133. package/packages/genie-app/views/wizard/ui/WizardView.tsx +269 -0
  134. package/packages/genie-app/vite.config.ts +14 -0
  135. package/plugins/genie/.claude-plugin/plugin.json +1 -1
  136. package/plugins/genie/README.md +1 -3
  137. package/plugins/genie/agents/council/AGENTS.md +32 -40
  138. package/plugins/genie/agents/council--architect/AGENTS.md +11 -22
  139. package/plugins/genie/agents/council--benchmarker/AGENTS.md +11 -21
  140. package/plugins/genie/agents/council--deployer/AGENTS.md +12 -23
  141. package/plugins/genie/agents/council--ergonomist/AGENTS.md +11 -22
  142. package/plugins/genie/agents/council--measurer/AGENTS.md +11 -22
  143. package/plugins/genie/agents/council--operator/AGENTS.md +11 -22
  144. package/plugins/genie/agents/council--questioner/AGENTS.md +12 -22
  145. package/plugins/genie/agents/council--sentinel/AGENTS.md +11 -22
  146. package/plugins/genie/agents/council--simplifier/AGENTS.md +12 -23
  147. package/plugins/genie/agents/council--tracer/AGENTS.md +11 -44
  148. package/plugins/genie/agents/engineer/AGENTS.md +73 -11
  149. package/plugins/genie/agents/fix/AGENTS.md +12 -2
  150. package/plugins/genie/agents/pm/AGENTS.md +46 -41
  151. package/plugins/genie/agents/qa/AGENTS.md +49 -1
  152. package/plugins/genie/agents/reviewer/AGENTS.md +41 -15
  153. package/plugins/genie/agents/team-lead/AGENTS.md +76 -23
  154. package/plugins/genie/agents/team-lead/HEARTBEAT.md +3 -0
  155. package/plugins/genie/genie.ts +2 -3
  156. package/plugins/genie/hooks/hooks.json +10 -0
  157. package/plugins/genie/index.ts +1 -1
  158. package/plugins/genie/package.json +1 -1
  159. package/plugins/genie/references/dispatch-contract.md +0 -23
  160. package/plugins/genie/rules/genie-orchestration.md +28 -0
  161. package/plugins/genie/scripts/first-run-check.cjs +24 -11
  162. package/plugins/genie/scripts/orchestration-guard.cjs +70 -0
  163. package/plugins/genie/scripts/session-context.cjs +1 -1
  164. package/plugins/genie/scripts/smart-install.js +18 -3
  165. package/scripts/build-app.ts +50 -0
  166. package/scripts/postinstall-tmux.js +123 -0
  167. package/scripts/smart-install.js +85 -17
  168. package/scripts/tmux/genie.tmux.conf +20 -12
  169. package/scripts/tmux/osc52-copy.sh +16 -0
  170. package/scripts/tmux/tui-tmux.conf +42 -0
  171. package/scripts/version.ts +6 -10
  172. package/skills/brain/SKILL.md +212 -119
  173. package/skills/brainstorm/SKILL.md +64 -7
  174. package/skills/council/SKILL.md +188 -109
  175. package/skills/council/members/config.md +44 -0
  176. package/skills/council/members/routing.md +32 -0
  177. package/skills/council/templates/report.md +71 -0
  178. package/skills/docs/SKILL.md +20 -1
  179. package/skills/dream/SKILL.md +44 -10
  180. package/skills/fix/SKILL.md +46 -2
  181. package/skills/genie/SKILL.md +71 -126
  182. package/skills/genie/reference/lifecycle.md +65 -0
  183. package/skills/genie-hacks/SKILL.md +626 -0
  184. package/skills/learn/SKILL.md +30 -0
  185. package/skills/pm/SKILL.md +395 -0
  186. package/skills/report/SKILL.md +65 -1
  187. package/skills/review/SKILL.md +46 -1
  188. package/skills/trace/SKILL.md +45 -2
  189. package/skills/wish/SKILL.md +29 -0
  190. package/skills/wizard/SKILL.md +160 -0
  191. package/skills/work/SKILL.md +117 -19
  192. package/src/__tests__/events.test.ts +50 -184
  193. package/src/__tests__/resume.test.ts +301 -0
  194. package/src/__tests__/tmux-config.test.ts +122 -0
  195. package/src/db/migrations/001_core.sql +176 -0
  196. package/src/db/migrations/002_task_lifecycle.sql +371 -0
  197. package/src/db/migrations/003_projects.sql +46 -0
  198. package/src/db/migrations/004_clean_test_artifacts.sql +66 -0
  199. package/src/db/migrations/005_pg_state.sql +193 -0
  200. package/src/db/migrations/006_fix_agents_schema.sql +73 -0
  201. package/src/db/migrations/007_observability.sql +56 -0
  202. package/src/db/migrations/007_reconcile_mailbox_team_chat.sql +121 -0
  203. package/src/db/migrations/008_boards.sql +201 -0
  204. package/src/db/migrations/009_app_store.sql +65 -0
  205. package/src/db/migrations/010_runtime_events.sql +38 -0
  206. package/src/db/migrations/010_session_capture_v2.sql +97 -0
  207. package/src/db/migrations/011_data_model_v5.sql +116 -0
  208. package/src/db/migrations/012_executor_model.sql +205 -0
  209. package/src/db/migrations/013_external_linking.sql +4 -0
  210. package/src/db/migrations/014_comms_protocol.sql +31 -0
  211. package/src/db/migrations/015_agent_archived_state.sql +40 -0
  212. package/src/db/migrations/015_archive_lifecycle.sql +37 -0
  213. package/src/db/migrations/016_team_spawner.sql +5 -0
  214. package/src/db/migrations/017_wishes_table.sql +18 -0
  215. package/src/db/migrations/018_drop_app_store.sql +4 -0
  216. package/src/db/migrations/019_retention.sql +15 -0
  217. package/src/db/migrations/020_agent_metadata.sql +8 -0
  218. package/src/genie-commands/__tests__/session.test.ts +83 -9
  219. package/src/genie-commands/__tests__/update.test.ts +49 -0
  220. package/src/genie-commands/doctor.ts +111 -4
  221. package/src/genie-commands/session.ts +250 -87
  222. package/src/genie-commands/setup.ts +40 -0
  223. package/src/genie-commands/update.ts +165 -35
  224. package/src/genie.ts +340 -10
  225. package/src/hooks/__tests__/dispatch.test.ts +66 -1
  226. package/src/hooks/__tests__/inject.test.ts +30 -1
  227. package/src/hooks/handlers/__tests__/auto-spawn.test.ts +73 -0
  228. package/src/hooks/handlers/auto-spawn.ts +27 -2
  229. package/src/hooks/handlers/identity-inject.ts +6 -3
  230. package/src/hooks/handlers/orchestration-guard.ts +64 -0
  231. package/src/hooks/handlers/runtime-emit.ts +139 -0
  232. package/src/hooks/index.ts +136 -15
  233. package/src/hooks/inject.ts +34 -6
  234. package/src/hooks/resolve-agent-name.ts +58 -0
  235. package/src/hooks/types.ts +9 -0
  236. package/src/lib/__tests__/edge-cases-stability.test.ts +530 -0
  237. package/src/lib/__tests__/mailbox.test.ts +223 -179
  238. package/src/lib/agent-directory.test.ts +225 -293
  239. package/src/lib/agent-directory.ts +203 -199
  240. package/src/lib/agent-identity-sync.test.ts +288 -0
  241. package/src/lib/agent-registry.test.ts +595 -359
  242. package/src/lib/agent-registry.ts +479 -260
  243. package/src/lib/agent-sync.ts +362 -0
  244. package/src/lib/assignment-registry.test.ts +363 -0
  245. package/src/lib/assignment-registry.ts +86 -0
  246. package/src/lib/audit.test.ts +233 -0
  247. package/src/lib/audit.ts +309 -0
  248. package/src/lib/auto-approve-engine.test.ts +53 -116
  249. package/src/lib/auto-approve-engine.ts +14 -87
  250. package/src/lib/board-service.test.ts +336 -0
  251. package/src/lib/board-service.ts +540 -0
  252. package/src/lib/brief.test.ts +154 -0
  253. package/src/lib/brief.ts +305 -0
  254. package/src/lib/builtin-agents.test.ts +4 -5
  255. package/src/lib/builtin-agents.ts +2 -28
  256. package/src/lib/claude-logs.test.ts +71 -0
  257. package/src/lib/claude-logs.ts +21 -2
  258. package/src/lib/claude-native-teams.test.ts +418 -0
  259. package/src/lib/claude-native-teams.ts +298 -9
  260. package/src/lib/claude-settings.ts +42 -1
  261. package/src/lib/codex-logs.ts +1 -1
  262. package/src/lib/context-enrichment.test.ts +21 -0
  263. package/src/lib/context-enrichment.ts +120 -0
  264. package/src/lib/cron.test.ts +113 -0
  265. package/src/lib/cron.ts +207 -0
  266. package/src/lib/db-backup.test.ts +105 -0
  267. package/src/lib/db-backup.ts +162 -0
  268. package/src/lib/db-migrations.ts +168 -0
  269. package/src/lib/db.test.ts +415 -0
  270. package/src/lib/db.ts +551 -0
  271. package/src/lib/ensure-tmux.ts +179 -0
  272. package/src/lib/event-router.test.ts +44 -0
  273. package/src/lib/event-router.ts +309 -0
  274. package/src/lib/executor-registry.test.ts +967 -0
  275. package/src/lib/executor-registry.ts +207 -0
  276. package/src/lib/executor-types.ts +314 -0
  277. package/src/lib/export-format.ts +85 -0
  278. package/src/lib/frontmatter.test.ts +285 -0
  279. package/src/lib/frontmatter.ts +107 -0
  280. package/src/lib/idle-timeout.test.ts +92 -95
  281. package/src/lib/idle-timeout.ts +40 -43
  282. package/src/lib/import-order.ts +81 -0
  283. package/src/lib/inbox-watcher.test.ts +253 -0
  284. package/src/lib/inbox-watcher.ts +157 -0
  285. package/src/lib/mailbox.ts +164 -73
  286. package/src/lib/omni-registration.ts +188 -0
  287. package/src/lib/orchestrator/state-detector.ts +3 -11
  288. package/src/lib/otel-receiver.test.ts +151 -0
  289. package/src/lib/otel-receiver.ts +386 -0
  290. package/src/lib/pg-seed.test.ts +459 -0
  291. package/src/lib/pg-seed.ts +468 -0
  292. package/src/lib/protocol-router-spawn.test.ts +137 -0
  293. package/src/lib/protocol-router-spawn.ts +284 -52
  294. package/src/lib/protocol-router.test.ts +449 -70
  295. package/src/lib/protocol-router.ts +203 -219
  296. package/src/lib/provider-adapters.test.ts +128 -0
  297. package/src/lib/provider-adapters.ts +92 -5
  298. package/src/lib/providers/app-pty.ts +227 -0
  299. package/src/lib/providers/claude-code.test.ts +311 -0
  300. package/src/lib/providers/claude-code.ts +302 -0
  301. package/src/lib/providers/codex.test.ts +219 -0
  302. package/src/lib/providers/codex.ts +109 -0
  303. package/src/lib/providers/registry.test.ts +73 -0
  304. package/src/lib/providers/registry.ts +49 -0
  305. package/src/lib/qa-parser.ts +249 -0
  306. package/src/lib/qa-runner.test.ts +240 -0
  307. package/src/lib/qa-runner.ts +721 -0
  308. package/src/lib/qa-state.test.ts +319 -0
  309. package/src/lib/qa-state.ts +165 -0
  310. package/src/lib/routing-header.test.ts +204 -0
  311. package/src/lib/routing-header.ts +133 -0
  312. package/src/lib/run-spec.test.ts +177 -0
  313. package/src/lib/run-spec.ts +178 -0
  314. package/src/lib/runtime-events-thread.test.ts +96 -0
  315. package/src/lib/runtime-events.test.ts +224 -0
  316. package/src/lib/runtime-events.ts +304 -0
  317. package/src/lib/scheduler-daemon.test.ts +1580 -0
  318. package/src/lib/scheduler-daemon.ts +1542 -0
  319. package/src/lib/service-registry.test.ts +89 -0
  320. package/src/lib/service-registry.ts +107 -0
  321. package/src/lib/session-backfill.ts +235 -0
  322. package/src/lib/session-capture.ts +714 -0
  323. package/src/lib/session-filewatch.ts +155 -0
  324. package/src/lib/spawn-command.test.ts +187 -5
  325. package/src/lib/spawn-command.ts +62 -2
  326. package/src/lib/table-detect.ts +46 -0
  327. package/src/lib/target-resolver.test.ts +903 -2
  328. package/src/lib/target-resolver.ts +259 -77
  329. package/src/lib/task-checkout-deps.test.ts +92 -0
  330. package/src/lib/task-close-merged.test.ts +233 -0
  331. package/src/lib/task-close-merged.ts +241 -0
  332. package/src/lib/task-service.test.ts +1203 -0
  333. package/src/lib/task-service.ts +1858 -0
  334. package/src/lib/team-auto-spawn.ts +38 -13
  335. package/src/lib/team-chat.test.ts +128 -102
  336. package/src/lib/team-chat.ts +40 -52
  337. package/src/lib/team-lead-command.test.ts +164 -0
  338. package/src/lib/team-lead-command.ts +73 -5
  339. package/src/lib/team-manager.test.ts +286 -199
  340. package/src/lib/team-manager.ts +323 -99
  341. package/src/lib/template-service.test.ts +245 -0
  342. package/src/lib/template-service.ts +227 -0
  343. package/src/lib/term-format.ts +68 -0
  344. package/src/lib/test-db.ts +160 -0
  345. package/src/lib/tmux-alive.test.ts +59 -0
  346. package/src/lib/tmux-resolve.test.ts +144 -0
  347. package/src/lib/tmux-wrapper.ts +32 -1
  348. package/src/lib/tmux.test.ts +135 -0
  349. package/src/lib/tmux.ts +239 -52
  350. package/src/lib/transcript-normalizer.test.ts +659 -0
  351. package/src/lib/transcript-normalizer.ts +548 -0
  352. package/src/lib/transcript-types.ts +146 -0
  353. package/src/lib/unified-log.test.ts +595 -0
  354. package/src/lib/unified-log.ts +387 -0
  355. package/src/lib/wish-resolve.test.ts +108 -0
  356. package/src/lib/wish-resolve.ts +124 -0
  357. package/src/lib/wish-state.test.ts +345 -18
  358. package/src/lib/wish-state.ts +433 -126
  359. package/src/lib/wish-sync.test.ts +141 -0
  360. package/src/lib/wish-sync.ts +182 -0
  361. package/src/lib/workspace.test.ts +116 -0
  362. package/src/lib/workspace.ts +159 -0
  363. package/src/templates/AGENTS.md +22 -0
  364. package/src/templates/HEARTBEAT.md +17 -0
  365. package/src/templates/SOUL.md +5 -0
  366. package/src/templates/index.ts +70 -0
  367. package/src/term-commands/__tests__/dispatch-slug.test.ts +86 -0
  368. package/src/term-commands/agent/answer.ts +22 -0
  369. package/src/term-commands/agent/brief.ts +50 -0
  370. package/src/term-commands/agent/directory.ts +162 -0
  371. package/src/term-commands/agent/inbox.ts +123 -0
  372. package/src/term-commands/agent/index.ts +46 -0
  373. package/src/term-commands/agent/kill.ts +22 -0
  374. package/src/term-commands/agent/list.ts +24 -0
  375. package/src/term-commands/agent/log.ts +155 -0
  376. package/src/term-commands/agent/register.ts +125 -0
  377. package/src/term-commands/agent/resume.ts +23 -0
  378. package/src/term-commands/agent/send.ts +233 -0
  379. package/src/term-commands/agent/show.ts +81 -0
  380. package/src/term-commands/agent/spawn.ts +37 -0
  381. package/src/term-commands/agent/stop.ts +22 -0
  382. package/src/term-commands/agents.test.ts +183 -0
  383. package/src/term-commands/agents.ts +879 -88
  384. package/src/term-commands/app.ts +81 -0
  385. package/src/term-commands/approve.test.ts +13 -96
  386. package/src/term-commands/approve.ts +32 -63
  387. package/src/term-commands/audit-events.ts +484 -0
  388. package/src/term-commands/board.ts +843 -0
  389. package/src/term-commands/brain.ts +158 -0
  390. package/src/term-commands/brief.ts +64 -0
  391. package/src/term-commands/daemon.test.ts +112 -0
  392. package/src/term-commands/daemon.ts +528 -0
  393. package/src/term-commands/db.ts +276 -0
  394. package/src/term-commands/dir.test.ts +32 -0
  395. package/src/term-commands/dir.ts +150 -58
  396. package/src/term-commands/dispatch.test.ts +36 -4
  397. package/src/term-commands/dispatch.ts +175 -84
  398. package/src/term-commands/events.ts +0 -149
  399. package/src/term-commands/exec/index.ts +160 -0
  400. package/src/term-commands/export.ts +399 -0
  401. package/src/term-commands/history.ts +25 -40
  402. package/src/term-commands/import.test.ts +91 -0
  403. package/src/term-commands/import.ts +348 -0
  404. package/src/term-commands/init-bootstrap.test.ts +102 -0
  405. package/src/term-commands/init-flow.test.ts +81 -0
  406. package/src/term-commands/init.test.ts +38 -0
  407. package/src/term-commands/init.ts +177 -0
  408. package/src/term-commands/log.test.ts +323 -0
  409. package/src/term-commands/log.ts +399 -0
  410. package/src/term-commands/metrics.ts +218 -0
  411. package/src/term-commands/msg.test.ts +69 -69
  412. package/src/term-commands/msg.ts +533 -167
  413. package/src/term-commands/notify.ts +129 -0
  414. package/src/term-commands/project.ts +208 -0
  415. package/src/term-commands/qa.test.ts +59 -0
  416. package/src/term-commands/qa.ts +502 -0
  417. package/src/term-commands/release.ts +71 -0
  418. package/src/term-commands/schedule.test.ts +93 -0
  419. package/src/term-commands/schedule.ts +533 -0
  420. package/src/term-commands/serve.test.ts +35 -0
  421. package/src/term-commands/serve.ts +789 -0
  422. package/src/term-commands/sessions.ts +324 -0
  423. package/src/term-commands/state.test.ts +355 -0
  424. package/src/term-commands/state.ts +325 -21
  425. package/src/term-commands/tag.ts +74 -0
  426. package/src/term-commands/task/board.ts +13 -0
  427. package/src/term-commands/task/index.ts +40 -0
  428. package/src/term-commands/task/project.ts +13 -0
  429. package/src/term-commands/task/release-mgmt.ts +69 -0
  430. package/src/term-commands/task/reset.ts +28 -0
  431. package/src/term-commands/task/status.ts +127 -0
  432. package/src/term-commands/task/type.ts +13 -0
  433. package/src/term-commands/task.ts +913 -0
  434. package/src/term-commands/team/index.ts +9 -0
  435. package/src/term-commands/team.test.ts +153 -69
  436. package/src/term-commands/team.ts +259 -46
  437. package/src/term-commands/template.ts +84 -0
  438. package/src/term-commands/type.ts +178 -0
  439. package/src/tui/app.tsx +70 -0
  440. package/src/tui/components/ContextMenu.tsx +133 -0
  441. package/src/tui/components/Nav.tsx +669 -0
  442. package/src/tui/components/QuitDialog.tsx +56 -0
  443. package/src/tui/components/SystemStats.tsx +166 -0
  444. package/src/tui/components/TreeNode.tsx +177 -0
  445. package/src/tui/context-menu-items.ts +65 -0
  446. package/src/tui/db.ts +76 -0
  447. package/src/tui/diagnostics.ts +239 -0
  448. package/src/tui/index.ts +20 -0
  449. package/src/tui/initial-agent.test.ts +76 -0
  450. package/src/tui/initial-agent.ts +22 -0
  451. package/src/tui/render.tsx +26 -0
  452. package/src/tui/session-tree.test.ts +583 -0
  453. package/src/tui/session-tree.ts +362 -0
  454. package/src/tui/theme.ts +50 -0
  455. package/src/tui/tmux.ts +142 -0
  456. package/src/tui/tree.ts +33 -0
  457. package/src/tui/tsconfig.json +9 -0
  458. package/src/tui/types.ts +71 -0
  459. package/src/types/genie-config.ts +25 -2
  460. package/tsconfig.json +3 -1
  461. package/.genie/state/v3-fixes-release.json +0 -26
  462. package/openclaw.plugin.json +0 -12
  463. package/plugins/genie/agents/council--architect.md +0 -78
  464. package/plugins/genie/agents/council--benchmarker.md +0 -101
  465. package/plugins/genie/agents/council--deployer.md +0 -78
  466. package/plugins/genie/agents/council--ergonomist.md +0 -77
  467. package/plugins/genie/agents/council--measurer.md +0 -89
  468. package/plugins/genie/agents/council--operator.md +0 -77
  469. package/plugins/genie/agents/council--questioner.md +0 -79
  470. package/plugins/genie/agents/council--sentinel.md +0 -81
  471. package/plugins/genie/agents/council--simplifier.md +0 -77
  472. package/plugins/genie/agents/council--tracer.md +0 -157
  473. package/plugins/genie/agents/council.md +0 -81
  474. package/plugins/genie/agents/docs.md +0 -83
  475. package/plugins/genie/agents/engineer.md +0 -92
  476. package/plugins/genie/agents/fix.md +0 -80
  477. package/plugins/genie/agents/learn/AGENTS.md +0 -87
  478. package/plugins/genie/agents/learn.md +0 -87
  479. package/plugins/genie/agents/pm.md +0 -137
  480. package/plugins/genie/agents/qa.md +0 -118
  481. package/plugins/genie/agents/refactor.md +0 -96
  482. package/plugins/genie/agents/reviewer.md +0 -103
  483. package/plugins/genie/agents/team-lead.md +0 -71
  484. package/plugins/genie/agents/trace.md +0 -81
  485. package/src/lib/batch-manager.test.ts +0 -565
  486. package/src/lib/batch-manager.ts +0 -358
  487. package/src/lib/event-aggregator.test.ts +0 -415
  488. package/src/lib/event-aggregator.ts +0 -192
  489. package/src/lib/file-lock.ts +0 -111
  490. package/src/lib/genie-dir.ts +0 -67
  491. package/src/lib/local-tasks.test.ts +0 -361
  492. package/src/lib/local-tasks.ts +0 -296
  493. package/src/lib/protocol-router-session.test.ts +0 -631
  494. package/src/lib/team-shortcut.test.ts +0 -141
  495. package/src/lib/team-shortcut.ts +0 -61
  496. package/src/lib/wish-editor.test.ts +0 -288
  497. package/src/lib/wish-editor.ts +0 -224
@@ -107,7 +107,7 @@ Silently scan the user's environment. Do NOT ask permission for each check. Just
107
107
  - Cron jobs, launchd services, or systemd services calling Claude on a schedule?
108
108
  - Background agents running 24/7 (pm2, systemd)?
109
109
  - Autonomous loop scripts (PRD + test suite patterns)?
110
- - Agent orchestration configs (Agent Teams, Gastown, OpenClaw)?
110
+ - Agent orchestration configs (Agent Teams, Gastown)?
111
111
  - Evidence of agents managing other agents?
112
112
  ```
113
113
 
@@ -541,7 +541,7 @@ Show ONLY the next level transition. Do not dump all 10 levels. Focus is everyth
541
541
  - Agents talk to each other through shared files. One agent writes a task list, another picks up items, does the work, and marks them done. They coordinate through your project folder and git branches, like coworkers using a shared task board.
542
542
 
543
543
  4. **Always-on assistants**
544
- - OpenClaw: an open source framework that runs Claude as a persistent assistant you can message via WhatsApp or Telegram. You text it like a colleague. It's always available, always has your context.
544
+ - Persistent agent frameworks that run Claude as an always-available assistant you can message via WhatsApp or Telegram. You text it like a colleague. It's always available, always has your context.
545
545
 
546
546
  **Community tip:** Level 10 is experimental. The community is actively building and testing these patterns. Things break. The value is in the learning. Very few people are here, and those who are spend significant time managing the systems. This is not "set and forget." This is "build, monitor, iterate."
547
547
 
@@ -10,6 +10,50 @@
10
10
  "timeout": 5
11
11
  }
12
12
  ]
13
+ },
14
+ {
15
+ "matcher": "*",
16
+ "hooks": [
17
+ {
18
+ "type": "command",
19
+ "command": "genie hook dispatch",
20
+ "timeout": 5
21
+ }
22
+ ]
23
+ }
24
+ ],
25
+ "PostToolUse": [
26
+ {
27
+ "matcher": "*",
28
+ "hooks": [
29
+ {
30
+ "type": "command",
31
+ "command": "genie hook dispatch",
32
+ "timeout": 5
33
+ }
34
+ ]
35
+ }
36
+ ],
37
+ "UserPromptSubmit": [
38
+ {
39
+ "hooks": [
40
+ {
41
+ "type": "command",
42
+ "command": "genie hook dispatch",
43
+ "timeout": 5
44
+ }
45
+ ]
46
+ }
47
+ ],
48
+ "Stop": [
49
+ {
50
+ "hooks": [
51
+ {
52
+ "type": "command",
53
+ "command": "genie hook dispatch",
54
+ "timeout": 5
55
+ }
56
+ ]
13
57
  }
14
58
  ]
15
59
  }
@@ -10,7 +10,7 @@
10
10
  "plugins": [
11
11
  {
12
12
  "name": "genie",
13
- "version": "3.260322.1",
13
+ "version": "4.260402.20",
14
14
  "source": "./plugins/genie",
15
15
  "description": "Human-AI partnership for Claude Code. Share a terminal, orchestrate workers, evolve together. Brainstorm ideas, wish them into plans, make with parallel agents, ship as one team. A coding genie that grows with your project."
16
16
  }
@@ -0,0 +1,29 @@
1
+ # metrics-updater Agent
2
+
3
+ Fetches live GitHub metrics daily and updates the README metrics table.
4
+
5
+ ## Metrics Collected
6
+
7
+ - **Releases/day** — releases published in the last 24h
8
+ - **Avg merge time** — mean lead time (created→merged) for PRs closed in last 7d
9
+ - **SHIP rate** — merged / total closed PRs in last 7d (%)
10
+ - **Merged PRs (7d)** — count of merged PRs in the rolling 7-day window
11
+
12
+ ## README Markers
13
+
14
+ The agent updates the block between `<!-- METRICS:START -->` and `<!-- METRICS:END -->` in README.md.
15
+
16
+ If markers are missing, insert the table after the badges block, before `## What is Genie?`.
17
+
18
+ ## Commit Convention
19
+
20
+ ```
21
+ chore: update live metrics (X/day, Yh avg, Z% SHIP)
22
+ ```
23
+
24
+ Push to `dev` branch only. Never push to `main`.
25
+
26
+ ## State Files
27
+
28
+ - `state.json` — last successful metrics run
29
+ - `runs.jsonl` — append-only log of every run
@@ -0,0 +1,17 @@
1
+ {"timestamp":"2026-03-24T22:44:08Z","duration_ms":4685,"api_calls":2,"tools_generated":0,"tools_available":5,"errors":[],"status":"success","fallback":false,"slowest_step":"unknown","steps":[],"metrics":{"releases_per_day":0,"avg_bugfix_time_hours":2.0,"ship_rate_pct":100.0,"parallel_agents":3,"updated":"2026-03-24"}}
2
+ {"timestamp": "2026-03-24T22:54:18Z", "duration_ms": 4579, "api_calls": 2, "tools_generated": 0, "tools_available": 10, "errors": [], "status": "success", "fallback": false, "slowest_step": "fetch_releases", "steps": [{"name": "load_state", "duration_ms": 31}, {"name": "fetch_releases", "duration_ms": 3023}, {"name": "fetch_prs", "duration_ms": 1218}, {"name": "count_agents", "duration_ms": 65}, {"name": "parse_metrics", "duration_ms": 126}, {"name": "update_readme", "duration_ms": 51}, {"name": "update_state", "duration_ms": 35}, {"name": "commit", "duration_ms": 4}], "metrics": {"releases_per_day": 0, "avg_bugfix_time_hours": 1.9, "ship_rate_pct": 100.0, "parallel_agents": 3, "updated": "2026-03-24"}}
3
+ {"timestamp": "2026-03-24T22:57:05Z", "duration_ms": 4292, "api_calls": 2, "tools_generated": 0, "tools_available": 10, "errors": [], "status": "success", "fallback": false, "slowest_step": "fetch_releases", "steps": [{"name": "load_state", "duration_ms": 35}, {"name": "fetch_releases", "duration_ms": 2778}, {"name": "fetch_prs", "duration_ms": 1149}, {"name": "count_agents", "duration_ms": 57}, {"name": "parse_metrics", "duration_ms": 118}, {"name": "update_readme", "duration_ms": 48}, {"name": "update_state", "duration_ms": 37}, {"name": "commit", "duration_ms": 45}], "metrics": {"releases_per_day": 0, "avg_bugfix_time_hours": 1.9, "ship_rate_pct": 100.0, "parallel_agents": 3, "updated": "2026-03-24"}}
4
+ {"timestamp": "2026-03-24T22:57:11Z", "duration_ms": 3833, "api_calls": 2, "tools_generated": 0, "tools_available": 10, "errors": [], "status": "no_changes", "fallback": false, "slowest_step": "fetch_releases", "steps": [{"name": "load_state", "duration_ms": 31}, {"name": "fetch_releases", "duration_ms": 2640}, {"name": "fetch_prs", "duration_ms": 872}, {"name": "count_agents", "duration_ms": 53}, {"name": "parse_metrics", "duration_ms": 124}, {"name": "update_readme", "duration_ms": 47}, {"name": "update_state", "duration_ms": 39}, {"name": "commit", "duration_ms": 3}], "metrics": {"releases_per_day": 0, "avg_bugfix_time_hours": 1.9, "ship_rate_pct": 100.0, "parallel_agents": 3, "updated": "2026-03-24"}}
5
+ {"timestamp": "2026-03-24T22:57:17Z", "duration_ms": 4637, "api_calls": 2, "tools_generated": 0, "tools_available": 10, "errors": [], "status": "no_changes", "fallback": false, "slowest_step": "fetch_releases", "steps": [{"name": "load_state", "duration_ms": 31}, {"name": "fetch_releases", "duration_ms": 3344}, {"name": "fetch_prs", "duration_ms": 980}, {"name": "count_agents", "duration_ms": 54}, {"name": "parse_metrics", "duration_ms": 122}, {"name": "update_readme", "duration_ms": 45}, {"name": "update_state", "duration_ms": 33}, {"name": "commit", "duration_ms": 3}], "metrics": {"releases_per_day": 0, "avg_bugfix_time_hours": 1.9, "ship_rate_pct": 100.0, "parallel_agents": 3, "updated": "2026-03-24"}}
6
+ {"timestamp": "2026-03-24T22:57:24Z", "duration_ms": 4067, "api_calls": 2, "tools_generated": 0, "tools_available": 10, "errors": [], "status": "no_changes", "fallback": false, "slowest_step": "fetch_releases", "steps": [{"name": "load_state", "duration_ms": 37}, {"name": "fetch_releases", "duration_ms": 2732}, {"name": "fetch_prs", "duration_ms": 1008}, {"name": "count_agents", "duration_ms": 55}, {"name": "parse_metrics", "duration_ms": 123}, {"name": "update_readme", "duration_ms": 45}, {"name": "update_state", "duration_ms": 38}, {"name": "commit", "duration_ms": 3}], "metrics": {"releases_per_day": 0, "avg_bugfix_time_hours": 1.9, "ship_rate_pct": 100.0, "parallel_agents": 3, "updated": "2026-03-24"}}
7
+ {"timestamp": "2026-03-24T22:57:30Z", "duration_ms": 4728, "api_calls": 2, "tools_generated": 0, "tools_available": 10, "errors": [], "status": "no_changes", "fallback": false, "slowest_step": "fetch_releases", "steps": [{"name": "load_state", "duration_ms": 31}, {"name": "fetch_releases", "duration_ms": 3211}, {"name": "fetch_prs", "duration_ms": 1186}, {"name": "count_agents", "duration_ms": 59}, {"name": "parse_metrics", "duration_ms": 126}, {"name": "update_readme", "duration_ms": 52}, {"name": "update_state", "duration_ms": 34}, {"name": "commit", "duration_ms": 3}], "metrics": {"releases_per_day": 0, "avg_bugfix_time_hours": 1.9, "ship_rate_pct": 100.0, "parallel_agents": 3, "updated": "2026-03-24"}}
8
+ {"timestamp": "2026-03-24T22:57:37Z", "duration_ms": 4374, "api_calls": 2, "tools_generated": 0, "tools_available": 10, "errors": [], "status": "no_changes", "fallback": false, "slowest_step": "fetch_releases", "steps": [{"name": "load_state", "duration_ms": 34}, {"name": "fetch_releases", "duration_ms": 2985}, {"name": "fetch_prs", "duration_ms": 1063}, {"name": "count_agents", "duration_ms": 53}, {"name": "parse_metrics", "duration_ms": 131}, {"name": "update_readme", "duration_ms": 47}, {"name": "update_state", "duration_ms": 34}, {"name": "commit", "duration_ms": 3}], "metrics": {"releases_per_day": 0, "avg_bugfix_time_hours": 1.9, "ship_rate_pct": 100.0, "parallel_agents": 3, "updated": "2026-03-24"}}
9
+ {"timestamp": "2026-03-24T22:57:43Z", "duration_ms": 4201, "api_calls": 2, "tools_generated": 0, "tools_available": 10, "errors": [], "status": "no_changes", "fallback": false, "slowest_step": "fetch_releases", "steps": [{"name": "load_state", "duration_ms": 32}, {"name": "fetch_releases", "duration_ms": 2704}, {"name": "fetch_prs", "duration_ms": 1172}, {"name": "count_agents", "duration_ms": 65}, {"name": "parse_metrics", "duration_ms": 122}, {"name": "update_readme", "duration_ms": 43}, {"name": "update_state", "duration_ms": 35}, {"name": "commit", "duration_ms": 3}], "metrics": {"releases_per_day": 0, "avg_bugfix_time_hours": 1.9, "ship_rate_pct": 100.0, "parallel_agents": 3, "updated": "2026-03-24"}}
10
+ {"timestamp": "2026-03-25T00:03:05Z", "duration_ms": 5882, "api_calls": 2, "tools_generated": 0, "tools_available": 10, "errors": [], "status": "success", "fallback": false, "slowest_step": "fetch_releases", "steps": [{"name": "load_state", "duration_ms": 33}, {"name": "fetch_releases", "duration_ms": 3458}, {"name": "fetch_prs", "duration_ms": 1046}, {"name": "count_agents", "duration_ms": 53}, {"name": "parse_metrics", "duration_ms": 1191}, {"name": "update_readme", "duration_ms": 45}, {"name": "update_state", "duration_ms": 30}, {"name": "commit", "duration_ms": 4}], "metrics": {"releases_per_day": 0, "avg_bugfix_time_hours": 1.7, "ship_rate_pct": 100.0, "loc_changed_24h": 7418, "commits_24h": 66, "prs_24h": 28, "parallel_agents": 3, "updated": "2026-03-25T00:03:04Z"}}
11
+ {"timestamp":"2026-03-25T00:00:00Z","duration_ms":31579683120,"api_calls":3,"tools_generated":1,"errors":0,"metrics":{"releases_24h":0,"avg_merge_time_hours":0.7,"ship_rate_pct":96,"merged_prs_7d":48}}
12
+ {"timestamp":"2026-03-28T00:00:00Z","duration_ms":45000,"api_calls":3,"tools_generated":0,"errors":[],"metrics":{"releases_24h":0,"avg_merge_time_hours":2.9,"ship_rate_pct":94,"merged_prs_7d":47}}
13
+ {"timestamp":"2026-03-29T00:00:00Z","duration_ms":52000,"api_calls":2,"tools_generated":0,"errors":[],"metrics":{"releases_24h":0,"avg_merge_time_hours":3.0,"ship_rate_pct":92,"merged_prs_7d":46}}
14
+ {"timestamp":"2026-03-30T00:00:00Z","duration_ms":5000,"api_calls":3,"tools_generated":0,"errors":0,"metrics":{"releases_24h":0,"releases_per_day":0,"avg_merge_time_hours":0.3,"ship_rate_pct":84,"merged_prs_7d":32,"closed_prs_7d":38}}
15
+ {"timestamp":"2026-03-31T00:00:00Z","duration_ms":5002,"api_calls":2,"tools_generated":4,"errors":0,"metrics":{"releases_24h":0,"merged_prs_7d":35,"avg_merge_time_h":0.3,"ship_rate_pct":85}}
16
+ {"timestamp":"2026-04-01T00:00:00Z","duration_ms":8000,"api_calls":0,"tools_generated":0,"errors":["gh CLI unavailable","GitHub MCP tools not loaded in session"],"status":"failed","fallback":false,"metrics":null}
17
+ {"timestamp":"2026-04-02T00:00:00.000Z","duration_ms":15000,"api_calls":0,"tools_generated":0,"errors":["gh CLI not available","GitHub MCP tools not present in session"],"status":"failed","fallback":false,"metrics":null}
@@ -0,0 +1,10 @@
1
+ {
2
+ "last_run": "2026-04-02T00:00:00.000Z",
3
+ "last_run_status": "failed",
4
+ "last_metrics": {
5
+ "releases_24h": 0,
6
+ "merged_prs_7d": 35,
7
+ "avg_merge_time_h": 0.3,
8
+ "ship_rate_pct": 85
9
+ }
10
+ }
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env bash
2
+ # batch-commit.sh — Optimized commit for metrics updates
3
+ # Auto-generated by generate-tools.py
4
+ # Idempotent: safe to run multiple times, regenerate freely.
5
+ #
6
+ # Usage: bash batch-commit.sh <metrics.json> <repo-root> <state-file>
7
+ #
8
+ # Optimizations:
9
+ # - Single git add for all files
10
+ # - Pre-formatted commit message (no subshell)
11
+ # - Skip if working tree is clean
12
+
13
+ set -euo pipefail
14
+
15
+ METRICS_FILE="${1:?Usage: batch-commit.sh <metrics.json> <repo-root> <state-file>}"
16
+ REPO_ROOT="${2:?}"
17
+ STATE_FILE="${3:?}"
18
+
19
+ cd "$REPO_ROOT"
20
+
21
+ # Skip if no changes
22
+ if git diff --quiet HEAD -- README.md "$STATE_FILE" 2>/dev/null; then
23
+ echo "No changes to commit" >&2
24
+ exit 2
25
+ fi
26
+
27
+ # Read metrics for commit message
28
+ releases=$(python3 -c "import json; print(json.load(open('$METRICS_FILE')).get('releases_per_day', 0))")
29
+ avg_time=$(python3 -c "import json; print(json.load(open('$METRICS_FILE')).get('avg_bugfix_time_hours', 0))")
30
+ ship_rate=$(python3 -c "import json; print(json.load(open('$METRICS_FILE')).get('ship_rate_pct', 0))")
31
+
32
+ COMMIT_MSG="chore: update live metrics (${releases}/day, ${avg_time}h avg, ${ship_rate}% SHIP)"
33
+
34
+ # Single add + commit
35
+ git add README.md "$STATE_FILE"
36
+ git commit -m "$COMMIT_MSG"
37
+
38
+ echo "$COMMIT_MSG"
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env bash
2
+ # cached-fetch.sh — Cached GitHub API fetcher with TTL
3
+ # Auto-generated by generate-tools.py
4
+ # Idempotent: safe to run multiple times, regenerate freely.
5
+ #
6
+ # Usage: source cached-fetch.sh; cached_gh_api <endpoint> [ttl_seconds]
7
+ # Default TTL: 1800s (30 minutes) — daily agent runs don't need real-time data
8
+
9
+ CACHE_DIR="${GENIE_METRICS_CACHE:-/tmp/metrics-updater-cache}"
10
+ DEFAULT_TTL="${GENIE_METRICS_CACHE_TTL:-1800}"
11
+
12
+ mkdir -p "$CACHE_DIR"
13
+
14
+ cached_gh_api() {
15
+ local endpoint="$1"
16
+ local ttl="${2:-$DEFAULT_TTL}"
17
+ local cache_key
18
+ cache_key=$(echo "$endpoint" | md5sum | cut -d' ' -f1)
19
+ local cache_file="$CACHE_DIR/${cache_key}.json"
20
+ local meta_file="$CACHE_DIR/${cache_key}.meta"
21
+
22
+ # Check cache validity
23
+ if [[ -f "$cache_file" && -f "$meta_file" ]]; then
24
+ local cached_at
25
+ cached_at=$(cat "$meta_file" 2>/dev/null || echo 0)
26
+ local now
27
+ now=$(date +%s)
28
+ local age=$((now - cached_at))
29
+
30
+ if (( age < ttl )); then
31
+ echo "[cache] HIT: $endpoint (age=${age}s, ttl=${ttl}s)" >&2
32
+ cat "$cache_file"
33
+ return 0
34
+ fi
35
+ echo "[cache] STALE: $endpoint (age=${age}s, ttl=${ttl}s)" >&2
36
+ else
37
+ echo "[cache] MISS: $endpoint" >&2
38
+ fi
39
+
40
+ # Fetch fresh data
41
+ local response
42
+ if response=$(gh api "$endpoint" --paginate 2>/dev/null); then
43
+ echo "$response" > "$cache_file"
44
+ date +%s > "$meta_file"
45
+ echo "$response"
46
+ return 0
47
+ fi
48
+
49
+ # Fallback to stale cache
50
+ if [[ -f "$cache_file" ]]; then
51
+ echo "[cache] FALLBACK: Using stale cache for $endpoint" >&2
52
+ cat "$cache_file"
53
+ return 0
54
+ fi
55
+
56
+ echo "[cache] FAIL: No data for $endpoint" >&2
57
+ return 1
58
+ }
59
+
60
+ # Warm cache for common endpoints (call at start of run)
61
+ warm_cache() {
62
+ local owner="${1:-automagik-dev}"
63
+ local repo="${2:-genie}"
64
+ echo "[cache] Warming cache for $owner/$repo..." >&2
65
+ cached_gh_api "repos/$owner/$repo/releases" >/dev/null 2>&1 &
66
+ cached_gh_api "repos/$owner/$repo/pulls?state=closed&sort=updated&direction=desc&per_page=100" >/dev/null 2>&1 &
67
+ wait
68
+ echo "[cache] Cache warmed" >&2
69
+ }
70
+
71
+ # Clear expired cache entries
72
+ clean_cache() {
73
+ local max_age="${1:-86400}" # Default: 24h
74
+ local now
75
+ now=$(date +%s)
76
+ for meta in "$CACHE_DIR"/*.meta; do
77
+ [[ -f "$meta" ]] || continue
78
+ local cached_at
79
+ cached_at=$(cat "$meta" 2>/dev/null || echo 0)
80
+ if (( now - cached_at > max_age )); then
81
+ local base="${meta%.meta}"
82
+ rm -f "$base.json" "$meta"
83
+ echo "[cache] Cleaned: $(basename "$base")" >&2
84
+ fi
85
+ done
86
+ }
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env bash
2
+ # commit-formatter.sh — Clean commit message formatter for metrics updates
3
+ # Auto-generated by metrics-updater agent (v1, 2026-03-24)
4
+ # Updated: v2 — includes LoC/commits/PRs in commit message
5
+
6
+ set -euo pipefail
7
+
8
+ # Usage: commit-formatter.sh <metrics_json_file>
9
+ # Reads metrics JSON and outputs a formatted commit message.
10
+
11
+ METRICS_FILE="${1:-}"
12
+
13
+ if [[ -z "$METRICS_FILE" || ! -f "$METRICS_FILE" ]]; then
14
+ echo "Usage: commit-formatter.sh <metrics.json>" >&2
15
+ exit 1
16
+ fi
17
+
18
+ # Extract values
19
+ releases=$(jq -r '.releases_per_day // 0' "$METRICS_FILE")
20
+ avg_time=$(jq -r '.avg_bugfix_time_hours // 0' "$METRICS_FILE")
21
+ ship_rate=$(jq -r '.ship_rate_pct // 0' "$METRICS_FILE")
22
+ loc=$(jq -r '.loc_changed_24h // 0' "$METRICS_FILE")
23
+ commits=$(jq -r '.commits_24h // 0' "$METRICS_FILE")
24
+ prs=$(jq -r '.prs_24h // 0' "$METRICS_FILE")
25
+
26
+ # Format commit message
27
+ echo "chore: update live metrics (${releases}/day, ${avg_time}h avg, ${ship_rate}% SHIP, ${loc} LoC, ${commits} commits, ${prs} PRs)"
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env python3
2
+ """fast-parse.py — Optimized metrics parser with pre-compiled patterns.
3
+
4
+ Auto-generated by generate-tools.py.
5
+ Idempotent: safe to run multiple times, regenerate freely.
6
+
7
+ Differences from parse-metrics.py:
8
+ - Pre-compiled datetime parsing (avoids repeated fromisoformat)
9
+ - Batch processing (single pass over PR data)
10
+ - Early termination (stops counting when past cutoff)
11
+
12
+ Usage:
13
+ python3 fast-parse.py --releases <file> --prs <file> --agents <N> [-o output.json]
14
+ """
15
+
16
+ import json
17
+ import sys
18
+ import argparse
19
+ from datetime import datetime, timedelta, timezone
20
+ from functools import lru_cache
21
+
22
+ NOW = datetime.now(timezone.utc)
23
+ CUTOFF_24H = NOW - timedelta(hours=24)
24
+ CUTOFF_7D = NOW - timedelta(days=7)
25
+
26
+
27
+ def parse_iso(s: str) -> datetime:
28
+ """Fast ISO8601 parsing."""
29
+ return datetime.fromisoformat(s.replace('Z', '+00:00'))
30
+
31
+
32
+ def compute_all_metrics(releases: list, prs: list, parallel_agents: int) -> dict:
33
+ """Single-pass computation of all metrics from raw API data."""
34
+ # Releases in last 24h
35
+ releases_24h = sum(1 for r in releases if parse_iso(r['created_at']) >= CUTOFF_24H)
36
+
37
+ # PR metrics in single pass
38
+ merge_durations = []
39
+ total_merged_7d = 0
40
+ shipped_first = 0
41
+
42
+ for pr in prs:
43
+ merged_at = pr.get('merged_at')
44
+ if not merged_at:
45
+ continue
46
+ merged = parse_iso(merged_at)
47
+ if merged < CUTOFF_7D:
48
+ continue # Past our window — skip
49
+
50
+ total_merged_7d += 1
51
+ created = parse_iso(pr['created_at'])
52
+ merge_durations.append((merged - created).total_seconds() / 3600)
53
+ shipped_first += 1 # v1: all merged = shipped
54
+
55
+ avg_merge = round(sum(merge_durations) / len(merge_durations), 1) if merge_durations else 0.0
56
+ ship_rate = round((shipped_first / total_merged_7d) * 100, 0) if total_merged_7d > 0 else 100.0
57
+
58
+ return {
59
+ 'releases_per_day': releases_24h,
60
+ 'avg_bugfix_time_hours': avg_merge,
61
+ 'ship_rate_pct': ship_rate,
62
+ 'parallel_agents': parallel_agents,
63
+ 'updated': NOW.strftime('%Y-%m-%d'),
64
+ }
65
+
66
+
67
+ def main():
68
+ parser = argparse.ArgumentParser(description='Fast metrics parser')
69
+ parser.add_argument('--releases', required=True, help='Releases JSON file')
70
+ parser.add_argument('--prs', required=True, help='PRs JSON file')
71
+ parser.add_argument('--agents', type=int, default=0, help='Parallel agents count')
72
+ parser.add_argument('--output', '-o', help='Output file (default: stdout)')
73
+
74
+ args = parser.parse_args()
75
+
76
+ with open(args.releases) as f:
77
+ releases = json.load(f)
78
+ with open(args.prs) as f:
79
+ prs = json.load(f)
80
+
81
+ metrics = compute_all_metrics(releases, prs, args.agents)
82
+ output = json.dumps(metrics, indent=2)
83
+
84
+ if args.output:
85
+ with open(args.output, 'w') as f:
86
+ f.write(output + '\n')
87
+ else:
88
+ print(output)
89
+
90
+
91
+ if __name__ == '__main__':
92
+ main()