@aria_asi/cli 0.2.36 → 0.2.38

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 (198) hide show
  1. package/CLIENT-ONBOARDING.md +4 -2
  2. package/bin/aria.js +11 -7
  3. package/dist/aria-connector/src/auth.d.ts +14 -0
  4. package/dist/aria-connector/src/auth.d.ts.map +1 -1
  5. package/dist/aria-connector/src/auth.js +103 -1
  6. package/dist/aria-connector/src/auth.js.map +1 -1
  7. package/dist/aria-connector/src/chat.d.ts.map +1 -1
  8. package/dist/aria-connector/src/chat.js +13 -8
  9. package/dist/aria-connector/src/chat.js.map +1 -1
  10. package/dist/aria-connector/src/config.d.ts +6 -1
  11. package/dist/aria-connector/src/config.d.ts.map +1 -1
  12. package/dist/aria-connector/src/config.js.map +1 -1
  13. package/dist/aria-connector/src/connectors/claude-code.d.ts.map +1 -1
  14. package/dist/aria-connector/src/connectors/claude-code.js +50 -6
  15. package/dist/aria-connector/src/connectors/claude-code.js.map +1 -1
  16. package/dist/aria-connector/src/connectors/codex.d.ts.map +1 -1
  17. package/dist/aria-connector/src/connectors/codex.js +290 -32
  18. package/dist/aria-connector/src/connectors/codex.js.map +1 -1
  19. package/dist/aria-connector/src/connectors/opencode.d.ts.map +1 -1
  20. package/dist/aria-connector/src/connectors/opencode.js +35 -11
  21. package/dist/aria-connector/src/connectors/opencode.js.map +1 -1
  22. package/dist/aria-connector/src/connectors/repo-guard.d.ts +10 -0
  23. package/dist/aria-connector/src/connectors/repo-guard.d.ts.map +1 -1
  24. package/dist/aria-connector/src/connectors/repo-guard.js +110 -164
  25. package/dist/aria-connector/src/connectors/repo-guard.js.map +1 -1
  26. package/dist/aria-connector/src/connectors/runtime.d.ts.map +1 -1
  27. package/dist/aria-connector/src/connectors/runtime.js +17 -7
  28. package/dist/aria-connector/src/connectors/runtime.js.map +1 -1
  29. package/dist/aria-connector/src/connectors/shell.d.ts.map +1 -1
  30. package/dist/aria-connector/src/connectors/shell.js +12 -8
  31. package/dist/aria-connector/src/connectors/shell.js.map +1 -1
  32. package/dist/aria-connector/src/harness-client.d.ts +3 -1
  33. package/dist/aria-connector/src/harness-client.d.ts.map +1 -1
  34. package/dist/aria-connector/src/harness-client.js +7 -20
  35. package/dist/aria-connector/src/harness-client.js.map +1 -1
  36. package/dist/aria-connector/src/model-context.d.ts.map +1 -1
  37. package/dist/aria-connector/src/model-context.js +5 -0
  38. package/dist/aria-connector/src/model-context.js.map +1 -1
  39. package/dist/aria-connector/src/providers/types.d.ts +1 -1
  40. package/dist/aria-connector/src/providers/types.d.ts.map +1 -1
  41. package/dist/aria-connector/src/providers/xai.d.ts +3 -0
  42. package/dist/aria-connector/src/providers/xai.d.ts.map +1 -0
  43. package/dist/aria-connector/src/providers/xai.js +40 -0
  44. package/dist/aria-connector/src/providers/xai.js.map +1 -0
  45. package/dist/aria-connector/src/setup-wizard.js +1 -0
  46. package/dist/aria-connector/src/setup-wizard.js.map +1 -1
  47. package/dist/aria-connector/src/types.d.ts +2 -0
  48. package/dist/aria-connector/src/types.d.ts.map +1 -1
  49. package/dist/assets/hooks/aria-cognition-substrate-binding.mjs +51 -9
  50. package/dist/assets/hooks/aria-first-class-coach.mjs +129 -0
  51. package/dist/assets/hooks/aria-harness-via-sdk.mjs +33 -6
  52. package/dist/assets/hooks/aria-pre-tool-gate.mjs +86 -8
  53. package/dist/assets/hooks/aria-pre-tool-use.mjs +75 -0
  54. package/dist/assets/hooks/aria-preprompt-consult.mjs +5 -6
  55. package/dist/assets/hooks/aria-preturn-memory-gate.mjs +5 -0
  56. package/dist/assets/hooks/aria-repo-doctrine-gate.mjs +15 -0
  57. package/dist/assets/hooks/aria-stop-gate.mjs +125 -17
  58. package/dist/assets/hooks/doctrine_trigger_map.json +11 -0
  59. package/dist/assets/hooks/lib/emergency-gateoff-impl.mjs +39 -0
  60. package/dist/assets/hooks/lib/emergency-gateoff.mjs +6 -0
  61. package/dist/assets/hooks/lib/first-class-coach.mjs +755 -0
  62. package/dist/assets/hooks/lib/skill-autoload-gate-impl.mjs +103 -0
  63. package/dist/assets/hooks/lib/skill-autoload-gate.mjs +1 -14
  64. package/dist/assets/opencode-plugins/harness-context/auth-token.mjs +126 -0
  65. package/dist/assets/opencode-plugins/harness-context/inject-context.mjs +62 -22
  66. package/dist/assets/opencode-plugins/harness-context/task-project-ledger.mjs +290 -0
  67. package/dist/assets/opencode-plugins/harness-gate/index.js +87 -27
  68. package/dist/assets/opencode-plugins/harness-gate/lib/skill-autoload-gate.js +1 -14
  69. package/dist/assets/opencode-plugins/harness-outcome/index.js +29 -24
  70. package/dist/assets/opencode-plugins/harness-stop/index.js +229 -68
  71. package/dist/assets/opencode-plugins/harness-stop/lib/skill-autoload-gate.js +1 -14
  72. package/dist/runtime/auth-token.mjs +121 -0
  73. package/dist/runtime/coach-kernel.mjs +377 -0
  74. package/dist/runtime/codex-bridge.mjs +440 -69
  75. package/dist/runtime/discipline/doctrine_trigger_map.json +11 -0
  76. package/dist/runtime/discipline/skills/aria-cognition/aria-essence/SKILL.md +18 -0
  77. package/dist/runtime/discipline/skills/aria-cognition/aria-forge-guardrails/SKILL.md +18 -0
  78. package/dist/runtime/discipline/skills/aria-cognition/aria-repo-doctrine/SKILL.md +18 -0
  79. package/dist/runtime/discipline/skills/aria-cognition/forge-quality-rules/SKILL.md +18 -0
  80. package/dist/runtime/discipline/skills/aria-cognition/ghazali-8lens/SKILL.md +18 -0
  81. package/dist/runtime/discipline/skills/aria-cognition/istiqra-induction/SKILL.md +18 -0
  82. package/dist/runtime/discipline/skills/aria-cognition/ladunni-22/SKILL.md +18 -0
  83. package/dist/runtime/discipline/skills/aria-cognition/mizan/SKILL.md +18 -0
  84. package/dist/runtime/discipline/skills/aria-cognition/nadia/SKILL.md +18 -0
  85. package/dist/runtime/discipline/skills/aria-cognition/nadia-psi/SKILL.md +18 -0
  86. package/dist/runtime/discipline/skills/aria-cognition/predictor/SKILL.md +18 -0
  87. package/dist/runtime/discipline/skills/aria-cognition/qiyas-analogy/SKILL.md +18 -0
  88. package/dist/runtime/discipline/skills/aria-cognition/soul-domains/SKILL.md +18 -0
  89. package/dist/runtime/discipline/skills/aria-harness/aria-aristotle-intra-phase/SKILL.md +18 -0
  90. package/dist/runtime/discipline/skills/aria-harness/aria-aristotle-post-phase/SKILL.md +18 -0
  91. package/dist/runtime/discipline/skills/aria-harness/aria-aristotle-pre-phase/SKILL.md +18 -0
  92. package/dist/runtime/discipline/skills/aria-harness/aria-harness-deploy/SKILL.md +18 -0
  93. package/dist/runtime/discipline/skills/aria-harness/aria-harness-no-stripping/SKILL.md +18 -0
  94. package/dist/runtime/discipline/skills/aria-harness/aria-harness-onboarding/SKILL.md +18 -0
  95. package/dist/runtime/discipline/skills/aria-harness/aria-harness-output-discipline/SKILL.md +18 -0
  96. package/dist/runtime/discipline/skills/aria-harness/aria-harness-substrate-binding/SKILL.md +18 -0
  97. package/dist/runtime/doctrine_trigger_map.json +11 -0
  98. package/dist/runtime/hooks/aria-cognition-substrate-binding.mjs +51 -9
  99. package/dist/runtime/hooks/aria-first-class-coach.mjs +129 -0
  100. package/dist/runtime/hooks/aria-harness-via-sdk.mjs +33 -6
  101. package/dist/runtime/hooks/aria-pre-tool-gate.mjs +86 -8
  102. package/dist/runtime/hooks/aria-pre-tool-use.mjs +75 -0
  103. package/dist/runtime/hooks/aria-preprompt-consult.mjs +5 -6
  104. package/dist/runtime/hooks/aria-preturn-memory-gate.mjs +5 -0
  105. package/dist/runtime/hooks/aria-repo-doctrine-gate.mjs +15 -0
  106. package/dist/runtime/hooks/aria-stop-gate.mjs +125 -17
  107. package/dist/runtime/hooks/doctrine_trigger_map.json +11 -0
  108. package/dist/runtime/hooks/lib/emergency-gateoff-impl.mjs +39 -0
  109. package/dist/runtime/hooks/lib/emergency-gateoff.mjs +6 -0
  110. package/dist/runtime/hooks/lib/first-class-coach.mjs +755 -0
  111. package/dist/runtime/hooks/lib/skill-autoload-gate-impl.mjs +103 -0
  112. package/dist/runtime/hooks/lib/skill-autoload-gate.mjs +1 -14
  113. package/dist/runtime/local-phase.mjs +8 -0
  114. package/dist/runtime/manifest.json +2 -2
  115. package/dist/runtime/provider-proxy.mjs +136 -33
  116. package/dist/runtime/sdk/BUNDLED.json +2 -2
  117. package/dist/runtime/sdk/auth.d.ts +17 -0
  118. package/dist/runtime/sdk/auth.js +158 -0
  119. package/dist/runtime/sdk/auth.js.map +1 -0
  120. package/dist/runtime/sdk/index.d.ts +8 -1
  121. package/dist/runtime/sdk/index.js +15 -1
  122. package/dist/runtime/sdk/index.js.map +1 -1
  123. package/dist/runtime/service.mjs +1711 -74
  124. package/dist/runtime/task-project-ledger.mjs +290 -0
  125. package/dist/sdk/BUNDLED.json +2 -2
  126. package/dist/sdk/auth.d.ts +17 -0
  127. package/dist/sdk/auth.js +158 -0
  128. package/dist/sdk/auth.js.map +1 -0
  129. package/dist/sdk/index.d.ts +8 -1
  130. package/dist/sdk/index.js +15 -1
  131. package/dist/sdk/index.js.map +1 -1
  132. package/hooks/aria-cognition-substrate-binding.mjs +51 -9
  133. package/hooks/aria-first-class-coach.mjs +129 -0
  134. package/hooks/aria-harness-via-sdk.mjs +33 -6
  135. package/hooks/aria-pre-tool-gate.mjs +86 -8
  136. package/hooks/aria-pre-tool-use.mjs +75 -0
  137. package/hooks/aria-preprompt-consult.mjs +5 -6
  138. package/hooks/aria-preturn-memory-gate.mjs +5 -0
  139. package/hooks/aria-repo-doctrine-gate.mjs +15 -0
  140. package/hooks/aria-stop-gate.mjs +125 -17
  141. package/hooks/doctrine_trigger_map.json +11 -0
  142. package/hooks/lib/emergency-gateoff-impl.mjs +39 -0
  143. package/hooks/lib/emergency-gateoff.mjs +6 -0
  144. package/hooks/lib/first-class-coach.mjs +755 -0
  145. package/hooks/lib/skill-autoload-gate-impl.mjs +103 -0
  146. package/hooks/lib/skill-autoload-gate.mjs +1 -14
  147. package/opencode-plugins/harness-context/auth-token.mjs +126 -0
  148. package/opencode-plugins/harness-context/inject-context.mjs +62 -22
  149. package/opencode-plugins/harness-context/task-project-ledger.mjs +290 -0
  150. package/opencode-plugins/harness-gate/index.js +87 -27
  151. package/opencode-plugins/harness-gate/lib/skill-autoload-gate.js +1 -14
  152. package/opencode-plugins/harness-outcome/index.js +29 -24
  153. package/opencode-plugins/harness-stop/index.js +229 -68
  154. package/opencode-plugins/harness-stop/lib/skill-autoload-gate.js +1 -14
  155. package/package.json +8 -2
  156. package/runtime-src/auth-token.mjs +121 -0
  157. package/runtime-src/coach-kernel.mjs +377 -0
  158. package/runtime-src/codex-bridge.mjs +440 -69
  159. package/runtime-src/local-phase.mjs +8 -0
  160. package/runtime-src/provider-proxy.mjs +136 -33
  161. package/runtime-src/service.mjs +1711 -74
  162. package/scripts/bundle-sdk.mjs +8 -0
  163. package/scripts/check-client-compatibility.mjs +422 -0
  164. package/scripts/check-coach-kernel.mjs +204 -0
  165. package/scripts/check-managed-runtime-ledger.mjs +107 -0
  166. package/scripts/check-opencode-config-contract.mjs +78 -0
  167. package/scripts/check-quality-ledger.mjs +121 -0
  168. package/scripts/self-test-harness-gates.mjs +179 -11
  169. package/scripts/self-test-repo-guard.mjs +38 -0
  170. package/scripts/validate-skill-prompts.mjs +14 -1
  171. package/skills/aria-cognition/aria-essence/SKILL.md +18 -0
  172. package/skills/aria-cognition/aria-forge-guardrails/SKILL.md +18 -0
  173. package/skills/aria-cognition/aria-repo-doctrine/SKILL.md +18 -0
  174. package/skills/aria-cognition/forge-quality-rules/SKILL.md +18 -0
  175. package/skills/aria-cognition/ghazali-8lens/SKILL.md +18 -0
  176. package/skills/aria-cognition/istiqra-induction/SKILL.md +18 -0
  177. package/skills/aria-cognition/ladunni-22/SKILL.md +18 -0
  178. package/skills/aria-cognition/mizan/SKILL.md +18 -0
  179. package/skills/aria-cognition/nadia/SKILL.md +18 -0
  180. package/skills/aria-cognition/nadia-psi/SKILL.md +18 -0
  181. package/skills/aria-cognition/predictor/SKILL.md +18 -0
  182. package/skills/aria-cognition/qiyas-analogy/SKILL.md +18 -0
  183. package/skills/aria-cognition/soul-domains/SKILL.md +18 -0
  184. package/src/auth.ts +136 -1
  185. package/src/chat.ts +13 -8
  186. package/src/config.ts +6 -1
  187. package/src/connectors/claude-code.ts +62 -18
  188. package/src/connectors/codex.ts +288 -32
  189. package/src/connectors/opencode.ts +35 -12
  190. package/src/connectors/repo-guard.ts +117 -172
  191. package/src/connectors/runtime.ts +19 -7
  192. package/src/connectors/shell.ts +12 -8
  193. package/src/harness-client.ts +8 -22
  194. package/src/model-context.ts +6 -0
  195. package/src/providers/types.ts +1 -1
  196. package/src/providers/xai.ts +55 -0
  197. package/src/setup-wizard.ts +1 -0
  198. package/src/types.ts +2 -0
@@ -0,0 +1,377 @@
1
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { createHash, randomUUID } from 'node:crypto';
3
+ import { dirname, join } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+
8
+ export const COACH_EVENT_SCHEMA = 'aria.coach_kernel_event.v1';
9
+ export const COACH_STATE_SCHEMA = 'aria.coach_kernel_state.v1';
10
+ export const DEFAULT_COACH_STATE_DIR = join(__dirname, 'state');
11
+ export const DEFAULT_COACH_LEDGER_PATH = join(DEFAULT_COACH_STATE_DIR, 'coach-events.jsonl');
12
+ export const DEFAULT_COACH_STATE_PATH = join(DEFAULT_COACH_STATE_DIR, 'coach-state.json');
13
+
14
+ export const COACH_PHASES = Object.freeze([
15
+ 'pre_turn',
16
+ 'pre_cognition',
17
+ 'post_cognition',
18
+ 'pre_generation',
19
+ 'post_generation',
20
+ 'pre_tool',
21
+ 'post_tool',
22
+ 'pre_output',
23
+ 'post_output',
24
+ 'background_start',
25
+ 'background_checkpoint',
26
+ 'background_complete',
27
+ 'claim_or_release',
28
+ ]);
29
+
30
+ const ALLOWED_PHASES = new Set(COACH_PHASES);
31
+ const OUTPUT_PHASES = new Set(['post_generation', 'pre_output', 'post_output', 'claim_or_release']);
32
+ const TOOL_PHASES = new Set(['pre_tool', 'post_tool']);
33
+ const SECRET_KEY_RX = /\b(?:api[_-]?key|secret|token|authorization|password|credential|private[_-]?key)\b/i;
34
+ const SECRET_VALUE_RX = /\b(?:sk-[A-Za-z0-9_-]{16,}|xox[baprs]-[A-Za-z0-9-]{20,}|gh[pousr]_[A-Za-z0-9_]{20,}|Bearer\s+[A-Za-z0-9._~+\/-]{20,}|AKIA[0-9A-Z]{16})\b/i;
35
+ const COGNITION_RX = /<cognition>[\s\S]*?<\/cognition>/i;
36
+ const APPLIED_COGNITION_RX = /<applied_cognition>[\s\S]*?<\/applied_cognition>/i;
37
+ const VERIFY_RX = /<verify>[\s\S]*?(?:verified|rollback|target|predicate)[\s\S]*?<\/verify>/i;
38
+ const COMPLETION_CLAIM_RX = /\b(?:done|complete|completed|ready|verified|fixed|shipped|production-ready|release-ready|passing|passed)\b/i;
39
+ const MEASURABLE_EVIDENCE_RX = /\b(?:exit\s*0|0\s+failures?|passed|status\s*[:=]\s*(?:ok|200|healthy|pass)|verified\s*[:=]\s*true|ledger_record_id|receiptId|sha256|http\s*2\d\d)\b/i;
40
+
41
+ function nowIso() {
42
+ return new Date().toISOString();
43
+ }
44
+
45
+ function stableString(value) {
46
+ if (typeof value === 'string') return value;
47
+ try {
48
+ return JSON.stringify(value);
49
+ } catch {
50
+ return String(value || '');
51
+ }
52
+ }
53
+
54
+ function hashValue(value) {
55
+ return createHash('sha256').update(stableString(value)).digest('hex');
56
+ }
57
+
58
+ function normalizeString(value, fallback = '') {
59
+ return typeof value === 'string' && value.trim() ? value.trim() : fallback;
60
+ }
61
+
62
+ function normalizeStringArray(values) {
63
+ return Array.from(new Set((Array.isArray(values) ? values : [])
64
+ .map((value) => normalizeString(value))
65
+ .filter(Boolean)))
66
+ .sort();
67
+ }
68
+
69
+ function redactPotentialSecrets(text) {
70
+ return String(text || '')
71
+ .replace(/Bearer\s+[A-Za-z0-9._~+\/-]{12,}/gi, 'Bearer [redacted]')
72
+ .replace(/\bsk-[A-Za-z0-9_-]{12,}\b/g, '[redacted-secret]')
73
+ .replace(/\bgh[pousr]_[A-Za-z0-9_]{12,}\b/g, '[redacted-secret]')
74
+ .replace(/\bxox[baprs]-[A-Za-z0-9-]{12,}\b/g, '[redacted-secret]')
75
+ .replace(/\bAKIA[0-9A-Z]{16}\b/g, '[redacted-secret]');
76
+ }
77
+
78
+ function redactedClone(value, depth = 0) {
79
+ if (depth > 5) return '[truncated]';
80
+ if (typeof value === 'string') return redactPotentialSecrets(value).slice(0, 2000);
81
+ if (typeof value === 'number' || typeof value === 'boolean' || value == null) return value;
82
+ if (Array.isArray(value)) return value.slice(0, 50).map((entry) => redactedClone(entry, depth + 1));
83
+ if (typeof value !== 'object') return String(value);
84
+ const out = {};
85
+ for (const [key, entry] of Object.entries(value).slice(0, 80)) {
86
+ if (SECRET_KEY_RX.test(key)) {
87
+ out[key] = '[redacted]';
88
+ continue;
89
+ }
90
+ out[key] = redactedClone(entry, depth + 1);
91
+ }
92
+ return out;
93
+ }
94
+
95
+ function normalizeEvidenceRefs(values) {
96
+ const raw = Array.isArray(values) ? values : [];
97
+ return raw.slice(0, 50).map((entry) => {
98
+ if (typeof entry === 'string') return redactPotentialSecrets(entry).slice(0, 500);
99
+ if (entry && typeof entry === 'object') return redactedClone(entry);
100
+ return String(entry || '').slice(0, 500);
101
+ }).filter((entry) => Boolean(typeof entry === 'string' ? entry.trim() : entry));
102
+ }
103
+
104
+ function phaseOrDefault(phase) {
105
+ const candidate = normalizeString(phase, 'pre_turn');
106
+ return ALLOWED_PHASES.has(candidate) ? candidate : 'pre_turn';
107
+ }
108
+
109
+ function hasEvidence(event, text) {
110
+ if (Array.isArray(event.evidence_refs) && event.evidence_refs.length > 0) return true;
111
+ if (event.validation?.passed === true || event.validation?.severity === 'pass') return true;
112
+ if (event.layer3?.pass === true) return true;
113
+ if (event.metadata?.validated_output === true || event.metadata?.verified === true) return true;
114
+ return MEASURABLE_EVIDENCE_RX.test(text || event.text_preview || '');
115
+ }
116
+
117
+ function hasVerifyEvidence(event, text) {
118
+ if (event.metadata?.requireVerify === false) return true;
119
+ if (event.metadata?.verify === true || event.metadata?.verified === true) return true;
120
+ if (VERIFY_RX.test(text || event.text_preview || '')) return true;
121
+ return hasEvidence(event, text) && /\b(?:rollback|verify|verified|deployment|rollout|kubectl|terraform|helm|docker)\b/i.test(text || event.text_preview || '');
122
+ }
123
+
124
+ function inferRiskClass(highRisk, repairable) {
125
+ if (highRisk.length > 0) return 'high';
126
+ if (repairable.length > 0) return 'medium';
127
+ return 'low';
128
+ }
129
+
130
+ function decisionFromSignals(highRisk, repairable, warnings) {
131
+ if (highRisk.length > 0) {
132
+ return {
133
+ decision: 'hard_block',
134
+ permitted: false,
135
+ nextAction: 'do_not_release; write operator evidence and re-author only after the high-risk condition is removed',
136
+ reasons: highRisk,
137
+ };
138
+ }
139
+ if (repairable.length > 0) {
140
+ return {
141
+ decision: 'repair_once',
142
+ permitted: false,
143
+ nextAction: 'repair_or_regenerate_once_before_user_visible_release',
144
+ reasons: repairable,
145
+ };
146
+ }
147
+ if (warnings.length > 0) {
148
+ return {
149
+ decision: 'warn_operator_only',
150
+ permitted: true,
151
+ nextAction: 'continue_and_preserve_operator_warning',
152
+ reasons: warnings,
153
+ };
154
+ }
155
+ return {
156
+ decision: 'allow',
157
+ permitted: true,
158
+ nextAction: 'continue',
159
+ reasons: [],
160
+ };
161
+ }
162
+
163
+ export function normalizeCoachEvent(input = {}) {
164
+ const phase = phaseOrDefault(input.phase);
165
+ const rawText = normalizeString(input.text || input.output || input.message || input.target || '');
166
+ const metadata = redactedClone(input.metadata && typeof input.metadata === 'object' ? input.metadata : {});
167
+ const record = {
168
+ coach_event_id: normalizeString(input.coachEventId || input.coach_event_id) || `coach_${randomUUID().replace(/-/g, '')}`,
169
+ request_id: normalizeString(input.requestId || input.request_id) || `req_${randomUUID().replace(/-/g, '')}`,
170
+ session_id: normalizeString(input.sessionId || input.session_id, 'unknown'),
171
+ surface: normalizeString(input.surface || input.client || input.platform, 'aria-runtime'),
172
+ lane: normalizeString(input.lane, 'managed_aria_provider'),
173
+ phase,
174
+ action: normalizeString(input.action),
175
+ target_hash: input.target ? hashValue(input.target) : null,
176
+ target_preview: input.target ? redactPotentialSecrets(String(input.target)).slice(0, 500) : null,
177
+ text_hash: rawText ? hashValue(rawText) : null,
178
+ text_preview: rawText ? redactPotentialSecrets(rawText).slice(0, 1000) : '',
179
+ harness_packet_hash: normalizeString(input.harnessPacketHash || input.harness_packet_hash),
180
+ role_profile: normalizeString(input.roleProfile || input.role_profile),
181
+ required_skill_ids: normalizeStringArray(input.requiredSkillIds || input.required_skill_ids),
182
+ loaded_skill_ids: normalizeStringArray(input.loadedSkillIds || input.loaded_skill_ids),
183
+ missing_skill_ids: normalizeStringArray(input.missingSkillIds || input.missing_skill_ids),
184
+ evidence_refs: normalizeEvidenceRefs(input.evidenceRefs || input.evidence_refs),
185
+ validation: redactedClone(input.validation || null),
186
+ layer3: redactedClone(input.layer3 || null),
187
+ quality_gate_status: normalizeString(input.qualityGateStatus || input.quality_gate_status, 'pending'),
188
+ compliance_gate_status: normalizeString(input.complianceGateStatus || input.compliance_gate_status, 'pending'),
189
+ metadata,
190
+ };
191
+ Object.defineProperty(record, 'rawText', { value: rawText, enumerable: false });
192
+ return record;
193
+ }
194
+
195
+ const DESTRUCTIVE_RX = /\b(?:rm\s+-[rRfF]+\S*|drop\s+(?:table|database|schema|collection|index)|git\s+(?:reset\s+--hard|push\s+--force|push\s+--delete)|sudo\s+|systemctl\s+(?:stop|disable|mask|kill)|kill\s+-[9K]|pkill\s+-[9K]|--no-verify|--no-gpg-sign|kubectl\s+(?:delete|scale\s+--replicas=0|rollout\s+undo)|docker\s+rm\s+-f|chmod\s+777|wget|curl.*\|\s*(?:ba)?sh)\b/i;
196
+ const DEPLOY_RX = /\b(?:kubectl\s+(?:apply|set|rollout|delete|create|replace|scale)|helm\s+(?:upgrade|install|uninstall)|terraform\s+(?:apply|destroy)|docker\s+(?:push|build\s+.*--push))\b/i;
197
+
198
+ export function evaluateCoachEvent(event = {}) {
199
+ const normalized = event.phase ? event : normalizeCoachEvent(event);
200
+ const text = normalized.rawText || normalized.text_preview || '';
201
+ const highRisk = [];
202
+ const repairable = [];
203
+ const warnings = [];
204
+ const action = String(normalized.action || '').toLowerCase();
205
+
206
+ if (!ALLOWED_PHASES.has(normalized.phase)) {
207
+ highRisk.push('unknown_coach_phase');
208
+ }
209
+ if (SECRET_VALUE_RX.test(text) || SECRET_VALUE_RX.test(stableString(normalized.metadata))) {
210
+ highRisk.push('secret_or_credential_exposure');
211
+ }
212
+ if (normalized.phase === 'pre_generation' && normalized.missing_skill_ids.length > 0) {
213
+ highRisk.push('required_skill_unavailable_before_generation');
214
+ }
215
+ if (TOOL_PHASES.has(normalized.phase) || action) {
216
+ if ((action === 'delete' || DESTRUCTIVE_RX.test(text)) && normalized.metadata?.approved !== true) {
217
+ highRisk.push('unapproved_destructive_action');
218
+ }
219
+ if ((action === 'deploy' || DEPLOY_RX.test(text)) && !hasVerifyEvidence(normalized, text)) {
220
+ highRisk.push('unverified_deploy_or_infra_mutation');
221
+ }
222
+ }
223
+ if (OUTPUT_PHASES.has(normalized.phase)) {
224
+ const nonTrivial = text.length >= 300 || COMPLETION_CLAIM_RX.test(text);
225
+ if (nonTrivial && !COGNITION_RX.test(text) && normalized.metadata?.requireCognitionBlock !== false) {
226
+ repairable.push('missing_readable_cognition_before_release');
227
+ }
228
+ if (nonTrivial && !APPLIED_COGNITION_RX.test(text) && normalized.metadata?.requireAppliedCognition !== false) {
229
+ repairable.push('missing_applied_cognition_before_release');
230
+ }
231
+ if (COMPLETION_CLAIM_RX.test(text) && !hasEvidence(normalized, text)) {
232
+ repairable.push('unsupported_completion_or_verification_claim');
233
+ }
234
+ }
235
+ if (normalized.missing_skill_ids.length > 0 && !normalized.metadata?.skillsAdvisoryOnly) {
236
+ repairable.push('required_skills_not_loaded');
237
+ }
238
+ if (normalized.lane.includes('unmanaged') || normalized.metadata?.complianceGuarantee === 'best_effort_only') {
239
+ warnings.push('unmanaged_direct_provider_best_effort_only');
240
+ }
241
+
242
+ const verdict = decisionFromSignals(highRisk, repairable, warnings);
243
+ return {
244
+ ...verdict,
245
+ riskClass: inferRiskClass(highRisk, repairable),
246
+ highRisk,
247
+ repairable,
248
+ warnings,
249
+ };
250
+ }
251
+
252
+ function readJson(pathname, fallback) {
253
+ if (!existsSync(pathname)) return fallback;
254
+ try {
255
+ return JSON.parse(readFileSync(pathname, 'utf8'));
256
+ } catch {
257
+ return fallback;
258
+ }
259
+ }
260
+
261
+ function summarizeRecord(record) {
262
+ return {
263
+ at: record.at,
264
+ coach_event_id: record.coach_event_id,
265
+ request_id: record.request_id,
266
+ session_id: record.session_id,
267
+ surface: record.surface,
268
+ lane: record.lane,
269
+ phase: record.phase,
270
+ decision: record.decision,
271
+ risk_class: record.risk_class,
272
+ action: record.action || null,
273
+ reasons: Array.isArray(record.reasons) ? record.reasons.slice(0, 6) : [],
274
+ evidence_count: Array.isArray(record.evidence_refs) ? record.evidence_refs.length : 0,
275
+ };
276
+ }
277
+
278
+ function updateCoachState(record, statePath) {
279
+ const state = readJson(statePath, {
280
+ schema: COACH_STATE_SCHEMA,
281
+ updated_at: null,
282
+ counts: { total: 0, by_phase: {}, by_decision: {} },
283
+ last_events: [],
284
+ last_by_session: {},
285
+ });
286
+ state.schema = COACH_STATE_SCHEMA;
287
+ state.updated_at = record.at;
288
+ state.counts = state.counts || { total: 0, by_phase: {}, by_decision: {} };
289
+ state.counts.total = Number(state.counts.total || 0) + 1;
290
+ state.counts.by_phase = state.counts.by_phase || {};
291
+ state.counts.by_decision = state.counts.by_decision || {};
292
+ state.counts.by_phase[record.phase] = Number(state.counts.by_phase[record.phase] || 0) + 1;
293
+ state.counts.by_decision[record.decision] = Number(state.counts.by_decision[record.decision] || 0) + 1;
294
+ const summary = summarizeRecord(record);
295
+ state.last_events = [...(Array.isArray(state.last_events) ? state.last_events : []), summary].slice(-100);
296
+ state.last_by_session = state.last_by_session || {};
297
+ state.last_by_session[record.session_id] = summary;
298
+ writeFileSync(statePath, `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 });
299
+ return state;
300
+ }
301
+
302
+ export function recordCoachPhase(input = {}, options = {}) {
303
+ const ledgerPath = options.ledgerPath || DEFAULT_COACH_LEDGER_PATH;
304
+ const statePath = options.statePath || DEFAULT_COACH_STATE_PATH;
305
+ mkdirSync(dirname(ledgerPath), { recursive: true, mode: 0o700 });
306
+ mkdirSync(dirname(statePath), { recursive: true, mode: 0o700 });
307
+ const event = normalizeCoachEvent(input);
308
+ const evaluation = evaluateCoachEvent(event);
309
+ const record = {
310
+ schema: COACH_EVENT_SCHEMA,
311
+ at: nowIso(),
312
+ ...event,
313
+ risk_class: evaluation.riskClass,
314
+ decision: evaluation.decision,
315
+ permitted: evaluation.permitted,
316
+ reasons: evaluation.reasons,
317
+ high_risk_signals: evaluation.highRisk,
318
+ repairable_signals: evaluation.repairable,
319
+ warnings: evaluation.warnings,
320
+ next_action: evaluation.nextAction,
321
+ };
322
+ appendFileSync(ledgerPath, `${JSON.stringify(record)}\n`, { mode: 0o600 });
323
+ const state = updateCoachState(record, statePath);
324
+ return {
325
+ ok: true,
326
+ permitted: record.permitted,
327
+ decision: record.decision,
328
+ ledgerPath,
329
+ statePath,
330
+ record,
331
+ state: summarizeCoachState(state),
332
+ clientMessage: formatCoachClientBlock(record),
333
+ };
334
+ }
335
+
336
+ export function summarizeCoachState(state = null) {
337
+ const source = state || readJson(DEFAULT_COACH_STATE_PATH, null);
338
+ if (!source) {
339
+ return {
340
+ schema: COACH_STATE_SCHEMA,
341
+ updated_at: null,
342
+ counts: { total: 0, by_phase: {}, by_decision: {} },
343
+ last_events: [],
344
+ };
345
+ }
346
+ return {
347
+ schema: source.schema || COACH_STATE_SCHEMA,
348
+ updated_at: source.updated_at || null,
349
+ counts: source.counts || { total: 0, by_phase: {}, by_decision: {} },
350
+ last_events: Array.isArray(source.last_events) ? source.last_events.slice(-25) : [],
351
+ };
352
+ }
353
+
354
+ export function readCoachState(options = {}) {
355
+ const statePath = options.statePath || DEFAULT_COACH_STATE_PATH;
356
+ const state = readJson(statePath, null);
357
+ return options.includeState === true ? state : summarizeCoachState(state);
358
+ }
359
+
360
+ export function formatCoachClientBlock(recordOrResult = {}) {
361
+ const record = recordOrResult.record || recordOrResult;
362
+ const reasons = Array.isArray(record.reasons) && record.reasons.length
363
+ ? record.reasons
364
+ : ['coach_kernel_policy_block'];
365
+ const status = record.decision === 'repair_once'
366
+ ? 'Aria Coach held this turn for repair before release.'
367
+ : record.decision === 'hard_block'
368
+ ? 'Aria Coach blocked this turn before release.'
369
+ : 'Aria Coach recorded an operator warning for this turn.';
370
+ const next = record.next_action || (record.decision === 'hard_block' ? 'remove the high-risk condition before retrying' : 'continue');
371
+ return [
372
+ status,
373
+ '',
374
+ `Reason: ${reasons.slice(0, 3).join('; ')}`,
375
+ `Next: ${next}`,
376
+ ].join('\n');
377
+ }