@moretea-labs/forge 1.5.1 → 1.7.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 (434) hide show
  1. package/AGENTS.md +2 -0
  2. package/CHANGELOG.md +46 -0
  3. package/CLAUDE.md +2 -0
  4. package/DESIGN.md +7 -2
  5. package/README.md +4 -4
  6. package/README.zh-CN.md +2 -2
  7. package/SKILL.md +2 -2
  8. package/THIRD_PARTY_NOTICES.md +1 -1
  9. package/agents/openai.yaml +1 -1
  10. package/assets/hooks/hook-input.sh +11 -8
  11. package/assets/hooks/lib/session-state.sh +10 -7
  12. package/assets/hooks/lib/workflow-state.sh +13 -177
  13. package/assets/hooks/post-tool-observer.sh +8 -2
  14. package/assets/hooks/pre-edit-guard.sh +8 -39
  15. package/assets/hooks/prompt-guard.sh +7 -83
  16. package/assets/hooks/session-start-context.sh +56 -1
  17. package/assets/partials/05-workflow.partial.md +1 -1
  18. package/assets/partials-agents/03-orchestration.partial.md +1 -1
  19. package/assets/plugin-registry.v1.json +54 -3
  20. package/assets/reference-configs/document-generation.md +1 -1
  21. package/assets/reference-configs/harness-overview.md +1 -1
  22. package/assets/reference-configs/hook-operations.md +1 -1
  23. package/assets/reference-configs/sprint-contracts.md +3 -3
  24. package/assets/skill-version.json +2 -2
  25. package/assets/templates/contract.template.md +2 -7
  26. package/assets/templates/helpers/capture-plan.sh +2 -2
  27. package/assets/templates/helpers/check-task-workflow.sh +4 -4
  28. package/assets/templates/helpers/contract-worktree.sh +1 -21
  29. package/assets/templates/helpers/ensure-task-workflow.sh +13 -38
  30. package/assets/templates/helpers/migrate-project-template.sh +22 -45
  31. package/assets/templates/helpers/new-plan.sh +1 -1
  32. package/assets/templates/helpers/plan-to-todo.sh +12 -37
  33. package/assets/templates/helpers/ship-worktrees.sh +2 -29
  34. package/assets/templates/helpers/sprint-backlog.sh +6 -6
  35. package/assets/templates/helpers/verify-contract.sh +1 -111
  36. package/assets/templates/helpers/verify-sprint.sh +3 -180
  37. package/assets/templates/plan.template.md +1 -1
  38. package/assets/templates/review.template.md +9 -34
  39. package/assets/workflow-contract.v1.json +10 -19
  40. package/docs/README.md +10 -10
  41. package/docs/architecture/CURRENT.md +170 -0
  42. package/docs/architecture/EVOLUTION.md +42 -0
  43. package/docs/architecture/current/README.md +4 -156
  44. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +2 -2
  45. package/docs/architecture/decisions/20260823-immediate-controller-relay.md +53 -0
  46. package/docs/architecture/decisions/20260826-browser-runtime-v2.md +73 -0
  47. package/docs/architecture/history/README.md +7 -0
  48. package/docs/architecture/{chatgpt-handoff-facade.md → history/chatgpt-handoff-facade.md} +4 -0
  49. package/docs/architecture/{global-hook-runtime.md → history/global-hook-runtime.md} +7 -3
  50. package/docs/architecture/{ios-semantic-automation-provider-v2.md → history/ios-semantic-automation-provider-v2.md} +6 -2
  51. package/docs/architecture/history.md +3 -34
  52. package/docs/architecture/index.md +15 -98
  53. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
  54. package/docs/architecture/reviews/2026-08-22-semantic-harness-convergence-acceptance.md +39 -0
  55. package/docs/architecture/versions/1.6.md +38 -0
  56. package/docs/architecture/versions/1.7.md +41 -0
  57. package/docs/forge-chatgpt-browser-engine.md +2 -2
  58. package/docs/forge-chatgpt-mcp-setup.md +4 -28
  59. package/docs/forge-chatgpt-supervised-automation.md +3 -3
  60. package/docs/forge-github-issue-launcher.md +1 -1
  61. package/docs/forge-runtime-self-healing-loop.md +1 -1
  62. package/docs/operations/controller-browser-plugin.md +38 -22
  63. package/docs/operations/controller-performance-and-502.md +124 -0
  64. package/docs/operations/controller-reliability-runbook.md +1 -1
  65. package/docs/operations/features.md +3 -3
  66. package/docs/operations/github-repository.md +1 -1
  67. package/docs/operations/homebrew.md +2 -2
  68. package/docs/operations/mcp-tool-exposure.md +5 -3
  69. package/docs/tutorials/01-install-and-start.md +1 -1
  70. package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
  71. package/docs/wiki/Architecture.md +6 -6
  72. package/docs/wiki/Implementation.md +2 -2
  73. package/docs/wiki/Installation.md +1 -1
  74. package/docs/wiki/Integrations.md +2 -2
  75. package/docs/wiki/Quick-Start.md +1 -1
  76. package/docs/wiki/Work-Lifecycle.md +1 -1
  77. package/package.json +29 -10
  78. package/scripts/activate-source-baseline.ts +17 -13
  79. package/scripts/benchmark-background-check-overlap.ts +228 -0
  80. package/scripts/benchmark-mcp-host.sh +117 -0
  81. package/scripts/benchmark-mcp-transport.ts +170 -0
  82. package/scripts/benchmark-quality-harness.ts +146 -0
  83. package/scripts/benchmark-route-session-concurrency.ts +207 -6
  84. package/scripts/benchmark-thin-harness-mcp-e2e.ts +7 -1
  85. package/scripts/benchmark-typescript-navigation.ts +186 -0
  86. package/scripts/benchmark-work-efficiency.ts +334 -0
  87. package/scripts/capture-plan.sh +3 -3
  88. package/scripts/check-agent-tooling.sh +8 -35
  89. package/scripts/check-architecture-sync.sh +17 -86
  90. package/scripts/check-mcp-compatibility.ts +14 -0
  91. package/scripts/check-public-docs.sh +14 -1
  92. package/scripts/check-runtime-architecture.mjs +107 -64
  93. package/scripts/check-stable-baseline.ts +92 -0
  94. package/scripts/check-task-workflow.sh +4 -4
  95. package/scripts/contract-worktree.sh +1 -21
  96. package/scripts/ensure-task-workflow.sh +22 -55
  97. package/scripts/host-temporary-cloud-mcp-e2e.sh +265 -0
  98. package/scripts/install-standalone-recovery.ts +24 -0
  99. package/scripts/lib/project-init-lib.sh +15 -44
  100. package/scripts/migrate-chatgpt-automation-schedules.ts +64 -0
  101. package/scripts/migrate-project-template.sh +23 -1179
  102. package/scripts/new-plan.sh +1 -1
  103. package/scripts/plan-to-todo.sh +11 -36
  104. package/scripts/run-governed-gate.ts +2 -1
  105. package/scripts/ship-worktrees.sh +2 -29
  106. package/scripts/smoke-ios-physical-device.ts +4 -2
  107. package/scripts/smoke-runtime-recovery.ts +1 -35
  108. package/scripts/smoke-schedule-engine.ts +1 -20
  109. package/scripts/sprint-backlog.sh +1 -1
  110. package/scripts/verify-contract.sh +1 -111
  111. package/scripts/verify-forge-runtime.sh +0 -1
  112. package/scripts/verify-sprint.sh +3 -180
  113. package/scripts/workflow-contract.ts +1 -5
  114. package/src/cli/commands/chatgpt.ts +31 -2
  115. package/src/cli/commands/init-hook.ts +3 -3
  116. package/src/cli/commands/mcp.ts +9 -5
  117. package/src/cli/commands/plugin.ts +37 -10
  118. package/src/cli/commands/recovery.ts +25 -3
  119. package/src/cli/commands/runtime.ts +55 -3
  120. package/src/cli/commands/security.ts +12 -1
  121. package/src/cli/commands/setup-profile.ts +31 -21
  122. package/src/cli/controller/check-runner.ts +106 -3
  123. package/src/cli/controller/composite-result.ts +1 -1
  124. package/src/cli/controller/context/focus.ts +51 -0
  125. package/src/cli/controller/context/instruction-context.ts +114 -0
  126. package/src/cli/controller/context/known-paths.ts +76 -0
  127. package/src/cli/controller/context/query-planning.ts +110 -0
  128. package/src/cli/controller/context/rule-resolution.ts +532 -0
  129. package/src/cli/controller/context/source-materializer.ts +278 -0
  130. package/src/cli/controller/context/structural.ts +16 -0
  131. package/src/cli/controller/context/types.ts +286 -0
  132. package/src/cli/controller/context-pack.ts +898 -430
  133. package/src/cli/controller/launch-agents.ts +77 -2
  134. package/src/cli/controller/operational-plan.ts +2 -2
  135. package/src/cli/controller/work-mode.ts +6 -4
  136. package/src/cli/editing/edit-session.ts +60 -7
  137. package/src/cli/github/github.ts +133 -0
  138. package/src/cli/hook/prompt-guard-decision.ts +17 -18
  139. package/src/cli/hook/prompt-intents.ts +1 -1
  140. package/src/cli/installer/managed-entries.ts +15 -1
  141. package/src/cli/local-bridge/console-automations.ts +225 -67
  142. package/src/cli/local-bridge/console-view-models.ts +3 -35
  143. package/src/cli/local-bridge/facade-api.ts +2 -217
  144. package/src/cli/local-bridge/frontend/src/App.tsx +3 -3
  145. package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +153 -3
  146. package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +37 -4
  147. package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +183 -3
  148. package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +1 -1
  149. package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +4 -3
  150. package/src/cli/local-bridge/frontend/src/lib/api.ts +18 -11
  151. package/src/cli/local-bridge/frontend/src/lib/routes.ts +1 -1
  152. package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +1 -1
  153. package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +4 -3
  154. package/src/cli/local-bridge/frontend/src/styles.css +27 -11
  155. package/src/cli/local-bridge/frontend/src/types.ts +8 -7
  156. package/src/cli/local-bridge/job-store.ts +1 -490
  157. package/src/cli/local-bridge/server.ts +29 -532
  158. package/src/cli/local-bridge/ui-dist/app.css +1 -1
  159. package/src/cli/local-bridge/ui-dist/app.js +5101 -4967
  160. package/src/cli/mcp/auth.ts +5 -5
  161. package/src/cli/mcp/instructions.ts +3 -2
  162. package/src/cli/mcp/legacy-tool-service.ts +0 -189
  163. package/src/cli/mcp/multi-repository.ts +16 -5
  164. package/src/cli/mcp/oauth.ts +175 -26
  165. package/src/cli/mcp/paths.ts +8 -2
  166. package/src/cli/mcp/repository-tools.ts +356 -101
  167. package/src/cli/mcp/server.ts +625 -54
  168. package/src/cli/mcp/tool-capability-cache.ts +1 -1
  169. package/src/cli/mcp/toolset-selection.ts +1 -1
  170. package/src/cli/mcp/toolset.ts +42 -5
  171. package/src/cli/mcp/transports/http.ts +125 -15
  172. package/src/cli/mcp/transports/session-registry.ts +67 -5
  173. package/src/cli/mcp/types.ts +3 -3
  174. package/src/cli/repositories/command-classifier.ts +209 -14
  175. package/src/cli/repositories/command-executor.ts +55 -521
  176. package/src/cli/repositories/command-process.ts +108 -0
  177. package/src/cli/repositories/command-scope.ts +99 -41
  178. package/src/cli/repositories/controller-home.ts +7 -8
  179. package/src/cli/repositories/git-command-executor.ts +2 -0
  180. package/src/cli/repositories/locks.ts +53 -16
  181. package/src/cli/repositories/repository-snapshot.ts +121 -0
  182. package/src/cli/repositories/safe-patch.ts +6 -4
  183. package/src/cli/repositories/selected-path-actions.ts +17 -9
  184. package/src/cli/repositories/structured-git.ts +110 -10
  185. package/src/cli/repository/inspector.ts +565 -62
  186. package/src/cli/repository/session-cache.ts +58 -17
  187. package/src/cli/v81-entry.ts +1 -4
  188. package/src/effects/fs-transaction.ts +85 -17
  189. package/src/runtime/context/codegraph-read-provider.ts +233 -2
  190. package/src/runtime/context/codegraph-sidecar.cjs +74 -40
  191. package/src/runtime/context/generic-lsp-provider.ts +355 -0
  192. package/src/runtime/context/lsp-client.ts +283 -0
  193. package/src/runtime/context/semantic-navigation.ts +275 -0
  194. package/src/runtime/context/swift-navigation.ts +565 -0
  195. package/src/runtime/context/typescript-navigation.ts +226 -0
  196. package/src/runtime/control-plane/dispatch-priority.ts +28 -0
  197. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +196 -2
  198. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +86 -24
  199. package/src/runtime/control-plane/execution/execution-identity.ts +65 -14
  200. package/src/runtime/control-plane/execution/session-store.ts +18 -0
  201. package/src/runtime/control-plane/execution/validation.ts +15 -2
  202. package/src/runtime/control-plane/execution/verification-evidence.ts +58 -3
  203. package/src/runtime/control-plane/execution/work-handle-store.ts +27 -2
  204. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +258 -0
  205. package/src/runtime/control-plane/execution/work-remote-delivery.ts +215 -0
  206. package/src/runtime/control-plane/execution/work-task-receipt.ts +54 -11
  207. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +175 -8
  208. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +28 -21
  209. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +87 -9
  210. package/src/runtime/control-plane/facade/capability-registry.ts +129 -25
  211. package/src/runtime/control-plane/facade/controller-round-relay.ts +991 -0
  212. package/src/runtime/control-plane/facade/controller-session-store.ts +144 -14
  213. package/src/runtime/control-plane/facade/goal-workloop-access.ts +9 -2
  214. package/src/runtime/control-plane/facade/goal-workloop.ts +885 -105
  215. package/src/runtime/control-plane/facade/index.ts +1 -0
  216. package/src/runtime/control-plane/facade/plan-contract-store.ts +211 -26
  217. package/src/runtime/control-plane/facade/requirement-board.ts +24 -8
  218. package/src/runtime/control-plane/facade/semantic-admission.ts +205 -0
  219. package/src/runtime/control-plane/facade/suggested-actions.ts +5 -1
  220. package/src/runtime/control-plane/facade/types.ts +55 -11
  221. package/src/runtime/control-plane/facade/work-contract-store.ts +204 -73
  222. package/src/runtime/control-plane/generated-cache-retention.ts +271 -0
  223. package/src/runtime/control-plane/global-scheduler/config.ts +44 -0
  224. package/src/runtime/control-plane/global-scheduler/dispatch-capacity.ts +80 -0
  225. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +46 -0
  226. package/src/runtime/control-plane/global-scheduler/maintenance.ts +145 -0
  227. package/src/runtime/control-plane/global-scheduler/projection-refresh.ts +84 -0
  228. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -3
  229. package/src/runtime/control-plane/global-scheduler/scheduler.ts +273 -542
  230. package/src/runtime/control-plane/global-scheduler/source-scan.ts +59 -0
  231. package/src/runtime/control-plane/global-scheduler/state.ts +88 -0
  232. package/src/runtime/control-plane/global-scheduler/worker-attachment.ts +57 -0
  233. package/src/runtime/control-plane/global-scheduler/worker-exit-decision.ts +38 -0
  234. package/src/runtime/control-plane/global-scheduler/worker-exit-reconciler.ts +175 -0
  235. package/src/runtime/control-plane/global-scheduler/worker-launch.ts +111 -0
  236. package/src/runtime/control-plane/global-scheduler/worker-lifecycle-store.ts +64 -0
  237. package/src/runtime/control-plane/global-scheduler/worker-lifecycle.ts +150 -0
  238. package/src/runtime/control-plane/global-scheduler/worker-process.ts +119 -0
  239. package/src/runtime/control-plane/global-scheduler/worker-stderr.ts +60 -0
  240. package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +50 -0
  241. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +642 -51
  242. package/src/runtime/control-plane/launcher/launch-reservation-store.ts +40 -0
  243. package/src/runtime/control-plane/launcher/thin-launcher.ts +194 -10
  244. package/src/runtime/control-plane/persistence/controller-home-migration.ts +487 -0
  245. package/src/runtime/control-plane/persistence/requirement-store.ts +15 -11
  246. package/src/runtime/control-plane/persistence/sqlite-store.ts +33 -2
  247. package/src/runtime/control-plane/release-retention.ts +62 -2
  248. package/src/runtime/control-plane/routing/route-policy.ts +7 -16
  249. package/src/runtime/control-plane/runtime-status-client.ts +0 -2
  250. package/src/runtime/diagnostics/mcp-timing.ts +19 -0
  251. package/src/runtime/diagnostics/mcp-transport-benchmark.ts +129 -0
  252. package/src/runtime/diagnostics/performance.ts +24 -1
  253. package/src/runtime/evidence/event-ledger.ts +1 -1
  254. package/src/runtime/execution/jobs/store.ts +58 -4
  255. package/src/runtime/execution/jobs/types.ts +1 -1
  256. package/src/runtime/execution/managed-workspace.ts +203 -1
  257. package/src/runtime/execution/process-runtime/check-facade.ts +52 -14
  258. package/src/runtime/execution/process-runtime/check-result.ts +63 -2
  259. package/src/runtime/execution/process-runtime/check-scheduling.ts +114 -0
  260. package/src/runtime/execution/process-runtime/command-facade.ts +346 -40
  261. package/src/runtime/execution/process-runtime/gc.ts +98 -12
  262. package/src/runtime/execution/process-runtime/lightweight-managed.ts +1184 -0
  263. package/src/runtime/execution/process-runtime/persisted-check.ts +57 -6
  264. package/src/runtime/execution/process-runtime/resource-claims.ts +97 -8
  265. package/src/runtime/execution/process-runtime/runtime.ts +59 -4
  266. package/src/runtime/execution/process-runtime/store.ts +7 -0
  267. package/src/runtime/execution/process-runtime/types.ts +2 -0
  268. package/src/runtime/execution/thin-harness/async-process.ts +12 -2
  269. package/src/runtime/execution/thin-harness/search-worker.ts +54 -5
  270. package/src/runtime/execution/workers/executor.ts +0 -48
  271. package/src/runtime/gateway/mcp/execution-tools.ts +1219 -126
  272. package/src/runtime/gateway/mcp/process-tools.ts +83 -37
  273. package/src/runtime/gateway/mcp/router.ts +185 -83
  274. package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +546 -0
  275. package/src/runtime/gateway/mcp/runtime-tools.ts +2555 -1616
  276. package/src/runtime/model-clients/deepseek-adapter.ts +0 -32
  277. package/src/runtime/plugins/app-store-connect-adapter.ts +123 -19
  278. package/src/runtime/plugins/browser-adapter.ts +2925 -318
  279. package/src/runtime/plugins/browser-automation-service.ts +10 -0
  280. package/src/runtime/plugins/browser-handoff-host.ts +6 -31
  281. package/src/runtime/plugins/browser-handoff.ts +92 -5
  282. package/src/runtime/plugins/browser-macos-bridge.ts +586 -45
  283. package/src/runtime/plugins/browser-node-bridge.ts +6 -34
  284. package/src/runtime/plugins/browser-provider-registry.ts +109 -0
  285. package/src/runtime/plugins/browser-runtime-contract.ts +152 -0
  286. package/src/runtime/plugins/browser-runtime.ts +183 -0
  287. package/src/runtime/plugins/browser-session-authority.ts +332 -0
  288. package/src/runtime/plugins/capability-authorization-grants.ts +354 -0
  289. package/src/runtime/plugins/desktop-operator-registration.ts +15 -12
  290. package/src/runtime/plugins/external-adapter.ts +324 -3
  291. package/src/runtime/plugins/external-registration.ts +84 -5
  292. package/src/runtime/plugins/external-unix-socket.ts +7 -1
  293. package/src/runtime/plugins/first-party-registry.ts +4 -2
  294. package/src/runtime/plugins/github-adapter.ts +125 -0
  295. package/src/runtime/plugins/gmail-adapter.ts +28 -2
  296. package/src/runtime/plugins/ios/agent-device-provider.ts +1 -1
  297. package/src/runtime/plugins/ios/agent-device-typed-provider.ts +52 -9
  298. package/src/runtime/plugins/ios/remote-xpc-hid.ts +1171 -0
  299. package/src/runtime/plugins/ios-adapter.ts +106 -16
  300. package/src/runtime/plugins/ios-agent-device.ts +234 -64
  301. package/src/runtime/plugins/ios-physical-device.ts +1143 -392
  302. package/src/runtime/plugins/lightweight-action.ts +153 -0
  303. package/src/runtime/plugins/local-system-adapter.ts +125 -8
  304. package/src/runtime/plugins/macos-capability-broker.ts +55 -9
  305. package/src/runtime/plugins/plugin-action-sidecar.ts +59 -0
  306. package/src/runtime/plugins/plugin-management-adapter.ts +181 -0
  307. package/src/runtime/plugins/resend-adapter.ts +1 -1
  308. package/src/runtime/plugins/store.ts +366 -24
  309. package/src/runtime/plugins/types.ts +39 -2
  310. package/src/runtime/plugins/xiaohongshu-publish.ts +515 -0
  311. package/src/runtime/projections/git-status-sampler.ts +16 -16
  312. package/src/runtime/projections/materialized-view.ts +28 -10
  313. package/src/runtime/recovery/actions.ts +0 -10
  314. package/src/runtime/recovery/classifier.ts +0 -9
  315. package/src/runtime/recovery/maintenance-executor.ts +415 -18
  316. package/src/runtime/recovery/probe.ts +0 -1
  317. package/src/runtime/recovery/types.ts +0 -1
  318. package/src/runtime/root/mcp-transport.ts +180 -10
  319. package/src/runtime/root/package-connector-service.ts +186 -8
  320. package/src/runtime/root/package-runtime-release.ts +143 -17
  321. package/src/runtime/root/package-runtime-service.ts +430 -22
  322. package/src/runtime/root/release-manifest.ts +7 -2
  323. package/src/runtime/root/release-materialize.ts +162 -19
  324. package/src/runtime/root/release-store.ts +48 -11
  325. package/src/runtime/root/runtime.ts +23 -5
  326. package/src/runtime/root/service.ts +100 -27
  327. package/src/runtime/root/types.ts +2 -0
  328. package/src/runtime/safe-tooling/index.ts +0 -1
  329. package/src/runtime/safe-tooling/ios-development.ts +321 -63
  330. package/src/runtime/safe-tooling/types.ts +0 -30
  331. package/src/runtime/shared/trusted-executable.ts +62 -0
  332. package/src/runtime/shared/trusted-node-executable.ts +48 -0
  333. package/src/runtime/standalone-recovery/core.ts +702 -94
  334. package/src/runtime/standalone-recovery/entry.ts +99 -23
  335. package/src/runtime/standalone-recovery/installer.ts +19 -3
  336. package/src/runtime/standalone-recovery/service-labels.ts +2 -0
  337. package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +160 -0
  338. package/src/runtime/workflow/schedules/browser-probe.ts +258 -0
  339. package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +40 -0
  340. package/src/runtime/workflow/schedules/engine.ts +509 -80
  341. package/src/runtime/workflow/schedules/github-issue-watch.ts +158 -0
  342. package/src/runtime/workflow/schedules/settlement.ts +48 -4
  343. package/src/runtime/workflow/schedules/store.ts +131 -10
  344. package/src/runtime/workflow/schedules/types.ts +6 -3
  345. package/src/runtime/workflow/schedules/work-continuation.ts +120 -34
  346. package/src/testing/test-governance.ts +8 -40
  347. package/assets/reference-configs/heartbeat-triage.md +0 -57
  348. package/assets/templates/helpers/harness-trace-grade.sh +0 -150
  349. package/assets/templates/helpers/heartbeat-triage.sh +0 -361
  350. package/assets/templates/helpers/maintenance-triage.sh +0 -167
  351. package/bin/forge-desktop-helper.mjs +0 -204
  352. package/docs/architecture/current/approved-target-architecture.zh-CN.md +0 -1501
  353. package/docs/architecture/current/architecture-invariants.md +0 -331
  354. package/docs/architecture/current/automation-and-schedule-engine.md +0 -453
  355. package/docs/architecture/current/codegraph-context-provider.md +0 -226
  356. package/docs/architecture/current/control-plane-authority-inventory.md +0 -94
  357. package/docs/architecture/current/controller-repository-decoupling.md +0 -148
  358. package/docs/architecture/current/dispatch-and-agent-strategy.md +0 -354
  359. package/docs/architecture/current/entity-model.md +0 -592
  360. package/docs/architecture/current/external-plugin-governance.md +0 -396
  361. package/docs/architecture/current/failure-recovery.md +0 -447
  362. package/docs/architecture/current/governance.md +0 -213
  363. package/docs/architecture/current/human-interaction-plane.md +0 -87
  364. package/docs/architecture/current/implementation-status.md +0 -128
  365. package/docs/architecture/current/job-and-run-lifecycle.md +0 -413
  366. package/docs/architecture/current/legacy-governance.md +0 -58
  367. package/docs/architecture/current/local-workspace-target-grants.md +0 -70
  368. package/docs/architecture/current/migration-roadmap.md +0 -105
  369. package/docs/architecture/current/multi-repository-execution.md +0 -371
  370. package/docs/architecture/current/operations-runbook.md +0 -45
  371. package/docs/architecture/current/peer-supercontroller-runtime.md +0 -32
  372. package/docs/architecture/current/personal-assistant-plugin-baseline.md +0 -206
  373. package/docs/architecture/current/repository-access-modes.md +0 -102
  374. package/docs/architecture/current/route-policy.md +0 -15
  375. package/docs/architecture/current/route-session-concurrency.md +0 -85
  376. package/docs/architecture/current/runtime-architecture-simplification.md +0 -214
  377. package/docs/architecture/current/runtime-directory-map.md +0 -49
  378. package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +0 -85
  379. package/docs/architecture/current/scheduler-and-resource-claims.md +0 -422
  380. package/docs/architecture/current/session-aware-execution-and-authorization.md +0 -77
  381. package/docs/architecture/current/system-overview.md +0 -144
  382. package/docs/architecture/current/target-requirements-traceability.md +0 -202
  383. package/docs/architecture/current/thin-harness-governance-policy.md +0 -32
  384. package/docs/architecture/current/thin-harness-v1.md +0 -311
  385. package/docs/architecture/current/verification-and-release-gates.md +0 -391
  386. package/docs/forge-autonomous-goal-loop.md +0 -9
  387. package/docs/forge-provider-configuration.md +0 -7
  388. package/docs/operations/chatgpt-personal-assistant-runtime.md +0 -83
  389. package/docs/operations/controller-desktop-plugin.md +0 -112
  390. package/docs/operations/gmail-assistant-routines.md +0 -186
  391. package/docs/operations/personal-assistant-operator-guide.md +0 -61
  392. package/docs/operations/provider-configuration.md +0 -31
  393. package/scripts/harness-trace-grade.sh +0 -150
  394. package/scripts/heartbeat-triage.sh +0 -361
  395. package/scripts/maintenance-triage.sh +0 -167
  396. package/src/cli/local-bridge/frontend/src/features/settings/SettingsView.tsx +0 -2
  397. package/src/cli/repositories/goal-registry.ts +0 -239
  398. package/src/runtime/assistant/action-proposals.ts +0 -279
  399. package/src/runtime/assistant/intent.ts +0 -395
  400. package/src/runtime/assistant/model-provider.ts +0 -460
  401. package/src/runtime/assistant/openapi.ts +0 -223
  402. package/src/runtime/assistant/policy.ts +0 -89
  403. package/src/runtime/assistant/readiness.ts +0 -258
  404. package/src/runtime/assistant/routine-runtime.ts +0 -477
  405. package/src/runtime/assistant/schedule-binding.ts +0 -171
  406. package/src/runtime/assistant/standing-grants.ts +0 -375
  407. package/src/runtime/assistant/store.ts +0 -243
  408. package/src/runtime/assistant/types.ts +0 -135
  409. package/src/runtime/control-plane/goal-loop/config-facade.ts +0 -700
  410. package/src/runtime/control-plane/goal-loop/config-store.ts +0 -570
  411. package/src/runtime/control-plane/goal-loop/config-types.ts +0 -213
  412. package/src/runtime/control-plane/goal-loop/executor-router.ts +0 -109
  413. package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +0 -149
  414. package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +0 -304
  415. package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +0 -1001
  416. package/src/runtime/control-plane/goal-loop/handoff-packet.ts +0 -160
  417. package/src/runtime/control-plane/goal-loop/index.ts +0 -13
  418. package/src/runtime/control-plane/goal-loop/local-tools.ts +0 -290
  419. package/src/runtime/control-plane/goal-loop/policy-gates.ts +0 -203
  420. package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +0 -93
  421. package/src/runtime/control-plane/goal-loop/provider-registry.ts +0 -545
  422. package/src/runtime/control-plane/goal-loop/types.ts +0 -378
  423. package/src/runtime/control-plane/startup-recovery.ts +0 -198
  424. package/src/runtime/gateway/mcp/resource-policy.ts +0 -186
  425. package/src/runtime/personal-assistant/gmail-triage-manager.ts +0 -231
  426. package/src/runtime/personal-assistant/reporting-runtime.ts +0 -344
  427. package/src/runtime/personal-assistant/triage-runtime.ts +0 -748
  428. package/src/runtime/plugins/desktop-adapter.ts +0 -374
  429. package/src/runtime/safe-tooling/browser-safe.ts +0 -133
  430. package/src/runtime/workflow/findings/store.ts +0 -204
  431. package/src/runtime/workflow/findings/types.ts +0 -58
  432. package/src/runtime/workflow/portfolio/engine.ts +0 -20
  433. package/src/runtime/workflow/portfolio/store.ts +0 -185
  434. package/src/runtime/workflow/portfolio/types.ts +0 -29
@@ -26,30 +26,24 @@ export type TestModule = (typeof TEST_MODULES)[number];
26
26
  export type TestResource = (typeof TEST_RESOURCES)[number];
27
27
  export type TestGate = 'affected' | 'core' | 'integration' | 'infrastructure' | 'fault' | 'full';
28
28
 
29
+ /**
30
+ * Acceptance evidence is the default. Tests must protect externally observable
31
+ * contracts, migrations/rollback, failure injection, security boundaries, or
32
+ * a recorded production incident. Do not add tests for private helpers,
33
+ * implementation payloads, copy, enum order, or mock-only lifecycles.
34
+ */
35
+ export const TEST_GOVERNANCE_POLICY = 'acceptance-first-no-internal-unit-tests' as const;
36
+
29
37
  export interface TestManifestEntry {
30
38
  module: TestModule;
31
39
  resource: TestResource;
32
40
  smoke?: boolean;
33
41
  }
34
42
 
35
- export interface TestBudgetPolicy {
36
- maxTestFiles: number;
37
- maxTestLines: number;
38
- maxPureFiles: number;
39
- maxTempIsolatedFiles: number;
40
- maxProcessTreeFiles: number;
41
- maxGitWorktreeFiles: number;
42
- maxFixedPortFiles: number;
43
- maxRuntimeSingletonFiles: number;
44
- maxControllerHomeIsolatedFiles: number;
45
- maxDestructiveFiles: number;
46
- }
47
-
48
43
  export interface TestManifest {
49
44
  version: 1;
50
45
  modules: TestModule[];
51
46
  resources: TestResource[];
52
- policy: TestBudgetPolicy;
53
47
  pathModuleRules: Array<{ prefix: string; modules: TestModule[] }>;
54
48
  tests: Record<string, TestManifestEntry>;
55
49
  }
@@ -232,32 +226,6 @@ export function validateTestManifest(repoRoot: string, manifest = loadTestManife
232
226
  if (!TEST_RESOURCES.includes(entry.resource)) errors.push(`${file}: invalid resource ${String(entry.resource)}`);
233
227
  }
234
228
  if (!Object.values(manifest.tests).some((entry) => entry.smoke)) errors.push('manifest has no core smoke tests');
235
- const resourceCounts = Object.values(manifest.tests).reduce<Record<string, number>>((counts, entry) => {
236
- counts[entry.resource] = (counts[entry.resource] ?? 0) + 1;
237
- return counts;
238
- }, {});
239
- const testLines = declaredFiles.reduce((total, file) => {
240
- try {
241
- return total + readFileSync(resolve(repoRoot, file), 'utf8').split('\n').length;
242
- } catch (_error) {
243
- return total;
244
- }
245
- }, 0);
246
- const budgetChecks: Array<[string, number, number | undefined]> = [
247
- ['maxTestFiles', declaredFiles.length, manifest.policy?.maxTestFiles],
248
- ['maxTestLines', testLines, manifest.policy?.maxTestLines],
249
- ['maxPureFiles', resourceCounts.pure ?? 0, manifest.policy?.maxPureFiles],
250
- ['maxTempIsolatedFiles', resourceCounts['temp-isolated'] ?? 0, manifest.policy?.maxTempIsolatedFiles],
251
- ['maxProcessTreeFiles', resourceCounts['process-tree'] ?? 0, manifest.policy?.maxProcessTreeFiles],
252
- ['maxGitWorktreeFiles', resourceCounts['git-worktree'] ?? 0, manifest.policy?.maxGitWorktreeFiles],
253
- ['maxFixedPortFiles', resourceCounts['fixed-port'] ?? 0, manifest.policy?.maxFixedPortFiles],
254
- ['maxRuntimeSingletonFiles', resourceCounts['runtime-singleton'] ?? 0, manifest.policy?.maxRuntimeSingletonFiles],
255
- ['maxControllerHomeIsolatedFiles', resourceCounts['controller-home-isolated'] ?? 0, manifest.policy?.maxControllerHomeIsolatedFiles],
256
- ['maxDestructiveFiles', resourceCounts.destructive ?? 0, manifest.policy?.maxDestructiveFiles],
257
- ];
258
- for (const [name, actual, limit] of budgetChecks) {
259
- if (typeof limit !== 'number' || actual > limit) errors.push(`test budget ${name} exceeded: ${actual} > ${String(limit)}`);
260
- }
261
229
  return errors;
262
230
  }
263
231
 
@@ -1,57 +0,0 @@
1
- # Heartbeat Triage
2
-
3
- Heartbeat triage is the repo-local scheduled discovery loop. It records findings
4
- for a human to review; it does not approve plans, execute fixes, spawn agents,
5
- open PRs, or install a persistent scheduler.
6
-
7
- ## Command
8
-
9
- Run from the repository root:
10
-
11
- ```bash
12
- bash .ai/harness/scripts/heartbeat-triage.sh run --source scheduled
13
- ```
14
-
15
- The command appends a run section to `.ai/harness/triage/inbox.md` and writes a
16
- JSON snapshot under `.ai/harness/runs/`. Each run records:
17
-
18
- - `workflow-check`: `bash .ai/harness/scripts/check-task-workflow.sh --strict`
19
- - `sprint-next`: `bash .ai/harness/scripts/sprint-backlog.sh next` when an active sprint
20
- marker exists, with a read-only sprint-file fallback when it does not
21
- - `drift-requests`: pending files under `docs/architecture/requests/`
22
-
23
- ## cron
24
-
25
- Example cron entry for a local checkout:
26
-
27
- ```cron
28
- 17 8 * * * cd /path/to/repo && bash .ai/harness/scripts/heartbeat-triage.sh run --source scheduled >/tmp/forge-heartbeat.log 2>&1
29
- ```
30
-
31
- ## loop
32
-
33
- Example long-running loop for a supervised terminal, launch wrapper, or local
34
- process manager:
35
-
36
- ```bash
37
- while true; do
38
- cd /path/to/repo && bash .ai/harness/scripts/heartbeat-triage.sh run --source scheduled
39
- sleep 86400
40
- done
41
- ```
42
-
43
- ## Adoption Review
44
-
45
- Every run includes an "Adoption review due" date fourteen days out. The review
46
- question is narrow: did the inbox produce any human-accepted triage item? If no
47
- item is accepted during the review window, remove the scheduler and keep the
48
- runner as an on-demand diagnostic command.
49
-
50
- ## Guardrails
51
-
52
- - Keep scheduler installation manual and host-local.
53
- - Treat workflow failures and drift requests as inbox entries, not process
54
- crashes.
55
- - Keep `.ai/harness/triage/inbox.md` as runtime state, not a source-of-truth
56
- plan or task ledger.
57
- - Keep execution authority in the normal plan -> contract -> verify flow.
@@ -1,150 +0,0 @@
1
- #!/bin/bash
2
- set -euo pipefail
3
-
4
- usage() {
5
- cat <<'USAGE_EOF'
6
- Usage: scripts/harness-trace-grade.sh --run <trace.json> [--repo <repo>] [--strict]
7
- USAGE_EOF
8
- }
9
-
10
- run_file=""
11
- repo="."
12
- strict=0
13
-
14
- while [[ $# -gt 0 ]]; do
15
- case "$1" in
16
- --run)
17
- run_file="${2:-}"
18
- shift 2
19
- ;;
20
- --repo)
21
- repo="${2:-.}"
22
- shift 2
23
- ;;
24
- --strict)
25
- strict=1
26
- shift
27
- ;;
28
- --help|-h)
29
- usage
30
- exit 0
31
- ;;
32
- *)
33
- echo "Unknown argument: $1" >&2
34
- usage
35
- exit 1
36
- ;;
37
- esac
38
- done
39
-
40
- [[ -n "$run_file" ]] || { usage >&2; exit 1; }
41
- [[ -f "$run_file" ]] || { echo "Trace run file not found: $run_file" >&2; exit 1; }
42
- command -v jq >/dev/null 2>&1 || { echo "jq is required for harness trace grading" >&2; exit 1; }
43
-
44
- if REPO_ROOT="$(cd "$repo" && pwd -P 2>/dev/null)"; then
45
- :
46
- else
47
- echo "Repo path not found: $repo" >&2
48
- exit 1
49
- fi
50
-
51
- results_file="$(mktemp)"
52
- trap 'rm -f "$results_file"' EXIT
53
- : > "$results_file"
54
-
55
- record() {
56
- local id="$1"
57
- local passed="$2"
58
- local message="$3"
59
- jq -n \
60
- --arg id "$id" \
61
- --argjson passed "$passed" \
62
- --arg message "$message" \
63
- '{id: $id, passed: $passed, message: $message}' >> "$results_file"
64
- }
65
-
66
- trace_get() {
67
- local query="$1"
68
- jq -r "$query // empty" "$run_file"
69
- }
70
-
71
- schema="$(trace_get '.schema')"
72
- active_plan="$(trace_get '.active_plan')"
73
- task_profile="$(trace_get '.task_profile')"
74
- review_card_verdict="$(trace_get '.review.card.verdict')"
75
- review_card_change_type="$(trace_get '.review.card.change_type')"
76
- review_card_rollback="$(trace_get '.review.card.rollback')"
77
- commands_count="$(jq '.commands | if type == "array" then length else 0 end' "$run_file")"
78
- outside_count="$(jq '.allowed_paths_check.outside | if type == "array" then length else 0 end' "$run_file")"
79
- allowed_status="$(trace_get '.allowed_paths_check.status')"
80
-
81
- if [[ "$schema" == "forge-run-trace.v1" ]]; then
82
- record "schema.v1" true "trace schema is forge-run-trace.v1"
83
- else
84
- record "schema.v1" false "trace schema is ${schema:-missing}"
85
- fi
86
-
87
- if [[ -n "$active_plan" && -f "$REPO_ROOT/$active_plan" ]]; then
88
- record "active_plan.resolves" true "active plan resolves: $active_plan"
89
- else
90
- record "active_plan.resolves" false "active plan does not resolve: ${active_plan:-missing}"
91
- fi
92
-
93
- case "$task_profile" in
94
- code-change|docs-only|ledger-closeout|migration|eval-only|delegated-run)
95
- record "contract_profile.valid" true "contract profile is valid: $task_profile"
96
- ;;
97
- *)
98
- record "contract_profile.valid" false "contract profile is invalid: ${task_profile:-missing}"
99
- ;;
100
- esac
101
-
102
- if [[ "$review_card_verdict" == "pass" ]]; then
103
- record "review_card.pass" true "Human Review Card verdict is pass"
104
- else
105
- record "review_card.pass" false "Human Review Card verdict is ${review_card_verdict:-missing}"
106
- fi
107
-
108
- if [[ -n "$review_card_change_type" && "$review_card_change_type" == "$task_profile" ]]; then
109
- record "review_card.change_type" true "Human Review Card change type matches task profile"
110
- else
111
- record "review_card.change_type" false "Human Review Card change type ${review_card_change_type:-missing} does not match task profile ${task_profile:-missing}"
112
- fi
113
-
114
- rollback_token="$(printf '%s' "$review_card_rollback" | sed -E 's/[;,].*$//; s/[[:space:]].*$//; s/^[[:space:]]+//; s/[[:space:]]+$//' | tr '[:upper:]' '[:lower:]')"
115
- case "$rollback_token" in
116
- ""|tbd|todo|n/a|na|none|unknown|unavailable|pending|...)
117
- record "review_card.rollback" false "Human Review Card rollback is missing or not concrete"
118
- ;;
119
- *)
120
- record "review_card.rollback" true "Human Review Card rollback is concrete"
121
- ;;
122
- esac
123
-
124
- if [[ "$commands_count" -gt 0 ]] && jq -e '.commands[]? | select((.command // "") | length > 0)' "$run_file" >/dev/null; then
125
- record "commands.present" true "commands evidence is present"
126
- else
127
- record "commands.present" false "commands evidence is missing"
128
- fi
129
-
130
- if [[ "$outside_count" -eq 0 && "$allowed_status" == "pass" ]]; then
131
- record "allowed_paths.clean" true "no changed file is outside allowed paths"
132
- else
133
- record "allowed_paths.clean" false "allowed_paths status is ${allowed_status:-missing}; changed files outside allowed paths: $outside_count"
134
- fi
135
-
136
- failed="$(jq -s '[.[] | select(.passed == false)] | length' "$results_file")"
137
- total="$(jq -s 'length' "$results_file")"
138
- status="pass"
139
- [[ "$failed" -eq 0 ]] || status="fail"
140
-
141
- jq -s \
142
- --arg status "$status" \
143
- --arg run "$run_file" \
144
- --argjson total "$total" \
145
- --argjson failed "$failed" \
146
- '{status: $status, run: $run, total: $total, failed: $failed, graders: .}' "$results_file"
147
-
148
- if [[ "$strict" -eq 1 && "$failed" -ne 0 ]]; then
149
- exit 1
150
- fi
@@ -1,361 +0,0 @@
1
- #!/bin/bash
2
- set -euo pipefail
3
-
4
- usage() {
5
- cat <<'USAGE_EOF'
6
- Usage: scripts/heartbeat-triage.sh [run] [--repo PATH] [--inbox PATH] [--run-id ID] [--source manual|scheduled] [--json]
7
-
8
- Writes a heartbeat triage run to .ai/harness/triage/inbox.md. The command is
9
- safe for cron/loop schedulers: findings are recorded as inbox entries and do
10
- not make the process fail unless the runner itself is misconfigured.
11
- USAGE_EOF
12
- }
13
-
14
- command="run"
15
- repo="."
16
- inbox_path=".ai/harness/triage/inbox.md"
17
- run_id=""
18
- run_source="manual"
19
- json_output=0
20
-
21
- if [[ "${1:-}" == "run" ]]; then
22
- shift
23
- elif [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
24
- usage
25
- exit 0
26
- elif [[ "${1:-}" != "" && "${1:-}" != --* ]]; then
27
- echo "heartbeat-triage: unknown command: $1" >&2
28
- usage >&2
29
- exit 2
30
- fi
31
-
32
- while [[ $# -gt 0 ]]; do
33
- case "$1" in
34
- --repo)
35
- [[ -n "${2:-}" ]] || { echo "heartbeat-triage: --repo requires a value" >&2; exit 2; }
36
- repo="$2"
37
- shift 2
38
- ;;
39
- --inbox)
40
- [[ -n "${2:-}" ]] || { echo "heartbeat-triage: --inbox requires a value" >&2; exit 2; }
41
- inbox_path="$2"
42
- shift 2
43
- ;;
44
- --run-id)
45
- [[ -n "${2:-}" ]] || { echo "heartbeat-triage: --run-id requires a value" >&2; exit 2; }
46
- run_id="$2"
47
- shift 2
48
- ;;
49
- --source)
50
- [[ -n "${2:-}" ]] || { echo "heartbeat-triage: --source requires a value" >&2; exit 2; }
51
- run_source="$2"
52
- shift 2
53
- ;;
54
- --json)
55
- json_output=1
56
- shift
57
- ;;
58
- --help|-h)
59
- usage
60
- exit 0
61
- ;;
62
- *)
63
- echo "heartbeat-triage: unknown argument: $1" >&2
64
- usage >&2
65
- exit 2
66
- ;;
67
- esac
68
- done
69
-
70
- [[ "$command" == "run" ]] || { echo "heartbeat-triage: unsupported command: $command" >&2; exit 2; }
71
-
72
- repo="$(cd "$repo" 2>/dev/null && pwd -P)" || { echo "heartbeat-triage: repo not found: $repo" >&2; exit 2; }
73
- cd "$repo"
74
-
75
- timestamp="$(date '+%Y-%m-%dT%H:%M:%S%z')"
76
- if [[ -z "$run_id" ]]; then
77
- run_id="heartbeat-$(date '+%Y%m%dT%H%M%S')-$$"
78
- fi
79
- safe_run_id="$(printf '%s' "$run_id" | sed -E 's/[^A-Za-z0-9._-]+/-/g')"
80
-
81
- if [[ "$inbox_path" = /* ]]; then
82
- inbox_file="$inbox_path"
83
- else
84
- inbox_file="$repo/$inbox_path"
85
- fi
86
-
87
- runs_dir="$repo/.ai/harness/runs"
88
- triage_dir="$(dirname "$inbox_file")"
89
- run_file="$runs_dir/${safe_run_id}-heartbeat-triage.json"
90
- mkdir -p "$triage_dir" "$runs_dir"
91
-
92
- json_escape() {
93
- local value="$1"
94
- value="${value//\\/\\\\}"
95
- value="${value//\"/\\\"}"
96
- value="${value//$'\n'/\\n}"
97
- value="${value//$'\r'/\\r}"
98
- value="${value//$'\t'/\\t}"
99
- printf '%s' "$value"
100
- }
101
-
102
- policy_get() {
103
- local jq_path="$1"
104
- local default_value="$2"
105
-
106
- if [[ -f ".ai/harness/policy.json" ]] && command -v jq >/dev/null 2>&1; then
107
- local value
108
- value="$(jq -r "$jq_path // empty" ".ai/harness/policy.json" 2>/dev/null || true)"
109
- if [[ -n "$value" ]]; then
110
- printf '%s' "$value"
111
- return 0
112
- fi
113
- fi
114
-
115
- printf '%s' "$default_value"
116
- }
117
-
118
- helper_runtime_dir="$(policy_get '.harness.helper_runtime_dir' '.ai/harness/scripts')"
119
-
120
- helper_path() {
121
- local helper_name="$1"
122
-
123
- if [[ -f "$helper_runtime_dir/$helper_name" ]]; then
124
- printf '%s/%s' "$helper_runtime_dir" "$helper_name"
125
- return 0
126
- fi
127
-
128
- if [[ -f "scripts/$helper_name" ]]; then
129
- printf '%s/%s' "scripts" "$helper_name"
130
- return 0
131
- fi
132
-
133
- printf '%s/%s' "$helper_runtime_dir" "$helper_name"
134
- }
135
-
136
- repo_relative() {
137
- local path="$1"
138
- case "$path" in
139
- "$repo"/*) printf '%s' "${path#"$repo"/}" ;;
140
- "$repo") printf '.' ;;
141
- *) printf '%s' "$path" ;;
142
- esac
143
- }
144
-
145
- first_line() {
146
- awk 'NF { print; exit }'
147
- }
148
-
149
- date_plus_14_days() {
150
- if date -v+14d '+%Y-%m-%d' >/dev/null 2>&1; then
151
- date -v+14d '+%Y-%m-%d'
152
- elif date -d '+14 days' '+%Y-%m-%d' >/dev/null 2>&1; then
153
- date -d '+14 days' '+%Y-%m-%d'
154
- else
155
- date '+%Y-%m-%d'
156
- fi
157
- }
158
-
159
- entry_kinds=()
160
- entry_statuses=()
161
- entry_summaries=()
162
- entry_details=()
163
-
164
- add_entry() {
165
- entry_kinds+=("$1")
166
- entry_statuses+=("$2")
167
- entry_summaries+=("$3")
168
- entry_details+=("$4")
169
- }
170
-
171
- run_workflow_check() {
172
- local output status summary
173
- local check_script
174
- check_script="$(helper_path "check-task-workflow.sh")"
175
-
176
- if [[ ! -f "$check_script" ]]; then
177
- add_entry "workflow-check" "warning" "$check_script is missing" ""
178
- return 0
179
- fi
180
-
181
- set +e
182
- output="$(bash "$check_script" --strict 2>&1)"
183
- status=$?
184
- set -e
185
-
186
- if [[ "$status" -eq 0 ]]; then
187
- add_entry "workflow-check" "pass" "check-task-workflow.sh --strict passed" "$output"
188
- else
189
- summary="$(printf '%s\n' "$output" | first_line)"
190
- add_entry "workflow-check" "fail" "${summary:-check-task-workflow.sh --strict failed}" "$output"
191
- fi
192
- }
193
-
194
- extract_next_pending_from_sprint() {
195
- local sprint_file="$1"
196
- awk -F '|' '
197
- function trim(s) {
198
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", s)
199
- return s
200
- }
201
- /^## Backlog[[:space:]]*$/ { in_section = 1; next }
202
- in_section && /^## / { exit }
203
- !in_section { next }
204
- /^\|[[:space:]]*[0-9]+[[:space:]]*\|/ {
205
- idx = trim($2)
206
- status = trim($3)
207
- task = trim($4)
208
- mode = trim($5)
209
- acceptance = trim($6)
210
- plan = trim($7)
211
- if (status == "[ ]") {
212
- printf "index: %s\ntask: %s\nmode: %s\nacceptance: %s\nplan: %s\n", idx, task, mode, acceptance, plan
213
- exit
214
- }
215
- }
216
- ' "$sprint_file"
217
- }
218
-
219
- find_executing_sprint() {
220
- local file status
221
- local sprints_dir
222
- sprints_dir="$(policy_get '.sprints.dir' 'plans/sprints')"
223
- [[ -d "$sprints_dir" ]] || return 1
224
- while IFS= read -r file; do
225
- status="$(awk '/\*\*Status\*\*:/ { sub(/^.*\*\*Status\*\*: */, ""); gsub(/\r/, ""); print; exit }' "$file" | xargs)"
226
- case "$status" in
227
- Executing|Approved)
228
- printf '%s\n' "$file"
229
- return 0
230
- ;;
231
- esac
232
- done < <(find "$sprints_dir" -maxdepth 1 -name '*.sprint.md' -type f | sort -r)
233
- return 1
234
- }
235
-
236
- run_sprint_next() {
237
- local output status summary sprint_file task
238
- local sprint_helper
239
- sprint_helper="$(helper_path "sprint-backlog.sh")"
240
-
241
- if [[ -f ".ai/harness/sprint/active-sprint" && -f "$sprint_helper" ]]; then
242
- set +e
243
- output="$(bash "$sprint_helper" next 2>&1)"
244
- status=$?
245
- set -e
246
- if [[ "$status" -eq 0 ]]; then
247
- task="$(printf '%s\n' "$output" | awk -F ': ' '/^task:/ { print $2; exit }')"
248
- add_entry "sprint-next" "action" "next sprint task: ${task:-unknown}" "$output"
249
- return 0
250
- fi
251
- if [[ "$status" -eq 3 ]]; then
252
- add_entry "sprint-next" "pass" "no pending sprint task" "$output"
253
- return 0
254
- fi
255
- fi
256
-
257
- if sprint_file="$(find_executing_sprint)"; then
258
- output="$(extract_next_pending_from_sprint "$sprint_file")"
259
- if [[ -n "$output" ]]; then
260
- task="$(printf '%s\n' "$output" | awk -F ': ' '/^task:/ { print $2; exit }')"
261
- add_entry "sprint-next" "action" "next sprint task: ${task:-unknown}" "$output"
262
- else
263
- add_entry "sprint-next" "pass" "no pending sprint task in $sprint_file" ""
264
- fi
265
- else
266
- add_entry "sprint-next" "info" "no active or executing sprint found" ""
267
- fi
268
- }
269
-
270
- run_drift_requests() {
271
- local details count
272
- if [[ ! -d "docs/architecture/requests" ]]; then
273
- add_entry "drift-requests" "pass" "no architecture request directory" ""
274
- return 0
275
- fi
276
-
277
- details="$(find docs/architecture/requests -maxdepth 1 -type f ! -name '.gitkeep' | sort)"
278
- if [[ -z "$details" ]]; then
279
- add_entry "drift-requests" "pass" "no pending architecture drift requests" ""
280
- return 0
281
- fi
282
-
283
- count="$(printf '%s\n' "$details" | sed '/^$/d' | wc -l | xargs)"
284
- add_entry "drift-requests" "action" "${count} pending architecture drift request(s)" "$details"
285
- }
286
-
287
- write_json_snapshot() {
288
- local target="$1"
289
- local idx
290
- {
291
- echo "{"
292
- printf ' "version": 1,\n'
293
- printf ' "kind": "forge-heartbeat-triage",\n'
294
- printf ' "run_id": "%s",\n' "$(json_escape "$run_id")"
295
- printf ' "source": "%s",\n' "$(json_escape "$run_source")"
296
- printf ' "generated_at": "%s",\n' "$(json_escape "$timestamp")"
297
- printf ' "repo": "%s",\n' "$(json_escape "$repo")"
298
- printf ' "inbox": "%s",\n' "$(json_escape "$(repo_relative "$inbox_file")")"
299
- printf ' "run_file": "%s",\n' "$(json_escape "$(repo_relative "$run_file")")"
300
- printf ' "adoption_review_due": "%s",\n' "$(json_escape "$adoption_review_due")"
301
- echo ' "entries": ['
302
- for idx in "${!entry_kinds[@]}"; do
303
- [[ "$idx" -eq 0 ]] || echo ","
304
- printf ' {"kind":"%s","status":"%s","summary":"%s","details":"%s"}' \
305
- "$(json_escape "${entry_kinds[$idx]}")" \
306
- "$(json_escape "${entry_statuses[$idx]}")" \
307
- "$(json_escape "${entry_summaries[$idx]}")" \
308
- "$(json_escape "${entry_details[$idx]}")"
309
- done
310
- echo
311
- echo ' ]'
312
- echo "}"
313
- } > "$target"
314
- }
315
-
316
- write_inbox() {
317
- local idx detail_line
318
- if [[ ! -f "$inbox_file" ]]; then
319
- {
320
- echo "# Heartbeat Triage Inbox"
321
- echo
322
- echo "<!-- managed by scripts/heartbeat-triage.sh; append-only run log -->"
323
- echo
324
- } > "$inbox_file"
325
- fi
326
-
327
- {
328
- echo "## Run ${run_id} - ${timestamp}"
329
- echo
330
- echo "- Source: ${run_source}"
331
- echo "- Run snapshot: $(repo_relative "$run_file")"
332
- echo "- Adoption review due: ${adoption_review_due}"
333
- echo
334
- echo "### Entries"
335
- echo
336
- for idx in "${!entry_kinds[@]}"; do
337
- printf -- "- [%s] %s: %s\n" "${entry_statuses[$idx]}" "${entry_kinds[$idx]}" "${entry_summaries[$idx]}"
338
- if [[ -n "${entry_details[$idx]}" ]]; then
339
- while IFS= read -r detail_line; do
340
- [[ -n "$detail_line" ]] || continue
341
- printf ' - %s\n' "$detail_line"
342
- done <<< "${entry_details[$idx]}"
343
- fi
344
- done
345
- echo
346
- } >> "$inbox_file"
347
- }
348
-
349
- adoption_review_due="$(date_plus_14_days)"
350
- run_workflow_check
351
- run_sprint_next
352
- run_drift_requests
353
- write_json_snapshot "$run_file"
354
- write_inbox
355
-
356
- if [[ "$json_output" -eq 1 ]]; then
357
- cat "$run_file"
358
- else
359
- echo "[Heartbeat] wrote $(repo_relative "$inbox_file")"
360
- echo "[Heartbeat] run snapshot: $(repo_relative "$run_file")"
361
- fi