@moretea-labs/forge 1.6.0 → 1.7.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 (469) hide show
  1. package/AGENTS.md +4 -0
  2. package/CHANGELOG.md +39 -0
  3. package/CLAUDE.md +4 -0
  4. package/README.md +2 -2
  5. package/README.zh-CN.md +1 -1
  6. package/SKILL.md +2 -2
  7. package/THIRD_PARTY_NOTICES.md +1 -1
  8. package/agents/openai.yaml +1 -1
  9. package/assets/hooks/hook-input.sh +11 -8
  10. package/assets/hooks/lib/session-state.sh +10 -7
  11. package/assets/hooks/lib/workflow-state.sh +13 -177
  12. package/assets/hooks/post-tool-observer.sh +8 -2
  13. package/assets/hooks/prompt-guard.sh +5 -81
  14. package/assets/hooks/session-start-context.sh +56 -1
  15. package/assets/partials/05-workflow.partial.md +1 -1
  16. package/assets/partials-agents/02-operating-mode.partial.md +2 -0
  17. package/assets/partials-agents/03-orchestration.partial.md +1 -1
  18. package/assets/plugin-registry.v1.json +3 -3
  19. package/assets/reference-configs/document-generation.md +1 -1
  20. package/assets/reference-configs/harness-overview.md +1 -1
  21. package/assets/reference-configs/sprint-contracts.md +3 -3
  22. package/assets/skill-version.json +2 -2
  23. package/assets/templates/contract.template.md +2 -7
  24. package/assets/templates/helpers/capture-plan.sh +2 -2
  25. package/assets/templates/helpers/check-architecture-sync.sh +17 -0
  26. package/assets/templates/helpers/check-task-workflow.sh +4 -4
  27. package/assets/templates/helpers/contract-worktree.sh +1 -21
  28. package/assets/templates/helpers/ensure-task-workflow.sh +11 -36
  29. package/assets/templates/helpers/inspect-project-state.ts +8 -6
  30. package/assets/templates/helpers/migrate-project-template.sh +22 -45
  31. package/assets/templates/helpers/migrate-workflow-docs.ts +9 -7
  32. package/assets/templates/helpers/new-plan.sh +1 -1
  33. package/assets/templates/helpers/plan-to-todo.sh +12 -37
  34. package/assets/templates/helpers/ship-worktrees.sh +2 -29
  35. package/assets/templates/helpers/verify-contract.sh +1 -111
  36. package/assets/templates/helpers/verify-sprint.sh +3 -180
  37. package/assets/templates/helpers/workflow-contract.ts +5 -1
  38. package/assets/templates/plan.template.md +1 -1
  39. package/assets/templates/review.template.md +9 -34
  40. package/assets/workflow-contract.v1.json +10 -19
  41. package/docs/README.md +10 -10
  42. package/docs/architecture/CURRENT.md +178 -0
  43. package/docs/architecture/EVOLUTION.md +42 -0
  44. package/docs/architecture/current/README.md +4 -156
  45. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +2 -2
  46. package/docs/architecture/decisions/20260823-immediate-controller-relay.md +53 -0
  47. package/docs/architecture/decisions/20260826-browser-runtime-v2.md +73 -0
  48. package/docs/architecture/history/README.md +7 -0
  49. package/docs/architecture/{chatgpt-handoff-facade.md → history/chatgpt-handoff-facade.md} +4 -0
  50. package/docs/architecture/{global-hook-runtime.md → history/global-hook-runtime.md} +7 -3
  51. package/docs/architecture/{ios-semantic-automation-provider-v2.md → history/ios-semantic-automation-provider-v2.md} +6 -2
  52. package/docs/architecture/history.md +3 -34
  53. package/docs/architecture/index.md +15 -98
  54. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
  55. package/docs/architecture/reviews/2026-08-22-semantic-harness-convergence-acceptance.md +39 -0
  56. package/docs/architecture/versions/1.6.md +38 -0
  57. package/docs/architecture/versions/1.7.md +41 -0
  58. package/docs/forge-chatgpt-browser-engine.md +2 -2
  59. package/docs/forge-chatgpt-mcp-setup.md +4 -28
  60. package/docs/forge-chatgpt-supervised-automation.md +3 -3
  61. package/docs/forge-github-issue-launcher.md +1 -1
  62. package/docs/forge-plugin-management.md +1 -1
  63. package/docs/forge-runtime-self-healing-loop.md +1 -1
  64. package/docs/operations/controller-browser-plugin.md +26 -6
  65. package/docs/operations/controller-performance-and-502.md +143 -0
  66. package/docs/operations/controller-reliability-runbook.md +1 -1
  67. package/docs/operations/features.md +2 -2
  68. package/docs/operations/github-repository.md +1 -1
  69. package/docs/operations/homebrew.md +2 -2
  70. package/docs/operations/mcp-tool-exposure.md +5 -3
  71. package/docs/wiki/Architecture.md +6 -6
  72. package/docs/wiki/Implementation.md +2 -2
  73. package/docs/wiki/Integrations.md +2 -2
  74. package/docs/wiki/Work-Lifecycle.md +1 -1
  75. package/package.json +33 -11
  76. package/scripts/activate-source-baseline.ts +17 -13
  77. package/scripts/architecture-event.ts +2 -820
  78. package/scripts/architecture-queue.sh +2 -645
  79. package/scripts/archive-architecture-request.sh +2 -242
  80. package/scripts/archive-workflow.sh +1 -291
  81. package/scripts/benchmark-background-check-overlap.ts +228 -0
  82. package/scripts/benchmark-mcp-host.sh +117 -0
  83. package/scripts/benchmark-mcp-transport.ts +170 -0
  84. package/scripts/benchmark-quality-harness.ts +146 -0
  85. package/scripts/benchmark-route-session-concurrency.ts +207 -6
  86. package/scripts/benchmark-thin-harness-mcp-e2e.ts +7 -1
  87. package/scripts/benchmark-typescript-navigation.ts +186 -0
  88. package/scripts/benchmark-work-efficiency.ts +334 -0
  89. package/scripts/capability-config.ts +2 -392
  90. package/scripts/capability-resolver.ts +2 -503
  91. package/scripts/capture-plan.sh +1 -332
  92. package/scripts/check-agent-tooling.sh +2 -1558
  93. package/scripts/check-architecture-sync.sh +2 -371
  94. package/scripts/check-brain-manifest.sh +2 -253
  95. package/scripts/check-context-files.sh +2 -47
  96. package/scripts/check-deploy-sql-order.sh +2 -115
  97. package/scripts/check-mcp-compatibility.ts +14 -0
  98. package/scripts/check-runtime-architecture.mjs +349 -79
  99. package/scripts/check-skill-version.ts +3 -191
  100. package/scripts/check-source-duplication.mjs +61 -0
  101. package/scripts/check-stable-baseline.ts +92 -0
  102. package/scripts/check-task-sync.sh +2 -63
  103. package/scripts/check-task-workflow.sh +2 -1000
  104. package/scripts/codex-handoff-resume.sh +2 -267
  105. package/scripts/context-contract-sync.sh +2 -514
  106. package/scripts/contract-run.ts +2 -463
  107. package/scripts/contract-worktree.sh +1 -722
  108. package/scripts/ensure-task-workflow.sh +1 -1225
  109. package/scripts/host-temporary-cloud-mcp-e2e.sh +265 -0
  110. package/scripts/inspect-project-state.ts +4 -279
  111. package/scripts/install-standalone-recovery.ts +24 -0
  112. package/scripts/lib/project-init-lib.sh +22 -46
  113. package/scripts/lib/run-forge-helper.sh +19 -0
  114. package/scripts/lib/run-forge-helper.ts +26 -0
  115. package/scripts/migrate-project-template.sh +1 -1189
  116. package/scripts/migrate-workflow-docs.ts +4 -412
  117. package/scripts/new-plan.sh +1 -180
  118. package/scripts/new-spec.sh +1 -47
  119. package/scripts/new-sprint.sh +1 -46
  120. package/scripts/plan-to-todo.sh +1 -796
  121. package/scripts/prepare-codex-handoff.sh +2 -201
  122. package/scripts/prepare-handoff.sh +1 -78
  123. package/scripts/refresh-current-status.sh +2 -467
  124. package/scripts/run-governed-gate.ts +5 -1
  125. package/scripts/select-agent-context-blocks.sh +2 -64
  126. package/scripts/ship-worktrees.sh +1 -558
  127. package/scripts/smoke-ios-physical-device.ts +4 -2
  128. package/scripts/smoke-runtime-recovery.ts +1 -35
  129. package/scripts/smoke-schedule-engine.ts +1 -20
  130. package/scripts/sprint-backlog.sh +1 -834
  131. package/scripts/stage-runtime-release.ts +2 -1
  132. package/scripts/summarize-failures.sh +2 -123
  133. package/scripts/switch-plan.sh +1 -150
  134. package/scripts/sync-brain-docs.sh +2 -379
  135. package/scripts/sync-generated-authority.mjs +175 -0
  136. package/scripts/verify-contract.sh +2 -703
  137. package/scripts/verify-forge-runtime.sh +0 -1
  138. package/scripts/verify-sprint.sh +1 -677
  139. package/scripts/workflow-contract.ts +4 -205
  140. package/scripts/workstream-sync.sh +2 -261
  141. package/src/cli/agent-jobs/executor-health.ts +1 -1
  142. package/src/cli/commands/init-hook.ts +3 -3
  143. package/src/cli/commands/mcp.ts +9 -5
  144. package/src/cli/commands/plugin.ts +12 -3
  145. package/src/cli/commands/recovery.ts +25 -3
  146. package/src/cli/commands/runtime.ts +55 -3
  147. package/src/cli/commands/security.ts +12 -1
  148. package/src/cli/commands/setup-profile.ts +31 -21
  149. package/src/cli/controller/check-runner.ts +113 -5
  150. package/src/cli/controller/composite-result.ts +1 -1
  151. package/src/cli/controller/context/focus.ts +51 -0
  152. package/src/cli/controller/context/instruction-context.ts +114 -0
  153. package/src/cli/controller/context/known-paths.ts +76 -0
  154. package/src/cli/controller/context/query-planning.ts +110 -0
  155. package/src/cli/controller/context/rule-resolution.ts +532 -0
  156. package/src/cli/controller/context/source-materializer.ts +278 -0
  157. package/src/cli/controller/context/structural.ts +16 -0
  158. package/src/cli/controller/context/types.ts +286 -0
  159. package/src/cli/controller/context-pack.ts +828 -487
  160. package/src/cli/controller/launch-agents.ts +77 -2
  161. package/src/cli/controller/operational-plan.ts +2 -2
  162. package/src/cli/controller/work-mode.ts +6 -4
  163. package/src/cli/editing/edit-session.ts +60 -7
  164. package/src/cli/github/contracts.ts +16 -0
  165. package/src/cli/github/github.ts +135 -16
  166. package/src/cli/github/session.ts +2 -1
  167. package/src/cli/installer/managed-entries.ts +15 -1
  168. package/src/cli/local-bridge/console-automations.ts +54 -78
  169. package/src/cli/local-bridge/console-view-models.ts +1 -35
  170. package/src/cli/local-bridge/facade-api.ts +37 -264
  171. package/src/cli/local-bridge/frontend/src/App.tsx +3 -3
  172. package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +23 -13
  173. package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +37 -4
  174. package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +6 -4
  175. package/src/cli/local-bridge/frontend/src/lib/api.ts +1 -6
  176. package/src/cli/local-bridge/frontend/src/lib/routes.ts +1 -1
  177. package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +2 -2
  178. package/src/cli/local-bridge/frontend/src/styles.css +1 -1
  179. package/src/cli/local-bridge/frontend/src/types.ts +5 -8
  180. package/src/cli/local-bridge/job-store.ts +1 -490
  181. package/src/cli/local-bridge/server.ts +2 -515
  182. package/src/cli/local-bridge/ui-dist/app.css +1 -1
  183. package/src/cli/local-bridge/ui-dist/app.js +3703 -3757
  184. package/src/cli/mcp/auth.ts +5 -5
  185. package/src/cli/mcp/instructions.ts +3 -2
  186. package/src/cli/mcp/legacy-tool-service.ts +10 -222
  187. package/src/cli/mcp/multi-repository.ts +16 -5
  188. package/src/cli/mcp/oauth.ts +175 -26
  189. package/src/cli/mcp/post-finalize-work-attribution.ts +150 -0
  190. package/src/cli/mcp/repository-tools.ts +282 -146
  191. package/src/cli/mcp/server.ts +586 -116
  192. package/src/cli/mcp/tool-capability-cache.ts +1 -1
  193. package/src/cli/mcp/tool-contract.ts +14 -0
  194. package/src/cli/mcp/toolset-selection.ts +1 -1
  195. package/src/cli/mcp/toolset.ts +44 -7
  196. package/src/cli/mcp/transports/http.ts +124 -14
  197. package/src/cli/mcp/transports/session-registry.ts +43 -5
  198. package/src/cli/mcp/types.ts +3 -3
  199. package/src/cli/repositories/command-classifier.ts +103 -21
  200. package/src/cli/repositories/command-executor.ts +78 -526
  201. package/src/cli/repositories/command-process.ts +108 -0
  202. package/src/cli/repositories/command-scope.ts +99 -41
  203. package/src/cli/repositories/controller-home.ts +7 -8
  204. package/src/cli/repositories/git-command-executor.ts +2 -0
  205. package/src/cli/repositories/locks.ts +53 -16
  206. package/src/cli/repositories/repository-snapshot.ts +124 -0
  207. package/src/cli/repositories/selected-path-actions.ts +17 -9
  208. package/src/cli/repositories/structured-git.ts +118 -6
  209. package/src/cli/repository/inspector.ts +563 -65
  210. package/src/cli/repository/session-cache.ts +58 -17
  211. package/src/cli/v81-entry.ts +1 -4
  212. package/src/effects/fs-transaction.ts +85 -17
  213. package/src/runtime/context/codegraph-read-provider.ts +233 -2
  214. package/src/runtime/context/codegraph-sidecar.cjs +74 -40
  215. package/src/runtime/context/generic-lsp-provider.ts +355 -0
  216. package/src/runtime/context/lsp-client.ts +283 -0
  217. package/src/runtime/context/semantic-navigation-contract.ts +61 -0
  218. package/src/runtime/context/semantic-navigation.ts +223 -0
  219. package/src/runtime/context/swift-navigation.ts +565 -0
  220. package/src/runtime/context/typescript-navigation.ts +226 -0
  221. package/src/runtime/control-plane/dispatch-priority.ts +28 -0
  222. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +48 -16
  223. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +86 -24
  224. package/src/runtime/control-plane/execution/repository-work-attribution.ts +106 -0
  225. package/src/runtime/control-plane/execution/retained-work-resume.ts +203 -0
  226. package/src/runtime/control-plane/execution/session-store.ts +18 -0
  227. package/src/runtime/control-plane/execution/verification-evidence.ts +58 -3
  228. package/src/runtime/control-plane/execution/work-completion-authority.ts +58 -0
  229. package/src/runtime/control-plane/execution/work-evidence-policy.ts +200 -0
  230. package/src/runtime/control-plane/execution/work-execution-support.ts +386 -0
  231. package/src/runtime/control-plane/execution/work-finalization-service.ts +1913 -0
  232. package/src/runtime/control-plane/execution/work-handle-authority.ts +96 -0
  233. package/src/runtime/control-plane/execution/work-handle-store.ts +27 -2
  234. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +258 -0
  235. package/src/runtime/control-plane/execution/work-operation-service.ts +468 -0
  236. package/src/runtime/control-plane/execution/work-path-scope.ts +37 -0
  237. package/src/runtime/control-plane/execution/work-preparation-service.ts +479 -0
  238. package/src/runtime/control-plane/execution/work-process-evidence.ts +129 -0
  239. package/src/runtime/control-plane/execution/work-remote-delivery.ts +215 -0
  240. package/src/runtime/control-plane/execution/work-task-receipt.ts +22 -18
  241. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +156 -11
  242. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +22 -14
  243. package/src/runtime/control-plane/execution/work-verification-context.ts +56 -0
  244. package/src/runtime/control-plane/execution/work-verification-service.ts +388 -0
  245. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +90 -9
  246. package/src/runtime/control-plane/facade/capability-registry.ts +129 -25
  247. package/src/runtime/control-plane/facade/controller-round-relay.ts +1118 -0
  248. package/src/runtime/control-plane/facade/controller-session-store.ts +302 -12
  249. package/src/runtime/control-plane/facade/goal-workloop-access.ts +17 -1
  250. package/src/runtime/control-plane/facade/goal-workloop.ts +928 -190
  251. package/src/runtime/control-plane/facade/index.ts +3 -0
  252. package/src/runtime/control-plane/facade/plan-contract-store.ts +275 -42
  253. package/src/runtime/control-plane/facade/repository-work-admission.ts +147 -0
  254. package/src/runtime/control-plane/facade/requirement-authority.ts +83 -0
  255. package/src/runtime/control-plane/facade/semantic-admission.ts +205 -0
  256. package/src/runtime/control-plane/facade/suggested-actions.ts +5 -1
  257. package/src/runtime/control-plane/facade/types.ts +90 -10
  258. package/src/runtime/control-plane/facade/work-contract-store.ts +157 -261
  259. package/src/runtime/control-plane/facade/work-state-machine.ts +250 -0
  260. package/src/runtime/control-plane/generated-cache-retention.ts +271 -0
  261. package/src/runtime/control-plane/global-scheduler/config.ts +44 -0
  262. package/src/runtime/control-plane/global-scheduler/dispatch-capacity.ts +80 -0
  263. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +46 -0
  264. package/src/runtime/control-plane/global-scheduler/maintenance.ts +152 -0
  265. package/src/runtime/control-plane/global-scheduler/projection-refresh.ts +84 -0
  266. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -3
  267. package/src/runtime/control-plane/global-scheduler/scheduler.ts +278 -543
  268. package/src/runtime/control-plane/global-scheduler/source-scan.ts +59 -0
  269. package/src/runtime/control-plane/global-scheduler/state.ts +88 -0
  270. package/src/runtime/control-plane/global-scheduler/worker-attachment.ts +57 -0
  271. package/src/runtime/control-plane/global-scheduler/worker-exit-decision.ts +38 -0
  272. package/src/runtime/control-plane/global-scheduler/worker-exit-reconciler.ts +175 -0
  273. package/src/runtime/control-plane/global-scheduler/worker-launch.ts +111 -0
  274. package/src/runtime/control-plane/global-scheduler/worker-lifecycle-store.ts +64 -0
  275. package/src/runtime/control-plane/global-scheduler/worker-lifecycle.ts +150 -0
  276. package/src/runtime/control-plane/global-scheduler/worker-process.ts +119 -0
  277. package/src/runtime/control-plane/global-scheduler/worker-stderr.ts +60 -0
  278. package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +63 -0
  279. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +365 -117
  280. package/src/runtime/control-plane/launcher/launch-reservation-store.ts +89 -0
  281. package/src/runtime/control-plane/launcher/thin-launcher.ts +244 -11
  282. package/src/runtime/control-plane/persistence/controller-home-migration.ts +487 -0
  283. package/src/runtime/control-plane/persistence/requirement-store.ts +0 -12
  284. package/src/runtime/control-plane/persistence/sqlite-store.ts +33 -2
  285. package/src/runtime/control-plane/release-retention.ts +62 -2
  286. package/src/runtime/control-plane/repo-actor/registry.ts +4 -2
  287. package/src/runtime/control-plane/routing/route-policy.ts +24 -21
  288. package/src/runtime/control-plane/routing/workspace-admission.ts +70 -0
  289. package/src/runtime/control-plane/runtime-status-client.ts +0 -2
  290. package/src/runtime/diagnostics/mcp-timing.ts +13 -0
  291. package/src/runtime/diagnostics/mcp-transport-benchmark.ts +129 -0
  292. package/src/runtime/diagnostics/performance.ts +24 -1
  293. package/src/runtime/evidence/event-ledger.ts +1 -1
  294. package/src/runtime/evidence/process-check-execution.ts +18 -0
  295. package/src/runtime/execution/jobs/child-reference.ts +6 -2
  296. package/src/runtime/execution/jobs/store.ts +58 -4
  297. package/src/runtime/execution/jobs/types.ts +1 -1
  298. package/src/runtime/execution/managed-workspace.ts +203 -1
  299. package/src/runtime/execution/process-runtime/check-facade.ts +51 -4
  300. package/src/runtime/execution/process-runtime/check-result.ts +88 -0
  301. package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +7 -1
  302. package/src/runtime/execution/process-runtime/check-scheduling.ts +114 -0
  303. package/src/runtime/execution/process-runtime/command-facade.ts +367 -40
  304. package/src/runtime/execution/process-runtime/gc.ts +38 -6
  305. package/src/runtime/execution/process-runtime/lightweight-managed.ts +1201 -0
  306. package/src/runtime/execution/process-runtime/persisted-check.ts +51 -5
  307. package/src/runtime/execution/process-runtime/resource-claims.ts +10 -6
  308. package/src/runtime/execution/process-runtime/runtime.ts +53 -3
  309. package/src/runtime/execution/process-runtime/store.ts +1 -0
  310. package/src/runtime/execution/process-runtime/types.ts +4 -12
  311. package/src/runtime/execution/thin-harness/async-process.ts +12 -2
  312. package/src/runtime/execution/thin-harness/search-worker.ts +54 -5
  313. package/src/runtime/execution/work-activity.ts +21 -0
  314. package/src/runtime/execution/workers/executor.ts +18 -61
  315. package/src/runtime/gateway/mcp/execution-tools.ts +35 -1852
  316. package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +61 -0
  317. package/src/runtime/gateway/mcp/process-tools.ts +83 -37
  318. package/src/runtime/gateway/mcp/router.ts +186 -84
  319. package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +565 -0
  320. package/src/runtime/gateway/mcp/runtime-tools.ts +2378 -1947
  321. package/src/runtime/plugins/app-store-connect-adapter.ts +216 -47
  322. package/src/runtime/plugins/browser-adapter.ts +2662 -829
  323. package/src/runtime/plugins/browser-automation-service.ts +10 -0
  324. package/src/runtime/plugins/browser-handoff-host.ts +2 -25
  325. package/src/runtime/plugins/browser-handoff.ts +110 -5
  326. package/src/runtime/plugins/browser-macos-bridge.ts +701 -63
  327. package/src/runtime/plugins/browser-manifest-surface.ts +603 -0
  328. package/src/runtime/plugins/browser-native-session-service.ts +222 -0
  329. package/src/runtime/plugins/browser-node-bridge.ts +6 -34
  330. package/src/runtime/plugins/browser-provider-registry.ts +109 -0
  331. package/src/runtime/plugins/browser-runtime-contract.ts +154 -0
  332. package/src/runtime/plugins/browser-runtime.ts +193 -0
  333. package/src/runtime/plugins/browser-session-authority.ts +332 -0
  334. package/src/runtime/plugins/browser-session-store.ts +121 -0
  335. package/src/runtime/plugins/browser-session-types.ts +98 -0
  336. package/src/runtime/plugins/capability-authorization-grants.ts +354 -0
  337. package/src/runtime/plugins/desktop-operator-registration.ts +10 -4
  338. package/src/runtime/plugins/external-adapter.ts +358 -3
  339. package/src/runtime/plugins/external-unix-socket.ts +7 -1
  340. package/src/runtime/plugins/first-party-registry.ts +2 -0
  341. package/src/runtime/plugins/github-adapter.ts +125 -0
  342. package/src/runtime/plugins/ios/agent-device-provider.ts +1 -1
  343. package/src/runtime/plugins/ios/agent-device-typed-provider.ts +52 -9
  344. package/src/runtime/plugins/ios/remote-xpc-hid.ts +1171 -0
  345. package/src/runtime/plugins/ios-adapter.ts +106 -16
  346. package/src/runtime/plugins/ios-agent-device.ts +234 -64
  347. package/src/runtime/plugins/ios-physical-device.ts +1143 -392
  348. package/src/runtime/plugins/lightweight-action.ts +153 -0
  349. package/src/runtime/plugins/local-system-adapter.ts +123 -6
  350. package/src/runtime/plugins/macos-capability-broker.ts +47 -9
  351. package/src/runtime/plugins/plugin-action-sidecar.ts +59 -0
  352. package/src/runtime/plugins/plugin-management-adapter.ts +49 -8
  353. package/src/runtime/plugins/resend-adapter.ts +1 -1
  354. package/src/runtime/plugins/store.ts +330 -33
  355. package/src/runtime/plugins/types.ts +38 -3
  356. package/src/runtime/plugins/xiaohongshu-publish.ts +515 -0
  357. package/src/runtime/projections/git-status-sampler.ts +16 -16
  358. package/src/runtime/projections/materialized-view.ts +28 -10
  359. package/src/runtime/recovery/maintenance-executor.ts +426 -25
  360. package/src/runtime/root/mcp-transport.ts +180 -10
  361. package/src/runtime/root/package-connector-service.ts +230 -10
  362. package/src/runtime/root/package-runtime-release.ts +143 -17
  363. package/src/runtime/root/package-runtime-service.ts +461 -22
  364. package/src/runtime/root/release-manifest.ts +144 -18
  365. package/src/runtime/root/release-materialize.ts +125 -32
  366. package/src/runtime/root/release-store.ts +48 -11
  367. package/src/runtime/root/runtime.ts +23 -5
  368. package/src/runtime/root/service.ts +100 -29
  369. package/src/runtime/root/types.ts +12 -0
  370. package/src/runtime/safe-tooling/ios-development.ts +321 -63
  371. package/src/runtime/shared/trusted-executable.ts +62 -0
  372. package/src/runtime/shared/trusted-node-executable.ts +48 -0
  373. package/src/runtime/standalone-recovery/core.ts +1079 -240
  374. package/src/runtime/standalone-recovery/entry.ts +100 -24
  375. package/src/runtime/standalone-recovery/installer.ts +20 -4
  376. package/src/runtime/standalone-recovery/service-labels.ts +2 -0
  377. package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +160 -0
  378. package/src/runtime/workflow/schedules/browser-probe.ts +81 -3
  379. package/src/runtime/workflow/schedules/engine.ts +364 -202
  380. package/src/runtime/workflow/schedules/github-issue-watch.ts +158 -0
  381. package/src/runtime/workflow/schedules/settlement.ts +64 -17
  382. package/src/runtime/workflow/schedules/store.ts +209 -19
  383. package/src/runtime/workflow/schedules/types.ts +2 -4
  384. package/src/runtime/workflow/schedules/work-continuation.ts +26 -13
  385. package/src/testing/test-governance.ts +8 -40
  386. package/assets/reference-configs/heartbeat-triage.md +0 -57
  387. package/assets/templates/helpers/harness-trace-grade.sh +0 -150
  388. package/assets/templates/helpers/heartbeat-triage.sh +0 -361
  389. package/assets/templates/helpers/maintenance-triage.sh +0 -167
  390. package/docs/architecture/current/approved-target-architecture.zh-CN.md +0 -1501
  391. package/docs/architecture/current/architecture-invariants.md +0 -331
  392. package/docs/architecture/current/automation-and-schedule-engine.md +0 -459
  393. package/docs/architecture/current/codegraph-context-provider.md +0 -238
  394. package/docs/architecture/current/control-plane-authority-inventory.md +0 -94
  395. package/docs/architecture/current/controller-repository-decoupling.md +0 -148
  396. package/docs/architecture/current/dispatch-and-agent-strategy.md +0 -373
  397. package/docs/architecture/current/entity-model.md +0 -612
  398. package/docs/architecture/current/external-plugin-governance.md +0 -396
  399. package/docs/architecture/current/failure-recovery.md +0 -447
  400. package/docs/architecture/current/governance.md +0 -213
  401. package/docs/architecture/current/human-interaction-plane.md +0 -87
  402. package/docs/architecture/current/implementation-status.md +0 -128
  403. package/docs/architecture/current/job-and-run-lifecycle.md +0 -413
  404. package/docs/architecture/current/legacy-governance.md +0 -58
  405. package/docs/architecture/current/local-workspace-target-grants.md +0 -70
  406. package/docs/architecture/current/migration-roadmap.md +0 -105
  407. package/docs/architecture/current/multi-repository-execution.md +0 -371
  408. package/docs/architecture/current/operations-runbook.md +0 -45
  409. package/docs/architecture/current/peer-supercontroller-runtime.md +0 -32
  410. package/docs/architecture/current/personal-assistant-plugin-baseline.md +0 -206
  411. package/docs/architecture/current/repository-access-modes.md +0 -102
  412. package/docs/architecture/current/route-policy.md +0 -15
  413. package/docs/architecture/current/route-session-concurrency.md +0 -85
  414. package/docs/architecture/current/runtime-architecture-simplification.md +0 -214
  415. package/docs/architecture/current/runtime-directory-map.md +0 -49
  416. package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +0 -85
  417. package/docs/architecture/current/scheduler-and-resource-claims.md +0 -422
  418. package/docs/architecture/current/session-aware-execution-and-authorization.md +0 -77
  419. package/docs/architecture/current/system-overview.md +0 -169
  420. package/docs/architecture/current/target-requirements-traceability.md +0 -202
  421. package/docs/architecture/current/thin-harness-governance-policy.md +0 -32
  422. package/docs/architecture/current/thin-harness-v1.md +0 -321
  423. package/docs/architecture/current/verification-and-release-gates.md +0 -391
  424. package/docs/forge-autonomous-goal-loop.md +0 -9
  425. package/docs/forge-provider-configuration.md +0 -7
  426. package/docs/operations/chatgpt-personal-assistant-runtime.md +0 -93
  427. package/docs/operations/gmail-assistant-routines.md +0 -186
  428. package/docs/operations/personal-assistant-operator-guide.md +0 -61
  429. package/docs/operations/provider-configuration.md +0 -31
  430. package/scripts/harness-trace-grade.sh +0 -150
  431. package/scripts/heartbeat-triage.sh +0 -361
  432. package/scripts/maintenance-triage.sh +0 -167
  433. package/src/cli/local-bridge/frontend/src/features/settings/SettingsView.tsx +0 -2
  434. package/src/cli/repositories/goal-registry.ts +0 -239
  435. package/src/runtime/assistant/action-proposals.ts +0 -279
  436. package/src/runtime/assistant/intent.ts +0 -395
  437. package/src/runtime/assistant/model-provider.ts +0 -460
  438. package/src/runtime/assistant/openapi.ts +0 -223
  439. package/src/runtime/assistant/policy.ts +0 -89
  440. package/src/runtime/assistant/readiness.ts +0 -258
  441. package/src/runtime/assistant/routine-runtime.ts +0 -477
  442. package/src/runtime/assistant/schedule-binding.ts +0 -171
  443. package/src/runtime/assistant/standing-grants.ts +0 -375
  444. package/src/runtime/assistant/store.ts +0 -243
  445. package/src/runtime/assistant/types.ts +0 -135
  446. package/src/runtime/control-plane/goal-loop/config-facade.ts +0 -700
  447. package/src/runtime/control-plane/goal-loop/config-store.ts +0 -570
  448. package/src/runtime/control-plane/goal-loop/config-types.ts +0 -213
  449. package/src/runtime/control-plane/goal-loop/executor-router.ts +0 -109
  450. package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +0 -149
  451. package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +0 -304
  452. package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +0 -1001
  453. package/src/runtime/control-plane/goal-loop/handoff-packet.ts +0 -160
  454. package/src/runtime/control-plane/goal-loop/index.ts +0 -13
  455. package/src/runtime/control-plane/goal-loop/local-tools.ts +0 -290
  456. package/src/runtime/control-plane/goal-loop/policy-gates.ts +0 -203
  457. package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +0 -93
  458. package/src/runtime/control-plane/goal-loop/provider-registry.ts +0 -545
  459. package/src/runtime/control-plane/goal-loop/types.ts +0 -378
  460. package/src/runtime/control-plane/startup-recovery.ts +0 -198
  461. package/src/runtime/gateway/mcp/resource-policy.ts +0 -186
  462. package/src/runtime/personal-assistant/gmail-triage-manager.ts +0 -231
  463. package/src/runtime/personal-assistant/reporting-runtime.ts +0 -344
  464. package/src/runtime/personal-assistant/triage-runtime.ts +0 -748
  465. package/src/runtime/workflow/findings/store.ts +0 -204
  466. package/src/runtime/workflow/findings/types.ts +0 -58
  467. package/src/runtime/workflow/portfolio/engine.ts +0 -20
  468. package/src/runtime/workflow/portfolio/store.ts +0 -185
  469. package/src/runtime/workflow/portfolio/types.ts +0 -29
@@ -1,837 +1,4 @@
1
1
  #!/bin/bash
2
2
  set -euo pipefail
3
-
4
3
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
- if REPO_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null)"; then
6
- cd "$REPO_ROOT"
7
- elif [[ "$SCRIPT_DIR" == */.ai/harness/scripts ]]; then
8
- cd "$SCRIPT_DIR/../../.."
9
- else
10
- cd "$SCRIPT_DIR/.."
11
- fi
12
-
13
- usage() {
14
- cat <<'USAGE_EOF'
15
- Usage:
16
- scripts/sprint-backlog.sh init --slug <slug> [--title <title>]
17
- scripts/sprint-backlog.sh status
18
- scripts/sprint-backlog.sh next
19
- scripts/sprint-backlog.sh start-task [--task <index|task>] [--execute] [--force] [--sprint <file>]
20
- scripts/sprint-backlog.sh complete-task --task <index|task> [--plan <plan-file>] [--sprint <file>]
21
-
22
- Program-level sprint backlog helper. PRDs live in plans/prds/ as the upper
23
- planning layer; sprints live in plans/sprints/ as ordered execution backlogs.
24
- Each backlog row is expanded with /plan before the existing plan -> contract
25
- -> worktree flow. tasks/todos.md stays the deferred-goal ledger.
26
-
27
- start-task reserves the next (or named) pending backlog row and can capture a
28
- thin plan seed. The coding agent must still use `/plan` to expand the row into
29
- a decision-complete plan before code edits.
30
- --sprint overrides the active-sprint marker (still confined to the sprints
31
- dir), which finish back-fill uses inside worktrees where the runtime marker
32
- is absent.
33
-
34
- Exit codes: 0 success; 1 error; 2 usage error; 3 no pending backlog task (next/start-task).
35
- USAGE_EOF
36
- }
37
-
38
- policy_file=".ai/harness/policy.json"
39
-
40
- policy_get() {
41
- local jq_path="$1"
42
- local default_value="$2"
43
-
44
- if [[ -f "$policy_file" ]] && command -v jq >/dev/null 2>&1; then
45
- local value
46
- value="$(jq -r "$jq_path // empty" "$policy_file" 2>/dev/null || true)"
47
- if [[ -n "$value" ]]; then
48
- printf '%s' "$value"
49
- return 0
50
- fi
51
- fi
52
-
53
- printf '%s' "$default_value"
54
- }
55
-
56
- sprints_dir="$(policy_get '.sprints.dir' 'plans/sprints')"
57
- marker_file="$(policy_get '.sprints.active_marker_file' '.ai/harness/sprint/active-sprint')"
58
- template_file="$(policy_get '.sprints.template_file' '.claude/templates/sprint.template.md')"
59
-
60
- normalize_slug() {
61
- printf '%s' "$1" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//; s/-{2,}/-/g'
62
- }
63
-
64
- # Trim without xargs: xargs chokes on unbalanced quotes in user-edited text.
65
- trim() {
66
- sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//'
67
- }
68
-
69
- extract_status() {
70
- local file="$1"
71
- awk '/\*\*Status\*\*:/ {sub(/^.*\*\*Status\*\*: */, ""); gsub(/\r/, ""); print; exit}' "$file" | trim
72
- }
73
-
74
- # Explicit sprint override (--sprint) for callers running where the runtime
75
- # marker does not exist, e.g. finish back-fill inside a contract worktree.
76
- sprint_override=""
77
-
78
- sprint_file_under_sprints_dir() {
79
- local sprint_file="$1"
80
- local sprints_real sprint_dir_real
81
-
82
- case "$sprint_file" in
83
- "$sprints_dir"/*) ;;
84
- *) return 1 ;;
85
- esac
86
- case "$sprint_file" in
87
- *..*) return 1 ;;
88
- esac
89
- [[ -f "$sprint_file" ]] || return 1
90
- [[ ! -L "$sprint_file" ]] || return 1
91
-
92
- sprints_real="$(cd -P "$sprints_dir" 2>/dev/null && pwd)" || return 1
93
- sprint_dir_real="$(cd -P "$(dirname "$sprint_file")" 2>/dev/null && pwd)" || return 1
94
- case "$sprint_dir_real" in
95
- "$sprints_real"|"$sprints_real"/*) ;;
96
- *) return 1 ;;
97
- esac
98
- }
99
-
100
- active_sprint_file() {
101
- local sprint_file
102
- if [[ -n "$sprint_override" ]]; then
103
- sprint_file="$sprint_override"
104
- else
105
- [[ -f "$marker_file" ]] || return 1
106
- sprint_file="$(trim < "$marker_file" 2>/dev/null)"
107
- fi
108
- [[ -n "$sprint_file" ]] || return 1
109
- # Containment: the marker is repo-controlled, but complete-task rewrites the
110
- # file it points at, so never follow it outside the sprints dir.
111
- sprint_file_under_sprints_dir "$sprint_file" || return 1
112
- printf '%s' "$sprint_file"
113
- }
114
-
115
- require_active_sprint() {
116
- local sprint_file
117
- if ! sprint_file="$(active_sprint_file)"; then
118
- if [[ -n "$sprint_override" ]]; then
119
- echo "sprint-backlog: --sprint does not resolve to a sprint file under ${sprints_dir}: $sprint_override" >&2
120
- else
121
- echo "sprint-backlog: no active sprint (marker: $marker_file)" >&2
122
- fi
123
- exit 1
124
- fi
125
- printf '%s' "$sprint_file"
126
- }
127
-
128
- # Serialize read-modify-write mutations: two concurrent complete-task or
129
- # start-task calls would otherwise both render from the same snapshot and the
130
- # second mv would drop the first writer's update.
131
- BACKLOG_LOCK_DIR=""
132
-
133
- release_backlog_lock() {
134
- if [[ -n "$BACKLOG_LOCK_DIR" ]]; then
135
- rmdir "$BACKLOG_LOCK_DIR" 2>/dev/null || true
136
- BACKLOG_LOCK_DIR=""
137
- fi
138
- }
139
-
140
- acquire_backlog_lock() {
141
- local attempts=0
142
- local max_attempts="${FORGE_BACKLOG_LOCK_ATTEMPTS:-100}"
143
- local sleep_seconds="${FORGE_BACKLOG_LOCK_SLEEP_SECONDS:-0.1}"
144
- case "$max_attempts" in
145
- ''|*[!0-9]*) max_attempts=100 ;;
146
- esac
147
- [[ "$sleep_seconds" =~ ^[0-9]+([.][0-9]+)?$ ]] || sleep_seconds=0.1
148
- BACKLOG_LOCK_DIR="$(dirname "$marker_file")/.backlog-lock"
149
- mkdir -p "$(dirname "$BACKLOG_LOCK_DIR")"
150
- until mkdir "$BACKLOG_LOCK_DIR" 2>/dev/null; do
151
- # Reclaim only when the stale dir actually goes away; a non-empty lock dir
152
- # must fall through to the timeout instead of hot-looping.
153
- if [[ -n "$(find "$BACKLOG_LOCK_DIR" -maxdepth 0 -mmin +1 2>/dev/null)" ]] \
154
- && rmdir "$BACKLOG_LOCK_DIR" 2>/dev/null; then
155
- echo "sprint-backlog: reclaiming stale backlog lock: $BACKLOG_LOCK_DIR" >&2
156
- continue
157
- fi
158
- attempts=$((attempts + 1))
159
- if [[ "$attempts" -ge "$max_attempts" ]]; then
160
- echo "sprint-backlog: timed out acquiring backlog lock: $BACKLOG_LOCK_DIR" >&2
161
- exit 1
162
- fi
163
- sleep "$sleep_seconds"
164
- done
165
- trap release_backlog_lock EXIT INT TERM
166
- }
167
-
168
- # Backlog rows live between '## Backlog' and the next '## ' heading:
169
- # | 1 | [ ] | task-slug | contract | acceptance | plan |
170
- # Output: index<TAB>status<TAB>task<TAB>mode<TAB>acceptance<TAB>plan
171
- backlog_rows() {
172
- local file="$1"
173
- awk -F '|' '
174
- /^## Backlog[[:space:]]*$/ { in_section = 1; next }
175
- in_section && /^## / { exit }
176
- !in_section { next }
177
- /^\|[[:space:]]*[0-9]+[[:space:]]*\|/ {
178
- for (i = 2; i <= 7; i++) {
179
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", $i)
180
- }
181
- printf "%s\t%s\t%s\t%s\t%s\t%s\n", $2, $3, $4, $5, $6, $7
182
- }
183
- ' "$file"
184
- }
185
-
186
- backlog_counts() {
187
- local file="$1"
188
- backlog_rows "$file" | awk -F '\t' '
189
- { total++ }
190
- $2 ~ /^\[[xX]\]$/ { done++ }
191
- END { printf "%d %d\n", done + 0, total + 0 }
192
- '
193
- }
194
-
195
- next_pending_row() {
196
- local file="$1"
197
- backlog_rows "$file" | awk -F '\t' '$2 == "[ ]" { print; exit }'
198
- }
199
-
200
- render_sprint_file() {
201
- local target="$1"
202
- local slug="$2"
203
- local title="$3"
204
- local timestamp="$4"
205
-
206
- if [[ ! -f "$template_file" ]]; then
207
- mkdir -p "$(dirname "$template_file")"
208
- cat > "$template_file" <<'SPRINT_TEMPLATE_EOF'
209
- # Sprint: {{SPRINT_TITLE}}
210
-
211
- > **Status**: Draft
212
- > **Slug**: {{SPRINT_SLUG}}
213
- > **Created**: {{TIMESTAMP}}
214
- > **Updated**: {{TIMESTAMP}}
215
- > **Source PRD**: (optional) `plans/prds/<prd>.prd.md`
216
- > **Source Spec**: `docs/spec.md`
217
- > **Goal Mode**: incremental
218
-
219
- Program-level sprint container. The Source PRD summary and ordered backlog
220
- decompose product intent into task-contract slices; each backlog row is a
221
- long-task waypoint that must be expanded with `/plan` before code edits.
222
- `tasks/todos.md` stays the deferred-goal ledger and never carries this backlog.
223
-
224
- ## PRD
225
-
226
- Summarize or link the upper-layer PRD here. Keep the full PRD in `plans/prds/`.
227
-
228
- ### Problem
229
-
230
- - ...
231
-
232
- ### Users
233
-
234
- - ...
235
-
236
- ### Success Criteria
237
-
238
- - ...
239
-
240
- ### Acceptance Scenarios
241
-
242
- - ...
243
-
244
- ### Non-goals
245
-
246
- - ...
247
-
248
- ## Architecture Notes
249
-
250
- ### Capabilities Touched
251
-
252
- - ...
253
-
254
- ### Dependency Order
255
-
256
- - ...
257
-
258
- ### Risks
259
-
260
- - ...
261
-
262
- ## Backlog
263
-
264
- Ordered execution queue; keep rows in dependency order. Mode `contract` runs
265
- the full plan -> contract -> worktree flow; `inline` allows primary-tree
266
- execution for small tasks. Every row needs a concrete acceptance line.
267
-
268
- | # | Status | Task | Mode | Acceptance | Plan |
269
- |---|--------|------|------|------------|------|
270
- | 1 | [ ] | {{SPRINT_SLUG}}-task-1 | contract | Replace with a machine-checkable acceptance line | (pending) |
271
-
272
- ## Execution Log
273
-
274
- Keep this section last; `scripts/sprint-backlog.sh complete-task` appends rows here.
275
-
276
- | When | Task | Plan | Result |
277
- |------|------|------|--------|
278
- SPRINT_TEMPLATE_EOF
279
- fi
280
-
281
- # Literal placeholder replacement via index/substr: sed/gsub replacement
282
- # strings treat |, &, \ and newlines as metacharacters, so free-text titles
283
- # must never reach them. Render to a temp file so a failure cannot leave a
284
- # half-written sprint file behind.
285
- local tmp_file
286
- tmp_file="$(mktemp)"
287
- if ! SPRINT_SLUG="$slug" SPRINT_TITLE="$title" SPRINT_TS="$timestamp" awk '
288
- function replace_all(line, ph, val, out, i) {
289
- out = ""
290
- while ((i = index(line, ph)) > 0) {
291
- out = out substr(line, 1, i - 1) val
292
- line = substr(line, i + length(ph))
293
- }
294
- return out line
295
- }
296
- {
297
- line = $0
298
- line = replace_all(line, "{{SPRINT_SLUG}}", ENVIRON["SPRINT_SLUG"])
299
- line = replace_all(line, "{{SPRINT_TITLE}}", ENVIRON["SPRINT_TITLE"])
300
- line = replace_all(line, "{{TIMESTAMP}}", ENVIRON["SPRINT_TS"])
301
- print line
302
- }
303
- ' "$template_file" > "$tmp_file"; then
304
- rm -f "$tmp_file"
305
- echo "sprint-backlog: failed to render sprint template" >&2
306
- exit 1
307
- fi
308
- mv "$tmp_file" "$target"
309
- }
310
-
311
- cmd_init() {
312
- local slug=""
313
- local title=""
314
-
315
- while [[ $# -gt 0 ]]; do
316
- case "$1" in
317
- --slug)
318
- [[ -n "${2:-}" ]] || { echo "sprint-backlog: --slug requires a value" >&2; exit 2; }
319
- slug="$2"
320
- shift 2
321
- ;;
322
- --title)
323
- [[ -n "${2:-}" ]] || { echo "sprint-backlog: --title requires a value" >&2; exit 2; }
324
- title="$2"
325
- shift 2
326
- ;;
327
- *)
328
- echo "sprint-backlog: unknown init argument: $1" >&2
329
- usage >&2
330
- exit 2
331
- ;;
332
- esac
333
- done
334
-
335
- [[ -n "$slug" ]] || { echo "sprint-backlog: init requires --slug" >&2; usage >&2; exit 2; }
336
- slug="$(normalize_slug "$slug")"
337
- [[ -n "$slug" ]] || { echo "sprint-backlog: slug is empty after normalization" >&2; exit 2; }
338
- [[ -n "$title" ]] || title="$slug"
339
- # Headings are single-line; fold control characters out of free-text titles.
340
- title="$(printf '%s' "$title" | tr '\n\r\t' ' ')"
341
-
342
- local existing existing_status
343
- if existing="$(active_sprint_file)"; then
344
- existing_status="$(extract_status "$existing")"
345
- case "$existing_status" in
346
- Done|Archived)
347
- ;;
348
- *)
349
- echo "sprint-backlog: active sprint already exists with status ${existing_status:-unknown}: $existing" >&2
350
- echo "sprint-backlog: complete or archive it before starting a new sprint" >&2
351
- exit 1
352
- ;;
353
- esac
354
- fi
355
-
356
- mkdir -p "$sprints_dir" "$(dirname "$marker_file")"
357
-
358
- local timestamp file_stamp sprint_file counter
359
- timestamp="$(date '+%Y-%m-%d %H:%M')"
360
- file_stamp="$(date +%Y%m%d-%H%M)"
361
- sprint_file="${sprints_dir}/${file_stamp}-${slug}.sprint.md"
362
- counter=2
363
- while [[ -e "$sprint_file" ]]; do
364
- sprint_file="${sprints_dir}/${file_stamp}-${slug}-v${counter}.sprint.md"
365
- counter=$((counter + 1))
366
- done
367
-
368
- render_sprint_file "$sprint_file" "$slug" "$title" "$timestamp"
369
- printf '%s' "$sprint_file" > "$marker_file"
370
-
371
- echo "Created draft sprint: $sprint_file"
372
- echo "Active sprint marker: $marker_file"
373
- echo "Fill PRD, Architecture Notes, and Backlog, then set Status to Approved before execution."
374
- }
375
-
376
- cmd_status() {
377
- local sprint_file status done total next_task
378
- if ! sprint_file="$(active_sprint_file)"; then
379
- echo "sprint: (none)"
380
- return 0
381
- fi
382
-
383
- status="$(extract_status "$sprint_file")"
384
- read -r done total <<<"$(backlog_counts "$sprint_file")"
385
- next_task="$(next_pending_row "$sprint_file" | awk -F '\t' '{ print $3 }')"
386
-
387
- echo "sprint: $sprint_file"
388
- echo "status: ${status:-unknown}"
389
- echo "tasks_done: $done"
390
- echo "tasks_total: $total"
391
- echo "next_task: ${next_task:-(none)}"
392
- }
393
-
394
- cmd_next() {
395
- local sprint_file row
396
- sprint_file="$(require_active_sprint)"
397
- row="$(next_pending_row "$sprint_file")"
398
- if [[ -z "$row" ]]; then
399
- echo "next_task: (none)"
400
- exit 3
401
- fi
402
-
403
- printf '%s\n' "$row" | awk -F '\t' '{
404
- printf "index: %s\ntask: %s\nmode: %s\nacceptance: %s\nplan: %s\n", $1, $3, $4, $5, $6
405
- }'
406
- }
407
-
408
- cmd_complete_task() {
409
- local task_ref=""
410
- local plan_file=""
411
-
412
- while [[ $# -gt 0 ]]; do
413
- case "$1" in
414
- --task)
415
- [[ -n "${2:-}" ]] || { echo "sprint-backlog: --task requires a value" >&2; exit 2; }
416
- task_ref="$2"
417
- shift 2
418
- ;;
419
- --plan)
420
- [[ -n "${2:-}" ]] || { echo "sprint-backlog: --plan requires a value" >&2; exit 2; }
421
- plan_file="$2"
422
- shift 2
423
- ;;
424
- --sprint)
425
- [[ -n "${2:-}" ]] || { echo "sprint-backlog: --sprint requires a value" >&2; exit 2; }
426
- sprint_override="$2"
427
- shift 2
428
- ;;
429
- *)
430
- echo "sprint-backlog: unknown complete-task argument: $1" >&2
431
- usage >&2
432
- exit 2
433
- ;;
434
- esac
435
- done
436
-
437
- [[ -n "$task_ref" ]] || { echo "sprint-backlog: complete-task requires --task" >&2; usage >&2; exit 2; }
438
-
439
- local sprint_file target_row target_index target_status target_task target_plan plan_cell match_count
440
- sprint_file="$(require_active_sprint)"
441
- acquire_backlog_lock
442
-
443
- # task_ref travels via ENVIRON (awk -v reprocesses backslash escapes).
444
- match_count="$(backlog_rows "$sprint_file" | TASK_REF="$task_ref" awk -F '\t' '$1 == ENVIRON["TASK_REF"] || $3 == ENVIRON["TASK_REF"] { count++ } END { print count + 0 }')"
445
- if [[ "$match_count" -eq 0 ]]; then
446
- echo "sprint-backlog: no backlog row matches task '$task_ref' in $sprint_file" >&2
447
- exit 1
448
- fi
449
- if [[ "$match_count" -gt 1 ]]; then
450
- echo "sprint-backlog: task reference '$task_ref' is ambiguous (${match_count} backlog rows match); fix duplicate indices or task names first" >&2
451
- exit 1
452
- fi
453
-
454
- target_row="$(backlog_rows "$sprint_file" | TASK_REF="$task_ref" awk -F '\t' '$1 == ENVIRON["TASK_REF"] || $3 == ENVIRON["TASK_REF"] { print; exit }')"
455
-
456
- target_index="$(printf '%s' "$target_row" | cut -f1)"
457
- target_status="$(printf '%s' "$target_row" | cut -f2)"
458
- target_task="$(printf '%s' "$target_row" | cut -f3)"
459
- target_plan="$(printf '%s' "$target_row" | cut -f6)"
460
-
461
- if [[ "$target_status" != "[ ]" ]]; then
462
- echo "sprint-backlog: backlog task '$target_task' (row $target_index) is already complete" >&2
463
- exit 1
464
- fi
465
-
466
- plan_cell="$target_plan"
467
- if [[ -n "$plan_file" ]]; then
468
- plan_cell="\`${plan_file}\`"
469
- fi
470
-
471
- local timestamp tmp_file
472
- timestamp="$(date '+%Y-%m-%d %H:%M')"
473
- tmp_file="$(mktemp)"
474
- # plan_cell and target_task travel via ENVIRON: awk -v reprocesses C
475
- # escapes, so a backslash in either would split or mismatch the table row.
476
- # The rewrite matches index AND task so a duplicate index can never flip a
477
- # different row than the one resolved above.
478
- if ! PLAN_CELL="$plan_cell" TARGET_TASK="$target_task" awk -F '|' -v target="$target_index" -v ts="$timestamp" '
479
- BEGIN { in_section = 0; rewritten = 0 }
480
- /^> \*\*Updated\*\*:/ {
481
- print "> **Updated**: " ts
482
- next
483
- }
484
- /^## Backlog[[:space:]]*$/ { in_section = 1; print; next }
485
- in_section && /^## / { in_section = 0 }
486
- {
487
- if (in_section && !rewritten && $0 ~ /^\|[[:space:]]*[0-9]+[[:space:]]*\|/) {
488
- idx = $2; task = $4; mode = $5; acceptance = $6
489
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", idx)
490
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", task)
491
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", mode)
492
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", acceptance)
493
- if (idx == target && task == ENVIRON["TARGET_TASK"]) {
494
- printf "| %s | [x] | %s | %s | %s | %s |\n", idx, task, mode, acceptance, ENVIRON["PLAN_CELL"]
495
- rewritten = 1
496
- next
497
- }
498
- }
499
- print
500
- }
501
- END { exit rewritten ? 0 : 1 }
502
- ' "$sprint_file" > "$tmp_file"; then
503
- rm -f "$tmp_file"
504
- echo "sprint-backlog: failed to rewrite backlog row (row not rewritten; check the table for malformed cells)" >&2
505
- exit 1
506
- fi
507
- mv "$tmp_file" "$sprint_file"
508
-
509
- if ! grep -Eq '^## Execution Log[[:space:]]*$' "$sprint_file"; then
510
- {
511
- echo
512
- echo "## Execution Log"
513
- echo
514
- echo "| When | Task | Plan | Result |"
515
- echo "|------|------|------|--------|"
516
- } >> "$sprint_file"
517
- fi
518
- printf '| %s | %s | %s | done |\n' "$timestamp" "$target_task" "${plan_cell:-(none)}" >> "$sprint_file"
519
-
520
- clear_in_flight "$target_task"
521
-
522
- local done total
523
- read -r done total <<<"$(backlog_counts "$sprint_file")"
524
- echo "Completed backlog task '$target_task' (row $target_index) in $sprint_file"
525
- echo "Backlog progress: ${done}/${total}"
526
- if [[ "$done" -eq "$total" ]]; then
527
- echo "All backlog tasks complete. Set the sprint Status to Done after review."
528
- fi
529
- }
530
-
531
- # In-flight markers live under the gitignored runtime dir so duplicate
532
- # start-task calls are refused without writing tracked files in the primary
533
- # tree (contract rows must stay merge-pure until finish back-fills them).
534
- in_flight_dir() {
535
- printf '%s/in-flight' "$(dirname "$marker_file")"
536
- }
537
-
538
- in_flight_marker_for() {
539
- printf '%s/%s' "$(in_flight_dir)" "$(normalize_slug "$1")"
540
- }
541
-
542
- task_in_flight() {
543
- [[ -f "$(in_flight_marker_for "$1")" ]]
544
- }
545
-
546
- record_in_flight() {
547
- mkdir -p "$(in_flight_dir)"
548
- printf '%s' "${2:-capturing}" > "$(in_flight_marker_for "$1")"
549
- }
550
-
551
- clear_in_flight() {
552
- rm -f "$(in_flight_marker_for "$1")" 2>/dev/null || true
553
- }
554
-
555
- # Drop markers whose backlog row is gone or already complete (finish back-fill
556
- # runs in the worktree and cannot clean the primary tree's markers).
557
- prune_in_flight_markers() {
558
- local file="$1"
559
- local marker task_slug keep _idx status task _rest
560
- [[ -d "$(in_flight_dir)" ]] || return 0
561
- for marker in "$(in_flight_dir)"/*; do
562
- [[ -e "$marker" ]] || continue
563
- task_slug="$(basename "$marker")"
564
- keep=0
565
- while IFS=$'\t' read -r _idx status task _rest; do
566
- if [[ "$(normalize_slug "$task")" == "$task_slug" && "$status" == "[ ]" ]]; then
567
- keep=1
568
- break
569
- fi
570
- done < <(backlog_rows "$file")
571
- [[ "$keep" -eq 1 ]] || rm -f "$marker"
572
- done
573
- }
574
-
575
- # Fill only the Plan cell of one backlog row (status untouched); used by
576
- # start-task so the backlog shows in-flight work.
577
- set_row_plan_cell() {
578
- local sprint_file="$1"
579
- local target_index="$2"
580
- local target_task="$3"
581
- local plan_cell="$4"
582
- local timestamp tmp_file
583
- timestamp="$(date '+%Y-%m-%d %H:%M')"
584
- tmp_file="$(mktemp)"
585
- if ! PLAN_CELL="$plan_cell" TARGET_TASK="$target_task" awk -F '|' -v target="$target_index" -v ts="$timestamp" '
586
- BEGIN { in_section = 0; rewritten = 0 }
587
- /^> \*\*Updated\*\*:/ {
588
- print "> **Updated**: " ts
589
- next
590
- }
591
- /^## Backlog[[:space:]]*$/ { in_section = 1; print; next }
592
- in_section && /^## / { in_section = 0 }
593
- {
594
- if (in_section && !rewritten && $0 ~ /^\|[[:space:]]*[0-9]+[[:space:]]*\|/) {
595
- idx = $2; status = $3; task = $4; mode = $5; acceptance = $6
596
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", idx)
597
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", status)
598
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", task)
599
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", mode)
600
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", acceptance)
601
- if (idx == target && task == ENVIRON["TARGET_TASK"]) {
602
- printf "| %s | %s | %s | %s | %s | %s |\n", idx, status, task, mode, acceptance, ENVIRON["PLAN_CELL"]
603
- rewritten = 1
604
- next
605
- }
606
- }
607
- print
608
- }
609
- END { exit rewritten ? 0 : 1 }
610
- ' "$sprint_file" > "$tmp_file"; then
611
- rm -f "$tmp_file"
612
- echo "sprint-backlog: failed to update backlog plan cell (row not rewritten; check the table for malformed cells)" >&2
613
- exit 1
614
- fi
615
- mv "$tmp_file" "$sprint_file"
616
- }
617
-
618
- cmd_start_task() {
619
- local task_ref=""
620
- local execute=0
621
- local force=0
622
-
623
- while [[ $# -gt 0 ]]; do
624
- case "$1" in
625
- --task)
626
- [[ -n "${2:-}" ]] || { echo "sprint-backlog: --task requires a value" >&2; exit 2; }
627
- task_ref="$2"
628
- shift 2
629
- ;;
630
- --execute)
631
- execute=1
632
- shift
633
- ;;
634
- --force)
635
- force=1
636
- shift
637
- ;;
638
- --sprint)
639
- [[ -n "${2:-}" ]] || { echo "sprint-backlog: --sprint requires a value" >&2; exit 2; }
640
- sprint_override="$2"
641
- shift 2
642
- ;;
643
- *)
644
- echo "sprint-backlog: unknown start-task argument: $1" >&2
645
- usage >&2
646
- exit 2
647
- ;;
648
- esac
649
- done
650
-
651
- local sprint_file sprint_status
652
- sprint_file="$(require_active_sprint)"
653
- sprint_status="$(extract_status "$sprint_file")"
654
- case "$sprint_status" in
655
- Approved|Executing)
656
- ;;
657
- *)
658
- echo "sprint-backlog: sprint status is ${sprint_status:-unknown}; approve the sprint before starting tasks" >&2
659
- exit 1
660
- ;;
661
- esac
662
-
663
- [[ -f "scripts/capture-plan.sh" ]] || { echo "sprint-backlog: scripts/capture-plan.sh not found" >&2; exit 1; }
664
-
665
- acquire_backlog_lock
666
- prune_in_flight_markers "$sprint_file"
667
-
668
- local target_row match_count candidate_task
669
- if [[ -n "$task_ref" ]]; then
670
- match_count="$(backlog_rows "$sprint_file" | TASK_REF="$task_ref" awk -F '\t' '$1 == ENVIRON["TASK_REF"] || $3 == ENVIRON["TASK_REF"] { count++ } END { print count + 0 }')"
671
- if [[ "$match_count" -eq 0 ]]; then
672
- echo "sprint-backlog: no backlog row matches task '$task_ref' in $sprint_file" >&2
673
- exit 1
674
- fi
675
- if [[ "$match_count" -gt 1 ]]; then
676
- echo "sprint-backlog: task reference '$task_ref' is ambiguous (${match_count} backlog rows match); fix duplicate indices or task names first" >&2
677
- exit 1
678
- fi
679
- target_row="$(backlog_rows "$sprint_file" | TASK_REF="$task_ref" awk -F '\t' '$1 == ENVIRON["TASK_REF"] || $3 == ENVIRON["TASK_REF"] { print; exit }')"
680
- else
681
- # Auto-select skips rows that are already in flight so repeated runs walk
682
- # the queue instead of duplicating an active task.
683
- target_row=""
684
- while IFS= read -r candidate_row; do
685
- [[ -n "$candidate_row" ]] || continue
686
- candidate_task="$(printf '%s' "$candidate_row" | cut -f3)"
687
- if ! task_in_flight "$candidate_task"; then
688
- target_row="$candidate_row"
689
- break
690
- fi
691
- done < <(backlog_rows "$sprint_file" | awk -F '\t' '$2 == "[ ]"')
692
- if [[ -z "$target_row" ]]; then
693
- if [[ -n "$(next_pending_row "$sprint_file")" ]]; then
694
- echo "sprint-backlog: every pending backlog task is already in flight; finish one or rerun with --task <ref> --force" >&2
695
- fi
696
- echo "next_task: (none)"
697
- exit 3
698
- fi
699
- fi
700
-
701
- local target_index target_status target_task target_mode target_acceptance
702
- target_index="$(printf '%s' "$target_row" | cut -f1)"
703
- target_status="$(printf '%s' "$target_row" | cut -f2)"
704
- target_task="$(printf '%s' "$target_row" | cut -f3)"
705
- target_mode="$(printf '%s' "$target_row" | cut -f4)"
706
- target_acceptance="$(printf '%s' "$target_row" | cut -f5)"
707
-
708
- if [[ "$target_status" != "[ ]" ]]; then
709
- echo "sprint-backlog: backlog task '$target_task' (row $target_index) is already complete" >&2
710
- exit 1
711
- fi
712
-
713
- if task_in_flight "$target_task" && [[ "$force" -ne 1 ]]; then
714
- echo "sprint-backlog: backlog task '$target_task' is already in flight (recorded: $(cat "$(in_flight_marker_for "$target_task")" 2>/dev/null || printf 'capturing')); rerun with --force to restart it" >&2
715
- exit 1
716
- fi
717
- record_in_flight "$target_task" "capturing"
718
-
719
- # Do not hold the backlog lock across capture-plan: with --execute it can
720
- # run git worktree setup for minutes and the stale-reclaim would hand the
721
- # lock to a second writer.
722
- release_backlog_lock
723
-
724
- local body_file capture_output plan_path
725
- body_file="$(mktemp)"
726
- cat > "$body_file" <<BODY_EOF
727
- # Sprint Task: ${target_task}
728
-
729
- ## Context
730
-
731
- - Sprint: \`${sprint_file}\`
732
- - Backlog row: ${target_index}
733
- - Mode: ${target_mode}
734
- - Read the sprint Source PRD and Architecture Notes before implementation.
735
- - The sprint row is a long-task waypoint, not a detailed implementation plan.
736
-
737
- ## Goal
738
-
739
- Deliver backlog task \`${target_task}\` so that the acceptance line holds: ${target_acceptance}
740
-
741
- ## Planning Expansion
742
-
743
- Before editing code, use \`/plan\` to expand this sprint row into a decision-complete implementation plan. The \`/plan\` pass should read the sprint file, preserve the acceptance line, name concrete files or commands, and produce the detailed \`plans/plan-*.md\` body that drives contract execution.
744
-
745
- ## Task Breakdown
746
-
747
- - [ ] Run \`/plan\` for backlog task \`${target_task}\` using sprint \`${sprint_file}\` and acceptance: ${target_acceptance}
748
- - [ ] Capture the approved \`/plan\` output with \`scripts/capture-plan.sh --source forge-plan --source-ref sprint:${sprint_file}#${target_task}\`
749
- - [ ] Verify acceptance: ${target_acceptance}
750
- BODY_EOF
751
-
752
- local -a capture_args
753
- capture_args=(
754
- --slug "$target_task"
755
- --title "Sprint task: ${target_task}"
756
- --status Approved
757
- --source forge-sprint
758
- --orchestration-kind sprint-task
759
- --source-ref "sprint:${sprint_file}#${target_task}"
760
- --body-file "$body_file"
761
- )
762
- if [[ "$execute" -eq 1 ]]; then
763
- capture_args+=(--execute)
764
- fi
765
-
766
- # Inline-mode rows execute in the primary tree: suppress the automatic
767
- # contract worktree for them.
768
- if [[ "$target_mode" == "inline" ]]; then
769
- capture_output="$(FORGE_DISABLE_CONTRACT_WORKTREE=1 bash scripts/capture-plan.sh "${capture_args[@]}" 2>&1)" || {
770
- printf '%s\n' "$capture_output" >&2
771
- rm -f "$body_file"
772
- clear_in_flight "$target_task"
773
- echo "sprint-backlog: capture-plan failed for task '$target_task'" >&2
774
- exit 1
775
- }
776
- else
777
- capture_output="$(bash scripts/capture-plan.sh "${capture_args[@]}" 2>&1)" || {
778
- printf '%s\n' "$capture_output" >&2
779
- rm -f "$body_file"
780
- clear_in_flight "$target_task"
781
- echo "sprint-backlog: capture-plan failed for task '$target_task'" >&2
782
- exit 1
783
- }
784
- fi
785
- rm -f "$body_file"
786
- printf '%s\n' "$capture_output"
787
-
788
- plan_path="$(printf '%s\n' "$capture_output" | sed -nE 's/^Captured plan: (.+)$/\1/p' | head -1)"
789
- if [[ -z "$plan_path" ]]; then
790
- echo "sprint-backlog: warning: could not resolve captured plan path; backlog Plan cell unchanged" >&2
791
- return 0
792
- fi
793
- record_in_flight "$target_task" "$plan_path"
794
-
795
- if [[ "$target_mode" == "inline" ]]; then
796
- acquire_backlog_lock
797
- set_row_plan_cell "$sprint_file" "$target_index" "$target_task" "\`${plan_path}\`"
798
- echo "Backlog row ${target_index} ('${target_task}') now references ${plan_path}"
799
- else
800
- # Contract mode: the plan moves into a worktree branched from HEAD, so
801
- # writing the Plan cell here would dirty the primary tree and block the
802
- # eventual --ff-only merge back. The finish back-fill writes the row
803
- # (status + plan) atomically with the merged slice instead.
804
- echo "Backlog row ${target_index} ('${target_task}') stays (pending); contract-worktree finish back-fills the Plan cell after merge."
805
- fi
806
- }
807
-
808
- [[ $# -gt 0 ]] || { usage >&2; exit 2; }
809
-
810
- command="$1"
811
- shift
812
-
813
- case "$command" in
814
- init)
815
- cmd_init "$@"
816
- ;;
817
- status)
818
- cmd_status "$@"
819
- ;;
820
- next)
821
- cmd_next "$@"
822
- ;;
823
- start-task)
824
- cmd_start_task "$@"
825
- ;;
826
- complete-task)
827
- cmd_complete_task "$@"
828
- ;;
829
- --help|-h|help)
830
- usage
831
- ;;
832
- *)
833
- echo "sprint-backlog: unknown command: $command" >&2
834
- usage >&2
835
- exit 2
836
- ;;
837
- esac
4
+ exec "$SCRIPT_DIR/lib/run-forge-helper.sh" "sprint-backlog.sh" "$@"