@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,248 @@
1
+ /**
2
+ * Aria Harness Gate — pre-tool cognition enforcement for OpenCode.
3
+ * Routes through HTTPHarnessClient SDK for substrate-backed validation.
4
+ */
5
+ import { existsSync, readFileSync } from 'node:fs';
6
+ import { homedir } from 'node:os';
7
+ import { join } from 'node:path';
8
+
9
+ const HOME = homedir();
10
+ const SDK_CANDIDATES = [
11
+ join(HOME, '.aria', 'sdk', 'index.js'),
12
+ join(HOME, '.codex', 'aria-sdk', 'index.js'),
13
+ join(HOME, '.claude', 'aria-sdk', 'index.js'),
14
+ ];
15
+ const OWNER_TOKEN_PATH = join(HOME, '.aria', 'owner-token');
16
+ const LICENSE_PATH = join(HOME, '.aria', 'license.json');
17
+ const RUNTIME_URL = (process.env.ARIA_RUNTIME_URL || 'http://127.0.0.1:4319').replace(/\/+$/, '');
18
+
19
+ const DESTRUCTIVE_PATTERNS = [
20
+ { rx: /(?:^|[;&|]\s*|\$\(\s*|`\s*)sudo\s+\S/, name: 'sudo' },
21
+ { rx: /systemctl\s+(disable|stop|mask|reset-failed|kill)/, name: 'systemctl-state-change' },
22
+ { rx: /\brm\s+-[rRfF]+/, name: 'rm-recursive-or-force' },
23
+ { rx: /\bgit\s+push\b.*\b--force\b/, name: 'git-push-force' },
24
+ { rx: /\bgit\s+reset\s+--hard\b/, name: 'git-reset-hard' },
25
+ { rx: /\bgit\s+checkout\s+--\b/, name: 'git-checkout-discard' },
26
+ { rx: /\b--no-verify\b/, name: 'commit-no-verify' },
27
+ { rx: /\b--no-gpg-sign\b/, name: 'commit-no-gpg-sign' },
28
+ { rx: /\bkill\s+-(9|KILL|TERM|HUP|INT)\b/, name: 'kill-signal' },
29
+ { rx: /\bpkill\b/, name: 'pkill' },
30
+ { rx: /\b(DROP|TRUNCATE)\s+(TABLE|DATABASE|SCHEMA|INDEX)\b/i, name: 'sql-drop-or-truncate' },
31
+ { rx: /\bkubectl\s+delete\b/, name: 'kubectl-delete' },
32
+ ];
33
+
34
+ const DEPLOY_PATTERNS = [
35
+ { rx: /\b(?:\.\/)?scripts\/deploy-/, name: 'deploy-script' },
36
+ { rx: /\bkubectl\s+apply\b/, name: 'kubectl-apply' },
37
+ { rx: /\bkubectl\s+set\s+image\b/, name: 'kubectl-set-image' },
38
+ { rx: /\bkubectl\s+rollout\s+restart\b/, name: 'kubectl-rollout-restart' },
39
+ { rx: /\bkubectl\s+rollout\s+undo\b/, name: 'kubectl-rollout-undo' },
40
+ { rx: /\bdocker\s+push\b/, name: 'docker-push' },
41
+ { rx: /\bdocker\s+build\b.*--push\b/, name: 'docker-build-push' },
42
+ ];
43
+
44
+ const INLINE_LENS_RX = /^\s*#\s*(?:nur|mizan|hikma|tafakkur|tadabbur|ilham|wahi|firasah|perception|balance|wisdom|reflection|foresight|insight|revelation|discernment)\s*:\s*.{20,}/im;
45
+ const VERIFY_BLOCK_RX = /<verify>[\s\S]*?target\s*:[\s\S]*?verified\s*:[\s\S]*?axiom\s*:[\s\S]*?<\/verify>/i;
46
+ const TRIVIAL_BASH_RX = /^\s*(?:ls|cat|head|tail|grep|find|echo|wc|stat|which|pwd|date|file|du|df|ss|ps)\s/;
47
+ const SHORT_BASH_LIMIT = 30;
48
+
49
+ let _client = null;
50
+ let _clientError = null;
51
+ let _lastMizanReceipt = null;
52
+ let _lastActionSummary = '';
53
+
54
+ function resolveToken() {
55
+ if (process.env.ARIA_HARNESS_TOKEN) return process.env.ARIA_HARNESS_TOKEN;
56
+ if (process.env.ARIA_API_KEY) return process.env.ARIA_API_KEY;
57
+ if (process.env.ARIA_MASTER_TOKEN) return process.env.ARIA_MASTER_TOKEN;
58
+ try {
59
+ if (existsSync(OWNER_TOKEN_PATH)) {
60
+ const v = readFileSync(OWNER_TOKEN_PATH, 'utf8').trim();
61
+ if (v) return v;
62
+ }
63
+ } catch {}
64
+ try {
65
+ if (existsSync(LICENSE_PATH)) {
66
+ const j = JSON.parse(readFileSync(LICENSE_PATH, 'utf8'));
67
+ if (j.token) return j.token;
68
+ }
69
+ } catch {}
70
+ return '';
71
+ }
72
+
73
+ function resolveBaseUrl() {
74
+ if (process.env.ARIA_HIVE_RUNTIME_URL) return process.env.ARIA_HIVE_RUNTIME_URL.replace(/\/+$/, '');
75
+ if (process.env.ARIA_HARNESS_BASE_URL) return process.env.ARIA_HARNESS_BASE_URL.replace(/\/+$/, '');
76
+ if (process.env.ARIA_SOUL_URL) return process.env.ARIA_SOUL_URL.replace(/\/+$/, '');
77
+ return process.env.ARIA_HARNESS_URL || 'https://harness.ariasos.com';
78
+ }
79
+
80
+ function resolveSdkPath() {
81
+ return SDK_CANDIDATES.find((candidate) => existsSync(candidate)) || '';
82
+ }
83
+
84
+ async function getClient() {
85
+ if (_client) return _client;
86
+ if (_clientError) return null;
87
+ const sdkPath = resolveSdkPath();
88
+ if (!sdkPath) { _clientError = 'SDK not found'; return null; }
89
+ const token = resolveToken();
90
+ if (!token) { _clientError = 'no token'; return null; }
91
+ try {
92
+ const mod = await import(sdkPath);
93
+ const Client = mod.HTTPHarnessClient;
94
+ if (!Client) { _clientError = 'no HTTPHarnessClient export'; return null; }
95
+ _client = new Client({ baseUrl: resolveBaseUrl(), apiKey: token, workspaceRoot: process.cwd() });
96
+ } catch (e) {
97
+ _clientError = e.message;
98
+ }
99
+ return _client;
100
+ }
101
+
102
+ async function runtimeCheckAction(action, target) {
103
+ const token = resolveToken();
104
+ if (!token) throw new Error('no token');
105
+ const response = await fetch(`${RUNTIME_URL}/check-action`, {
106
+ method: 'POST',
107
+ headers: {
108
+ 'Content-Type': 'application/json',
109
+ Authorization: `Bearer ${token}`,
110
+ },
111
+ body: JSON.stringify({ action, target }),
112
+ });
113
+ if (!response.ok) {
114
+ const body = await response.text().catch(() => response.statusText);
115
+ throw new Error(`runtime check-action failed ${response.status}: ${body}`);
116
+ }
117
+ const payload = await response.json();
118
+ return payload.allowed == null && payload.ok && payload.reason == null ? payload.result || payload : payload;
119
+ }
120
+
121
+ async function runtimeMizan(phase, body) {
122
+ const token = resolveToken();
123
+ if (!token) throw new Error('no token');
124
+ const response = await fetch(`${RUNTIME_URL}/mizan/${phase}`, {
125
+ method: 'POST',
126
+ headers: {
127
+ 'Content-Type': 'application/json',
128
+ Authorization: `Bearer ${token}`,
129
+ },
130
+ body: JSON.stringify(body),
131
+ });
132
+ if (!response.ok) {
133
+ const raw = await response.text().catch(() => response.statusText);
134
+ throw new Error(`runtime mizan/${phase} failed ${response.status}: ${raw}`);
135
+ }
136
+ return response.json();
137
+ }
138
+
139
+ export default async function HarnessGatePlugin(ctx) {
140
+ process.stderr.write('[harness-gate] Active — SDK-backed cognition gate\n');
141
+
142
+ return {
143
+ 'tool.execute.before': async (input, output) => {
144
+ const toolName = input.tool;
145
+ if (!['Bash', 'Edit', 'Write', 'NotebookEdit'].includes(toolName)) return;
146
+
147
+ const cmd = toolName === 'Bash' ? String(input.args?.command ?? '') : '';
148
+ const filePath = toolName !== 'Bash' ? String(input.args?.file_path ?? input.args?.notebook_path ?? '') : '';
149
+ const cmdPreview = toolName === 'Bash' ? cmd.slice(0, 80) : `${toolName} ${filePath || '(no path)'}`.slice(0, 80);
150
+
151
+ // Trivial reads pass
152
+ if (toolName === 'Bash' && TRIVIAL_BASH_RX.test(cmd) && cmd.length < 200) return;
153
+ if (toolName === 'Bash' && cmd.length < SHORT_BASH_LIMIT) return;
154
+ // Inline cognition in bash comments passes
155
+ if (toolName === 'Bash' && INLINE_LENS_RX.test(cmd)) return;
156
+
157
+ const destructive = DESTRUCTIVE_PATTERNS.find(({ rx }) => rx.test(cmd));
158
+ const deploy = DEPLOY_PATTERNS.find(({ rx }) => rx.test(cmd));
159
+ const isFileMutation = ['Edit', 'Write', 'NotebookEdit'].includes(toolName) && filePath;
160
+
161
+ if (!destructive && !deploy && !isFileMutation) return;
162
+
163
+ // Try SDK checkAction() first — substrate-backed validation
164
+ const client = await getClient();
165
+ const sessionId = process.env.ARIA_SESSION_ID || 'opencode';
166
+ const label = destructive?.name || deploy?.name || `${toolName}:${filePath?.split('/').pop() || ''}`;
167
+ const action = toolName === 'Bash' ? 'bash' : 'edit';
168
+ const target = toolName === 'Bash' ? cmd.slice(0, 200) : filePath.slice(0, 200);
169
+ const rationale =
170
+ destructive ? `High-risk action ${label} requested in OpenCode and must satisfy Mizan truth, protection, and quality before execution.`
171
+ : deploy ? `Deployment action ${label} requested in OpenCode and must satisfy Mizan survivability before execution.`
172
+ : `Repository mutation ${label} requested in OpenCode and must satisfy Mizan quality and doctrine before execution.`;
173
+
174
+ try {
175
+ const pre = await runtimeMizan('pre', {
176
+ sessionId,
177
+ context: {
178
+ sessionId,
179
+ message: cmdPreview,
180
+ intendedAction: target || cmdPreview,
181
+ rationale,
182
+ },
183
+ });
184
+ _lastMizanReceipt = pre.receipt || null;
185
+ _lastActionSummary = cmdPreview;
186
+ if (pre.receipt?.blocked || pre.result?.fitrahVetoed || pre.result?.reAuthorSignal) {
187
+ throw new Error(
188
+ `=== ARIA MIZAN PRE BLOCK: ${label} ===\n\n` +
189
+ `${(pre.result?.notes || ['Mizan pre-phase blocked this action.']).slice(0, 4).join('\n')}\n\n` +
190
+ `Required packs: ${(pre.operatorPlan?.requiredPacks || []).join(', ')}\n` +
191
+ `Required operators: ${(pre.operatorPlan?.priorityOperators || []).join(', ')}`
192
+ );
193
+ }
194
+ if (_lastMizanReceipt?.receiptId && _lastActionSummary && _lastActionSummary !== cmdPreview) {
195
+ await runtimeMizan('mid', {
196
+ sessionId,
197
+ parentReceiptId: _lastMizanReceipt.receiptId,
198
+ message: _lastActionSummary,
199
+ plannedApproach: cmdPreview,
200
+ context: {
201
+ sessionId,
202
+ message: _lastActionSummary,
203
+ plannedApproach: cmdPreview,
204
+ rationale,
205
+ },
206
+ }).catch(() => null);
207
+ }
208
+ } catch (e) {
209
+ if (String(e?.message || '').startsWith('=== ARIA MIZAN PRE BLOCK')) throw e;
210
+ process.stderr.write(`[harness-gate] mizan pre unavailable: ${e.message}\n`);
211
+ }
212
+
213
+ if (client) {
214
+ try {
215
+ const check = await runtimeCheckAction(action, target).catch(() => client.checkAction(action, target));
216
+ if (!check.allowed) {
217
+ throw new Error(
218
+ `=== ARIA SD GATE: ${label} ===\n\n` +
219
+ `Blocked by substrate gate: ${check.reason || 'no reason provided'}\n` +
220
+ `Required gates: ${(check.requiredGates || []).join(', ')}\n\n` +
221
+ `Complete a <cognition> block or inline cognition comments before this action.`
222
+ );
223
+ }
224
+ return;
225
+ } catch (e) {
226
+ if (e.message.startsWith('=== ARIA SD GATE')) throw e;
227
+ // SDK unreachable — fall through to local gate below
228
+ process.stderr.write(`[harness-gate] SDK checkAction failed: ${e.message} — falling through to local gate\n`);
229
+ }
230
+ }
231
+
232
+ // Local fallback gate
233
+ const msg = [
234
+ `=== ARIA GATE: ${label} ===`,
235
+ '',
236
+ `This tool (${label}) requires pre-action cognition. Add inline cognition comments:`,
237
+ ' # nur: [perception of current state, ≥20 chars]',
238
+ ' # mizan: [balance analysis, trade-offs, risks, ≥20 chars]',
239
+ ' # hikma: [wisdom — which doctrine applies, ≥20 chars]',
240
+ ' # tafakkur: [reflection — second-order effects, ≥20 chars]',
241
+ '',
242
+ `${deploy ? 'DEPLOY requires a <verify> block with target, verified, rollback, axiom fields.\n' : ''}`,
243
+ `Run \`aria connect\` to install the full SDK-backed gate (substrate checkAction).`,
244
+ ].filter(Boolean).join('\n');
245
+ throw new Error(msg);
246
+ },
247
+ };
248
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Aria Harness Outcome — post-tool recording via HTTPHarnessClient SDK.
3
+ * Routes through the canonical SDK for outcome/garden/ledger writes.
4
+ */
5
+ import { existsSync, readFileSync } from 'node:fs';
6
+ import { homedir } from 'node:os';
7
+ import { join } from 'node:path';
8
+
9
+ const HOME = homedir();
10
+ const SDK_CANDIDATES = [
11
+ join(HOME, '.aria', 'sdk', 'index.js'),
12
+ join(HOME, '.codex', 'aria-sdk', 'index.js'),
13
+ join(HOME, '.claude', 'aria-sdk', 'index.js'),
14
+ ];
15
+ const OWNER_TOKEN_PATH = join(HOME, '.aria', 'owner-token');
16
+ const LICENSE_PATH = join(HOME, '.aria', 'license.json');
17
+
18
+ let _client = null;
19
+ let _clientError = null;
20
+
21
+ function resolveToken() {
22
+ if (process.env.ARIA_HARNESS_TOKEN) return process.env.ARIA_HARNESS_TOKEN;
23
+ if (process.env.ARIA_API_KEY) return process.env.ARIA_API_KEY;
24
+ try {
25
+ if (existsSync(OWNER_TOKEN_PATH)) {
26
+ const v = readFileSync(OWNER_TOKEN_PATH, 'utf8').trim();
27
+ if (v) return v;
28
+ }
29
+ } catch {}
30
+ try {
31
+ if (existsSync(LICENSE_PATH)) {
32
+ const j = JSON.parse(readFileSync(LICENSE_PATH, 'utf8'));
33
+ if (j.token) return j.token;
34
+ }
35
+ } catch {}
36
+ return '';
37
+ }
38
+
39
+ function resolveBaseUrl() {
40
+ if (process.env.ARIA_HIVE_RUNTIME_URL) return process.env.ARIA_HIVE_RUNTIME_URL.replace(/\/+$/, '');
41
+ if (process.env.ARIA_HARNESS_BASE_URL) return process.env.ARIA_HARNESS_BASE_URL.replace(/\/+$/, '');
42
+ return process.env.ARIA_HARNESS_URL || 'https://harness.ariasos.com';
43
+ }
44
+
45
+ function resolveSdkPath() {
46
+ return SDK_CANDIDATES.find((candidate) => existsSync(candidate)) || '';
47
+ }
48
+
49
+ async function getClient() {
50
+ if (_client) return _client;
51
+ if (_clientError) return null;
52
+ const sdkPath = resolveSdkPath();
53
+ if (!sdkPath) { _clientError = 'SDK not found'; return null; }
54
+ const token = resolveToken();
55
+ if (!token) { _clientError = 'no token'; return null; }
56
+ try {
57
+ const mod = await import(sdkPath);
58
+ const Client = mod.HTTPHarnessClient;
59
+ if (!Client) { _clientError = 'no HTTPHarnessClient export'; return null; }
60
+ _client = new Client({ baseUrl: resolveBaseUrl(), apiKey: token, workspaceRoot: process.cwd() });
61
+ } catch (e) {
62
+ _clientError = e.message;
63
+ }
64
+ return _client;
65
+ }
66
+
67
+ export default async function HarnessOutcomePlugin(ctx) {
68
+ process.stderr.write('[harness-outcome] Active — SDK-backed outcome recording\n');
69
+
70
+ return {
71
+ 'tool.execute.after': async (input, output) => {
72
+ const toolName = input.tool;
73
+ if (!['Bash', 'Edit', 'Write', 'NotebookEdit'].includes(toolName)) return;
74
+
75
+ const actionKind = toolName === 'Bash' ? 'bash' : 'edit';
76
+ const actionTarget = toolName === 'Bash'
77
+ ? String(input.args?.command ?? '').split(/\s+/)[0]?.slice(0, 100) || 'unknown'
78
+ : String(input.args?.file_path ?? input.args?.notebook_path ?? '').slice(0, 200) || 'unknown';
79
+ const success = !output?.error;
80
+ const sessionId = process.env.ARIA_SESSION_ID || 'opencode';
81
+
82
+ // Try SDK first
83
+ const client = await getClient();
84
+ if (client) {
85
+ try {
86
+ await client.recordDiscovery({
87
+ text: `${actionKind}: ${actionTarget} — ${success ? 'ok' : 'failed'}`,
88
+ kind: success ? 'observation' : 'defect',
89
+ source: 'opencode-outcome-plugin',
90
+ resolution_status: success ? 'resolved' : 'open',
91
+ sessionId,
92
+ });
93
+ return;
94
+ } catch (e) {
95
+ // Fire-and-forget — SDK unreachable is non-blocking
96
+ process.stderr.write(`[harness-outcome] SDK recordDiscovery failed: ${e.message} — falling through to raw fetch\n`);
97
+ }
98
+ }
99
+
100
+ // Fallback: raw fetch
101
+ const harnessUrl =
102
+ process.env.ARIA_HIVE_RUNTIME_URL ||
103
+ process.env.ARIA_HARNESS_BASE_URL ||
104
+ process.env.ARIA_HARNESS_URL ||
105
+ 'https://harness.ariasos.com';
106
+ let harnessToken = process.env.ARIA_HARNESS_TOKEN || process.env.ARIA_API_KEY || '';
107
+ try {
108
+ if (!harnessToken) {
109
+ if (existsSync(OWNER_TOKEN_PATH)) harnessToken = readFileSync(OWNER_TOKEN_PATH, 'utf8').trim();
110
+ }
111
+ } catch {}
112
+ if (!harnessToken) return;
113
+
114
+ fetch(`${harnessUrl}/api/harness/outcome-record`, {
115
+ method: 'POST',
116
+ headers: {
117
+ 'Content-Type': 'application/json',
118
+ Authorization: `Bearer ${harnessToken}`,
119
+ },
120
+ body: JSON.stringify({
121
+ sessionId,
122
+ actionKind,
123
+ actionTarget,
124
+ actionShape: { tool: toolName, success },
125
+ }),
126
+ }).catch(() => {});
127
+ },
128
+ };
129
+ }
@@ -0,0 +1,241 @@
1
+ /**
2
+ * Aria Harness Stop — text-emission gate via HTTPHarnessClient SDK.
3
+ * Routes text through Mizan validateOutput() for substrate-backed QC.
4
+ */
5
+ import { existsSync, readFileSync } from 'node:fs';
6
+ import { homedir } from 'node:os';
7
+ import { join } from 'node:path';
8
+
9
+ const HOME = homedir();
10
+ const SDK_CANDIDATES = [
11
+ join(HOME, '.aria', 'sdk', 'index.js'),
12
+ join(HOME, '.codex', 'aria-sdk', 'index.js'),
13
+ join(HOME, '.claude', 'aria-sdk', 'index.js'),
14
+ ];
15
+ const OWNER_TOKEN_PATH = join(HOME, '.aria', 'owner-token');
16
+ const LICENSE_PATH = join(HOME, '.aria', 'license.json');
17
+ const RUNTIME_URL = (process.env.ARIA_RUNTIME_URL || 'http://127.0.0.1:4319').replace(/\/+$/, '');
18
+
19
+ const LENS_NAMES = [
20
+ 'nur', 'mizan', 'hikma', 'tafakkur', 'tadabbur', 'ilham', 'wahi', 'firasah',
21
+ 'perception', 'balance', 'wisdom', 'reflection', 'foresight', 'insight', 'revelation', 'discernment',
22
+ ];
23
+
24
+ const COGNITION_BLOCK_RX = /<cognition>([\s\S]*?)<\/cognition>/i;
25
+ const REQUIRED_LENSES = 4;
26
+ const SUBSTANCE_MIN_CHARS = 20;
27
+ const NON_TRIVIAL_MIN_CHARS = 300;
28
+ const DECISION_SIGNAL_RX = /(?:should|recommend|propose|suggest|let'?s|go with|i'd|i would|here'?s the plan|i'll|next step|action item|ship it|yes do|let me)/i;
29
+ const TRIVIAL_ACK_RX = /^(?:got it|on it|ok|sure|yes|no|done|ack)\b/i;
30
+ const PLACEHOLDER_RX = /^\s*<[^<>]+>\s*$/;
31
+
32
+ let _client = null;
33
+ let _clientError = null;
34
+ let _lastMizanReceipt = null;
35
+
36
+ function resolveToken() {
37
+ if (process.env.ARIA_HARNESS_TOKEN) return process.env.ARIA_HARNESS_TOKEN;
38
+ if (process.env.ARIA_API_KEY) return process.env.ARIA_API_KEY;
39
+ if (process.env.ARIA_MASTER_TOKEN) return process.env.ARIA_MASTER_TOKEN;
40
+ try {
41
+ if (existsSync(OWNER_TOKEN_PATH)) {
42
+ const v = readFileSync(OWNER_TOKEN_PATH, 'utf8').trim();
43
+ if (v) return v;
44
+ }
45
+ } catch {}
46
+ try {
47
+ if (existsSync(LICENSE_PATH)) {
48
+ const j = JSON.parse(readFileSync(LICENSE_PATH, 'utf8'));
49
+ if (j.token) return j.token;
50
+ }
51
+ } catch {}
52
+ return '';
53
+ }
54
+
55
+ function resolveBaseUrl() {
56
+ if (process.env.ARIA_HIVE_RUNTIME_URL) return process.env.ARIA_HIVE_RUNTIME_URL.replace(/\/+$/, '');
57
+ if (process.env.ARIA_HARNESS_BASE_URL) return process.env.ARIA_HARNESS_BASE_URL.replace(/\/+$/, '');
58
+ return process.env.ARIA_HARNESS_URL || 'https://harness.ariasos.com';
59
+ }
60
+
61
+ function resolveSdkPath() {
62
+ return SDK_CANDIDATES.find((candidate) => existsSync(candidate)) || '';
63
+ }
64
+
65
+ async function getClient() {
66
+ if (_client) return _client;
67
+ if (_clientError) return null;
68
+ const sdkPath = resolveSdkPath();
69
+ if (!sdkPath) { _clientError = 'SDK not found'; return null; }
70
+ const token = resolveToken();
71
+ if (!token) { _clientError = 'no token'; return null; }
72
+ try {
73
+ const mod = await import(sdkPath);
74
+ const Client = mod.HTTPHarnessClient;
75
+ if (!Client) { _clientError = 'no HTTPHarnessClient export'; return null; }
76
+ _client = new Client({ baseUrl: resolveBaseUrl(), apiKey: token, workspaceRoot: process.cwd() });
77
+ } catch (e) {
78
+ _clientError = e.message;
79
+ }
80
+ return _client;
81
+ }
82
+
83
+ async function runtimeValidateOutput(text, sessionId) {
84
+ const token = resolveToken();
85
+ if (!token) throw new Error('no token');
86
+ const response = await fetch(`${RUNTIME_URL}/validate-output`, {
87
+ method: 'POST',
88
+ headers: {
89
+ 'Content-Type': 'application/json',
90
+ Authorization: `Bearer ${token}`,
91
+ },
92
+ body: JSON.stringify({ text, sessionId }),
93
+ });
94
+ if (!response.ok) {
95
+ const body = await response.text().catch(() => response.statusText);
96
+ throw new Error(`runtime validate-output failed ${response.status}: ${body}`);
97
+ }
98
+ const payload = await response.json();
99
+ return payload.validation || payload.result || payload;
100
+ }
101
+
102
+ async function runtimeMizanPost(text, sessionId, context = {}) {
103
+ const token = resolveToken();
104
+ if (!token) throw new Error('no token');
105
+ const response = await fetch(`${RUNTIME_URL}/mizan/post`, {
106
+ method: 'POST',
107
+ headers: {
108
+ 'Content-Type': 'application/json',
109
+ Authorization: `Bearer ${token}`,
110
+ },
111
+ body: JSON.stringify({
112
+ sessionId,
113
+ text,
114
+ context: {
115
+ sessionId,
116
+ ...context,
117
+ },
118
+ parentReceiptId: _lastMizanReceipt?.receiptId || null,
119
+ }),
120
+ });
121
+ if (!response.ok) {
122
+ const body = await response.text().catch(() => response.statusText);
123
+ throw new Error(`runtime mizan/post failed ${response.status}: ${body}`);
124
+ }
125
+ return response.json();
126
+ }
127
+
128
+ function detectCognitionLenses(text) {
129
+ if (!text) return { count: 0, names: [] };
130
+ const block = text.match(COGNITION_BLOCK_RX);
131
+ const searchSpace = block ? block[1] : text;
132
+ const names = [];
133
+ for (const lens of LENS_NAMES) {
134
+ const lensRx = new RegExp(
135
+ `\\b${lens}\\s*:\\s*([^\\n]*(?:\\n(?!\\s*(?:${LENS_NAMES.join('|')})\\s*:|<\\/cognition>)[^\\n]*)*)`,
136
+ 'i',
137
+ );
138
+ const m = searchSpace.match(lensRx);
139
+ if (!m) continue;
140
+ const content = (m[1] || '').trim();
141
+ if (content.length < SUBSTANCE_MIN_CHARS) continue;
142
+ if (PLACEHOLDER_RX.test(content)) continue;
143
+ names.push(lens);
144
+ }
145
+ return { count: names.length, names };
146
+ }
147
+
148
+ export default async function HarnessStopPlugin(ctx) {
149
+ process.stderr.write('[harness-stop] Active — SDK-backed text-emission gate\n');
150
+
151
+ return {
152
+ 'session.idle': async (event) => {
153
+ process.stderr.write(' [strip gate registed — session i\n');
154
+ },
155
+
156
+ event: async ({ event }) => {
157
+ if (event.type !== 'message.updated') return;
158
+ const parts = event.properties?.parts || [];
159
+ const text = parts
160
+ .filter(p => p.type === 'text')
161
+ .map(p => p.text || '')
162
+ .join('\n');
163
+
164
+ if (!text || text.length < NON_TRIVIAL_MIN_CHARS) return;
165
+ if (TRIVIAL_ACK_RX.test(text.trim())) return;
166
+
167
+ const cog = detectCognitionLenses(text);
168
+ const sessionId = process.env.ARIA_SESSION_ID || 'opencode';
169
+ try {
170
+ const mizan = await runtimeMizanPost(text.slice(0, 8000), sessionId, {
171
+ message: text.slice(0, 1000),
172
+ plannedApproach: 'OpenCode stop gate output review',
173
+ });
174
+ _lastMizanReceipt = mizan.receipt || _lastMizanReceipt;
175
+ if (mizan.receipt?.blocked || mizan.result?.fitrahVetoed || mizan.result?.reAuthorSignal) {
176
+ process.stderr.write(
177
+ `[harness-stop] MIZAN POST BLOCK — ${(mizan.result?.notes || ['post-phase blocked']).slice(0, 4).join(' | ')}\n`
178
+ );
179
+ }
180
+ } catch (e) {
181
+ process.stderr.write(`[harness-stop] mizan/post unavailable: ${e.message}\n`);
182
+ }
183
+
184
+ // Try SDK validateOutput() — Mizan classifier-backed validation
185
+ const client = await getClient();
186
+ if (client) {
187
+ try {
188
+ const result = await runtimeValidateOutput(
189
+ text.slice(0, 8000),
190
+ sessionId,
191
+ ).catch(() => client.validateOutput(
192
+ text.slice(0, 8000),
193
+ sessionId,
194
+ ));
195
+ if (result.severity === 'block') {
196
+ process.stderr.write(
197
+ `[harness-stop] SDK BLOCK — ${result.violations.length} violations: ${result.violations.join('; ').slice(0, 300)}\n`
198
+ );
199
+ } else if (result.severity === 'warn') {
200
+ process.stderr.write(
201
+ `[harness-stop] SDK WARN — ${result.violations.length} violations (non-blocking)\n`
202
+ );
203
+ }
204
+ // Log gate triggers
205
+ if (result.gateTriggers?.length) {
206
+ process.stderr.write(`[harness-stop] SDK triggers: ${result.gateTriggers.join(', ')}\n`);
207
+ }
208
+ return;
209
+ } catch (e) {
210
+ process.stderr.write(`[harness-stop] SDK validateOutput failed: ${e.message} — falling through to local gate\n`);
211
+ }
212
+ }
213
+
214
+ // Local fallback gate
215
+ // Scan drift triggers
216
+ const triggerMapPath = `${HOME}/.claude/hooks/doctrine_trigger_map.json`;
217
+ let driftHits = [];
218
+ try {
219
+ if (existsSync(triggerMapPath)) {
220
+ const triggerMap = JSON.parse(readFileSync(triggerMapPath, 'utf8'));
221
+ const lower = text.toLowerCase();
222
+ for (const t of triggerMap.triggers || []) {
223
+ try {
224
+ const rx = new RegExp(t.trigger, 'i');
225
+ if (rx.test(lower)) {
226
+ const memCited = t.memory && lower.includes(t.memory.replace(/\.md$/, '').toLowerCase());
227
+ if (!memCited) driftHits.push(t.trigger);
228
+ }
229
+ } catch {}
230
+ }
231
+ }
232
+ } catch {}
233
+
234
+ if (cog.count < REQUIRED_LENSES || driftHits.length >= 2) {
235
+ process.stderr.write(
236
+ `[harness-stop] LOCAL GATE — cognition=${cog.count}/${REQUIRED_LENSES} drift=${driftHits.length}\n`
237
+ );
238
+ }
239
+ },
240
+ };
241
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aria_asi/cli",
3
- "version": "0.2.25",
3
+ "version": "0.2.29",
4
4
  "description": "Aria Smart CLI — the world's first harness-powered terminal companion",
5
5
  "bin": {
6
6
  "aria": "./bin/aria.js"
@@ -18,6 +18,8 @@
18
18
  },
19
19
  "scripts": {
20
20
  "build": "tsc && node scripts/bundle-sdk.mjs",
21
+ "check:hooks": "node scripts/validate-hook-contracts.mjs",
22
+ "check:skills": "node scripts/validate-skill-prompts.mjs",
21
23
  "prepare": "npm run build",
22
24
  "dev": "tsc --watch",
23
25
  "publish:all": "bash scripts/publish-all.sh",
@@ -37,8 +39,12 @@
37
39
  "bin",
38
40
  "dist",
39
41
  "src",
42
+ "runtime-src",
43
+ "scripts",
44
+ "skills",
40
45
  "hooks",
41
- "opencode-plugins"
46
+ "opencode-plugins",
47
+ "CLIENT-ONBOARDING.md"
42
48
  ],
43
49
  "engines": {
44
50
  "node": ">=20.0.0"
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+
3
+ const runtimeUrl = process.env.ARIA_RUNTIME_URL || 'http://127.0.0.1:4319';
4
+
5
+ try {
6
+ const response = await fetch(`${runtimeUrl}/health`);
7
+ const payload = await response.json();
8
+ process.stdout.write(JSON.stringify(payload, null, 2) + '\n');
9
+ process.exit(response.ok ? 0 : 1);
10
+ } catch (error) {
11
+ process.stderr.write(
12
+ JSON.stringify(
13
+ {
14
+ ok: false,
15
+ runtimeUrl,
16
+ error: error instanceof Error ? error.message : String(error),
17
+ },
18
+ null,
19
+ 2,
20
+ ) + '\n',
21
+ );
22
+ process.exit(1);
23
+ }