@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,1002 +1,4 @@
1
1
  #!/bin/bash
2
2
  set -euo pipefail
3
-
4
- usage() {
5
- cat <<'USAGE_EOF'
6
- Usage: scripts/check-task-workflow.sh [--strict]
7
- USAGE_EOF
8
- }
9
-
10
- strict=0
11
-
12
- while [[ $# -gt 0 ]]; do
13
- case "$1" in
14
- --strict)
15
- strict=1
16
- shift
17
- ;;
18
- --help|-h)
19
- usage
20
- exit 0
21
- ;;
22
- *)
23
- echo "Unknown argument: $1" >&2
24
- usage
25
- exit 1
26
- ;;
27
- esac
28
- done
29
-
30
- issues=0
31
- bootstrap_issues=0
32
- WORKFLOW_CONTRACT_PATH=".ai/harness/workflow-contract.json"
33
- policy_file=".ai/harness/policy.json"
34
- json_runtime=""
35
-
36
- report_issue() {
37
- local message="$1"
38
- echo "[workflow] $message"
39
- issues=$((issues + 1))
40
- }
41
-
42
- report_bootstrap() {
43
- local message="$1"
44
- bootstrap_issues=$((bootstrap_issues + 1))
45
- echo "[workflow] Bootstrap/remediation required (ignored runtime; check is read-only): $message"
46
- echo "[workflow] Supported remediation: bash scripts/migrate-project-template.sh --repo . --dry-run (inspect), then run the repository bootstrap/migration command in the owning checkout."
47
- }
48
-
49
- resolve_json_runtime() {
50
- if command -v node >/dev/null 2>&1; then
51
- printf 'node'
52
- return 0
53
- fi
54
-
55
- if command -v bun >/dev/null 2>&1; then
56
- printf 'bun'
57
- return 0
58
- fi
59
-
60
- if command -v python3 >/dev/null 2>&1; then
61
- printf 'python3'
62
- return 0
63
- fi
64
-
65
- return 1
66
- }
67
-
68
- contract_query_lines() {
69
- local selector="$1"
70
- local runtime
71
-
72
- runtime="$(resolve_json_runtime || true)"
73
- if [[ -z "$runtime" || ! -f "$WORKFLOW_CONTRACT_PATH" ]]; then
74
- return 1
75
- fi
76
-
77
- case "$runtime" in
78
- python3)
79
- "$runtime" - "$WORKFLOW_CONTRACT_PATH" "$selector" <<'PY_EOF'
80
- import json
81
- import sys
82
-
83
- path, selector = sys.argv[1], sys.argv[2]
84
- value = json.load(open(path, "r", encoding="utf-8"))
85
- for part in selector.split("."):
86
- value = value.get(part) if isinstance(value, dict) else None
87
- if isinstance(value, list):
88
- for item in value:
89
- print(item)
90
- elif value is not None:
91
- print(value)
92
- PY_EOF
93
- ;;
94
- *)
95
- "$runtime" -e '
96
- const fs = require("fs");
97
- const [, filePath, selector] = process.argv;
98
- let value = JSON.parse(fs.readFileSync(filePath, "utf8"));
99
- for (const part of selector.split(".")) {
100
- value = value && typeof value === "object" ? value[part] : undefined;
101
- }
102
- if (Array.isArray(value)) {
103
- for (const item of value) {
104
- console.log(item);
105
- }
106
- } else if (value !== undefined && value !== null) {
107
- console.log(value);
108
- }
109
- ' "$WORKFLOW_CONTRACT_PATH" "$selector"
110
- ;;
111
- esac
112
- }
113
-
114
- ACTIVE_PLAN_MARKER=".ai/harness/active-plan"
115
- LEGACY_ACTIVE_PLAN_MARKER=".claude/.active-plan"
116
- ACTIVE_WORKTREE_MARKER=".ai/harness/active-worktree"
117
-
118
- read_active_plan_marker() {
119
- local marker_file="$1"
120
- local marker_plan
121
-
122
- if [[ -f "$marker_file" ]]; then
123
- marker_plan="$(cat "$marker_file" 2>/dev/null | xargs)"
124
- if [[ -n "$marker_plan" && -f "$marker_plan" ]]; then
125
- printf '%s' "$marker_plan"
126
- return 0
127
- fi
128
- fi
129
-
130
- return 1
131
- }
132
-
133
- get_active_plan() {
134
- read_active_plan_marker "$ACTIVE_PLAN_MARKER" \
135
- || read_active_plan_marker "$LEGACY_ACTIVE_PLAN_MARKER"
136
- }
137
-
138
- extract_status() {
139
- local file="$1"
140
- # Trim with sed, not xargs: xargs aborts on unbalanced quotes in user-edited
141
- # status text, which would kill the whole check under set -e.
142
- awk '/\*\*Status\*\*:/ {sub(/^.*\*\*Status\*\*: */, ""); gsub(/\r/, ""); print; exit}' "$file" \
143
- | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//'
144
- }
145
-
146
- plan_evidence_contract_error() {
147
- local file="$1"
148
- local section=""
149
- local missing=0
150
-
151
- section="$(awk '
152
- BEGIN { in_section = 0 }
153
- /^## Evidence Contract[[:space:]]*$/ { in_section = 1; next }
154
- in_section && /^## / { exit }
155
- in_section { print }
156
- ' "$file")"
157
-
158
- if [[ -z "$(printf '%s' "$section" | tr -d '[:space:]')" ]]; then
159
- echo "missing ## Evidence Contract section"
160
- return 1
161
- fi
162
-
163
- local label line value
164
- for label in "State/progress path" "Verification evidence" "Evaluator rubric" "Stop condition" "Rollback surface"; do
165
- line="$(printf '%s\n' "$section" | grep -Ei "^[[:space:]]*-[[:space:]]*(\\*\\*)?${label}(\\*\\*)?[[:space:]]*:" | head -1 || true)"
166
- if [[ -z "$line" ]]; then
167
- echo "missing field: ${label}"
168
- missing=1
169
- continue
170
- fi
171
-
172
- value="${line#*:}"
173
- value="$(printf '%s' "$value" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')"
174
- if [[ -z "$value" ]] || printf '%s' "$value" | grep -Eiq '^(tbd|todo|n/a|none|unknown|\.\.\.)$'; then
175
- echo "field has no concrete value: ${label}"
176
- missing=1
177
- fi
178
- done
179
-
180
- [[ "$missing" -eq 0 ]]
181
- }
182
-
183
- check_plan_template_evidence_contract() {
184
- local file="$1"
185
- local label
186
-
187
- grep -Eq '^## Evidence Contract[[:space:]]*$' "$file" || {
188
- report_issue "Plan template is missing ## Evidence Contract: $file"
189
- return
190
- }
191
-
192
- for label in "State/progress path" "Verification evidence" "Evaluator rubric" "Stop condition" "Rollback surface"; do
193
- if ! grep -Eiq "^[[:space:]]*-[[:space:]]*(\\*\\*)?${label}(\\*\\*)?[[:space:]]*:" "$file"; then
194
- report_issue "Plan template Evidence Contract is missing field '${label}': $file"
195
- fi
196
- done
197
- }
198
-
199
- todo_source_plan() {
200
- if [[ ! -f "${todo_file:-tasks/todos.md}" ]]; then
201
- return 1
202
- fi
203
- awk -F': ' '/^\> \*\*Source Plan\*\*:/ {print $2; exit}' "${todo_file:-tasks/todos.md}" | xargs
204
- }
205
-
206
- todo_is_deferred_ledger() {
207
- local file="${1:-${todo_file:-tasks/todos.md}}"
208
- [[ -f "$file" ]] || return 1
209
- grep -Eq '^# Deferred Goal Ledger[[:space:]]*$' "$file" \
210
- && grep -Eq '^> \*\*Status\*\*:[[:space:]]*Backlog[[:space:]]*$' "$file"
211
- }
212
-
213
- todo_deferred_ledger_error() {
214
- local file="${1:-${todo_file:-tasks/todos.md}}"
215
- local missing=0
216
-
217
- grep -Eq '^# Deferred Goal Ledger[[:space:]]*$' "$file" || {
218
- echo "missing '# Deferred Goal Ledger' heading"
219
- missing=1
220
- }
221
- grep -Eq '^> \*\*Status\*\*:[[:space:]]*Backlog[[:space:]]*$' "$file" || {
222
- echo "missing Backlog status"
223
- missing=1
224
- }
225
- grep -Eq '^## Deferred Goals[[:space:]]*$' "$file" || {
226
- echo "missing ## Deferred Goals section"
227
- missing=1
228
- }
229
- grep -Eq '\|[[:space:]]*Goal[[:space:]]*\|[[:space:]]*Why Deferred[[:space:]]*\|[[:space:]]*Tradeoff[[:space:]]*\|[[:space:]]*Revisit Trigger[[:space:]]*\|' "$file" || {
230
- echo "missing deferred-goal table with Tradeoff and Revisit Trigger"
231
- missing=1
232
- }
233
-
234
- [[ "$missing" -eq 0 ]]
235
- }
236
-
237
- sprint_known_status() {
238
- case "$1" in
239
- Draft|Approved|Executing|Done|Archived)
240
- return 0
241
- ;;
242
- esac
243
- return 1
244
- }
245
-
246
- prd_known_status() {
247
- case "$1" in
248
- Draft|Approved|Superseded)
249
- return 0
250
- ;;
251
- esac
252
- return 1
253
- }
254
-
255
- markdown_section_has_content() {
256
- local file="$1"
257
- local section="$2"
258
- awk -v section="$section" '
259
- $0 ~ "^## " section "[[:space:]]*$" { in_section = 1; next }
260
- in_section && /^## / { exit }
261
- !in_section { next }
262
- /^#/ { next }
263
- {
264
- line = $0
265
- gsub(/^[[:space:]]*[->]*[[:space:]]*/, "", line)
266
- gsub(/[[:space:]]+$/, "", line)
267
- if (line == "" || line == "..." || line ~ /^Replace /) next
268
- content = 1
269
- }
270
- END { exit content ? 0 : 1 }
271
- ' "$file"
272
- }
273
-
274
- sprint_prd_has_content() {
275
- local file="$1"
276
- markdown_section_has_content "$file" "PRD"
277
- }
278
-
279
- sprint_ready_error() {
280
- local file="$1"
281
- local missing=0
282
-
283
- if ! sprint_prd_has_content "$file"; then
284
- echo "PRD section is empty or placeholder-only"
285
- missing=1
286
- fi
287
-
288
- if ! grep -Eq '^\|[[:space:]]*#[[:space:]]*\|[[:space:]]*Status[[:space:]]*\|[[:space:]]*Task[[:space:]]*\|[[:space:]]*Mode[[:space:]]*\|[[:space:]]*Acceptance[[:space:]]*\|[[:space:]]*Plan[[:space:]]*\|' "$file"; then
289
- echo "missing backlog table header '| # | Status | Task | Mode | Acceptance | Plan |'"
290
- missing=1
291
- else
292
- local row_errors
293
- row_errors="$(awk -F '|' '
294
- /^## Backlog[[:space:]]*$/ { in_section = 1; next }
295
- in_section && /^## / { exit }
296
- !in_section { next }
297
- /^\|[[:space:]]*[0-9]+[[:space:]]*\|/ {
298
- rows++
299
- idx = $2; status = $3; task = $4; mode = $5; acceptance = $6
300
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", idx)
301
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", status)
302
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", task)
303
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", mode)
304
- gsub(/^[[:space:]]+|[[:space:]]+$/, "", acceptance)
305
- if (status !~ /^\[[ xX]\]$/) printf "row %s has an invalid status cell (expected [ ] or [x])\n", idx
306
- if (task == "" || task == "...") printf "row %s is missing a task\n", idx
307
- if (mode != "contract" && mode != "inline") printf "row %s has an invalid mode (expected contract or inline)\n", idx
308
- if (acceptance == "" || tolower(acceptance) ~ /^(\.\.\.|tbd|todo|n\/a|none)$/) printf "row %s is missing a concrete acceptance line\n", idx
309
- if (acceptance == "Replace with a machine-checkable acceptance line") printf "row %s still has the template placeholder acceptance\n", idx
310
- seen_idx[idx]++
311
- if (task != "") seen_task[task]++
312
- }
313
- END {
314
- if (rows == 0) print "backlog table has no task rows"
315
- for (i in seen_idx) if (seen_idx[i] > 1) printf "duplicate backlog index %s\n", i
316
- for (t in seen_task) if (seen_task[t] > 1) printf "duplicate backlog task %s\n", t
317
- }
318
- ' "$file")"
319
- if [[ -n "$row_errors" ]]; then
320
- printf '%s\n' "$row_errors"
321
- missing=1
322
- fi
323
- fi
324
-
325
- [[ "$missing" -eq 0 ]]
326
- }
327
-
328
- prd_ready_error() {
329
- local file="$1"
330
- local missing=0
331
-
332
- for section in "AI Quick-Read Card" "Problem" "Acceptance Scenarios"; do
333
- if ! markdown_section_has_content "$file" "$section"; then
334
- echo "PRD section '$section' is missing or placeholder-only"
335
- missing=1
336
- fi
337
- done
338
-
339
- [[ "$missing" -eq 0 ]]
340
- }
341
-
342
- derive_slug() {
343
- basename "$1" | sed -E 's/^plan-[0-9]{8}-[0-9]{4}-//; s/\.md$//'
344
- }
345
-
346
- plan_contract_path() {
347
- local plan_file="$1" path
348
- path="$(awk '
349
- /^> \*\*Task Contract\*\*:/ {
350
- sub(/^> \*\*Task Contract\*\*:[[:space:]]*/, "")
351
- gsub(/`/, "")
352
- print
353
- exit
354
- }
355
- /^> \*\*Sprint Contract\*\*:/ {
356
- sub(/^> \*\*Sprint Contract\*\*:[[:space:]]*/, "")
357
- gsub(/`/, "")
358
- print
359
- exit
360
- }
361
- ' "$plan_file" | xargs)"
362
-
363
- case "$path" in
364
- tasks/contracts/*.contract.md)
365
- printf '%s' "$path"
366
- ;;
367
- esac
368
- }
369
-
370
- derive_contract_path() {
371
- local plan_file="$1"
372
- local explicit slug stem
373
- explicit="$(plan_contract_path "$plan_file")"
374
- if [[ -n "$explicit" ]]; then
375
- printf '%s' "$explicit"
376
- return 0
377
- fi
378
-
379
- slug="$(derive_slug "$plan_file")"
380
- stem="$(basename "$plan_file" | sed -E 's/^plan-//; s/\.md$//')"
381
- if [[ -f "tasks/contracts/${stem}.contract.md" ]] || [[ ! -f "tasks/contracts/${slug}.contract.md" ]]; then
382
- printf 'tasks/contracts/%s.contract.md' "$stem"
383
- else
384
- printf 'tasks/contracts/%s.contract.md' "$slug"
385
- fi
386
- }
387
-
388
- file_mtime() {
389
- local file="$1"
390
- local mtime
391
-
392
- mtime="$(stat -c '%Y' "$file" 2>/dev/null || true)"
393
- if [[ "$mtime" =~ ^[0-9]+$ ]]; then
394
- printf '%s' "$mtime"
395
- return 0
396
- fi
397
-
398
- mtime="$(stat -f '%m' "$file" 2>/dev/null || true)"
399
- if [[ "$mtime" =~ ^[0-9]+$ ]]; then
400
- printf '%s' "$mtime"
401
- return 0
402
- fi
403
-
404
- printf '0'
405
- }
406
-
407
- handoff_declares_no_active_plan() {
408
- local file="$1"
409
- [[ -f "$file" ]] || return 1
410
- grep -Eiq '(^|[^[:alnum:]])No active plan([^[:alnum:]]|$)|^[[:space:]]*(-[[:space:]]*)?(Active Plan|Plan):[[:space:]]*\(none\)[[:space:]]*$' "$file"
411
- }
412
-
413
- resume_references_plan() {
414
- local file="$1"
415
- [[ -f "$file" ]] || return 1
416
- grep -Eiq '^[[:space:]]*-[[:space:]]*(Active plan|Plan):[[:space:]]+`?plans/' "$file"
417
- }
418
-
419
- check_handoff_resume_pair() {
420
- local handoff_file="$1"
421
- local resume_file="$2"
422
- local handoff_mtime resume_mtime
423
-
424
- [[ -f "$handoff_file" || -f "$resume_file" ]] || return 0
425
-
426
- if [[ -f "$handoff_file" && ! -f "$resume_file" ]]; then
427
- report_bootstrap "Handoff current exists but resume packet is missing: $resume_file"
428
- return 0
429
- fi
430
-
431
- if [[ ! -f "$handoff_file" && -f "$resume_file" ]]; then
432
- report_bootstrap "Resume packet exists but handoff current is missing: $handoff_file"
433
- return 0
434
- fi
435
-
436
- handoff_mtime="$(file_mtime "$handoff_file")"
437
- resume_mtime="$(file_mtime "$resume_file")"
438
- if [[ "$resume_mtime" =~ ^[0-9]+$ && "$handoff_mtime" =~ ^[0-9]+$ && "$resume_mtime" -lt "$handoff_mtime" ]]; then
439
- report_bootstrap "Resume packet is older than handoff current: $resume_file < $handoff_file. Refresh it with scripts/prepare-handoff.sh or scripts/codex-handoff-resume.sh."
440
- fi
441
-
442
- if handoff_declares_no_active_plan "$handoff_file" && resume_references_plan "$resume_file"; then
443
- report_bootstrap "Handoff current declares no active plan but resume packet references a historical plan: $resume_file. Archive or regenerate the resume packet before continuing."
444
- fi
445
- }
446
-
447
- check_current_resume_freshness() {
448
- local current_file="$1"
449
- local resume_file="$2"
450
- local current_mtime resume_mtime
451
-
452
- [[ -f "$current_file" && -f "$resume_file" ]] || return 0
453
- current_mtime="$(file_mtime "$current_file")"
454
- resume_mtime="$(file_mtime "$resume_file")"
455
- if [[ "$current_mtime" =~ ^[0-9]+$ && "$resume_mtime" =~ ^[0-9]+$ && "$resume_mtime" -lt "$current_mtime" ]]; then
456
- report_bootstrap "Resume packet is older than current status snapshot: $resume_file < $current_file. Run scripts/prepare-handoff.sh --reason <reason> or scripts/codex-handoff-resume.sh."
457
- fi
458
- }
459
-
460
- check_required_file() {
461
- local path="$1"
462
- if [[ -f "$path" ]]; then
463
- return 0
464
- fi
465
-
466
- if [[ "$path" == .ai/harness/scripts/* ]]; then
467
- local helper_name="${path##*/}"
468
- if [[ "${helper_source:-package}" == "package" && -f "scripts/$helper_name" ]]; then
469
- return 0
470
- fi
471
- if [[ -f "assets/templates/helpers/$helper_name" && -f "scripts/$helper_name" ]]; then
472
- return 0
473
- fi
474
- fi
475
-
476
- case "$path" in
477
- .ai/context/*|.ai/harness/*)
478
- report_bootstrap "Missing generated runtime file: $path"
479
- ;;
480
- *)
481
- report_issue "Missing required file: $path"
482
- ;;
483
- esac
484
- }
485
-
486
- check_reference_config_stub() {
487
- local path="$1"
488
- [[ -f "$path" ]] || return 0
489
- grep -Fq "<!-- forge: reference-config-stub v1 -->" "$path" || return 0
490
-
491
- local name="${path##*/}"
492
- local doc_id="${name%.md}"
493
- if ! grep -Fq "> **Doc ID**: $doc_id" "$path"; then
494
- report_issue "Reference config stub has wrong or missing Doc ID: $path"
495
- fi
496
- if ! grep -Fq "forge docs path $doc_id" "$path"; then
497
- report_issue "Reference config stub is missing resolver command: $path"
498
- fi
499
- }
500
-
501
- check_reference_config_stubs() {
502
- local path
503
- if [[ ! -d "docs/reference-configs" ]]; then
504
- return 0
505
- fi
506
- for path in docs/reference-configs/*.md; do
507
- [[ -e "$path" ]] || continue
508
- check_reference_config_stub "$path"
509
- done
510
- }
511
-
512
- check_generation_surface_terminology() {
513
- local file
514
- local surfaces=(
515
- ".claude/templates/plan.template.md"
516
- ".claude/templates/contract.template.md"
517
- ".claude/templates/review.template.md"
518
- "scripts/capture-plan.sh"
519
- "scripts/new-plan.sh"
520
- "scripts/ensure-task-workflow.sh"
521
- "scripts/plan-to-todo.sh"
522
- "scripts/lib/project-init-lib.sh"
523
- )
524
-
525
- for file in "${surfaces[@]}"; do
526
- [[ -f "$file" ]] || continue
527
- if grep -Eq 'Sprint Contract|Sprint Review' "$file"; then
528
- report_issue "Legacy task artifact terminology in generation surface: $file. Use Task Contract / Task Review for new artifacts; keep verify-sprint.sh and other legacy filenames only for compatibility."
529
- fi
530
- if grep -Eq 'tasks/todo\.md|tasks/sprints/' "$file"; then
531
- report_issue "Legacy workflow path emitted by generation surface: $file. Migrate tasks/todo.md to tasks/todos.md and tasks/sprints/*.sprint.md to plans/sprints/."
532
- fi
533
- done
534
- }
535
-
536
- trace_schema_error() {
537
- local file="$1"
538
- local runtime
539
-
540
- [[ -s "$file" ]] || return 0
541
- if ! grep -q '[^[:space:]]' "$file"; then
542
- return 0
543
- fi
544
- if grep -Eq '^[[:space:]]*\{[[:space:]]*\}[[:space:]]*$' "$file"; then
545
- return 0
546
- fi
547
-
548
- runtime="$(resolve_json_runtime || true)"
549
- if [[ -z "$runtime" ]]; then
550
- echo "missing node, bun, or python3 to validate trace schema"
551
- return 1
552
- fi
553
-
554
- case "$runtime" in
555
- python3)
556
- "$runtime" - "$file" <<'PY_EOF'
557
- import json
558
- import sys
559
-
560
- path = sys.argv[1]
561
- try:
562
- data = json.load(open(path, "r", encoding="utf-8"))
563
- except Exception as exc:
564
- print(f"invalid JSON: {exc}")
565
- sys.exit(1)
566
-
567
- errors = []
568
- if data.get("schema") != "forge-run-trace.v1":
569
- errors.append("schema must be forge-run-trace.v1")
570
- for key in ["run_id", "task_profile", "active_plan", "worktree", "branch", "failure_class", "next_step"]:
571
- if key not in data:
572
- errors.append(f"missing field: {key}")
573
- for key in ["commands", "guards", "handoffs", "files_changed"]:
574
- if not isinstance(data.get(key), list):
575
- errors.append(f"field must be an array: {key}")
576
- for key in ["external_acceptance", "allowed_paths_check"]:
577
- if not isinstance(data.get(key), dict):
578
- errors.append(f"field must be an object: {key}")
579
- if data.get("status") not in ["pass", "fail"]:
580
- errors.append("status must be pass or fail")
581
- contract = data.get("contract")
582
- if not (isinstance(contract, str) or (isinstance(contract, dict) and contract.get("file"))):
583
- errors.append("contract must be a string or object with file")
584
- review = data.get("review")
585
- if not (isinstance(review, str) or (isinstance(review, dict) and "file" in review)):
586
- errors.append("review must be a string or object with file")
587
- if errors:
588
- print("; ".join(errors))
589
- sys.exit(1)
590
- PY_EOF
591
- ;;
592
- *)
593
- "$runtime" -e '
594
- const fs = require("fs");
595
- const file = process.argv[1];
596
- let data;
597
- try {
598
- data = JSON.parse(fs.readFileSync(file, "utf8"));
599
- } catch (error) {
600
- console.log(`invalid JSON: ${error.message}`);
601
- process.exit(1);
602
- }
603
- const errors = [];
604
- if (data.schema !== "forge-run-trace.v1") errors.push("schema must be forge-run-trace.v1");
605
- for (const key of ["run_id", "task_profile", "active_plan", "worktree", "branch", "failure_class", "next_step"]) {
606
- if (!(key in data)) errors.push(`missing field: ${key}`);
607
- }
608
- for (const key of ["commands", "guards", "handoffs", "files_changed"]) {
609
- if (!Array.isArray(data[key])) errors.push(`field must be an array: ${key}`);
610
- }
611
- for (const key of ["external_acceptance", "allowed_paths_check"]) {
612
- if (!data[key] || typeof data[key] !== "object" || Array.isArray(data[key])) {
613
- errors.push(`field must be an object: ${key}`);
614
- }
615
- }
616
- if (!["pass", "fail"].includes(data.status)) errors.push("status must be pass or fail");
617
- if (!(typeof data.contract === "string" || (data.contract && typeof data.contract === "object" && data.contract.file))) {
618
- errors.push("contract must be a string or object with file");
619
- }
620
- if (!(typeof data.review === "string" || (data.review && typeof data.review === "object" && "file" in data.review))) {
621
- errors.push("review must be a string or object with file");
622
- }
623
- if (errors.length) {
624
- console.log(errors.join("; "));
625
- process.exit(1);
626
- }
627
- ' "$file"
628
- ;;
629
- esac
630
- }
631
-
632
- check_required_dir() {
633
- local path="$1"
634
- if [[ -d "$path" ]]; then
635
- return 0
636
- fi
637
-
638
- if [[ "$path" == ".ai/harness/scripts" && "${helper_source:-package}" == "package" && -d "scripts" ]]; then
639
- return 0
640
- fi
641
-
642
- if [[ "$path" == ".ai/harness/scripts" && -d "assets/templates/helpers" && -d "scripts" ]]; then
643
- return 0
644
- fi
645
-
646
- case "$path" in
647
- .ai/context|.ai/context/*|.ai/harness|.ai/harness/*)
648
- report_bootstrap "Missing generated runtime directory: $path"
649
- ;;
650
- *)
651
- report_issue "Missing required directory: $path"
652
- ;;
653
- esac
654
- }
655
-
656
- check_helper_runtime_files() {
657
- local helper_names=()
658
- local helper_name
659
-
660
- if [[ -f "$WORKFLOW_CONTRACT_PATH" ]]; then
661
- while IFS= read -r helper_name; do
662
- [[ -n "$helper_name" ]] && helper_names+=("$helper_name")
663
- done < <(contract_query_lines "helpers.scripts" 2>/dev/null || true)
664
- fi
665
-
666
- if [[ "${#helper_names[@]}" -eq 0 ]]; then
667
- helper_names=(
668
- new-spec.sh new-sprint.sh new-plan.sh capture-plan.sh plan-to-todo.sh
669
- contract-run.ts contract-worktree.sh ship-worktrees.sh archive-workflow.sh
670
- refresh-current-status.sh prepare-handoff.sh verify-contract.sh summarize-failures.sh
671
- verify-sprint.sh harness-trace-grade.sh sprint-backlog.sh check-task-sync.sh check-deploy-sql-order.sh
672
- check-architecture-sync.sh check-agent-tooling.sh check-context-files.sh
673
- check-brain-manifest.sh sync-brain-docs.sh check-skill-version.ts
674
- select-agent-context-blocks.sh ensure-task-workflow.sh check-task-workflow.sh
675
- maintenance-triage.sh heartbeat-triage.sh switch-plan.sh workflow-contract.ts
676
- inspect-project-state.ts migrate-workflow-docs.ts migrate-project-template.sh
677
- capability-resolver.ts architecture-event.ts capability-config.ts architecture-queue.sh
678
- archive-architecture-request.sh context-contract-sync.sh workstream-sync.sh
679
- prepare-codex-handoff.sh codex-handoff-resume.sh
680
- )
681
- fi
682
-
683
- check_required_dir "$helper_compat_dir"
684
- if [[ "${helper_source:-package}" != "package" ]]; then
685
- check_required_dir "$helper_runtime_dir"
686
- fi
687
-
688
- for helper_name in "${helper_names[@]}"; do
689
- check_required_file "$helper_compat_dir/$helper_name"
690
- if [[ "${helper_source:-package}" != "package" && "$helper_runtime_dir" != "$helper_compat_dir" ]]; then
691
- check_required_file "$helper_runtime_dir/$helper_name"
692
- fi
693
- done
694
- }
695
-
696
- policy_get() {
697
- local jq_path="$1"
698
- local default_value="$2"
699
-
700
- if [[ -f "$policy_file" ]] && command -v jq >/dev/null 2>&1; then
701
- local value
702
- value="$(jq -r "$jq_path // empty" "$policy_file" 2>/dev/null || true)"
703
- if [[ -n "$value" ]]; then
704
- printf '%s' "$value"
705
- return 0
706
- fi
707
- fi
708
-
709
- printf '%s' "$default_value"
710
- }
711
-
712
- todo_file="$(policy_get '.tasks.todo_file' 'tasks/todos.md')"
713
- current_status_file="$(policy_get '.tasks.current_status_file' 'tasks/current.md')"
714
- lessons_file="$(policy_get '.tasks.lessons_file' 'tasks/lessons.md')"
715
- research_dir="$(policy_get '.tasks.research_dir' 'docs/researches')"
716
- contracts_dir="$(policy_get '.tasks.contracts_dir' 'tasks/contracts')"
717
- reviews_dir="$(policy_get '.tasks.reviews_dir' 'tasks/reviews')"
718
- notes_dir="$(policy_get '.tasks.notes_dir' 'tasks/notes')"
719
- workstreams_dir="$(policy_get '.tasks.workstreams_dir' 'tasks/workstreams')"
720
- runs_dir="$(policy_get '.harness.runs_dir' '.ai/harness/runs')"
721
- checks_file="$(policy_get '.harness.checks_file' '.ai/harness/checks/latest.json')"
722
- helper_runtime_dir="$(policy_get '.harness.helper_runtime_dir' '.ai/harness/scripts')"
723
- helper_compat_dir="$(policy_get '.harness.helper_compat_dir' 'scripts')"
724
- helper_source="$(policy_get '.harness.helper_source' 'package')"
725
- context_map_file="$(policy_get '.context.map_file' '.ai/context/context-map.json')"
726
- brain_manifest_file="$(policy_get '.information_lifecycle.external_knowledge.manifest_file' '.ai/harness/brain-manifest.json')"
727
- handoff_file="$(policy_get '.session.continuation_file' '.ai/harness/session/continuation.md')"
728
- resume_file="$(policy_get '.session.resume_file' '.ai/harness/session/resume.md')"
729
- sprints_dir="$(policy_get '.sprints.dir' 'plans/sprints')"
730
- sprint_marker_file="$(policy_get '.sprints.active_marker_file' '.ai/harness/sprint/active-sprint')"
731
- legacy_sprints_dir="tasks/sprints"
732
- upgrade_strategy_version=""
733
- if [[ -f "$policy_file" ]] && command -v jq >/dev/null 2>&1; then
734
- upgrade_strategy_version="$(policy_get '.upgrade.strategy_version' '')"
735
- fi
736
-
737
- check_required_dir "plans"
738
- check_required_dir "plans/archive"
739
- check_required_dir "plans/prds"
740
- check_required_dir "$sprints_dir"
741
- check_required_dir "tasks"
742
- check_required_dir "tasks/archive"
743
- check_required_dir "$contracts_dir"
744
- check_required_dir "$reviews_dir"
745
- check_required_dir "$notes_dir"
746
- check_required_dir "$workstreams_dir"
747
- check_required_dir ".claude/templates"
748
- check_required_dir ".ai/context"
749
- check_required_dir ".ai/harness"
750
- if [[ "$helper_source" != "package" ]]; then
751
- check_required_dir "$helper_runtime_dir"
752
- fi
753
- check_required_dir "$runs_dir"
754
-
755
- helper_file() {
756
- printf '%s/%s' "$helper_runtime_dir" "$1"
757
- }
758
-
759
- check_required_file "docs/spec.md"
760
- check_required_file ".claude/templates/spec.template.md"
761
- check_required_file ".claude/templates/plan.template.md"
762
- check_required_file ".claude/templates/research.template.md"
763
- check_required_file ".claude/templates/contract.template.md"
764
- check_required_file ".claude/templates/review.template.md"
765
- check_required_file ".claude/templates/implementation-notes.template.md"
766
- check_required_file ".claude/templates/prd.template.md"
767
- check_helper_runtime_files
768
- check_required_file "$todo_file"
769
- check_required_file "$current_status_file"
770
- check_required_file "$lessons_file"
771
- check_required_dir "$research_dir"
772
- check_required_file "$context_map_file"
773
- check_required_file "$policy_file"
774
- check_required_file "$brain_manifest_file"
775
-
776
- if [[ -f ".claude/templates/plan.template.md" ]]; then
777
- check_plan_template_evidence_contract ".claude/templates/plan.template.md"
778
- fi
779
-
780
- if [[ -f "$policy_file" && -z "$upgrade_strategy_version" ]] && command -v jq >/dev/null 2>&1; then
781
- report_issue "Harness policy is missing upgrade.strategy_version; rerun migration to merge the versioned upgrade strategy."
782
- fi
783
-
784
- if [[ ! -f "$WORKFLOW_CONTRACT_PATH" ]]; then
785
- report_bootstrap "Missing generated workflow contract manifest: $WORKFLOW_CONTRACT_PATH"
786
- else
787
- json_runtime="$(resolve_json_runtime || true)"
788
- if [[ -z "$json_runtime" ]]; then
789
- report_issue "Missing node, bun, or python3 to read workflow contract manifest: $WORKFLOW_CONTRACT_PATH"
790
- else
791
- while IFS= read -r rel_dir; do
792
- [[ -z "$rel_dir" ]] && continue
793
- check_required_dir "$rel_dir"
794
- done < <(contract_query_lines "artifacts.requiredDirectories")
795
-
796
- while IFS= read -r rel_file; do
797
- [[ -z "$rel_file" ]] && continue
798
- check_required_file "$rel_file"
799
- done < <(contract_query_lines "artifacts.requiredFiles")
800
- fi
801
- fi
802
-
803
- check_reference_config_stubs
804
- check_generation_surface_terminology
805
- if [[ -f "$checks_file" ]] && ! trace_error="$(trace_schema_error "$checks_file")"; then
806
- report_issue "Latest checks trace is not forge-run-trace.v1 compatible: ${trace_error//$'\n'/; }"
807
- fi
808
-
809
- if [[ -f "docs/plan.md" ]]; then
810
- report_issue "Legacy docs/plan.md detected; migrate or archive it into plans/."
811
- fi
812
-
813
- if [[ -f "docs/TODO.md" ]]; then
814
- report_issue "Legacy docs/TODO.md detected; migrate it into tasks/todos.md."
815
- fi
816
-
817
- if [[ "$todo_file" != "tasks/todo.md" && -f "tasks/todo.md" ]]; then
818
- report_issue "Legacy tasks/todo.md detected; migrate it into ${todo_file}."
819
- fi
820
-
821
- if [[ -f "scripts/check-deploy-sql-order.sh" ]]; then
822
- if ! bash "scripts/check-deploy-sql-order.sh" --quiet; then
823
- report_issue "Deploy SQL order check failed."
824
- fi
825
- fi
826
-
827
- if [[ -f "scripts/check-brain-manifest.sh" && -f "$brain_manifest_file" ]]; then
828
- if ! bash "scripts/check-brain-manifest.sh"; then
829
- report_issue "Brain manifest check failed."
830
- fi
831
- fi
832
-
833
- if [[ -f "scripts/sync-brain-docs.sh" && -f "$brain_manifest_file" ]]; then
834
- if ! bash "scripts/sync-brain-docs.sh" --check; then
835
- report_issue "Brain doc sync check failed."
836
- fi
837
- fi
838
-
839
- todo_source="$(todo_source_plan || true)"
840
- if [[ -f "$todo_file" ]]; then
841
- if grep -q '[^[:space:]]' "$todo_file"; then
842
- if ! todo_is_deferred_ledger "$todo_file"; then
843
- report_issue "Legacy ${todo_file} detected; expected a deferred-goal ledger, not an active execution checklist."
844
- elif ! ledger_error="$(todo_deferred_ledger_error "$todo_file")"; then
845
- report_issue "${todo_file} deferred ledger is incomplete: ${ledger_error//$'\n'/; }"
846
- fi
847
- fi
848
- fi
849
-
850
- if [[ -d "plans/prds" ]]; then
851
- while IFS= read -r prd_sprint_file; do
852
- [[ -n "$prd_sprint_file" ]] || continue
853
- report_issue "Sprint backlog file is in the PRD catalog; migrate ${prd_sprint_file} into ${sprints_dir}/."
854
- done < <(
855
- find plans/prds -maxdepth 1 -type f -name '*.prd.md' -print0 2>/dev/null \
856
- | xargs -0 grep -El '^(# Sprint:|## Backlog[[:space:]]*$)' 2>/dev/null || true
857
- )
858
-
859
- while IFS= read -r prd_file; do
860
- [[ -n "$prd_file" ]] || continue
861
- case "$(basename "$prd_file")" in
862
- [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]-*.prd.md)
863
- ;;
864
- *)
865
- report_issue "PRD filename must match <YYYYMMDD>-<HHMM>-<slug>.prd.md: $prd_file"
866
- continue
867
- ;;
868
- esac
869
-
870
- prd_status="$(extract_status "$prd_file")"
871
- if [[ -z "$prd_status" ]]; then
872
- report_issue "PRD is missing a '**Status**' line: $prd_file"
873
- continue
874
- fi
875
- if ! prd_known_status "$prd_status"; then
876
- report_issue "PRD has unknown status '${prd_status}': $prd_file"
877
- continue
878
- fi
879
- if [[ "$prd_status" == "Approved" ]]; then
880
- if ! prd_error="$(prd_ready_error "$prd_file")"; then
881
- report_issue "PRD $prd_file is not approval-ready: ${prd_error//$'\n'/; }"
882
- fi
883
- fi
884
- done < <(find plans/prds -maxdepth 1 -type f -name '*.prd.md' 2>/dev/null | sort)
885
- fi
886
-
887
- if [[ -d "$sprints_dir" ]]; then
888
- while IFS= read -r sprint_file; do
889
- [[ -n "$sprint_file" ]] || continue
890
- sprint_status="$(extract_status "$sprint_file")"
891
- if [[ -z "$sprint_status" ]]; then
892
- report_issue "Sprint is missing a '**Status**' line: $sprint_file"
893
- continue
894
- fi
895
- if ! sprint_known_status "$sprint_status"; then
896
- report_issue "Sprint has unknown status '${sprint_status}': $sprint_file"
897
- continue
898
- fi
899
- if [[ "$sprint_status" == "Approved" || "$sprint_status" == "Executing" ]]; then
900
- if ! sprint_error="$(sprint_ready_error "$sprint_file")"; then
901
- report_issue "Sprint $sprint_file is not execution-ready: ${sprint_error//$'\n'/; }"
902
- fi
903
- fi
904
- done < <(find "$sprints_dir" -maxdepth 1 -type f -name '*.sprint.md' 2>/dev/null | sort)
905
- fi
906
-
907
- if [[ "$sprints_dir" != "$legacy_sprints_dir" && -d "$legacy_sprints_dir" ]]; then
908
- report_issue "Legacy sprint directory detected; migrate ${legacy_sprints_dir}/*.sprint.md into ${sprints_dir}/*.sprint.md."
909
- fi
910
-
911
- if [[ -d "plans/prds" ]]; then
912
- while IFS= read -r prd_sprint_file; do
913
- [[ -n "$prd_sprint_file" ]] || continue
914
- report_issue "Sprint backlog file is in the PRD catalog; migrate ${prd_sprint_file} into ${sprints_dir}/."
915
- done < <(
916
- find plans/prds -maxdepth 1 -type f -name '*.prd.md' -print0 2>/dev/null \
917
- | xargs -0 grep -El '^(# Sprint:|## Backlog[[:space:]]*$)' 2>/dev/null || true
918
- )
919
- fi
920
-
921
- if [[ -f "$sprint_marker_file" ]]; then
922
- marker_sprint="$(sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//' "$sprint_marker_file" 2>/dev/null || true)"
923
- if [[ -z "$marker_sprint" || ! -f "$marker_sprint" ]]; then
924
- report_issue "Active sprint marker does not resolve to a sprint file: ${marker_sprint:-(empty)} (marker: $sprint_marker_file)"
925
- else
926
- case "$marker_sprint" in
927
- "$sprints_dir"/*)
928
- case "$marker_sprint" in
929
- *..*)
930
- report_issue "Active sprint marker must not contain '..': $marker_sprint (marker: $sprint_marker_file)"
931
- ;;
932
- esac
933
- ;;
934
- *)
935
- report_issue "Active sprint marker points outside ${sprints_dir}: $marker_sprint (marker: $sprint_marker_file)"
936
- ;;
937
- esac
938
- fi
939
- fi
940
-
941
- if [[ -f "$current_status_file" ]]; then
942
- if ! grep -Eq '^# Current Status Snapshot[[:space:]]*$' "$current_status_file"; then
943
- report_issue "${current_status_file} is missing '# Current Status Snapshot' heading."
944
- fi
945
- if grep -Eq '^[[:space:]]*-[[:space:]]\[[ xX]\][[:space:]]+' "$current_status_file"; then
946
- report_issue "${current_status_file} must remain a read model, not a checklist."
947
- fi
948
- fi
949
-
950
- check_handoff_resume_pair "$handoff_file" "$resume_file"
951
- check_current_resume_freshness "$current_status_file" "$resume_file"
952
-
953
- active_plan="$(get_active_plan || true)"
954
- if [[ -z "$active_plan" ]]; then
955
- if [[ -f "$ACTIVE_WORKTREE_MARKER" ]]; then
956
- report_issue "$ACTIVE_WORKTREE_MARKER exists but no active plan marker resolves to a plan."
957
- fi
958
- else
959
- if [[ ! -f "$ACTIVE_WORKTREE_MARKER" ]]; then
960
- report_issue "Active plan marker exists but $ACTIVE_WORKTREE_MARKER is missing."
961
- else
962
- current_worktree="$(pwd -P)"
963
- marked_worktree="$(cat "$ACTIVE_WORKTREE_MARKER" 2>/dev/null | xargs || true)"
964
- if [[ -z "$marked_worktree" ]]; then
965
- report_issue "$ACTIVE_WORKTREE_MARKER is empty."
966
- elif [[ "$marked_worktree" != "$current_worktree" ]]; then
967
- report_issue "$ACTIVE_WORKTREE_MARKER points to $marked_worktree, expected $current_worktree."
968
- fi
969
- fi
970
-
971
- plan_status="$(extract_status "$active_plan")"
972
- if [[ -z "$plan_status" ]]; then
973
- report_issue "Active plan is missing a '**Status**' line: $active_plan"
974
- fi
975
-
976
- if [[ "$plan_status" == "Approved" || "$plan_status" == "Executing" ]]; then
977
- if ! evidence_error="$(plan_evidence_contract_error "$active_plan")"; then
978
- report_issue "Active $plan_status plan has incomplete Evidence Contract: $active_plan (${evidence_error//$'\n'/; })"
979
- fi
980
-
981
- contract_file="$(derive_contract_path "$active_plan")"
982
- if [[ ! -f "$contract_file" ]]; then
983
- report_issue "Active $plan_status plan is missing its task contract: $contract_file"
984
- elif ! grep -Eq '^> \*\*Capability ID\*\*: .+' "$contract_file"; then
985
- report_issue "Active task contract is missing a capability binding: $contract_file"
986
- fi
987
- fi
988
- fi
989
-
990
- if [[ "$issues" -eq 0 ]]; then
991
- if [[ "$bootstrap_issues" -gt 0 ]]; then
992
- echo "[workflow] OK: source/document contracts pass; $bootstrap_issues generated runtime item(s) need local bootstrap/remediation."
993
- fi
994
- echo "[workflow] OK"
995
- exit 0
996
- fi
997
-
998
- if [[ "$strict" -eq 1 ]]; then
999
- exit 1
1000
- fi
1001
-
1002
- echo "[workflow] Found $issues issue(s); rerun with --strict to fail the check."
3
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
4
+ exec "$SCRIPT_DIR/lib/run-forge-helper.sh" "check-task-workflow.sh" "$@"