@moretea-labs/forge 1.5.0-rc.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 (903) hide show
  1. package/AGENTS.md +120 -0
  2. package/CHANGELOG.md +36 -0
  3. package/CLAUDE.md +120 -0
  4. package/CODE_OF_CONDUCT.md +23 -0
  5. package/CONTRIBUTING.md +77 -0
  6. package/LICENSE +22 -0
  7. package/NOTICE +9 -0
  8. package/README.en.md +5 -0
  9. package/README.es.md +12 -0
  10. package/README.fr.md +12 -0
  11. package/README.ja.md +12 -0
  12. package/README.md +132 -0
  13. package/README.zh-CN.md +84 -0
  14. package/SECURITY.md +50 -0
  15. package/SKILL.md +431 -0
  16. package/SUPPORT.md +31 -0
  17. package/THIRD_PARTY_NOTICES.md +18 -0
  18. package/agents/openai.yaml +4 -0
  19. package/assets/AGENTS.md +68 -0
  20. package/assets/CLAUDE.md +68 -0
  21. package/assets/branding/README.md +10 -0
  22. package/assets/branding/forge-controller-flow.mmd +8 -0
  23. package/assets/hooks/AGENTS.md +75 -0
  24. package/assets/hooks/CLAUDE.md +75 -0
  25. package/assets/hooks/anti-simplification.sh +12 -0
  26. package/assets/hooks/changelog-guard.sh +80 -0
  27. package/assets/hooks/codex.hooks.template.json +60 -0
  28. package/assets/hooks/first-principles-guard.sh +72 -0
  29. package/assets/hooks/hook-input.sh +618 -0
  30. package/assets/hooks/lib/session-state.sh +106 -0
  31. package/assets/hooks/lib/workflow-state.sh +1730 -0
  32. package/assets/hooks/post-bash.sh +215 -0
  33. package/assets/hooks/post-edit-guard.sh +256 -0
  34. package/assets/hooks/post-tool-observer.sh +99 -0
  35. package/assets/hooks/pre-edit-guard.sh +240 -0
  36. package/assets/hooks/prompt-guard.sh +1077 -0
  37. package/assets/hooks/run-hook.sh +67 -0
  38. package/assets/hooks/security-sentinel.sh +115 -0
  39. package/assets/hooks/session-start-context.sh +593 -0
  40. package/assets/hooks/settings.template.json +60 -0
  41. package/assets/hooks/stop-orchestrator.sh +171 -0
  42. package/assets/hooks/subagent-return-channel-guard.sh +107 -0
  43. package/assets/hooks/worktree-guard.sh +39 -0
  44. package/assets/initializer-question-pack.v1.json +132 -0
  45. package/assets/initializer-question-pack.v1.schema.json +46 -0
  46. package/assets/initializer-question-pack.v2.json +174 -0
  47. package/assets/initializer-question-pack.v3.json +206 -0
  48. package/assets/initializer-question-pack.v3.schema.json +92 -0
  49. package/assets/initializer-question-pack.v4.json +557 -0
  50. package/assets/initializer-question-pack.v4.schema.json +169 -0
  51. package/assets/partials/01-header.partial.md +10 -0
  52. package/assets/partials/02-iron-rules.partial.md +30 -0
  53. package/assets/partials/03-philosophy.partial.md +32 -0
  54. package/assets/partials/04-project-structure.partial.md +56 -0
  55. package/assets/partials/05-workflow.partial.md +79 -0
  56. package/assets/partials/06-cloudflare.partial.md +20 -0
  57. package/assets/partials/07-footer.partial.md +38 -0
  58. package/assets/partials/08-orchestration.partial.md +49 -0
  59. package/assets/partials/09-compact-instructions.partial.md +11 -0
  60. package/assets/partials/_assembly-order.md +40 -0
  61. package/assets/partials-agents/01-header.partial.md +8 -0
  62. package/assets/partials-agents/02-operating-mode.partial.md +44 -0
  63. package/assets/partials-agents/03-orchestration.partial.md +45 -0
  64. package/assets/partials-agents/04-task-protocol.partial.md +69 -0
  65. package/assets/partials-agents/05-coding-constraints.partial.md +20 -0
  66. package/assets/partials-agents/06-quality-safety.partial.md +23 -0
  67. package/assets/partials-agents/07-cloudflare.partial.md +9 -0
  68. package/assets/partials-agents/08-deep-docs.partial.md +32 -0
  69. package/assets/plan-map.json +301 -0
  70. package/assets/plugin-registry.v1.json +8 -0
  71. package/assets/project-structures/ai-native-collaborative-editor.txt +25 -0
  72. package/assets/project-structures/ai-native-product-copilot.txt +21 -0
  73. package/assets/project-structures/ai-native-runtime-console.txt +25 -0
  74. package/assets/project-structures/ai-native-sidecar-kernel.txt +19 -0
  75. package/assets/project-structures/astro-ssr.txt +25 -0
  76. package/assets/project-structures/expo-nativewind.txt +52 -0
  77. package/assets/project-structures/monorepo.txt +63 -0
  78. package/assets/project-structures/remix.txt +50 -0
  79. package/assets/project-structures/tanstack-start-workers.txt +51 -0
  80. package/assets/project-structures/vite-tanstack.txt +58 -0
  81. package/assets/reference-configs/AGENTS.md +13 -0
  82. package/assets/reference-configs/CLAUDE.md +13 -0
  83. package/assets/reference-configs/agentic-development-flow.md +94 -0
  84. package/assets/reference-configs/ai-workflows.md +14 -0
  85. package/assets/reference-configs/changelog-versioning.md +13 -0
  86. package/assets/reference-configs/coding-standards.md +14 -0
  87. package/assets/reference-configs/development-protocol.md +21 -0
  88. package/assets/reference-configs/document-generation.md +38 -0
  89. package/assets/reference-configs/evaluator-rubric.md +19 -0
  90. package/assets/reference-configs/external-tooling.md +374 -0
  91. package/assets/reference-configs/git-strategy.md +14 -0
  92. package/assets/reference-configs/global-working-rules.md +64 -0
  93. package/assets/reference-configs/handoff-protocol.md +38 -0
  94. package/assets/reference-configs/harness-overview.md +124 -0
  95. package/assets/reference-configs/heartbeat-triage.md +57 -0
  96. package/assets/reference-configs/hook-operations.md +96 -0
  97. package/assets/reference-configs/release-deploy.md +40 -0
  98. package/assets/reference-configs/spa-day-protocol.md +14 -0
  99. package/assets/reference-configs/sprint-contracts.md +89 -0
  100. package/assets/reference-configs/workflow-orchestration.md +14 -0
  101. package/assets/skill-hooks.json +41 -0
  102. package/assets/skill-version.json +189 -0
  103. package/assets/skills/claude-review/SKILL.md +231 -0
  104. package/assets/skills/codex-review/SKILL.md +103 -0
  105. package/assets/templates/AGENTS.md +13 -0
  106. package/assets/templates/CLAUDE.md +13 -0
  107. package/assets/templates/architecture.template.md +80 -0
  108. package/assets/templates/brief.template.md +38 -0
  109. package/assets/templates/contract.template.md +104 -0
  110. package/assets/templates/decisions.template.md +85 -0
  111. package/assets/templates/factor-factory/factor-backtest-report.template.md +36 -0
  112. package/assets/templates/factor-factory/factor-hypothesis.template.md +30 -0
  113. package/assets/templates/factor-factory/factor-registry.template.json +5 -0
  114. package/assets/templates/gitignore.template +53 -0
  115. package/assets/templates/guides/metro-esm-gotchas.template.md +46 -0
  116. package/assets/templates/helpers/architecture-event.ts +822 -0
  117. package/assets/templates/helpers/architecture-queue.sh +647 -0
  118. package/assets/templates/helpers/archive-architecture-request.sh +244 -0
  119. package/assets/templates/helpers/archive-workflow.sh +295 -0
  120. package/assets/templates/helpers/capability-config.ts +394 -0
  121. package/assets/templates/helpers/capability-resolver.ts +505 -0
  122. package/assets/templates/helpers/capture-plan.sh +335 -0
  123. package/assets/templates/helpers/check-agent-tooling.sh +1533 -0
  124. package/assets/templates/helpers/check-architecture-sync.sh +287 -0
  125. package/assets/templates/helpers/check-brain-manifest.sh +255 -0
  126. package/assets/templates/helpers/check-context-files.sh +49 -0
  127. package/assets/templates/helpers/check-deploy-sql-order.sh +117 -0
  128. package/assets/templates/helpers/check-skill-version.ts +193 -0
  129. package/assets/templates/helpers/check-task-sync.sh +65 -0
  130. package/assets/templates/helpers/check-task-workflow.sh +1002 -0
  131. package/assets/templates/helpers/codex-handoff-resume.sh +269 -0
  132. package/assets/templates/helpers/context-contract-sync.sh +516 -0
  133. package/assets/templates/helpers/contract-run.ts +465 -0
  134. package/assets/templates/helpers/contract-worktree.sh +725 -0
  135. package/assets/templates/helpers/ensure-task-workflow.sh +1218 -0
  136. package/assets/templates/helpers/harness-trace-grade.sh +150 -0
  137. package/assets/templates/helpers/heartbeat-triage.sh +361 -0
  138. package/assets/templates/helpers/inspect-project-state.ts +280 -0
  139. package/assets/templates/helpers/maintenance-triage.sh +167 -0
  140. package/assets/templates/helpers/migrate-project-template.sh +54 -0
  141. package/assets/templates/helpers/migrate-workflow-docs.ts +413 -0
  142. package/assets/templates/helpers/new-plan.sh +183 -0
  143. package/assets/templates/helpers/new-spec.sh +50 -0
  144. package/assets/templates/helpers/new-sprint.sh +49 -0
  145. package/assets/templates/helpers/plan-to-todo.sh +799 -0
  146. package/assets/templates/helpers/prepare-codex-handoff.sh +203 -0
  147. package/assets/templates/helpers/prepare-handoff.sh +81 -0
  148. package/assets/templates/helpers/refresh-current-status.sh +469 -0
  149. package/assets/templates/helpers/select-agent-context-blocks.sh +66 -0
  150. package/assets/templates/helpers/ship-worktrees.sh +561 -0
  151. package/assets/templates/helpers/sprint-backlog.sh +837 -0
  152. package/assets/templates/helpers/summarize-failures.sh +125 -0
  153. package/assets/templates/helpers/switch-plan.sh +153 -0
  154. package/assets/templates/helpers/sync-brain-docs.sh +381 -0
  155. package/assets/templates/helpers/verify-contract.sh +705 -0
  156. package/assets/templates/helpers/verify-sprint.sh +680 -0
  157. package/assets/templates/helpers/workflow-contract.ts +202 -0
  158. package/assets/templates/helpers/workstream-sync.sh +263 -0
  159. package/assets/templates/implementation-notes.template.md +37 -0
  160. package/assets/templates/packages.template.md +45 -0
  161. package/assets/templates/plan.template.md +77 -0
  162. package/assets/templates/prd.template.md +165 -0
  163. package/assets/templates/research.template.md +25 -0
  164. package/assets/templates/review.template.md +78 -0
  165. package/assets/templates/spec.template.md +31 -0
  166. package/assets/templates/sprint.template.md +69 -0
  167. package/assets/templates/tech-stack.template.md +57 -0
  168. package/assets/versions.json +77 -0
  169. package/assets/workflow-contract.v1.json +671 -0
  170. package/bin/forge-desktop-helper.mjs +204 -0
  171. package/bin/forge-hook.mjs +32 -0
  172. package/bin/forge-runtime-service.mjs +34 -0
  173. package/bin/forge-runtime.mjs +30 -0
  174. package/bin/forge.mjs +32 -0
  175. package/docs/CHANGELOG.md +978 -0
  176. package/docs/README.md +72 -0
  177. package/docs/README.zh-CN.md +58 -0
  178. package/docs/architecture/chatgpt-handoff-facade.md +393 -0
  179. package/docs/architecture/current/README.md +158 -0
  180. package/docs/architecture/current/approved-target-architecture.zh-CN.md +1501 -0
  181. package/docs/architecture/current/architecture-invariants.md +331 -0
  182. package/docs/architecture/current/automation-and-schedule-engine.md +453 -0
  183. package/docs/architecture/current/codegraph-context-provider.md +226 -0
  184. package/docs/architecture/current/control-plane-authority-inventory.md +82 -0
  185. package/docs/architecture/current/controller-repository-decoupling.md +148 -0
  186. package/docs/architecture/current/dispatch-and-agent-strategy.md +354 -0
  187. package/docs/architecture/current/entity-model.md +619 -0
  188. package/docs/architecture/current/external-plugin-governance.md +396 -0
  189. package/docs/architecture/current/failure-recovery.md +471 -0
  190. package/docs/architecture/current/governance.md +213 -0
  191. package/docs/architecture/current/human-interaction-plane.md +87 -0
  192. package/docs/architecture/current/implementation-status.md +128 -0
  193. package/docs/architecture/current/job-and-run-lifecycle.md +413 -0
  194. package/docs/architecture/current/local-workspace-target-grants.md +70 -0
  195. package/docs/architecture/current/migration-roadmap.md +105 -0
  196. package/docs/architecture/current/multi-repository-execution.md +371 -0
  197. package/docs/architecture/current/operations-runbook.md +45 -0
  198. package/docs/architecture/current/peer-supercontroller-runtime.md +32 -0
  199. package/docs/architecture/current/personal-assistant-plugin-baseline.md +207 -0
  200. package/docs/architecture/current/repository-access-modes.md +102 -0
  201. package/docs/architecture/current/route-policy.md +15 -0
  202. package/docs/architecture/current/route-session-concurrency.md +85 -0
  203. package/docs/architecture/current/runtime-architecture-simplification.md +214 -0
  204. package/docs/architecture/current/runtime-directory-map.md +49 -0
  205. package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +85 -0
  206. package/docs/architecture/current/scheduler-and-resource-claims.md +432 -0
  207. package/docs/architecture/current/session-aware-execution-and-authorization.md +77 -0
  208. package/docs/architecture/current/system-overview.md +144 -0
  209. package/docs/architecture/current/target-requirements-traceability.md +202 -0
  210. package/docs/architecture/current/thin-harness-governance-policy.md +32 -0
  211. package/docs/architecture/current/thin-harness-v1.md +313 -0
  212. package/docs/architecture/current/verification-and-release-gates.md +391 -0
  213. package/docs/architecture/decisions/20260801-controller-home-sqlite-state.md +100 -0
  214. package/docs/architecture/decisions/20260803-canonical-skill-surface.md +40 -0
  215. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +53 -0
  216. package/docs/architecture/diagrams/.gitkeep +1 -0
  217. package/docs/architecture/diagrams/agentic-dev-plugin-architecture.html +186 -0
  218. package/docs/architecture/domains/.gitkeep +0 -0
  219. package/docs/architecture/domains/public-surface.md +30 -0
  220. package/docs/architecture/domains/runtime-harness.md +33 -0
  221. package/docs/architecture/domains/verification.md +33 -0
  222. package/docs/architecture/domains/workflow-engine.md +30 -0
  223. package/docs/architecture/global-hook-runtime.md +162 -0
  224. package/docs/architecture/history.md +38 -0
  225. package/docs/architecture/index.md +114 -0
  226. package/docs/architecture/ios-semantic-automation-provider-v2.md +166 -0
  227. package/docs/architecture/modules/.gitkeep +0 -0
  228. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +24 -0
  229. package/docs/architecture/requests/.gitkeep +1 -0
  230. package/docs/architecture/requests/archive/2026/20260528-154740-ai-hooks-ai-hooks-hook-input-sh.md +59 -0
  231. package/docs/architecture/requests/archive/2026/20260528-154816-assets-hooks-assets-hooks-hook-input-sh.md +59 -0
  232. package/docs/architecture/requests/archive/2026/20260528-161851-ai-harness-workflow-contract-json-ai-harness-workflow-contract-json.md +59 -0
  233. package/docs/architecture/requests/archive/2026/20260528-161853-scripts-check-task-workflow-sh-scripts-check-task-workflow-sh.md +59 -0
  234. package/docs/architecture/requests/archive/2026/20260528-161911-assets-workflow-contract-v1-json-assets-workflow-contract-v1-json.md +59 -0
  235. package/docs/architecture/requests/archive/2026/20260528-222416-ai-hooks-ai-hooks-hook-input-sh.md +59 -0
  236. package/docs/architecture/requests/archive/2026/20260528-222444-ai-hooks-ai-hooks-pre-edit-guard-sh.md +59 -0
  237. package/docs/architecture/requests/archive/2026/20260528-222457-ai-hooks-ai-hooks-pre-edit-guard-sh.md +59 -0
  238. package/docs/architecture/requests/archive/2026/20260528-222648-ai-hooks-ai-hooks-pre-edit-guard-sh.md +59 -0
  239. package/docs/architecture/requests/archive/2026/20260528-222705-ai-hooks-ai-hooks-worktree-guard-sh.md +59 -0
  240. package/docs/architecture/requests/archive/2026/20260528-222726-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
  241. package/docs/architecture/requests/archive/2026/20260528-222727-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
  242. package/docs/architecture/requests/archive/2026/20260528-224736-ai-hooks-ai-hooks-hook-input-sh.md +59 -0
  243. package/docs/architecture/requests/archive/2026/20260528-233259-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
  244. package/docs/architecture/requests/archive/2026/20260528-233335-assets-hooks-assets-hooks-prompt-guard-sh.md +59 -0
  245. package/docs/architecture/requests/archive/2026/20260528-233456-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
  246. package/docs/architecture/requests/archive/2026/20260528-233457-assets-hooks-assets-hooks-prompt-guard-sh.md +59 -0
  247. package/docs/architecture/requests/archive/2026/20260528-233637-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
  248. package/docs/architecture/requests/archive/2026/20260528-233638-assets-hooks-assets-hooks-prompt-guard-sh.md +59 -0
  249. package/docs/architecture/requests/archive/2026/20260529-000322-root-package-json.md +59 -0
  250. package/docs/architecture/requests/archive/2026/20260529-004238-ai-hooks-ai-hooks-lib-workflow-state-sh.md +59 -0
  251. package/docs/architecture/requests/archive/2026/20260529-020654-ai-harness-policy-json-ai-harness-policy-json.md +63 -0
  252. package/docs/architecture/requests/archive/2026/20260529-094236-ai-hooks-ai-hooks-prompt-guard-sh.md +60 -0
  253. package/docs/architecture/requests/archive/2026/20260529-094323-assets-hooks-assets-hooks-prompt-guard-sh.md +60 -0
  254. package/docs/architecture/requests/archive/2026/20260529-094331-ai-hooks-ai-hooks-prompt-guard-sh.md +60 -0
  255. package/docs/architecture/requests/archive/2026/20260529-094339-assets-hooks-assets-hooks-prompt-guard-sh.md +60 -0
  256. package/docs/architecture/requests/archive/2026/20260529-094430-assets-hooks-assets-hooks-session-start-context-sh.md +60 -0
  257. package/docs/architecture/requests/archive/2026/20260529-094446-ai-hooks-ai-hooks-session-start-context-sh.md +60 -0
  258. package/docs/architecture/requests/archive/2026/20260613-002040-runtime-harness-hook-adapters.md +68 -0
  259. package/docs/architecture/requests/archive/2026/root.md +68 -0
  260. package/docs/architecture/requests/archive/2026/runtime-harness-hook-adapters.md +76 -0
  261. package/docs/architecture/requests/archive/2026/verification-evals-checks.md +68 -0
  262. package/docs/architecture/requests/archive/2026/workflow-engine-contract-assets.md +69 -0
  263. package/docs/architecture/reviews/2026-07-11-access-surface-review.md +99 -0
  264. package/docs/architecture/snapshots/.gitkeep +1 -0
  265. package/docs/forge-autonomous-goal-loop.md +7 -0
  266. package/docs/forge-chatgpt-browser-engine.md +11 -0
  267. package/docs/forge-chatgpt-mcp-setup.md +239 -0
  268. package/docs/forge-chatgpt-supervised-automation.md +11 -0
  269. package/docs/forge-github-issue-launcher.md +7 -0
  270. package/docs/forge-plugin-management.md +95 -0
  271. package/docs/forge-provider-configuration.md +7 -0
  272. package/docs/forge-runtime-self-healing-loop.md +7 -0
  273. package/docs/images/forge-banner-cn.svg +1 -0
  274. package/docs/images/forge-banner.svg +1 -0
  275. package/docs/images/forge-controller-flow.svg +1 -0
  276. package/docs/images/image.png +0 -0
  277. package/docs/images/repo-harness-gptpro-cn.png +0 -0
  278. package/docs/images/repo-harness-gptpro.png +0 -0
  279. package/docs/images/repo-harness-hook-carrot.png +0 -0
  280. package/docs/operations/chatgpt-personal-assistant-runtime.md +83 -0
  281. package/docs/operations/checkout-route-integrity.md +22 -0
  282. package/docs/operations/controller-browser-plugin.md +299 -0
  283. package/docs/operations/controller-desktop-plugin.md +112 -0
  284. package/docs/operations/controller-performance-and-502.md +126 -0
  285. package/docs/operations/controller-reliability-runbook.md +134 -0
  286. package/docs/operations/environment-hardening.md +50 -0
  287. package/docs/operations/features.md +45 -0
  288. package/docs/operations/features.zh-CN.md +45 -0
  289. package/docs/operations/github-repository.md +60 -0
  290. package/docs/operations/gmail-assistant-routines.md +186 -0
  291. package/docs/operations/homebrew.md +26 -0
  292. package/docs/operations/local-system-assistant.md +46 -0
  293. package/docs/operations/local-system-assistant.zh-CN.md +46 -0
  294. package/docs/operations/mcp-tool-exposure.md +58 -0
  295. package/docs/operations/mobile-intents-shortcuts.md +117 -0
  296. package/docs/operations/open-source-release-hygiene.md +31 -0
  297. package/docs/operations/personal-assistant-operator-guide.md +61 -0
  298. package/docs/operations/platform-support.md +62 -0
  299. package/docs/operations/platform-support.zh-CN.md +61 -0
  300. package/docs/operations/provider-configuration.md +31 -0
  301. package/docs/operations/releasing.md +86 -0
  302. package/docs/operations/releasing.zh-CN.md +86 -0
  303. package/docs/operations/route-session-concurrency-baseline.json +893 -0
  304. package/docs/operations/route-session-concurrency-baseline.md +94 -0
  305. package/docs/operations/runtime-performance-diagnostics.md +14 -0
  306. package/docs/operations/sqlite-control-plane-recovery.md +65 -0
  307. package/docs/operations/standalone-disaster-recovery.md +136 -0
  308. package/docs/operations/troubleshooting.md +72 -0
  309. package/docs/operations/troubleshooting.zh-CN.md +70 -0
  310. package/docs/public-usage-guide.md +33 -0
  311. package/docs/public-usage-guide.zh-CN.md +33 -0
  312. package/docs/tutorials/01-install-and-start.md +93 -0
  313. package/docs/tutorials/01-install-and-start.zh-CN.md +93 -0
  314. package/docs/tutorials/02-connect-chatgpt.md +82 -0
  315. package/docs/tutorials/02-connect-chatgpt.zh-CN.md +80 -0
  316. package/docs/tutorials/03-first-repository-task.md +57 -0
  317. package/docs/tutorials/03-first-repository-task.zh-CN.md +57 -0
  318. package/docs/tutorials/README.md +13 -0
  319. package/docs/tutorials/README.zh-CN.md +13 -0
  320. package/docs/wiki/Architecture.md +85 -0
  321. package/docs/wiki/Core-Concepts.md +27 -0
  322. package/docs/wiki/Home.md +36 -0
  323. package/docs/wiki/Implementation.md +172 -0
  324. package/docs/wiki/Installation.md +50 -0
  325. package/docs/wiki/Integrations.md +29 -0
  326. package/docs/wiki/Operations.md +26 -0
  327. package/docs/wiki/Quick-Start.md +46 -0
  328. package/docs/wiki/Releases-and-Upgrades.md +34 -0
  329. package/docs/wiki/Runtime-Architecture.md +50 -0
  330. package/docs/wiki/Security-Model.md +31 -0
  331. package/docs/wiki/Troubleshooting.md +38 -0
  332. package/docs/wiki/Work-Lifecycle.md +31 -0
  333. package/docs/wiki/_Sidebar.md +21 -0
  334. package/install.ps1 +48 -0
  335. package/install.sh +66 -0
  336. package/package.json +156 -0
  337. package/scripts/activate-source-baseline.ts +335 -0
  338. package/scripts/architecture-event.ts +822 -0
  339. package/scripts/architecture-queue.sh +647 -0
  340. package/scripts/archive-architecture-request.sh +244 -0
  341. package/scripts/archive-workflow.sh +295 -0
  342. package/scripts/assemble-template.ts +1172 -0
  343. package/scripts/benchmark-controller-hotpath.ts +212 -0
  344. package/scripts/benchmark-controller-round2.ts +139 -0
  345. package/scripts/benchmark-ios-agent-device.ts +514 -0
  346. package/scripts/benchmark-route-session-concurrency.ts +714 -0
  347. package/scripts/benchmark-thin-harness-gateway-ab.ts +632 -0
  348. package/scripts/benchmark-thin-harness-mcp-e2e.ts +479 -0
  349. package/scripts/benchmark-thin-harness.ts +251 -0
  350. package/scripts/bootstrap-runtime-maintenance-recovery.sh +183 -0
  351. package/scripts/canary-global-hook.sh +263 -0
  352. package/scripts/capability-config.ts +394 -0
  353. package/scripts/capability-resolver.ts +505 -0
  354. package/scripts/capture-plan.sh +335 -0
  355. package/scripts/check-agent-tooling.sh +1549 -0
  356. package/scripts/check-architecture-sync.sh +373 -0
  357. package/scripts/check-brain-manifest.sh +255 -0
  358. package/scripts/check-ci.sh +16 -0
  359. package/scripts/check-context-files.sh +49 -0
  360. package/scripts/check-deploy-sql-order.sh +117 -0
  361. package/scripts/check-mcp-compatibility.ts +93 -0
  362. package/scripts/check-npm-release.sh +32 -0
  363. package/scripts/check-open-source-tracked-surface.sh +146 -0
  364. package/scripts/check-package-identity.mjs +117 -0
  365. package/scripts/check-platform-support.mjs +79 -0
  366. package/scripts/check-public-docs.sh +105 -0
  367. package/scripts/check-public-release-surface.sh +19 -0
  368. package/scripts/check-release-published.sh +57 -0
  369. package/scripts/check-release-readiness.sh +43 -0
  370. package/scripts/check-release-version.mjs +74 -0
  371. package/scripts/check-runtime-architecture.mjs +593 -0
  372. package/scripts/check-runtime-env.mjs +89 -0
  373. package/scripts/check-skill-version.ts +193 -0
  374. package/scripts/check-tarball-install-smoke.sh +66 -0
  375. package/scripts/check-task-sync.sh +65 -0
  376. package/scripts/check-task-workflow.sh +1002 -0
  377. package/scripts/check-third-party-notices.mjs +36 -0
  378. package/scripts/codex-handoff-resume.sh +269 -0
  379. package/scripts/complete-control-plane-cutover.ts +126 -0
  380. package/scripts/context-contract-sync.sh +516 -0
  381. package/scripts/contract-run.ts +465 -0
  382. package/scripts/contract-worktree.sh +725 -0
  383. package/scripts/controller-ngrok-rotation.sh +678 -0
  384. package/scripts/create-project-dirs.sh +282 -0
  385. package/scripts/ensure-codegraph.sh +16 -0
  386. package/scripts/ensure-task-workflow.sh +1218 -0
  387. package/scripts/export-requirement-portfolio.ts +28 -0
  388. package/scripts/factor-lab-check.sh +73 -0
  389. package/scripts/factor-lab-new.sh +96 -0
  390. package/scripts/factor-lab-promote.sh +86 -0
  391. package/scripts/factor-lab-reject.sh +68 -0
  392. package/scripts/harness-trace-grade.sh +150 -0
  393. package/scripts/heartbeat-triage.sh +361 -0
  394. package/scripts/hook-dispatch-diet-report.ts +234 -0
  395. package/scripts/hook-shim.sh +93 -0
  396. package/scripts/init-project.sh +505 -0
  397. package/scripts/initializer-question-pack.ts +200 -0
  398. package/scripts/inspect-project-state.ts +280 -0
  399. package/scripts/install-desktop-operator-registration.ts +45 -0
  400. package/scripts/install-standalone-recovery.ts +74 -0
  401. package/scripts/lib/AGENTS.md +13 -0
  402. package/scripts/lib/CLAUDE.md +13 -0
  403. package/scripts/lib/controller-home-env.sh +69 -0
  404. package/scripts/lib/project-init-lib.sh +2759 -0
  405. package/scripts/load-standalone-recovery.sh +17 -0
  406. package/scripts/loop-engine-cutover-gate.ts +324 -0
  407. package/scripts/maintenance-triage.sh +167 -0
  408. package/scripts/migrate-project-template.sh +1189 -0
  409. package/scripts/migrate-requirement-portfolio.ts +86 -0
  410. package/scripts/migrate-workflow-docs.ts +413 -0
  411. package/scripts/new-plan.sh +183 -0
  412. package/scripts/new-spec.sh +50 -0
  413. package/scripts/new-sprint.sh +49 -0
  414. package/scripts/open-source-audit-allowlist.txt +46 -0
  415. package/scripts/package-source-archive.sh +147 -0
  416. package/scripts/plan-to-todo.sh +799 -0
  417. package/scripts/prepare-codex-handoff.sh +203 -0
  418. package/scripts/prepare-handoff.sh +81 -0
  419. package/scripts/public-release-files.txt +39 -0
  420. package/scripts/public-release.ts +174 -0
  421. package/scripts/publish-release-tarball.sh +27 -0
  422. package/scripts/refresh-current-status.sh +469 -0
  423. package/scripts/refresh-ios-physical-runtime.ts +196 -0
  424. package/scripts/repair-executable-modes.ts +8 -0
  425. package/scripts/rollout-all-registered-repos.sh +7 -0
  426. package/scripts/route-nl-vs-ts-eval.ts +679 -0
  427. package/scripts/run-bun-test-file.ts +182 -0
  428. package/scripts/run-governed-gate.ts +140 -0
  429. package/scripts/run-mobile-monitor-bridge.ts +71 -0
  430. package/scripts/run-skill-evals.ts +1022 -0
  431. package/scripts/run-skill-hook.ts +244 -0
  432. package/scripts/run-supervised-command.ts +24 -0
  433. package/scripts/run-tests-portable.sh +20 -0
  434. package/scripts/select-agent-context-blocks.sh +66 -0
  435. package/scripts/setup-plugins.sh +43 -0
  436. package/scripts/ship-worktrees.sh +561 -0
  437. package/scripts/smoke-browser-cdp-bridge.ts +93 -0
  438. package/scripts/smoke-chatgpt-supervised-automation.ts +208 -0
  439. package/scripts/smoke-ios-physical-device.ts +114 -0
  440. package/scripts/smoke-mcp-http-runtime.ts +216 -0
  441. package/scripts/smoke-mcp-tool-surface.ts +117 -0
  442. package/scripts/smoke-runtime-recovery.ts +220 -0
  443. package/scripts/smoke-schedule-engine.ts +283 -0
  444. package/scripts/sprint-backlog.sh +837 -0
  445. package/scripts/stage-runtime-release.ts +38 -0
  446. package/scripts/summarize-failures.sh +125 -0
  447. package/scripts/switch-plan.sh +153 -0
  448. package/scripts/sync-brain-docs.sh +381 -0
  449. package/scripts/sync-codex-installed-copies.sh +183 -0
  450. package/scripts/test-governance.ts +75 -0
  451. package/scripts/verify-contract.sh +705 -0
  452. package/scripts/verify-forge-runtime.sh +31 -0
  453. package/scripts/verify-sprint.sh +680 -0
  454. package/scripts/windows-paths.d.mts +7 -0
  455. package/scripts/windows-paths.mjs +28 -0
  456. package/scripts/workflow-contract.ts +206 -0
  457. package/scripts/workstream-sync.sh +263 -0
  458. package/src/cli/agent-jobs/executable-resolver.ts +289 -0
  459. package/src/cli/agent-jobs/executor-health.ts +252 -0
  460. package/src/cli/agent-jobs/integration.ts +963 -0
  461. package/src/cli/agent-jobs/job-manager.ts +2030 -0
  462. package/src/cli/agent-jobs/types.ts +219 -0
  463. package/src/cli/agent-jobs/worker-lifecycle.ts +288 -0
  464. package/src/cli/chatgpt-browser/bind-server.ts +504 -0
  465. package/src/cli/chatgpt-browser/binding.ts +140 -0
  466. package/src/cli/chatgpt-browser/bridge-extension.ts +221 -0
  467. package/src/cli/chatgpt-browser/bridge-provider.ts +268 -0
  468. package/src/cli/chatgpt-browser/engine.ts +569 -0
  469. package/src/cli/chatgpt-browser/file-policy.ts +158 -0
  470. package/src/cli/chatgpt-browser/native-provider.ts +553 -0
  471. package/src/cli/chatgpt-browser/oracle-provider.ts +437 -0
  472. package/src/cli/chatgpt-browser/prompt-assembler.ts +29 -0
  473. package/src/cli/chatgpt-browser/session-store.ts +301 -0
  474. package/src/cli/chatgpt-browser/types.ts +172 -0
  475. package/src/cli/commands/adopt-plan.ts +186 -0
  476. package/src/cli/commands/brain-root.ts +132 -0
  477. package/src/cli/commands/brain.ts +609 -0
  478. package/src/cli/commands/capability-context.ts +613 -0
  479. package/src/cli/commands/chatgpt.ts +424 -0
  480. package/src/cli/commands/controller.ts +680 -0
  481. package/src/cli/commands/docs.ts +103 -0
  482. package/src/cli/commands/doctor.ts +476 -0
  483. package/src/cli/commands/global-runtime.ts +323 -0
  484. package/src/cli/commands/hook.ts +34 -0
  485. package/src/cli/commands/init-hook.ts +870 -0
  486. package/src/cli/commands/init.ts +829 -0
  487. package/src/cli/commands/install.ts +86 -0
  488. package/src/cli/commands/mcp.ts +315 -0
  489. package/src/cli/commands/migrate.ts +154 -0
  490. package/src/cli/commands/plugin.ts +74 -0
  491. package/src/cli/commands/prompt-guard-decision.ts +238 -0
  492. package/src/cli/commands/recovery.ts +667 -0
  493. package/src/cli/commands/repository.ts +224 -0
  494. package/src/cli/commands/run.ts +23 -0
  495. package/src/cli/commands/runtime.ts +191 -0
  496. package/src/cli/commands/security.ts +440 -0
  497. package/src/cli/commands/status.ts +137 -0
  498. package/src/cli/commands/tools.ts +167 -0
  499. package/src/cli/controller/check-runner.ts +1022 -0
  500. package/src/cli/controller/codex-continuation.ts +153 -0
  501. package/src/cli/controller/completion-backlog.ts +380 -0
  502. package/src/cli/controller/completion-orchestrator.ts +1807 -0
  503. package/src/cli/controller/completion-target.ts +96 -0
  504. package/src/cli/controller/composite-operations.ts +196 -0
  505. package/src/cli/controller/composite-result.ts +130 -0
  506. package/src/cli/controller/context-pack.ts +652 -0
  507. package/src/cli/controller/execution-completion.ts +175 -0
  508. package/src/cli/controller/execution-policy.ts +392 -0
  509. package/src/cli/controller/governance.ts +594 -0
  510. package/src/cli/controller/issue-store.ts +1421 -0
  511. package/src/cli/controller/launch-agents.ts +410 -0
  512. package/src/cli/controller/legacy-issue-cutover.ts +415 -0
  513. package/src/cli/controller/lifecycle-authority.ts +16 -0
  514. package/src/cli/controller/migrated-issue-decision.ts +237 -0
  515. package/src/cli/controller/operational-plan.ts +226 -0
  516. package/src/cli/controller/postcondition.ts +134 -0
  517. package/src/cli/controller/progress.ts +656 -0
  518. package/src/cli/controller/project-state.ts +147 -0
  519. package/src/cli/controller/requirement-portfolio-export.ts +146 -0
  520. package/src/cli/controller/requirement-portfolio-migration.ts +613 -0
  521. package/src/cli/controller/run-evidence.ts +43 -0
  522. package/src/cli/controller/runtime-config.ts +92 -0
  523. package/src/cli/controller/stuck-state-migration.ts +396 -0
  524. package/src/cli/controller/task-ledger.ts +632 -0
  525. package/src/cli/controller/task-status-resolver.ts +403 -0
  526. package/src/cli/controller/types.ts +273 -0
  527. package/src/cli/controller/work-mode.ts +186 -0
  528. package/src/cli/controller/worklog.ts +201 -0
  529. package/src/cli/diagnostic-entry.ts +39 -0
  530. package/src/cli/editing/edit-session.ts +1606 -0
  531. package/src/cli/editing/executable-modes.ts +70 -0
  532. package/src/cli/github/github.ts +274 -0
  533. package/src/cli/github/plugin.ts +345 -0
  534. package/src/cli/github/session.ts +104 -0
  535. package/src/cli/hook/prompt-guard-decision.ts +238 -0
  536. package/src/cli/hook/prompt-intents.ts +534 -0
  537. package/src/cli/hook/route-registry.ts +107 -0
  538. package/src/cli/hook/runtime.ts +303 -0
  539. package/src/cli/hook/state-snapshot.ts +388 -0
  540. package/src/cli/hook-entry.ts +51 -0
  541. package/src/cli/index.ts +574 -0
  542. package/src/cli/installer/managed-entries.ts +78 -0
  543. package/src/cli/installer/shared.ts +65 -0
  544. package/src/cli/installer/targets/claude.ts +136 -0
  545. package/src/cli/installer/targets/codex.ts +174 -0
  546. package/src/cli/installer/targets/registry.ts +28 -0
  547. package/src/cli/installer/types.ts +72 -0
  548. package/src/cli/local-bridge/connector-freshness.ts +529 -0
  549. package/src/cli/local-bridge/console-view-models.ts +324 -0
  550. package/src/cli/local-bridge/dashboard.ts +1312 -0
  551. package/src/cli/local-bridge/facade-api.ts +1877 -0
  552. package/src/cli/local-bridge/job-store.ts +1451 -0
  553. package/src/cli/local-bridge/mobile-intents.ts +344 -0
  554. package/src/cli/local-bridge/mobile-monitor.ts +209 -0
  555. package/src/cli/local-bridge/server.ts +3183 -0
  556. package/src/cli/local-bridge/types.ts +176 -0
  557. package/src/cli/mcp/access-mode.ts +132 -0
  558. package/src/cli/mcp/access-tools.ts +387 -0
  559. package/src/cli/mcp/audit.ts +32 -0
  560. package/src/cli/mcp/auth.ts +402 -0
  561. package/src/cli/mcp/instructions.ts +33 -0
  562. package/src/cli/mcp/legacy-context.ts +16 -0
  563. package/src/cli/mcp/legacy-tool-service.ts +5516 -0
  564. package/src/cli/mcp/multi-repository.ts +423 -0
  565. package/src/cli/mcp/oauth.ts +226 -0
  566. package/src/cli/mcp/paths.ts +134 -0
  567. package/src/cli/mcp/policy.ts +230 -0
  568. package/src/cli/mcp/proxy-env.ts +62 -0
  569. package/src/cli/mcp/readiness-projection.ts +24 -0
  570. package/src/cli/mcp/redaction.ts +21 -0
  571. package/src/cli/mcp/repo.ts +24 -0
  572. package/src/cli/mcp/repository-tools.ts +1295 -0
  573. package/src/cli/mcp/server.ts +341 -0
  574. package/src/cli/mcp/setup.ts +793 -0
  575. package/src/cli/mcp/tool-capability-cache.ts +87 -0
  576. package/src/cli/mcp/tools.ts +9 -0
  577. package/src/cli/mcp/toolset-names.ts +70 -0
  578. package/src/cli/mcp/toolset-selection.ts +41 -0
  579. package/src/cli/mcp/toolset.ts +300 -0
  580. package/src/cli/mcp/transports/AGENTS.md +39 -0
  581. package/src/cli/mcp/transports/CLAUDE.md +39 -0
  582. package/src/cli/mcp/transports/http.ts +1234 -0
  583. package/src/cli/mcp/transports/session-registry.ts +428 -0
  584. package/src/cli/mcp/transports/stdio.ts +8 -0
  585. package/src/cli/mcp/types.ts +41 -0
  586. package/src/cli/mcp/umbrella-tools.ts +117 -0
  587. package/src/cli/repo-adoption/reclaim-runtime.ts +681 -0
  588. package/src/cli/repositories/branch-name-policy.ts +57 -0
  589. package/src/cli/repositories/command-classifier.ts +600 -0
  590. package/src/cli/repositories/command-executor.ts +1066 -0
  591. package/src/cli/repositories/command-normalization.ts +53 -0
  592. package/src/cli/repositories/command-scope.ts +264 -0
  593. package/src/cli/repositories/controller-home.ts +88 -0
  594. package/src/cli/repositories/entity-migration.ts +199 -0
  595. package/src/cli/repositories/ephemeral-workspace.ts +62 -0
  596. package/src/cli/repositories/git-command-executor.ts +301 -0
  597. package/src/cli/repositories/goal-registry.ts +239 -0
  598. package/src/cli/repositories/identity.ts +64 -0
  599. package/src/cli/repositories/local-project-onboarding.ts +539 -0
  600. package/src/cli/repositories/locks.ts +262 -0
  601. package/src/cli/repositories/registry.ts +1057 -0
  602. package/src/cli/repositories/runtime-storage.ts +411 -0
  603. package/src/cli/repositories/safe-patch.ts +421 -0
  604. package/src/cli/repositories/selected-path-actions.ts +341 -0
  605. package/src/cli/repositories/structured-git.ts +257 -0
  606. package/src/cli/repositories/types.ts +155 -0
  607. package/src/cli/repositories/umbrella.ts +134 -0
  608. package/src/cli/repositories/workbench.ts +140 -0
  609. package/src/cli/repositories/worktree-storage.ts +137 -0
  610. package/src/cli/repository/inspector.ts +637 -0
  611. package/src/cli/repository/session-cache.ts +453 -0
  612. package/src/cli/runtime/helper-runner.ts +172 -0
  613. package/src/cli/runtime-invocation.ts +318 -0
  614. package/src/cli/tools/codegraph.ts +676 -0
  615. package/src/cli/v81-entry.ts +29 -0
  616. package/src/core/adoption/gitignore-plan.ts +127 -0
  617. package/src/core/adoption/helper-wrapper-plan.ts +159 -0
  618. package/src/core/adoption/manifest-templates.ts +60 -0
  619. package/src/core/adoption/modes.ts +7 -0
  620. package/src/core/adoption/operations.ts +126 -0
  621. package/src/core/adoption/plan.ts +149 -0
  622. package/src/core/adoption/render.ts +70 -0
  623. package/src/core/adoption/rollback.ts +62 -0
  624. package/src/core/adoption/summary.ts +43 -0
  625. package/src/core/adoption/workflow-contract-asset.ts +14 -0
  626. package/src/core/adoption/workflow-contract-plan.ts +31 -0
  627. package/src/effects/fs-transaction.ts +540 -0
  628. package/src/effects/git-executable.ts +59 -0
  629. package/src/effects/managed-block.ts +86 -0
  630. package/src/effects/path-safety.ts +47 -0
  631. package/src/effects/process-runner.ts +192 -0
  632. package/src/runtime/assistant/action-proposals.ts +279 -0
  633. package/src/runtime/assistant/intent.ts +395 -0
  634. package/src/runtime/assistant/model-provider.ts +460 -0
  635. package/src/runtime/assistant/openapi.ts +223 -0
  636. package/src/runtime/assistant/policy.ts +89 -0
  637. package/src/runtime/assistant/readiness.ts +258 -0
  638. package/src/runtime/assistant/routine-runtime.ts +477 -0
  639. package/src/runtime/assistant/schedule-binding.ts +171 -0
  640. package/src/runtime/assistant/standing-grants.ts +375 -0
  641. package/src/runtime/assistant/store.ts +243 -0
  642. package/src/runtime/assistant/types.ts +135 -0
  643. package/src/runtime/context/codegraph-read-provider.ts +347 -0
  644. package/src/runtime/context/codegraph-sidecar.cjs +207 -0
  645. package/src/runtime/control-plane/dispatch-priority.ts +67 -0
  646. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +151 -0
  647. package/src/runtime/control-plane/execution/execution-identity.ts +456 -0
  648. package/src/runtime/control-plane/execution/session-store.ts +175 -0
  649. package/src/runtime/control-plane/execution/validation.ts +117 -0
  650. package/src/runtime/control-plane/execution/verification-evidence.ts +191 -0
  651. package/src/runtime/control-plane/execution/work-handle-store.ts +225 -0
  652. package/src/runtime/control-plane/execution/work-prepare-request-store.ts +159 -0
  653. package/src/runtime/control-plane/execution/work-task-receipt.ts +445 -0
  654. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +821 -0
  655. package/src/runtime/control-plane/facade/capability-registry.ts +279 -0
  656. package/src/runtime/control-plane/facade/check-normalization.ts +233 -0
  657. package/src/runtime/control-plane/facade/codex-delegation.ts +196 -0
  658. package/src/runtime/control-plane/facade/controller-session-store.ts +199 -0
  659. package/src/runtime/control-plane/facade/facade-result.ts +41 -0
  660. package/src/runtime/control-plane/facade/goal-workloop-access.ts +177 -0
  661. package/src/runtime/control-plane/facade/goal-workloop.ts +1216 -0
  662. package/src/runtime/control-plane/facade/handoff-inbox-store.ts +221 -0
  663. package/src/runtime/control-plane/facade/index.ts +16 -0
  664. package/src/runtime/control-plane/facade/operation-digest.ts +528 -0
  665. package/src/runtime/control-plane/facade/plan-contract-store.ts +403 -0
  666. package/src/runtime/control-plane/facade/policy-gate.ts +149 -0
  667. package/src/runtime/control-plane/facade/requirement-board.ts +280 -0
  668. package/src/runtime/control-plane/facade/self-healing-loop.ts +555 -0
  669. package/src/runtime/control-plane/facade/suggested-actions.ts +108 -0
  670. package/src/runtime/control-plane/facade/types.ts +729 -0
  671. package/src/runtime/control-plane/facade/work-admission-policy.ts +93 -0
  672. package/src/runtime/control-plane/facade/work-continuation.ts +104 -0
  673. package/src/runtime/control-plane/facade/work-contract-store.ts +1118 -0
  674. package/src/runtime/control-plane/facade/work-task-projection.ts +66 -0
  675. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +365 -0
  676. package/src/runtime/control-plane/global-scheduler/scheduler.ts +920 -0
  677. package/src/runtime/control-plane/global-scheduler/wake-signal.ts +89 -0
  678. package/src/runtime/control-plane/goal-loop/config-facade.ts +700 -0
  679. package/src/runtime/control-plane/goal-loop/config-store.ts +570 -0
  680. package/src/runtime/control-plane/goal-loop/config-types.ts +213 -0
  681. package/src/runtime/control-plane/goal-loop/executor-router.ts +109 -0
  682. package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +149 -0
  683. package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +304 -0
  684. package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +1001 -0
  685. package/src/runtime/control-plane/goal-loop/handoff-packet.ts +160 -0
  686. package/src/runtime/control-plane/goal-loop/index.ts +13 -0
  687. package/src/runtime/control-plane/goal-loop/local-tools.ts +290 -0
  688. package/src/runtime/control-plane/goal-loop/policy-gates.ts +203 -0
  689. package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +93 -0
  690. package/src/runtime/control-plane/goal-loop/provider-registry.ts +545 -0
  691. package/src/runtime/control-plane/goal-loop/types.ts +378 -0
  692. package/src/runtime/control-plane/governance/access-policy.ts +147 -0
  693. package/src/runtime/control-plane/governance/authorization.ts +195 -0
  694. package/src/runtime/control-plane/governance/external-effects.ts +43 -0
  695. package/src/runtime/control-plane/launcher/thin-launcher.ts +97 -0
  696. package/src/runtime/control-plane/persistence/metadata-payload-policy.ts +53 -0
  697. package/src/runtime/control-plane/persistence/requirement-store.ts +241 -0
  698. package/src/runtime/control-plane/persistence/sqlite-store.ts +539 -0
  699. package/src/runtime/control-plane/release-retention.ts +447 -0
  700. package/src/runtime/control-plane/repo-actor/actor.ts +181 -0
  701. package/src/runtime/control-plane/repo-actor/registry.ts +20 -0
  702. package/src/runtime/control-plane/routing/index.ts +1 -0
  703. package/src/runtime/control-plane/routing/route-policy.ts +379 -0
  704. package/src/runtime/control-plane/runtime-cleanup.ts +727 -0
  705. package/src/runtime/control-plane/runtime-generation.ts +509 -0
  706. package/src/runtime/control-plane/runtime-pid-ownership.ts +11 -0
  707. package/src/runtime/control-plane/runtime-status-client.ts +90 -0
  708. package/src/runtime/control-plane/startup-recovery.ts +198 -0
  709. package/src/runtime/diagnostics/connectivity-observability.ts +475 -0
  710. package/src/runtime/diagnostics/mcp-timing.ts +64 -0
  711. package/src/runtime/diagnostics/performance.ts +379 -0
  712. package/src/runtime/diagnostics/process-facade.ts +350 -0
  713. package/src/runtime/diagnostics/read-only-tool.ts +226 -0
  714. package/src/runtime/evidence/artifact-store.ts +154 -0
  715. package/src/runtime/evidence/event-ledger.ts +80 -0
  716. package/src/runtime/evidence/evidence-store.ts +68 -0
  717. package/src/runtime/evidence/process-check-receipt.ts +43 -0
  718. package/src/runtime/evidence/result-store.ts +209 -0
  719. package/src/runtime/evidence/sensitive-output.ts +353 -0
  720. package/src/runtime/execution/jobs/child-reference.ts +124 -0
  721. package/src/runtime/execution/jobs/legacy-adapter.ts +22 -0
  722. package/src/runtime/execution/jobs/receipt-recovery.ts +119 -0
  723. package/src/runtime/execution/jobs/receipt-store.ts +243 -0
  724. package/src/runtime/execution/jobs/store.ts +737 -0
  725. package/src/runtime/execution/jobs/timeouts.ts +109 -0
  726. package/src/runtime/execution/jobs/types.ts +230 -0
  727. package/src/runtime/execution/jobs/wait.ts +45 -0
  728. package/src/runtime/execution/process-runtime/canary.ts +26 -0
  729. package/src/runtime/execution/process-runtime/check-facade.ts +272 -0
  730. package/src/runtime/execution/process-runtime/check-receipt.ts +185 -0
  731. package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +60 -0
  732. package/src/runtime/execution/process-runtime/command-facade.ts +321 -0
  733. package/src/runtime/execution/process-runtime/gc.ts +171 -0
  734. package/src/runtime/execution/process-runtime/index.ts +9 -0
  735. package/src/runtime/execution/process-runtime/interactive-admission.ts +23 -0
  736. package/src/runtime/execution/process-runtime/process-runner-entry.ts +466 -0
  737. package/src/runtime/execution/process-runtime/resource-claims.ts +440 -0
  738. package/src/runtime/execution/process-runtime/runtime.ts +1816 -0
  739. package/src/runtime/execution/process-runtime/store.ts +687 -0
  740. package/src/runtime/execution/process-runtime/types.ts +352 -0
  741. package/src/runtime/execution/thin-harness/async-process.ts +181 -0
  742. package/src/runtime/execution/thin-harness/batch-executor.ts +671 -0
  743. package/src/runtime/execution/thin-harness/execution-router.ts +700 -0
  744. package/src/runtime/execution/thin-harness/fast-executor.ts +1263 -0
  745. package/src/runtime/execution/thin-harness/fast-receipt.ts +235 -0
  746. package/src/runtime/execution/thin-harness/fingerprint-worker.ts +191 -0
  747. package/src/runtime/execution/thin-harness/index.ts +13 -0
  748. package/src/runtime/execution/thin-harness/latency-trace.ts +107 -0
  749. package/src/runtime/execution/thin-harness/lightweight-lanes.ts +745 -0
  750. package/src/runtime/execution/thin-harness/mutation-gate.ts +578 -0
  751. package/src/runtime/execution/thin-harness/proposal-store.ts +409 -0
  752. package/src/runtime/execution/thin-harness/request-ledger.ts +595 -0
  753. package/src/runtime/execution/thin-harness/search-worker.ts +114 -0
  754. package/src/runtime/execution/thin-harness/types.ts +313 -0
  755. package/src/runtime/execution/thin-harness/workspace-savepoint.ts +333 -0
  756. package/src/runtime/execution/workers/executor.ts +687 -0
  757. package/src/runtime/execution/workers/ownership.ts +94 -0
  758. package/src/runtime/execution/workers/worker-entry.ts +277 -0
  759. package/src/runtime/gateway/mcp/execution-tools.ts +2009 -0
  760. package/src/runtime/gateway/mcp/persisted-check-process.ts +255 -0
  761. package/src/runtime/gateway/mcp/process-tools.ts +230 -0
  762. package/src/runtime/gateway/mcp/resource-policy.ts +195 -0
  763. package/src/runtime/gateway/mcp/router.ts +1088 -0
  764. package/src/runtime/gateway/mcp/runtime-tools.ts +5994 -0
  765. package/src/runtime/gateway/mcp/work-validation-reconciler.ts +219 -0
  766. package/src/runtime/health/evaluator.ts +474 -0
  767. package/src/runtime/health/index.ts +2 -0
  768. package/src/runtime/health/operational-view.ts +198 -0
  769. package/src/runtime/maintenance/cleanup.ts +419 -0
  770. package/src/runtime/model-clients/deepseek-adapter.ts +312 -0
  771. package/src/runtime/model-clients/index.ts +2 -0
  772. package/src/runtime/model-clients/types.ts +101 -0
  773. package/src/runtime/observability/gateway-contention-metrics.ts +129 -0
  774. package/src/runtime/observability/route-session-benchmark.ts +110 -0
  775. package/src/runtime/personal-assistant/gmail-triage-manager.ts +231 -0
  776. package/src/runtime/personal-assistant/reporting-runtime.ts +344 -0
  777. package/src/runtime/personal-assistant/triage-runtime.ts +748 -0
  778. package/src/runtime/plugins/app-store-connect-adapter.ts +868 -0
  779. package/src/runtime/plugins/browser-adapter.ts +2812 -0
  780. package/src/runtime/plugins/browser-automation-service.ts +46 -0
  781. package/src/runtime/plugins/browser-handoff-host.ts +304 -0
  782. package/src/runtime/plugins/browser-handoff.ts +371 -0
  783. package/src/runtime/plugins/browser-macos-bridge.ts +865 -0
  784. package/src/runtime/plugins/browser-node-bridge-host.ts +64 -0
  785. package/src/runtime/plugins/browser-node-bridge.ts +249 -0
  786. package/src/runtime/plugins/desktop-adapter.ts +374 -0
  787. package/src/runtime/plugins/desktop-operator-registration.ts +418 -0
  788. package/src/runtime/plugins/errors.ts +39 -0
  789. package/src/runtime/plugins/execution-origin.ts +26 -0
  790. package/src/runtime/plugins/external-adapter.ts +322 -0
  791. package/src/runtime/plugins/external-registration.ts +308 -0
  792. package/src/runtime/plugins/external-unix-socket-probe.cjs +79 -0
  793. package/src/runtime/plugins/external-unix-socket.ts +238 -0
  794. package/src/runtime/plugins/first-party-registry.ts +37 -0
  795. package/src/runtime/plugins/github-adapter.ts +266 -0
  796. package/src/runtime/plugins/gmail-adapter.ts +729 -0
  797. package/src/runtime/plugins/google-calendar-adapter.ts +468 -0
  798. package/src/runtime/plugins/google-shared.ts +578 -0
  799. package/src/runtime/plugins/google-tasks-adapter.ts +535 -0
  800. package/src/runtime/plugins/interaction-session.ts +252 -0
  801. package/src/runtime/plugins/ios/agent-device-capabilities.ts +258 -0
  802. package/src/runtime/plugins/ios/agent-device-failures.ts +95 -0
  803. package/src/runtime/plugins/ios/agent-device-provider.ts +63 -0
  804. package/src/runtime/plugins/ios/agent-device-typed-provider.ts +268 -0
  805. package/src/runtime/plugins/ios/app-adapters.ts +122 -0
  806. package/src/runtime/plugins/ios-adapter.ts +509 -0
  807. package/src/runtime/plugins/ios-agent-device.ts +2311 -0
  808. package/src/runtime/plugins/ios-physical-device.ts +955 -0
  809. package/src/runtime/plugins/local-system-adapter.ts +1016 -0
  810. package/src/runtime/plugins/macos-capability-broker.ts +73 -0
  811. package/src/runtime/plugins/managed-process-adapter.ts +366 -0
  812. package/src/runtime/plugins/resend-adapter.ts +506 -0
  813. package/src/runtime/plugins/store.ts +1025 -0
  814. package/src/runtime/plugins/types.ts +138 -0
  815. package/src/runtime/projections/controller-context.ts +596 -0
  816. package/src/runtime/projections/git-status-sampler.ts +84 -0
  817. package/src/runtime/projections/invalidation.ts +250 -0
  818. package/src/runtime/projections/materialized-view.ts +694 -0
  819. package/src/runtime/recovery/actions.ts +158 -0
  820. package/src/runtime/recovery/audit.ts +38 -0
  821. package/src/runtime/recovery/classifier.ts +163 -0
  822. package/src/runtime/recovery/index.ts +9 -0
  823. package/src/runtime/recovery/local-jobs-repair.ts +393 -0
  824. package/src/runtime/recovery/maintenance-executor.ts +822 -0
  825. package/src/runtime/recovery/patch-handoff.ts +50 -0
  826. package/src/runtime/recovery/probe.ts +308 -0
  827. package/src/runtime/recovery/store.ts +35 -0
  828. package/src/runtime/recovery/types.ts +175 -0
  829. package/src/runtime/release/identity.ts +101 -0
  830. package/src/runtime/release/release-gate.ts +137 -0
  831. package/src/runtime/resources/claims/conflicts.ts +205 -0
  832. package/src/runtime/resources/index.ts +1 -0
  833. package/src/runtime/resources/leases/store.ts +539 -0
  834. package/src/runtime/resources/leases/types.ts +50 -0
  835. package/src/runtime/resources/ownership.ts +72 -0
  836. package/src/runtime/root/controller-services.ts +42 -0
  837. package/src/runtime/root/entry.ts +70 -0
  838. package/src/runtime/root/gateway-adapter.ts +46 -0
  839. package/src/runtime/root/local-bridge.ts +72 -0
  840. package/src/runtime/root/mcp-transport.ts +198 -0
  841. package/src/runtime/root/ownership.ts +94 -0
  842. package/src/runtime/root/readiness.ts +69 -0
  843. package/src/runtime/root/release-manifest.ts +147 -0
  844. package/src/runtime/root/release-materialize.ts +509 -0
  845. package/src/runtime/root/release-store.ts +236 -0
  846. package/src/runtime/root/runtime.ts +318 -0
  847. package/src/runtime/root/scheduler.ts +58 -0
  848. package/src/runtime/root/service-runner-entry.ts +20 -0
  849. package/src/runtime/root/service-runner.ts +69 -0
  850. package/src/runtime/root/service.ts +291 -0
  851. package/src/runtime/root/status.ts +127 -0
  852. package/src/runtime/root/types.ts +112 -0
  853. package/src/runtime/root/write-fence.ts +309 -0
  854. package/src/runtime/safe-tooling/browser-safe.ts +133 -0
  855. package/src/runtime/safe-tooling/external-filesystem.ts +304 -0
  856. package/src/runtime/safe-tooling/google-credential-store.ts +95 -0
  857. package/src/runtime/safe-tooling/google-oauth-broker.ts +286 -0
  858. package/src/runtime/safe-tooling/index.ts +11 -0
  859. package/src/runtime/safe-tooling/ios-development.ts +1039 -0
  860. package/src/runtime/safe-tooling/job-summary.ts +361 -0
  861. package/src/runtime/safe-tooling/plugin-summary.ts +53 -0
  862. package/src/runtime/safe-tooling/resend-oauth.ts +387 -0
  863. package/src/runtime/safe-tooling/review-artifacts.ts +133 -0
  864. package/src/runtime/safe-tooling/types.ts +103 -0
  865. package/src/runtime/safe-tooling/workspace-auth.ts +116 -0
  866. package/src/runtime/shared/bounded-child-supervisor.ts +235 -0
  867. package/src/runtime/shared/idempotent-retry.ts +128 -0
  868. package/src/runtime/shared/json-files.ts +43 -0
  869. package/src/runtime/shared/local-bridge-surface.ts +231 -0
  870. package/src/runtime/shared/managed-env.ts +154 -0
  871. package/src/runtime/shared/node-ts-loader.mjs +50 -0
  872. package/src/runtime/shared/process-environment.ts +97 -0
  873. package/src/runtime/shared/process-identity.ts +72 -0
  874. package/src/runtime/shared/process-tree.ts +227 -0
  875. package/src/runtime/shared/response-budget.ts +246 -0
  876. package/src/runtime/standalone-recovery/core.ts +2275 -0
  877. package/src/runtime/standalone-recovery/entry.ts +686 -0
  878. package/src/runtime/standalone-recovery/http-transport.ts +317 -0
  879. package/src/runtime/standalone-recovery/installer.ts +747 -0
  880. package/src/runtime/standalone-recovery/release.ts +241 -0
  881. package/src/runtime/watchdog/workflow-watchdog.ts +118 -0
  882. package/src/runtime/workflow/campaigns/cleanup.ts +263 -0
  883. package/src/runtime/workflow/campaigns/engine.ts +112 -0
  884. package/src/runtime/workflow/campaigns/normalize.ts +100 -0
  885. package/src/runtime/workflow/campaigns/review.ts +315 -0
  886. package/src/runtime/workflow/campaigns/store.ts +526 -0
  887. package/src/runtime/workflow/campaigns/supervisor.ts +112 -0
  888. package/src/runtime/workflow/campaigns/types.ts +290 -0
  889. package/src/runtime/workflow/campaigns/workspace-agent.ts +155 -0
  890. package/src/runtime/workflow/campaigns/workspace.ts +200 -0
  891. package/src/runtime/workflow/findings/store.ts +165 -0
  892. package/src/runtime/workflow/findings/types.ts +36 -0
  893. package/src/runtime/workflow/portfolio/engine.ts +20 -0
  894. package/src/runtime/workflow/portfolio/store.ts +185 -0
  895. package/src/runtime/workflow/portfolio/types.ts +29 -0
  896. package/src/runtime/workflow/schedules/engine.ts +620 -0
  897. package/src/runtime/workflow/schedules/settlement.ts +144 -0
  898. package/src/runtime/workflow/schedules/store.ts +417 -0
  899. package/src/runtime/workflow/schedules/types.ts +124 -0
  900. package/src/runtime/workspace-targets/index.ts +24 -0
  901. package/src/runtime/workspace-targets/target-grant.ts +721 -0
  902. package/src/testing/test-governance.ts +626 -0
  903. package/src/version.ts +21 -0
@@ -0,0 +1,2759 @@
1
+ #!/bin/bash
2
+ # Shared install helpers for forge scaffolding scripts.
3
+
4
+ PI_RUNTIME_BLOCK_BEGIN="# BEGIN: claude-runtime-temp (managed by forge)"
5
+ PI_RUNTIME_BLOCK_END="# END: claude-runtime-temp"
6
+ PI_DEFAULT_GITIGNORE_CONTENT=$(cat <<'EOF_GITIGNORE'
7
+ # Dependencies
8
+ node_modules/
9
+
10
+ # Build artifacts
11
+ artifacts/
12
+ coverage/
13
+ *.tar.gz
14
+ *.tgz
15
+
16
+ # External references
17
+ _ref/
18
+ .codegraph/
19
+
20
+ # Local operations state
21
+ _ops/
22
+
23
+ # Environment
24
+ .env
25
+ .env.*
26
+ !.env.example
27
+
28
+ # OS metadata
29
+ .DS_Store
30
+ EOF_GITIGNORE
31
+ )
32
+ PI_DEFAULT_RUNTIME_ENTRIES=$(cat <<'EOF_RUNTIME'
33
+ .claude/settings.local.json
34
+ .claude/.atomic_pending
35
+ .claude/.session-id
36
+ .claude/.trace.jsonl
37
+ .claude/.session-handoff.md
38
+ .claude/.task-state.json
39
+ .claude/.task-handoff.md
40
+ .claude/.codegraph-state/
41
+ .claude/*.tmp
42
+ .claude/*.bak
43
+ .claude/*.bak.*
44
+ .claude/*.backup-*
45
+ tasks/.current.md.tmp.*
46
+ .ai/harness/checks/latest.json
47
+ .ai/harness/checks/post-bash-latest.json
48
+ .ai/harness/events.jsonl
49
+ .ai/harness/archive/
50
+ .ai/harness/failures/latest.jsonl
51
+ .ai/harness/handoff/current.md
52
+ .ai/harness/handoff/resume.md
53
+ .ai/harness/capability-context/
54
+ .ai/harness/security/*
55
+ !.ai/harness/security/.gitkeep
56
+ .ai/harness/planning/*
57
+ !.ai/harness/planning/.gitkeep
58
+ .ai/harness/architecture/events.jsonl
59
+ .ai/harness/active-plan
60
+ .ai/harness/active-worktree
61
+ .ai/harness/sprint/
62
+ .ai/harness/worktrees/
63
+ .ai/harness/runs/
64
+ .ai/harness/chatgpt/browser-lock.json
65
+ .ai/harness/chatgpt/bridge-extension/
66
+ .ai/harness/chatgpt/tmp/
67
+ .ai/harness/chatgpt/sessions/
68
+ .ai/harness/triage/*
69
+ !.ai/harness/triage/.gitkeep
70
+ .forge/chatgpt-browser.local.json
71
+ .forge/chatgpt-browser.tokens.json
72
+ .forge/interactions/
73
+ .codex/*
74
+ .claude/.active-plan
75
+ .claude/.plan-state/
76
+ EOF_RUNTIME
77
+ )
78
+ PI_EXTERNAL_TOOLING_HOSTS_DEFAULT=$(cat <<'EOF_EXTERNAL_TOOLING_HOSTS'
79
+ [
80
+ "claude-code",
81
+ "codex"
82
+ ]
83
+ EOF_EXTERNAL_TOOLING_HOSTS
84
+ )
85
+ PI_TEMPLATE_RESEARCH=$(cat <<'EOF_TEMPLATE_RESEARCH'
86
+ # {{PROJECT_NAME}} — Research Notes
87
+
88
+ > **Last Updated**: {{DATE}}
89
+ > **Scope**: (what area of the codebase was researched)
90
+ > **Usage**: Store deep codebase findings and hidden contracts here, not in chat-only summaries.
91
+
92
+ ## Codebase Map
93
+ | File | Purpose | Key Exports |
94
+ |------|---------|-------------|
95
+
96
+ ## Architecture Observations
97
+ ### Patterns & Conventions
98
+ ### Implicit Contracts
99
+ ### Edge Cases & Intricacies
100
+
101
+ ## Technical Debt / Risks
102
+
103
+ ## Research Conclusions
104
+ ### What to Preserve
105
+ ### What to Change
106
+ ### Open Questions
107
+ EOF_TEMPLATE_RESEARCH
108
+ )
109
+ PI_TEMPLATE_SPEC=$(cat <<'EOF_TEMPLATE_SPEC'
110
+ # Product Spec: {{PROJECT_NAME}}
111
+
112
+ > **Status**: Draft
113
+ > **Last Updated**: {{TIMESTAMP}}
114
+ > **Owner**: Planner
115
+
116
+ ## Product Outcome
117
+
118
+ Describe the stable user or operator outcome this repo should deliver.
119
+
120
+ ## Success Criteria
121
+
122
+ - Primary workflow:
123
+ - Quality bar:
124
+ - Out of scope:
125
+
126
+ ## Constraints
127
+
128
+ - Technical:
129
+ - Compliance:
130
+ - Delivery:
131
+
132
+ ## Acceptance Scenarios
133
+
134
+ - Given
135
+ When
136
+ Then
137
+
138
+ ## Open Questions
139
+
140
+ - ...
141
+ EOF_TEMPLATE_SPEC
142
+ )
143
+ PI_TEMPLATE_PLAN=$(cat <<'EOF_TEMPLATE_PLAN'
144
+ # Plan: {{TITLE}}
145
+
146
+ > **Status**: Draft
147
+ > **Created**: {{TIMESTAMP}}
148
+ > **Slug**: {{SLUG}}
149
+ > **Spec**: `docs/spec.md`
150
+ > **Research**: See `docs/researches/`
151
+ > **Task Contract**: `tasks/contracts/{{ARTIFACT_STEM}}.contract.md`
152
+ > **Task Review**: `tasks/reviews/{{ARTIFACT_STEM}}.review.md`
153
+ > **Implementation Notes**: `tasks/notes/{{ARTIFACT_STEM}}.notes.md`
154
+
155
+ ## Agentic Routing
156
+ - Selected route:
157
+ - Routing reason:
158
+ - Due diligence:
159
+ - P1 map:
160
+ - P2 trace:
161
+ - P3 decision rationale:
162
+
163
+ ## Workflow Inventory
164
+ Complete this inventory before implementation. If any line is unknown, keep the plan in Draft and fill it before projection.
165
+
166
+ - Active plan: `{{PLAN_FILE}}`
167
+ - Sprint contract: `tasks/contracts/{{ARTIFACT_STEM}}.contract.md`
168
+ - Sprint review: `tasks/reviews/{{ARTIFACT_STEM}}.review.md`
169
+ - Implementation notes: `tasks/notes/{{ARTIFACT_STEM}}.notes.md`
170
+ - Deferred-goal ledger: `tasks/todos.md`
171
+ - Current checks: `.ai/harness/checks/latest.json`
172
+ - Run snapshots: `.ai/harness/runs/`
173
+ - Scope authority: `tasks/contracts/{{ARTIFACT_STEM}}.contract.md` `allowed_paths`
174
+ - Concurrency rule: `.ai/harness/active-plan` selects the active plan for this worktree when present; `.ai/harness/active-worktree` records the owning worktree; `.claude/.active-plan` is a legacy fallback during transition. If another worktree already owns active work, open or switch to the matching worktree instead of serializing unrelated plans.
175
+ - Execution isolation: approved contract-level work projects through `.ai/harness/scripts/plan-to-todo.sh --plan {{PLAN_FILE}}` and may start `.ai/harness/scripts/contract-worktree.sh start --plan {{PLAN_FILE}}`.
176
+
177
+ ## Approach
178
+ ### Strategy
179
+ ### Trade-offs
180
+ | Option | Pros | Cons | Decision |
181
+ |--------|------|------|----------|
182
+
183
+ ## Detailed Design
184
+ ### File Changes
185
+ | File | Action | Description |
186
+ |------|--------|-------------|
187
+
188
+ ### Code Snippets
189
+ ### Data Flow
190
+
191
+ ## Risk Assessment
192
+ | Risk | Likelihood | Impact | Mitigation |
193
+ |------|------------|--------|------------|
194
+
195
+ ## Task Contracts
196
+ - Contract file: `tasks/contracts/{{ARTIFACT_STEM}}.contract.md`
197
+ - Review file: `tasks/reviews/{{ARTIFACT_STEM}}.review.md`
198
+ - Implementation notes file: `tasks/notes/{{ARTIFACT_STEM}}.notes.md`
199
+ - Template: `.claude/templates/contract.template.md`
200
+ - Verification command: `bash .ai/harness/scripts/verify-contract.sh --contract tasks/contracts/{{ARTIFACT_STEM}}.contract.md --strict`
201
+ - Active plan rule: `.ai/harness/active-plan` is authoritative for this worktree when present; `.ai/harness/active-worktree` records the owning worktree; `.claude/.active-plan` is a legacy fallback during transition. Do not infer active execution from the latest non-archived plan.
202
+
203
+ ## Handoff
204
+
205
+ - Checks file: `.ai/harness/checks/latest.json`
206
+ - Session handoff: `.ai/harness/handoff/current.md`
207
+
208
+ ## Evidence Contract
209
+
210
+ - **State/progress path**:
211
+ - **Verification evidence**:
212
+ - **Evaluator rubric**:
213
+ - **Stop condition**:
214
+ - **Rollback surface**:
215
+
216
+ ## Annotations
217
+ <!-- [NOTE]: prefixed inline. Claude processes all and revises. -->
218
+
219
+ ## Task Breakdown
220
+ - [ ] ...
221
+ EOF_TEMPLATE_PLAN
222
+ )
223
+ PI_TEMPLATE_CONTRACT=$(cat <<'EOF_TEMPLATE_CONTRACT'
224
+ # Task Contract: {{TASK_SLUG}}
225
+
226
+ > **Status**: Pending
227
+ > **Plan**: {{PLAN_FILE}}
228
+ > **Task Profile**: {{TASK_PROFILE}}
229
+ > **Owner**: {{OWNER}}
230
+ > **Capability ID**: {{CAPABILITY_ID}}
231
+ > **Last Updated**: {{TIMESTAMP}}
232
+ > **Review File**: `{{REVIEW_FILE}}`
233
+ > **Notes File**: `{{NOTES_FILE}}`
234
+
235
+ ## Goal
236
+
237
+ Describe the exact outcome this task must deliver.
238
+
239
+ ## Scope
240
+
241
+ - In scope:
242
+ - Out of scope:
243
+
244
+ ## Workflow Inventory
245
+
246
+ - Source plan: `{{PLAN_FILE}}`
247
+ - Deferred-goal ledger: `tasks/todos.md`
248
+ - Review file: `{{REVIEW_FILE}}`
249
+ - Notes file: `{{NOTES_FILE}}`
250
+ - Checks file: `.ai/harness/checks/latest.json`
251
+ - Run snapshots: `.ai/harness/runs/`
252
+ - Scope gate: edit only paths listed under `allowed_paths`; update this contract before widening scope.
253
+ - Completion gate: `scripts/verify-sprint.sh` must see this contract pass, the review recommend pass, and `## External Acceptance Advice` pass or record a manual override.
254
+
255
+ ## Allowed Paths
256
+
257
+ ```yaml
258
+ allowed_paths:
259
+ - plans/
260
+ - tasks/todos.md
261
+ - {{CONTRACT_FILE}}
262
+ - {{REVIEW_FILE}}
263
+ - {{NOTES_FILE}}
264
+ - .ai/context/capabilities.json
265
+ - src/
266
+ - tests/
267
+ ```
268
+
269
+ ## Delegation Contract
270
+
271
+ ```yaml
272
+ delegation:
273
+ budget:
274
+ tokens: null
275
+ tool_calls: null
276
+ wall_time_minutes: null
277
+ permission_scope:
278
+ mode: inherit_allowed_paths
279
+ writable_paths: []
280
+ network: inherited
281
+ roles:
282
+ parent:
283
+ mode: narrate_and_gatekeep
284
+ purpose: approval_checkpoint_owner
285
+ explorer:
286
+ mode: read_only
287
+ purpose: codebase_research
288
+ worker:
289
+ mode: edit_within_allowed_paths
290
+ purpose: implementation
291
+ verifier:
292
+ mode: read_only
293
+ purpose: exit_criteria_review
294
+ ```
295
+
296
+ ## Exit Criteria (Machine Verifiable)
297
+
298
+ ```yaml
299
+ exit_criteria:
300
+ files_exist:
301
+ - src/modules/{{TASK_SLUG}}/index.ts
302
+ - {{NOTES_FILE}}
303
+ tests_pass:
304
+ - path: tests/unit/{{TASK_SLUG}}.test.ts
305
+ commands_succeed:
306
+ - bun run typecheck
307
+ files_contain:
308
+ - path: src/modules/{{TASK_SLUG}}/index.ts
309
+ pattern: "export"
310
+ ```
311
+
312
+ ## Acceptance Notes (Human Review)
313
+
314
+ - Functional behavior:
315
+ - Edge cases:
316
+ - Regression risks:
317
+
318
+ ## Rollback Point
319
+
320
+ - Commit / checkpoint:
321
+ - Revert strategy:
322
+ EOF_TEMPLATE_CONTRACT
323
+ )
324
+ PI_TEMPLATE_REVIEW=$(cat <<'EOF_TEMPLATE_REVIEW'
325
+ # Task Review: {{TASK_SLUG}}
326
+
327
+ > **Status**: Pending
328
+ > **Plan**: {{PLAN_FILE}}
329
+ > **Contract**: {{CONTRACT_FILE}}
330
+ > **Notes File**: {{NOTES_FILE}}
331
+ > **Checks File**: {{CHECKS_FILE}}
332
+ > **Last Updated**: {{TIMESTAMP}}
333
+ > **Recommendation**: fail
334
+
335
+ ## Human Review Card
336
+
337
+ - Verdict: pending
338
+ - Change type: code-change | docs-only | ledger-closeout | migration | eval-only | delegated-run
339
+ - Intended files changed:
340
+ - Actual files changed:
341
+ - Commands passed:
342
+ - External acceptance: unavailable
343
+ - Residual risks:
344
+ - Reviewer action required: inspect diff and card
345
+ - Rollback:
346
+
347
+ ## Verification Evidence
348
+
349
+ - Waza /check run:
350
+ - Commands run:
351
+ - Manual checks:
352
+ - Supporting artifacts:
353
+
354
+ ## External Acceptance Advice
355
+
356
+ > **External Acceptance**: unavailable
357
+ > **External Reviewer**:
358
+ > **External Source**:
359
+ > **External Started**:
360
+ > **External Completed**:
361
+
362
+ - P1 blockers:
363
+ - P2 advisories:
364
+ - Acceptance checklist:
365
+
366
+ ## Behavior Diff Notes
367
+
368
+ - ...
369
+
370
+ ## Residual Risks / Follow-ups
371
+
372
+ - ...
373
+
374
+ ## Scorecard
375
+
376
+ | Dimension | Score | Notes |
377
+ |-----------|-------|-------|
378
+ | Functionality | 0/10 | |
379
+ | Product depth | 0/10 | |
380
+ | Design quality | 0/10 | |
381
+ | Code quality | 0/10 | |
382
+
383
+ ## Failing Items
384
+
385
+ - ...
386
+
387
+ ## Retest Steps
388
+
389
+ - Re-run:
390
+ - Re-check:
391
+
392
+ ## Summary
393
+
394
+ - ...
395
+ EOF_TEMPLATE_REVIEW
396
+ )
397
+ PI_TEMPLATE_IMPLEMENTATION_NOTES=$(cat <<'EOF_TEMPLATE_IMPLEMENTATION_NOTES'
398
+ # Implementation Notes: {{TASK_SLUG}}
399
+
400
+ > **Status**: Active
401
+ > **Plan**: {{PLAN_FILE}}
402
+ > **Contract**: {{CONTRACT_FILE}}
403
+ > **Review**: {{REVIEW_FILE}}
404
+ > **Last Updated**: {{TIMESTAMP}}
405
+ > **Lifecycle**: notes
406
+
407
+ ## Design Decisions
408
+
409
+ - ...
410
+
411
+ ## Deviations From Plan Or Spec
412
+
413
+ - None recorded.
414
+
415
+ ## Tradeoffs Considered
416
+
417
+ | Option | Decision | Reason |
418
+ |--------|----------|--------|
419
+ | ... | ... | ... |
420
+
421
+ ## Open Questions
422
+
423
+ - None.
424
+
425
+ ## Evidence Links
426
+
427
+ - Checks: `.ai/harness/checks/latest.json`
428
+ - Run snapshots: `.ai/harness/runs/`
429
+
430
+ ## Promotion Candidates
431
+
432
+ - Promote to `tasks/lessons.md` only after a repeated correction or failure pattern.
433
+ - Promote to `docs/researches/` only when it is durable repo knowledge with evidence.
434
+ - Promote to harness asset files only after verification across more than one task or fixture.
435
+ EOF_TEMPLATE_IMPLEMENTATION_NOTES
436
+ )
437
+ PI_CONTEXT_PROFILE_DEFAULT="stable-root-progressive-subdir"
438
+ PI_RECOVERY_PROFILE_DEFAULT="hybrid"
439
+ PI_STATE_PROFILE_DEFAULT="file-backed"
440
+ PI_ORCHESTRATION_PROFILE_DEFAULT="shared-long-running-harness"
441
+ PI_EVALUATION_PROFILE_DEFAULT="browser-qa"
442
+ PI_HANDOFF_PROFILE_DEFAULT="artifact-aware"
443
+ PI_DOCUMENTATION_PROFILE_DEFAULT="minimal-agentic"
444
+ PI_DEFAULT_LSP_PROFILE="typescript-lsp"
445
+ PI_MINIMAL_REFERENCE_CONFIGS="harness-overview.md agentic-development-flow.md external-tooling.md sprint-contracts.md heartbeat-triage.md handoff-protocol.md document-generation.md global-working-rules.md"
446
+ PI_FULL_REFERENCE_CONFIGS="agentic-development-flow.md ai-workflows.md changelog-versioning.md coding-standards.md development-protocol.md document-generation.md evaluator-rubric.md external-tooling.md git-strategy.md global-working-rules.md heartbeat-triage.md handoff-protocol.md harness-overview.md hook-operations.md release-deploy.md spa-day-protocol.md sprint-contracts.md workflow-orchestration.md"
447
+ PI_REFERENCE_CONFIG_STUB_MARKER="<!-- forge: reference-config-stub v1 -->"
448
+
449
+ pi_write_file_if_apply() {
450
+ local mode="${1:-apply}"
451
+ local path="$2"
452
+ local content="$3"
453
+
454
+ if [[ "$mode" != "apply" ]]; then
455
+ echo "[dry-run] write $path"
456
+ return 0
457
+ fi
458
+
459
+ mkdir -p "$(dirname "$path")"
460
+ printf '%s\n' "$content" > "$path"
461
+ }
462
+
463
+ pi_copy_file_if_apply() {
464
+ local mode="${1:-apply}"
465
+ local src="$2"
466
+ local dest="$3"
467
+ local src_abs=""
468
+ local dest_abs=""
469
+
470
+ if [[ "$mode" != "apply" ]]; then
471
+ echo "[dry-run] cp \"$src\" \"$dest\""
472
+ return 0
473
+ fi
474
+
475
+ mkdir -p "$(dirname "$dest")"
476
+ src_abs="$(cd "$(dirname "$src")" && pwd)/$(basename "$src")"
477
+ dest_abs="$(cd "$(dirname "$dest")" && pwd)/$(basename "$dest")"
478
+
479
+ if [[ "$src_abs" == "$dest_abs" ]]; then
480
+ return 0
481
+ fi
482
+
483
+ cp "$src" "$dest"
484
+ }
485
+
486
+ pi_install_hook_adapters() {
487
+ local repo="$1"
488
+ local _hooks_dir="$2"
489
+ local mode="${3:-apply}"
490
+
491
+ pi_retire_project_hook_adapter "$mode" "$repo/.claude/settings.json"
492
+ pi_retire_project_hook_adapter "$mode" "$repo/.claude/settings.local.json"
493
+ pi_retire_project_hook_adapter "$mode" "$repo/.codex/hooks.json"
494
+ }
495
+
496
+ pi_retire_project_hook_adapter() {
497
+ local mode="${1:-apply}"
498
+ local file_path="$2"
499
+
500
+ if [[ ! -f "$file_path" ]]; then
501
+ return 0
502
+ fi
503
+
504
+ if [[ "$mode" != "apply" ]]; then
505
+ echo "[dry-run] retire project hook adapter $file_path"
506
+ return 0
507
+ fi
508
+
509
+ if ! command -v node >/dev/null 2>&1; then
510
+ echo "[project-init] Skipping project hook adapter retirement for $file_path because node is unavailable" >&2
511
+ return 0
512
+ fi
513
+
514
+ node - "$file_path" <<'NODE_EOF'
515
+ const fs = require("fs");
516
+ const path = process.argv[2];
517
+
518
+ function writeJson(file, value) {
519
+ fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`);
520
+ }
521
+
522
+ let data;
523
+ try {
524
+ const raw = fs.readFileSync(path, "utf8");
525
+ data = raw.trim() ? JSON.parse(raw) : {};
526
+ } catch (err) {
527
+ console.error(`[project-init] Skipping invalid JSON while retiring project hook adapter: ${path}`);
528
+ process.exit(0);
529
+ }
530
+
531
+ if (!Object.prototype.hasOwnProperty.call(data, "hooks")) {
532
+ if (Object.keys(data).length === 0) fs.rmSync(path, { force: true });
533
+ process.exit(0);
534
+ }
535
+
536
+ const backup = `${path}.forge-migrate-backup`;
537
+ if (!fs.existsSync(backup)) fs.copyFileSync(path, backup);
538
+ delete data.hooks;
539
+
540
+ if (Object.keys(data).length === 0) {
541
+ fs.rmSync(path, { force: true });
542
+ } else {
543
+ writeJson(path, data);
544
+ }
545
+ NODE_EOF
546
+ }
547
+
548
+ pi_print_codex_hook_trust_notice() {
549
+ echo "Host hook adapters are user-level: run forge install --target both --location global, then trust ~/.codex/hooks.json in Codex Settings."
550
+ }
551
+
552
+ pi_repo_pins_hook_source() {
553
+ local repo="$1"
554
+ local policy_file="$repo/.ai/harness/policy.json"
555
+
556
+ if [[ "${FORGE_HOOK_SOURCE:-}" == "repo" ]]; then
557
+ return 0
558
+ fi
559
+
560
+ [[ -f "$policy_file" ]] || return 1
561
+ grep -Eq '"hook_source"[[:space:]]*:[[:space:]]*"repo"' "$policy_file"
562
+ }
563
+
564
+ pi_repo_pins_helper_source() {
565
+ local repo="$1"
566
+ local policy_file="$repo/.ai/harness/policy.json"
567
+
568
+ if [[ "${FORGE_HELPER_SOURCE:-}" == "repo" ]]; then
569
+ return 0
570
+ fi
571
+
572
+ [[ -f "$policy_file" ]] || return 1
573
+ grep -Eq '"helper_source"[[:space:]]*:[[:space:]]*"repo"' "$policy_file"
574
+ }
575
+
576
+ pi_write_hook_runtime_readme() {
577
+ local hooks_dir="$1"
578
+ local mode="${2:-apply}"
579
+ local readme="$hooks_dir/README.md"
580
+
581
+ if [[ "$mode" != "apply" ]]; then
582
+ echo "[dry-run] write $readme"
583
+ return 0
584
+ fi
585
+
586
+ mkdir -p "$hooks_dir"
587
+ cat > "$readme" <<'EOF_HOOK_README'
588
+ # Repo-Local Hook Fallback
589
+
590
+ This repo does not pin `"hook_source": "repo"`, so active hook execution is
591
+ user-level and central-first:
592
+
593
+ `~/.codex/hooks.json` / `~/.claude/settings.json` -> `forge-hook` ->
594
+ packaged hooks from the installed forge runtime.
595
+
596
+ The files under `.ai/hooks/lib/` are kept only for repo workflow helper scripts
597
+ that source shared shell utilities. Full hook runtime scripts are not vendored
598
+ here by default because stale copies can be mistaken for the active hook path.
599
+
600
+ Set `"hook_source": "repo"` in `.ai/harness/policy.json` only for self-hosted
601
+ hook development or an explicitly reviewed repo-local hook override.
602
+ EOF_HOOK_README
603
+ }
604
+
605
+ pi_prune_repo_local_hook_runtime() {
606
+ local hooks_dir="$1"
607
+ local mode="${2:-apply}"
608
+
609
+ if [[ ! -d "$hooks_dir" ]]; then
610
+ return 0
611
+ fi
612
+
613
+ if [[ "$mode" != "apply" ]]; then
614
+ echo "[dry-run] remove repo-local hook entry scripts from $hooks_dir unless hook_source is repo"
615
+ return 0
616
+ fi
617
+
618
+ find "$hooks_dir" -mindepth 1 -maxdepth 1 -type f \
619
+ \( -name '*.sh' \
620
+ -o -name 'AGENTS.md' \
621
+ -o -name 'CLAUDE.md' \
622
+ -o -name 'settings.template.json' \
623
+ -o -name 'codex.hooks.template.json' \
624
+ -o -name '.version' \) \
625
+ -delete
626
+ }
627
+
628
+ pi_install_hook_assets() {
629
+ local target_dir="$1"
630
+ local hooks_assets_dir="$2"
631
+ local mode="${3:-apply}"
632
+ local hooks_dir="$target_dir/.ai/hooks"
633
+
634
+ if [[ ! -d "$hooks_assets_dir" ]]; then
635
+ echo "[project-init] Warning: hook assets not found at $hooks_assets_dir" >&2
636
+ echo "[project-init] User-level host adapters dispatch through forge-hook packaged hooks." >&2
637
+ return 0
638
+ fi
639
+
640
+ if [[ "$mode" != "apply" ]]; then
641
+ echo "[dry-run] mkdir -p \"$hooks_dir\""
642
+ else
643
+ mkdir -p "$hooks_dir"
644
+ fi
645
+
646
+ if pi_repo_pins_hook_source "$target_dir"; then
647
+ while IFS= read -r hook; do
648
+ local rel_path rel_dir dest_dir hook_name
649
+ rel_path="${hook#"$hooks_assets_dir"/}"
650
+ rel_dir="$(dirname "$rel_path")"
651
+ if [[ "$rel_dir" == "." ]]; then
652
+ dest_dir="$hooks_dir"
653
+ else
654
+ dest_dir="$hooks_dir/$rel_dir"
655
+ fi
656
+ hook_name="$(basename "$hook")"
657
+ if [[ "$mode" != "apply" ]]; then
658
+ echo "[dry-run] mkdir -p \"$dest_dir\""
659
+ echo "[dry-run] cp \"$hook\" \"$dest_dir/$hook_name\""
660
+ continue
661
+ fi
662
+ mkdir -p "$dest_dir"
663
+ cp "$hook" "$dest_dir/$hook_name"
664
+ chmod +x "$dest_dir/$hook_name" 2>/dev/null || true
665
+ done < <(find "$hooks_assets_dir" -type f -name '*.sh' | sort)
666
+ return 0
667
+ fi
668
+
669
+ pi_prune_repo_local_hook_runtime "$hooks_dir" "$mode"
670
+
671
+ if [[ "$mode" != "apply" ]]; then
672
+ echo "[dry-run] mkdir -p \"$hooks_dir/lib\""
673
+ else
674
+ mkdir -p "$hooks_dir/lib"
675
+ fi
676
+
677
+ if [[ -d "$hooks_assets_dir/lib" ]]; then
678
+ while IFS= read -r hook_lib; do
679
+ local lib_name
680
+ lib_name="$(basename "$hook_lib")"
681
+ if [[ "$mode" != "apply" ]]; then
682
+ echo "[dry-run] cp \"$hook_lib\" \"$hooks_dir/lib/$lib_name\""
683
+ continue
684
+ fi
685
+ cp "$hook_lib" "$hooks_dir/lib/$lib_name"
686
+ chmod +x "$hooks_dir/lib/$lib_name" 2>/dev/null || true
687
+ done < <(find "$hooks_assets_dir/lib" -maxdepth 1 -type f -name '*.sh' | sort)
688
+ fi
689
+
690
+ pi_write_hook_runtime_readme "$hooks_dir" "$mode"
691
+ }
692
+
693
+ pi_ensure_executable_if_apply() {
694
+ local mode="${1:-apply}"
695
+ shift || true
696
+
697
+ if [[ "$mode" != "apply" || "$#" -eq 0 ]]; then
698
+ return 0
699
+ fi
700
+
701
+ local candidate first_line
702
+ for candidate in "$@"; do
703
+ [[ -f "$candidate" ]] || continue
704
+ case "$candidate" in
705
+ *.sh)
706
+ chmod +x "$candidate" 2>/dev/null || true
707
+ ;;
708
+ *.ts)
709
+ first_line="$(head -n 1 "$candidate" 2>/dev/null || true)"
710
+ if [[ "$first_line" == '#!'* ]]; then
711
+ chmod +x "$candidate" 2>/dev/null || true
712
+ fi
713
+ ;;
714
+ esac
715
+ done
716
+ }
717
+
718
+ pi_default_runtime_block() {
719
+ local extra_entries="${1:-}"
720
+ local runtime_entries="$PI_DEFAULT_RUNTIME_ENTRIES"
721
+
722
+ if [[ -n "$extra_entries" ]]; then
723
+ runtime_entries="${runtime_entries}"$'\n'"${extra_entries}"
724
+ fi
725
+
726
+ printf '%s\n%s\n%s\n' "$PI_RUNTIME_BLOCK_BEGIN" "$runtime_entries" "$PI_RUNTIME_BLOCK_END"
727
+ }
728
+
729
+ pi_helper_wrapper_paths() {
730
+ local workflow_contract="$1"
731
+ local helper_names
732
+ local helper_name
733
+
734
+ helper_names="$(pi_workflow_contract_query_lines "$workflow_contract" "helpers.scripts" | xargs)"
735
+ for helper_name in $helper_names; do
736
+ printf 'scripts/%s\n' "$helper_name"
737
+ done
738
+ }
739
+
740
+ pi_helper_wrapper_gitignore_entries() {
741
+ local workflow_contract="$1"
742
+ local paths
743
+
744
+ paths="$(pi_helper_wrapper_paths "$workflow_contract")"
745
+ [[ -n "$paths" ]] || return 0
746
+
747
+ printf '%s\n' "# forge generated helper wrappers"
748
+ printf '%s\n' "$paths"
749
+ printf '%s\n' "scripts/forge/"
750
+ }
751
+
752
+ pi_is_runtime_block_begin() {
753
+ local line="$1"
754
+ [[ "$line" == "$PI_RUNTIME_BLOCK_BEGIN" ]]
755
+ }
756
+
757
+ pi_has_runtime_block() {
758
+ local file_path="$1"
759
+ grep -Fq "$PI_RUNTIME_BLOCK_BEGIN" "$file_path"
760
+ }
761
+
762
+ pi_ensure_gitignore_block() {
763
+ local file_path="$1"
764
+ local prelude="${2:-}"
765
+ local extra_entries="${3:-}"
766
+ local mode="${4:-apply}"
767
+ local block
768
+
769
+ block="$(pi_default_runtime_block "$extra_entries")"
770
+
771
+ if [[ "$mode" != "apply" ]]; then
772
+ echo "[dry-run] ensure managed runtime block in $file_path"
773
+ return 0
774
+ fi
775
+
776
+ mkdir -p "$(dirname "$file_path")"
777
+ if [[ ! -f "$file_path" ]]; then
778
+ if [[ -n "$prelude" ]]; then
779
+ printf '%s\n' "$prelude" > "$file_path"
780
+ else
781
+ touch "$file_path"
782
+ fi
783
+ fi
784
+
785
+ if ! pi_has_runtime_block "$file_path"; then
786
+ printf '\n%s\n' "$block" >> "$file_path"
787
+ return 0
788
+ fi
789
+
790
+ local tmp_file
791
+ local block_written=0
792
+ tmp_file="$(mktemp)"
793
+
794
+ while IFS= read -r line || [[ -n "$line" ]]; do
795
+ if pi_is_runtime_block_begin "$line"; then
796
+ if [[ "$block_written" -eq 0 ]]; then
797
+ printf '%s\n' "$block" >> "$tmp_file"
798
+ block_written=1
799
+ fi
800
+
801
+ while IFS= read -r inner_line || [[ -n "$inner_line" ]]; do
802
+ if [[ "$inner_line" == "$PI_RUNTIME_BLOCK_END" ]]; then
803
+ break
804
+ fi
805
+ done
806
+ continue
807
+ fi
808
+
809
+ printf '%s\n' "$line" >> "$tmp_file"
810
+ done < "$file_path"
811
+
812
+ mv "$tmp_file" "$file_path"
813
+ }
814
+
815
+ pi_resolve_json_runtime() {
816
+ if command -v node >/dev/null 2>&1; then
817
+ printf 'node'
818
+ return 0
819
+ fi
820
+
821
+ if command -v bun >/dev/null 2>&1; then
822
+ printf 'bun'
823
+ return 0
824
+ fi
825
+
826
+ if command -v python3 >/dev/null 2>&1; then
827
+ printf 'python3'
828
+ return 0
829
+ fi
830
+
831
+ return 1
832
+ }
833
+
834
+ pi_workflow_contract_query_lines() {
835
+ local contract_file="$1"
836
+ local selector="$2"
837
+ local runtime
838
+
839
+ if [[ ! -f "$contract_file" ]]; then
840
+ return 1
841
+ fi
842
+
843
+ runtime="$(pi_resolve_json_runtime || true)"
844
+ if [[ -z "$runtime" ]]; then
845
+ echo "[warn] no runtime available to read workflow contract: $contract_file" >&2
846
+ return 1
847
+ fi
848
+
849
+ case "$runtime" in
850
+ python3)
851
+ "$runtime" - "$contract_file" "$selector" <<'PY_EOF'
852
+ import json
853
+ import sys
854
+
855
+ path, selector = sys.argv[1], sys.argv[2]
856
+ value = json.load(open(path, "r", encoding="utf-8"))
857
+ for part in selector.split("."):
858
+ value = value.get(part) if isinstance(value, dict) else None
859
+ if isinstance(value, list):
860
+ for item in value:
861
+ print(item)
862
+ elif value is not None:
863
+ print(value)
864
+ PY_EOF
865
+ ;;
866
+ *)
867
+ "$runtime" -e '
868
+ const fs = require("fs");
869
+ const [, filePath, selector] = process.argv;
870
+ const parts = selector.split(".");
871
+ let value = JSON.parse(fs.readFileSync(filePath, "utf8"));
872
+ for (const part of parts) {
873
+ value = value && typeof value === "object" ? value[part] : undefined;
874
+ }
875
+ if (Array.isArray(value)) {
876
+ for (const item of value) {
877
+ console.log(item);
878
+ }
879
+ } else if (value !== undefined && value !== null) {
880
+ console.log(value);
881
+ }
882
+ ' "$contract_file" "$selector"
883
+ ;;
884
+ esac
885
+ }
886
+
887
+ pi_workflow_contract_upgrade_action_paths() {
888
+ local contract_file="$1"
889
+ local action_filter="${2:-remove}"
890
+ local ownership_filter="${3:-known_generated}"
891
+ local runtime
892
+
893
+ if [[ ! -f "$contract_file" ]]; then
894
+ return 1
895
+ fi
896
+
897
+ runtime="$(pi_resolve_json_runtime || true)"
898
+ if [[ -z "$runtime" ]]; then
899
+ echo "[warn] no runtime available to read workflow contract: $contract_file" >&2
900
+ return 1
901
+ fi
902
+
903
+ case "$runtime" in
904
+ python3)
905
+ "$runtime" - "$contract_file" "$action_filter" "$ownership_filter" <<'PY_EOF'
906
+ import json
907
+ import sys
908
+
909
+ path, action_filter, ownership_filter = sys.argv[1], sys.argv[2], sys.argv[3]
910
+ contract = json.load(open(path, "r", encoding="utf-8"))
911
+ for action in contract.get("migrations", {}).get("upgrade", {}).get("actions", []):
912
+ if action.get("action") != action_filter:
913
+ continue
914
+ if ownership_filter and action.get("ownership") != ownership_filter:
915
+ continue
916
+ for rel_path in action.get("paths", []):
917
+ print(rel_path)
918
+ PY_EOF
919
+ ;;
920
+ *)
921
+ "$runtime" -e '
922
+ const fs = require("fs");
923
+ const [, filePath, actionFilter, ownershipFilter] = process.argv;
924
+ const contract = JSON.parse(fs.readFileSync(filePath, "utf8"));
925
+ const actions = contract.migrations?.upgrade?.actions ?? [];
926
+ for (const action of actions) {
927
+ if (action.action !== actionFilter) continue;
928
+ if (ownershipFilter && action.ownership !== ownershipFilter) continue;
929
+ for (const relPath of action.paths ?? []) {
930
+ console.log(relPath);
931
+ }
932
+ }
933
+ ' "$contract_file" "$action_filter" "$ownership_filter"
934
+ ;;
935
+ esac
936
+ }
937
+
938
+ pi_workflow_contract_upgrade_action_entries() {
939
+ local contract_file="$1"
940
+ local action_filter="${2:-remove}"
941
+ local ownership_filter="${3:-known_generated}"
942
+ local runtime
943
+
944
+ if [[ ! -f "$contract_file" ]]; then
945
+ return 1
946
+ fi
947
+
948
+ runtime="$(pi_resolve_json_runtime || true)"
949
+ if [[ -z "$runtime" ]]; then
950
+ echo "[warn] no runtime available to read workflow contract: $contract_file" >&2
951
+ return 1
952
+ fi
953
+
954
+ case "$runtime" in
955
+ python3)
956
+ "$runtime" - "$contract_file" "$action_filter" "$ownership_filter" <<'PY_EOF'
957
+ import json
958
+ import sys
959
+
960
+ path, action_filter, ownership_filter = sys.argv[1], sys.argv[2], sys.argv[3]
961
+ contract = json.load(open(path, "r", encoding="utf-8"))
962
+ for action in contract.get("migrations", {}).get("upgrade", {}).get("actions", []):
963
+ if action.get("action") != action_filter:
964
+ continue
965
+ if ownership_filter and action.get("ownership") != ownership_filter:
966
+ continue
967
+ cleanup_mode = action.get("cleanupMode", "always")
968
+ for rel_path in action.get("paths", []):
969
+ print(f"{cleanup_mode}\t{rel_path}")
970
+ PY_EOF
971
+ ;;
972
+ *)
973
+ "$runtime" -e '
974
+ const fs = require("fs");
975
+ const [, filePath, actionFilter, ownershipFilter] = process.argv;
976
+ const contract = JSON.parse(fs.readFileSync(filePath, "utf8"));
977
+ const actions = contract.migrations?.upgrade?.actions ?? [];
978
+ for (const action of actions) {
979
+ if (action.action !== actionFilter) continue;
980
+ if (ownershipFilter && action.ownership !== ownershipFilter) continue;
981
+ const cleanupMode = action.cleanupMode ?? "always";
982
+ for (const relPath of action.paths ?? []) {
983
+ console.log(`${cleanupMode}\t${relPath}`);
984
+ }
985
+ }
986
+ ' "$contract_file" "$action_filter" "$ownership_filter"
987
+ ;;
988
+ esac
989
+ }
990
+
991
+ pi_install_workflow_contract() {
992
+ local target_dir="$1"
993
+ local contract_asset="$2"
994
+ local mode="${3:-apply}"
995
+ local output_path="$target_dir/.ai/harness/workflow-contract.json"
996
+
997
+ if [[ "$mode" != "apply" ]]; then
998
+ echo "[dry-run] install workflow contract into $output_path"
999
+ return 0
1000
+ fi
1001
+
1002
+ mkdir -p "$(dirname "$output_path")"
1003
+ cp "$contract_asset" "$output_path"
1004
+ }
1005
+
1006
+ pi_install_templates() {
1007
+ local target_dir="$1"
1008
+ local templates_dir="$2"
1009
+ local mode="${3:-apply}"
1010
+ local output_dir="$target_dir/.claude/templates"
1011
+
1012
+ if [[ "$mode" != "apply" ]]; then
1013
+ echo "[dry-run] install templates into $output_dir"
1014
+ return 0
1015
+ fi
1016
+
1017
+ mkdir -p "$output_dir"
1018
+
1019
+ if [[ -f "$templates_dir/research.template.md" ]]; then
1020
+ cp "$templates_dir/research.template.md" "$output_dir/research.template.md"
1021
+ else
1022
+ printf '%s\n' "$PI_TEMPLATE_RESEARCH" > "$output_dir/research.template.md"
1023
+ fi
1024
+
1025
+ if [[ -f "$templates_dir/spec.template.md" ]]; then
1026
+ cp "$templates_dir/spec.template.md" "$output_dir/spec.template.md"
1027
+ else
1028
+ printf '%s\n' "$PI_TEMPLATE_SPEC" > "$output_dir/spec.template.md"
1029
+ fi
1030
+
1031
+ if [[ -f "$templates_dir/plan.template.md" ]]; then
1032
+ cp "$templates_dir/plan.template.md" "$output_dir/plan.template.md"
1033
+ else
1034
+ printf '%s\n' "$PI_TEMPLATE_PLAN" > "$output_dir/plan.template.md"
1035
+ fi
1036
+
1037
+ if [[ -f "$templates_dir/contract.template.md" ]]; then
1038
+ cp "$templates_dir/contract.template.md" "$output_dir/contract.template.md"
1039
+ else
1040
+ printf '%s\n' "$PI_TEMPLATE_CONTRACT" > "$output_dir/contract.template.md"
1041
+ fi
1042
+
1043
+ if [[ -f "$templates_dir/review.template.md" ]]; then
1044
+ cp "$templates_dir/review.template.md" "$output_dir/review.template.md"
1045
+ else
1046
+ printf '%s\n' "$PI_TEMPLATE_REVIEW" > "$output_dir/review.template.md"
1047
+ fi
1048
+
1049
+ if [[ -f "$templates_dir/implementation-notes.template.md" ]]; then
1050
+ cp "$templates_dir/implementation-notes.template.md" "$output_dir/implementation-notes.template.md"
1051
+ else
1052
+ printf '%s\n' "$PI_TEMPLATE_IMPLEMENTATION_NOTES" > "$output_dir/implementation-notes.template.md"
1053
+ fi
1054
+
1055
+ # Sprint template ships when available; sprint-backlog.sh also carries an
1056
+ # inline fallback, so older asset dirs degrade gracefully.
1057
+ if [[ -f "$templates_dir/sprint.template.md" ]]; then
1058
+ cp "$templates_dir/sprint.template.md" "$output_dir/sprint.template.md"
1059
+ fi
1060
+
1061
+ if [[ -f "$templates_dir/prd.template.md" ]]; then
1062
+ cp "$templates_dir/prd.template.md" "$output_dir/prd.template.md"
1063
+ fi
1064
+ }
1065
+
1066
+ pi_install_helpers() {
1067
+ local target_dir="$1"
1068
+ local helpers_dir="$2"
1069
+ local mode="${3:-apply}"
1070
+ local helper_names="${4:-new-spec.sh new-sprint.sh new-plan.sh capture-plan.sh plan-to-todo.sh contract-run.ts contract-worktree.sh ship-worktrees.sh archive-workflow.sh refresh-current-status.sh prepare-handoff.sh verify-contract.sh summarize-failures.sh verify-sprint.sh harness-trace-grade.sh sprint-backlog.sh check-task-sync.sh check-deploy-sql-order.sh check-architecture-sync.sh check-agent-tooling.sh check-context-files.sh check-brain-manifest.sh sync-brain-docs.sh check-skill-version.ts select-agent-context-blocks.sh ensure-task-workflow.sh check-task-workflow.sh maintenance-triage.sh heartbeat-triage.sh switch-plan.sh workflow-contract.ts inspect-project-state.ts migrate-workflow-docs.ts migrate-project-template.sh capability-resolver.ts architecture-event.ts capability-config.ts architecture-queue.sh archive-architecture-request.sh context-contract-sync.sh workstream-sync.sh prepare-codex-handoff.sh codex-handoff-resume.sh}"
1071
+ local scripts_dir="$target_dir/scripts"
1072
+ local runtime_dir="$target_dir/.ai/harness/scripts"
1073
+ local helper_name
1074
+ local source_repo_target=0
1075
+
1076
+ if [[ -d "$target_dir/assets/templates/helpers" && -d "$helpers_dir" ]]; then
1077
+ local target_helpers_abs helpers_abs
1078
+ target_helpers_abs="$(cd "$target_dir/assets/templates/helpers" && pwd)"
1079
+ helpers_abs="$(cd "$helpers_dir" && pwd)"
1080
+ if [[ "$target_helpers_abs" == "$helpers_abs" ]]; then
1081
+ source_repo_target=1
1082
+ fi
1083
+ fi
1084
+
1085
+ if [[ "$mode" != "apply" ]]; then
1086
+ if [[ "$source_repo_target" -eq 1 || "$(pi_repo_pins_helper_source "$target_dir" && printf yes || true)" == "yes" ]]; then
1087
+ echo "[dry-run] install source helpers into $scripts_dir"
1088
+ else
1089
+ echo "[dry-run] install helper compatibility wrappers in $scripts_dir; package runtime dispatches through forge run"
1090
+ fi
1091
+ return 0
1092
+ fi
1093
+
1094
+ mkdir -p "$scripts_dir"
1095
+ mkdir -p "$runtime_dir"
1096
+
1097
+ if [[ -d "$helpers_dir" ]]; then
1098
+ for helper_name in $helper_names; do
1099
+ if [[ -f "$helpers_dir/$helper_name" ]]; then
1100
+ if [[ "$helper_name" == "migrate-project-template.sh" ]]; then
1101
+ local target_abs=""
1102
+ local skill_abs=""
1103
+ target_abs="$(cd "$target_dir" && pwd)"
1104
+ if [[ -n "${SKILL_ROOT:-}" ]]; then
1105
+ skill_abs="$(cd "$SKILL_ROOT" && pwd)"
1106
+ else
1107
+ skill_abs="$(cd "$helpers_dir/../.." && pwd)"
1108
+ fi
1109
+ if [[ "$target_abs" == "$skill_abs" ]]; then
1110
+ continue
1111
+ fi
1112
+ fi
1113
+ if [[ "$source_repo_target" -eq 1 ]]; then
1114
+ cp "$helpers_dir/$helper_name" "$scripts_dir/$helper_name"
1115
+ elif pi_repo_pins_helper_source "$target_dir"; then
1116
+ cp "$helpers_dir/$helper_name" "$runtime_dir/$helper_name"
1117
+ pi_normalize_installed_helper "$runtime_dir/$helper_name"
1118
+ if ! pi_preserve_existing_app_script "$scripts_dir/$helper_name" "$helpers_dir/$helper_name"; then
1119
+ pi_write_helper_wrapper "$scripts_dir/$helper_name" "$helper_name"
1120
+ fi
1121
+ else
1122
+ if ! pi_preserve_existing_app_script "$scripts_dir/$helper_name" "$helpers_dir/$helper_name"; then
1123
+ pi_write_helper_wrapper "$scripts_dir/$helper_name" "$helper_name"
1124
+ else
1125
+ mkdir -p "$scripts_dir/forge"
1126
+ pi_write_helper_wrapper "$scripts_dir/forge/$helper_name" "$helper_name"
1127
+ fi
1128
+ fi
1129
+ fi
1130
+ done
1131
+ pi_ensure_executable_if_apply "$mode" "$runtime_dir"/*.sh "$runtime_dir"/*.ts "$scripts_dir"/*.sh "$scripts_dir"/*.ts "$scripts_dir/forge"/*.sh "$scripts_dir/forge"/*.ts
1132
+ return 0
1133
+ fi
1134
+
1135
+ for helper_name in $helper_names; do
1136
+ pi_write_helper_wrapper "$scripts_dir/$helper_name" "$helper_name"
1137
+ done
1138
+ pi_ensure_executable_if_apply "$mode" "$scripts_dir"/*.sh "$scripts_dir"/*.ts
1139
+ }
1140
+
1141
+ pi_preserve_existing_app_script() {
1142
+ local output_file="$1"
1143
+ local source_file="$2"
1144
+
1145
+ [[ -f "$output_file" ]] || return 1
1146
+
1147
+ if cmp -s "$output_file" "$source_file"; then
1148
+ return 1
1149
+ fi
1150
+
1151
+ if grep -Eiq '(forge|claude-runtime-temp|Task Contract|Task Review|Deferred Goal Ledger|Workflow Contract|ContractWorktree|SprintBacklog|ArchitectureSync|ArchitectureDrift|BrainSync|CurrentStatus|\.ai/harness|\.claude/templates|tasks/contracts|tasks/reviews)' "$output_file"; then
1152
+ return 1
1153
+ fi
1154
+
1155
+ return 0
1156
+ }
1157
+
1158
+ pi_write_helper_wrapper() {
1159
+ local output_file="$1"
1160
+ local helper_name="$2"
1161
+
1162
+ case "$helper_name" in
1163
+ *.ts)
1164
+ cat > "$output_file" <<EOF_WRAPPER_TS
1165
+ #!/usr/bin/env bun
1166
+ import { spawnSync } from "node:child_process";
1167
+ import { existsSync } from "node:fs";
1168
+ import { join } from "node:path";
1169
+
1170
+ const sourceRoot =
1171
+ process.env.FORGE_SOURCE_ROOT ||
1172
+ process.env.AGENTIC_DEV_ROOT ||
1173
+ process.env.AGENTIC_DEV_SKILL_ROOT;
1174
+ const command = sourceRoot && existsSync(join(sourceRoot, "src", "cli", "index.ts"))
1175
+ ? ["bun", join(sourceRoot, "src", "cli", "index.ts"), "run", "$(basename "$helper_name" .ts)"]
1176
+ : ["forge", "run", "$(basename "$helper_name" .ts)"];
1177
+
1178
+ const result = spawnSync(command[0], [...command.slice(1), ...process.argv.slice(2)], {
1179
+ cwd: process.cwd(),
1180
+ env: process.env,
1181
+ stdio: "inherit",
1182
+ });
1183
+
1184
+ if (result.error) {
1185
+ console.error(\`Missing forge CLI for helper $(basename "$helper_name" .ts): \${result.error.message}\`);
1186
+ process.exit(1);
1187
+ }
1188
+
1189
+ process.exit(result.status ?? 1);
1190
+ EOF_WRAPPER_TS
1191
+ ;;
1192
+ *)
1193
+ local helper_id="${helper_name%.*}"
1194
+ cat > "$output_file" <<EOF_WRAPPER_SH
1195
+ #!/bin/bash
1196
+ set -euo pipefail
1197
+
1198
+ SOURCE_ROOT="\${FORGE_SOURCE_ROOT:-\${AGENTIC_DEV_ROOT:-\${AGENTIC_DEV_SKILL_ROOT:-}}}"
1199
+
1200
+ if [[ -n "\$SOURCE_ROOT" && -f "\$SOURCE_ROOT/src/cli/index.ts" ]]; then
1201
+ if command -v bun >/dev/null 2>&1; then
1202
+ exec bun "\$SOURCE_ROOT/src/cli/index.ts" run $helper_id "\$@"
1203
+ fi
1204
+ fi
1205
+
1206
+ if command -v forge >/dev/null 2>&1; then
1207
+ exec forge run $helper_id "\$@"
1208
+ fi
1209
+
1210
+ echo "Missing forge CLI for helper $helper_id" >&2
1211
+ exit 1
1212
+ EOF_WRAPPER_SH
1213
+ ;;
1214
+ esac
1215
+ }
1216
+
1217
+ pi_normalize_installed_helper() {
1218
+ local helper_file="$1"
1219
+ [[ -f "$helper_file" ]] || return 0
1220
+
1221
+ if [[ "$helper_file" == *.sh ]]; then
1222
+ perl -0pi -e '
1223
+ s#([A-Z_][A-Z0-9_]*)="\$\(cd "\$SCRIPT_DIR/\.\." && pwd\)"#${1}="\$(cd "\$SCRIPT_DIR/../../.." && pwd)"#g;
1224
+ s#if ([A-Z_][A-Z0-9_]*)="\$\(git -C "\$SCRIPT_DIR/\.\." rev-parse --show-toplevel 2>/dev/null\)"; then#if ${1}="\$(git -C "\$SCRIPT_DIR/../../.." rev-parse --show-toplevel 2>/dev/null)"; then#g;
1225
+ s#cd "\$SCRIPT_DIR/\.\."#if [[ "\$SCRIPT_DIR" == */.ai/harness/scripts ]]; then\n cd "\$SCRIPT_DIR/../../.."\nelse\n cd "\$SCRIPT_DIR/.."\nfi#g;
1226
+ s#git -C "\$SCRIPT_DIR/\.\."#git -C "\$SCRIPT_DIR/../../.."#g;
1227
+ s#\./scripts/#.ai/harness/scripts/#g;
1228
+ s#(\$[A-Za-z_][A-Za-z0-9_]*|\$\{[A-Za-z_][A-Za-z0-9_]*\})/scripts/#$1/.ai/harness/scripts/#g;
1229
+ s#(?<![A-Za-z0-9_./-])scripts/#.ai/harness/scripts/#g;
1230
+ ' "$helper_file"
1231
+ elif [[ "$helper_file" == *.ts ]]; then
1232
+ perl -0pi -e '
1233
+ s#join\(SCRIPT_DIR, "\.\."\)#join(SCRIPT_DIR, "..", "..", "..")#g;
1234
+ s#join\(__dirname, "\.\."\)#join(__dirname, "..", "..", "..")#g;
1235
+ s#\./scripts/#.ai/harness/scripts/#g;
1236
+ s#(\$[A-Za-z_][A-Za-z0-9_]*|\$\{[A-Za-z_][A-Za-z0-9_]*\})/scripts/#$1/.ai/harness/scripts/#g;
1237
+ s#(?<![A-Za-z0-9_./-])scripts/#.ai/harness/scripts/#g;
1238
+ ' "$helper_file"
1239
+ fi
1240
+ }
1241
+
1242
+ pi_env_value() {
1243
+ local name="$1"
1244
+ local default_value="${2:-}"
1245
+ local value
1246
+
1247
+ value="${!name-}"
1248
+ if [[ -n "$value" ]]; then
1249
+ printf '%s' "$value"
1250
+ return 0
1251
+ fi
1252
+
1253
+ printf '%s' "$default_value"
1254
+ }
1255
+
1256
+ pi_plan_type() {
1257
+ local default_value="${1:-}"
1258
+ pi_env_value "FORGE_PLAN_TYPE" "$default_value"
1259
+ }
1260
+
1261
+ pi_context_profile() {
1262
+ pi_env_value "FORGE_CONTEXT_PROFILE" "$PI_CONTEXT_PROFILE_DEFAULT"
1263
+ }
1264
+
1265
+ pi_recovery_profile() {
1266
+ pi_env_value "FORGE_RECOVERY_PROFILE" "$PI_RECOVERY_PROFILE_DEFAULT"
1267
+ }
1268
+
1269
+ pi_state_profile() {
1270
+ pi_env_value "FORGE_STATE_PROFILE" "$PI_STATE_PROFILE_DEFAULT"
1271
+ }
1272
+
1273
+ pi_orchestration_profile() {
1274
+ pi_env_value "FORGE_ORCHESTRATION_PROFILE" "$PI_ORCHESTRATION_PROFILE_DEFAULT"
1275
+ }
1276
+
1277
+ pi_evaluation_profile() {
1278
+ pi_env_value "FORGE_EVALUATION_PROFILE" "$PI_EVALUATION_PROFILE_DEFAULT"
1279
+ }
1280
+
1281
+ pi_handoff_profile() {
1282
+ pi_env_value "FORGE_HANDOFF_PROFILE" "$PI_HANDOFF_PROFILE_DEFAULT"
1283
+ }
1284
+
1285
+ pi_documentation_profile() {
1286
+ pi_env_value "FORGE_DOCUMENTATION_PROFILE" "$PI_DOCUMENTATION_PROFILE_DEFAULT"
1287
+ }
1288
+
1289
+ pi_lsp_profile() {
1290
+ pi_env_value "FORGE_LSP_PROFILE" "$PI_DEFAULT_LSP_PROFILE"
1291
+ }
1292
+
1293
+ pi_should_generate_full_docs() {
1294
+ case "$(pi_documentation_profile)" in
1295
+ full|full-docs|legacy-full)
1296
+ return 0
1297
+ ;;
1298
+ *)
1299
+ return 1
1300
+ ;;
1301
+ esac
1302
+ }
1303
+
1304
+ pi_external_tooling_hosts_json() {
1305
+ pi_env_value "FORGE_EXTERNAL_TOOLING_HOSTS_JSON" "$PI_EXTERNAL_TOOLING_HOSTS_DEFAULT"
1306
+ }
1307
+
1308
+ pi_external_tooling_gbrain_mcp() {
1309
+ pi_env_value "FORGE_EXTERNAL_TOOLING_GBRAIN_MCP" "candidate-disabled"
1310
+ }
1311
+
1312
+ pi_external_tooling_defaults_summary() {
1313
+ cat <<'EOF_EXTERNAL_TOOLING_DEFAULTS'
1314
+ - Policy defaults: routing complex->gstack, simple->waza, knowledge->gbrain
1315
+ - Hosts: claude-code, codex
1316
+ - Mode: agent-readiness-required
1317
+ - Detection: init-migrate
1318
+ - Waza: Codex-first, managed skills think/hunt/check/health, stage upstream in ~/.agents/skills, sync verified copies into ~/.codex/skills
1319
+ - Codex automation profile: required health/check/mermaid from ~/.codex/skills; do not vendor skill bodies
1320
+ - gbrain MCP: candidate-disabled
1321
+ - CodeGraph: required agent code-navigation readiness tool, target-aware MCP configure by explicit user command or authorized agent action, per-repo ignored .codegraph/ index; generated repos do not add it as a package dependency unless local policy opts in
1322
+ - Auto-actions: never install, upgrade, serve, sync, or enable MCP automatically
1323
+ EOF_EXTERNAL_TOOLING_DEFAULTS
1324
+ }
1325
+
1326
+ pi_resolve_external_tooling_detector() {
1327
+ local repo_dir="$1"
1328
+ local fallback_script="${2:-}"
1329
+ local repo_detector="$repo_dir/.ai/harness/scripts/check-agent-tooling.sh"
1330
+ local legacy_repo_detector="$repo_dir/scripts/check-agent-tooling.sh"
1331
+
1332
+ if [[ -n "$fallback_script" && -f "$fallback_script" ]]; then
1333
+ printf '%s' "$fallback_script"
1334
+ return 0
1335
+ fi
1336
+
1337
+ if [[ -f "$repo_detector" ]]; then
1338
+ printf '%s' "$repo_detector"
1339
+ return 0
1340
+ fi
1341
+
1342
+ if [[ -f "$legacy_repo_detector" ]]; then
1343
+ printf '%s' "$legacy_repo_detector"
1344
+ return 0
1345
+ fi
1346
+
1347
+ return 1
1348
+ }
1349
+
1350
+ pi_print_external_tooling_report() {
1351
+ local repo_dir="$1"
1352
+ local mode="${2:-apply}"
1353
+ local fallback_script="${3:-}"
1354
+ local detector
1355
+ local output
1356
+
1357
+ echo "--- External Tooling ---"
1358
+ pi_external_tooling_defaults_summary
1359
+
1360
+ detector="$(pi_resolve_external_tooling_detector "$repo_dir" "$fallback_script" || true)"
1361
+ if [[ -z "$detector" ]]; then
1362
+ echo "- Advisory detector: unavailable"
1363
+ return 0
1364
+ fi
1365
+
1366
+ local detector_args=(--host both)
1367
+ local check_tooling_updates="${FORGE_CHECK_TOOLING_UPDATES:-${AGENTIC_DEV_CHECK_TOOLING_UPDATES:-0}}"
1368
+ if [[ "$check_tooling_updates" == "1" ]]; then
1369
+ detector_args+=(--check-updates)
1370
+ fi
1371
+
1372
+ if output="$(cd "$repo_dir" && bash "$detector" "${detector_args[@]}" 2>&1)"; then
1373
+ if [[ "$mode" == "apply" ]]; then
1374
+ echo "- Advisory report:"
1375
+ else
1376
+ echo "- Advisory report (dry-run snapshot):"
1377
+ fi
1378
+ printf '%s\n' "$output" | sed 's/^/ /'
1379
+ return 0
1380
+ fi
1381
+
1382
+ echo "- Advisory report: detector failed (non-fatal)"
1383
+ printf '%s\n' "$output" | sed 's/^/ /'
1384
+ }
1385
+
1386
+ pi_reference_config_names() {
1387
+ local ref_assets_dir="$1"
1388
+ local name
1389
+
1390
+ if pi_should_generate_full_docs; then
1391
+ find "$ref_assets_dir" -maxdepth 1 -type f -name '*.md' \
1392
+ ! -name 'AGENTS.md' \
1393
+ ! -name 'CLAUDE.md' \
1394
+ -print 2>/dev/null | sort | while IFS= read -r ref_file; do
1395
+ basename "$ref_file"
1396
+ done
1397
+ return 0
1398
+ fi
1399
+
1400
+ for name in $PI_MINIMAL_REFERENCE_CONFIGS; do
1401
+ [[ -f "$ref_assets_dir/$name" ]] || continue
1402
+ printf '%s\n' "$name"
1403
+ done
1404
+ }
1405
+
1406
+ pi_install_reference_configs() {
1407
+ local target_dir="$1"
1408
+ local ref_assets_dir="$2"
1409
+ local mode="${3:-apply}"
1410
+ local ref_dir="$target_dir/docs/reference-configs"
1411
+ local name
1412
+ local source_repo_target=0
1413
+
1414
+ if [[ "$mode" != "apply" ]]; then
1415
+ echo "[dry-run] install $(pi_documentation_profile) reference config stubs into $ref_dir"
1416
+ return 0
1417
+ fi
1418
+
1419
+ mkdir -p "$ref_dir"
1420
+ if [[ ! -d "$ref_assets_dir" ]]; then
1421
+ return 0
1422
+ fi
1423
+
1424
+ if [[ -d "$target_dir/assets/reference-configs" ]]; then
1425
+ local target_refs_abs refs_abs
1426
+ target_refs_abs="$(cd "$target_dir/assets/reference-configs" && pwd)"
1427
+ refs_abs="$(cd "$ref_assets_dir" && pwd)"
1428
+ if [[ "$target_refs_abs" == "$refs_abs" ]]; then
1429
+ source_repo_target=1
1430
+ fi
1431
+ fi
1432
+
1433
+ while IFS= read -r name; do
1434
+ [[ -n "$name" ]] || continue
1435
+ if [[ "$source_repo_target" -eq 1 ]]; then
1436
+ cp "$ref_assets_dir/$name" "$ref_dir/$name"
1437
+ continue
1438
+ fi
1439
+
1440
+ if pi_should_preserve_reference_config "$ref_dir/$name" "$ref_assets_dir/$name"; then
1441
+ echo "[forge] preserved user-authored reference config: docs/reference-configs/$name"
1442
+ continue
1443
+ fi
1444
+
1445
+ pi_write_reference_config_stub "$ref_dir/$name" "$name" "$ref_assets_dir"
1446
+ done < <(pi_reference_config_names "$ref_assets_dir")
1447
+ }
1448
+
1449
+ pi_reference_config_doc_id() {
1450
+ local name="$1"
1451
+ printf '%s\n' "${name%.md}"
1452
+ }
1453
+
1454
+ pi_forge_version_for_refs() {
1455
+ local ref_assets_dir="$1"
1456
+ local root_dir
1457
+ root_dir="$(cd "$ref_assets_dir/../.." 2>/dev/null && pwd || true)"
1458
+ if [[ -z "$root_dir" ]]; then
1459
+ printf '%s\n' "unknown"
1460
+ return 0
1461
+ fi
1462
+ local version_file="$root_dir/assets/skill-version.json"
1463
+
1464
+ if [[ -f "$version_file" ]]; then
1465
+ sed -n 's/^[[:space:]]*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$version_file" | head -n 1
1466
+ return 0
1467
+ fi
1468
+
1469
+ printf '%s\n' "unknown"
1470
+ }
1471
+
1472
+ pi_should_preserve_reference_config() {
1473
+ local target_file="$1"
1474
+ local asset_file="$2"
1475
+
1476
+ [[ -f "$target_file" ]] || return 1
1477
+ if [[ -f "$asset_file" ]] && cmp -s "$target_file" "$asset_file"; then
1478
+ return 1
1479
+ fi
1480
+ if grep -Fq "$PI_REFERENCE_CONFIG_STUB_MARKER" "$target_file"; then
1481
+ return 1
1482
+ fi
1483
+ local target_heading asset_heading
1484
+ target_heading="$(pi_reference_config_first_heading "$target_file")"
1485
+ asset_heading="$(pi_reference_config_first_heading "$asset_file")"
1486
+ if [[ -n "$asset_heading" && "$target_heading" == "$asset_heading" ]]; then
1487
+ return 1
1488
+ fi
1489
+
1490
+ return 0
1491
+ }
1492
+
1493
+ pi_reference_config_first_heading() {
1494
+ local file="$1"
1495
+ [[ -f "$file" ]] || return 0
1496
+ sed -n 's/^# //p' "$file" | head -n 1
1497
+ }
1498
+
1499
+ pi_write_reference_config_stub() {
1500
+ local output_file="$1"
1501
+ local name="$2"
1502
+ local ref_assets_dir="$3"
1503
+ local doc_id
1504
+ local version
1505
+
1506
+ doc_id="$(pi_reference_config_doc_id "$name")"
1507
+ version="$(pi_forge_version_for_refs "$ref_assets_dir")"
1508
+
1509
+ cat > "$output_file" <<EOF_REFERENCE_STUB
1510
+ $PI_REFERENCE_CONFIG_STUB_MARKER
1511
+ # forge Reference: $doc_id
1512
+
1513
+ > **Runtime Docs**: user-level forge reference
1514
+ > **Doc ID**: $doc_id
1515
+ > **Version**: $version
1516
+ > **Source Command**: \`forge docs path $doc_id\`
1517
+
1518
+ This repo keeps workflow facts and runtime artifacts locally under \`.ai/\`.
1519
+ The full generic runtime guide is supplied by the installed forge
1520
+ package/user-level runtime so each repository does not need to refresh a full
1521
+ copy of shared documentation.
1522
+
1523
+ Use:
1524
+
1525
+ \`\`\`bash
1526
+ forge docs path $doc_id
1527
+ forge docs show $doc_id
1528
+ \`\`\`
1529
+ EOF_REFERENCE_STUB
1530
+ }
1531
+
1532
+ pi_policy_reference_config_names() {
1533
+ if pi_should_generate_full_docs; then
1534
+ printf '%s\n' $PI_FULL_REFERENCE_CONFIGS
1535
+ return 0
1536
+ fi
1537
+
1538
+ printf '%s\n' $PI_MINIMAL_REFERENCE_CONFIGS
1539
+ }
1540
+
1541
+ pi_json_string_array_from_lines() {
1542
+ local first=1
1543
+ local item
1544
+
1545
+ while IFS= read -r item; do
1546
+ [[ -n "$item" ]] || continue
1547
+ if [[ "$first" -eq 0 ]]; then
1548
+ printf ', '
1549
+ fi
1550
+ first=0
1551
+ printf '"%s"' "$item"
1552
+ done
1553
+ }
1554
+
1555
+ pi_context_block_config_file() {
1556
+ local target_dir="$1"
1557
+ pi_env_value "FORGE_CONTEXT_BLOCKS_FILE" "$target_dir/.ai/context/agent-context-blocks.txt"
1558
+ }
1559
+
1560
+ pi_capability_registry_file() {
1561
+ local target_dir="$1"
1562
+ printf '%s' "$target_dir/.ai/context/capabilities.json"
1563
+ }
1564
+
1565
+ pi_safe_token() {
1566
+ local value="$1"
1567
+ value="$(printf '%s' "$value" | tr '[:upper:]' '[:lower:]')"
1568
+ value="$(printf '%s' "$value" | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//; s/-{2,}/-/g')"
1569
+ printf '%s' "${value:-capability}"
1570
+ }
1571
+
1572
+ pi_legacy_context_block_candidates() {
1573
+ local target_dir="$1"
1574
+ local config_file
1575
+
1576
+ local env_blocks
1577
+ env_blocks="$(pi_env_value "FORGE_CONTEXT_BLOCKS")"
1578
+ if [[ -n "$env_blocks" ]]; then
1579
+ printf '%s\n' "$env_blocks" | tr ',:' '\n'
1580
+ return 0
1581
+ fi
1582
+
1583
+ config_file="$(pi_context_block_config_file "$target_dir")"
1584
+ if [[ -f "$config_file" ]]; then
1585
+ sed -e 's/#.*$//' -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' "$config_file" | sed '/^$/d'
1586
+ return 0
1587
+ fi
1588
+
1589
+ find "$target_dir" \
1590
+ \( \
1591
+ -name .git -o -name node_modules -o -name vendor -o -name .ai -o -name .claude \
1592
+ -o -name _ref -o -name _ops -o -name .worktrees -o -name .cache \
1593
+ -o -name .venv -o -name venv -o -name dist -o -name build -o -name coverage \
1594
+ -o -name .next -o -name .turbo -o -path '*/go/pkg/mod' -o -path '*/Library' \
1595
+ \) -prune -o \
1596
+ \( -type f \( -name 'CLAUDE.md' -o -name 'AGENTS.md' \) \) -print 2>/dev/null | while IFS= read -r context_file; do
1597
+ local context_dir
1598
+ local rel_dir
1599
+ context_dir="$(dirname "$context_file")"
1600
+ rel_dir="${context_dir#$target_dir/}"
1601
+ [[ "$rel_dir" == "$context_dir" || "$rel_dir" == "." ]] && continue
1602
+ printf '%s\n' "$rel_dir"
1603
+ done
1604
+ }
1605
+
1606
+ pi_context_block_candidates() {
1607
+ local target_dir="$1"
1608
+ local registry_file
1609
+ local selector
1610
+
1611
+ registry_file="$(pi_capability_registry_file "$target_dir")"
1612
+ if [[ -f "$registry_file" ]]; then
1613
+ if command -v bun >/dev/null 2>&1 && [[ -f "$target_dir/.ai/harness/scripts/capability-resolver.ts" ]]; then
1614
+ (cd "$target_dir" && bun .ai/harness/scripts/capability-resolver.ts list --format prefixes 2>/dev/null || true)
1615
+ return 0
1616
+ fi
1617
+
1618
+ if command -v node >/dev/null 2>&1; then
1619
+ node - "$registry_file" <<'JS_EOF'
1620
+ const fs = require("fs");
1621
+ const registry = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
1622
+ for (const capability of registry.capabilities || []) {
1623
+ for (const prefix of capability.prefixes || []) console.log(prefix);
1624
+ }
1625
+ JS_EOF
1626
+ return 0
1627
+ fi
1628
+ fi
1629
+
1630
+ selector="$(pi_env_value "FORGE_CONTEXT_BLOCK_SELECTOR")"
1631
+ if [[ -n "$selector" && -x "$selector" ]]; then
1632
+ (cd "$target_dir" && "$selector" "$target_dir")
1633
+ return 0
1634
+ fi
1635
+
1636
+ pi_legacy_context_block_candidates "$target_dir"
1637
+ }
1638
+
1639
+ pi_legacy_context_block_dirs() {
1640
+ local target_dir="$1"
1641
+ local raw_path
1642
+ local rel_path
1643
+
1644
+ pi_legacy_context_block_candidates "$target_dir" | while IFS= read -r raw_path; do
1645
+ rel_path="$(printf '%s' "$raw_path" | sed -e 's/#.*$//' -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
1646
+ rel_path="${rel_path#./}"
1647
+ rel_path="${rel_path%/}"
1648
+ [[ -z "$rel_path" || "$rel_path" == "." ]] && continue
1649
+ case "$rel_path" in
1650
+ /*|../*|*/../*|*\"*)
1651
+ continue
1652
+ ;;
1653
+ esac
1654
+ [[ -d "$target_dir/$rel_path" ]] || continue
1655
+ printf '%s\n' "$rel_path"
1656
+ done | sort -u
1657
+ }
1658
+
1659
+ pi_context_block_dirs() {
1660
+ local target_dir="$1"
1661
+ local raw_path
1662
+ local rel_path
1663
+
1664
+ pi_context_block_candidates "$target_dir" | while IFS= read -r raw_path; do
1665
+ rel_path="$(printf '%s' "$raw_path" | sed -e 's/#.*$//' -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
1666
+ rel_path="${rel_path#./}"
1667
+ rel_path="${rel_path%/}"
1668
+ [[ -z "$rel_path" || "$rel_path" == "." ]] && continue
1669
+ case "$rel_path" in
1670
+ /*|../*|*/../*|*\"*)
1671
+ continue
1672
+ ;;
1673
+ esac
1674
+ [[ -d "$target_dir/$rel_path" ]] || continue
1675
+ printf '%s\n' "$rel_path"
1676
+ done | sort -u
1677
+ }
1678
+
1679
+ pi_write_capability_registry() {
1680
+ local target_dir="$1"
1681
+ local mode="${2:-apply}"
1682
+ local output_file
1683
+ local rel_dir
1684
+ local first=1
1685
+
1686
+ output_file="$(pi_capability_registry_file "$target_dir")"
1687
+
1688
+ if [[ "$mode" != "apply" ]]; then
1689
+ echo "[dry-run] write $output_file"
1690
+ return 0
1691
+ fi
1692
+
1693
+ if [[ -f "$output_file" ]]; then
1694
+ return 0
1695
+ fi
1696
+
1697
+ mkdir -p "$(dirname "$output_file")"
1698
+ {
1699
+ printf '{\n "version": 1,\n "capabilities": [\n'
1700
+ while IFS= read -r rel_dir; do
1701
+ [[ -n "$rel_dir" ]] || continue
1702
+ local domain
1703
+ local name
1704
+ local id
1705
+ local parts_count
1706
+ local last_part
1707
+
1708
+ parts_count="$(awk -F'/' '{print NF}' <<< "$rel_dir")"
1709
+ last_part="${rel_dir##*/}"
1710
+ if [[ "$parts_count" -ge 2 ]]; then
1711
+ domain="$(pi_safe_token "$(cut -d/ -f1-2 <<< "$rel_dir" | tr '/' '-')")"
1712
+ else
1713
+ domain="$(pi_safe_token "$rel_dir")"
1714
+ fi
1715
+ if [[ "$parts_count" -gt 2 ]]; then
1716
+ name="$(pi_safe_token "$last_part")"
1717
+ id="${domain}-${name}"
1718
+ else
1719
+ name="$(pi_safe_token "$last_part")"
1720
+ id="$domain"
1721
+ fi
1722
+
1723
+ if [[ "$first" -eq 0 ]]; then
1724
+ printf ',\n'
1725
+ fi
1726
+ first=0
1727
+ cat <<EOF_CAPABILITY
1728
+ {
1729
+ "id": "$id",
1730
+ "domain": "$domain",
1731
+ "name": "$name",
1732
+ "prefixes": ["$rel_dir"],
1733
+ "contract_files": {
1734
+ "agents": "$rel_dir/AGENTS.md",
1735
+ "claude": "$rel_dir/CLAUDE.md"
1736
+ },
1737
+ "architecture_module": "docs/architecture/modules/$domain/$name.md",
1738
+ "workstream_dir": "tasks/workstreams/$domain/$name",
1739
+ "lsp_profile": "$(pi_lsp_profile)",
1740
+ "verification_hints": ["record local commands here before implementation"]
1741
+ }
1742
+ EOF_CAPABILITY
1743
+ done < <(pi_legacy_context_block_dirs "$target_dir")
1744
+ printf '\n ]\n}\n'
1745
+ } > "$output_file"
1746
+ }
1747
+
1748
+ pi_should_generate_directory_context() {
1749
+ local target_dir="$1"
1750
+ [[ -n "$(pi_context_block_dirs "$target_dir" | head -n 1)" ]]
1751
+ }
1752
+
1753
+ pi_context_map_discoverable_entries() {
1754
+ local target_dir="$1"
1755
+ local first_entry=1
1756
+ local rel_dir
1757
+ local file_name
1758
+ local target_agent
1759
+ local registry_file
1760
+ local capability_entries
1761
+
1762
+ registry_file="$(pi_capability_registry_file "$target_dir")"
1763
+ if [[ -f "$registry_file" ]] && command -v node >/dev/null 2>&1; then
1764
+ capability_entries="$(node - "$registry_file" <<'JS_EOF'
1765
+ const fs = require("fs");
1766
+ const registry = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
1767
+ const entries = [];
1768
+ for (const capability of registry.capabilities || []) {
1769
+ const prefix = (capability.prefixes || [])[0];
1770
+ if (!prefix || !capability.contract_files) continue;
1771
+ for (const [fileName, targetAgent] of [["CLAUDE.md", "claude"], ["AGENTS.md", "codex"]]) {
1772
+ const path = fileName === "CLAUDE.md" ? capability.contract_files.claude : capability.contract_files.agents;
1773
+ entries.push({
1774
+ path,
1775
+ priority: "high",
1776
+ char_budget: 1000,
1777
+ purpose: "capability-contract",
1778
+ capability_id: capability.id,
1779
+ functional_block: prefix,
1780
+ matched_prefix: prefix,
1781
+ architecture_domain: capability.domain,
1782
+ architecture_capability: capability.name,
1783
+ target_agent: targetAgent,
1784
+ lsp_profile: capability.lsp_profile || "typescript-lsp",
1785
+ doc_scope: "capability-contract",
1786
+ verification_hint: (capability.verification_hints || [])[0] || "record local commands here before implementation"
1787
+ });
1788
+ }
1789
+ }
1790
+ process.stdout.write(entries.map((entry) => JSON.stringify(entry, null, 6).replace(/^/gm, " ")).join(",\n"));
1791
+ JS_EOF
1792
+ )"
1793
+ if [[ -n "$capability_entries" ]]; then
1794
+ printf '%s,\n' "$capability_entries"
1795
+ fi
1796
+ cat <<'EOF_CONTEXT_ENTRY'
1797
+ {
1798
+ "path": "docs/reference-configs/*.md",
1799
+ "priority": "low",
1800
+ "char_budget": 900,
1801
+ "purpose": "deep-doc"
1802
+ },
1803
+ {
1804
+ "path": "tasks/workstreams/**/*.md",
1805
+ "priority": "high",
1806
+ "char_budget": 1200,
1807
+ "purpose": "capability-workstream"
1808
+ }
1809
+ EOF_CONTEXT_ENTRY
1810
+ return 0
1811
+ fi
1812
+
1813
+ while IFS= read -r rel_dir; do
1814
+ [[ -n "$rel_dir" ]] || continue
1815
+ for file_name in CLAUDE.md AGENTS.md; do
1816
+ if [[ "$first_entry" -eq 0 ]]; then
1817
+ printf ',\n'
1818
+ fi
1819
+ first_entry=0
1820
+ target_agent="codex"
1821
+ [[ "$file_name" == "CLAUDE.md" ]] && target_agent="claude"
1822
+ cat <<EOF_CONTEXT_ENTRY
1823
+ {
1824
+ "path": "$rel_dir/$file_name",
1825
+ "priority": "high",
1826
+ "char_budget": 1000,
1827
+ "purpose": "capability-contract",
1828
+ "functional_block": "$rel_dir",
1829
+ "target_agent": "$target_agent",
1830
+ "lsp_profile": "$(pi_lsp_profile)",
1831
+ "doc_scope": "capability-contract",
1832
+ "verification_hint": "record local commands here before implementation"
1833
+ }
1834
+ EOF_CONTEXT_ENTRY
1835
+ done
1836
+ done < <(pi_context_block_dirs "$target_dir")
1837
+
1838
+ if [[ "$first_entry" -eq 0 ]]; then
1839
+ printf ',\n'
1840
+ fi
1841
+
1842
+ cat <<'EOF_CONTEXT_ENTRY'
1843
+ {
1844
+ "path": "docs/reference-configs/*.md",
1845
+ "priority": "low",
1846
+ "char_budget": 900,
1847
+ "purpose": "deep-doc"
1848
+ },
1849
+ {
1850
+ "path": "tasks/workstreams/**/*.md",
1851
+ "priority": "high",
1852
+ "char_budget": 1200,
1853
+ "purpose": "capability-workstream"
1854
+ }
1855
+ EOF_CONTEXT_ENTRY
1856
+ }
1857
+
1858
+ pi_write_harness_policy() {
1859
+ local target_dir="$1"
1860
+ local mode="${2:-apply}"
1861
+ local output_file="$target_dir/.ai/harness/policy.json"
1862
+ local default_file
1863
+ local merged_file
1864
+
1865
+ if [[ "$mode" != "apply" ]]; then
1866
+ echo "[dry-run] write $output_file"
1867
+ return 0
1868
+ fi
1869
+
1870
+ mkdir -p "$(dirname "$output_file")"
1871
+ default_file="$(mktemp)"
1872
+ merged_file="$(mktemp)"
1873
+ cat > "$default_file" <<EOF_POLICY
1874
+ {
1875
+ "version": 1,
1876
+ "active_plan": {
1877
+ "marker_file": ".ai/harness/active-plan",
1878
+ "legacy_marker_file": ".claude/.active-plan",
1879
+ "directory": "plans",
1880
+ "archive_directory": "plans/archive",
1881
+ "glob": "plan-*.md",
1882
+ "active_worktree_marker_file": ".ai/harness/active-worktree",
1883
+ "source_of_truth": "per-worktree explicit marker with active-worktree owner; legacy Claude marker fallback only"
1884
+ },
1885
+ "tasks": {
1886
+ "todo_file": "tasks/todos.md",
1887
+ "current_status_file": "tasks/current.md",
1888
+ "lessons_file": "tasks/lessons.md",
1889
+ "research_dir": "docs/researches",
1890
+ "workstreams_dir": "tasks/workstreams",
1891
+ "contracts_dir": "tasks/contracts",
1892
+ "reviews_dir": "tasks/reviews",
1893
+ "notes_dir": "tasks/notes"
1894
+ },
1895
+ "prds": {
1896
+ "dir": "plans/prds",
1897
+ "template_file": ".claude/templates/prd.template.md",
1898
+ "statuses": ["Draft", "Approved", "Superseded"],
1899
+ "rule": "PRDs live in plans/prds as the upper planning layer. They decompose docs/spec.md intent into product direction, acceptance scenarios, module behavior, data model, performance targets, and developer handoff. Sprints reference PRDs through Source PRD and decompose them into ordered execution backlogs."
1900
+ },
1901
+ "sprints": {
1902
+ "dir": "plans/sprints",
1903
+ "active_marker_file": ".ai/harness/sprint/active-sprint",
1904
+ "template_file": ".claude/templates/sprint.template.md",
1905
+ "helper_script": "scripts/sprint-backlog.sh",
1906
+ "statuses": ["Draft", "Approved", "Executing", "Done", "Archived"],
1907
+ "rule": "PRDs live in plans/prds as the upper planning layer. Sprints live in plans/sprints as long-task execution backlogs; each sprint row is expanded with Waza \$think into a detailed plans/plan-*.md before the plan -> contract -> worktree flow; tasks/todos.md stays the deferred-goal ledger"
1908
+ },
1909
+ "reference_material": {
1910
+ "dir": "_ref",
1911
+ "mode": "external-ignored",
1912
+ "commit_policy": "never commit _ref contents",
1913
+ "rule": "use _ref as an occasional ignored external reference checkout cache for upstream/source comparison only; refresh from external sources instead of editing as product code; when it influences a decision, cite the source repo plus commit/tag and path in tasks/notes/ or docs/researches/"
1914
+ },
1915
+ "operations": {
1916
+ "dir": "deploy",
1917
+ "private_dir": "_ops",
1918
+ "tracked": ["deploy/README.md", "deploy/scripts/", "deploy/submissions/", "deploy/runbooks/", "deploy/release-checklists/", "deploy/sql/", "deploy/*.md", "deploy/env/.env.example"],
1919
+ "ignored": ["_ops/"],
1920
+ "rule": "commit deployment runbooks, submission materials, release checklists, helper scripts, ordered SQL files, and env examples under deploy/; keep deploy SQL in deploy/sql/ with 4-digit ascending prefixes; keep keys, tokens, real env values, provider state, artifacts, logs, and scratch files in ignored _ops/ only"
1921
+ },
1922
+ "context": {
1923
+ "profile": "$(pi_context_profile)",
1924
+ "map_file": ".ai/context/context-map.json",
1925
+ "capability_registry_file": ".ai/context/capabilities.json",
1926
+ "capability_resolver": "scripts/capability-resolver.ts",
1927
+ "capability_config": "scripts/capability-config.ts",
1928
+ "capability_match_rule": "longest-prefix; same-length ambiguity fails",
1929
+ "functional_block_selector": {
1930
+ "script": "scripts/select-agent-context-blocks.sh",
1931
+ "config_file": ".ai/context/agent-context-blocks.txt",
1932
+ "env": "FORGE_CONTEXT_BLOCKS",
1933
+ "rule": "compatibility selector; capability registry is the source of truth"
1934
+ }
1935
+ },
1936
+ "harness": {
1937
+ "policy_file": ".ai/harness/policy.json",
1938
+ "checks_file": ".ai/harness/checks/latest.json",
1939
+ "handoff_file": ".ai/harness/handoff/current.md",
1940
+ "failure_log_file": ".ai/harness/failures/latest.jsonl",
1941
+ "events_file": ".ai/harness/events.jsonl",
1942
+ "architecture_events_file": ".ai/harness/architecture/events.jsonl",
1943
+ "runs_dir": ".ai/harness/runs",
1944
+ "helper_runtime_dir": ".ai/harness/scripts",
1945
+ "helper_compat_dir": "scripts",
1946
+ "helper_source": "package",
1947
+ "helper_package_dir": "assets/templates/helpers"
1948
+ },
1949
+ "architecture": {
1950
+ "index_file": "docs/architecture/index.md",
1951
+ "requests_dir": "docs/architecture/requests",
1952
+ "snapshots_dir": "docs/architecture/snapshots",
1953
+ "diagrams_dir": "docs/architecture/diagrams",
1954
+ "domains_dir": "docs/architecture/domains",
1955
+ "modules_dir": "docs/architecture/modules",
1956
+ "diagram_skill": "mermaid",
1957
+ "diagram_skill_source": "~/.codex/skills/mermaid",
1958
+ "vendoring_policy": "do-not-vendor-diagram-skill-assets",
1959
+ "freshness_gate": "advisory",
1960
+ "gate_min_severity": "medium",
1961
+ "pending_card_scope": "capability",
1962
+ "pending_block_begin": "<!-- BEGIN ARCHITECTURE PENDING REQUESTS -->",
1963
+ "pending_block_end": "<!-- END ARCHITECTURE PENDING REQUESTS -->",
1964
+ "queue_script": ".ai/harness/scripts/architecture-queue.sh",
1965
+ "contract_block_begin": "<!-- BEGIN ARCHITECTURE CONTRACT -->",
1966
+ "contract_block_end": "<!-- END ARCHITECTURE CONTRACT -->",
1967
+ "rule": "hooks record architecture queue cards and sync controlled local context blocks; agents author semantic snapshots and diagrams"
1968
+ },
1969
+ "workstreams": {
1970
+ "dir": "tasks/workstreams",
1971
+ "scope": "capability",
1972
+ "projection": "local-contract-active-pointer-and-current-slice",
1973
+ "todo_projection": "tasks/todos.md",
1974
+ "rule": "durable multi-session progress lives under tasks/workstreams/<domain>/<capability>; current plan execution lives in the plan Task Breakdown; tasks/todos.md records deferred goals only"
1975
+ },
1976
+ "information_lifecycle": {
1977
+ "notes": {
1978
+ "dir": "tasks/notes",
1979
+ "purpose": "task-local implementation decisions, deviations, tradeoffs, and open questions",
1980
+ "promotion": "archive on workflow close; promote only repeated or durable findings"
1981
+ },
1982
+ "evidence": {
1983
+ "latest": ".ai/harness/checks/latest.json",
1984
+ "snapshots_dir": ".ai/harness/runs",
1985
+ "purpose": "raw verification records used to audit notes, reviews, and future promotion"
1986
+ },
1987
+ "assets": {
1988
+ "sources": [".ai/harness/policy.json", ".ai/harness/workflow-contract.json", ".ai/hooks/", "scripts/", "docs/reference-configs/"],
1989
+ "promotion_rule": "only promote patterns after verified reuse across tasks or fixtures"
1990
+ },
1991
+ "memory": {
1992
+ "sources": ["docs/researches/", "tasks/lessons.md", "gbrain"],
1993
+ "rule": "memory is advisory; current repo state and evidence override summaries"
1994
+ },
1995
+ "external_knowledge": {
1996
+ "default_brain_path": "brain/<project>/*",
1997
+ "project_path": "brain/<project>/*",
1998
+ "manifest_file": ".ai/harness/brain-manifest.json",
1999
+ "drift_check": "scripts/check-brain-manifest.sh",
2000
+ "sync_script": "scripts/sync-brain-docs.sh",
2001
+ "hook_trigger": "PostToolUse Edit|Write for manifest entries with sync.direction=repo-to-brain",
2002
+ "rule": "external knowledge stores long-lived explanations, runbooks, and patterns only; repo-local contracts, hooks, scripts, checks, and evidence remain authoritative",
2003
+ "sync_rule": "only explicitly opted-in repo-to-brain manifest entries may be written to the default brain vault; pointer-only externalized stubs remain check-only"
2004
+ }
2005
+ },
2006
+ "handoff_resume": {
2007
+ "resume_packet_file": ".ai/harness/handoff/resume.md",
2008
+ "global_handoff_dir": "~/.codex/handoffs",
2009
+ "auto_start_new_session": false
2010
+ },
2011
+ "plan_capture": {
2012
+ "script": "scripts/capture-plan.sh",
2013
+ "sources": ["codex-plan-mode", "waza-think", "forge-plan", "forge-sprint"],
2014
+ "rule": "Codex Plan mode and Waza think planning should capture decision-complete plans into plans/plan-*.md; implementation approval then projects the active approved plan through scripts/plan-to-todo.sh; sprint backlog rows are long-task waypoints and should be expanded with \$think before capture/execution"
2015
+ },
2016
+ "planning": {
2017
+ "pending_orchestration_file": ".ai/harness/planning/pending.json",
2018
+ "source_of_truth": "transient host planning bridge only; plans/ and .ai/harness/active-plan remain authoritative"
2019
+ },
2020
+ "guards": {
2021
+ "edit_plan_gate": "advice",
2022
+ "edit_plan_gate_modes": ["enforce", "advice", "off"],
2023
+ "rule": "pre-edit-guard advises when implementation lacks an active plan; execution remains available unless a real safety boundary blocks it"
2024
+ },
2025
+ "sidecar_research": {
2026
+ "default": true,
2027
+ "output_dir": "docs/researches",
2028
+ "preferred_runners": ["subagent", "codex exec --json", "main-thread trace"],
2029
+ "spawn_decision": "main agent decides from task breadth, context impact, raw-log volume, and callable runner availability; do not ask the user for spawn confirmation",
2030
+ "fallback_runner": "main-thread trace",
2031
+ "main_thread_policy": "if spawning is not worthwhile or no sidecar runner is callable, perform bounded research in the main thread; consume conclusions and evidence paths, not raw logs"
2032
+ },
2033
+ "documentation": {
2034
+ "profile": "$(pi_documentation_profile)",
2035
+ "reference_source": "user-level-runtime-docs",
2036
+ "reference_stub_marker": "$PI_REFERENCE_CONFIG_STUB_MARKER",
2037
+ "reference_resolver": "forge docs path <doc-id>",
2038
+ "required": ["docs/spec.md", "docs/architecture/index.md"],
2039
+ "on_demand": ["docs/brief.md", "docs/tech-stack.md", "docs/decisions.md", "docs/architecture.md", "docs/packages.md"],
2040
+ "reference_configs": [$(pi_policy_reference_config_names | pi_json_string_array_from_lines)],
2041
+ "rule": "create optional docs only when the agent has concrete repo evidence or the user asks; docs/reference-configs contains repo-local pointer stubs while full generic runtime docs live in the user-level/package forge install"
2042
+ },
2043
+ "lsp_profiles": {
2044
+ "default": "$(pi_lsp_profile)",
2045
+ "selection": "functional-block-first",
2046
+ "rule": "use block-level LSP/tooling hints before broad repo assumptions"
2047
+ },
2048
+ "worktree_strategy": {
2049
+ "auto_on_conflict": true,
2050
+ "auto_for_contract_tasks": true,
2051
+ "branch_prefix": "codex/",
2052
+ "base_branch": "main",
2053
+ "worktree_dir_template": "../{{repo}}-wt-{{slug}}",
2054
+ "start_script": "scripts/contract-worktree.sh start --plan <plan-file>",
2055
+ "finish_script": "scripts/contract-worktree.sh finish",
2056
+ "cleanup_script": "scripts/contract-worktree.sh cleanup --slug <slug>",
2057
+ "conflict_signals": [
2058
+ "dirty_worktree_overlaps_task_files",
2059
+ "current_branch_not_suitable_for_task",
2060
+ "existing_changes_unrelated_but_would_block_review",
2061
+ "task_requires_clean_validation_surface"
2062
+ ],
2063
+ "validation_route": "waza:check",
2064
+ "merge_back": {
2065
+ "target": "main",
2066
+ "requires_clean_check": true,
2067
+ "preserve_unrelated_changes": true
2068
+ }
2069
+ },
2070
+ "upgrade": {
2071
+ "strategy_version": 1,
2072
+ "supported_legacy_versions": ["pre-tasks-first", "tasks-first-without-contract-manifest", "current-v1"],
2073
+ "action_classes": {
2074
+ "preserve": "keep user-authored hooks, ignored reference material, private operations state, secrets, and local env files unchanged",
2075
+ "archive": "move user-authored legacy workflow documents or checklists into archive/research surfaces before refresh",
2076
+ "reconfigure": "merge managed config defaults without overwriting explicit repo overrides",
2077
+ "remove": "delete only workflow-contract actions marked ownership=known_generated"
2078
+ },
2079
+ "cleanup": {
2080
+ "source": ".ai/harness/workflow-contract.json#migrations.upgrade.actions",
2081
+ "remove_only_ownership": "known_generated",
2082
+ "unknown_files": "preserve-or-archive",
2083
+ "custom_hooks": "preserve",
2084
+ "ignored_reference_material": "preserve",
2085
+ "local_operations_state": "preserve",
2086
+ "local_secrets": "preserve"
2087
+ },
2088
+ "reporting": {
2089
+ "inspector_field": "upgrade_plan",
2090
+ "dry_run_required": true
2091
+ }
2092
+ },
2093
+ "profiles": {
2094
+ "orchestration": "$(pi_orchestration_profile)",
2095
+ "evaluation": "$(pi_evaluation_profile)",
2096
+ "handoff": "$(pi_handoff_profile)",
2097
+ "recovery": "$(pi_recovery_profile)",
2098
+ "state": "$(pi_state_profile)"
2099
+ },
2100
+ "external_tooling": {
2101
+ "routing": {
2102
+ "complex": "gstack",
2103
+ "simple": "waza",
2104
+ "knowledge": "gbrain"
2105
+ },
2106
+ "hosts": $(pi_external_tooling_hosts_json),
2107
+ "mode": "agent-readiness-required",
2108
+ "detection": "init-migrate",
2109
+ "readiness_gate": "forge run check-agent-tooling --host codex --strict-readiness",
2110
+ "waza": {
2111
+ "source_repo": "tw93/Waza",
2112
+ "source_url": "https://github.com/tw93/Waza.git",
2113
+ "managed_skills": ["think", "hunt", "check", "health"],
2114
+ "primary_host": "codex",
2115
+ "codex_primary_path": "~/.codex/skills",
2116
+ "staging_cache_path": "~/.agents/skills",
2117
+ "sync_mode": "stage-upstream-then-copy-to-codex",
2118
+ "host_drift_policy": "report-per-host-version-staging-and-upstream-drift"
2119
+ },
2120
+ "codex_automation_profile": {
2121
+ "required_skills": ["health", "check", "mermaid"],
2122
+ "optional_skills": [],
2123
+ "mode": "codex-runtime-reference",
2124
+ "source": "~/.codex/skills",
2125
+ "routes": {
2126
+ "workflow_health": "waza:health",
2127
+ "review_gate": "waza:check",
2128
+ "architecture_diagram": "mermaid"
2129
+ },
2130
+ "vendoring_policy": "do-not-vendor-skill-body"
2131
+ },
2132
+ "diagram_design": {
2133
+ "skill_name": "mermaid",
2134
+ "primary_host": "codex",
2135
+ "codex_primary_path": "~/.codex/skills/mermaid",
2136
+ "sync_mode": "external-installed-skill",
2137
+ "vendoring_policy": "do-not-vendor"
2138
+ },
2139
+ "gbrain": {
2140
+ "mcp": "$(pi_external_tooling_gbrain_mcp)"
2141
+ },
2142
+ "codegraph": {
2143
+ "package": "@colbymchenry/codegraph",
2144
+ "primary_host": "both",
2145
+ "install_mode": "target-aware-mcp",
2146
+ "codex_config_path": "~/.codex/config.toml",
2147
+ "claude_config_path": "~/.claude.json",
2148
+ "index_dir": ".codegraph",
2149
+ "readiness": "required-for-agent-code-navigation",
2150
+ "hook_policy": "do-not-block-hooks",
2151
+ "install_command": "bun add -g @colbymchenry/codegraph && forge tools configure codegraph --target codex --location global",
2152
+ "project_init_command": "codegraph init -i .",
2153
+ "sync_command": "codegraph sync .",
2154
+ "vendoring_policy": "do-not-add-package-dependency"
2155
+ }
2156
+ },
2157
+ "agentic_development": {
2158
+ "routing": {
2159
+ "product_discovery": "gstack:office-hours",
2160
+ "complex_engineering_plan": "gstack:plan-eng-review",
2161
+ "design_plan": "gstack:plan-design-review",
2162
+ "small_or_medium_plan": "waza:think",
2163
+ "bug_or_regression": "waza:hunt",
2164
+ "post_implementation_review": "waza:check"
2165
+ },
2166
+ "due_diligence": {
2167
+ "levels": ["P1_GLOBAL_ARCHITECTURE", "P2_DATA_FLOW_TRACE", "P3_DESIGN_DECISION"],
2168
+ "explicit_report_required_for": ["plan-eng-review", "hunt", "risky_refactor", "deployment", "auth_payment_data", "shared_contract"]
2169
+ }
2170
+ },
2171
+ "enforcement": {
2172
+ "worktree_guard": "warn-by-default",
2173
+ "verification_gate": "contract-and-review",
2174
+ "completion_requires_checks": true
2175
+ }
2176
+ }
2177
+ EOF_POLICY
2178
+
2179
+ if [[ -f "$output_file" ]]; then
2180
+ if ! pi_merge_json_defaults "$default_file" "$output_file" "$merged_file"; then
2181
+ cp "$default_file" "$merged_file"
2182
+ fi
2183
+ elif ! pi_merge_json_defaults "$default_file" "$default_file" "$merged_file"; then
2184
+ cp "$default_file" "$merged_file"
2185
+ else
2186
+ :
2187
+ fi
2188
+
2189
+ mv "$merged_file" "$output_file"
2190
+ rm -f "$default_file"
2191
+ }
2192
+
2193
+ pi_write_brain_manifest() {
2194
+ local target_dir="$1"
2195
+ local mode="${2:-apply}"
2196
+ local output_file="$target_dir/.ai/harness/brain-manifest.json"
2197
+ local project_name
2198
+
2199
+ if [[ "$mode" != "apply" ]]; then
2200
+ echo "[dry-run] write $output_file if missing"
2201
+ return 0
2202
+ fi
2203
+
2204
+ if [[ -f "$output_file" ]]; then
2205
+ return 0
2206
+ fi
2207
+
2208
+ project_name="$(basename "$target_dir")"
2209
+ mkdir -p "$(dirname "$output_file")"
2210
+ cat > "$output_file" <<EOF_BRAIN_MANIFEST
2211
+ {
2212
+ "version": 1,
2213
+ "project": "${project_name}",
2214
+ "mode": "repo-contract-external-knowledge",
2215
+ "default_brain_path": "brain/<project>/*",
2216
+ "rules": [
2217
+ "repo-local contracts, hooks, scripts, checks, and evidence remain authoritative",
2218
+ "default brain stores long-lived explanations, runbooks, decisions, references, and patterns",
2219
+ "hook runtime may sync explicitly opted-in repo-to-brain entries only; it must not query gbrain, MCP, or unregistered default brain paths"
2220
+ ],
2221
+ "entries": []
2222
+ }
2223
+ EOF_BRAIN_MANIFEST
2224
+ }
2225
+
2226
+ pi_write_context_map() {
2227
+ local target_dir="$1"
2228
+ local mode="${2:-apply}"
2229
+ local output_file="$target_dir/.ai/context/context-map.json"
2230
+ local discoverable_entries
2231
+
2232
+ discoverable_entries="$(pi_context_map_discoverable_entries "$target_dir")"
2233
+
2234
+ if [[ "$mode" != "apply" ]]; then
2235
+ echo "[dry-run] write $output_file"
2236
+ return 0
2237
+ fi
2238
+
2239
+ mkdir -p "$(dirname "$output_file")"
2240
+ cat > "$output_file" <<EOF_CONTEXT
2241
+ {
2242
+ "version": 1,
2243
+ "profile": "$(pi_context_profile)",
2244
+ "functional_block_selector": {
2245
+ "script": "scripts/select-agent-context-blocks.sh",
2246
+ "config_file": ".ai/context/agent-context-blocks.txt",
2247
+ "env": "FORGE_CONTEXT_BLOCKS",
2248
+ "rule": "compatibility selector; capability registry is the source of truth"
2249
+ },
2250
+ "lsp_profiles": {
2251
+ "default": "$(pi_lsp_profile)",
2252
+ "selection": "functional-block-first"
2253
+ },
2254
+ "root_context_files": [
2255
+ "CLAUDE.md",
2256
+ "AGENTS.md",
2257
+ "docs/spec.md",
2258
+ "tasks/current.md",
2259
+ "tasks/todos.md",
2260
+ "tasks/lessons.md",
2261
+ ".ai/context/capabilities.json",
2262
+ ".ai/harness/policy.json"
2263
+ ],
2264
+ "discoverable_contexts": [
2265
+ ${discoverable_entries}
2266
+ ],
2267
+ "budgets": {
2268
+ "root_total_chars": 12000,
2269
+ "per_discoverable_file_chars": 1200
2270
+ }
2271
+ }
2272
+ EOF_CONTEXT
2273
+ }
2274
+
2275
+ pi_root_context_content() {
2276
+ cat <<'EOF_ROOT_CONTEXT'
2277
+ # Repo Agent Context
2278
+
2279
+ This is the root routing contract for Claude Code and Codex.
2280
+
2281
+ ## Root Workflow Contract
2282
+
2283
+ - Keep sibling `CLAUDE.md` and `AGENTS.md` files aligned. Claude Code consumes `CLAUDE.md`; Codex consumes `AGENTS.md`.
2284
+ - Treat `docs/spec.md` as stable product truth, `tasks/current.md` as a derived status snapshot, and `tasks/todos.md` as the deferred-goal ledger; current execution stays in the active plan's `## Task Breakdown`.
2285
+ - Treat `docs/researches/`, `tasks/lessons.md`, and `.ai/harness/policy.json` as durable workflow context.
2286
+ - Use `.ai/context/context-map.json` and `.ai/context/capabilities.json` to discover functional-block contracts.
2287
+ - Do not infer local `CLAUDE.md` or `AGENTS.md` files from broad physical layouts such as `apps/*`, `packages/*`, or `services/*`.
2288
+ - Put capability-specific ownership, entrypoints, and verification commands in explicitly selected functional-block contracts.
2289
+ - Keep root context concise; route deep implementation detail into plans, task notes, research, workstreams, or architecture docs.
2290
+ - Treat `_ref/` as ignored external reference material and `_ops/` as ignored local operations state.
2291
+ - Prefer repo-local workflow artifacts over tool-specific chat memory.
2292
+ EOF_ROOT_CONTEXT
2293
+ }
2294
+
2295
+ pi_install_root_context_files() {
2296
+ local target_dir="$1"
2297
+ local mode="${2:-apply}"
2298
+
2299
+ if [[ "$mode" != "apply" ]]; then
2300
+ echo "[dry-run] install root CLAUDE.md/AGENTS.md files in $target_dir"
2301
+ return 0
2302
+ fi
2303
+
2304
+ if [[ -f "$target_dir/AGENTS.md" && ! -f "$target_dir/CLAUDE.md" ]]; then
2305
+ cp "$target_dir/AGENTS.md" "$target_dir/CLAUDE.md"
2306
+ return 0
2307
+ fi
2308
+
2309
+ if [[ -f "$target_dir/CLAUDE.md" && ! -f "$target_dir/AGENTS.md" ]]; then
2310
+ cp "$target_dir/CLAUDE.md" "$target_dir/AGENTS.md"
2311
+ return 0
2312
+ fi
2313
+
2314
+ if [[ ! -f "$target_dir/CLAUDE.md" ]]; then
2315
+ pi_root_context_content > "$target_dir/CLAUDE.md"
2316
+ fi
2317
+
2318
+ if [[ ! -f "$target_dir/AGENTS.md" ]]; then
2319
+ pi_root_context_content > "$target_dir/AGENTS.md"
2320
+ fi
2321
+ }
2322
+
2323
+ pi_install_directory_context_files() {
2324
+ local target_dir="$1"
2325
+ local mode="${2:-apply}"
2326
+ local directory_agents_content
2327
+ local selected_dirs
2328
+ local rel_dir
2329
+ local module_dir
2330
+
2331
+ selected_dirs="$(pi_context_block_dirs "$target_dir")"
2332
+ if [[ -z "$selected_dirs" ]]; then
2333
+ return 0
2334
+ fi
2335
+
2336
+ if [[ "$mode" != "apply" ]]; then
2337
+ echo "[dry-run] install selected CLAUDE.md/AGENTS.md files in $target_dir"
2338
+ return 0
2339
+ fi
2340
+
2341
+ directory_agents_content=$(cat <<'EOF_DIRECTORY_AGENTS'
2342
+ # Functional Block Agent Context
2343
+
2344
+ Keep this file focused on the local contract for this primary functional block.
2345
+
2346
+ ## Local Context Contract
2347
+
2348
+ - Describe only the ownership, boundaries, stable entrypoints, and local verification commands for this functional block.
2349
+ - Keep sibling `CLAUDE.md` and `AGENTS.md` files aligned. Claude Code consumes `CLAUDE.md`; Codex consumes `AGENTS.md`.
2350
+ - Record the local LSP/tooling profile here when it differs from the repo default.
2351
+ - Route deep implementation detail into nearby docs instead of inflating root agent context files.
2352
+ - Treat `.ai/context/context-map.json` as the index of discoverable context files.
2353
+ - Do not keep pushing context files deeper by default; add lower-level files only for a separately owned functional block with its own commands and invariants.
2354
+ - Prefer repo-local workflow artifacts over tool-specific chat memory.
2355
+ EOF_DIRECTORY_AGENTS
2356
+ )
2357
+
2358
+ while IFS= read -r rel_dir; do
2359
+ [[ -n "$rel_dir" ]] || continue
2360
+ module_dir="$target_dir/$rel_dir"
2361
+ if [[ ! -d "$module_dir" ]]; then
2362
+ continue
2363
+ fi
2364
+ if [[ ! -w "$module_dir" ]]; then
2365
+ echo "[migrate] skipped context mirror in unwritable directory: $rel_dir" >&2
2366
+ continue
2367
+ fi
2368
+ if [[ -f "$module_dir/AGENTS.md" && ! -f "$module_dir/CLAUDE.md" ]]; then
2369
+ cp "$module_dir/AGENTS.md" "$module_dir/CLAUDE.md" || {
2370
+ echo "[migrate] skipped context mirror AGENTS.md -> CLAUDE.md in $rel_dir" >&2
2371
+ continue
2372
+ }
2373
+ elif [[ -f "$module_dir/CLAUDE.md" && ! -f "$module_dir/AGENTS.md" ]]; then
2374
+ cp "$module_dir/CLAUDE.md" "$module_dir/AGENTS.md" || {
2375
+ echo "[migrate] skipped context mirror CLAUDE.md -> AGENTS.md in $rel_dir" >&2
2376
+ continue
2377
+ }
2378
+ else
2379
+ if [[ ! -f "$module_dir/CLAUDE.md" ]]; then
2380
+ printf '%s\n' "$directory_agents_content" > "$module_dir/CLAUDE.md"
2381
+ fi
2382
+ if [[ ! -f "$module_dir/AGENTS.md" ]]; then
2383
+ printf '%s\n' "$directory_agents_content" > "$module_dir/AGENTS.md"
2384
+ fi
2385
+ fi
2386
+ done <<< "$selected_dirs"
2387
+ }
2388
+
2389
+ pi_ensure_harness_state_surface() {
2390
+ local target_dir="$1"
2391
+ local mode="${2:-apply}"
2392
+
2393
+ if [[ "$mode" != "apply" ]]; then
2394
+ echo "[dry-run] ensure harness policy/context/events/runs/worktrees/local-jobs/controller/triage/planning in $target_dir"
2395
+ return 0
2396
+ fi
2397
+
2398
+ mkdir -p \
2399
+ "$target_dir/tasks/notes" \
2400
+ "$target_dir/tasks/workstreams" \
2401
+ "$target_dir/.ai/context" \
2402
+ "$target_dir/.ai/harness/checks" \
2403
+ "$target_dir/.ai/harness/handoff" \
2404
+ "$target_dir/.ai/harness/scripts" \
2405
+ "$target_dir/.ai/harness/failures" \
2406
+ "$target_dir/.ai/harness/security" \
2407
+ "$target_dir/.ai/harness/planning" \
2408
+ "$target_dir/.ai/harness/architecture" \
2409
+ "$target_dir/.ai/harness/worktrees" \
2410
+ "$target_dir/.ai/harness/controller" \
2411
+ "$target_dir/.ai/harness/local-jobs" \
2412
+ "$target_dir/.ai/harness/triage" \
2413
+ "$target_dir/docs/researches" \
2414
+ "$target_dir/docs/architecture/domains" \
2415
+ "$target_dir/docs/architecture/modules" \
2416
+ "$target_dir/docs/architecture/requests" \
2417
+ "$target_dir/docs/architecture/snapshots" \
2418
+ "$target_dir/docs/architecture/diagrams" \
2419
+ "$target_dir/.ai/harness/runs"
2420
+
2421
+ [[ -f "$target_dir/.ai/harness/checks/latest.json" ]] || printf "{}\n" > "$target_dir/.ai/harness/checks/latest.json"
2422
+ [[ -f "$target_dir/.ai/harness/handoff/current.md" ]] || printf "# Harness Handoff\n\n> **Reason**: bootstrap\n" > "$target_dir/.ai/harness/handoff/current.md"
2423
+ [[ -f "$target_dir/.ai/harness/handoff/resume.md" ]] || printf "# Codex Resume Packet\n\n> **Reason**: bootstrap\n" > "$target_dir/.ai/harness/handoff/resume.md"
2424
+ [[ -f "$target_dir/.ai/context/capability-source-map.json" ]] || printf '{\n "version": 1,\n "capabilities": {}\n}\n' > "$target_dir/.ai/context/capability-source-map.json"
2425
+ [[ -f "$target_dir/.ai/harness/events.jsonl" ]] || : > "$target_dir/.ai/harness/events.jsonl"
2426
+ [[ -f "$target_dir/.ai/harness/architecture/events.jsonl" ]] || : > "$target_dir/.ai/harness/architecture/events.jsonl"
2427
+ [[ -f "$target_dir/.ai/harness/architecture/.gitkeep" ]] || : > "$target_dir/.ai/harness/architecture/.gitkeep"
2428
+ [[ -f "$target_dir/.ai/harness/failures/latest.jsonl" ]] || : > "$target_dir/.ai/harness/failures/latest.jsonl"
2429
+ [[ -f "$target_dir/.ai/harness/security/.gitkeep" ]] || : > "$target_dir/.ai/harness/security/.gitkeep"
2430
+ [[ -f "$target_dir/.ai/harness/scripts/.gitkeep" ]] || : > "$target_dir/.ai/harness/scripts/.gitkeep"
2431
+ [[ -f "$target_dir/.ai/harness/planning/.gitkeep" ]] || : > "$target_dir/.ai/harness/planning/.gitkeep"
2432
+ [[ -f "$target_dir/.ai/harness/worktrees/.gitkeep" ]] || : > "$target_dir/.ai/harness/worktrees/.gitkeep"
2433
+ [[ -f "$target_dir/.ai/harness/runs/.gitkeep" ]] || : > "$target_dir/.ai/harness/runs/.gitkeep"
2434
+ [[ -f "$target_dir/.ai/harness/triage/.gitkeep" ]] || : > "$target_dir/.ai/harness/triage/.gitkeep"
2435
+ [[ -f "$target_dir/tasks/workstreams/.gitkeep" ]] || : > "$target_dir/tasks/workstreams/.gitkeep"
2436
+ if [[ ! -f "$target_dir/docs/researches/README.md" ]]; then
2437
+ cat > "$target_dir/docs/researches/README.md" <<'RESEARCH_README_EOF'
2438
+ # Research Reports
2439
+
2440
+ Durable research reports live in this directory as topic-scoped Markdown files.
2441
+
2442
+ Use `YYYYMMDD-topic.md` names when chronology matters, or `<topic>.md` for
2443
+ stable subject reports. Keep task-local implementation decisions in
2444
+ `tasks/notes/`, and keep repeated correction-derived rules in `tasks/lessons.md`.
2445
+ RESEARCH_README_EOF
2446
+ fi
2447
+ if [[ ! -f "$target_dir/tasks/current.md" ]]; then
2448
+ cat > "$target_dir/tasks/current.md" <<'CURRENT_STATUS_EOF'
2449
+ # Current Status Snapshot
2450
+
2451
+ <!-- generated-by: forge refresh-current-status v1 -->
2452
+ <!-- updated_at: bootstrap -->
2453
+ <!-- stale_after: 24h -->
2454
+
2455
+ > **Status**: Idle
2456
+ > **Updated At**: bootstrap
2457
+ > **Source Branch**: main
2458
+ > **Source Commit**: bootstrap
2459
+ > **Target Branch**: main
2460
+ > **Stale After**: 24h
2461
+ > **Reason**: bootstrap
2462
+ > **Derived From**: active-plan, active-sprint, workstreams, handoff, checks, git status
2463
+
2464
+ This file is a tracked mainline snapshot derived from repo artifacts. It is not a live lock, not a kanban board, and not an implementation gate. If it is stale, read the source artifacts below.
2465
+ CURRENT_STATUS_EOF
2466
+ fi
2467
+ [[ -f "$target_dir/docs/architecture/domains/.gitkeep" ]] || : > "$target_dir/docs/architecture/domains/.gitkeep"
2468
+ [[ -f "$target_dir/docs/architecture/modules/.gitkeep" ]] || : > "$target_dir/docs/architecture/modules/.gitkeep"
2469
+ [[ -f "$target_dir/docs/architecture/requests/.gitkeep" ]] || : > "$target_dir/docs/architecture/requests/.gitkeep"
2470
+ [[ -f "$target_dir/docs/architecture/snapshots/.gitkeep" ]] || : > "$target_dir/docs/architecture/snapshots/.gitkeep"
2471
+ [[ -f "$target_dir/docs/architecture/diagrams/.gitkeep" ]] || : > "$target_dir/docs/architecture/diagrams/.gitkeep"
2472
+ if [[ ! -f "$target_dir/docs/architecture/index.md" ]]; then
2473
+ cat > "$target_dir/docs/architecture/index.md" <<'ARCHITECTURE_INDEX_EOF'
2474
+ # Architecture Index
2475
+
2476
+ > Umbrella architecture ledger for current boundaries, drift requests, snapshots, and diagrams.
2477
+
2478
+ ## Current Snapshot
2479
+
2480
+ - Latest snapshot: (none yet)
2481
+ - Semantic diagram source: (none yet)
2482
+ - Latest human diagram: (none yet)
2483
+
2484
+ ## Architecture Drift Flow
2485
+
2486
+ - `.ai/harness/scripts/architecture-queue.sh` records architecture-sensitive edits as requests.
2487
+ - `.ai/harness/scripts/archive-architecture-request.sh` archives handled requests after an agent records the resolution status and linked artifacts.
2488
+ - `.ai/harness/scripts/context-contract-sync.sh` keeps only the controlled architecture block in functional-block `AGENTS.md` and `CLAUDE.md` files aligned.
2489
+ - `.ai/harness/scripts/workstream-sync.sh` keeps durable multi-session progress under `tasks/workstreams/<domain>/<capability>/` and projects only pointers into local contracts.
2490
+ - Semantic architecture diagrams live as Mermaid fenced blocks in the relevant module or snapshot Markdown.
2491
+ - Human-readable architecture diagrams are optional `mermaid` HTML files in `docs/architecture/diagrams/` and should link back to the Markdown semantic source.
2492
+
2493
+ ## Pending Requests
2494
+
2495
+ <!-- BEGIN ARCHITECTURE PENDING REQUESTS -->
2496
+ - (none)
2497
+ <!-- END ARCHITECTURE PENDING REQUESTS -->
2498
+
2499
+ ARCHITECTURE_INDEX_EOF
2500
+ fi
2501
+
2502
+ pi_write_capability_registry "$target_dir" "$mode"
2503
+ pi_write_harness_policy "$target_dir" "$mode"
2504
+ pi_write_brain_manifest "$target_dir" "$mode"
2505
+ pi_write_context_map "$target_dir" "$mode"
2506
+ pi_install_root_context_files "$target_dir" "$mode"
2507
+ pi_install_directory_context_files "$target_dir" "$mode"
2508
+ }
2509
+
2510
+ pi_resolve_js_runtime() {
2511
+ if command -v node >/dev/null 2>&1; then
2512
+ printf 'node'
2513
+ return 0
2514
+ fi
2515
+
2516
+ if command -v bun >/dev/null 2>&1; then
2517
+ printf 'bun'
2518
+ return 0
2519
+ fi
2520
+
2521
+ if [[ -x "${HOME}/.bun/bin/bun" ]]; then
2522
+ printf '%s' "${HOME}/.bun/bin/bun"
2523
+ return 0
2524
+ fi
2525
+
2526
+ return 1
2527
+ }
2528
+
2529
+ pi_merge_json_defaults() {
2530
+ local defaults_file="$1"
2531
+ local current_file="$2"
2532
+ local output_file="$3"
2533
+ local js_runtime
2534
+
2535
+ js_runtime="$(pi_resolve_js_runtime || true)"
2536
+ if [[ -n "$js_runtime" ]]; then
2537
+ "$js_runtime" -e '
2538
+ const fs = require("fs");
2539
+ const [defaultsPath, currentPath, outputPath] = process.argv.slice(1);
2540
+
2541
+ function isPlainObject(value) {
2542
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2543
+ }
2544
+
2545
+ const unionArrayPaths = new Set(["documentation.reference_configs"]);
2546
+
2547
+ function mergeDefaults(defaultsValue, currentValue, path = []) {
2548
+ if (Array.isArray(defaultsValue)) {
2549
+ const keyPath = path.join(".");
2550
+ if (Array.isArray(currentValue) && unionArrayPaths.has(keyPath)) {
2551
+ const result = [...currentValue];
2552
+ for (const item of defaultsValue) {
2553
+ if (!result.includes(item)) result.push(item);
2554
+ }
2555
+ return result;
2556
+ }
2557
+ return Array.isArray(currentValue) ? currentValue : defaultsValue;
2558
+ }
2559
+
2560
+ if (isPlainObject(defaultsValue)) {
2561
+ const result = { ...defaultsValue };
2562
+ if (isPlainObject(currentValue)) {
2563
+ for (const [key, value] of Object.entries(currentValue)) {
2564
+ result[key] = Object.prototype.hasOwnProperty.call(defaultsValue, key)
2565
+ ? mergeDefaults(defaultsValue[key], value, [...path, key])
2566
+ : value;
2567
+ }
2568
+ }
2569
+ return result;
2570
+ }
2571
+
2572
+ return currentValue === undefined ? defaultsValue : currentValue;
2573
+ }
2574
+
2575
+ const defaultsJson = JSON.parse(fs.readFileSync(defaultsPath, "utf8"));
2576
+ let currentJson = {};
2577
+ try {
2578
+ currentJson = JSON.parse(fs.readFileSync(currentPath, "utf8"));
2579
+ } catch (_error) {
2580
+ currentJson = {};
2581
+ }
2582
+
2583
+ const merged = mergeDefaults(defaultsJson, currentJson);
2584
+ fs.writeFileSync(outputPath, JSON.stringify(merged, null, 2) + "\n");
2585
+ ' "$defaults_file" "$current_file" "$output_file"
2586
+ return $?
2587
+ fi
2588
+
2589
+ if command -v python3 >/dev/null 2>&1; then
2590
+ python3 - "$defaults_file" "$current_file" "$output_file" <<'PY_EOF'
2591
+ import json
2592
+ import sys
2593
+
2594
+ defaults_path, current_path, output_path = sys.argv[1:]
2595
+
2596
+ UNION_ARRAY_PATHS = {("documentation", "reference_configs")}
2597
+
2598
+ def merge_defaults(defaults_value, current_value, path=()):
2599
+ if isinstance(defaults_value, list):
2600
+ if isinstance(current_value, list) and path in UNION_ARRAY_PATHS:
2601
+ result = list(current_value)
2602
+ for item in defaults_value:
2603
+ if item not in result:
2604
+ result.append(item)
2605
+ return result
2606
+ return current_value if isinstance(current_value, list) else defaults_value
2607
+ if isinstance(defaults_value, dict):
2608
+ result = dict(defaults_value)
2609
+ if isinstance(current_value, dict):
2610
+ for key, value in current_value.items():
2611
+ result[key] = merge_defaults(defaults_value[key], value, path + (key,)) if key in defaults_value else value
2612
+ return result
2613
+ return defaults_value if current_value is None else current_value
2614
+
2615
+ with open(defaults_path, "r", encoding="utf-8") as handle:
2616
+ defaults_json = json.load(handle)
2617
+
2618
+ try:
2619
+ with open(current_path, "r", encoding="utf-8") as handle:
2620
+ current_json = json.load(handle)
2621
+ except Exception:
2622
+ current_json = {}
2623
+
2624
+ merged = merge_defaults(defaults_json, current_json)
2625
+ with open(output_path, "w", encoding="utf-8") as handle:
2626
+ json.dump(merged, handle, indent=2)
2627
+ handle.write("\n")
2628
+ PY_EOF
2629
+ return $?
2630
+ fi
2631
+
2632
+ return 1
2633
+ }
2634
+
2635
+ pi_ensure_task_sync() {
2636
+ local target_dir="$1"
2637
+ local create_if_missing="${2:-0}"
2638
+ local mode="${3:-apply}"
2639
+ local package_file="$target_dir/package.json"
2640
+ local js_runtime
2641
+ local project_name
2642
+
2643
+ if [[ ! -f "$package_file" && "$create_if_missing" != "1" ]]; then
2644
+ if [[ "$mode" != "apply" ]]; then
2645
+ echo "[dry-run] package.json missing; skip task workflow script injection"
2646
+ fi
2647
+ return 0
2648
+ fi
2649
+
2650
+ if [[ "$mode" != "apply" ]]; then
2651
+ echo "[dry-run] inject task workflow scripts into $package_file"
2652
+ return 0
2653
+ fi
2654
+
2655
+ if [[ ! -f "$package_file" ]]; then
2656
+ project_name="$(basename "$target_dir" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9-' '-')"
2657
+ project_name="${project_name:-project}"
2658
+ cat > "$package_file" <<EOF_PACKAGE
2659
+ {
2660
+ "name": "$project_name",
2661
+ "private": true,
2662
+ "scripts": {
2663
+ "check:brain-manifest": "forge run check-brain-manifest",
2664
+ "check:context-files": "forge run check-context-files",
2665
+ "check:deploy-sql": "forge run check-deploy-sql-order",
2666
+ "check:architecture-sync": "forge run check-architecture-sync",
2667
+ "check:task": "bash scripts/check-task-workflow.sh --strict",
2668
+ "check:task-sync": "forge run check-task-sync",
2669
+ "check:task-workflow": "forge run check-task-workflow --strict",
2670
+ "sync:brain-docs": "forge run sync-brain-docs --all"
2671
+ }
2672
+ }
2673
+ EOF_PACKAGE
2674
+ return 0
2675
+ fi
2676
+
2677
+ js_runtime="$(pi_resolve_js_runtime || true)"
2678
+ if [[ -z "$js_runtime" ]]; then
2679
+ echo "[warn] no JavaScript runtime found; unable to inject task workflow scripts into $package_file" >&2
2680
+ return 0
2681
+ fi
2682
+
2683
+ "$js_runtime" -e '
2684
+ const fs = require("fs");
2685
+ const file = process.argv[1];
2686
+ const pkg = JSON.parse(fs.readFileSync(file, "utf8"));
2687
+ pkg.private ??= true;
2688
+ pkg.scripts ??= {};
2689
+ pkg.scripts["check:brain-manifest"] = "forge run check-brain-manifest";
2690
+ pkg.scripts["check:context-files"] = "forge run check-context-files";
2691
+ pkg.scripts["check:deploy-sql"] = "forge run check-deploy-sql-order";
2692
+ pkg.scripts["check:architecture-sync"] = "forge run check-architecture-sync";
2693
+ pkg.scripts["check:task"] = "bash scripts/check-task-workflow.sh --strict";
2694
+ pkg.scripts["check:task-sync"] = "forge run check-task-sync";
2695
+ pkg.scripts["check:task-workflow"] = "forge run check-task-workflow --strict";
2696
+ pkg.scripts["sync:brain-docs"] = "forge run sync-brain-docs --all";
2697
+ fs.writeFileSync(file, JSON.stringify(pkg, null, 2) + "\n");
2698
+ ' "$package_file"
2699
+ }
2700
+
2701
+ pi_factor_factory_gitignore_entries() {
2702
+ printf '%s\n' ".claude/.factor-cache/"
2703
+ }
2704
+
2705
+ pi_should_enable_factor_factory() {
2706
+ local plan_type="${1:-$(pi_plan_type)}"
2707
+ local explicit
2708
+ explicit="$(pi_env_value "FORGE_FACTOR_FACTORY" "0")"
2709
+
2710
+ case "$explicit" in
2711
+ 1|true|TRUE|yes|YES) return 0 ;;
2712
+ esac
2713
+
2714
+ [[ "$plan_type" == "G" ]]
2715
+ }
2716
+
2717
+ pi_install_factor_factory() {
2718
+ local target_dir="$1"
2719
+ local factor_assets_dir="$2"
2720
+ local scripts_source_dir="$3"
2721
+ local mode="${4:-apply}"
2722
+ local scripts_dir="$target_dir/.ai/harness/scripts"
2723
+ local factors_dir="$target_dir/tasks/factors"
2724
+ local cache_dir="$target_dir/.claude/.factor-cache/candidates"
2725
+ local registry_template="$factor_assets_dir/factor-registry.template.json"
2726
+ local hypothesis_template="$factor_assets_dir/factor-hypothesis.template.md"
2727
+ local report_template="$factor_assets_dir/factor-backtest-report.template.md"
2728
+
2729
+ if [[ "$mode" != "apply" ]]; then
2730
+ echo "[dry-run] install factor factory assets into $target_dir"
2731
+ return 0
2732
+ fi
2733
+
2734
+ mkdir -p "$factors_dir/promoted" "$cache_dir" "$scripts_dir"
2735
+
2736
+ if [[ -f "$registry_template" ]]; then
2737
+ cp "$registry_template" "$factors_dir/registry.json"
2738
+ fi
2739
+
2740
+ if [[ -f "$hypothesis_template" ]]; then
2741
+ mkdir -p "$target_dir/.claude/factor-factory"
2742
+ cp "$hypothesis_template" "$target_dir/.claude/factor-factory/hypothesis.template.md"
2743
+ fi
2744
+
2745
+ if [[ -f "$report_template" ]]; then
2746
+ mkdir -p "$target_dir/.claude/factor-factory"
2747
+ cp "$report_template" "$target_dir/.claude/factor-factory/backtest-report.template.md"
2748
+ fi
2749
+
2750
+ local factor_script
2751
+ for factor_script in factor-lab-new.sh factor-lab-promote.sh factor-lab-reject.sh factor-lab-check.sh; do
2752
+ if [[ -f "$scripts_source_dir/$factor_script" ]]; then
2753
+ cp "$scripts_source_dir/$factor_script" "$scripts_dir/$factor_script"
2754
+ pi_normalize_installed_helper "$scripts_dir/$factor_script"
2755
+ fi
2756
+ done
2757
+
2758
+ pi_ensure_executable_if_apply "$mode" "$scripts_dir"/factor-lab-*.sh
2759
+ }