@aria_asi/cli 0.2.39 → 0.2.41

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 (802) hide show
  1. package/bin/aria.js +236 -34
  2. package/dist/aria-connector/src/action-ledger-core.d.ts +387 -0
  3. package/dist/aria-connector/src/action-ledger-core.d.ts.map +1 -0
  4. package/dist/aria-connector/src/action-ledger-core.js +638 -0
  5. package/dist/aria-connector/src/action-ledger-core.js.map +1 -0
  6. package/dist/aria-connector/src/chat.d.ts.map +1 -1
  7. package/dist/aria-connector/src/chat.js +5 -6
  8. package/dist/aria-connector/src/chat.js.map +1 -1
  9. package/dist/aria-connector/src/codebase-scanner.d.ts +1 -1
  10. package/dist/aria-connector/src/codebase-scanner.d.ts.map +1 -1
  11. package/dist/aria-connector/src/connectors/claude-code.d.ts +1 -0
  12. package/dist/aria-connector/src/connectors/claude-code.d.ts.map +1 -1
  13. package/dist/aria-connector/src/connectors/claude-code.js +152 -14
  14. package/dist/aria-connector/src/connectors/claude-code.js.map +1 -1
  15. package/dist/aria-connector/src/connectors/codebase-awareness.d.ts +10 -0
  16. package/dist/aria-connector/src/connectors/codebase-awareness.d.ts.map +1 -1
  17. package/dist/aria-connector/src/connectors/codebase-awareness.js +276 -27
  18. package/dist/aria-connector/src/connectors/codebase-awareness.js.map +1 -1
  19. package/dist/aria-connector/src/connectors/codex.d.ts +3 -1
  20. package/dist/aria-connector/src/connectors/codex.d.ts.map +1 -1
  21. package/dist/aria-connector/src/connectors/codex.js +1271 -40
  22. package/dist/aria-connector/src/connectors/codex.js.map +1 -1
  23. package/dist/aria-connector/src/connectors/cursor.d.ts.map +1 -1
  24. package/dist/aria-connector/src/connectors/cursor.js +7 -0
  25. package/dist/aria-connector/src/connectors/cursor.js.map +1 -1
  26. package/dist/aria-connector/src/connectors/governed-adapter.d.ts +30 -0
  27. package/dist/aria-connector/src/connectors/governed-adapter.d.ts.map +1 -0
  28. package/dist/aria-connector/src/connectors/governed-adapter.js +132 -0
  29. package/dist/aria-connector/src/connectors/governed-adapter.js.map +1 -0
  30. package/dist/aria-connector/src/connectors/opencode.d.ts +3 -1
  31. package/dist/aria-connector/src/connectors/opencode.d.ts.map +1 -1
  32. package/dist/aria-connector/src/connectors/opencode.js +18 -2
  33. package/dist/aria-connector/src/connectors/opencode.js.map +1 -1
  34. package/dist/aria-connector/src/connectors/repo-guard.d.ts.map +1 -1
  35. package/dist/aria-connector/src/connectors/repo-guard.js +25 -14
  36. package/dist/aria-connector/src/connectors/repo-guard.js.map +1 -1
  37. package/dist/aria-connector/src/connectors/runtime.d.ts.map +1 -1
  38. package/dist/aria-connector/src/connectors/runtime.js +92 -2
  39. package/dist/aria-connector/src/connectors/runtime.js.map +1 -1
  40. package/dist/aria-connector/src/connectors/shell.d.ts.map +1 -1
  41. package/dist/aria-connector/src/connectors/shell.js +123 -7
  42. package/dist/aria-connector/src/connectors/shell.js.map +1 -1
  43. package/dist/aria-connector/src/cross-cli-hive-binding.d.ts +63 -0
  44. package/dist/aria-connector/src/cross-cli-hive-binding.d.ts.map +1 -0
  45. package/dist/aria-connector/src/cross-cli-hive-binding.js +205 -0
  46. package/dist/aria-connector/src/cross-cli-hive-binding.js.map +1 -0
  47. package/dist/aria-connector/src/garden-control-plane.d.ts +6 -1
  48. package/dist/aria-connector/src/garden-control-plane.d.ts.map +1 -1
  49. package/dist/aria-connector/src/garden-control-plane.js +8 -2
  50. package/dist/aria-connector/src/garden-control-plane.js.map +1 -1
  51. package/dist/aria-connector/src/governed-surface-runner.d.ts +189 -0
  52. package/dist/aria-connector/src/governed-surface-runner.d.ts.map +1 -0
  53. package/dist/aria-connector/src/governed-surface-runner.js +1022 -0
  54. package/dist/aria-connector/src/governed-surface-runner.js.map +1 -0
  55. package/dist/aria-connector/src/index.d.ts +10 -1
  56. package/dist/aria-connector/src/index.d.ts.map +1 -1
  57. package/dist/aria-connector/src/index.js +5 -0
  58. package/dist/aria-connector/src/index.js.map +1 -1
  59. package/dist/aria-connector/src/task-runner.d.ts +3 -0
  60. package/dist/aria-connector/src/task-runner.d.ts.map +1 -0
  61. package/dist/aria-connector/src/task-runner.js +3526 -0
  62. package/dist/aria-connector/src/task-runner.js.map +1 -0
  63. package/dist/aria-web/src/lib/codebase-scanner.d.ts +21 -2
  64. package/dist/aria-web/src/lib/codebase-scanner.d.ts.map +1 -1
  65. package/dist/aria-web/src/lib/codebase-scanner.js +59 -14
  66. package/dist/aria-web/src/lib/codebase-scanner.js.map +1 -1
  67. package/dist/assets/hooks/README.md +58 -0
  68. package/dist/assets/hooks/aria-agent-handoff.mjs +147 -2
  69. package/dist/assets/hooks/aria-agent-ledger-merge.mjs +31 -7
  70. package/dist/assets/hooks/aria-architect-fallback.mjs +10 -2
  71. package/dist/assets/hooks/aria-claim-evidence-stop-gate.mjs +240 -0
  72. package/dist/assets/hooks/aria-cognition-substrate-binding.mjs +84 -10
  73. package/dist/assets/hooks/aria-first-class-coach.mjs +305 -10
  74. package/dist/assets/hooks/aria-harness-via-sdk.mjs +93 -16
  75. package/dist/assets/hooks/aria-import-resolution-gate.mjs +106 -20
  76. package/dist/assets/hooks/aria-outcome-record.mjs +56 -20
  77. package/dist/assets/hooks/aria-pre-emit-autoload.mjs +1809 -0
  78. package/dist/assets/hooks/aria-pre-emit-autoload.mjs.before-orchestration-redesign +1400 -0
  79. package/dist/assets/hooks/aria-pre-emit-dryrun.mjs +22 -3
  80. package/dist/assets/hooks/aria-pre-text-gate.mjs +11 -2
  81. package/dist/assets/hooks/aria-pre-tool-gate.mjs +516 -92
  82. package/dist/assets/hooks/aria-pre-tool-use.mjs +70 -6
  83. package/dist/assets/hooks/aria-preprompt-consult.mjs +23 -4
  84. package/dist/assets/hooks/aria-repo-doctrine-gate.mjs +29 -3
  85. package/dist/assets/hooks/aria-stop-gate.mjs +585 -76
  86. package/dist/assets/hooks/aria-trigger-autolearn.mjs +17 -3
  87. package/dist/assets/hooks/aria-universal-turn-packet.mjs +1165 -0
  88. package/dist/assets/hooks/aria-userprompt-abandon-detect.mjs +9 -1
  89. package/dist/assets/hooks/canonical-settings-block.json +172 -0
  90. package/dist/assets/hooks/codex-native/aria-harness-ticker-sidecar.mjs +92 -0
  91. package/dist/assets/hooks/codex-native/aria-hive-wal-consumer.mjs +86 -0
  92. package/dist/assets/hooks/codex-native/aria-live-ticker.mjs +38 -0
  93. package/dist/assets/hooks/codex-native/aria-post-tool-use.mjs +236 -0
  94. package/dist/assets/hooks/codex-native/aria-pre-tool-use.mjs +362 -0
  95. package/dist/assets/hooks/codex-native/aria-stop.mjs +691 -0
  96. package/dist/assets/hooks/codex-native/aria-userprompt-submit.mjs +623 -0
  97. package/dist/assets/hooks/codex-native/atlas-session-context.mjs +121 -0
  98. package/dist/assets/hooks/codex-native/lib/evaluate-with-kernel.mjs +257 -0
  99. package/dist/assets/hooks/codex-native/lib/hive-wal-consumer.mjs +452 -0
  100. package/dist/assets/hooks/codex-native/lib/kernel/deterministic-cognitive-kernel.mjs +914 -0
  101. package/dist/assets/hooks/codex-native/lib/project-boundary-cognition.mjs +143 -0
  102. package/dist/assets/hooks/codex-native/lib/runtime-client.mjs +3567 -0
  103. package/dist/assets/hooks/codex-native/lib/task-project-ledger.mjs +294 -0
  104. package/dist/assets/hooks/doctrine_trigger_map.json +236 -25
  105. package/dist/assets/hooks/doctrine_trigger_map.schema.json +46 -0
  106. package/dist/assets/hooks/install.sh +84 -0
  107. package/dist/assets/hooks/lib/action-ledger-core.mjs +269 -0
  108. package/dist/assets/hooks/lib/aria-gate-ledger.mjs +143 -0
  109. package/dist/assets/hooks/lib/ast-stub-shape-detector.mjs +107 -0
  110. package/dist/assets/hooks/lib/atlas-dossier-client.mjs +151 -0
  111. package/dist/assets/hooks/lib/atlas-orchestrator-postwire.mjs +221 -0
  112. package/dist/assets/hooks/lib/canonical-lenses.mjs +83 -6
  113. package/dist/assets/hooks/lib/coach-intent-classifier.mjs +248 -0
  114. package/dist/assets/hooks/lib/cognitive-block-parser.mjs +111 -0
  115. package/dist/assets/hooks/lib/doctrine-trigger-map-loader.mjs +137 -0
  116. package/dist/assets/hooks/lib/domain-output-quality.mjs +132 -3
  117. package/dist/assets/hooks/lib/empty-catch-scanner.mjs +91 -0
  118. package/dist/assets/hooks/lib/end-phase-qa-autofire.mjs +426 -0
  119. package/dist/assets/hooks/lib/evaluate-with-kernel.mjs +133 -0
  120. package/dist/assets/hooks/lib/first-class-coach.mjs +454 -19
  121. package/dist/assets/hooks/lib/gate-audit.mjs +12 -2
  122. package/dist/assets/hooks/lib/gate-loop-state.mjs +11 -2
  123. package/dist/assets/hooks/lib/goal-contract-quality.mjs +302 -0
  124. package/dist/assets/hooks/lib/hook-message-window.mjs +101 -9
  125. package/dist/assets/hooks/lib/invocation-required-verifier.mjs +184 -0
  126. package/dist/assets/hooks/lib/kernel/deterministic-cognitive-kernel.mjs +906 -0
  127. package/dist/assets/hooks/lib/obligation-ledger.mjs +147 -0
  128. package/dist/assets/hooks/lib/orchestration-manifest-extract.mjs +217 -0
  129. package/dist/assets/hooks/lib/owner-authorizations.mjs +269 -0
  130. package/dist/assets/hooks/lib/probe-discipline-scanner.mjs +142 -0
  131. package/dist/assets/hooks/lib/project-boundary-cognition.mjs +143 -0
  132. package/dist/assets/hooks/lib/recovery-context.mjs +151 -0
  133. package/dist/assets/hooks/lib/recovery-template-loader.mjs +154 -0
  134. package/dist/assets/hooks/lib/self-doctrine-check.mjs +321 -0
  135. package/dist/assets/hooks/lib/sensitive-shape-detector.mjs +64 -0
  136. package/dist/assets/hooks/lib/skill-autoload-gate-impl.mjs +226 -1
  137. package/dist/assets/hooks/lib/stop-hook-protocol.mjs +166 -0
  138. package/dist/assets/hooks/lib/surface-caught.mjs +94 -0
  139. package/dist/assets/hooks/recovery-templates/force-reauthor.md +67 -0
  140. package/dist/assets/hooks/recovery-templates/handoff-recovery.md +25 -0
  141. package/dist/assets/hooks/scripts/check-hard-risk-prefix.mjs +99 -0
  142. package/dist/assets/hooks/skills/aria-conversational-doctrine-discipline/SKILL.md +101 -0
  143. package/dist/assets/hooks/test-aria-preturn-memory-gate.mjs +2 -2
  144. package/dist/assets/hooks/test-tier-lens-labeling.mjs +14 -3
  145. package/dist/assets/opencode-plugins/harness-context/index.js +39 -6
  146. package/dist/assets/opencode-plugins/harness-context/task-project-ledger.mjs +5 -1
  147. package/dist/assets/opencode-plugins/harness-gate/index.js +36 -0
  148. package/dist/assets/opencode-plugins/harness-gate/lib/atlas-dossier-client.js +1 -0
  149. package/dist/assets/opencode-plugins/harness-gate/lib/recovery-grants.js +79 -0
  150. package/dist/assets/opencode-plugins/harness-outcome/index.js +12 -0
  151. package/dist/assets/opencode-plugins/harness-stop/index.js +97 -2
  152. package/dist/assets/opencode-plugins/harness-stop/lib/atlas-dossier-client.js +1 -0
  153. package/dist/assets/opencode-plugins/harness-stop/lib/domain-output-quality.js +15 -2
  154. package/dist/assets/opencode-plugins/lib/coach.js +148 -0
  155. package/dist/runtime/coach-kernel.mjs +144 -7
  156. package/dist/runtime/codex-bridge.mjs +254 -8
  157. package/dist/runtime/discipline/doctrine_trigger_map.json +236 -25
  158. package/dist/runtime/discipline/skills/aria-cognition/34-frameworks-unified/SKILL.md +42 -0
  159. package/dist/runtime/discipline/skills/aria-cognition/aria-aristotle-cognitives/SKILL.md +128 -0
  160. package/dist/runtime/discipline/skills/aria-cognition/aria-aristotle-intra-phase/SKILL.md +99 -0
  161. package/dist/runtime/discipline/skills/aria-cognition/aria-aristotle-post-phase/SKILL.md +118 -0
  162. package/dist/runtime/discipline/skills/aria-cognition/aria-aristotle-pre-phase/SKILL.md +117 -0
  163. package/dist/runtime/discipline/skills/aria-cognition/aria-axioms-first-principles/SKILL.md +202 -0
  164. package/dist/runtime/discipline/skills/aria-cognition/aria-axioms-first-principles/agents/openai.yaml +4 -0
  165. package/dist/runtime/discipline/skills/aria-cognition/aria-axioms-first-principles/references/source-map.md +130 -0
  166. package/dist/runtime/discipline/skills/aria-cognition/aria-backend-architect/SKILL.md +124 -0
  167. package/dist/runtime/discipline/skills/aria-cognition/aria-backend-architect/references/backend-cookbook.md +417 -0
  168. package/dist/runtime/discipline/skills/aria-cognition/aria-business-audit/SKILL.md +133 -0
  169. package/dist/runtime/discipline/skills/aria-cognition/aria-business-audit/references/audit-cookbook.md +247 -0
  170. package/dist/runtime/discipline/skills/aria-cognition/aria-business-frame/SKILL.md +138 -0
  171. package/dist/runtime/discipline/skills/aria-cognition/aria-business-frame/references/business-cookbook.md +154 -0
  172. package/dist/runtime/discipline/skills/aria-cognition/aria-chat/SKILL.md +84 -0
  173. package/dist/runtime/discipline/skills/aria-cognition/aria-chat/scripts/aria-chat.sh +57 -0
  174. package/dist/runtime/discipline/skills/aria-cognition/aria-cognition-autofire/SKILL.md +137 -0
  175. package/dist/runtime/discipline/skills/aria-cognition/aria-cognition-batch/SKILL.md +264 -0
  176. package/dist/runtime/discipline/skills/aria-cognition/aria-decision-mizan/SKILL.md +136 -0
  177. package/dist/runtime/discipline/skills/aria-cognition/aria-decision-mizan/references/decision-frameworks.md +287 -0
  178. package/dist/runtime/discipline/skills/aria-cognition/aria-first-class-operating-contract/SKILL.md +104 -0
  179. package/dist/runtime/discipline/skills/aria-cognition/aria-frontend-architect/SKILL.md +123 -0
  180. package/dist/runtime/discipline/skills/aria-cognition/aria-frontend-architect/references/frontend-cookbook.md +358 -0
  181. package/dist/runtime/discipline/skills/aria-cognition/aria-fullstack-orchestrator/SKILL.md +127 -0
  182. package/dist/runtime/discipline/skills/aria-cognition/aria-fullstack-orchestrator/references/fullstack-cookbook.md +383 -0
  183. package/dist/runtime/discipline/skills/aria-cognition/aria-gtm-architect/SKILL.md +126 -0
  184. package/dist/runtime/discipline/skills/aria-cognition/aria-gtm-architect/references/gtm-cookbook.md +235 -0
  185. package/dist/runtime/discipline/skills/aria-cognition/aria-harness-deploy/SKILL.md +145 -0
  186. package/dist/runtime/discipline/skills/aria-cognition/aria-harness-no-stripping/SKILL.md +135 -0
  187. package/dist/runtime/discipline/skills/aria-cognition/aria-harness-onboarding/SKILL.md +130 -0
  188. package/dist/runtime/discipline/skills/aria-cognition/aria-harness-output-discipline/SKILL.md +120 -0
  189. package/dist/runtime/discipline/skills/aria-cognition/aria-harness-substrate-binding/SKILL.md +139 -0
  190. package/dist/runtime/discipline/skills/aria-cognition/aria-http-harness-client/SKILL.md +85 -0
  191. package/dist/runtime/discipline/skills/aria-cognition/aria-http-harness-client/scripts/smoke.mjs +47 -0
  192. package/dist/runtime/discipline/skills/aria-cognition/aria-k8s-deploy/SKILL.md +174 -0
  193. package/dist/runtime/discipline/skills/aria-cognition/aria-k8s-deploy/agents/openai.yaml +3 -0
  194. package/dist/runtime/discipline/skills/aria-cognition/aria-ladduniframe/SKILL.md +60 -0
  195. package/dist/runtime/discipline/skills/aria-cognition/aria-ledger-fleet-execution/SKILL.md +126 -0
  196. package/dist/runtime/discipline/skills/aria-cognition/aria-live-ops/SKILL.md +54 -0
  197. package/dist/runtime/discipline/skills/aria-cognition/aria-mac-ssh-ops/SKILL.md +100 -0
  198. package/dist/runtime/discipline/skills/aria-cognition/aria-memory-index/SKILL.md +42 -0
  199. package/dist/runtime/discipline/skills/aria-cognition/aria-noor-cognitives/SKILL.md +120 -0
  200. package/dist/runtime/discipline/skills/aria-cognition/aria-ops/SKILL.md +60 -0
  201. package/dist/runtime/discipline/skills/aria-cognition/aria-ops/references/live-endpoints.md +59 -0
  202. package/dist/runtime/discipline/skills/aria-cognition/aria-quality-audit/SKILL.md +133 -0
  203. package/dist/runtime/discipline/skills/aria-cognition/aria-readable-output/SKILL.md +239 -0
  204. package/dist/runtime/discipline/skills/aria-cognition/aria-readable-output/references/layout-cookbook.md +366 -0
  205. package/dist/runtime/discipline/skills/aria-cognition/aria-reasoning/SKILL.md +67 -0
  206. package/dist/runtime/discipline/skills/aria-cognition/aria-reasoning/references/core-principles.md +42 -0
  207. package/dist/runtime/discipline/skills/aria-cognition/aria-repo-audit/SKILL.md +135 -0
  208. package/dist/runtime/discipline/skills/aria-cognition/aria-repo-audit/references/repo-audit-cookbook.md +375 -0
  209. package/dist/runtime/discipline/skills/aria-cognition/aria-research-orchestrator/SKILL.md +138 -0
  210. package/dist/runtime/discipline/skills/aria-cognition/aria-research-orchestrator/references/research-patterns.md +270 -0
  211. package/dist/runtime/discipline/skills/aria-cognition/aria-retention-engine/SKILL.md +120 -0
  212. package/dist/runtime/discipline/skills/aria-cognition/aria-retention-engine/references/retention-cookbook.md +271 -0
  213. package/dist/runtime/discipline/skills/aria-cognition/aria-revenue-engine/SKILL.md +128 -0
  214. package/dist/runtime/discipline/skills/aria-cognition/aria-revenue-engine/references/revenue-cookbook.md +227 -0
  215. package/dist/runtime/discipline/skills/aria-cognition/aria-senior-code-audit/SKILL.md +233 -0
  216. package/dist/runtime/discipline/skills/aria-cognition/aria-senior-code-audit/references/audit-checklist.md +369 -0
  217. package/dist/runtime/discipline/skills/aria-cognition/aria-senior-code-cookbook/SKILL.md +288 -0
  218. package/dist/runtime/discipline/skills/aria-cognition/aria-senior-code-cookbook/references/engineering-cookbook.md +489 -0
  219. package/dist/runtime/discipline/skills/aria-cognition/aria-soul-principles/SKILL.md +42 -0
  220. package/dist/runtime/discipline/skills/aria-cognition/aria-task-codex-executor/SKILL.md +86 -0
  221. package/dist/runtime/discipline/skills/aria-cognition/aristotle-engine/SKILL.md +42 -0
  222. package/dist/runtime/discipline/skills/aria-cognition/cross-domain-24/SKILL.md +42 -0
  223. package/dist/runtime/discipline/skills/aria-cognition/deepsoul-emotional/SKILL.md +42 -0
  224. package/dist/runtime/discipline/skills/aria-cognition/fitrah-guard/SKILL.md +78 -0
  225. package/dist/runtime/discipline/skills/aria-cognition/ghazali-8lens/SKILL.md +227 -29
  226. package/dist/runtime/discipline/skills/aria-cognition/ghazali-8lens/references/ghazali-8lens-cookbook.md +797 -0
  227. package/dist/runtime/discipline/skills/aria-cognition/ijtihad-novel/SKILL.md +42 -0
  228. package/dist/runtime/discipline/skills/aria-cognition/ilham-intuition/SKILL.md +42 -0
  229. package/dist/runtime/discipline/skills/aria-cognition/never-guess/SKILL.md +77 -0
  230. package/dist/runtime/discipline/skills/aria-cognition/noor-recognition/SKILL.md +45 -0
  231. package/dist/runtime/discipline/skills/aria-cognition/qiyas-analogy/SKILL.md +174 -14
  232. package/dist/runtime/discipline/skills/aria-cognition/ruh-basis/SKILL.md +42 -0
  233. package/dist/runtime/discipline/skills/aria-cognition/tadabbur/SKILL.md +506 -0
  234. package/dist/runtime/discipline/skills/aria-cognition/tadabbur/references/tadabbur-cookbook.md +921 -0
  235. package/dist/runtime/discipline/skills/aria-cognition/tadabbur-ops/SKILL.md +42 -0
  236. package/dist/runtime/discipline/skills/aria-cognition/tafakkur/SKILL.md +104 -0
  237. package/dist/runtime/doctrine_trigger_map.json +236 -25
  238. package/dist/runtime/embedded-public-key.mjs +27 -0
  239. package/dist/runtime/gated-ledger.mjs +41 -14
  240. package/dist/runtime/harness-daemon.mjs +85 -10
  241. package/dist/runtime/hive-wal-publisher.mjs +292 -0
  242. package/dist/runtime/hooks/README.md +58 -0
  243. package/dist/runtime/hooks/aria-agent-handoff.mjs +147 -2
  244. package/dist/runtime/hooks/aria-agent-ledger-merge.mjs +31 -7
  245. package/dist/runtime/hooks/aria-architect-fallback.mjs +10 -2
  246. package/dist/runtime/hooks/aria-claim-evidence-stop-gate.mjs +240 -0
  247. package/dist/runtime/hooks/aria-cognition-substrate-binding.mjs +84 -10
  248. package/dist/runtime/hooks/aria-first-class-coach.mjs +305 -10
  249. package/dist/runtime/hooks/aria-harness-via-sdk.mjs +93 -16
  250. package/dist/runtime/hooks/aria-import-resolution-gate.mjs +106 -20
  251. package/dist/runtime/hooks/aria-outcome-record.mjs +56 -20
  252. package/dist/runtime/hooks/aria-pre-emit-autoload.mjs +1809 -0
  253. package/dist/runtime/hooks/aria-pre-emit-autoload.mjs.before-orchestration-redesign +1400 -0
  254. package/dist/runtime/hooks/aria-pre-emit-dryrun.mjs +22 -3
  255. package/dist/runtime/hooks/aria-pre-text-gate.mjs +11 -2
  256. package/dist/runtime/hooks/aria-pre-tool-gate.mjs +516 -92
  257. package/dist/runtime/hooks/aria-pre-tool-use.mjs +70 -6
  258. package/dist/runtime/hooks/aria-preprompt-consult.mjs +23 -4
  259. package/dist/runtime/hooks/aria-repo-doctrine-gate.mjs +29 -3
  260. package/dist/runtime/hooks/aria-stop-gate.mjs +585 -76
  261. package/dist/runtime/hooks/aria-trigger-autolearn.mjs +17 -3
  262. package/dist/runtime/hooks/aria-universal-turn-packet.mjs +1165 -0
  263. package/dist/runtime/hooks/aria-userprompt-abandon-detect.mjs +9 -1
  264. package/dist/runtime/hooks/canonical-settings-block.json +172 -0
  265. package/dist/runtime/hooks/codex-native/aria-harness-ticker-sidecar.mjs +92 -0
  266. package/dist/runtime/hooks/codex-native/aria-hive-wal-consumer.mjs +86 -0
  267. package/dist/runtime/hooks/codex-native/aria-live-ticker.mjs +38 -0
  268. package/dist/runtime/hooks/codex-native/aria-post-tool-use.mjs +236 -0
  269. package/dist/runtime/hooks/codex-native/aria-pre-tool-use.mjs +362 -0
  270. package/dist/runtime/hooks/codex-native/aria-stop.mjs +691 -0
  271. package/dist/runtime/hooks/codex-native/aria-userprompt-submit.mjs +623 -0
  272. package/dist/runtime/hooks/codex-native/atlas-session-context.mjs +121 -0
  273. package/dist/runtime/hooks/codex-native/lib/evaluate-with-kernel.mjs +257 -0
  274. package/dist/runtime/hooks/codex-native/lib/hive-wal-consumer.mjs +452 -0
  275. package/dist/runtime/hooks/codex-native/lib/kernel/deterministic-cognitive-kernel.mjs +914 -0
  276. package/dist/runtime/hooks/codex-native/lib/project-boundary-cognition.mjs +143 -0
  277. package/dist/runtime/hooks/codex-native/lib/runtime-client.mjs +3567 -0
  278. package/dist/runtime/hooks/codex-native/lib/task-project-ledger.mjs +294 -0
  279. package/dist/runtime/hooks/doctrine_trigger_map.json +236 -25
  280. package/dist/runtime/hooks/doctrine_trigger_map.schema.json +46 -0
  281. package/dist/runtime/hooks/install.sh +84 -0
  282. package/dist/runtime/hooks/lib/action-ledger-core.mjs +269 -0
  283. package/dist/runtime/hooks/lib/aria-gate-ledger.mjs +143 -0
  284. package/dist/runtime/hooks/lib/ast-stub-shape-detector.mjs +107 -0
  285. package/dist/runtime/hooks/lib/atlas-dossier-client.mjs +151 -0
  286. package/dist/runtime/hooks/lib/atlas-orchestrator-postwire.mjs +221 -0
  287. package/dist/runtime/hooks/lib/canonical-lenses.mjs +83 -6
  288. package/dist/runtime/hooks/lib/coach-intent-classifier.mjs +248 -0
  289. package/dist/runtime/hooks/lib/cognitive-block-parser.mjs +111 -0
  290. package/dist/runtime/hooks/lib/doctrine-trigger-map-loader.mjs +137 -0
  291. package/dist/runtime/hooks/lib/domain-output-quality.mjs +132 -3
  292. package/dist/runtime/hooks/lib/empty-catch-scanner.mjs +91 -0
  293. package/dist/runtime/hooks/lib/end-phase-qa-autofire.mjs +426 -0
  294. package/dist/runtime/hooks/lib/evaluate-with-kernel.mjs +133 -0
  295. package/dist/runtime/hooks/lib/first-class-coach.mjs +454 -19
  296. package/dist/runtime/hooks/lib/gate-audit.mjs +12 -2
  297. package/dist/runtime/hooks/lib/gate-loop-state.mjs +11 -2
  298. package/dist/runtime/hooks/lib/goal-contract-quality.mjs +302 -0
  299. package/dist/runtime/hooks/lib/hook-message-window.mjs +101 -9
  300. package/dist/runtime/hooks/lib/invocation-required-verifier.mjs +184 -0
  301. package/dist/runtime/hooks/lib/kernel/deterministic-cognitive-kernel.mjs +906 -0
  302. package/dist/runtime/hooks/lib/obligation-ledger.mjs +147 -0
  303. package/dist/runtime/hooks/lib/orchestration-manifest-extract.mjs +217 -0
  304. package/dist/runtime/hooks/lib/owner-authorizations.mjs +269 -0
  305. package/dist/runtime/hooks/lib/probe-discipline-scanner.mjs +142 -0
  306. package/dist/runtime/hooks/lib/project-boundary-cognition.mjs +143 -0
  307. package/dist/runtime/hooks/lib/recovery-context.mjs +151 -0
  308. package/dist/runtime/hooks/lib/recovery-template-loader.mjs +154 -0
  309. package/dist/runtime/hooks/lib/self-doctrine-check.mjs +321 -0
  310. package/dist/runtime/hooks/lib/sensitive-shape-detector.mjs +64 -0
  311. package/dist/runtime/hooks/lib/skill-autoload-gate-impl.mjs +226 -1
  312. package/dist/runtime/hooks/lib/stop-hook-protocol.mjs +166 -0
  313. package/dist/runtime/hooks/lib/surface-caught.mjs +94 -0
  314. package/dist/runtime/hooks/recovery-templates/force-reauthor.md +67 -0
  315. package/dist/runtime/hooks/recovery-templates/handoff-recovery.md +25 -0
  316. package/dist/runtime/hooks/scripts/check-hard-risk-prefix.mjs +99 -0
  317. package/dist/runtime/hooks/skills/aria-conversational-doctrine-discipline/SKILL.md +101 -0
  318. package/dist/runtime/hooks/test-aria-preturn-memory-gate.mjs +2 -2
  319. package/dist/runtime/hooks/test-tier-lens-labeling.mjs +14 -3
  320. package/dist/runtime/lib/evaluate-with-kernel.mjs +133 -0
  321. package/dist/runtime/lib/kernel/deterministic-cognitive-kernel.mjs +906 -0
  322. package/dist/runtime/local-phase.mjs +10 -5
  323. package/dist/runtime/manifest.json +8 -8
  324. package/dist/runtime/packet-verifier.mjs +166 -0
  325. package/dist/runtime/provider-proxy.mjs +13 -0
  326. package/dist/runtime/quality-enforcer.mjs +40 -23
  327. package/dist/runtime/runtime-rails/registry.mjs +252 -0
  328. package/dist/runtime/sdk/BUNDLED.json +2 -2
  329. package/dist/runtime/sdk/index.d.ts +119 -4
  330. package/dist/runtime/sdk/index.js +138 -12
  331. package/dist/runtime/sdk/index.js.map +1 -1
  332. package/dist/runtime/service.mjs +8036 -764
  333. package/dist/runtime/sub-agent-enforcer.mjs +201 -0
  334. package/dist/runtime/task-project-ledger.mjs +5 -1
  335. package/dist/sdk/BUNDLED.json +2 -2
  336. package/dist/sdk/index.d.ts +119 -4
  337. package/dist/sdk/index.js +138 -12
  338. package/dist/sdk/index.js.map +1 -1
  339. package/hooks/README.md +58 -0
  340. package/hooks/aria-agent-handoff.mjs +147 -2
  341. package/hooks/aria-agent-ledger-merge.mjs +31 -7
  342. package/hooks/aria-architect-fallback.mjs +10 -2
  343. package/hooks/aria-claim-evidence-stop-gate.mjs +240 -0
  344. package/hooks/aria-cognition-substrate-binding.mjs +84 -10
  345. package/hooks/aria-first-class-coach.mjs +305 -10
  346. package/hooks/aria-harness-via-sdk.mjs +93 -16
  347. package/hooks/aria-import-resolution-gate.mjs +106 -20
  348. package/hooks/aria-outcome-record.mjs +56 -20
  349. package/hooks/aria-pre-emit-autoload.mjs +1809 -0
  350. package/hooks/aria-pre-emit-autoload.mjs.before-orchestration-redesign +1400 -0
  351. package/hooks/aria-pre-emit-dryrun.mjs +22 -3
  352. package/hooks/aria-pre-text-gate.mjs +11 -2
  353. package/hooks/aria-pre-tool-gate.mjs +516 -92
  354. package/hooks/aria-pre-tool-use.mjs +70 -6
  355. package/hooks/aria-preprompt-consult.mjs +23 -4
  356. package/hooks/aria-repo-doctrine-gate.mjs +29 -3
  357. package/hooks/aria-stop-gate.mjs +585 -76
  358. package/hooks/aria-trigger-autolearn.mjs +17 -3
  359. package/hooks/aria-universal-turn-packet.mjs +1165 -0
  360. package/hooks/aria-userprompt-abandon-detect.mjs +9 -1
  361. package/hooks/canonical-settings-block.json +172 -0
  362. package/hooks/codex-native/aria-harness-ticker-sidecar.mjs +92 -0
  363. package/hooks/codex-native/aria-hive-wal-consumer.mjs +86 -0
  364. package/hooks/codex-native/aria-live-ticker.mjs +38 -0
  365. package/hooks/codex-native/aria-post-tool-use.mjs +236 -0
  366. package/hooks/codex-native/aria-pre-tool-use.mjs +362 -0
  367. package/hooks/codex-native/aria-stop.mjs +691 -0
  368. package/hooks/codex-native/aria-userprompt-submit.mjs +623 -0
  369. package/hooks/codex-native/atlas-session-context.mjs +121 -0
  370. package/hooks/codex-native/lib/evaluate-with-kernel.mjs +257 -0
  371. package/hooks/codex-native/lib/hive-wal-consumer.mjs +452 -0
  372. package/hooks/codex-native/lib/kernel/deterministic-cognitive-kernel.mjs +914 -0
  373. package/hooks/codex-native/lib/project-boundary-cognition.mjs +143 -0
  374. package/hooks/codex-native/lib/runtime-client.mjs +3567 -0
  375. package/hooks/codex-native/lib/task-project-ledger.mjs +294 -0
  376. package/hooks/doctrine_trigger_map.json +236 -25
  377. package/hooks/doctrine_trigger_map.schema.json +46 -0
  378. package/hooks/install.sh +84 -0
  379. package/hooks/lib/action-ledger-core.mjs +269 -0
  380. package/hooks/lib/aria-gate-ledger.mjs +143 -0
  381. package/hooks/lib/ast-stub-shape-detector.mjs +107 -0
  382. package/hooks/lib/atlas-dossier-client.mjs +151 -0
  383. package/hooks/lib/atlas-orchestrator-postwire.mjs +221 -0
  384. package/hooks/lib/canonical-lenses.mjs +83 -6
  385. package/hooks/lib/coach-intent-classifier.mjs +248 -0
  386. package/hooks/lib/cognitive-block-parser.mjs +111 -0
  387. package/hooks/lib/doctrine-trigger-map-loader.mjs +137 -0
  388. package/hooks/lib/domain-output-quality.mjs +132 -3
  389. package/hooks/lib/empty-catch-scanner.mjs +91 -0
  390. package/hooks/lib/end-phase-qa-autofire.mjs +426 -0
  391. package/hooks/lib/evaluate-with-kernel.mjs +133 -0
  392. package/hooks/lib/first-class-coach.mjs +454 -19
  393. package/hooks/lib/gate-audit.mjs +12 -2
  394. package/hooks/lib/gate-loop-state.mjs +11 -2
  395. package/hooks/lib/goal-contract-quality.mjs +302 -0
  396. package/hooks/lib/hook-message-window.mjs +101 -9
  397. package/hooks/lib/invocation-required-verifier.mjs +184 -0
  398. package/hooks/lib/kernel/deterministic-cognitive-kernel.mjs +906 -0
  399. package/hooks/lib/obligation-ledger.mjs +147 -0
  400. package/hooks/lib/orchestration-manifest-extract.mjs +217 -0
  401. package/hooks/lib/owner-authorizations.mjs +269 -0
  402. package/hooks/lib/probe-discipline-scanner.mjs +142 -0
  403. package/hooks/lib/project-boundary-cognition.mjs +143 -0
  404. package/hooks/lib/recovery-context.mjs +151 -0
  405. package/hooks/lib/recovery-template-loader.mjs +154 -0
  406. package/hooks/lib/self-doctrine-check.mjs +321 -0
  407. package/hooks/lib/sensitive-shape-detector.mjs +64 -0
  408. package/hooks/lib/skill-autoload-gate-impl.mjs +226 -1
  409. package/hooks/lib/stop-hook-protocol.mjs +166 -0
  410. package/hooks/lib/surface-caught.mjs +94 -0
  411. package/hooks/recovery-templates/force-reauthor.md +67 -0
  412. package/hooks/recovery-templates/handoff-recovery.md +25 -0
  413. package/hooks/scripts/check-hard-risk-prefix.mjs +99 -0
  414. package/hooks/skills/aria-conversational-doctrine-discipline/SKILL.md +101 -0
  415. package/hooks/test-aria-preturn-memory-gate.mjs +2 -2
  416. package/hooks/test-tier-lens-labeling.mjs +14 -3
  417. package/opencode-plugins/harness-context/index.js +39 -6
  418. package/opencode-plugins/harness-context/task-project-ledger.mjs +5 -1
  419. package/opencode-plugins/harness-gate/index.js +36 -0
  420. package/opencode-plugins/harness-gate/lib/atlas-dossier-client.js +1 -0
  421. package/opencode-plugins/harness-gate/lib/recovery-grants.js +79 -0
  422. package/opencode-plugins/harness-outcome/index.js +12 -0
  423. package/opencode-plugins/harness-stop/index.js +97 -2
  424. package/opencode-plugins/harness-stop/lib/atlas-dossier-client.js +1 -0
  425. package/opencode-plugins/harness-stop/lib/domain-output-quality.js +15 -2
  426. package/opencode-plugins/lib/coach.js +148 -0
  427. package/package.json +71 -5
  428. package/runtime-src/coach-kernel.mjs +144 -7
  429. package/runtime-src/codex-bridge.mjs +254 -8
  430. package/runtime-src/embedded-public-key.mjs +27 -0
  431. package/runtime-src/gated-ledger.mjs +41 -14
  432. package/runtime-src/harness-daemon.mjs +85 -10
  433. package/runtime-src/hive-wal-publisher.mjs +292 -0
  434. package/runtime-src/lib/evaluate-with-kernel.mjs +133 -0
  435. package/runtime-src/lib/kernel/deterministic-cognitive-kernel.mjs +906 -0
  436. package/runtime-src/local-phase.mjs +10 -5
  437. package/runtime-src/packet-verifier.mjs +166 -0
  438. package/runtime-src/provider-proxy.mjs +13 -0
  439. package/runtime-src/quality-enforcer.mjs +40 -23
  440. package/runtime-src/runtime-rails/registry.mjs +252 -0
  441. package/runtime-src/service.mjs +8036 -764
  442. package/runtime-src/sub-agent-enforcer.mjs +201 -0
  443. package/scripts/aria-ledger-append.mjs +337 -0
  444. package/scripts/aria-task-cheap-worker-dispatch.mjs +234 -0
  445. package/scripts/audit-of-audit-prior-tasks.mjs +194 -0
  446. package/scripts/audit-of-audit-this-turn.mjs +116 -0
  447. package/scripts/bundle-sdk.mjs +31 -5
  448. package/scripts/check-cli-wrapper-provider-contract.mjs +160 -0
  449. package/scripts/check-client-compatibility.mjs +15 -5
  450. package/scripts/check-client-smoke.mjs +297 -0
  451. package/scripts/check-codex-orchestrator-adoption.mjs +150 -0
  452. package/scripts/check-glm-env-wired.mjs +131 -0
  453. package/scripts/check-hive-local-storage-contract.mjs +91 -0
  454. package/scripts/check-hook-mirror.mjs +150 -0
  455. package/scripts/check-install-sh-drift.mjs +152 -0
  456. package/scripts/check-kernel-sync.mjs +101 -0
  457. package/scripts/check-package-artifact.mjs +152 -0
  458. package/scripts/check-registry-mirror.mjs +71 -0
  459. package/scripts/drain-owner-airtable-sync-queue.mjs +287 -0
  460. package/scripts/export-owner-status-sheets.mjs +589 -0
  461. package/scripts/live-sidecar-receipt-canary.mjs +347 -0
  462. package/scripts/qiyas-tadabbur-model-matrix.mjs +970 -0
  463. package/scripts/quality-ab-live-provider.mjs +913 -0
  464. package/scripts/self-test-action-ledger-core.mjs +190 -0
  465. package/scripts/self-test-approval-receipt-binding.mjs +122 -0
  466. package/scripts/self-test-autofire-quality-output.mjs +110 -0
  467. package/scripts/self-test-claude-code-action-ledger.mjs +132 -0
  468. package/scripts/self-test-claude-code-mechanical-autofire-hive.mjs +138 -0
  469. package/scripts/self-test-claude-code-mechanical-autofire.mjs +234 -0
  470. package/scripts/self-test-codebase-awareness-atlas-delta.mjs +159 -0
  471. package/scripts/self-test-codebase-awareness-delta-ingest.mjs +179 -0
  472. package/scripts/self-test-codex-live-hook-parity.mjs +84 -0
  473. package/scripts/self-test-codex-native-action-ledger.mjs +167 -0
  474. package/scripts/self-test-codex-native-hook-json-contract.mjs +74 -0
  475. package/scripts/self-test-codex-orchestrator-continuity.mjs +113 -0
  476. package/scripts/self-test-codex-readable-recovery.mjs +94 -0
  477. package/scripts/self-test-codex-self-harness.mjs +538 -0
  478. package/scripts/self-test-compiled-workunit.mjs +214 -0
  479. package/scripts/self-test-continuation-output-smoke.mjs +101 -0
  480. package/scripts/self-test-cross-cli-fleet-ticker.mjs +85 -0
  481. package/scripts/self-test-cross-cli-hive-adoption.mjs +125 -0
  482. package/scripts/self-test-cross-cli-hive-learning.mjs +146 -0
  483. package/scripts/self-test-cross-phase-tool-failure.mjs +110 -0
  484. package/scripts/self-test-cross-surface-action-ledger.mjs +149 -0
  485. package/scripts/self-test-end-of-phase-qa-court.mjs +616 -0
  486. package/scripts/self-test-evaluate-with-kernel.mjs +111 -0
  487. package/scripts/self-test-first-class-output-delta-proof.mjs +307 -0
  488. package/scripts/self-test-goal-contract-output-qa.mjs +73 -0
  489. package/scripts/self-test-goal-contract.mjs +35 -0
  490. package/scripts/self-test-governed-adapters.mjs +105 -0
  491. package/scripts/self-test-governed-surface-runner.mjs +198 -0
  492. package/scripts/self-test-harness-gates.mjs +15 -12
  493. package/scripts/self-test-harness-ticker-sidecar.mjs +153 -0
  494. package/scripts/self-test-hive-org-kernel.mjs +233 -0
  495. package/scripts/self-test-hive-session-coordination.mjs +156 -0
  496. package/scripts/self-test-hive-wal-consumer.mjs +111 -0
  497. package/scripts/self-test-kernel-a3-a4-selection.mjs +179 -0
  498. package/scripts/self-test-ledger-append.mjs +175 -0
  499. package/scripts/self-test-live-codex-posttool-packet-smoke.mjs +111 -0
  500. package/scripts/self-test-live-codex-pretool-packet-smoke.mjs +101 -0
  501. package/scripts/self-test-live-codex-stop-qa-kernel-smoke.mjs +43 -0
  502. package/scripts/self-test-live-wrapper-substrate-inventory.mjs +149 -0
  503. package/scripts/self-test-local-main-sync-script.mjs +47 -0
  504. package/scripts/self-test-mechanical-autofire-resolver.mjs +296 -0
  505. package/scripts/self-test-no-consult-cognitive-skills-output.mjs +135 -0
  506. package/scripts/self-test-owner-airtable-sync-queue.mjs +196 -0
  507. package/scripts/self-test-owner-airtable-sync.mjs +181 -0
  508. package/scripts/self-test-owner-sheets-action-ledger.mjs +100 -0
  509. package/scripts/self-test-production-preflight.mjs +78 -0
  510. package/scripts/self-test-project-boundary-cognition.mjs +79 -0
  511. package/scripts/self-test-qa-exec-kernel.mjs +34 -0
  512. package/scripts/self-test-qa-recovery-learning-loop.mjs +113 -0
  513. package/scripts/self-test-qiyas-label-alignment.mjs +94 -0
  514. package/scripts/self-test-recovery-context.mjs +110 -0
  515. package/scripts/self-test-repo-guard.mjs +10 -0
  516. package/scripts/self-test-runtime-health-self-heal.mjs +161 -0
  517. package/scripts/self-test-runtime-postcondition.mjs +70 -0
  518. package/scripts/self-test-soul-precommit-hook.mjs +39 -0
  519. package/scripts/self-test-stop-gate-kernel-guards.mjs +185 -0
  520. package/scripts/self-test-stop-gate.mjs +128 -0
  521. package/scripts/self-test-substrate-kernel-execution-receipt.mjs +130 -0
  522. package/scripts/self-test-substrate-open-skill-floor.mjs +87 -0
  523. package/scripts/self-test-substrate-output-quality-eval.mjs +171 -0
  524. package/scripts/self-test-task-closeout-drift.mjs +97 -0
  525. package/scripts/self-test-task-project-ledger-readiness.mjs +43 -0
  526. package/scripts/self-test-task-runner-phase-consumer.mjs +134 -0
  527. package/scripts/self-test-task-worker-lane.mjs +256 -0
  528. package/scripts/self-test-turn-substrate-qa-kernel.mjs +188 -0
  529. package/scripts/self-test-universal-action-capture.mjs +153 -0
  530. package/scripts/self-test-universal-turn-packet-entrypoints.mjs +252 -0
  531. package/scripts/self-test-universal-turn-packet.mjs +320 -0
  532. package/scripts/session-quality-backfill.mjs +253 -0
  533. package/scripts/smoke-autofire-100-prompts.mjs +481 -0
  534. package/scripts/sync-local-main-on-task-complete.mjs +278 -0
  535. package/scripts/sync-owner-status-airtable.mjs +1158 -0
  536. package/scripts/validate-skill-prompts.mjs +12 -1
  537. package/scripts/verify-codex-native-mirror.mjs +262 -0
  538. package/skills/34-frameworks-unified/SKILL.md +42 -0
  539. package/skills/api-design/SKILL.md +123 -0
  540. package/skills/architecture-decision/SKILL.md +105 -0
  541. package/skills/aria-aristotle-cognitives/SKILL.md +128 -0
  542. package/skills/aria-aristotle-intra-phase/SKILL.md +99 -0
  543. package/skills/aria-aristotle-post-phase/SKILL.md +116 -0
  544. package/skills/aria-aristotle-pre-phase/SKILL.md +117 -0
  545. package/skills/aria-axioms-first-principles/SKILL.md +202 -0
  546. package/skills/aria-axioms-first-principles/agents/openai.yaml +4 -0
  547. package/skills/aria-axioms-first-principles/references/source-map.md +130 -0
  548. package/skills/aria-chat/SKILL.md +84 -0
  549. package/skills/aria-chat/scripts/aria-chat.sh +57 -0
  550. package/skills/aria-cognition/34-frameworks-unified/SKILL.md +42 -0
  551. package/skills/aria-cognition/aria-aristotle-cognitives/SKILL.md +128 -0
  552. package/skills/aria-cognition/aria-aristotle-intra-phase/SKILL.md +99 -0
  553. package/skills/aria-cognition/aria-aristotle-post-phase/SKILL.md +118 -0
  554. package/skills/aria-cognition/aria-aristotle-pre-phase/SKILL.md +117 -0
  555. package/skills/aria-cognition/aria-axioms-first-principles/SKILL.md +202 -0
  556. package/skills/aria-cognition/aria-axioms-first-principles/agents/openai.yaml +4 -0
  557. package/skills/aria-cognition/aria-axioms-first-principles/references/source-map.md +130 -0
  558. package/skills/aria-cognition/aria-backend-architect/SKILL.md +124 -0
  559. package/skills/aria-cognition/aria-backend-architect/references/backend-cookbook.md +417 -0
  560. package/skills/aria-cognition/aria-business-audit/SKILL.md +133 -0
  561. package/skills/aria-cognition/aria-business-audit/references/audit-cookbook.md +247 -0
  562. package/skills/aria-cognition/aria-business-frame/SKILL.md +138 -0
  563. package/skills/aria-cognition/aria-business-frame/references/business-cookbook.md +154 -0
  564. package/skills/aria-cognition/aria-chat/SKILL.md +84 -0
  565. package/skills/aria-cognition/aria-chat/scripts/aria-chat.sh +57 -0
  566. package/skills/aria-cognition/aria-cognition-autofire/SKILL.md +137 -0
  567. package/skills/aria-cognition/aria-cognition-batch/SKILL.md +264 -0
  568. package/skills/aria-cognition/aria-decision-mizan/SKILL.md +136 -0
  569. package/skills/aria-cognition/aria-decision-mizan/references/decision-frameworks.md +287 -0
  570. package/skills/aria-cognition/aria-first-class-operating-contract/SKILL.md +104 -0
  571. package/skills/aria-cognition/aria-frontend-architect/SKILL.md +123 -0
  572. package/skills/aria-cognition/aria-frontend-architect/references/frontend-cookbook.md +358 -0
  573. package/skills/aria-cognition/aria-fullstack-orchestrator/SKILL.md +127 -0
  574. package/skills/aria-cognition/aria-fullstack-orchestrator/references/fullstack-cookbook.md +383 -0
  575. package/skills/aria-cognition/aria-gtm-architect/SKILL.md +126 -0
  576. package/skills/aria-cognition/aria-gtm-architect/references/gtm-cookbook.md +235 -0
  577. package/skills/aria-cognition/aria-harness-deploy/SKILL.md +145 -0
  578. package/skills/aria-cognition/aria-harness-no-stripping/SKILL.md +135 -0
  579. package/skills/aria-cognition/aria-harness-onboarding/SKILL.md +130 -0
  580. package/skills/aria-cognition/aria-harness-output-discipline/SKILL.md +120 -0
  581. package/skills/aria-cognition/aria-harness-substrate-binding/SKILL.md +139 -0
  582. package/skills/aria-cognition/aria-http-harness-client/SKILL.md +85 -0
  583. package/skills/aria-cognition/aria-http-harness-client/scripts/smoke.mjs +47 -0
  584. package/skills/aria-cognition/aria-k8s-deploy/SKILL.md +174 -0
  585. package/skills/aria-cognition/aria-k8s-deploy/agents/openai.yaml +3 -0
  586. package/skills/aria-cognition/aria-ladduniframe/SKILL.md +60 -0
  587. package/skills/aria-cognition/aria-ledger-fleet-execution/SKILL.md +126 -0
  588. package/skills/aria-cognition/aria-live-ops/SKILL.md +54 -0
  589. package/skills/aria-cognition/aria-mac-ssh-ops/SKILL.md +100 -0
  590. package/skills/aria-cognition/aria-memory-index/SKILL.md +42 -0
  591. package/skills/aria-cognition/aria-noor-cognitives/SKILL.md +120 -0
  592. package/skills/aria-cognition/aria-ops/SKILL.md +60 -0
  593. package/skills/aria-cognition/aria-ops/references/live-endpoints.md +59 -0
  594. package/skills/aria-cognition/aria-quality-audit/SKILL.md +133 -0
  595. package/skills/aria-cognition/aria-readable-output/SKILL.md +239 -0
  596. package/skills/aria-cognition/aria-readable-output/references/layout-cookbook.md +366 -0
  597. package/skills/aria-cognition/aria-reasoning/SKILL.md +67 -0
  598. package/skills/aria-cognition/aria-reasoning/references/core-principles.md +42 -0
  599. package/skills/aria-cognition/aria-repo-audit/SKILL.md +135 -0
  600. package/skills/aria-cognition/aria-repo-audit/references/repo-audit-cookbook.md +375 -0
  601. package/skills/aria-cognition/aria-research-orchestrator/SKILL.md +138 -0
  602. package/skills/aria-cognition/aria-research-orchestrator/references/research-patterns.md +270 -0
  603. package/skills/aria-cognition/aria-retention-engine/SKILL.md +120 -0
  604. package/skills/aria-cognition/aria-retention-engine/references/retention-cookbook.md +271 -0
  605. package/skills/aria-cognition/aria-revenue-engine/SKILL.md +128 -0
  606. package/skills/aria-cognition/aria-revenue-engine/references/revenue-cookbook.md +227 -0
  607. package/skills/aria-cognition/aria-senior-code-audit/SKILL.md +233 -0
  608. package/skills/aria-cognition/aria-senior-code-audit/references/audit-checklist.md +369 -0
  609. package/skills/aria-cognition/aria-senior-code-cookbook/SKILL.md +288 -0
  610. package/skills/aria-cognition/aria-senior-code-cookbook/references/engineering-cookbook.md +489 -0
  611. package/skills/aria-cognition/aria-soul-principles/SKILL.md +42 -0
  612. package/skills/aria-cognition/aria-task-codex-executor/SKILL.md +86 -0
  613. package/skills/aria-cognition/aristotle-engine/SKILL.md +42 -0
  614. package/skills/aria-cognition/cross-domain-24/SKILL.md +42 -0
  615. package/skills/aria-cognition/deepsoul-emotional/SKILL.md +42 -0
  616. package/skills/aria-cognition/fitrah-guard/SKILL.md +78 -0
  617. package/skills/aria-cognition/ghazali-8lens/SKILL.md +227 -29
  618. package/skills/aria-cognition/ghazali-8lens/references/ghazali-8lens-cookbook.md +797 -0
  619. package/skills/aria-cognition/ijtihad-novel/SKILL.md +42 -0
  620. package/skills/aria-cognition/ilham-intuition/SKILL.md +42 -0
  621. package/skills/aria-cognition/never-guess/SKILL.md +77 -0
  622. package/skills/aria-cognition/noor-recognition/SKILL.md +45 -0
  623. package/skills/aria-cognition/qiyas-analogy/SKILL.md +174 -14
  624. package/skills/aria-cognition/ruh-basis/SKILL.md +42 -0
  625. package/skills/aria-cognition/tadabbur/SKILL.md +506 -0
  626. package/skills/aria-cognition/tadabbur/references/tadabbur-cookbook.md +921 -0
  627. package/skills/aria-cognition/tadabbur-ops/SKILL.md +42 -0
  628. package/skills/aria-cognition/tafakkur/SKILL.md +104 -0
  629. package/skills/aria-cognition-autofire/SKILL.md +109 -0
  630. package/skills/aria-cognition-batch/SKILL.md +264 -0
  631. package/skills/aria-conversational-doctrine-discipline/SKILL.md +125 -0
  632. package/skills/aria-essence/SKILL.md +81 -0
  633. package/skills/aria-essence/references/domain-matrix.md +80 -0
  634. package/skills/aria-essence/references/evolution-loop.md +30 -0
  635. package/skills/aria-essence/references/readable-cognition.md +27 -0
  636. package/skills/aria-first-class-operating-contract/SKILL.md +104 -0
  637. package/skills/aria-forge-guardrails/SKILL.md +53 -0
  638. package/skills/aria-forge-guardrails/references/checklist.md +31 -0
  639. package/skills/aria-harness-deploy/SKILL.md +145 -0
  640. package/skills/aria-harness-no-stripping/SKILL.md +135 -0
  641. package/skills/aria-harness-onboarding/SKILL.md +130 -0
  642. package/skills/aria-harness-output-discipline/SKILL.md +120 -0
  643. package/skills/aria-harness-substrate-binding/SKILL.md +139 -0
  644. package/skills/aria-http-harness-client/SKILL.md +85 -0
  645. package/skills/aria-http-harness-client/scripts/smoke.mjs +47 -0
  646. package/skills/aria-k8s-deploy/SKILL.md +174 -0
  647. package/skills/aria-k8s-deploy/agents/openai.yaml +3 -0
  648. package/skills/aria-ladduniframe/SKILL.md +60 -0
  649. package/skills/aria-ledger-fleet-execution/SKILL.md +126 -0
  650. package/skills/aria-live-ops/SKILL.md +54 -0
  651. package/skills/aria-mac-ssh-ops/SKILL.md +100 -0
  652. package/skills/aria-memory-index/SKILL.md +42 -0
  653. package/skills/aria-noor-cognitives/SKILL.md +120 -0
  654. package/skills/aria-ops/SKILL.md +60 -0
  655. package/skills/aria-ops/references/live-endpoints.md +59 -0
  656. package/skills/aria-quality-audit/SKILL.md +133 -0
  657. package/skills/aria-reasoning/SKILL.md +67 -0
  658. package/skills/aria-reasoning/references/core-principles.md +42 -0
  659. package/skills/aria-repo-doctrine/SKILL.md +57 -0
  660. package/skills/aria-soul-principles/SKILL.md +42 -0
  661. package/skills/aria-task-codex-executor/SKILL.md +86 -0
  662. package/skills/aristotle-engine/SKILL.md +42 -0
  663. package/skills/ci-cd-pipeline/SKILL.md +116 -0
  664. package/skills/code-review/SKILL.md +131 -0
  665. package/skills/cross-domain-24/SKILL.md +42 -0
  666. package/skills/database-design/SKILL.md +124 -0
  667. package/skills/deepsoul-emotional/SKILL.md +42 -0
  668. package/skills/deno-kv-raft-pubsub/SKILL.md +561 -0
  669. package/skills/deno-kv-raft-pubsub/reference/maelstrom-integration.md +393 -0
  670. package/skills/deno-kv-raft-pubsub/reference/pubsub-api.md +376 -0
  671. package/skills/deno-kv-raft-pubsub/reference/raft-spec.md +402 -0
  672. package/skills/deno-kv-raft-pubsub/reference/state-machine.md +182 -0
  673. package/skills/error-handling/SKILL.md +159 -0
  674. package/skills/firecrawl/SKILL.md +165 -0
  675. package/skills/firecrawl/rules/install.md +82 -0
  676. package/skills/firecrawl/rules/security.md +26 -0
  677. package/skills/firecrawl-agent/SKILL.md +86 -0
  678. package/skills/firecrawl-build-interact/SKILL.md +96 -0
  679. package/skills/firecrawl-build-onboarding/SKILL.md +131 -0
  680. package/skills/firecrawl-build-onboarding/references/auth-flow.md +39 -0
  681. package/skills/firecrawl-build-onboarding/references/project-setup.md +20 -0
  682. package/skills/firecrawl-build-onboarding/references/sdk-installation.md +17 -0
  683. package/skills/firecrawl-build-scrape/SKILL.md +97 -0
  684. package/skills/firecrawl-build-search/SKILL.md +97 -0
  685. package/skills/firecrawl-clone/SKILL.md +419 -0
  686. package/skills/firecrawl-crawl/SKILL.md +87 -0
  687. package/skills/firecrawl-download/SKILL.md +98 -0
  688. package/skills/firecrawl-interact/SKILL.md +112 -0
  689. package/skills/firecrawl-map/SKILL.md +79 -0
  690. package/skills/firecrawl-scrape/SKILL.md +97 -0
  691. package/skills/firecrawl-search/SKILL.md +88 -0
  692. package/skills/fitrah-guard/SKILL.md +78 -0
  693. package/skills/forge-quality-rules/SKILL.md +61 -0
  694. package/skills/ghazali-8lens/SKILL.md +56 -0
  695. package/skills/ijtihad-novel/SKILL.md +42 -0
  696. package/skills/ilham-intuition/SKILL.md +42 -0
  697. package/skills/imagegen/LICENSE.txt +201 -0
  698. package/skills/imagegen/SKILL.md +374 -0
  699. package/skills/imagegen/agents/openai.yaml +6 -0
  700. package/skills/imagegen/assets/imagegen-small.svg +5 -0
  701. package/skills/imagegen/assets/imagegen.png +0 -0
  702. package/skills/imagegen/references/cli.md +242 -0
  703. package/skills/imagegen/references/codex-network.md +33 -0
  704. package/skills/imagegen/references/image-api.md +90 -0
  705. package/skills/imagegen/references/prompting.md +118 -0
  706. package/skills/imagegen/references/sample-prompts.md +433 -0
  707. package/skills/imagegen/scripts/image_gen.py +995 -0
  708. package/skills/imagegen/scripts/remove_chroma_key.py +440 -0
  709. package/skills/istiqra-induction/SKILL.md +44 -0
  710. package/skills/ladunni-22/SKILL.md +53 -0
  711. package/skills/mizan/SKILL.md +90 -0
  712. package/skills/nadia/SKILL.md +56 -0
  713. package/skills/nadia-psi/SKILL.md +56 -0
  714. package/skills/never-guess/SKILL.md +75 -0
  715. package/skills/noor-recognition/SKILL.md +45 -0
  716. package/skills/observability/SKILL.md +133 -0
  717. package/skills/openai-docs/LICENSE.txt +201 -0
  718. package/skills/openai-docs/SKILL.md +100 -0
  719. package/skills/openai-docs/agents/openai.yaml +14 -0
  720. package/skills/openai-docs/assets/openai-small.svg +3 -0
  721. package/skills/openai-docs/assets/openai.png +0 -0
  722. package/skills/openai-docs/references/latest-model.md +37 -0
  723. package/skills/openai-docs/references/prompting-guide.md +244 -0
  724. package/skills/openai-docs/references/upgrade-guide.md +181 -0
  725. package/skills/openai-docs/scripts/resolve-latest-model-info.js +147 -0
  726. package/skills/pdf/LICENSE.txt +201 -0
  727. package/skills/pdf/SKILL.md +85 -0
  728. package/skills/pdf/agents/openai.yaml +5 -0
  729. package/skills/pdf/assets/pdf.png +0 -0
  730. package/skills/playwright/LICENSE.txt +201 -0
  731. package/skills/playwright/NOTICE.txt +14 -0
  732. package/skills/playwright/SKILL.md +165 -0
  733. package/skills/playwright/agents/openai.yaml +6 -0
  734. package/skills/playwright/assets/playwright-small.svg +3 -0
  735. package/skills/playwright/assets/playwright.png +0 -0
  736. package/skills/playwright/references/cli.md +116 -0
  737. package/skills/playwright/references/workflows.md +95 -0
  738. package/skills/playwright/scripts/playwright_cli.sh +25 -0
  739. package/skills/plugin-creator/SKILL.md +178 -0
  740. package/skills/plugin-creator/agents/openai.yaml +6 -0
  741. package/skills/plugin-creator/assets/plugin-creator-small.svg +3 -0
  742. package/skills/plugin-creator/assets/plugin-creator.png +0 -0
  743. package/skills/plugin-creator/references/plugin-json-spec.md +170 -0
  744. package/skills/plugin-creator/scripts/create_basic_plugin.py +301 -0
  745. package/skills/predictor/SKILL.md +43 -0
  746. package/skills/qiyas-analogy/SKILL.md +204 -0
  747. package/skills/refactoring/SKILL.md +137 -0
  748. package/skills/ruh-basis/SKILL.md +42 -0
  749. package/skills/security-review/SKILL.md +129 -0
  750. package/skills/skill-creator/SKILL.md +434 -0
  751. package/skills/skill-creator/agents/openai.yaml +5 -0
  752. package/skills/skill-creator/assets/skill-creator-small.svg +3 -0
  753. package/skills/skill-creator/assets/skill-creator.png +0 -0
  754. package/skills/skill-creator/license.txt +202 -0
  755. package/skills/skill-creator/references/openai_yaml.md +49 -0
  756. package/skills/skill-creator/scripts/generate_openai_yaml.py +226 -0
  757. package/skills/skill-creator/scripts/init_skill.py +400 -0
  758. package/skills/skill-creator/scripts/quick_validate.py +101 -0
  759. package/skills/skill-installer/LICENSE.txt +202 -0
  760. package/skills/skill-installer/SKILL.md +76 -0
  761. package/skills/skill-installer/agents/openai.yaml +5 -0
  762. package/skills/skill-installer/assets/skill-installer-small.svg +3 -0
  763. package/skills/skill-installer/assets/skill-installer.png +0 -0
  764. package/skills/skill-installer/scripts/github_utils.py +21 -0
  765. package/skills/skill-installer/scripts/install-skill-from-github.py +308 -0
  766. package/skills/skill-installer/scripts/list-skills.py +107 -0
  767. package/skills/skills-and-hooks-reference/SKILL.md +196 -0
  768. package/skills/soul-domains/SKILL.md +43 -0
  769. package/skills/tadabbur/SKILL.md +232 -0
  770. package/skills/tadabbur-ops/SKILL.md +42 -0
  771. package/skills/tafakkur/SKILL.md +104 -0
  772. package/skills/testing-strategy/SKILL.md +122 -0
  773. package/src/action-ledger-core.ts +1054 -0
  774. package/src/chat.ts +5 -6
  775. package/src/codebase-scanner.ts +2 -0
  776. package/src/connectors/claude-code.ts +149 -12
  777. package/src/connectors/codebase-awareness.ts +325 -25
  778. package/src/connectors/codex.ts +1273 -40
  779. package/src/connectors/cursor.ts +8 -0
  780. package/src/connectors/governed-adapter.ts +174 -0
  781. package/src/connectors/opencode.ts +18 -2
  782. package/src/connectors/repo-guard.ts +24 -12
  783. package/src/connectors/runtime.ts +99 -2
  784. package/src/connectors/shell.ts +125 -7
  785. package/src/cross-cli-hive-binding.ts +290 -0
  786. package/src/garden-control-plane.ts +24 -1
  787. package/src/governed-surface-runner.ts +1227 -0
  788. package/src/index.ts +104 -1
  789. package/src/task-runner.ts +3794 -0
  790. package/dist/aria-connector/src/install-hooks.d.ts +0 -18
  791. package/dist/aria-connector/src/install-hooks.d.ts.map +0 -1
  792. package/dist/aria-connector/src/install-hooks.js +0 -224
  793. package/dist/aria-connector/src/install-hooks.js.map +0 -1
  794. package/dist/aria-connector/src/onboarding-wizard.d.ts +0 -5
  795. package/dist/aria-connector/src/onboarding-wizard.d.ts.map +0 -1
  796. package/dist/aria-connector/src/onboarding-wizard.js +0 -188
  797. package/dist/aria-connector/src/onboarding-wizard.js.map +0 -1
  798. package/dist/cli-0.2.38.tgz +0 -0
  799. package/dist/install.sh +0 -13
  800. package/src/__tests__/anthropic-oauth.test.ts +0 -186
  801. package/src/__tests__/auth-commands.test.ts +0 -132
  802. package/src/__tests__/owner-login.test.ts +0 -311
@@ -0,0 +1,1809 @@
1
+ #!/usr/bin/env node
2
+ // aria-pre-emit-autoload.mjs — UserPromptSubmit hook
3
+ //
4
+ // Redesigned 2026-05-09 per Hamza directive: cognition must FRAME the work
5
+ // pre-flight, not be written as ceremony at end-of-turn. Hooks cannot invoke
6
+ // tools, but they CAN inject content as additionalContext. This hook is the
7
+ // pre-flight cognition delivery mechanism: it reads each required skill's
8
+ // BODY (operative rules, workflow, triggers — not just the description) and
9
+ // injects it into the assistant's UserPromptSubmit context BEFORE drafting.
10
+ //
11
+ // Decoupled from the gates-off marker. The gates-off marker disables BLOCKING
12
+ // gates (coach, recovery-executor); it must NOT disable content enrichment,
13
+ // because the very thing that makes the agent's work first-class is having
14
+ // the doctrine content present in context. Use ARIA_AUTOLOAD_DISABLE=1 only
15
+ // for genuine debugging of this hook itself.
16
+ //
17
+ // Triplet honored:
18
+ // - Thinking: classifier picks required skills based on prompt + carry-forward
19
+ // - Implementation: this file reads bodies + injects them
20
+ // - Accountability: sidecar records body excerpts; gate-ledger records byte counts
21
+ //
22
+ // What this hook does on every UserPromptSubmit:
23
+ // 1. Read user prompt from hook event
24
+ // 2. Seed canonical floor substrate; manifest drives per-turn workflow
25
+ // invocation downstream instead of prompt-keyword classification
26
+ // 3. For each required skill, read SKILL.md body (frontmatter stripped,
27
+ // redundant trailing boilerplate stripped, capped at 4KB per skill)
28
+ // 4. Build structured additionalContext: FRAME (skill bodies) +
29
+ // DRIVING-RULES (operative summary) + POST-QA (predicate template) +
30
+ // cognition vocabulary
31
+ // 5. Persist sidecar at ~/.claude/.aria-current-turn-context.json with
32
+ // body excerpts for post-phase QA reference
33
+ // 6. Append gate-ledger entry with byte counts injected
34
+ //
35
+ // What this hook does NOT do:
36
+ // - Does not invoke the Skill tool itself (Claude Code hooks cannot mutate
37
+ // the assistant's tool-call list). Body content arrives as context.
38
+ // - Does not block. Pre-emit is enrichment; pre-tool-gate enforces.
39
+
40
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, statSync, lstatSync, readdirSync } from 'node:fs';
41
+ import { dirname } from 'node:path';
42
+ import { homedir } from 'node:os';
43
+ import { createHash } from 'node:crypto';
44
+ import { parseLoadFirstSection } from './lib/skill-autoload-gate-impl.mjs';
45
+ import { appendGateLedger } from './lib/aria-gate-ledger.mjs';
46
+ import { loadDoctrineTriggerMap } from './lib/doctrine-trigger-map-loader.mjs';
47
+ // A3 + A4 (2026-05-17) — atlas-driven skill selection + end-phase court
48
+ // verdict feedback. Static import is safe because the kernel mirror is
49
+ // guaranteed-present per kernel-sync gate (packages/aria-connector/scripts/
50
+ // check-kernel-sync.mjs). Kernel call itself is wrapped in try/catch with
51
+ // LOUD-stderr fallback per feedback_no_silent_fail_open_in_hooks.md.
52
+ import { compileCognitiveOptions } from './lib/kernel/deterministic-cognitive-kernel.mjs';
53
+ // A5 (2026-05-18) — atlas dossier client. Atlas-as-orchestrator: the daemon's
54
+ // per-file governing_skills knowledge is consulted per turn alongside the
55
+ // kernel's class-anchored selection. File-shape tokens in the prompt are
56
+ // resolved against the dossier index; resulting governing_skills are unioned
57
+ // into the cascade so substrate carries both the kernel floor + atlas's
58
+ // per-target reinforcement. fetchGoverningSkills is already LOUD-on-fail per
59
+ // feedback_no_silent_fail_open_in_hooks.md.
60
+ import { fetchGoverningSkills } from './lib/atlas-dossier-client.mjs';
61
+
62
+ const HOME = homedir();
63
+ const RUNTIME_URL = (process.env.ARIA_RUNTIME_URL || 'http://127.0.0.1:4319').replace(/\/+$/, '');
64
+ const SIDECAR_PATH = `${HOME}/.claude/.aria-current-turn-context.json`;
65
+ const SKILLS_DIR = `${HOME}/.claude/skills`;
66
+ const HOOK_EVENT_NAME = 'UserPromptSubmit';
67
+ const HEADER_PREFIX = '[ARIA_PRE_EMIT_AUTOLOAD]';
68
+
69
+ // Budget caps. Per-skill 4KB keeps each skill's operative section in scope
70
+ // without bloating context. Total 25KB stays well within additionalContext
71
+ // tolerance observed in this surface. Hard file-size cap 50KB rejects
72
+ // abnormally large or attacker-planted SKILL.md files.
73
+ const MAX_BYTES_PER_SKILL = 4096;
74
+ const MAX_BYTES_TOTAL = 25 * 1024;
75
+ const MAX_SKILL_FILE_BYTES = 50 * 1024;
76
+ const SUBSTRATE_OPEN_TIMEOUT_MS = Number(process.env.ARIA_SUBSTRATE_OPEN_TIMEOUT_MS || 900);
77
+
78
+ // AI-11803-LOOP1 (2026-05-12): cascade-depth cap. Each loaded skill body is
79
+ // scanned for Load First / Mode Selection / Load Order / Ta'aqqul Autofire
80
+ // sections; named skills cascade onto the load set. Depth 3 covers
81
+ // autofire → quality-audit → first-principles cascades without unbounded
82
+ // recursion through skills that load each other.
83
+ const MAX_CASCADE_DEPTH = 3;
84
+
85
+ // AI-11803-LOOP2 (2026-05-12): doctrine-trigger map pre-emit pass caps.
86
+ // The trigger map has 79 entries; scanning the user prompt against each
87
+ // regex is O(79 * promptLen). The cap on matched triggers prevents a
88
+ // pathological prompt from producing a giant alert block. The per-trigger
89
+ // byte budget keeps each alert compact (teaching + counter_action + memory
90
+ // file name + trigger). Total budget fits inside additionalContext alongside
91
+ // skill bodies without competing for the 25KB skill-body cap.
92
+ const DOCTRINE_TRIGGER_MAP_PATH = `${HOME}/.claude/hooks/doctrine_trigger_map.json`;
93
+ const MEMORY_DIR = `${HOME}/.claude/projects/-home-hamzaibrahim1/memory`;
94
+ const MAX_DOCTRINE_TRIGGER_MATCHES = 8;
95
+ const MAX_BYTES_PER_TRIGGER_ALERT = 480;
96
+ // AI-11803-QA-GAP3 (2026-05-12): per-memory body injection cap.
97
+ // QA-FIX (2026-05-12 same turn): raised to 4KB so the must-satisfy Recovery
98
+ // Contract section (Pre-Conditions + Classification A/B/C/D + Loop Safety +
99
+ // Turn-End Checklist) fits. Same-memory dedup keeps total bounded to
100
+ // ~12KB worst-case (3 distinct memories × 4KB) but typically 4-8KB.
101
+ const MAX_BYTES_PER_MEMORY_BODY = 4096;
102
+ // File-size ceiling raised to 32KB so strengthened doctrine memories
103
+ // (Recovery Contracts + qiyas + tadabbur + 8-lens substrate) don't get
104
+ // silently rejected. Per-body cap above still bounds what gets injected;
105
+ // the ceiling only rejects abnormally-large or attacker-planted files.
106
+ const MAX_MEMORY_FILE_CEILING = 32 * 1024;
107
+ // QA-FIX-SECTION-AWARE: when a memory body has a "# Recovery Contract"
108
+ // section, prefer to extract from that section forward. This makes the
109
+ // must-satisfy operative content load-bearing in autoload context even
110
+ // when the memory is 12-18KB. Falls back to top-of-body truncation when
111
+ // the header isn't present. Header pattern matches "# Recovery Contract"
112
+ // or "# Recovery contract" (case-insensitive) anchored on a heading line.
113
+ const RECOVERY_CONTRACT_HEADER_RX = /^#{1,3}\s+Recovery\s+Contract\b/im;
114
+
115
+ // AI-11803-STEP5 (2026-05-12) — cookbook auto-pull on trigger match.
116
+ // Skill bodies reference `references/<name>.md` cookbooks (1KB-79KB). The
117
+ // cascade primitive loads SKILL.md but NOT the referenced cookbooks. This
118
+ // primitive scans loaded skill bodies for the reference pattern, parses
119
+ // each cookbook's section headers, scores sections by prompt-keyword
120
+ // overlap, and injects the top-1 section per cookbook into context.
121
+ //
122
+ // Deterministic selection (no LLM call, no faux-fallback):
123
+ // 1. Extract keywords from prompt: lowercase tokens length ≥ 4, deduped.
124
+ // 2. Score each `## ` or `### ` section by count of distinct prompt
125
+ // keywords appearing in section text (header to next header of
126
+ // same/higher level).
127
+ // 3. Min threshold: section must score ≥ 2 distinct keywords. Below
128
+ // threshold → skip the cookbook entirely. NO faux-fallback to "first
129
+ // section if no match" — that would be polluting context with
130
+ // arbitrary content (cf. tadabbur INVERSION + forge-guardrails).
131
+ // 4. Tie-break: later position in file wins.
132
+ // 5. Per-cookbook injection capped at MAX_BYTES_PER_COOKBOOK_SECTION (2KB).
133
+ // 6. Total cookbook injection capped at MAX_BYTES_COOKBOOK_TOTAL (4KB).
134
+ //
135
+ // Loop safety: depth cap = 1 (no transitive cookbook→cookbook expansion);
136
+ // each cookbook path injected at most once per turn (Set dedup).
137
+ //
138
+ // Kill switch: ARIA_AUTOLOAD_COOKBOOK_OFF=1.
139
+ // Captures both same-skill (`references/x.md`) and cross-skill
140
+ // (`../<other-skill>/references/x.md`) reference patterns. Group 1 (if
141
+ // present) is the cross-skill name; group 2 is the cookbook filename.
142
+ // QA-FIX (2026-05-12 same turn): cross-skill references were previously
143
+ // silently mis-resolved to the wrong skill dir → invisible to autoload.
144
+ const COOKBOOK_REF_RX = /(?:\.\.\/([a-z0-9_-]+)\/)?references\/([a-z0-9_-]+\.md)/gi;
145
+
146
+ // AI-11803-F3 (2026-05-12) — sub-agent parent-handoff inheritance.
147
+ // When this autoload fires inside a sub-agent session, the parent
148
+ // orchestrator's aria-agent-handoff.mjs wrote a handoff JSON containing
149
+ // the parent's autoload pins (skill names, memory filenames, cookbook
150
+ // section selections). Read those FIRST, layer them into the load set,
151
+ // then let the sub-agent's own classifier add task-specific skills on
152
+ // top. Augment, not override.
153
+ //
154
+ // Loop safety: handoff JSON includes chainDepth=1 marker; downstream
155
+ // hops (sub-sub-agent) DROP propagation when constructing their own
156
+ // handoff (write-side check in aria-agent-handoff.mjs).
157
+ //
158
+ // TTL: handoff carries ttlMs (5min); if expired vs writtenAt, ignore.
159
+ // Stale handoffs aren't an error — they're from a finished parent turn
160
+ // whose context is no longer load-bearing.
161
+ //
162
+ // Kill switch: ARIA_AUTOLOAD_PARENT_HANDOFF_OFF=1
163
+ const PARENT_HANDOFF_PATH = `${HOME}/.claude/aria-agent-harness-handoff.json`;
164
+ const COOKBOOK_HEADER_RX = /^(#{2,3})\s+(.+)$/gm;
165
+ const MAX_BYTES_PER_COOKBOOK_SECTION = 2048;
166
+ const MAX_BYTES_COOKBOOK_TOTAL = 4096;
167
+ const COOKBOOK_MIN_SCORE = 2;
168
+ const COOKBOOK_KEYWORD_MIN_LEN = 4;
169
+ const COOKBOOK_FILE_CEILING = 200 * 1024; // 200KB hard ceiling on cookbook files (largest seen is 79KB)
170
+
171
+ // AI-11803-STEP4 (2026-05-12) — MEMORY.md auto-load + top-N body injection.
172
+ // MEMORY.md is the master index of every Aria doctrine memory written across
173
+ // sessions. Without this primitive, the model only sees memory bodies when a
174
+ // doctrine-trigger regex fires (lib/doctrine-trigger-map-loader.mjs path) —
175
+ // which means ~80% of accumulated doctrine is invisible per turn. Hamza
176
+ // directive 2026-05-12: "memory.md should def auto load."
177
+ //
178
+ // Budget split (hard cap 8KB total so this doesn't crowd the 25KB skill-body
179
+ // budget):
180
+ // - 4KB MEMORY.md index (one-line entries from the file verbatim,
181
+ // gracefully truncated with a tail marker naming how many entries fell
182
+ // off the cap so the agent knows to consult the file directly)
183
+ // - 4KB for top-N memory bodies (default N=3, ~1.3KB each)
184
+ //
185
+ // Priority signal for top-N selection (deterministic, no faux-priority):
186
+ // 1. Frontmatter `priority: <number>` field if present (explicit owner
187
+ // signal — honest first-tier). Higher number = higher priority.
188
+ // 2. mtime descending (recency fallback when no explicit priority — the
189
+ // most-recently authored or edited memory is the most likely to be
190
+ // currently relevant; this matches Hamza's authoring cadence).
191
+ //
192
+ // Dedup contract: top-N body injection MUST skip memories already injected
193
+ // by buildDoctrineTriggerInjection() this turn (trigger-map regex matched
194
+ // → memory body inlined already). Without dedup, the same memory body could
195
+ // land twice on the same turn. Implemented via a Set<string> of memory
196
+ // filenames passed from main() after doctrineScan.matches is computed.
197
+ const MAX_BYTES_MEMORY_INDEX = 4096;
198
+ const MAX_BYTES_MEMORY_BODIES = 4096;
199
+ const TOP_N_MEMORY_BODIES = 3;
200
+ const MEMORY_INDEX_PATH = `${MEMORY_DIR}/MEMORY.md`;
201
+
202
+ // Trailing boilerplate sections that are identical across skills and add
203
+ // only noise when injected. Stripping these gives 1-1.5KB of headroom per
204
+ // skill back to the operative content (Trigger, Rules, Workflow). This is
205
+ // trimming redundant duplication, NOT contract-stripping per the
206
+ // no-stripping-as-workaround doctrine.
207
+ const REDUNDANT_TRAILING_SECTIONS = [
208
+ /## First-Class Production Contract[\s\S]*?(?=\n## |\n# |$)/i,
209
+ /## Self-Executing Recovery Contract[\s\S]*?(?=\n## |\n# |$)/i,
210
+ /## Required Workflow[\s\S]*?(?=\n## |\n# |$)/i, // generic 5-step list also identical across skills
211
+ ];
212
+
213
+ function readEvent() {
214
+ try {
215
+ const raw = readFileSync(0, 'utf8');
216
+ return raw.trim() ? JSON.parse(raw) : {};
217
+ } catch {
218
+ return {};
219
+ }
220
+ }
221
+
222
+ // A4 (2026-05-17) — end-phase court verdict feedback loop.
223
+ // Reads the tail-N entries from ~/.aria/runtime/state/end-of-phase-qa-court.jsonl
224
+ // (written by lib/end-phase-qa-autofire.mjs at every Stop). The kernel uses
225
+ // these to reinforce quality skills when recent verdicts indicate failure.
226
+ // LOUD-fallback to [] per feedback_no_silent_fail_open_in_hooks.md so the
227
+ // caller can proceed with cascade-only manifest if court state unreadable.
228
+ const END_PHASE_COURT_JSONL = `${HOME}/.aria/runtime/state/end-of-phase-qa-court.jsonl`;
229
+ const RECENT_COURT_TAIL_LIMIT = Number(process.env.ARIA_AUTOLOAD_COURT_TAIL || 3);
230
+ // A5 (2026-05-18) — hardening-directive consumer. Stop-gate writes
231
+ // aria.atlas_orchestrator_hardening_directive.v1 to the hive WAL when a
232
+ // prior turn's atlas-selected skills weren't all invoked OR the QA court
233
+ // verdict was below verified. This pre-emit reads the most recent N
234
+ // directives and force-adds their `forceInvokeNextTurn` skills to
235
+ // invocationRequired. Single-pass tail read; LOUD-fallback to [] on read
236
+ // failure so cascade-only manifest is preserved.
237
+ const HIVE_LEDGER_WAL_PATH = `${HOME}/.aria/runtime/state/hive-ledger-wal.jsonl`;
238
+ const HARDENING_DIRECTIVE_TAIL_LIMIT = Number(process.env.ARIA_AUTOLOAD_HARDENING_TAIL || 16);
239
+
240
+ function readRecentHardeningDirectives(limit = HARDENING_DIRECTIVE_TAIL_LIMIT) {
241
+ try {
242
+ if (!existsSync(HIVE_LEDGER_WAL_PATH)) return [];
243
+ const raw = readFileSync(HIVE_LEDGER_WAL_PATH, 'utf8').trim();
244
+ if (!raw) return [];
245
+ const lines = raw.split('\n');
246
+ // Tail scan — only the most recent N candidate lines (bounds memory + IO).
247
+ const tail = lines.slice(-Math.max(1, limit * 8));
248
+ const directives = [];
249
+ for (let i = tail.length - 1; i >= 0 && directives.length < limit; i--) {
250
+ try {
251
+ const obj = JSON.parse(tail[i]);
252
+ if (obj?.schema === 'aria.atlas_orchestrator_hardening_directive.v1' && Array.isArray(obj.forceInvokeNextTurn)) {
253
+ directives.push({
254
+ at: obj.at || null,
255
+ session_id: obj.session_id || null,
256
+ reason: obj.reason || null,
257
+ forceInvokeNextTurn: obj.forceInvokeNextTurn.filter((s) => typeof s === 'string'),
258
+ qaVerdict: obj.qaVerdict || null,
259
+ adherenceRatio: typeof obj.adherenceRatio === 'number' ? obj.adherenceRatio : null,
260
+ });
261
+ }
262
+ } catch { /* malformed line non-fatal */ }
263
+ }
264
+ return directives;
265
+ } catch (err) {
266
+ process.stderr.write(`[aria-pre-emit-autoload:hardening-directive-read] LOUD ${err instanceof Error ? err.message : String(err)} — proceeding without hardening feedback\n`);
267
+ return [];
268
+ }
269
+ }
270
+
271
+ function readRecentCourtVerdicts(limit = RECENT_COURT_TAIL_LIMIT) {
272
+ try {
273
+ if (!existsSync(END_PHASE_COURT_JSONL)) return [];
274
+ const raw = readFileSync(END_PHASE_COURT_JSONL, 'utf8').trim();
275
+ if (!raw) return [];
276
+ const lines = raw.split('\n');
277
+ const tail = lines.slice(-Math.max(1, limit));
278
+ const verdicts = [];
279
+ for (const ln of tail) {
280
+ try {
281
+ const obj = JSON.parse(ln);
282
+ if (obj && typeof obj === 'object' && typeof obj.verdict === 'string') {
283
+ verdicts.push({
284
+ verdict: obj.verdict,
285
+ at: obj.at || null,
286
+ phase_id: obj.phase_id || null,
287
+ trigger: obj.trigger || null,
288
+ session_id: obj.session_id || null,
289
+ });
290
+ }
291
+ } catch {
292
+ // Single malformed line is non-fatal — court is append-only JSONL
293
+ }
294
+ }
295
+ return verdicts;
296
+ } catch (err) {
297
+ process.stderr.write(`[aria-pre-emit-autoload:court-read-fallback] LOUD-fail path=${END_PHASE_COURT_JSONL} err=${err?.message || String(err)}\n`);
298
+ return [];
299
+ }
300
+ }
301
+
302
+ function emit(envelope) {
303
+ process.stdout.write(`${JSON.stringify(envelope)}\n`);
304
+ }
305
+
306
+ function emitNoop(reason) {
307
+ emit({
308
+ hookSpecificOutput: {
309
+ hookEventName: HOOK_EVENT_NAME,
310
+ additionalContext: `${HEADER_PREFIX} skipped: ${reason}`,
311
+ },
312
+ });
313
+ process.exit(0);
314
+ }
315
+
316
+ async function openRuntimeSubstrate({ event, prompt, requiredSkills }) {
317
+ const controller = new AbortController();
318
+ const timeout = setTimeout(() => controller.abort(), SUBSTRATE_OPEN_TIMEOUT_MS);
319
+ try {
320
+ const response = await fetch(`${RUNTIME_URL}/substrate/open`, {
321
+ method: 'POST',
322
+ headers: { 'content-type': 'application/json' },
323
+ signal: controller.signal,
324
+ body: JSON.stringify({
325
+ surface: 'claude-code-pre-emit',
326
+ sessionId: event.session_id || event.sessionId || process.env.CLAUDE_SESSION_ID || `pre-emit-${process.pid}`,
327
+ prompt,
328
+ requiredSkills,
329
+ source: 'aria-pre-emit-autoload',
330
+ event: 'pre_emit_autoload',
331
+ }),
332
+ });
333
+ const text = await response.text();
334
+ let data = null;
335
+ try { data = text ? JSON.parse(text) : null; } catch { data = { raw: text.slice(0, 500) }; }
336
+ return response.ok && data?.ok === true
337
+ ? { ok: true, status: response.status, packet: data }
338
+ : { ok: false, status: response.status, packet: data, error: data?.error || 'substrate_open_failed' };
339
+ } catch (error) {
340
+ return { ok: false, status: 0, error: error instanceof Error ? error.message : String(error) };
341
+ } finally {
342
+ clearTimeout(timeout);
343
+ }
344
+ }
345
+
346
+ function buildSubstrateOpenInjection(substrateOpen) {
347
+ if (!substrateOpen?.ok || !substrateOpen.packet) {
348
+ return [
349
+ '═══ ARIA SUBSTRATE OPEN GAP ═══',
350
+ `runtime=${RUNTIME_URL}`,
351
+ `status=${substrateOpen?.status || 0}`,
352
+ `error=${substrateOpen?.error || 'substrate_open_unavailable'}`,
353
+ 'Treat Atlas/Hive binding as unverified for this turn; completion claims require direct evidence.',
354
+ ].join('\n');
355
+ }
356
+ const packet = substrateOpen.packet;
357
+ const forge = packet.atlasFirstPrinciplesForgeReceipt || {};
358
+ return [
359
+ '═══ ARIA SUBSTRATE OPEN — ATLAS FIRST-PRINCIPLES FORGE ═══',
360
+ `work_unit_id=${packet.workUnitId}`,
361
+ `hive_project_id=${packet.projectId}`,
362
+ `hive_thread_id=${packet.threadId}`,
363
+ `atlas_status=${forge.atlas?.status || 'missing'}`,
364
+ `atlas_context_hash=${forge.atlas?.contextHash || 'missing'}`,
365
+ `first_principles_mode=${forge.mode || 'missing'}`,
366
+ `generative_axioms=${forge.generativeAxiomCount || 0}`,
367
+ `required_skills=${(packet.requiredSkillIds || []).join(',')}`,
368
+ `drift_correction=${forge.driftCorrection?.correctedPurpose || 'missing'}`,
369
+ 'Binding rule: first principles must generate cross-domain connections, bounded novelty trials, and breakthrough candidates. Truth protection is a boundary, not the primary purpose.',
370
+ ].join('\n');
371
+ }
372
+
373
+ function writeSidecar(payload) {
374
+ try {
375
+ mkdirSync(dirname(SIDECAR_PATH), { recursive: true, mode: 0o700 });
376
+ writeFileSync(SIDECAR_PATH, `${JSON.stringify(payload, null, 2)}\n`, { mode: 0o600 });
377
+ } catch (err) {
378
+ process.stderr.write(`[aria-pre-emit-autoload:sidecar-write] ${err instanceof Error ? err.message : String(err)}\n`);
379
+ }
380
+ }
381
+
382
+ // Read and prepare a skill body for injection. Returns { body, bytes,
383
+ // fullBytes, redacted, reason } so caller can record what was injected and
384
+ // why. Hardens against:
385
+ // - non-regular files (symlinks, fifos, devices) → reject
386
+ // - oversize SKILL.md (> MAX_SKILL_FILE_BYTES) → reject
387
+ // - missing files → empty body, no crash
388
+ function readSkillBody(skillName) {
389
+ const path = `${SKILLS_DIR}/${skillName}/SKILL.md`;
390
+ if (!existsSync(path)) {
391
+ return { body: '', bytes: 0, fullBytes: 0, redacted: false, reason: 'missing' };
392
+ }
393
+ let lst;
394
+ try {
395
+ lst = lstatSync(path);
396
+ } catch (err) {
397
+ return { body: '', bytes: 0, fullBytes: 0, redacted: false, reason: `lstat-failed: ${err?.message || err}` };
398
+ }
399
+ if (!lst.isFile()) {
400
+ return { body: '', bytes: 0, fullBytes: 0, redacted: true, reason: 'not-regular-file' };
401
+ }
402
+ if (lst.size > MAX_SKILL_FILE_BYTES) {
403
+ return { body: '', bytes: 0, fullBytes: lst.size, redacted: true, reason: `oversize: ${lst.size}B > ${MAX_SKILL_FILE_BYTES}B` };
404
+ }
405
+ let raw;
406
+ try {
407
+ raw = readFileSync(path, 'utf8');
408
+ } catch (err) {
409
+ return { body: '', bytes: 0, fullBytes: lst.size, redacted: false, reason: `read-failed: ${err?.message || err}` };
410
+ }
411
+ const fullBytes = Buffer.byteLength(raw, 'utf8');
412
+ // Strip YAML frontmatter (--- ... --- at top of file)
413
+ let trimmed = raw.replace(/^---[\s\S]*?---\s*/, '');
414
+ // Strip redundant trailing boilerplate sections that are identical
415
+ // across all skills (per pre-phase analysis). This is duplication
416
+ // trimming, not contract stripping.
417
+ for (const rx of REDUNDANT_TRAILING_SECTIONS) {
418
+ trimmed = trimmed.replace(rx, '');
419
+ }
420
+ trimmed = trimmed.trimEnd();
421
+ // Apply per-skill byte cap. If we have to truncate, leave a marker so
422
+ // the agent knows there's more content available via Skill tool.
423
+ let body = trimmed;
424
+ let truncated = false;
425
+ if (Buffer.byteLength(body, 'utf8') > MAX_BYTES_PER_SKILL) {
426
+ // Truncate at a paragraph boundary near the cap when possible.
427
+ const buf = Buffer.from(body, 'utf8').slice(0, MAX_BYTES_PER_SKILL);
428
+ body = buf.toString('utf8');
429
+ const lastBreak = Math.max(body.lastIndexOf('\n\n'), body.lastIndexOf('\n## '));
430
+ if (lastBreak > MAX_BYTES_PER_SKILL * 0.6) {
431
+ body = body.slice(0, lastBreak);
432
+ }
433
+ truncated = true;
434
+ body += `\n\n[…body truncated at ${MAX_BYTES_PER_SKILL}B; full SKILL.md available via /skills/${skillName}/SKILL.md…]`;
435
+ }
436
+ const bytes = Buffer.byteLength(body, 'utf8');
437
+ return {
438
+ body,
439
+ bytes,
440
+ fullBytes,
441
+ redacted: false,
442
+ truncated,
443
+ reason: 'ok',
444
+ };
445
+ }
446
+
447
+ // AI-11803-LOOP2 (2026-05-12) — doctrine-trigger pre-emit scan.
448
+ // Runs the 79-trigger doctrine map against the user's prompt text at
449
+ // UserPromptSubmit so prose-pattern matches (e.g., "graceful degradation",
450
+ // "out of scope", "want me to") surface their bound doctrine memory +
451
+ // teaching + counter_action BEFORE the model drafts. Prior architecture
452
+ // only ran the trigger map post-emit (after the answer was drafted), which
453
+ // caught drift after the fact instead of preventing it.
454
+ //
455
+ // Output shape: a separate "[ARIA_DOCTRINE_TRIGGERS_MATCHED]" section in
456
+ // additionalContext, formatted as compact one-line-per-trigger alerts.
457
+ // Does NOT inject the bound memory file content (separate from skill-body
458
+ // injection); the memory filename surfaces so the model can read it via
459
+ // the existing memory-consumption gate at PreToolUse.
460
+ //
461
+ // Fail-allow: any error in trigger map load returns empty matches list and
462
+ // LOUD telemetry — never blocks the autoload's emission.
463
+ //
464
+ // Kill switch: ARIA_AUTOLOAD_TRIGGER_MAP_OFF=1.
465
+ function scanDoctrineTriggers(promptText) {
466
+ if (/^(?:1|true|yes|on)$/i.test(String(process.env.ARIA_AUTOLOAD_TRIGGER_MAP_OFF || ''))) {
467
+ return { matches: [], errors: [], skipped: 'env-disabled' };
468
+ }
469
+ if (!promptText || typeof promptText !== 'string') {
470
+ return { matches: [], errors: [], skipped: 'empty-prompt' };
471
+ }
472
+ let loaded;
473
+ try {
474
+ loaded = loadDoctrineTriggerMap(DOCTRINE_TRIGGER_MAP_PATH);
475
+ } catch (err) {
476
+ const msg = err instanceof Error ? err.message : String(err);
477
+ process.stderr.write(`[aria-pre-emit-autoload:trigger-map-load-error] ${msg}\n`);
478
+ return { matches: [], errors: [msg], skipped: 'load-error' };
479
+ }
480
+ const matches = [];
481
+ const seen = new Set();
482
+ for (const entry of loaded.triggers) {
483
+ if (matches.length >= MAX_DOCTRINE_TRIGGER_MATCHES) break;
484
+ // Each entry's compiled regex carries the `gi` flags; reset lastIndex
485
+ // so re-use across multiple scans doesn't skip from prior call state.
486
+ entry.regex.lastIndex = 0;
487
+ if (!entry.regex.test(promptText)) continue;
488
+ // De-dup by memory file (multiple triggers may bind the same memory).
489
+ if (seen.has(entry.memory)) continue;
490
+ seen.add(entry.memory);
491
+ matches.push({
492
+ trigger: entry.trigger,
493
+ memory: entry.memory,
494
+ teaching: entry.teaching,
495
+ counter_action: entry.counter_action,
496
+ });
497
+ }
498
+ return { matches, errors: loaded.errors || [], skipped: null };
499
+ }
500
+
501
+ // AI-11803-QA-GAP3 (2026-05-12): read memory body for injection.
502
+ // Returns frontmatter-stripped, cap-truncated body or empty string on any
503
+ // failure. Per parallel-session safety, never throws.
504
+ function readMemoryBody(memoryFilename) {
505
+ if (!memoryFilename || typeof memoryFilename !== 'string') return '';
506
+ const path = `${MEMORY_DIR}/${memoryFilename}`;
507
+ if (!existsSync(path)) return '';
508
+ let lst;
509
+ try { lst = lstatSync(path); } catch { return ''; }
510
+ if (!lst.isFile()) return '';
511
+ if (lst.size > MAX_MEMORY_FILE_CEILING) return ''; // hard ceiling on file size
512
+ let raw;
513
+ try { raw = readFileSync(path, 'utf8'); } catch { return ''; }
514
+ // Strip YAML frontmatter; if absent, raw passes through.
515
+ let body = raw.replace(/^---[\s\S]*?---\s*/, '').trimStart();
516
+ // QA-FIX-SECTION-AWARE: if the body has a "# Recovery Contract" section,
517
+ // extract from that section forward. The must-satisfy contract becomes
518
+ // the operative content; preceding rationale (qiyas / tadabbur / 8-lens
519
+ // pre-amble) stays in the file for read-on-demand but doesn't crowd the
520
+ // pre-emit context.
521
+ const recoveryMatch = body.match(RECOVERY_CONTRACT_HEADER_RX);
522
+ let extractionMode = 'top-of-body';
523
+ if (recoveryMatch) {
524
+ const headerStart = body.indexOf(recoveryMatch[0]);
525
+ const before = body.slice(0, headerStart);
526
+ const beforeBytes = Buffer.byteLength(before, 'utf8');
527
+ body = `[…body preamble omitted, ${beforeBytes}B; recovery contract follows…]\n\n${body.slice(headerStart)}`;
528
+ extractionMode = 'recovery-contract-section';
529
+ }
530
+ if (Buffer.byteLength(body, 'utf8') > MAX_BYTES_PER_MEMORY_BODY) {
531
+ const buf = Buffer.from(body, 'utf8').slice(0, MAX_BYTES_PER_MEMORY_BODY);
532
+ body = buf.toString('utf8');
533
+ const lastBreak = Math.max(body.lastIndexOf('\n\n'), body.lastIndexOf('\n'));
534
+ if (lastBreak > MAX_BYTES_PER_MEMORY_BODY * 0.6) body = body.slice(0, lastBreak);
535
+ body += `\n[…memory body truncated at ${MAX_BYTES_PER_MEMORY_BODY}B; mode=${extractionMode}; full file at ${path}…]`;
536
+ }
537
+ return body;
538
+ }
539
+
540
+ function buildDoctrineTriggerInjection(matches) {
541
+ if (!matches || matches.length === 0) return '';
542
+ const lines = [];
543
+ lines.push('═══ ARIA DOCTRINE TRIGGERS MATCHED (prose patterns in your prompt bind to these memories) ═══');
544
+ for (const m of matches) {
545
+ let teaching = m.teaching;
546
+ let counter = m.counter_action;
547
+ // Per-alert byte cap — truncate teaching+counter if combined exceed budget.
548
+ const baseLen = ` • [${m.trigger}] → ${m.memory}: `.length;
549
+ const budget = MAX_BYTES_PER_TRIGGER_ALERT - baseLen;
550
+ const combined = `${teaching} || ${counter}`;
551
+ const slice = combined.length > budget ? `${combined.slice(0, budget - 3)}...` : combined;
552
+ lines.push(` • [${m.trigger}] → ${m.memory}: ${slice}`);
553
+ // AI-11803-QA-GAP3: inject memory body (capped) so the model sees the
554
+ // operative rule + Why + How-to-apply lines directly, not just a pointer.
555
+ const memBody = readMemoryBody(m.memory);
556
+ if (memBody) {
557
+ lines.push(` ┌─ memory body (${m.memory}):`);
558
+ for (const ln of memBody.split('\n')) lines.push(` │ ${ln}`);
559
+ lines.push(` └─`);
560
+ }
561
+ }
562
+ lines.push('Apply each: the trigger phrase in the prompt names a doctrine the agent must honor THIS turn.');
563
+ return lines.join('\n');
564
+ }
565
+
566
+ // AI-11803-LOOP1 (2026-05-12) — cascade autoload.
567
+ // Expand the initial skill set by reading each skill body and parsing its
568
+ // Load First / Mode Selection / Load Order / Ta'aqqul Autofire Pattern
569
+ // sections. Recursive BFS bounded by MAX_CASCADE_DEPTH and MAX_BYTES_TOTAL.
570
+ // Returns the load order, body map, total bytes, and observed depth so the
571
+ // caller can build skillBodies + sidecar + ledger telemetry from one pass.
572
+ //
573
+ // Cycle-safe: each skill is read at most once (Set<string> seen tracker).
574
+ // Budget-safe: once total bytes would exceed MAX_BYTES_TOTAL, subsequent
575
+ // skills are recorded with reason="budget-exhausted (cascade-depth=N)"
576
+ // instead of being dropped silently — the agent still sees that the skill
577
+ // was wanted but unavailable in context.
578
+ // Existence-filtered: cascade candidates are only enqueued if the SKILL.md
579
+ // actually exists on disk, so mode-label noise (`qa`, `light`, `batch`)
580
+ // and stale skill names from older bodies don't pollute the queue.
581
+ function expandSkillCascade(initialSkills) {
582
+ const loadedBodies = new Map(); // skill -> readSkillBody result
583
+ const order = []; // load order in BFS-by-depth
584
+ const seen = new Set();
585
+ let totalBytes = 0;
586
+ let queue = [...new Set(initialSkills)];
587
+ let depth = 0;
588
+ let maxObservedDepth = 0;
589
+ let maxAttemptedDepth = 0;
590
+ while (queue.length > 0 && depth <= MAX_CASCADE_DEPTH) {
591
+ const nextQueue = [];
592
+ for (const skill of queue) {
593
+ if (seen.has(skill)) continue;
594
+ seen.add(skill);
595
+ const result = readSkillBody(skill);
596
+ // Skip skills that don't exist on disk — keeps cascade quiet on mode
597
+ // labels and stale references.
598
+ if (result.reason === 'missing') continue;
599
+ // AI-11803-QA-GAP1 (2026-05-12): track attempted-depth separately from
600
+ // injected-depth. A candidate enqueued at depth N counts toward
601
+ // maxAttemptedDepth even if its body is budget-exhausted and bytes=0.
602
+ // Prior telemetry conflated "no body injected" with "no depth observed",
603
+ // under-reporting cascade reach when the 25KB cap saturated early.
604
+ maxAttemptedDepth = Math.max(maxAttemptedDepth, depth);
605
+ if (loadedBodies.size > 0 && totalBytes + result.bytes > MAX_BYTES_TOTAL) {
606
+ loadedBodies.set(skill, {
607
+ ...result,
608
+ body: '',
609
+ bytes: 0,
610
+ truncated: false,
611
+ redacted: false,
612
+ reason: `budget-exhausted (cascade-depth=${depth})`,
613
+ });
614
+ order.push(skill);
615
+ // Even when body is budget-exhausted, we still scan for downstream
616
+ // cascade candidates — but only if we have the body (we don't here),
617
+ // so this branch terminates the cascade for this skill's children.
618
+ continue;
619
+ }
620
+ loadedBodies.set(skill, result);
621
+ order.push(skill);
622
+ totalBytes += result.bytes;
623
+ maxObservedDepth = depth;
624
+ if (result.body) {
625
+ for (const c of parseLoadFirstSection(result.body)) {
626
+ if (seen.has(c)) continue;
627
+ if (!existsSync(`${SKILLS_DIR}/${c}/SKILL.md`)) continue;
628
+ nextQueue.push(c);
629
+ }
630
+ }
631
+ }
632
+ queue = nextQueue;
633
+ depth++;
634
+ }
635
+ return {
636
+ loadedBodies,
637
+ order,
638
+ totalBytes,
639
+ cascadeDepth: maxObservedDepth, // depth at which a body was injected (legacy alias for telemetry compat)
640
+ depthInjected: maxObservedDepth,
641
+ depthAttempted: maxAttemptedDepth,
642
+ };
643
+ }
644
+
645
+ // AI-11803-STEP4 (2026-05-12) — read MEMORY.md as an index, capped at
646
+ // MAX_BYTES_MEMORY_INDEX.
647
+ //
648
+ // QA-FIX-1 (2026-05-12, qiyas Owner-Hamza-tomorrow + scale + tadabbur
649
+ // INVERSION): tail-bias the truncation. MEMORY.md is append-only — Hamza
650
+ // writes new memories as entries at the BOTTOM. A head-bias truncation
651
+ // (drop from end) would drop the NEWEST doctrine first, recreating the
652
+ // exact gap this step was meant to close. Tail-bias keeps recent doctrine
653
+ // visible and drops older entries with a head-marker.
654
+ //
655
+ // Algorithm: walk lines from END to START, accumulate while under cap,
656
+ // reverse the kept set, prepend a head-marker naming how many earlier
657
+ // entries were dropped.
658
+ function readMemoryIndex() {
659
+ if (!existsSync(MEMORY_INDEX_PATH)) {
660
+ return { body: '', bytes: 0, totalLines: 0, droppedLines: 0, reason: 'missing' };
661
+ }
662
+ let lst;
663
+ try { lst = lstatSync(MEMORY_INDEX_PATH); } catch (err) {
664
+ return { body: '', bytes: 0, totalLines: 0, droppedLines: 0, reason: `lstat-failed: ${err?.message || err}` };
665
+ }
666
+ if (!lst.isFile()) {
667
+ return { body: '', bytes: 0, totalLines: 0, droppedLines: 0, reason: 'not-regular-file' };
668
+ }
669
+ let raw;
670
+ try { raw = readFileSync(MEMORY_INDEX_PATH, 'utf8'); } catch (err) {
671
+ return { body: '', bytes: 0, totalLines: 0, droppedLines: 0, reason: `read-failed: ${err?.message || err}` };
672
+ }
673
+ const lines = raw.split('\n');
674
+ const totalLines = lines.length;
675
+ if (Buffer.byteLength(raw, 'utf8') <= MAX_BYTES_MEMORY_INDEX) {
676
+ return { body: raw.trimEnd(), bytes: Buffer.byteLength(raw, 'utf8'), totalLines, droppedLines: 0, reason: 'ok' };
677
+ }
678
+ // Tail-bias: walk from end, accumulate newest lines first.
679
+ const keptReversed = [];
680
+ let accBytes = 0;
681
+ const reserveForMarker = 140;
682
+ for (let i = lines.length - 1; i >= 0; i--) {
683
+ const line = lines[i];
684
+ const lineBytes = Buffer.byteLength(line, 'utf8') + 1; // +1 for newline
685
+ if (accBytes + lineBytes > MAX_BYTES_MEMORY_INDEX - reserveForMarker) break;
686
+ keptReversed.push(line);
687
+ accBytes += lineBytes;
688
+ }
689
+ const kept = keptReversed.reverse();
690
+ const droppedLines = Math.max(0, totalLines - kept.length);
691
+ const headMarker = `[…MEMORY.md tail-biased: ${droppedLines} older entries dropped; full file at ${MEMORY_INDEX_PATH}. Showing latest ${kept.length} entries below…]`;
692
+ const body = `${headMarker}\n\n${kept.join('\n').trimEnd()}`;
693
+ return { body, bytes: Buffer.byteLength(body, 'utf8'), totalLines, droppedLines, reason: 'tail-biased' };
694
+ }
695
+
696
+ // AI-11803-STEP4 (2026-05-12) — score every memory file in MEMORY_DIR by
697
+ // (a) frontmatter `priority: <number>` if present (explicit), or
698
+ // (b) mtime descending (recency fallback).
699
+ // Returns sorted array of { filename, score, source } where higher score is
700
+ // more important. `source` is either "frontmatter:<n>" or "mtime:<ms>" so
701
+ // telemetry can audit which signal won.
702
+ //
703
+ // Filters: MEMORY.md itself is excluded (we inject it separately as the
704
+ // index). Non-.md files excluded. Files unreadable or non-regular are
705
+ // skipped silently — never throws.
706
+ function scoreMemoriesForPriority() {
707
+ let entries;
708
+ try { entries = readdirSync(MEMORY_DIR); } catch (err) {
709
+ return { scored: [], errors: [err?.message || String(err)] };
710
+ }
711
+ const scored = [];
712
+ const errors = [];
713
+ for (const filename of entries) {
714
+ if (filename === 'MEMORY.md') continue;
715
+ if (!filename.endsWith('.md')) continue;
716
+ const fullPath = `${MEMORY_DIR}/${filename}`;
717
+ let lst;
718
+ try { lst = lstatSync(fullPath); } catch (err) {
719
+ errors.push(`lstat ${filename}: ${err?.message || err}`);
720
+ continue;
721
+ }
722
+ if (!lst.isFile()) continue;
723
+ // Read just the frontmatter region — first ~1KB is plenty for YAML.
724
+ let head;
725
+ try {
726
+ const fd = readFileSync(fullPath, 'utf8');
727
+ head = fd.slice(0, 2048);
728
+ } catch (err) {
729
+ errors.push(`read ${filename}: ${err?.message || err}`);
730
+ continue;
731
+ }
732
+ const fmMatch = head.match(/^---\s*\n([\s\S]*?)\n---/);
733
+ let priority = null;
734
+ if (fmMatch) {
735
+ const fm = fmMatch[1];
736
+ const pMatch = fm.match(/^priority:\s*(-?\d+(?:\.\d+)?)\s*$/m);
737
+ if (pMatch) {
738
+ const parsed = Number(pMatch[1]);
739
+ if (Number.isFinite(parsed)) priority = parsed;
740
+ }
741
+ }
742
+ if (priority !== null) {
743
+ scored.push({ filename, score: priority, source: `frontmatter:${priority}`, tier: 'explicit' });
744
+ } else {
745
+ const mtimeMs = lst.mtimeMs || 0;
746
+ scored.push({ filename, score: mtimeMs, source: `mtime:${Math.floor(mtimeMs)}`, tier: 'recency' });
747
+ }
748
+ }
749
+ // Explicit-tier always outranks recency-tier. Within tier, score desc.
750
+ scored.sort((a, b) => {
751
+ if (a.tier !== b.tier) return a.tier === 'explicit' ? -1 : 1;
752
+ return b.score - a.score;
753
+ });
754
+ return { scored, errors };
755
+ }
756
+
757
+ // AI-11803-STEP4 (2026-05-12) — select top-N memory files for body injection,
758
+ // excluding those already injected by trigger-map. Reads each body via the
759
+ // existing readMemoryBody primitive (so the same per-memory cap +
760
+ // frontmatter-strip + size-ceiling applies). Stops once
761
+ // MAX_BYTES_MEMORY_BODIES is exhausted to enforce the hard 8KB total.
762
+ //
763
+ // Returns { injected: [{ filename, body, bytes, tier, score }], totalBytes,
764
+ // dedupedFilenames, scoredCount } so telemetry can audit selection + dedup.
765
+ function selectTopNMemoryBodies(alreadyInjectedFilenames) {
766
+ const { scored, errors } = scoreMemoriesForPriority();
767
+ const dedupedFilenames = [];
768
+ const injected = [];
769
+ let totalBytes = 0;
770
+ for (const entry of scored) {
771
+ if (injected.length >= TOP_N_MEMORY_BODIES) break;
772
+ if (alreadyInjectedFilenames && alreadyInjectedFilenames.has(entry.filename)) {
773
+ dedupedFilenames.push(entry.filename);
774
+ continue;
775
+ }
776
+ const body = readMemoryBody(entry.filename);
777
+ if (!body) continue;
778
+ const bodyBytes = Buffer.byteLength(body, 'utf8');
779
+ if (totalBytes + bodyBytes > MAX_BYTES_MEMORY_BODIES) {
780
+ // Don't take a body that would bust the cap; try the next-priority
781
+ // entry (which may be smaller). This avoids a single oversized
782
+ // memory starving subsequent smaller-but-still-important entries.
783
+ continue;
784
+ }
785
+ injected.push({ filename: entry.filename, body, bytes: bodyBytes, tier: entry.tier, score: entry.score });
786
+ totalBytes += bodyBytes;
787
+ }
788
+ return { injected, totalBytes, dedupedFilenames, scoredCount: scored.length, errors };
789
+ }
790
+
791
+ function buildMemoryAutoloadInjection({ indexResult, bodyResult }) {
792
+ // Kill-switch and pure-missing cases: emit nothing rather than a stub
793
+ // that crowds context with a "[unavailable]" placeholder.
794
+ if (indexResult.reason === 'env-disabled' && bodyResult.injected.length === 0) {
795
+ return '';
796
+ }
797
+ const lines = [];
798
+ lines.push('═══ MEMORY.md INDEX (auto-loaded — every doctrine memory available this session) ═══');
799
+ if (indexResult.bytes === 0) {
800
+ lines.push(`[MEMORY.md unavailable: ${indexResult.reason}]`);
801
+ } else {
802
+ lines.push(indexResult.body);
803
+ }
804
+ if (bodyResult.injected.length > 0) {
805
+ lines.push('');
806
+ lines.push(`═══ TOP-${bodyResult.injected.length} MEMORY BODIES (priority-selected, dedup'd against trigger-map matches) ═══`);
807
+ for (const entry of bodyResult.injected) {
808
+ lines.push('');
809
+ lines.push(`──── ${entry.filename} [${entry.tier === 'explicit' ? `priority=${entry.score}` : `mtime-rank`}] ────`);
810
+ lines.push(entry.body);
811
+ }
812
+ }
813
+ if (bodyResult.dedupedFilenames.length > 0) {
814
+ lines.push('');
815
+ lines.push(`[dedup: ${bodyResult.dedupedFilenames.length} top-N candidate(s) already injected by doctrine-trigger match: ${bodyResult.dedupedFilenames.join(', ')}]`);
816
+ }
817
+ return lines.join('\n');
818
+ }
819
+
820
+ // A5 (2026-05-18) — extract file-path-shape tokens from prompt for atlas
821
+ // dossier consultation. Looks for repo-relative paths (e.g.
822
+ // apps/aria-telemetry/src/mizan.ts, packages/aria-connector/runtime-src/
823
+ // service.mjs) — extension-suffixed tokens, slash-separated. Dedup, cap at
824
+ // ATLAS_DOSSIER_TARGETS_MAX so a long prompt with many paths doesn't fan-out
825
+ // arbitrarily against the atlas socket budget.
826
+ const ATLAS_DOSSIER_TARGETS_MAX = 8;
827
+ const ATLAS_DOSSIER_OVERALL_BUDGET_MS = 800;
828
+ const ATLAS_DOSSIER_PER_TARGET_MS = 300;
829
+ const PATH_SHAPE_RX = /[a-z0-9_.-]+(?:\/[a-z0-9_.-]+){1,}\.(?:ts|tsx|js|jsx|mjs|cjs|json|yaml|yml|md|sh|py|sql|prisma|toml|css|html|tf)/gi;
830
+ function harvestPromptTargets(promptText) {
831
+ if (!promptText || typeof promptText !== 'string') return [];
832
+ const seen = new Set();
833
+ const out = [];
834
+ PATH_SHAPE_RX.lastIndex = 0;
835
+ let m;
836
+ while ((m = PATH_SHAPE_RX.exec(promptText)) !== null) {
837
+ const tok = m[0];
838
+ // Skip URLs (https://..., npm://...) — prefix with letters+colon.
839
+ if (/^[a-z]+:/i.test(tok)) continue;
840
+ if (seen.has(tok)) continue;
841
+ seen.add(tok);
842
+ out.push(tok);
843
+ if (out.length >= ATLAS_DOSSIER_TARGETS_MAX) break;
844
+ }
845
+ return out;
846
+ }
847
+
848
+ // A5 (2026-05-18) — atlas dossier-as-orchestrator: resolve harvested path
849
+ // targets to governing_skills via the atlas daemon. Parallel fan-out bounded
850
+ // by an overall budget; per-target timeout is enforced inside fetch helper.
851
+ // Returns { governingSkills: string[], targetsResolved: number, targetsErr:
852
+ // number, durationMs: number }. LOUD-on-fail is handled per-target by
853
+ // fetchGoverningSkills itself (atlas-dossier-client emits stderr lines on
854
+ // timeout/socket-missing/parse-fail etc).
855
+ async function atlasGoverningSkillsForPrompt(targets) {
856
+ const started = Date.now();
857
+ const out = { governingSkills: [], targetsResolved: 0, targetsErr: 0, durationMs: 0 };
858
+ if (!Array.isArray(targets) || targets.length === 0) return out;
859
+ const seenSkills = new Set();
860
+ const overallDeadline = started + ATLAS_DOSSIER_OVERALL_BUDGET_MS;
861
+ const promises = targets.map((target) => fetchGoverningSkills(target, { timeoutMs: ATLAS_DOSSIER_PER_TARGET_MS })
862
+ .then((skills) => ({ target, skills, err: null }))
863
+ .catch((err) => ({ target, skills: [], err: err?.message || String(err) })),
864
+ );
865
+ // Race the whole batch against the overall budget. Settled-promises
866
+ // contribute their results; un-settled count as errors (LOUD already by helper).
867
+ let settled;
868
+ try {
869
+ settled = await Promise.race([
870
+ Promise.allSettled(promises),
871
+ new Promise((r) => setTimeout(() => r('budget_exceeded'), Math.max(50, overallDeadline - Date.now()))),
872
+ ]);
873
+ } catch {
874
+ settled = 'budget_exceeded';
875
+ }
876
+ if (settled === 'budget_exceeded') {
877
+ process.stderr.write(`[aria-pre-emit-autoload:atlas-orchestrator] LOUD budget_exceeded overall_ms=${ATLAS_DOSSIER_OVERALL_BUDGET_MS} targets=${targets.length}\n`);
878
+ out.targetsErr = targets.length;
879
+ out.durationMs = Date.now() - started;
880
+ return out;
881
+ }
882
+ for (const entry of settled) {
883
+ if (entry.status !== 'fulfilled' || !entry.value) {
884
+ out.targetsErr++;
885
+ continue;
886
+ }
887
+ const v = entry.value;
888
+ if (v.err) {
889
+ out.targetsErr++;
890
+ continue;
891
+ }
892
+ out.targetsResolved++;
893
+ for (const s of v.skills || []) {
894
+ if (typeof s !== 'string' || !s.trim()) continue;
895
+ if (!seenSkills.has(s)) {
896
+ seenSkills.add(s);
897
+ out.governingSkills.push(s);
898
+ }
899
+ }
900
+ }
901
+ out.durationMs = Date.now() - started;
902
+ return out;
903
+ }
904
+
905
+ // AI-11803-STEP5 — extract keywords from prompt for cookbook scoring.
906
+ // Lowercase, tokenize on non-word characters, filter to length ≥ 4, dedup.
907
+ // Returns Set<string> for O(1) membership check in section scoring.
908
+ function extractPromptKeywords(promptText) {
909
+ if (!promptText || typeof promptText !== 'string') return new Set();
910
+ const tokens = promptText.toLowerCase().split(/[^a-z0-9_-]+/);
911
+ const keywords = new Set();
912
+ for (const t of tokens) {
913
+ if (t.length >= COOKBOOK_KEYWORD_MIN_LEN) keywords.add(t);
914
+ }
915
+ return keywords;
916
+ }
917
+
918
+ // AI-11803-STEP5 — scan a loaded skill body for `references/<name>.md`
919
+ // patterns and resolve to absolute paths under the skill's references/
920
+ // directory. Returns array of { skill, cookbookName, absPath }, dedup by
921
+ // absPath so two skills referencing the same cookbook only enqueue it once.
922
+ function discoverCookbookReferences(skillBodies) {
923
+ const found = [];
924
+ const seenPaths = new Set();
925
+ for (const entry of skillBodies) {
926
+ if (!entry.body || typeof entry.body !== 'string') continue;
927
+ COOKBOOK_REF_RX.lastIndex = 0;
928
+ let m;
929
+ while ((m = COOKBOOK_REF_RX.exec(entry.body)) !== null) {
930
+ const crossSkillName = m[1]; // may be undefined for same-skill refs
931
+ const cookbookName = m[2];
932
+ // Resolve to the correct skill directory: cross-skill targets the
933
+ // named other skill; otherwise stays in the source skill's own dir.
934
+ const resolvedSkill = crossSkillName || entry.skill;
935
+ const absPath = `${SKILLS_DIR}/${resolvedSkill}/references/${cookbookName}`;
936
+ if (seenPaths.has(absPath)) continue;
937
+ if (!existsSync(absPath)) continue;
938
+ seenPaths.add(absPath);
939
+ found.push({
940
+ skill: entry.skill,
941
+ referencedSkill: resolvedSkill,
942
+ cookbookName,
943
+ absPath,
944
+ crossSkill: !!crossSkillName,
945
+ });
946
+ }
947
+ }
948
+ return found;
949
+ }
950
+
951
+ // AI-11803-STEP5 — parse a cookbook into sections by `## ` and `### `
952
+ // headers. Each section = { level, title, headerLine, bodyStart, bodyEnd }
953
+ // where bodyEnd is the byte-offset of the next header (or end of file).
954
+ // Returns sections array in document order.
955
+ function parseCookbookSections(cookbookText) {
956
+ const sections = [];
957
+ const lines = cookbookText.split('\n');
958
+ // Build line offsets so we can map header line index → byte offset.
959
+ const lineOffsets = [0];
960
+ for (let i = 0; i < lines.length - 1; i++) {
961
+ lineOffsets.push(lineOffsets[i] + Buffer.byteLength(lines[i], 'utf8') + 1); // +1 for \n
962
+ }
963
+ const totalBytes = Buffer.byteLength(cookbookText, 'utf8');
964
+ // First pass: collect header positions.
965
+ const headerPositions = [];
966
+ for (let i = 0; i < lines.length; i++) {
967
+ const headerMatch = lines[i].match(/^(#{2,3})\s+(.+?)\s*$/);
968
+ if (headerMatch) {
969
+ headerPositions.push({
970
+ level: headerMatch[1].length,
971
+ title: headerMatch[2],
972
+ lineIdx: i,
973
+ byteOffset: lineOffsets[i],
974
+ });
975
+ }
976
+ }
977
+ // Second pass: build sections with bodyEnd = next header byteOffset.
978
+ for (let i = 0; i < headerPositions.length; i++) {
979
+ const h = headerPositions[i];
980
+ const next = headerPositions[i + 1];
981
+ sections.push({
982
+ level: h.level,
983
+ title: h.title,
984
+ headerByteOffset: h.byteOffset,
985
+ bodyEnd: next ? next.byteOffset : totalBytes,
986
+ });
987
+ }
988
+ return sections;
989
+ }
990
+
991
+ // AI-11803-STEP5 — score a section by counting distinct prompt keywords
992
+ // in its body text. Deterministic, observable. Returns integer.
993
+ function scoreSectionByKeywords(cookbookText, section, promptKeywords) {
994
+ if (promptKeywords.size === 0) return 0;
995
+ const sectionText = cookbookText
996
+ .slice(section.headerByteOffset, section.bodyEnd)
997
+ .toLowerCase();
998
+ let score = 0;
999
+ for (const kw of promptKeywords) {
1000
+ if (sectionText.includes(kw)) score++;
1001
+ }
1002
+ return score;
1003
+ }
1004
+
1005
+ // AI-11803-STEP5 — pick the top-1 section for a cookbook by keyword score.
1006
+ // Returns { section, score, extracted } or null if no section meets the
1007
+ // min-score threshold. extracted is the section text capped at
1008
+ // MAX_BYTES_PER_COOKBOOK_SECTION with a truncation marker if needed.
1009
+ function selectTopSectionForCookbook(cookbookText, sections, promptKeywords) {
1010
+ let best = null;
1011
+ for (const sec of sections) {
1012
+ const score = scoreSectionByKeywords(cookbookText, sec, promptKeywords);
1013
+ if (score < COOKBOOK_MIN_SCORE) continue;
1014
+ // Tie-break: later position wins (later sections often more refined).
1015
+ if (best === null || score > best.score || (score === best.score && sec.headerByteOffset > best.section.headerByteOffset)) {
1016
+ best = { section: sec, score };
1017
+ }
1018
+ }
1019
+ if (!best) return null;
1020
+ let extracted = cookbookText.slice(best.section.headerByteOffset, best.section.bodyEnd).trimEnd();
1021
+ if (Buffer.byteLength(extracted, 'utf8') > MAX_BYTES_PER_COOKBOOK_SECTION) {
1022
+ const buf = Buffer.from(extracted, 'utf8').slice(0, MAX_BYTES_PER_COOKBOOK_SECTION);
1023
+ extracted = buf.toString('utf8');
1024
+ const lastBreak = Math.max(extracted.lastIndexOf('\n\n'), extracted.lastIndexOf('\n'));
1025
+ if (lastBreak > MAX_BYTES_PER_COOKBOOK_SECTION * 0.6) extracted = extracted.slice(0, lastBreak);
1026
+ extracted += `\n[…section truncated at ${MAX_BYTES_PER_COOKBOOK_SECTION}B; full section available in source file…]`;
1027
+ }
1028
+ return { section: best.section, score: best.score, extracted };
1029
+ }
1030
+
1031
+ // AI-11803-STEP5 — orchestrate cookbook discovery + selection + injection.
1032
+ // Returns { injected: [{ skill, cookbookName, absPath, sectionTitle,
1033
+ // score, bytes }], totalBytes, scannedCount, skippedBelowThreshold,
1034
+ // errors }. Never throws; on any file-read error, the cookbook is
1035
+ // recorded as skipped with the error reason.
1036
+ function autoloadCookbookSections(skillBodies, promptKeywords) {
1037
+ if (/^(?:1|true|yes|on)$/i.test(String(process.env.ARIA_AUTOLOAD_COOKBOOK_OFF || ''))) {
1038
+ return { injected: [], totalBytes: 0, scannedCount: 0, skippedBelowThreshold: [], errors: [], skipped: 'env-disabled' };
1039
+ }
1040
+ const refs = discoverCookbookReferences(skillBodies);
1041
+ const injected = [];
1042
+ const skippedBelowThreshold = [];
1043
+ const errors = [];
1044
+ let totalBytes = 0;
1045
+ for (const ref of refs) {
1046
+ if (totalBytes >= MAX_BYTES_COOKBOOK_TOTAL) {
1047
+ skippedBelowThreshold.push({ ...ref, reason: 'total-budget-exhausted' });
1048
+ continue;
1049
+ }
1050
+ let lst;
1051
+ try { lst = lstatSync(ref.absPath); } catch (err) {
1052
+ errors.push(`lstat ${ref.cookbookName}: ${err?.message || err}`);
1053
+ continue;
1054
+ }
1055
+ if (!lst.isFile()) continue;
1056
+ if (lst.size > COOKBOOK_FILE_CEILING) {
1057
+ errors.push(`oversize ${ref.cookbookName}: ${lst.size}B > ${COOKBOOK_FILE_CEILING}B`);
1058
+ continue;
1059
+ }
1060
+ let raw;
1061
+ try { raw = readFileSync(ref.absPath, 'utf8'); } catch (err) {
1062
+ errors.push(`read ${ref.cookbookName}: ${err?.message || err}`);
1063
+ continue;
1064
+ }
1065
+ const sections = parseCookbookSections(raw);
1066
+ if (sections.length === 0) {
1067
+ skippedBelowThreshold.push({ ...ref, reason: 'no-sections-parsed' });
1068
+ continue;
1069
+ }
1070
+ const result = selectTopSectionForCookbook(raw, sections, promptKeywords);
1071
+ if (!result) {
1072
+ skippedBelowThreshold.push({ ...ref, reason: `no-section-met-min-score-${COOKBOOK_MIN_SCORE}` });
1073
+ continue;
1074
+ }
1075
+ const remainingBudget = MAX_BYTES_COOKBOOK_TOTAL - totalBytes;
1076
+ const extractedBytes = Buffer.byteLength(result.extracted, 'utf8');
1077
+ if (extractedBytes > remainingBudget) {
1078
+ skippedBelowThreshold.push({ ...ref, reason: `total-budget-would-overflow (${extractedBytes}B > ${remainingBudget}B remaining)` });
1079
+ continue;
1080
+ }
1081
+ injected.push({
1082
+ skill: ref.skill,
1083
+ cookbookName: ref.cookbookName,
1084
+ absPath: ref.absPath,
1085
+ sectionTitle: result.section.title,
1086
+ score: result.score,
1087
+ bytes: extractedBytes,
1088
+ extracted: result.extracted,
1089
+ });
1090
+ totalBytes += extractedBytes;
1091
+ }
1092
+ return { injected, totalBytes, scannedCount: refs.length, skippedBelowThreshold, errors, skipped: null };
1093
+ }
1094
+
1095
+ function buildCookbookInjection({ result, promptKeywords }) {
1096
+ if (result.skipped === 'env-disabled') return '';
1097
+ if (result.injected.length === 0) {
1098
+ // Emit a low-information stub only when at least 1 cookbook was scanned
1099
+ // but none scored above threshold — surfaces signal that scoring fired
1100
+ // but selected nothing, so the agent knows cookbook context is empty
1101
+ // by design, not by error.
1102
+ if (result.scannedCount > 0) {
1103
+ return `═══ COOKBOOK AUTOLOAD (scanned ${result.scannedCount} cookbook(s); 0 section(s) met min-score=${COOKBOOK_MIN_SCORE}; ${promptKeywords.size} prompt keywords) ═══`;
1104
+ }
1105
+ return '';
1106
+ }
1107
+ const lines = [];
1108
+ lines.push(`═══ COOKBOOK AUTOLOAD (top-1 sections from ${result.injected.length} cookbook(s); deterministic keyword-overlap scoring) ═══`);
1109
+ for (const entry of result.injected) {
1110
+ lines.push('');
1111
+ lines.push(`──── ${entry.cookbookName} [section: "${entry.sectionTitle}" — score=${entry.score}] ────`);
1112
+ lines.push(entry.extracted);
1113
+ }
1114
+ return lines.join('\n');
1115
+ }
1116
+
1117
+ // AI-11803-F3 (2026-05-12) — read the parent handoff JSON if present
1118
+ // and within TTL. Returns the `parentAutoload` field (skill names,
1119
+ // memory filenames, cookbook section pointers) or null if absent / stale
1120
+ // / kill-switched / malformed.
1121
+ function readParentHandoffAutoload() {
1122
+ if (/^(?:1|true|yes|on)$/i.test(String(process.env.ARIA_AUTOLOAD_PARENT_HANDOFF_OFF || ''))) {
1123
+ return { result: null, skipped: 'env-disabled' };
1124
+ }
1125
+ if (!existsSync(PARENT_HANDOFF_PATH)) {
1126
+ return { result: null, skipped: 'no-handoff-file' };
1127
+ }
1128
+ let raw;
1129
+ try { raw = readFileSync(PARENT_HANDOFF_PATH, 'utf-8'); } catch (err) {
1130
+ process.stderr.write(`[aria-pre-emit-autoload:parent-handoff-read-error] ${err?.message || err}\n`);
1131
+ return { result: null, skipped: `read-error:${err?.message || err}` };
1132
+ }
1133
+ let parsed;
1134
+ try { parsed = JSON.parse(raw); } catch (err) {
1135
+ process.stderr.write(`[aria-pre-emit-autoload:parent-handoff-parse-error] ${err?.message || err}\n`);
1136
+ return { result: null, skipped: `parse-error:${err?.message || err}` };
1137
+ }
1138
+ // TTL check — if handoff older than ttlMs vs writtenAt, ignore.
1139
+ const ttlMs = Number(parsed.ttlMs) || (5 * 60 * 1000);
1140
+ const writtenAtMs = new Date(parsed.writtenAt || 0).getTime();
1141
+ if (Number.isFinite(writtenAtMs) && writtenAtMs > 0) {
1142
+ const ageMs = Date.now() - writtenAtMs;
1143
+ if (ageMs > ttlMs) {
1144
+ return { result: null, skipped: `stale:age=${Math.round(ageMs/1000)}s>ttl=${Math.round(ttlMs/1000)}s` };
1145
+ }
1146
+ }
1147
+ const parentAutoload = parsed.parentAutoload;
1148
+ if (!parentAutoload || typeof parentAutoload !== 'object') {
1149
+ return { result: null, skipped: 'no-parentAutoload-field' };
1150
+ }
1151
+ return { result: parentAutoload, skipped: null, ageMs: Date.now() - writtenAtMs };
1152
+ }
1153
+
1154
+ // Default cognition vocabulary anchors the named-lens labels the
1155
+ // substrate-binding gate parses. Agents in the same session converge on
1156
+ // one vocabulary so emissions stay coherent across a turn.
1157
+ function chooseCognitionVocabulary() {
1158
+ return ['nur', 'mizan', 'hikma', 'tafakkur', 'tadabbur', 'ilham', 'wahi', 'firasah'];
1159
+ }
1160
+
1161
+ // Stage 5 — cross-turn substrate feedback: read recent gate-block events
1162
+ // from the gate-ledger and surface them as next-turn FRAME content. This
1163
+ // turns past gate-blocks into structural pressure on the next turn so the
1164
+ // agent literally cannot drift the same way twice without seeing it.
1165
+ function readRecentGateBlocks({ maxAgeMinutes = 30, maxEntries = 8, sessionId = null } = {}) {
1166
+ const ledgerPath = `${HOME}/.claude/.aria-gate-ledger.jsonl`;
1167
+ if (!existsSync(ledgerPath)) return [];
1168
+ let raw;
1169
+ try {
1170
+ raw = readFileSync(ledgerPath, 'utf8');
1171
+ } catch {
1172
+ return [];
1173
+ }
1174
+ const lines = raw.split('\n').filter(Boolean);
1175
+ const recent = lines.slice(-300); // bound the parse cost
1176
+ const cutoff = Date.now() - maxAgeMinutes * 60 * 1000;
1177
+ const blocks = [];
1178
+ for (let i = recent.length - 1; i >= 0 && blocks.length < maxEntries; i--) {
1179
+ let entry;
1180
+ try { entry = JSON.parse(recent[i]); } catch { continue; }
1181
+ if (!entry || typeof entry !== 'object') continue;
1182
+ if (entry.decision !== 'block') continue;
1183
+ const t = Date.parse(entry.ts || '');
1184
+ if (!Number.isFinite(t) || t < cutoff) continue;
1185
+ if (sessionId && entry.sessionId && entry.sessionId !== sessionId) continue;
1186
+ blocks.push({
1187
+ ts: entry.ts,
1188
+ hook: entry.hook,
1189
+ source: entry.source,
1190
+ reason: entry.reasonShort || '(no reason)',
1191
+ });
1192
+ }
1193
+ return blocks;
1194
+ }
1195
+
1196
+ function buildFrameInjection({ requiredSkills, reasons, redirectOnly, cognitionVocab, skillBodies, totalBytes, recentBlocks = [] }) {
1197
+ if (!requiredSkills || requiredSkills.length === 0) {
1198
+ const lines = [`${HEADER_PREFIX} no doctrine-bound skills required for this prompt; standard cognition expected.`];
1199
+ if (recentBlocks && recentBlocks.length > 0) {
1200
+ lines.push('');
1201
+ lines.push('═══ STAGE 5 — RECENT GATE BLOCKS (cross-turn substrate feedback) ═══');
1202
+ lines.push(`Past ${recentBlocks.length} block(s) within last 30 minutes for this session — adjust this turn to NOT recur:`);
1203
+ for (const b of recentBlocks) {
1204
+ lines.push(` - [${b.hook}] ${b.source}: ${b.reason}`);
1205
+ }
1206
+ lines.push('Apply the lesson: same block reason in this turn means same drift pattern; address the root, not the surface.');
1207
+ }
1208
+ return lines.join('\n');
1209
+ }
1210
+ const lines = [];
1211
+ lines.push(`${HEADER_PREFIX} FRAME — required skills loaded for this turn (content below should shape your work BEFORE you draft).`);
1212
+ lines.push('');
1213
+ lines.push(`Required skills (${requiredSkills.length}): ${requiredSkills.join(', ')}`);
1214
+ if (reasons.length > 0) {
1215
+ lines.push('Why these skills:');
1216
+ for (const reason of reasons) lines.push(` - ${reason}`);
1217
+ }
1218
+ lines.push('');
1219
+ lines.push(`Total injected: ${totalBytes}B across ${skillBodies.filter(s => s.bytes > 0).length} skill(s).`);
1220
+ lines.push('');
1221
+ lines.push('═══ SKILL BODIES (operative content — apply, do not narrate) ═══');
1222
+ lines.push('');
1223
+ for (const entry of skillBodies) {
1224
+ if (entry.bytes === 0) {
1225
+ if (entry.reason !== 'missing' && entry.reason !== 'ok') {
1226
+ lines.push(`──── ${entry.skill} ──── [SKIPPED: ${entry.reason}]`);
1227
+ lines.push('');
1228
+ }
1229
+ continue;
1230
+ }
1231
+ lines.push(`──── ${entry.skill}${entry.truncated ? ' (truncated)' : ''} ────`);
1232
+ lines.push(entry.body);
1233
+ lines.push('');
1234
+ }
1235
+ lines.push('═══ END SKILL BODIES ═══');
1236
+ lines.push('');
1237
+ lines.push('═══ DRIVING RULES (apply during work) ═══');
1238
+ lines.push('- Each skill above carries operative rules. Apply them as you draft, edit, and tool-call.');
1239
+ lines.push('- Do NOT emit lens blocks as ceremony at end-of-turn. The lens IS the thinking that already happened.');
1240
+ lines.push('- If a skill names a doctrine memory, treat it as an active constraint, not a citation.');
1241
+ lines.push('- If two skills conflict, the more specific one (e.g., aria-harness-deploy) outranks the general (e.g., aria-forge-guardrails).');
1242
+ lines.push('');
1243
+ lines.push('═══ COGNITION VOCABULARY ═══');
1244
+ lines.push(`Use these named lenses for substantive emissions: ${cognitionVocab.join(', ')}`);
1245
+ lines.push('Per substantive action emit:');
1246
+ lines.push(' <cognition> with all 8 named lenses (≥20 chars per lens, anchored to substrate)');
1247
+ lines.push(' <expected> with measurable predicate');
1248
+ lines.push(' <applied_cognition> with decision_delta + dominant_domain + binds_to + expected_predicate + artifact_change');
1249
+ lines.push('');
1250
+ lines.push('═══ POST-QA CRITERIA (verify before completion claim) ═══');
1251
+ lines.push('- Did at least one substrate change as a result of cognition firing?');
1252
+ lines.push('- Is every readiness/completion word ("done", "fixed", "shipped", "verified") backed by tool-output evidence?');
1253
+ lines.push('- Does the closing prose match output discipline (no raw IPs/SHAs/file-paths in chat; semantic reframing applied)?');
1254
+ lines.push('- Are unresolved discoveries either fixed-now or tracked-as-task before turn end?');
1255
+ lines.push('');
1256
+ lines.push('═══ PHASE 2 ORCHESTRATION MANIFEST CONTRACT ═══');
1257
+ lines.push('For substantive turns, emit an OrchestrationManifest_v1 alongside the response so downstream hooks consume typed workflow/gate fields instead of prompt-keyword guesses.');
1258
+ lines.push('Accepted shape: <orchestration_manifest>{...JSON...}</orchestration_manifest> or a json-fenced object with schema_version:"v1".');
1259
+ lines.push('The manifest is the workflow-routing source: intent.workflow_skills_to_invoke names active workflows; gates.* names cognition/verification requirements; voice.* names response shape.');
1260
+ lines.push('No manifest means downstream hooks keep the strict legacy gate path.');
1261
+ if (redirectOnly) {
1262
+ lines.push('');
1263
+ lines.push('NOTE: redirectOnly mode — gate guides not hard-blocks. Treat guidance as quality bar, not skip-license.');
1264
+ }
1265
+ if (recentBlocks && recentBlocks.length > 0) {
1266
+ lines.push('');
1267
+ lines.push('═══ STAGE 5 — RECENT GATE BLOCKS (cross-turn substrate feedback) ═══');
1268
+ lines.push(`Past ${recentBlocks.length} block(s) within last 30 minutes for this session — adjust this turn to NOT recur:`);
1269
+ for (const b of recentBlocks) {
1270
+ lines.push(` - [${b.hook}] ${b.source}: ${b.reason}`);
1271
+ }
1272
+ lines.push('Apply the lesson: the same block reason in this turn means the same drift pattern; address the root, not the surface.');
1273
+ }
1274
+ return lines.join('\n');
1275
+ }
1276
+
1277
+ // Canonical floor substrate that loads unconditionally for any non-empty
1278
+ // prompt. Step 6 removes autoload's prompt-keyword classifier from the
1279
+ // UserPromptSubmit path: workflow choice moves to the emitted manifest,
1280
+ // while this floor keeps evidence, doctrine, output, and source-trust rules
1281
+ // present before drafting.
1282
+ const CANONICAL_FLOOR_SKILLS = [
1283
+ 'aria-cognition-autofire',
1284
+ 'aria-first-class-operating-contract',
1285
+ 'aria-harness-output-discipline',
1286
+ 'aria-readable-output',
1287
+ 'aria-repo-doctrine',
1288
+ 'never-guess',
1289
+ ];
1290
+
1291
+ // AI-11803-F5 (2026-05-12): active-workflow skill allow-list. These
1292
+ // skills have explicit "Required Workflow" / "Apply the pipeline" /
1293
+ // "TRIGGER for cognitive turn" imperatives in their bodies. Loading
1294
+ // them as context is NOT the same as running their workflow — the LLM
1295
+ // MUST invoke them via the Skill tool when their body is loaded.
1296
+ // See feedback_autoload_does_not_invoke_skills.md for the full Recovery
1297
+ // Contract (classification A/B/C/D, 5-per-turn cap, parent composition).
1298
+ // Maintenance protocol: review new skills' frontmatter for active-shape
1299
+ // signals; add to this list. False-positive operator-frustration → move
1300
+ // back to passive-substrate (default).
1301
+ // QA-FIX-1 (2026-05-12, qiyas Tadabbur EXCAVATE): allow-list expanded from
1302
+ // 5 to 8 after qiyas+tadabbur QA pass found 3 missing active-workflow
1303
+ // skills. ghazali-8lens has explicit Required Workflow + 8-lens validation
1304
+ // pipeline. aria-decision-mizan is active refusal-shape (refuses to choose
1305
+ // for owner, surfaces both options — active not passive). tafakkur has
1306
+ // explicit 5-lens contemplation workflow. Cap is per-TURN INVOCATION count
1307
+ // (5), not list size; list can grow as more active skills are identified.
1308
+ const ACTIVE_WORKFLOW_SKILLS = new Set([
1309
+ 'tadabbur',
1310
+ 'qiyas-analogy',
1311
+ 'aria-cognition-batch',
1312
+ 'mizan',
1313
+ 'aria-forge-guardrails',
1314
+ 'ghazali-8lens',
1315
+ 'aria-decision-mizan',
1316
+ 'tafakkur',
1317
+ ]);
1318
+ const INVOCATION_CAP_PER_TURN = 5;
1319
+
1320
+ async function main() {
1321
+ const event = readEvent();
1322
+ const prompt = String(
1323
+ event.user_prompt ??
1324
+ event.userPrompt ??
1325
+ event.prompt ??
1326
+ event.text ??
1327
+ event.message ??
1328
+ ''
1329
+ ).trim();
1330
+
1331
+ // ARIA_AUTOLOAD_DISABLE is the proper kill switch for this hook
1332
+ // specifically. Use only when debugging the autoload itself. The
1333
+ // gates-off marker is for blocking gates, NOT for disabling content
1334
+ // enrichment — disabling enrichment is exactly what made cognition
1335
+ // ceremonial in the first place.
1336
+ if (/^(?:1|true|yes|on)$/i.test(String(process.env.ARIA_AUTOLOAD_DISABLE || ''))) {
1337
+ appendGateLedger({ hook: 'pre-emit-autoload', event: HOOK_EVENT_NAME, decision: 'bypass', source: 'pre-emit/autoload-disabled-env', reasonShort: 'ARIA_AUTOLOAD_DISABLE=1', sessionId: event.session_id });
1338
+ emitNoop('ARIA_AUTOLOAD_DISABLE=1');
1339
+ }
1340
+
1341
+ if (!prompt) {
1342
+ appendGateLedger({ hook: 'pre-emit-autoload', event: HOOK_EVENT_NAME, decision: 'allow', source: 'pre-emit/empty-prompt', sessionId: event.session_id });
1343
+ emitNoop('empty user prompt');
1344
+ }
1345
+
1346
+ const classified = {
1347
+ requiredSkills: [],
1348
+ recoveryMissing: [],
1349
+ reasons: ['Phase 2 manifest-mode autoload: canonical floor substrate loaded; workflow invocation is manifest-driven.'],
1350
+ redirectOnly: false,
1351
+ };
1352
+
1353
+ const initialSkillSet = new Set();
1354
+ for (const s of CANONICAL_FLOOR_SKILLS) {
1355
+ if (existsSync(`${SKILLS_DIR}/${s}/SKILL.md`)) initialSkillSet.add(s);
1356
+ }
1357
+
1358
+ // AI-11803-F3: parent-handoff substrate inheritance. If this autoload
1359
+ // is firing inside a sub-agent session, layer the parent's pinned
1360
+ // skill names into the load set BEFORE cascade expansion. Sub-agent's
1361
+ // own classifier output is preserved (already in initialSkillSet);
1362
+ // parent pins are additive — sub-agent sees its own narrow-prompt
1363
+ // skills + the parent's broader doctrine context.
1364
+ const parentHandoffRead = readParentHandoffAutoload();
1365
+ const parentHandoff = parentHandoffRead.result;
1366
+ if (parentHandoff && Array.isArray(parentHandoff.requiredSkills)) {
1367
+ let inheritedCount = 0;
1368
+ for (const s of parentHandoff.requiredSkills) {
1369
+ if (typeof s !== 'string') continue;
1370
+ if (existsSync(`${SKILLS_DIR}/${s}/SKILL.md`) && !initialSkillSet.has(s)) {
1371
+ initialSkillSet.add(s);
1372
+ inheritedCount++;
1373
+ }
1374
+ }
1375
+ process.stderr.write(`[aria-pre-emit-autoload:parent-handoff-inherited] skills=${inheritedCount} memories=${(parentHandoff.memoryFilenames||[]).length} cookbooks=${(parentHandoff.cookbookSelections||[]).length} ageMs=${parentHandoffRead.ageMs}\n`);
1376
+ }
1377
+
1378
+ const cognitionVocab = chooseCognitionVocabulary();
1379
+
1380
+ // AI-11803-LOOP1 (2026-05-12) — cascade expansion replaces the prior
1381
+ // single-pass body-injection loop. The cascade reads each skill body,
1382
+ // parses its Load First / Mode Selection / Load Order sections, and
1383
+ // recursively enqueues the named skills (existence-filtered, cycle-safe,
1384
+ // budget-capped). Final requiredSkills reflects the FULL loaded set so
1385
+ // sidecar + ledger downstream consumers see what actually ran in context.
1386
+ const cascade = expandSkillCascade([...initialSkillSet]);
1387
+
1388
+ // A5 (2026-05-18) — atlas-as-orchestrator: query the atlas daemon for
1389
+ // per-file governing_skills against path-shape tokens harvested from the
1390
+ // prompt. Unioned into cascade BEFORE the kernel selection block so the
1391
+ // kernel sees a substrate already enriched by atlas's per-target knowledge.
1392
+ // Fail-open: if atlas socket is down or every target returns 404 the
1393
+ // manifest is unchanged from the cascade floor. Helper LOUD-on-fail per
1394
+ // feedback_no_silent_fail_open_in_hooks.md.
1395
+ let atlasOrchestrator = null;
1396
+ let atlasOrchestratorErr = null;
1397
+ try {
1398
+ const promptTargets = harvestPromptTargets(prompt);
1399
+ if (promptTargets.length > 0) {
1400
+ atlasOrchestrator = await atlasGoverningSkillsForPrompt(promptTargets);
1401
+ let unionedByDossier = 0;
1402
+ for (const s of atlasOrchestrator.governingSkills) {
1403
+ if (typeof s !== 'string') continue;
1404
+ if (cascade.order.includes(s)) continue;
1405
+ if (existsSync(`${SKILLS_DIR}/${s}/SKILL.md`)) {
1406
+ cascade.order.push(s);
1407
+ unionedByDossier++;
1408
+ }
1409
+ }
1410
+ atlasOrchestrator.targetsHarvested = promptTargets.length;
1411
+ atlasOrchestrator.unionedByDossier = unionedByDossier;
1412
+ process.stderr.write(`[aria-pre-emit-autoload:atlas-orchestrator] targets=${promptTargets.length} resolved=${atlasOrchestrator.targetsResolved} err=${atlasOrchestrator.targetsErr} governingSkills=${atlasOrchestrator.governingSkills.length} unioned=${unionedByDossier} durationMs=${atlasOrchestrator.durationMs}\n`);
1413
+ } else {
1414
+ atlasOrchestrator = { governingSkills: [], targetsHarvested: 0, targetsResolved: 0, targetsErr: 0, unionedByDossier: 0, durationMs: 0 };
1415
+ }
1416
+ } catch (err) {
1417
+ atlasOrchestratorErr = err?.message || String(err);
1418
+ process.stderr.write(`[aria-pre-emit-autoload:atlas-orchestrator-fallback] LOUD-fail err=${atlasOrchestratorErr} — falling back to cascade+kernel-only manifest\n`);
1419
+ }
1420
+
1421
+ // A3 + A4 (2026-05-17) — atlas-driven skill selection feeds back into the
1422
+ // cascade BEFORE the requiredSkills publish. Kernel sees observation kind,
1423
+ // prior end-phase court verdicts (A4 loop), and returns selectedSkillIds.
1424
+ // UNIONed into cascade.order (additive — never replaces the cascade floor)
1425
+ // so the manifest carries both the doctrinal floor + atlas's per-turn
1426
+ // reinforcement. Failure path: LOUD-stderr + fall back to cascade-only.
1427
+ let atlasSelection = null;
1428
+ let atlasSelectionErr = null;
1429
+ try {
1430
+ const priorCourtVerdicts = readRecentCourtVerdicts();
1431
+ const observationKind = (() => {
1432
+ const cls = classified?.taskClass || classified?.kind || '';
1433
+ if (typeof cls !== 'string') return 'default';
1434
+ // Map autoload's task class vocabulary onto kernel SKILL_SELECTION_MAP keys.
1435
+ // Conservative: known kinds pass through; everything else hits 'default'
1436
+ // (kernel handles unknown keys via its own default branch).
1437
+ if (['output_emit', 'goal_contract_eval', 'edit', 'deploy', 'sensitive_artifact_in_tool_input'].includes(cls)) return cls;
1438
+ return 'default';
1439
+ })();
1440
+ const compilation = compileCognitiveOptions({
1441
+ kind: observationKind,
1442
+ source: 'aria-pre-emit-autoload',
1443
+ summary: 'turn-start skill+runtime selection (A3/A4 autofire)',
1444
+ attrs: {
1445
+ surface: 'claude-code',
1446
+ priorCourtVerdictsCount: priorCourtVerdicts.length,
1447
+ },
1448
+ priorCourtVerdicts,
1449
+ evidence: priorCourtVerdicts.map((v, idx) => ({
1450
+ kind: 'prior_court_verdict',
1451
+ id: `court_${idx}`,
1452
+ value: v.verdict,
1453
+ at: v.at,
1454
+ })),
1455
+ });
1456
+ atlasSelection = {
1457
+ selectedSkillIds: Array.isArray(compilation?.selectedSkillIds) ? compilation.selectedSkillIds : [],
1458
+ selectedRuntimeIds: Array.isArray(compilation?.selectedRuntimeIds) ? compilation.selectedRuntimeIds : [],
1459
+ selectionMeta: compilation?.selectionMeta || null,
1460
+ compilation_hash: compilation?.compilation_hash || null,
1461
+ observationKind,
1462
+ priorCourtVerdictCount: priorCourtVerdicts.length,
1463
+ };
1464
+ // UNION: add kernel-selected skills that exist on disk + aren't already cascaded
1465
+ let unioned = 0;
1466
+ for (const s of atlasSelection.selectedSkillIds) {
1467
+ if (typeof s !== 'string') continue;
1468
+ if (cascade.order.includes(s)) continue;
1469
+ if (existsSync(`${SKILLS_DIR}/${s}/SKILL.md`)) {
1470
+ cascade.order.push(s);
1471
+ unioned++;
1472
+ }
1473
+ }
1474
+ atlasSelection.unionedSkillCount = unioned;
1475
+ process.stderr.write(`[aria-pre-emit-autoload:atlas-selection] kind=${atlasSelection.observationKind} selected=${atlasSelection.selectedSkillIds.length} runtimes=${atlasSelection.selectedRuntimeIds.length} unioned=${unioned} courtFeedback=${Boolean(atlasSelection.selectionMeta?.courtFeedbackApplied)} priorVerdicts=${atlasSelection.priorCourtVerdictCount} hash=${(atlasSelection.compilation_hash || '').slice(0, 12)}\n`);
1476
+ } catch (err) {
1477
+ atlasSelectionErr = err?.message || String(err);
1478
+ process.stderr.write(`[aria-pre-emit-autoload:atlas-selection-fallback] LOUD-fail err=${atlasSelectionErr} — falling back to cascade-only manifest (no behavior change vs pre-A3 baseline)\n`);
1479
+ }
1480
+
1481
+ classified.requiredSkills = [...new Set(cascade.order)].sort();
1482
+ const skillBodies = cascade.order.map((skill) => ({ skill, ...cascade.loadedBodies.get(skill) }));
1483
+ const totalBytes = cascade.totalBytes;
1484
+ const cascadeDepth = cascade.cascadeDepth;
1485
+ const depthInjected = cascade.depthInjected;
1486
+ const depthAttempted = cascade.depthAttempted;
1487
+ const cascadedSkills = cascade.order.filter((s) => !initialSkillSet.has(s));
1488
+
1489
+ // AI-11803-LOOP2: doctrine-trigger pre-emit scan. Matches the prompt
1490
+ // against the 79-trigger map. Computed here (before sidecar+ledger writes)
1491
+ // so its results land in the meta + sidecar telemetry too.
1492
+ const doctrineScan = scanDoctrineTriggers(prompt);
1493
+
1494
+ // AI-11803-F5 (2026-05-12) — compute invocationRequired set: which of
1495
+ // the loaded skills this turn are active-workflow (Skill tool MUST be
1496
+ // called) vs passive-substrate (body-as-context is sufficient). Capped
1497
+ // at INVOCATION_CAP_PER_TURN to prevent operator-overhead from too many
1498
+ // sequential invocations. The list is surfaced to the LLM via a
1499
+ // dedicated additionalContext section AND persisted to sidecar so the
1500
+ // future F5.c stop-gate can verify the named skills were actually
1501
+ // invoked before turn-close.
1502
+ //
1503
+ // QA-FIX-2 (2026-05-12): source the candidate skills from cascade.order
1504
+ // (the FINAL loaded set after cascade expansion) instead of
1505
+ // classified.requiredSkills (initial classifier output). Cascade can
1506
+ // pull active-workflow skills depth-N (e.g. aria-cognition-batch in
1507
+ // initial set loads tadabbur via Load First section); those depth-N
1508
+ // active skills must also appear in invocationRequired or the contract
1509
+ // misses them.
1510
+ //
1511
+ // QA-FIX-3 (2026-05-12): include parent-handoff inherited active skills
1512
+ // so sub-agents continue to honor the parent's invocation requirements
1513
+ // even when the sub-agent's own classifier didn't trigger them.
1514
+ const invocationRequiredSet = new Set();
1515
+ for (const skill of cascade.order) {
1516
+ if (invocationRequiredSet.size >= INVOCATION_CAP_PER_TURN) break;
1517
+ if (ACTIVE_WORKFLOW_SKILLS.has(skill)) invocationRequiredSet.add(skill);
1518
+ }
1519
+ if (parentHandoff && Array.isArray(parentHandoff.invocationRequired)) {
1520
+ for (const skill of parentHandoff.invocationRequired) {
1521
+ if (invocationRequiredSet.size >= INVOCATION_CAP_PER_TURN) break;
1522
+ if (typeof skill === 'string' && ACTIVE_WORKFLOW_SKILLS.has(skill)) {
1523
+ invocationRequiredSet.add(skill);
1524
+ }
1525
+ }
1526
+ }
1527
+ // A5 (2026-05-18) — atlas-orchestrator + kernel-class selections force-add
1528
+ // to invocationRequired regardless of ACTIVE_WORKFLOW_SKILLS membership.
1529
+ // Atlas's per-turn selection IS the trigger; pre-tool-gate enforces these
1530
+ // as a floor before any Bash/Edit/Write/NotebookEdit. Closes the
1531
+ // mechanical-firing gap surfaced by feedback_substrate_load_session_violation
1532
+ // _2026_05_14.md (substrate loaded, invocation absent). Cap honored.
1533
+ const atlasForceInvoke = [];
1534
+ if (atlasOrchestrator && Array.isArray(atlasOrchestrator.governingSkills)) {
1535
+ for (const s of atlasOrchestrator.governingSkills) {
1536
+ if (invocationRequiredSet.size >= INVOCATION_CAP_PER_TURN) break;
1537
+ if (typeof s !== 'string' || !s.trim()) continue;
1538
+ if (invocationRequiredSet.has(s)) continue;
1539
+ if (existsSync(`${SKILLS_DIR}/${s}/SKILL.md`)) {
1540
+ invocationRequiredSet.add(s);
1541
+ atlasForceInvoke.push({ source: 'atlas-dossier', skill: s });
1542
+ }
1543
+ }
1544
+ }
1545
+ if (atlasSelection && Array.isArray(atlasSelection.selectedSkillIds)) {
1546
+ for (const s of atlasSelection.selectedSkillIds) {
1547
+ if (invocationRequiredSet.size >= INVOCATION_CAP_PER_TURN) break;
1548
+ if (typeof s !== 'string' || !s.trim()) continue;
1549
+ if (invocationRequiredSet.has(s)) continue;
1550
+ if (existsSync(`${SKILLS_DIR}/${s}/SKILL.md`)) {
1551
+ invocationRequiredSet.add(s);
1552
+ atlasForceInvoke.push({ source: 'atlas-kernel-class', skill: s });
1553
+ }
1554
+ }
1555
+ }
1556
+ // A5 hardening loop — read prior-turn atlas-orchestrator hardening
1557
+ // directives from the hive WAL. Each directive lists skills that were
1558
+ // selected-by-atlas the prior turn but NOT invoked (adherence gap) OR
1559
+ // were ordered re-invoked because the QA court verdict was below
1560
+ // verified. Force-add to invocationRequired this turn. Same cap.
1561
+ const hardeningDirectives = readRecentHardeningDirectives();
1562
+ for (const directive of hardeningDirectives) {
1563
+ if (invocationRequiredSet.size >= INVOCATION_CAP_PER_TURN) break;
1564
+ for (const s of directive.forceInvokeNextTurn || []) {
1565
+ if (invocationRequiredSet.size >= INVOCATION_CAP_PER_TURN) break;
1566
+ if (typeof s !== 'string' || !s.trim()) continue;
1567
+ if (invocationRequiredSet.has(s)) continue;
1568
+ if (existsSync(`${SKILLS_DIR}/${s}/SKILL.md`)) {
1569
+ invocationRequiredSet.add(s);
1570
+ atlasForceInvoke.push({ source: 'atlas-hardening-directive', skill: s, reason: directive.reason });
1571
+ }
1572
+ }
1573
+ }
1574
+ const invocationRequired = [...invocationRequiredSet];
1575
+ if (atlasForceInvoke.length > 0) {
1576
+ const sourceCounts = atlasForceInvoke.reduce((acc, e) => { acc[e.source] = (acc[e.source] || 0) + 1; return acc; }, {});
1577
+ process.stderr.write(`[aria-pre-emit-autoload:atlas-invocation-floor] forced=${atlasForceInvoke.length} bySource=${JSON.stringify(sourceCounts)} hardeningDirectivesRead=${hardeningDirectives.length}\n`);
1578
+ }
1579
+
1580
+ // AI-11803-STEP4 (2026-05-12) — MEMORY.md auto-load + top-N body injection.
1581
+ // Dedup set: memories already injected via trigger-map this turn must not
1582
+ // double-inject as top-N bodies (would waste budget + repeat content).
1583
+ // QA-FIX-2 (2026-05-12): kill switch parity with cascade + trigger-map.
1584
+ // ARIA_AUTOLOAD_MEMORY_OFF=1 disables memory autoload while leaving the
1585
+ // other primitives running, for isolated debugging of this primitive.
1586
+ const memoryAutoloadDisabled = /^(?:1|true|yes|on)$/i.test(String(process.env.ARIA_AUTOLOAD_MEMORY_OFF || ''));
1587
+ const triggerMatchedMemories = new Set(doctrineScan.matches.map((m) => m.memory));
1588
+ const memoryIndexResult = memoryAutoloadDisabled
1589
+ ? { body: '', bytes: 0, totalLines: 0, droppedLines: 0, reason: 'env-disabled' }
1590
+ : readMemoryIndex();
1591
+ const memoryBodyResult = memoryAutoloadDisabled
1592
+ ? { injected: [], totalBytes: 0, dedupedFilenames: [], scoredCount: 0, errors: [] }
1593
+ : selectTopNMemoryBodies(triggerMatchedMemories);
1594
+
1595
+ // AI-11803-STEP5 (2026-05-12) — cookbook auto-pull from loaded skill bodies.
1596
+ // Scans skillBodies for `references/<name>.md` patterns, parses each
1597
+ // cookbook's sections, scores by prompt-keyword overlap, injects top-1
1598
+ // section per cookbook above min-score threshold. Same-turn dedup via
1599
+ // Set of absPath. Loop-safe: depth cap = 1 (cookbooks don't transitively
1600
+ // pull other cookbooks). Kill switch: ARIA_AUTOLOAD_COOKBOOK_OFF=1.
1601
+ const promptKeywords = extractPromptKeywords(prompt);
1602
+ const cookbookResult = autoloadCookbookSections(skillBodies, promptKeywords);
1603
+ const substrateOpen = await openRuntimeSubstrate({
1604
+ event,
1605
+ prompt,
1606
+ requiredSkills: classified.requiredSkills,
1607
+ });
1608
+
1609
+ const sidecar = {
1610
+ schema: 'aria-current-turn-context.v2',
1611
+ ts: new Date().toISOString(),
1612
+ sessionId: event.session_id ?? null,
1613
+ // AI-11803-F3: chain-depth marker — if this autoload inherited parent
1614
+ // handoff substrate, downstream Agent dispatch hook reads this and
1615
+ // SKIPS propagating to grandchild (chain depth cap = 1).
1616
+ parentHandoffChainDepth: parentHandoff ? 1 : 0,
1617
+ parentHandoffSkipped: parentHandoffRead.skipped,
1618
+ // AI-11803-F5: active-workflow skills that MUST be invoked via the
1619
+ // Skill tool this turn. Doctrine: feedback_autoload_does_not_invoke_skills.md.
1620
+ // The F5.c stop-gate (future step) reads this and verifies invocations
1621
+ // before turn-close.
1622
+ invocationRequired,
1623
+ promptHash: createHash('sha256').update(prompt).digest('hex').slice(0, 16),
1624
+ requiredSkills: classified.requiredSkills,
1625
+ redirectOnly: classified.redirectOnly === true,
1626
+ reasons: classified.reasons,
1627
+ cognitionVocabulary: cognitionVocab,
1628
+ injection: {
1629
+ totalBytes,
1630
+ perSkill: skillBodies.map(s => ({
1631
+ skill: s.skill,
1632
+ bytes: s.bytes,
1633
+ fullBytes: s.fullBytes,
1634
+ truncated: !!s.truncated,
1635
+ redacted: !!s.redacted,
1636
+ reason: s.reason,
1637
+ // First 600 chars of injected body so post-phase can verify what
1638
+ // was actually visible to the agent.
1639
+ excerpt: typeof s.body === 'string' ? s.body.slice(0, 600) : '',
1640
+ })),
1641
+ },
1642
+ memoryAutoload: {
1643
+ indexBytes: memoryIndexResult.bytes,
1644
+ indexReason: memoryIndexResult.reason,
1645
+ indexDroppedLines: memoryIndexResult.droppedLines,
1646
+ bodiesBytes: memoryBodyResult.totalBytes,
1647
+ bodiesInjected: memoryBodyResult.injected.map((e) => ({
1648
+ filename: e.filename, tier: e.tier, score: e.score, bytes: e.bytes,
1649
+ })),
1650
+ bodiesDeduped: memoryBodyResult.dedupedFilenames,
1651
+ scoredCount: memoryBodyResult.scoredCount,
1652
+ },
1653
+ cookbookAutoload: {
1654
+ scannedCount: cookbookResult.scannedCount,
1655
+ keywordCount: promptKeywords.size,
1656
+ totalBytes: cookbookResult.totalBytes,
1657
+ injected: cookbookResult.injected.map((e) => ({
1658
+ skill: e.skill,
1659
+ cookbookName: e.cookbookName,
1660
+ sectionTitle: e.sectionTitle,
1661
+ score: e.score,
1662
+ bytes: e.bytes,
1663
+ })),
1664
+ skippedBelowThreshold: cookbookResult.skippedBelowThreshold,
1665
+ skipped: cookbookResult.skipped,
1666
+ errors: cookbookResult.errors,
1667
+ },
1668
+ substrateOpen: substrateOpen.ok
1669
+ ? {
1670
+ ok: true,
1671
+ workUnitId: substrateOpen.packet?.workUnitId,
1672
+ projectId: substrateOpen.packet?.projectId,
1673
+ threadId: substrateOpen.packet?.threadId,
1674
+ atlasStatus: substrateOpen.packet?.atlasFirstPrinciplesForgeReceipt?.atlas?.status,
1675
+ generativeAxiomCount: substrateOpen.packet?.atlasFirstPrinciplesForgeReceipt?.generativeAxiomCount,
1676
+ receiptHash: substrateOpen.packet?.receiptHash,
1677
+ }
1678
+ : {
1679
+ ok: false,
1680
+ status: substrateOpen.status,
1681
+ error: substrateOpen.error,
1682
+ },
1683
+ // A3 + A4 (2026-05-17) — kernel-class selection receipt persisted so
1684
+ // post-turn QA can verify deterministic skill-selection input/output.
1685
+ atlasSelection: atlasSelection || (atlasSelectionErr ? { error: atlasSelectionErr } : null),
1686
+ // A5 (2026-05-18) — atlas-as-orchestrator receipt. Per-turn governing-
1687
+ // skill resolution against atlas daemon dossier for path-shape prompt
1688
+ // targets. Empty when prompt has no path tokens; targetsErr > 0 indicates
1689
+ // the atlas daemon was unavailable for one or more lookups (LOUD-stderr
1690
+ // already emitted by atlas-dossier-client).
1691
+ atlasOrchestrator: atlasOrchestrator || (atlasOrchestratorErr ? { error: atlasOrchestratorErr } : null),
1692
+ };
1693
+ writeSidecar(sidecar);
1694
+
1695
+ appendGateLedger({
1696
+ hook: 'pre-emit-autoload',
1697
+ event: HOOK_EVENT_NAME,
1698
+ decision: 'allow',
1699
+ source: 'pre-emit/autoload',
1700
+ reasonShort: classified.requiredSkills.length > 0
1701
+ ? `injected=${totalBytes}B skills=${classified.requiredSkills.join(',')}`
1702
+ : 'no doctrine-bound skills required',
1703
+ meta: {
1704
+ requiredSkills: classified.requiredSkills,
1705
+ redirectOnly: classified.redirectOnly === true,
1706
+ promptLen: prompt.length,
1707
+ injectedBytes: totalBytes,
1708
+ injectedSkills: skillBodies.filter(s => s.bytes > 0).map(s => s.skill),
1709
+ skippedSkills: skillBodies.filter(s => s.bytes === 0).map(s => ({ skill: s.skill, reason: s.reason })),
1710
+ cascadeDepth,
1711
+ depthInjected,
1712
+ depthAttempted,
1713
+ cascadedSkills,
1714
+ doctrineTriggerMatchCount: doctrineScan.matches.length,
1715
+ doctrineTriggersMatched: doctrineScan.matches.map((m) => m.trigger),
1716
+ doctrineTriggerSkipped: doctrineScan.skipped,
1717
+ memoryIndexBytes: memoryIndexResult.bytes,
1718
+ memoryIndexReason: memoryIndexResult.reason,
1719
+ memoryIndexDroppedLines: memoryIndexResult.droppedLines,
1720
+ memoryBodiesInjected: memoryBodyResult.injected.length,
1721
+ memoryBodiesInjectedBytes: memoryBodyResult.totalBytes,
1722
+ memoryBodiesScoredCount: memoryBodyResult.scoredCount,
1723
+ memoryBodiesDeduped: memoryBodyResult.dedupedFilenames,
1724
+ memoryBodiesSelected: memoryBodyResult.injected.map((e) => ({ filename: e.filename, tier: e.tier, bytes: e.bytes })),
1725
+ cookbookScannedCount: cookbookResult.scannedCount,
1726
+ cookbookInjectedCount: cookbookResult.injected.length,
1727
+ cookbookInjectedBytes: cookbookResult.totalBytes,
1728
+ cookbookKeywordCount: promptKeywords.size,
1729
+ cookbookSkippedReasons: cookbookResult.skippedBelowThreshold.map((s) => `${s.cookbookName}:${s.reason}`),
1730
+ cookbookSkipped: cookbookResult.skipped,
1731
+ invocationRequired,
1732
+ invocationRequiredCount: invocationRequired.length,
1733
+ substrateOpenOk: substrateOpen.ok === true,
1734
+ substrateWorkUnitId: substrateOpen.packet?.workUnitId || null,
1735
+ atlasFirstPrinciplesForgeHash: substrateOpen.packet?.atlasFirstPrinciplesForgeReceipt?.evidenceHash || null,
1736
+ },
1737
+ sessionId: event.session_id,
1738
+ });
1739
+
1740
+ // Stage 5: pull recent gate-blocks for this session so the agent sees
1741
+ // them as pre-flight FRAME context and cannot drift the same way twice.
1742
+ const recentBlocks = readRecentGateBlocks({ sessionId: event.session_id });
1743
+
1744
+ const doctrineInjection = buildDoctrineTriggerInjection(doctrineScan.matches);
1745
+
1746
+ const memoryInjection = buildMemoryAutoloadInjection({
1747
+ indexResult: memoryIndexResult,
1748
+ bodyResult: memoryBodyResult,
1749
+ });
1750
+
1751
+ const frameInjection = buildFrameInjection({
1752
+ requiredSkills: classified.requiredSkills,
1753
+ reasons: classified.reasons,
1754
+ redirectOnly: classified.redirectOnly === true,
1755
+ cognitionVocab,
1756
+ skillBodies,
1757
+ totalBytes,
1758
+ recentBlocks,
1759
+ });
1760
+
1761
+ const cookbookInjection = buildCookbookInjection({
1762
+ result: cookbookResult,
1763
+ promptKeywords,
1764
+ });
1765
+
1766
+ // AI-11803-F5: INVOCATION REQUIRED section — make it explicit that
1767
+ // active-workflow skills loaded as bodies still need Skill tool
1768
+ // invocation. Doctrine drift if skipped (see
1769
+ // feedback_autoload_does_not_invoke_skills.md).
1770
+ let invocationInjection = '';
1771
+ if (invocationRequired.length > 0) {
1772
+ const lines = [];
1773
+ lines.push('═══ INVOCATION REQUIRED (active-workflow skills — body in context is NOT enough) ═══');
1774
+ lines.push(`The following loaded skills are ACTIVE-WORKFLOW. You MUST invoke each via the Skill tool BEFORE drafting substantive work this turn. Reading the body in context does NOT run the workflow.`);
1775
+ lines.push('');
1776
+ for (const skill of invocationRequired) {
1777
+ lines.push(` • ${skill}`);
1778
+ }
1779
+ lines.push('');
1780
+ lines.push('Doctrine: feedback_autoload_does_not_invoke_skills.md');
1781
+ lines.push('Recovery Contract — every loaded active-workflow skill closes the turn classified as:');
1782
+ lines.push(' A. INVOKED — Skill tool call visible in transcript');
1783
+ lines.push(' B. COMPOSED-VIA-PARENT — parent skill (e.g., aria-cognition-batch) invoked, child is a composition member');
1784
+ lines.push(' C. SCOPE-EXEMPT — prompt is read-only inspection of the skill body, not asking the workflow to run');
1785
+ lines.push(' D. CAP-DEFERRED — > 5 active-workflow skills loaded; deferred to follow-up');
1786
+ lines.push(`No other classifications permitted. "I considered it" / "it's loaded" / "substrate has it" = the antipattern.`);
1787
+ invocationInjection = lines.join('\n');
1788
+ }
1789
+
1790
+ const parts = [frameInjection];
1791
+ parts.push(buildSubstrateOpenInjection(substrateOpen));
1792
+ if (invocationInjection) parts.push(invocationInjection);
1793
+ if (doctrineInjection) parts.push(doctrineInjection);
1794
+ if (memoryInjection) parts.push(memoryInjection);
1795
+ if (cookbookInjection) parts.push(cookbookInjection);
1796
+ const additionalContext = parts.join('\n\n');
1797
+
1798
+ emit({
1799
+ hookSpecificOutput: {
1800
+ hookEventName: HOOK_EVENT_NAME,
1801
+ additionalContext,
1802
+ },
1803
+ });
1804
+ }
1805
+
1806
+ main().catch((err) => {
1807
+ process.stderr.write(`[aria-pre-emit-autoload] ${err instanceof Error ? err.message : String(err)}\n`);
1808
+ emitNoop('fatal pre-emit autoload error');
1809
+ });