@mmerterden/multi-agent-pipeline 20.33.0 → 20.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (390) hide show
  1. package/CHANGELOG.md +98 -1
  2. package/README.md +3 -1
  3. package/README.tr.md +2 -1
  4. package/docs/adr/0018-cross-repo-links-not-a-global-graph.md +43 -0
  5. package/docs/adr/README.md +2 -1
  6. package/docs/facts.json +5 -4
  7. package/docs/features.md +1 -1
  8. package/install/_dev-only-files.mjs +1 -0
  9. package/install/catalog-history.json +1 -1
  10. package/install/claude.mjs +24 -2
  11. package/install/templates/claude-hooks.json +34 -1
  12. package/manifest.json +393 -339
  13. package/package.json +3 -1
  14. package/pipeline/agents/bulk-reader.md +3 -0
  15. package/pipeline/agents/code-reviewer.md +9 -0
  16. package/pipeline/agents/explorer.md +4 -0
  17. package/pipeline/agents/plan-critic.md +4 -2
  18. package/pipeline/commands/multi-agent/SKILL.md +17 -136
  19. package/pipeline/commands/multi-agent/channels/SKILL.md +16 -298
  20. package/pipeline/commands/multi-agent/graph/SKILL.md +5 -2
  21. package/pipeline/commands/multi-agent/language/SKILL.md +3 -3
  22. package/pipeline/commands/multi-agent/office-on/SKILL.md +7 -3
  23. package/pipeline/commands/multi-agent/office-status/SKILL.md +3 -2
  24. package/pipeline/commands/multi-agent/resume/SKILL.md +8 -22
  25. package/pipeline/commands/multi-agent/review/SKILL.md +7 -131
  26. package/pipeline/commands/multi-agent/setup/SKILL.md +19 -224
  27. package/pipeline/contract/CHANGELOG.md +9 -0
  28. package/pipeline/contract/README.md +6 -2
  29. package/pipeline/contract/fixtures/error-invalid-request.json +1 -1
  30. package/pipeline/contract/fixtures/error-unauthorized.json +1 -1
  31. package/pipeline/contract/fixtures/error-unsigned.json +1 -1
  32. package/pipeline/contract/manifest.json +14 -1
  33. package/pipeline/contract/types/index.d.ts +24 -2
  34. package/pipeline/lib/json-file-lock.mjs +61 -15
  35. package/pipeline/lib/office-remote.mjs +228 -0
  36. package/pipeline/lib/qr-code.mjs +360 -0
  37. package/pipeline/lib/repo-hygiene.sh +1 -0
  38. package/pipeline/lib/run-completion.mjs +17 -0
  39. package/pipeline/multi-agent-refs/channels/generator.md +146 -0
  40. package/pipeline/multi-agent-refs/channels/issue-comment.md +1 -1
  41. package/pipeline/multi-agent-refs/channels/menu.md +55 -0
  42. package/pipeline/multi-agent-refs/channels/multi-repo.md +6 -0
  43. package/pipeline/multi-agent-refs/channels/preview.md +25 -0
  44. package/pipeline/multi-agent-refs/channels/reference.md +98 -0
  45. package/pipeline/multi-agent-refs/features/autopilot-circuit-breaker.md +1 -1
  46. package/pipeline/multi-agent-refs/features/code-graph.md +27 -0
  47. package/pipeline/multi-agent-refs/features/office-remote-protocol.md +166 -0
  48. package/pipeline/multi-agent-refs/features/office-threat-model.md +2 -2
  49. package/pipeline/multi-agent-refs/features/plan-critic.md +5 -2
  50. package/pipeline/multi-agent-refs/features/review-delta.md +4 -1
  51. package/pipeline/multi-agent-refs/features/scope-check.md +25 -1
  52. package/pipeline/multi-agent-refs/features/verify-by-test.md +10 -0
  53. package/pipeline/multi-agent-refs/keychain.md +7 -0
  54. package/pipeline/multi-agent-refs/knowledge.md +9 -0
  55. package/pipeline/multi-agent-refs/orchestrator/dispatcher.md +163 -0
  56. package/pipeline/multi-agent-refs/phases/phase-0-init.md +6 -2
  57. package/pipeline/multi-agent-refs/phases/phase-1-plan.md +8 -10
  58. package/pipeline/multi-agent-refs/phases/phase-2-dev.md +18 -20
  59. package/pipeline/multi-agent-refs/phases/phase-3-review.md +20 -14
  60. package/pipeline/multi-agent-refs/phases/phase-4-commit.md +8 -7
  61. package/pipeline/multi-agent-refs/phases/phase-5-report.md +6 -3
  62. package/pipeline/multi-agent-refs/picker-contract.md +1 -1
  63. package/pipeline/multi-agent-refs/resume/details.md +35 -0
  64. package/pipeline/multi-agent-refs/review/inputs.md +87 -0
  65. package/pipeline/multi-agent-refs/review/module-guides.md +25 -0
  66. package/pipeline/multi-agent-refs/review/valven.md +42 -0
  67. package/pipeline/multi-agent-refs/rules.md +3 -2
  68. package/pipeline/multi-agent-refs/setup/accounts.md +27 -0
  69. package/pipeline/multi-agent-refs/setup/app-store-connect.md +5 -0
  70. package/pipeline/multi-agent-refs/setup/firebase.md +5 -0
  71. package/pipeline/multi-agent-refs/setup/google-play.md +4 -0
  72. package/pipeline/multi-agent-refs/setup/hooks-and-plugins.md +21 -0
  73. package/pipeline/multi-agent-refs/setup/language.md +46 -0
  74. package/pipeline/multi-agent-refs/setup/multi-repo-group.md +51 -0
  75. package/pipeline/multi-agent-refs/setup/summaries.md +63 -0
  76. package/pipeline/multi-agent-refs/setup/token-save-flow.md +51 -0
  77. package/pipeline/multi-agent-refs/tracker-contract.md +1 -1
  78. package/pipeline/office/NOTICE.md +4 -1
  79. package/pipeline/office/assets/char_12.png +0 -0
  80. package/pipeline/office/assets/char_13.png +0 -0
  81. package/pipeline/office/assets/char_14.png +0 -0
  82. package/pipeline/office/assets/char_15.png +0 -0
  83. package/pipeline/office/assets/char_16.png +0 -0
  84. package/pipeline/office/assets/char_17.png +0 -0
  85. package/pipeline/office/assets/char_18.png +0 -0
  86. package/pipeline/office/assets/char_19.png +0 -0
  87. package/pipeline/office/assets/char_20.png +0 -0
  88. package/pipeline/office/assets/char_21.png +0 -0
  89. package/pipeline/office/assets/char_22.png +0 -0
  90. package/pipeline/office/assets/char_23.png +0 -0
  91. package/pipeline/office/assets/char_24.png +0 -0
  92. package/pipeline/office/assets/char_25.png +0 -0
  93. package/pipeline/office/assets/char_26.png +0 -0
  94. package/pipeline/office/assets/char_27.png +0 -0
  95. package/pipeline/office/assets/char_28.png +0 -0
  96. package/pipeline/office/assets/char_29.png +0 -0
  97. package/pipeline/office/assets/char_30.png +0 -0
  98. package/pipeline/office/index.html +304 -55
  99. package/pipeline/office/toolkit.json +1 -1
  100. package/pipeline/rules/response-shape.md +6 -7
  101. package/pipeline/schemas/agent-state.schema.json +36 -0
  102. package/pipeline/schemas/phases.json +4 -4
  103. package/pipeline/schemas/plan-critique.schema.json +9 -2
  104. package/pipeline/schemas/planning-output.schema.json +43 -2
  105. package/pipeline/schemas/pr-reach.schema.json +55 -0
  106. package/pipeline/schemas/prefs.schema.json +37 -8
  107. package/pipeline/schemas/reviewer-output.schema.json +20 -2
  108. package/pipeline/schemas/token-budget.json +4 -4
  109. package/pipeline/schemas/triage-output.schema.json +32 -3
  110. package/pipeline/schemas/unattended-policy.json +2 -1
  111. package/pipeline/scripts/_graph-analysis.mjs +270 -0
  112. package/pipeline/scripts/_guard_rules.py +449 -1
  113. package/pipeline/scripts/_memory-policy.mjs +165 -0
  114. package/pipeline/scripts/_secret-scan.mjs +105 -0
  115. package/pipeline/scripts/_test-gaming.mjs +36 -0
  116. package/pipeline/scripts/_unified-diff.mjs +2 -2
  117. package/pipeline/scripts/agent-guard.py +79 -19
  118. package/pipeline/scripts/anonymize-findings.mjs +99 -0
  119. package/pipeline/scripts/answer-check.mjs +113 -0
  120. package/pipeline/scripts/answer-check.sh +20 -0
  121. package/pipeline/scripts/autopilot-publish.mjs +9 -2
  122. package/pipeline/scripts/capture-flush.sh +12 -2
  123. package/pipeline/scripts/check-read-size.sh +9 -0
  124. package/pipeline/scripts/code-graph-rules/android.json +8 -3
  125. package/pipeline/scripts/contract-server.mjs +71 -16
  126. package/pipeline/scripts/debt-ledger.mjs +323 -0
  127. package/pipeline/scripts/file-context.mjs +261 -0
  128. package/pipeline/scripts/file-context.sh +20 -0
  129. package/pipeline/scripts/gate-ledger.mjs +144 -21
  130. package/pipeline/scripts/graph-links.mjs +230 -0
  131. package/pipeline/scripts/graph-query.mjs +133 -1
  132. package/pipeline/scripts/graph-report.mjs +65 -0
  133. package/pipeline/scripts/learn-from-transcripts.mjs +12 -48
  134. package/pipeline/scripts/learnings-ledger.mjs +143 -24
  135. package/pipeline/scripts/office-build.mjs +276 -5
  136. package/pipeline/scripts/office-control.mjs +70 -10
  137. package/pipeline/scripts/office-pair.mjs +407 -0
  138. package/pipeline/scripts/office-remote-client.mjs +463 -0
  139. package/pipeline/scripts/phase-tracker.sh +8 -0
  140. package/pipeline/scripts/phase0-exit-gate.mjs +40 -37
  141. package/pipeline/scripts/phone-devices.mjs +9 -1
  142. package/pipeline/scripts/plan-critique-gate.mjs +11 -2
  143. package/pipeline/scripts/pre-commit-check.sh +28 -2
  144. package/pipeline/scripts/pre-push-check.sh +6 -12
  145. package/pipeline/scripts/rework-base.mjs +87 -0
  146. package/pipeline/scripts/rework-rulings.mjs +106 -0
  147. package/pipeline/scripts/run-commit-check.mjs +104 -0
  148. package/pipeline/scripts/run-scope-guard.mjs +58 -3
  149. package/pipeline/scripts/run-scope-guard.sh +13 -1
  150. package/pipeline/scripts/scope-check-gate.mjs +213 -2
  151. package/pipeline/scripts/task-mirror.mjs +106 -15
  152. package/pipeline/scripts/task-mirror.sh +3 -2
  153. package/pipeline/scripts/test-stability-gate.mjs +112 -0
  154. package/pipeline/scripts/triage-memory.mjs +64 -37
  155. package/pipeline/scripts/update-check.sh +7 -1
  156. package/pipeline/scripts/update-issue-progress.sh +73 -8
  157. package/pipeline/scripts/validate-planning.mjs +172 -4
  158. package/pipeline/scripts/validate-reviewer.mjs +20 -0
  159. package/pipeline/scripts/validate-triage.mjs +149 -4
  160. package/pipeline/scripts/work-items.mjs +119 -1
  161. package/pipeline/scripts/worktree-prepare-all.mjs +200 -0
  162. package/pipeline/scripts/worktree-prepare.sh +40 -4
  163. package/pipeline/scripts/write-state.mjs +67 -24
  164. package/pipeline/skills/.skill-manifest.json +9 -9
  165. package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +5 -5
  166. package/pipeline/skills/shared/core/google-play-compliance/references/rules.yml +1 -1
  167. package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +1 -1
  168. package/pipeline/skills/shared/core/multi-agent-graph/SKILL.md +5 -2
  169. package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +4 -4
  170. package/pipeline/skills/shared/core/multi-agent-office-status/SKILL.md +2 -2
  171. package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +2 -0
  172. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +4 -4
  173. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +14 -0
  174. package/pipeline/skills/shared/external/android-architecture/references/patterns.md +6 -0
  175. package/pipeline/skills/shared/external/android-build-quality-gates/references/patterns.md +10 -0
  176. package/pipeline/skills/shared/external/android-datastore/references/patterns.md +11 -0
  177. package/pipeline/skills/shared/external/android-design-tokens-codegen/references/patterns.md +8 -0
  178. package/pipeline/skills/shared/external/android-jetpack-compose-expert/references/patterns.md +6 -0
  179. package/pipeline/skills/shared/external/android-mvi-viewmodel/references/patterns.md +10 -0
  180. package/pipeline/skills/shared/external/android-performance/references/patterns.md +13 -0
  181. package/pipeline/skills/shared/external/android-security/references/patterns.md +16 -0
  182. package/pipeline/skills/shared/external/api-patterns/references/contract-details.md +9 -0
  183. package/pipeline/skills/shared/external/api-security-best-practices/references/abuse-controls.md +12 -0
  184. package/pipeline/skills/shared/external/api-security-best-practices/references/identity-and-access.md +13 -0
  185. package/pipeline/skills/shared/external/api-security-best-practices/references/request-handling.md +12 -0
  186. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +9 -0
  187. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +8 -0
  188. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +10 -0
  189. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +21 -0
  190. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +9 -0
  191. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +7 -0
  192. package/pipeline/skills/shared/external/app-store-review/SKILL.md +2 -2
  193. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +10 -0
  194. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +10 -1
  195. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +22 -0
  196. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +17 -0
  197. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +22 -0
  198. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +17 -0
  199. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +9 -0
  200. package/pipeline/skills/shared/external/authentication/references/passkeys.md +11 -0
  201. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +13 -0
  202. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +9 -0
  203. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +10 -0
  204. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +15 -0
  205. package/pipeline/skills/shared/external/compose-components/references/patterns.md +7 -0
  206. package/pipeline/skills/shared/external/compose-navigation/references/patterns.md +7 -0
  207. package/pipeline/skills/shared/external/compose-testing/references/patterns.md +15 -0
  208. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +9 -0
  209. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +11 -0
  210. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +10 -0
  211. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +13 -0
  212. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +20 -0
  213. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +16 -0
  214. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +16 -0
  215. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +14 -0
  216. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +13 -0
  217. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +10 -0
  218. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +10 -0
  219. package/pipeline/skills/shared/external/fastapi-pro/references/app-structure.md +10 -0
  220. package/pipeline/skills/shared/external/gradle-kotlin-dsl/references/patterns.md +17 -0
  221. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +12 -0
  222. package/pipeline/skills/shared/external/hig-app-icons/references/icon-workflow.md +10 -0
  223. package/pipeline/skills/shared/external/hig-components-content/references/content-views.md +10 -0
  224. package/pipeline/skills/shared/external/hig-components-layout/references/bars-and-tabs.md +11 -0
  225. package/pipeline/skills/shared/external/hig-foundations/references/foundations-detail.md +13 -0
  226. package/pipeline/skills/shared/external/hig-foundations/references/type-color-spacing.md +13 -0
  227. package/pipeline/skills/shared/external/hig-patterns/references/onboarding-and-states.md +11 -0
  228. package/pipeline/skills/shared/external/hig-platforms/references/ipad-layout.md +12 -0
  229. package/pipeline/skills/shared/external/hig-technologies/references/technologies.md +16 -0
  230. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +9 -0
  231. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +18 -0
  232. package/pipeline/skills/shared/external/ios-accessibility/references/large-content-and-appearance.md +9 -0
  233. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +9 -0
  234. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +7 -0
  235. package/pipeline/skills/shared/external/ios-coding-standard/references/STANDARD.md +13 -0
  236. package/pipeline/skills/shared/external/ios-design-review/references/appearance-matrix.md +9 -0
  237. package/pipeline/skills/shared/external/ios-design-review/references/checklist.md +15 -0
  238. package/pipeline/skills/shared/external/ios-haptics/references/core-haptics.md +11 -0
  239. package/pipeline/skills/shared/external/ios-iphone-duo/references/api-map.md +11 -0
  240. package/pipeline/skills/shared/external/ios-iphone-duo/references/fixed-assumptions.md +15 -0
  241. package/pipeline/skills/shared/external/ios-iphone-duo/references/poses-and-panes.md +11 -0
  242. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +18 -0
  243. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +19 -0
  244. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +15 -0
  245. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +7 -0
  246. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +8 -0
  247. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +12 -0
  248. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +17 -0
  249. package/pipeline/skills/shared/external/ios-security/references/app-review-guidelines.md +8 -0
  250. package/pipeline/skills/shared/external/ios-security/references/cryptokit-advanced.md +14 -0
  251. package/pipeline/skills/shared/external/ios-security/references/file-storage-patterns.md +8 -0
  252. package/pipeline/skills/shared/external/ios-security/references/privacy-manifest.md +9 -0
  253. package/pipeline/skills/shared/external/ios-sf-symbols/references/effects-and-custom-symbols.md +9 -0
  254. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +13 -0
  255. package/pipeline/skills/shared/external/kotlin-coroutines-expert/references/patterns.md +8 -0
  256. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +21 -0
  257. package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +9 -0
  258. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +12 -0
  259. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +16 -0
  260. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +21 -0
  261. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +10 -0
  262. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +9 -0
  263. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +12 -0
  264. package/pipeline/skills/shared/external/nodejs-backend-patterns/references/runtime-patterns.md +11 -0
  265. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +11 -0
  266. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +18 -0
  267. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +11 -0
  268. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +11 -0
  269. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +15 -0
  270. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +14 -0
  271. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +14 -0
  272. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +14 -0
  273. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +14 -0
  274. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +10 -0
  275. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +12 -0
  276. package/pipeline/skills/shared/external/retrofit-networking/references/patterns.md +14 -0
  277. package/pipeline/skills/shared/external/room-database/references/patterns.md +16 -0
  278. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +10 -0
  279. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +10 -0
  280. package/pipeline/skills/shared/external/spm-build-analysis/references/build-optimization-sources.md +14 -0
  281. package/pipeline/skills/shared/external/spm-build-analysis/references/spm-analysis-checks.md +19 -0
  282. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +13 -0
  283. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +31 -0
  284. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +8 -0
  285. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +9 -0
  286. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +10 -0
  287. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +8 -0
  288. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +24 -0
  289. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +8 -0
  290. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +14 -0
  291. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +12 -0
  292. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +10 -0
  293. package/pipeline/skills/shared/external/swift-concurrency-expert/references/swift-6-2-concurrency.md +8 -0
  294. package/pipeline/skills/shared/external/swift-concurrency-pro/references/actors.md +10 -0
  295. package/pipeline/skills/shared/external/swift-concurrency-pro/references/cancellation.md +7 -0
  296. package/pipeline/skills/shared/external/swift-concurrency-pro/references/interop.md +10 -0
  297. package/pipeline/skills/shared/external/swift-concurrency-pro/references/new-features.md +11 -0
  298. package/pipeline/skills/shared/external/swift-concurrency-pro/references/structured.md +9 -0
  299. package/pipeline/skills/shared/external/swift-concurrency-pro/references/testing.md +13 -0
  300. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +7 -0
  301. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +14 -0
  302. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +16 -0
  303. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +17 -0
  304. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +19 -0
  305. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +16 -0
  306. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +19 -0
  307. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +18 -0
  308. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +16 -0
  309. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +17 -0
  310. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +17 -0
  311. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +17 -0
  312. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +18 -0
  313. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +21 -0
  314. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +16 -0
  315. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +16 -0
  316. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +9 -0
  317. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +24 -0
  318. package/pipeline/skills/shared/external/swift-testing-pro/references/async-tests.md +9 -0
  319. package/pipeline/skills/shared/external/swift-testing-pro/references/new-features.md +11 -0
  320. package/pipeline/skills/shared/external/swift-testing-pro/references/writing-better-tests.md +13 -0
  321. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +8 -0
  322. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +17 -0
  323. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +12 -0
  324. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +11 -0
  325. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +7 -0
  326. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +13 -0
  327. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +24 -0
  328. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +12 -0
  329. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +15 -0
  330. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +15 -0
  331. package/pipeline/skills/shared/external/swiftui-animation/references/scroll-effects.md +12 -0
  332. package/pipeline/skills/shared/external/swiftui-expert-skill/references/accessibility-patterns.md +11 -0
  333. package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-advanced.md +7 -0
  334. package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-basics.md +13 -0
  335. package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-transitions.md +9 -0
  336. package/pipeline/skills/shared/external/swiftui-expert-skill/references/charts-accessibility.md +9 -0
  337. package/pipeline/skills/shared/external/swiftui-expert-skill/references/charts.md +17 -0
  338. package/pipeline/skills/shared/external/swiftui-expert-skill/references/image-optimization.md +9 -0
  339. package/pipeline/skills/shared/external/swiftui-expert-skill/references/latest-apis.md +10 -0
  340. package/pipeline/skills/shared/external/swiftui-expert-skill/references/layout-best-practices.md +12 -0
  341. package/pipeline/skills/shared/external/swiftui-expert-skill/references/list-patterns.md +12 -0
  342. package/pipeline/skills/shared/external/swiftui-expert-skill/references/macos-scenes.md +13 -0
  343. package/pipeline/skills/shared/external/swiftui-expert-skill/references/macos-views.md +12 -0
  344. package/pipeline/skills/shared/external/swiftui-expert-skill/references/macos-window-styling.md +12 -0
  345. package/pipeline/skills/shared/external/swiftui-expert-skill/references/performance-patterns.md +7 -0
  346. package/pipeline/skills/shared/external/swiftui-expert-skill/references/scroll-patterns.md +9 -0
  347. package/pipeline/skills/shared/external/swiftui-expert-skill/references/sheet-navigation-patterns.md +10 -0
  348. package/pipeline/skills/shared/external/swiftui-expert-skill/references/state-management.md +18 -0
  349. package/pipeline/skills/shared/external/swiftui-expert-skill/references/view-structure.md +16 -0
  350. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +11 -0
  351. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +8 -0
  352. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +14 -0
  353. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +9 -0
  354. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +22 -0
  355. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/uikit-glass.md +14 -0
  356. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +10 -0
  357. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +10 -0
  358. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +13 -0
  359. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +10 -0
  360. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +14 -0
  361. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +30 -0
  362. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +16 -0
  363. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +11 -0
  364. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +11 -0
  365. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +10 -0
  366. package/pipeline/skills/shared/external/swiftui-performance-audit/references/code-smells.md +8 -0
  367. package/pipeline/skills/shared/external/swiftui-ui-patterns/references/app-wiring.md +12 -0
  368. package/pipeline/skills/shared/external/swiftui-ui-patterns/references/menu-bar.md +10 -0
  369. package/pipeline/skills/shared/external/swiftui-ui-patterns/references/navigationstack.md +11 -0
  370. package/pipeline/skills/shared/external/swiftui-ui-patterns/references/scroll-reveal.md +12 -0
  371. package/pipeline/skills/shared/external/swiftui-ui-patterns/references/sheets.md +14 -0
  372. package/pipeline/skills/shared/external/swiftui-ui-patterns/references/tabview.md +10 -0
  373. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +10 -0
  374. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +13 -0
  375. package/pipeline/skills/shared/external/swiftui-view-refactor/references/mv-patterns.md +12 -0
  376. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +8 -0
  377. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +8 -0
  378. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +14 -0
  379. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +17 -0
  380. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +11 -0
  381. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +11 -0
  382. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +27 -0
  383. package/pipeline/skills/shared/external/xcode-build-fixer/references/build-settings-best-practices.md +9 -0
  384. package/pipeline/skills/shared/external/xcode-build-fixer/references/fix-patterns.md +7 -0
  385. package/pipeline/skills/shared/external/xcode-build-orchestrator/references/build-settings-best-practices.md +9 -0
  386. package/pipeline/skills/shared/external/xcode-compilation-analyzer/references/build-optimization-sources.md +14 -0
  387. package/pipeline/skills/shared/external/xcode-compilation-analyzer/references/code-compilation-checks.md +8 -0
  388. package/pipeline/skills/shared/external/xcode-project-analyzer/references/build-optimization-sources.md +14 -0
  389. package/pipeline/skills/shared/external/xcode-project-analyzer/references/build-settings-best-practices.md +9 -0
  390. package/pipeline/skills/shared/external/xcode-project-analyzer/references/project-audit-checks.md +13 -0
@@ -0,0 +1,261 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @file file-context.mjs - what the repository's memory says about a file,
4
+ * handed to the model right after it reads that file.
5
+ *
6
+ * PostToolUse on Read. For the file just read it looks up, in the per-repo
7
+ * stores under ~/.claude/memory/multi-agent/<repo-slug>/:
8
+ *
9
+ * learnings-ledger.jsonl durable facts and conventions whose scope covers the file,
10
+ * minus those the feedback suppressed (_memory-policy.mjs)
11
+ * triage-corpus.jsonl the latest review findings recorded against it
12
+ * debt.jsonl open known limits in it (debt-ledger.mjs)
13
+ *
14
+ * and returns at most MAX_LINES of them as PostToolUse additionalContext,
15
+ * inside an <untrusted-data> block: the rows hold model-written text, so they
16
+ * are evidence about the file, never an instruction.
17
+ *
18
+ * When it runs: inside a pipeline run bound to the session (_active-run.mjs),
19
+ * or anywhere when prefs.global.fileContext.enabled is true; never when that
20
+ * flag is false. Each file is answered once per session. The text passes the
21
+ * secret scan before it is handed over; a hit means nothing is said.
22
+ *
23
+ * `file-context.mjs --lines <path>` prints the same lines, secret-scanned and
24
+ * wrapped the same way, for a caller that already decided to show them
25
+ * (check-read-size.sh, when it turns a whole-file read away). It applies no
26
+ * session or run condition, but stays silent when the flag is false.
27
+ *
28
+ * Blocks nothing and prints nothing on any failure: a missing store, a slow
29
+ * scan or a malformed payload all end in exit 0 with no output.
30
+ *
31
+ * @module pipeline/scripts/file-context
32
+ */
33
+
34
+ import { spawnSync } from "node:child_process";
35
+ import {
36
+ existsSync,
37
+ lstatSync,
38
+ mkdirSync,
39
+ readFileSync,
40
+ realpathSync,
41
+ statSync,
42
+ writeFileSync,
43
+ } from "node:fs";
44
+ import { homedir, tmpdir } from "node:os";
45
+ import { basename, dirname, join, relative } from "node:path";
46
+
47
+ import { wrapUntrusted } from "../lib/untrusted.mjs";
48
+ import { findActiveRun } from "./_active-run.mjs";
49
+ import { ledgerRowId, standing } from "./_memory-policy.mjs";
50
+ import { openScanner } from "./_secret-scan.mjs";
51
+ import { invokedDirectly } from "../lib/invoked-directly.mjs";
52
+
53
+ const MAX_INPUT = 256 * 1024;
54
+ const MAX_LINES = 6;
55
+ const MAX_LINE_CHARS = 220;
56
+ const STORE_MAX_BYTES = 4 * 1024 * 1024;
57
+
58
+ const prefsPath = (env) =>
59
+ env.MULTI_AGENT_PREFS || join(env.HOME || homedir(), ".claude", "multi-agent-preferences.json");
60
+
61
+ /** off | on | run-only, from prefs.global.fileContext.enabled. */
62
+ export function mode(env = process.env) {
63
+ try {
64
+ const flag = JSON.parse(readFileSync(prefsPath(env), "utf8"))?.global?.fileContext?.enabled;
65
+ if (flag === false) return "off";
66
+ if (flag === true) return "on";
67
+ } catch {
68
+ /* no prefs: the default */
69
+ }
70
+ return "run-only";
71
+ }
72
+
73
+ /** Repo slug and the file's path inside the repo, as the stores key them. */
74
+ export function locate(filePath) {
75
+ const dir = dirname(filePath);
76
+ const git = (args) =>
77
+ spawnSync("git", ["-C", dir, ...args], { encoding: "utf8", timeout: 2000 }).stdout?.trim();
78
+ const top = git(["rev-parse", "--show-toplevel"]);
79
+ if (!top) return null;
80
+ const common = git(["rev-parse", "--path-format=absolute", "--git-common-dir"]) || "";
81
+ const root = basename(common) === ".git" ? dirname(common) : top;
82
+ // git answers with the resolved path (/private/var on macOS), so the file is
83
+ // resolved the same way before the two are compared.
84
+ return { slug: basename(root), rel: relative(realpathSync(top), realpathSync(filePath)) };
85
+ }
86
+
87
+ function rows(path) {
88
+ try {
89
+ if (statSync(path).size > STORE_MAX_BYTES) return [];
90
+ return readFileSync(path, "utf8")
91
+ .split("\n")
92
+ .filter((l) => l.trim())
93
+ .flatMap((l) => {
94
+ try {
95
+ return [JSON.parse(l)];
96
+ } catch {
97
+ return [];
98
+ }
99
+ });
100
+ } catch {
101
+ return [];
102
+ }
103
+ }
104
+
105
+ function scopeCovers(scope, rel) {
106
+ if (!scope || scope === "global") return false;
107
+ const dirOf = (g) =>
108
+ String(g)
109
+ .replace(/\/+$/, "")
110
+ .replace(/\/\*+$/, "");
111
+ const s = dirOf(scope);
112
+ return s === rel || rel.startsWith(s + "/");
113
+ }
114
+
115
+ const clip = (s) => {
116
+ const one = String(s ?? "")
117
+ .replace(/\s+/g, " ")
118
+ .trim();
119
+ return one.length > MAX_LINE_CHARS ? one.slice(0, MAX_LINE_CHARS - 3) + "..." : one;
120
+ };
121
+
122
+ /** The lines worth saying about one file, most specific first. */
123
+ export function linesFor(storeDir, rel) {
124
+ const out = [];
125
+ const feedback = new Map();
126
+ for (const f of rows(join(storeDir, "learnings-feedback.jsonl"))) {
127
+ if (!feedback.has(f.id)) feedback.set(f.id, []);
128
+ feedback.get(f.id).push(f);
129
+ }
130
+ for (const r of rows(join(storeDir, "learnings-ledger.jsonl"))) {
131
+ if (!scopeCovers(r.scope, rel)) continue;
132
+ if (standing(feedback.get(ledgerRowId(r)) ?? []).suppressed) continue;
133
+ out.push(`${r.kind}: ${clip(r.statement)}`);
134
+ }
135
+ const findings = rows(join(storeDir, "triage-corpus.jsonl"))
136
+ .filter((r) => r.file === rel)
137
+ .slice(-3)
138
+ .reverse();
139
+ for (const f of findings) {
140
+ out.push(`past review (${f.classification}, ${f.severity}): ${clip(f.issue)}`);
141
+ }
142
+ const debt = new Map();
143
+ for (const r of rows(join(storeDir, "debt.jsonl"))) debt.set(r.id, { ...debt.get(r.id), ...r });
144
+ for (const d of debt.values()) {
145
+ if (d.status === "open" && d.file === rel) out.push(`known limit (${d.kind}): ${clip(d.text)}`);
146
+ }
147
+ return out.slice(0, MAX_LINES);
148
+ }
149
+
150
+ /** The cache directory exists, is a real directory and belongs to this user. */
151
+ function ownDir(dir) {
152
+ try {
153
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
154
+ const st = lstatSync(dir);
155
+ return st.isDirectory() && (process.getuid === undefined || st.uid === process.getuid());
156
+ } catch {
157
+ return false;
158
+ }
159
+ }
160
+
161
+ function seenBefore(sessionId, rel, slug) {
162
+ if (!sessionId) return false;
163
+ const uid = process.getuid?.() ?? "user";
164
+ const dir = join(tmpdir(), `multi-agent-file-context-${uid}`);
165
+ const f = join(dir, `${String(sessionId).replace(/[^A-Za-z0-9_-]/g, "")}.json`);
166
+ if (!ownDir(dir)) return false;
167
+ let seen = [];
168
+ try {
169
+ seen = JSON.parse(readFileSync(f, "utf8"));
170
+ } catch {
171
+ /* first file this session */
172
+ }
173
+ const key = `${slug}:${rel}`;
174
+ if (seen.includes(key)) return true;
175
+ try {
176
+ writeFileSync(f, JSON.stringify([...seen, key].slice(-500)), { mode: 0o600 });
177
+ } catch {
178
+ /* a lost cache only means saying it twice */
179
+ }
180
+ return false;
181
+ }
182
+
183
+ /** The hook's answer for one payload, or null for silence. */
184
+ export function answer(payload, env = process.env) {
185
+ if (payload?.tool_name !== "Read") return null;
186
+ const filePath = payload?.tool_input?.file_path;
187
+ if (typeof filePath !== "string" || !filePath || !existsSync(filePath)) return null;
188
+ const m = mode(env);
189
+ if (m === "off") return null;
190
+ if (m === "run-only" && !findActiveRun({ sessionId: payload.session_id, cwd: payload.cwd, env }))
191
+ return null;
192
+ const where = locate(filePath);
193
+ if (!where || where.rel.startsWith("..")) return null;
194
+ const storeDir = join(env.HOME || homedir(), ".claude", "memory", "multi-agent", where.slug);
195
+ const lines = linesFor(storeDir, where.rel);
196
+ if (!lines.length || seenBefore(payload.session_id, where.rel, where.slug)) return null;
197
+ const text = lines.map((l) => `- ${l}`).join("\n");
198
+ const scan = openScanner();
199
+ try {
200
+ if (!scan.isClean(text)) return null;
201
+ } finally {
202
+ scan.close();
203
+ }
204
+ return {
205
+ hookSpecificOutput: {
206
+ hookEventName: "PostToolUse",
207
+ additionalContext: wrapUntrusted(`memory:${where.slug}/${where.rel}`, text),
208
+ },
209
+ };
210
+ }
211
+
212
+ /**
213
+ * The scanned lines for one file inside an untrusted-data block, or "" when
214
+ * file context is off, there is nothing, or the scan refused it.
215
+ */
216
+ export function blockForPath(filePath, env = process.env) {
217
+ if (mode(env) === "off" || !existsSync(filePath)) return "";
218
+ const where = locate(filePath);
219
+ if (!where || where.rel.startsWith("..")) return "";
220
+ const storeDir = join(env.HOME || homedir(), ".claude", "memory", "multi-agent", where.slug);
221
+ const text = linesFor(storeDir, where.rel)
222
+ .map((l) => `- ${l}`)
223
+ .join("\n");
224
+ if (!text) return "";
225
+ const scan = openScanner();
226
+ try {
227
+ return scan.isClean(text) ? wrapUntrusted(`memory:${where.slug}/${where.rel}`, text) : "";
228
+ } finally {
229
+ scan.close();
230
+ }
231
+ }
232
+
233
+ function main() {
234
+ const i = process.argv.indexOf("--lines");
235
+ if (i > 0) {
236
+ const block = process.argv[i + 1] ? blockForPath(process.argv[i + 1]) : "";
237
+ if (block) process.stdout.write(block);
238
+ return;
239
+ }
240
+ let raw;
241
+ try {
242
+ raw = readFileSync(0, "utf8");
243
+ } catch {
244
+ return;
245
+ }
246
+ if (!raw || raw.length > MAX_INPUT) return;
247
+ let payload;
248
+ try {
249
+ payload = JSON.parse(raw);
250
+ } catch {
251
+ return;
252
+ }
253
+ const out = answer(payload);
254
+ if (out) process.stdout.write(JSON.stringify(out) + "\n");
255
+ }
256
+
257
+ try {
258
+ if (invokedDirectly(import.meta.url)) main();
259
+ } catch {
260
+ /* silent by contract */
261
+ }
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env bash
2
+ # file-context.sh - PostToolUse hook (Read) for the pipeline.
3
+ #
4
+ # Hands the model what the repository's memory says about the file it just
5
+ # read: ledger facts, past review findings and open known limits. The logic is
6
+ # in file-context.mjs; this wrapper exists because every hook the pipeline
7
+ # registers is a `bash "$HOME/.<host>/scripts/<name>"` command.
8
+ #
9
+ # Exits 0 on every path: a missing node, a slow scan or any internal error
10
+ # means no context, never a blocked tool call.
11
+
12
+ set -u
13
+
14
+ HERE="$(cd "$(dirname "$0")" 2>/dev/null && pwd || true)"
15
+ CORE="$HERE/file-context.mjs"
16
+ [ -f "$CORE" ] || exit 0
17
+ command -v node >/dev/null 2>&1 || exit 0
18
+
19
+ node "$CORE" 2>/dev/null || true
20
+ exit 0
@@ -54,14 +54,18 @@
54
54
 
55
55
  import { spawnSync } from "node:child_process";
56
56
  import {
57
+ copyFileSync,
57
58
  existsSync,
59
+ mkdtempSync,
58
60
  readFileSync,
59
61
  realpathSync,
60
62
  renameSync,
63
+ rmSync,
61
64
  statSync,
62
65
  writeFileSync,
63
66
  } from "node:fs";
64
- import { basename, dirname } from "node:path";
67
+ import { tmpdir } from "node:os";
68
+ import { basename, dirname, join } from "node:path";
65
69
 
66
70
  import { decisionEntry, withDecision } from "../lib/decisions.mjs";
67
71
  import { invokedDirectly } from "../lib/invoked-directly.mjs";
@@ -103,31 +107,77 @@ export const ATTENDED_RECORDED = new Set([
103
107
  "plan-coverage",
104
108
  "evidence-gate/build",
105
109
  "evidence-gate/test",
110
+ "review-decision",
106
111
  ]);
107
112
 
108
113
  /** What an attended commit is checked for (pre-commit-check.sh, `evidence`). */
114
+ /**
115
+ * Fix loops with a hard cap (rules.md: three attempts, the fourth failure
116
+ * pauses): consecutive failing verdicts of one of these gates count, and the
117
+ * append that reaches RETRY_CAP pauses the run with a halt reason.
118
+ */
119
+ export const RETRY_CAPPED = new Set(["evidence-gate/build", "evidence-gate/test"]);
120
+ export const RETRY_CAP = 4;
121
+
122
+ /** Consecutive failing verdicts at the end of `gates` for one gate. */
123
+ export function trailingFailures(gates, gate) {
124
+ let n = 0;
125
+ for (let i = gates.length - 1; i >= 0; i--) {
126
+ const e = gates[i];
127
+ if (!e || e.gate !== gate) continue;
128
+ if (e.verdict !== "fail") break;
129
+ n += 1;
130
+ }
131
+ return n;
132
+ }
133
+
109
134
  export const ATTENDED_COMMIT_EVIDENCE = ["evidence-gate/build", "evidence-gate/test"];
110
135
 
111
- /** prefs.global.attendedCommitGate.mode values; `warn` is the default. */
112
- export const ATTENDED_COMMIT_MODES = ["off", "warn", "block"];
136
+ /** Asked for too once the run is in its commit phase: the review verdict. */
137
+ export const ATTENDED_REVIEW_EVIDENCE = "review-decision";
138
+ export const ATTENDED_REVIEW_FROM_PHASE = 4;
113
139
 
114
140
  /**
115
- * The build/test evidence an attended commit on `sha` lacks: every gate in
116
- * ATTENDED_COMMIT_EVIDENCE whose latest entry for that sha, attended or not,
117
- * is missing or not passing.
141
+ * prefs.global.attendedCommitGate.mode values. `auto`, the default, blocks
142
+ * the commit when the run is bound to the committing session (the session
143
+ * driving it) and warns otherwise.
144
+ */
145
+ export const ATTENDED_COMMIT_MODES = ["off", "warn", "block", "auto"];
146
+
147
+ /**
148
+ * The evidence an attended commit on `sha` lacks: every gate in
149
+ * ATTENDED_COMMIT_EVIDENCE, plus the review verdict from the commit phase on,
150
+ * whose latest entry for that sha, attended or not, is missing or not passing.
151
+ * A checkpoint commit during development comes before any review and is held
152
+ * to build and test only.
118
153
  *
119
154
  * @param {object} state
120
155
  * @param {string} sha
121
156
  * @returns {string[]}
122
157
  */
123
- export function attendedEvidenceGaps(state, sha) {
124
- const latest = latestByGate(state?.gates, sha);
125
- return ATTENDED_COMMIT_EVIDENCE.filter((g) => {
158
+ export function attendedEvidenceGaps(state, sha, { sameTree } = {}) {
159
+ const wanted = [...ATTENDED_COMMIT_EVIDENCE];
160
+ if (Number(state?.currentPhase) >= ATTENDED_REVIEW_FROM_PHASE)
161
+ wanted.push(ATTENDED_REVIEW_EVIDENCE);
162
+ const asked = (Array.isArray(state?.gates) ? state.gates : []).filter((e) =>
163
+ wanted.includes(e?.gate),
164
+ );
165
+ const latest = sameTree
166
+ ? latestByGateWhere(asked, (s) => s === sha || sameTree(s))
167
+ : latestByGate(asked, sha);
168
+ return wanted.filter((g) => {
126
169
  const e = latest.get(g);
127
170
  return !e || !PASSING.has(e.verdict);
128
171
  });
129
172
  }
130
173
 
174
+ /** The mode that applies: an explicit off/warn/block, else block for a bound run. */
175
+ export function effectiveCommitMode(pref, bound) {
176
+ const mode = ATTENDED_COMMIT_MODES.includes(pref) ? pref : "auto";
177
+ if (mode !== "auto") return mode;
178
+ return bound ? "block" : "warn";
179
+ }
180
+
131
181
  const QUESTION_ID = /^[a-z][a-z0-9-]*$/;
132
182
  const OPTION_ID = /^[a-z0-9][a-z0-9+_-]*$/;
133
183
  const QUESTION_KEYS = ["id", "stepId", "text", "kind", "options"];
@@ -184,6 +234,54 @@ export class LedgerError extends Error {
184
234
  * HEAD of the repository at `dir`, or null outside one.
185
235
  * @param {string} dir
186
236
  */
237
+ /**
238
+ * A predicate: does a recorded sha hold the content this commit records?
239
+ * Yes when its tree is the index's, or the tree `git add -A` would stage from
240
+ * the working tree (built in a throwaway copy of the index, so the real index
241
+ * is untouched). The hook runs before a `git add ... && git commit` line
242
+ * stages anything, and Phase 4's `git reset HEAD~1` leaves a checkpoint
243
+ * commit's new files untracked; both still match the evidence they were
244
+ * tested with, while a file added after the evidence does not. Each sha is
245
+ * asked once; anything git cannot answer is "no".
246
+ */
247
+ export function sameTreeAs(dir) {
248
+ const run = (args, env) => {
249
+ const r = spawnSync("git", ["-C", dir, ...args], {
250
+ encoding: "utf8",
251
+ timeout: 20000,
252
+ env: env ? { ...process.env, ...env } : process.env,
253
+ });
254
+ return r.status === 0 ? r.stdout.trim() : null;
255
+ };
256
+ const indexTree = run(["write-tree"]);
257
+ let workTree = null;
258
+ const indexPath = run(["rev-parse", "--path-format=absolute", "--git-path", "index"]);
259
+ if (indexPath) {
260
+ const scratch = mkdtempSync(join(tmpdir(), "ma-tree-"));
261
+ const copy = join(scratch, "index");
262
+ try {
263
+ if (existsSync(indexPath)) copyFileSync(indexPath, copy);
264
+ if (run(["add", "-A"], { GIT_INDEX_FILE: copy }) !== null) {
265
+ workTree = run(["write-tree"], { GIT_INDEX_FILE: copy });
266
+ }
267
+ } catch {
268
+ workTree = null;
269
+ } finally {
270
+ rmSync(scratch, { recursive: true, force: true });
271
+ }
272
+ }
273
+ const targets = new Set([indexTree, workTree].filter(Boolean));
274
+ const seen = new Map();
275
+ return (sha) => {
276
+ if (!targets.size || typeof sha !== "string" || !/^[0-9a-f]{7,64}$/.test(sha)) return false;
277
+ if (!seen.has(sha)) {
278
+ const tree = run(["rev-parse", "--verify", "--quiet", `${sha}^{tree}`]);
279
+ seen.set(sha, Boolean(tree) && targets.has(tree));
280
+ }
281
+ return seen.get(sha);
282
+ };
283
+ }
284
+
187
285
  export function headSha(dir) {
188
286
  const r = spawnSync("git", ["-C", dir, "rev-parse", "HEAD"], {
189
287
  encoding: "utf8",
@@ -399,11 +497,22 @@ export async function record(
399
497
  detail: detail && typeof detail === "object" ? detail : { value: detail },
400
498
  ...(attended ? { attended: true } : {}),
401
499
  };
402
- await updateState(path, (s) => ({
403
- ...s,
404
- gates: [...(Array.isArray(s.gates) ? s.gates : []), entry],
405
- }));
406
- return { written: true, statePath: path, entry };
500
+ let capped = false;
501
+ await updateState(path, (s) => {
502
+ const gates = [...(Array.isArray(s.gates) ? s.gates : []), entry];
503
+ const next = { ...s, gates };
504
+ if (
505
+ RETRY_CAPPED.has(gate) &&
506
+ verdict === "fail" &&
507
+ trailingFailures(gates, gate) >= RETRY_CAP
508
+ ) {
509
+ capped = true;
510
+ next.status = "paused";
511
+ next.haltReason = `${phaseOf(s)}:retry-cap: ${gate} failed ${RETRY_CAP} times in a row; the fix loop stops here for the user`;
512
+ }
513
+ return next;
514
+ });
515
+ return { written: true, statePath: path, entry, capped };
407
516
  }
408
517
 
409
518
  /**
@@ -494,9 +603,14 @@ function phaseOf(state) {
494
603
  * Latest entry per gate for one sha. "Latest" is by `at`, then by position.
495
604
  */
496
605
  export function latestByGate(gates, sha) {
606
+ return latestByGateWhere(gates, (s) => s === sha);
607
+ }
608
+
609
+ /** latestByGate over the entries whose sha `accept` takes. */
610
+ export function latestByGateWhere(gates, accept) {
497
611
  const out = new Map();
498
612
  (Array.isArray(gates) ? gates : []).forEach((e, i) => {
499
- if (!e || typeof e !== "object" || e.sha !== sha || typeof e.gate !== "string") return;
613
+ if (!e || typeof e !== "object" || typeof e.gate !== "string" || !accept(e.sha)) return;
500
614
  const prev = out.get(e.gate);
501
615
  const t = Date.parse(e.at) || 0;
502
616
  if (!prev || t > prev.t || (t === prev.t && i > prev.i)) out.set(e.gate, { e, t, i });
@@ -570,6 +684,12 @@ async function main(argv) {
570
684
  // Gates off: nothing is written and nothing is said.
571
685
  if (!r.written && r.reason === attendedVerdict(opts.gate).reason) return 0;
572
686
  if (!r.written) process.stderr.write(`gate-ledger: nothing written: ${r.reason}\n`);
687
+ if (r.capped) {
688
+ process.stderr.write(
689
+ `gate-ledger: ${opts.gate} failed ${RETRY_CAP} times in a row; the run is paused (retry cap). Report what was tried and ask the user how to continue.\n`,
690
+ );
691
+ return 5;
692
+ }
573
693
  return r.written ? 0 : 3;
574
694
  }
575
695
  if (mode === "check") {
@@ -619,9 +739,8 @@ async function main(argv) {
619
739
  // mode that commits nothing, evidence present), 1 warn, 4 block. Never 2
620
740
  // or 3 for a missing run: outside the pipeline a commit is none of this
621
741
  // hook's business.
622
- const pref = globalPref("attendedCommitGate.mode", "warn");
623
- const gateMode = ATTENDED_COMMIT_MODES.includes(pref) ? pref : "warn";
624
- if (gateMode === "off") return 0;
742
+ const pref = globalPref("attendedCommitGate.mode", "auto");
743
+ if (pref === "off") return 0;
625
744
  let session = "";
626
745
  if (opts["hook-input"] === "-") {
627
746
  try {
@@ -638,7 +757,11 @@ async function main(argv) {
638
757
  if (modeEntry(state)?.commits === false) return 0;
639
758
  const sha = opts.sha || headSha(repo);
640
759
  if (!sha) return 0;
641
- const missing = attendedEvidenceGaps(state, sha);
760
+ const launched = process.env.MULTI_AGENT_SESSION_ID || "";
761
+ const bound =
762
+ (session && state.hostSessionId === session) || (launched && state.sessionId === launched);
763
+ const gateMode = effectiveCommitMode(pref, Boolean(bound));
764
+ const missing = attendedEvidenceGaps(state, sha, { sameTree: sameTreeAs(repo) });
642
765
  if (opts.json)
643
766
  writeFileSync(1, `${JSON.stringify({ statePath: path, sha, gateMode, missing })}\n`);
644
767
  if (!missing.length) return 0;
@@ -647,9 +770,9 @@ async function main(argv) {
647
770
  2,
648
771
  `${[
649
772
  `pre-commit-check: ${verb}: the run's gate ledger (${path}) has no passing ${missing.join(" / ")} for HEAD ${sha.slice(0, 12)}.`,
650
- " Run the build and the tests through evidence-gate.mjs (Phase 2 Gate 1) so the commit rests on recorded evidence.",
773
+ " Run the build and the tests through evidence-gate.mjs (Phase 2 Gate 1), and in the commit phase the review verdict (review-decision-gate.mjs), so the commit rests on recorded evidence.",
651
774
  gateMode === "block"
652
- ? " prefs.global.attendedCommitGate.mode is block; set it to warn to commit anyway."
775
+ ? " This session drives the run, so the commit waits for the evidence; prefs.global.attendedCommitGate.mode warn lets it through."
653
776
  : " The commit goes ahead; prefs.global.attendedCommitGate.mode block refuses it instead.",
654
777
  ].join("\n")}\n`,
655
778
  );