@aria_asi/cli 0.2.25 → 0.2.29

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 (249) hide show
  1. package/CLIENT-ONBOARDING.md +282 -0
  2. package/bin/aria.js +1140 -14
  3. package/dist/aria-connector/src/auth-commands.d.ts +1 -0
  4. package/dist/aria-connector/src/auth-commands.d.ts.map +1 -1
  5. package/dist/aria-connector/src/auth-commands.js +89 -41
  6. package/dist/aria-connector/src/auth-commands.js.map +1 -1
  7. package/dist/aria-connector/src/chat.d.ts +3 -0
  8. package/dist/aria-connector/src/chat.d.ts.map +1 -1
  9. package/dist/aria-connector/src/chat.js +146 -8
  10. package/dist/aria-connector/src/chat.js.map +1 -1
  11. package/dist/aria-connector/src/codebase-scanner.d.ts +2 -2
  12. package/dist/aria-connector/src/codebase-scanner.d.ts.map +1 -1
  13. package/dist/aria-connector/src/codebase-scanner.js +1 -1
  14. package/dist/aria-connector/src/codebase-scanner.js.map +1 -1
  15. package/dist/aria-connector/src/config.d.ts +12 -0
  16. package/dist/aria-connector/src/config.d.ts.map +1 -1
  17. package/dist/aria-connector/src/config.js +2 -0
  18. package/dist/aria-connector/src/config.js.map +1 -1
  19. package/dist/aria-connector/src/connectors/claude-code.d.ts.map +1 -1
  20. package/dist/aria-connector/src/connectors/claude-code.js +111 -21
  21. package/dist/aria-connector/src/connectors/claude-code.js.map +1 -1
  22. package/dist/aria-connector/src/connectors/codebase-awareness.d.ts +37 -0
  23. package/dist/aria-connector/src/connectors/codebase-awareness.d.ts.map +1 -0
  24. package/dist/aria-connector/src/connectors/codebase-awareness.js +335 -0
  25. package/dist/aria-connector/src/connectors/codebase-awareness.js.map +1 -0
  26. package/dist/aria-connector/src/connectors/codex.d.ts +3 -0
  27. package/dist/aria-connector/src/connectors/codex.d.ts.map +1 -0
  28. package/dist/aria-connector/src/connectors/codex.js +248 -0
  29. package/dist/aria-connector/src/connectors/codex.js.map +1 -0
  30. package/dist/aria-connector/src/connectors/cognitive-skills.d.ts +2 -0
  31. package/dist/aria-connector/src/connectors/cognitive-skills.d.ts.map +1 -0
  32. package/dist/aria-connector/src/connectors/cognitive-skills.js +47 -0
  33. package/dist/aria-connector/src/connectors/cognitive-skills.js.map +1 -0
  34. package/dist/aria-connector/src/connectors/opencode.d.ts.map +1 -1
  35. package/dist/aria-connector/src/connectors/opencode.js +90 -4
  36. package/dist/aria-connector/src/connectors/opencode.js.map +1 -1
  37. package/dist/aria-connector/src/connectors/repo-git-hooks.d.ts +3 -0
  38. package/dist/aria-connector/src/connectors/repo-git-hooks.d.ts.map +1 -0
  39. package/dist/aria-connector/src/connectors/repo-git-hooks.js +87 -0
  40. package/dist/aria-connector/src/connectors/repo-git-hooks.js.map +1 -0
  41. package/dist/aria-connector/src/connectors/repo-guard.d.ts +19 -0
  42. package/dist/aria-connector/src/connectors/repo-guard.d.ts.map +1 -0
  43. package/dist/aria-connector/src/connectors/repo-guard.js +509 -0
  44. package/dist/aria-connector/src/connectors/repo-guard.js.map +1 -0
  45. package/dist/aria-connector/src/connectors/runtime.d.ts +2 -0
  46. package/dist/aria-connector/src/connectors/runtime.d.ts.map +1 -0
  47. package/dist/aria-connector/src/connectors/runtime.js +330 -0
  48. package/dist/aria-connector/src/connectors/runtime.js.map +1 -0
  49. package/dist/aria-connector/src/connectors/shell.d.ts.map +1 -1
  50. package/dist/aria-connector/src/connectors/shell.js +78 -13
  51. package/dist/aria-connector/src/connectors/shell.js.map +1 -1
  52. package/dist/aria-connector/src/connectors/syncd.d.ts +27 -0
  53. package/dist/aria-connector/src/connectors/syncd.d.ts.map +1 -0
  54. package/dist/aria-connector/src/connectors/syncd.js +405 -0
  55. package/dist/aria-connector/src/connectors/syncd.js.map +1 -0
  56. package/dist/aria-connector/src/decisions.d.ts +207 -0
  57. package/dist/aria-connector/src/decisions.d.ts.map +1 -0
  58. package/dist/aria-connector/src/decisions.js +291 -0
  59. package/dist/aria-connector/src/decisions.js.map +1 -0
  60. package/dist/aria-connector/src/garden-control-plane.d.ts.map +1 -1
  61. package/dist/aria-connector/src/garden-control-plane.js +74 -17
  62. package/dist/aria-connector/src/garden-control-plane.js.map +1 -1
  63. package/dist/aria-connector/src/github-connect.d.ts +18 -0
  64. package/dist/aria-connector/src/github-connect.d.ts.map +1 -0
  65. package/dist/aria-connector/src/github-connect.js +117 -0
  66. package/dist/aria-connector/src/github-connect.js.map +1 -0
  67. package/dist/aria-connector/src/harness-client.d.ts +15 -0
  68. package/dist/aria-connector/src/harness-client.d.ts.map +1 -1
  69. package/dist/aria-connector/src/harness-client.js +106 -3
  70. package/dist/aria-connector/src/harness-client.js.map +1 -1
  71. package/dist/aria-connector/src/hive-client.d.ts +30 -0
  72. package/dist/aria-connector/src/hive-client.d.ts.map +1 -1
  73. package/dist/aria-connector/src/hive-client.js +124 -5
  74. package/dist/aria-connector/src/hive-client.js.map +1 -1
  75. package/dist/aria-connector/src/index.d.ts +13 -2
  76. package/dist/aria-connector/src/index.d.ts.map +1 -1
  77. package/dist/aria-connector/src/index.js +10 -1
  78. package/dist/aria-connector/src/index.js.map +1 -1
  79. package/dist/aria-connector/src/lib/aristotle-noor-wire.d.ts +102 -0
  80. package/dist/aria-connector/src/lib/aristotle-noor-wire.d.ts.map +1 -0
  81. package/dist/aria-connector/src/lib/aristotle-noor-wire.js +231 -0
  82. package/dist/aria-connector/src/lib/aristotle-noor-wire.js.map +1 -0
  83. package/dist/aria-connector/src/providers/types.d.ts +5 -0
  84. package/dist/aria-connector/src/providers/types.d.ts.map +1 -1
  85. package/dist/aria-connector/src/runtime-proof.d.ts +45 -0
  86. package/dist/aria-connector/src/runtime-proof.d.ts.map +1 -0
  87. package/dist/aria-connector/src/runtime-proof.js +340 -0
  88. package/dist/aria-connector/src/runtime-proof.js.map +1 -0
  89. package/dist/aria-connector/src/setup-wizard.d.ts.map +1 -1
  90. package/dist/aria-connector/src/setup-wizard.js +34 -2
  91. package/dist/aria-connector/src/setup-wizard.js.map +1 -1
  92. package/dist/assets/hooks/aria-agent-handoff.mjs +224 -0
  93. package/dist/assets/hooks/aria-agent-ledger-merge.mjs +164 -0
  94. package/dist/assets/hooks/aria-architect-fallback.mjs +267 -0
  95. package/dist/assets/hooks/aria-cognition-substrate-binding.mjs +676 -0
  96. package/dist/assets/hooks/aria-discovery-record.mjs +101 -0
  97. package/dist/assets/hooks/aria-harness-via-sdk.mjs +412 -0
  98. package/dist/assets/hooks/aria-import-resolution-gate.mjs +330 -0
  99. package/dist/assets/hooks/aria-outcome-record.mjs +84 -0
  100. package/dist/assets/hooks/aria-pre-emit-dryrun.mjs +294 -0
  101. package/dist/assets/hooks/aria-pre-text-gate.mjs +112 -0
  102. package/dist/assets/hooks/aria-pre-tool-gate.mjs +2133 -0
  103. package/dist/assets/hooks/aria-preprompt-consult.mjs +438 -0
  104. package/dist/assets/hooks/aria-preturn-memory-gate.mjs +570 -0
  105. package/dist/assets/hooks/aria-repo-doctrine-gate.mjs +397 -0
  106. package/dist/assets/hooks/aria-stop-gate.mjs +1551 -0
  107. package/dist/assets/hooks/aria-trigger-autolearn.mjs +229 -0
  108. package/dist/assets/hooks/aria-userprompt-abandon-detect.mjs +192 -0
  109. package/dist/assets/hooks/doctrine_trigger_map.json +479 -0
  110. package/dist/assets/hooks/lib/canonical-lenses.mjs +64 -0
  111. package/dist/assets/hooks/lib/gate-audit.mjs +43 -0
  112. package/dist/assets/hooks/test-aria-preturn-memory-gate.mjs +245 -0
  113. package/dist/assets/hooks/test-tier-lens-labeling.mjs +399 -0
  114. package/dist/assets/opencode-plugins/harness-context/index.js +60 -0
  115. package/dist/assets/opencode-plugins/harness-context/inject-context.mjs +179 -0
  116. package/dist/assets/opencode-plugins/harness-context/package.json +9 -0
  117. package/dist/assets/opencode-plugins/harness-gate/index.js +248 -0
  118. package/dist/assets/opencode-plugins/harness-outcome/index.js +129 -0
  119. package/dist/assets/opencode-plugins/harness-role/index.js +77 -0
  120. package/dist/assets/opencode-plugins/harness-role/package.json +9 -0
  121. package/dist/assets/opencode-plugins/harness-stop/index.js +241 -0
  122. package/dist/runtime/discipline/CLAUDE.md +339 -0
  123. package/dist/runtime/discipline/skills/aria-cognition/aria-essence/SKILL.md +63 -0
  124. package/dist/runtime/discipline/skills/aria-cognition/aria-essence/references/domain-matrix.md +80 -0
  125. package/dist/runtime/discipline/skills/aria-cognition/aria-essence/references/evolution-loop.md +30 -0
  126. package/dist/runtime/discipline/skills/aria-cognition/aria-essence/references/readable-cognition.md +27 -0
  127. package/dist/runtime/discipline/skills/aria-cognition/aria-forge-guardrails/SKILL.md +35 -0
  128. package/dist/runtime/discipline/skills/aria-cognition/aria-forge-guardrails/references/checklist.md +31 -0
  129. package/dist/runtime/discipline/skills/aria-cognition/aria-repo-doctrine/SKILL.md +39 -0
  130. package/dist/runtime/discipline/skills/aria-cognition/forge-quality-rules/SKILL.md +43 -0
  131. package/dist/runtime/discipline/skills/aria-cognition/ghazali-8lens/SKILL.md +38 -0
  132. package/dist/runtime/discipline/skills/aria-cognition/istiqra-induction/SKILL.md +26 -0
  133. package/dist/runtime/discipline/skills/aria-cognition/ladunni-22/SKILL.md +35 -0
  134. package/dist/runtime/discipline/skills/aria-cognition/mizan/SKILL.md +72 -0
  135. package/dist/runtime/discipline/skills/aria-cognition/nadia/SKILL.md +38 -0
  136. package/dist/runtime/discipline/skills/aria-cognition/nadia-psi/SKILL.md +38 -0
  137. package/dist/runtime/discipline/skills/aria-cognition/predictor/SKILL.md +25 -0
  138. package/dist/runtime/discipline/skills/aria-cognition/qiyas-analogy/SKILL.md +26 -0
  139. package/dist/runtime/discipline/skills/aria-cognition/soul-domains/SKILL.md +25 -0
  140. package/dist/runtime/discipline/skills/aria-harness/aria-aristotle-intra-phase/SKILL.md +81 -0
  141. package/dist/runtime/discipline/skills/aria-harness/aria-aristotle-post-phase/SKILL.md +98 -0
  142. package/dist/runtime/discipline/skills/aria-harness/aria-aristotle-pre-phase/SKILL.md +99 -0
  143. package/dist/runtime/discipline/skills/aria-harness/aria-harness-deploy/SKILL.md +127 -0
  144. package/dist/runtime/discipline/skills/aria-harness/aria-harness-no-stripping/SKILL.md +117 -0
  145. package/dist/runtime/discipline/skills/aria-harness/aria-harness-onboarding/SKILL.md +112 -0
  146. package/dist/runtime/discipline/skills/aria-harness/aria-harness-output-discipline/SKILL.md +102 -0
  147. package/dist/runtime/discipline/skills/aria-harness/aria-harness-substrate-binding/SKILL.md +121 -0
  148. package/dist/runtime/doctor.mjs +23 -0
  149. package/dist/runtime/local-phase.mjs +632 -0
  150. package/dist/runtime/manifest.json +15 -0
  151. package/dist/runtime/mizan-scheduler.mjs +331 -0
  152. package/dist/runtime/package.json +6 -0
  153. package/dist/runtime/provider-proxy.mjs +594 -0
  154. package/dist/runtime/sdk/BUNDLED.json +5 -0
  155. package/dist/runtime/sdk/index.d.ts +477 -0
  156. package/dist/runtime/sdk/index.js +1469 -0
  157. package/dist/runtime/sdk/index.js.map +1 -0
  158. package/dist/runtime/sdk/package.json +8 -0
  159. package/dist/runtime/sdk/runWithCognition.d.ts +77 -0
  160. package/dist/runtime/sdk/runWithCognition.js +157 -0
  161. package/dist/runtime/sdk/runWithCognition.js.map +1 -0
  162. package/dist/runtime/service.mjs +2708 -0
  163. package/dist/runtime/vendor/aria-gate-runtime/index.d.ts +53 -0
  164. package/dist/runtime/vendor/aria-gate-runtime/index.d.ts.map +1 -0
  165. package/dist/runtime/vendor/aria-gate-runtime/index.js +277 -0
  166. package/dist/runtime/vendor/aria-gate-runtime/index.js.map +1 -0
  167. package/dist/runtime/vendor/aria-gate-runtime/package.json +6 -0
  168. package/dist/sdk/BUNDLED.json +2 -2
  169. package/dist/sdk/index.d.ts +317 -0
  170. package/dist/sdk/index.js +827 -85
  171. package/dist/sdk/index.js.map +1 -1
  172. package/dist/sdk/runWithCognition.d.ts +77 -0
  173. package/dist/sdk/runWithCognition.js +157 -0
  174. package/dist/sdk/runWithCognition.js.map +1 -0
  175. package/hooks/aria-agent-handoff.mjs +11 -1
  176. package/hooks/aria-architect-fallback.mjs +267 -0
  177. package/hooks/aria-cognition-substrate-binding.mjs +676 -0
  178. package/hooks/aria-discovery-record.mjs +101 -0
  179. package/hooks/aria-harness-via-sdk.mjs +34 -21
  180. package/hooks/aria-import-resolution-gate.mjs +330 -0
  181. package/hooks/aria-outcome-record.mjs +84 -0
  182. package/hooks/aria-pre-emit-dryrun.mjs +294 -0
  183. package/hooks/aria-pre-tool-gate.mjs +985 -40
  184. package/hooks/aria-preprompt-consult.mjs +113 -13
  185. package/hooks/aria-preturn-memory-gate.mjs +298 -6
  186. package/hooks/aria-repo-doctrine-gate.mjs +397 -0
  187. package/hooks/aria-stop-gate.mjs +840 -75
  188. package/hooks/aria-userprompt-abandon-detect.mjs +5 -1
  189. package/hooks/doctrine_trigger_map.json +209 -15
  190. package/hooks/lib/canonical-lenses.mjs +64 -0
  191. package/hooks/lib/gate-audit.mjs +43 -0
  192. package/opencode-plugins/harness-context/index.js +1 -1
  193. package/opencode-plugins/harness-context/inject-context.mjs +82 -23
  194. package/opencode-plugins/harness-gate/index.js +248 -0
  195. package/opencode-plugins/harness-outcome/index.js +129 -0
  196. package/opencode-plugins/harness-stop/index.js +241 -0
  197. package/package.json +8 -2
  198. package/runtime-src/doctor.mjs +23 -0
  199. package/runtime-src/local-phase.mjs +632 -0
  200. package/runtime-src/mizan-scheduler.mjs +331 -0
  201. package/runtime-src/provider-proxy.mjs +594 -0
  202. package/runtime-src/service.mjs +2708 -0
  203. package/scripts/bundle-sdk.mjs +317 -0
  204. package/scripts/install-client.sh +176 -0
  205. package/scripts/publish-all.sh +344 -0
  206. package/scripts/publish-docker.sh +27 -0
  207. package/scripts/validate-hook-contracts.mjs +54 -0
  208. package/scripts/validate-skill-prompts.mjs +95 -0
  209. package/skills/aria-cognition/aria-essence/SKILL.md +63 -0
  210. package/skills/aria-cognition/aria-essence/references/domain-matrix.md +80 -0
  211. package/skills/aria-cognition/aria-essence/references/evolution-loop.md +30 -0
  212. package/skills/aria-cognition/aria-essence/references/readable-cognition.md +27 -0
  213. package/skills/aria-cognition/aria-forge-guardrails/SKILL.md +35 -0
  214. package/skills/aria-cognition/aria-forge-guardrails/references/checklist.md +31 -0
  215. package/skills/aria-cognition/aria-repo-doctrine/SKILL.md +39 -0
  216. package/skills/aria-cognition/forge-quality-rules/SKILL.md +43 -0
  217. package/skills/aria-cognition/ghazali-8lens/SKILL.md +38 -0
  218. package/skills/aria-cognition/istiqra-induction/SKILL.md +26 -0
  219. package/skills/aria-cognition/ladunni-22/SKILL.md +35 -0
  220. package/skills/aria-cognition/mizan/SKILL.md +72 -0
  221. package/skills/aria-cognition/nadia/SKILL.md +38 -0
  222. package/skills/aria-cognition/nadia-psi/SKILL.md +38 -0
  223. package/skills/aria-cognition/predictor/SKILL.md +25 -0
  224. package/skills/aria-cognition/qiyas-analogy/SKILL.md +26 -0
  225. package/skills/aria-cognition/soul-domains/SKILL.md +25 -0
  226. package/src/auth-commands.ts +111 -45
  227. package/src/chat.ts +174 -13
  228. package/src/codebase-scanner.ts +4 -0
  229. package/src/config.ts +15 -0
  230. package/src/connectors/claude-code.ts +115 -26
  231. package/src/connectors/codebase-awareness.ts +408 -0
  232. package/src/connectors/codex.ts +274 -0
  233. package/src/connectors/cognitive-skills.ts +51 -0
  234. package/src/connectors/opencode.ts +93 -4
  235. package/src/connectors/repo-git-hooks.ts +86 -0
  236. package/src/connectors/repo-guard.ts +589 -0
  237. package/src/connectors/runtime.ts +374 -0
  238. package/src/connectors/shell.ts +83 -14
  239. package/src/connectors/syncd.ts +488 -0
  240. package/src/decisions.ts +469 -0
  241. package/src/garden-control-plane.ts +101 -26
  242. package/src/github-connect.ts +143 -0
  243. package/src/harness-client.ts +128 -3
  244. package/src/hive-client.ts +165 -5
  245. package/src/index.ts +41 -2
  246. package/src/lib/aristotle-noor-wire.ts +310 -0
  247. package/src/providers/types.ts +6 -0
  248. package/src/runtime-proof.ts +392 -0
  249. package/src/setup-wizard.ts +37 -2
@@ -0,0 +1,294 @@
1
+ #!/usr/bin/env node
2
+ // aria-pre-emit-dryrun.mjs (#140)
3
+ //
4
+ // Pre-emit dry-run validator. CLI tool the model invokes BEFORE actually
5
+ // emitting an assistant response, to self-validate against the same gates
6
+ // that run at Stop time (substrate-binding, drift-triggers, discovery-
7
+ // binding, owner-decision-marker).
8
+ //
9
+ // Owner directive 2026-04-28: structural prevention of the cosmetic-loop
10
+ // pattern where Claude emits → gate blocks → re-drafts → emits → blocked
11
+ // again. With this dry-run, the model can self-check the draft against
12
+ // the loaded substrate manifest (#142) and the drift-trigger list before
13
+ // sending. Catches forgery + drift + missing first_principle locally.
14
+ //
15
+ // Usage:
16
+ // echo '{"draft":"<full assistant response text>","action_type":"deploy|edit|bash|text"}' \
17
+ // | node ~/.claude/hooks/aria-pre-emit-dryrun.mjs
18
+ //
19
+ // Output JSON:
20
+ // {
21
+ // pass: bool,
22
+ // failures: [
23
+ // {kind: "substrate_anchor_forgery", lens: "nur", anchor: "axiom:made_up", reason: "..."},
24
+ // {kind: "drift_trigger", word: "wrapper", position: 1234},
25
+ // {kind: "missing_first_principle"},
26
+ // {kind: "lens_count_below_threshold", count: 5, required: 8},
27
+ // {kind: "lens_substance_below", lens: "mizan", chars: 12, required: 40},
28
+ // ...
29
+ // ],
30
+ // summary: "X failures: <one-line summary>"
31
+ // }
32
+ //
33
+ // Exit code:
34
+ // 0 if pass=true (draft would pass the gates)
35
+ // 1 if pass=false (draft would be rejected; failures array names the issues)
36
+ // 2 if input is malformed (cannot parse draft)
37
+ //
38
+ // Substrate source: reads ~/.claude/.aria-loaded-substrate.json written by
39
+ // aria-cognition-substrate-binding.mjs each turn. If that file is missing
40
+ // or stale, the dry-run still runs but substrate-anchor forgery checks
41
+ // degrade to "warn" instead of "fail" (LOUD log on stderr).
42
+
43
+ import { readFileSync, existsSync } from 'node:fs';
44
+ import { homedir } from 'node:os';
45
+
46
+ const HOME = process.env.HOME || homedir() || '/tmp';
47
+ const SUBSTRATE_DUMP_PATH = `${HOME}/.claude/.aria-loaded-substrate.json`;
48
+ const MEMORY_DIR = `${HOME}/.claude/projects/-home-hamzaibrahim1/memory`;
49
+
50
+ // Mirror the canonical gate constants — keep in sync if the gates change.
51
+ const LENS_NAMES = ['nur', 'mizan', 'hikma', 'tafakkur', 'tadabbur', 'ilham', 'wahi', 'firasah'];
52
+ const REQUIRED_LENSES = 8;
53
+ const SUBSTANCE_MIN_AFTER_ANCHOR_STRIP = 40;
54
+ const ANCHOR_RX = /\b(axiom|frame|memory|doctrine|packet|language):[a-z0-9_\-./]+/gi;
55
+ const COGNITION_BLOCK_RX = /<cognition>([\s\S]*?)<\/cognition>/i;
56
+ const FIRST_PRINCIPLE_RX = /\b(first[_\s-]?principle[s]?|first_principle=)\b/i;
57
+
58
+ // Drift trigger patterns (mirror aria-stop-gate.mjs canonical list).
59
+ // Keep this conservative — false negatives are tolerable (real gate will
60
+ // catch); false positives waste model time.
61
+ const DRIFT_TRIGGERS = [
62
+ { rx: /\b(want me to|should i)\b/i, doctrine: 'feedback_use_harness_to_architect.md' },
63
+ { rx: /\b(i think|i guess|i assume)\b/i, doctrine: 'feedback_doctrine_first.md' },
64
+ { rx: /\b(shadow|proxy|wrapper)\b/i, doctrine: 'feedback_aria_already_has_fleet_use_existing_substrate.md' },
65
+ { rx: /\b(patch|hotfix|band[- ]?aid)\b/i, doctrine: 'feedback_gates_enforce_form_not_substance.md' },
66
+ { rx: /\b(preferred over|optional|fallback layer)\b/i, doctrine: 'feedback_pretoolgate_covers_all_action_tools.md' },
67
+ { rx: /\b(non[- ]?blocking|fail[- ]?open|silent[- ]?pass|fire[- ]?and[- ]?forget|graceful[- ]?degradation)\b/i, doctrine: 'feedback_non_blocking_errors_unacceptable.md' },
68
+ { rx: /\bdemo\b/i, doctrine: 'feedback_no_demos.md' },
69
+ { rx: /\b(fail loud|crash on missing)\b/i, doctrine: 'feedback_no_graceful_degradation.md' },
70
+ { rx: /\b(just context|advisory|read[. ]only)\b/i, doctrine: 'feedback_full_harness_binding_must_be_structural.md' },
71
+ ];
72
+
73
+ function loadSubstrate() {
74
+ if (!existsSync(SUBSTRATE_DUMP_PATH)) return null;
75
+ try {
76
+ return JSON.parse(readFileSync(SUBSTRATE_DUMP_PATH, 'utf8'));
77
+ } catch {
78
+ return null;
79
+ }
80
+ }
81
+
82
+ function extractLensTexts(cognitionInner) {
83
+ const out = {};
84
+ for (const lens of LENS_NAMES) {
85
+ const lensRx = new RegExp(
86
+ `\\b${lens}\\s*:\\s*([^\\n]*(?:\\n(?!\\s*(?:${LENS_NAMES.join('|')})\\s*:|<\\/cognition>)[^\\n]*)*)`,
87
+ 'i',
88
+ );
89
+ const m = cognitionInner.match(lensRx);
90
+ if (m) out[lens] = (m[1] || '').trim();
91
+ }
92
+ return out;
93
+ }
94
+
95
+ function lensSubstanceLength(text) {
96
+ if (!text) return 0;
97
+ return text.replace(ANCHOR_RX, '').replace(/\s+/g, ' ').trim().length;
98
+ }
99
+
100
+ function verifyAnchor(anchor, substrate) {
101
+ const [kind, ...nameParts] = anchor.split(':');
102
+ const name = nameParts.join(':').toLowerCase().replace(/[.,;:!?]+$/, '');
103
+ const kindLc = kind.toLowerCase();
104
+ if (!substrate) return { ok: true, reason: 'substrate_dump_missing_so_warn_only' };
105
+ if (kindLc === 'axiom') {
106
+ const ok = (substrate.axioms || []).map((a) => a.toLowerCase()).includes(name)
107
+ || (substrate.axioms || []).map((a) => a.toLowerCase().replace(/_/g, '')).includes(name);
108
+ return { ok, reason: ok ? '' : `axiom '${name}' not in loaded set (loaded: ${(substrate.axioms || []).slice(0, 8).join(', ')}…)` };
109
+ }
110
+ if (kindLc === 'frame') {
111
+ const ok = (substrate.frames || []).map((f) => f.toLowerCase()).includes(name);
112
+ return { ok, reason: ok ? '' : `frame '${name}' not loaded` };
113
+ }
114
+ if (kindLc === 'memory') {
115
+ const baseName = name.endsWith('.md') ? name : `${name}.md`;
116
+ const ok = (substrate.memories || []).map((m) => m.toLowerCase()).includes(baseName);
117
+ return { ok, reason: ok ? '' : `memory '${baseName}' not in MEMORY.md index` };
118
+ }
119
+ if (kindLc === 'doctrine') {
120
+ const ok = (substrate.doctrines_acceptable_via_memory || []).includes(name)
121
+ || (substrate.memories || []).some((m) => m.toLowerCase() === `feedback_${name}.md` || m.toLowerCase() === `${name}.md`);
122
+ return { ok, reason: ok ? '' : `doctrine '${name}' has no backing memory file` };
123
+ }
124
+ if (kindLc === 'packet') {
125
+ const ok = (substrate.packets || []).map((p) => p.toLowerCase()).includes(name)
126
+ || (substrate.packets || []).map((p) => p.toLowerCase()).includes(`${name}_rule`)
127
+ || (substrate.packets || []).map((p) => p.toLowerCase()).includes(`${name}_block`);
128
+ return { ok, reason: ok ? '' : `packet '${name}' not in loaded packet sections` };
129
+ }
130
+ if (kindLc === 'language') {
131
+ const langOk = (substrate.languages_loaded || []).includes(name);
132
+ const stateOk = name === 'nadia' ? !!substrate.languages_state_active?.nadia
133
+ : name === 'noor' ? !!substrate.languages_state_active?.noor
134
+ : true;
135
+ const ok = langOk && stateOk;
136
+ return { ok, reason: ok ? '' : `language '${name}' ${langOk ? 'state inactive (preStateGate)' : 'not loaded'}` };
137
+ }
138
+ return { ok: true, reason: '' };
139
+ }
140
+
141
+ // ── Read draft from stdin ─────────────────────────────────────────────
142
+ let stdin = '';
143
+ try {
144
+ for await (const chunk of process.stdin) stdin += chunk;
145
+ } catch {
146
+ process.stderr.write('aria-pre-emit-dryrun: failed to read stdin\n');
147
+ process.exit(2);
148
+ }
149
+
150
+ let payload;
151
+ try {
152
+ payload = JSON.parse(stdin);
153
+ } catch {
154
+ process.stderr.write('aria-pre-emit-dryrun: stdin not valid JSON; expected {"draft":"...","action_type":"..."}\n');
155
+ process.exit(2);
156
+ }
157
+
158
+ const draft = String(payload.draft || '');
159
+ const actionType = String(payload.action_type || 'text').toLowerCase();
160
+
161
+ if (draft.length < 10) {
162
+ console.log(JSON.stringify({ pass: true, failures: [], summary: 'draft too short to validate (trivial)' }));
163
+ process.exit(0);
164
+ }
165
+
166
+ const substrate = loadSubstrate();
167
+ const failures = [];
168
+
169
+ // ── Cognition block presence + lens count + substance ─────────────────
170
+ const cogMatch = draft.match(COGNITION_BLOCK_RX);
171
+ const cognitionInner = cogMatch ? cogMatch[1] : '';
172
+
173
+ if (!cogMatch && draft.length >= 300) {
174
+ failures.push({ kind: 'missing_cognition_block', message: 'Non-trivial draft lacks <cognition>...</cognition> block' });
175
+ }
176
+
177
+ let presentLenses = [];
178
+ if (cogMatch) {
179
+ const lensTexts = extractLensTexts(cognitionInner);
180
+ presentLenses = LENS_NAMES.filter((l) => lensSubstanceLength(lensTexts[l] || '') >= SUBSTANCE_MIN_AFTER_ANCHOR_STRIP);
181
+ if (presentLenses.length < REQUIRED_LENSES) {
182
+ failures.push({
183
+ kind: 'lens_count_below_threshold',
184
+ count: presentLenses.length,
185
+ required: REQUIRED_LENSES,
186
+ lenses_substantive: presentLenses,
187
+ lenses_missing_or_thin: LENS_NAMES.filter((l) => !presentLenses.includes(l)),
188
+ });
189
+ }
190
+
191
+ // Anchor verification per lens
192
+ for (const lens of presentLenses) {
193
+ const text = lensTexts[lens];
194
+ const anchors = text.match(ANCHOR_RX) || [];
195
+ if (anchors.length === 0) {
196
+ failures.push({ kind: 'lens_no_anchor', lens });
197
+ continue;
198
+ }
199
+ const validAnchors = [];
200
+ const invalidAnchors = [];
201
+ for (const a of anchors) {
202
+ const r = verifyAnchor(a, substrate);
203
+ if (r.ok) validAnchors.push(a);
204
+ else invalidAnchors.push({ anchor: a, reason: r.reason });
205
+ }
206
+ if (validAnchors.length === 0 && invalidAnchors.length > 0) {
207
+ failures.push({ kind: 'lens_only_fake_anchors', lens, invalid: invalidAnchors });
208
+ } else if (invalidAnchors.length > 0) {
209
+ // Some valid + some invalid — warn but lens passes if ≥1 valid
210
+ failures.push({ kind: 'lens_some_fake_anchors_warn', lens, invalid: invalidAnchors, severity: 'warn' });
211
+ }
212
+ }
213
+
214
+ // First-principle reference
215
+ const hasFirstPrinciple = FIRST_PRINCIPLE_RX.test(cognitionInner) ||
216
+ (substrate?.first_principle_text && cognitionInner.toLowerCase().includes(String(substrate.first_principle_text).toLowerCase().slice(0, 30)));
217
+ if (!hasFirstPrinciple) {
218
+ failures.push({ kind: 'missing_first_principle', message: 'Cognition block must reference first_principle' });
219
+ }
220
+
221
+ // Nadia citation forgery
222
+ const nadiaCited = /\blanguage:nadia\b/i.test(cognitionInner);
223
+ if (nadiaCited && substrate && !substrate.languages_state_active?.nadia) {
224
+ failures.push({ kind: 'nadia_citation_invalid', message: 'language:nadia cited but nadia_state_absent in harness' });
225
+ }
226
+ }
227
+
228
+ // ── Drift triggers ────────────────────────────────────────────────────
229
+ for (const trigger of DRIFT_TRIGGERS) {
230
+ const match = draft.match(trigger.rx);
231
+ if (match) {
232
+ failures.push({
233
+ kind: 'drift_trigger',
234
+ pattern: trigger.rx.source,
235
+ doctrine: trigger.doctrine,
236
+ match_text: match[0],
237
+ match_position: match.index,
238
+ });
239
+ }
240
+ }
241
+
242
+ // ── Deploy-class checks (when action_type indicates deploy) ────────────
243
+ if (
244
+ actionType === 'deploy' ||
245
+ /\bbash\s+(?:\.\/)?scripts\/deploy-service\.sh\b/.test(draft) ||
246
+ /\bkubectl\s+rollout\s+(?:restart|undo)\b/.test(draft)
247
+ ) {
248
+ const verifyMatch = draft.match(/<verify>([\s\S]*?)<\/verify>/i);
249
+ if (!verifyMatch) {
250
+ failures.push({ kind: 'deploy_missing_verify_block' });
251
+ } else {
252
+ const verifyBody = verifyMatch[1];
253
+ const requiredFields = [
254
+ { rx: /\b(?:commit|HEAD|SHA|files\s+changed)\b/i, name: 'commit_or_files' },
255
+ { rx: /\b(?:tsc|type[\s-]?check|build|npm\s+run\s+build)\b/i, name: 'build_or_typecheck' },
256
+ { rx: /\b(?:admission[\s_-]?policy|validatingadmissionpolicy)\b/i, name: 'admission_policy' },
257
+ ];
258
+ const missingFields = requiredFields.filter(({ rx }) => !rx.test(verifyBody)).map(({ name }) => name);
259
+ if (missingFields.length > 0) {
260
+ failures.push({ kind: 'deploy_verify_missing_fields', missing: missingFields });
261
+ }
262
+ }
263
+ }
264
+
265
+ // ── Expected block (Dalio Layer 1) ─────────────────────────────────────
266
+ if (actionType !== 'text' && actionType !== 'trivial') {
267
+ const expectedMatch = draft.match(/<expected>([\s\S]*?)<\/expected>/i);
268
+ if (!expectedMatch) {
269
+ failures.push({ kind: 'missing_expected_block', message: 'Non-trivial action requires <expected> block per doctrine:dalio_expected_required' });
270
+ } else {
271
+ const expectedBody = expectedMatch[1];
272
+ const QUALITATIVE_DRIFT = /\b(better|improved|more\s+robust|cleaner|nicer|should\s+work|hopefully|more\s+reliable|enhanced)\b/i;
273
+ if (QUALITATIVE_DRIFT.test(expectedBody)) {
274
+ failures.push({ kind: 'expected_qualitative_drift', message: 'Expected block contains qualitative-only language' });
275
+ }
276
+ }
277
+ }
278
+
279
+ // ── Final verdict ─────────────────────────────────────────────────────
280
+ const hardFailures = failures.filter((f) => f.severity !== 'warn');
281
+ const pass = hardFailures.length === 0;
282
+ const summary = pass
283
+ ? `pass — lenses=${presentLenses.length}/${REQUIRED_LENSES}, anchors verified${substrate ? '' : ' (substrate dump missing)'}`
284
+ : `${hardFailures.length} hard failures: ${hardFailures.map((f) => f.kind).join(', ')}`;
285
+
286
+ console.log(JSON.stringify({
287
+ pass,
288
+ failures,
289
+ summary,
290
+ lenses_present: presentLenses,
291
+ substrate_loaded: !!substrate,
292
+ }, null, 2));
293
+
294
+ process.exit(pass ? 0 : 1);