@aria_asi/cli 0.2.32 → 0.2.34

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 (93) hide show
  1. package/dist/aria-connector/src/connectors/codebase-awareness.d.ts +8 -1
  2. package/dist/aria-connector/src/connectors/codebase-awareness.d.ts.map +1 -1
  3. package/dist/aria-connector/src/connectors/codebase-awareness.js +126 -71
  4. package/dist/aria-connector/src/connectors/codebase-awareness.js.map +1 -1
  5. package/dist/aria-connector/src/connectors/codex.d.ts.map +1 -1
  6. package/dist/aria-connector/src/connectors/codex.js +98 -0
  7. package/dist/aria-connector/src/connectors/codex.js.map +1 -1
  8. package/dist/aria-connector/src/setup-wizard.d.ts.map +1 -1
  9. package/dist/aria-connector/src/setup-wizard.js +91 -24
  10. package/dist/aria-connector/src/setup-wizard.js.map +1 -1
  11. package/dist/assets/hooks/aria-harness-via-sdk.mjs +26 -8
  12. package/dist/assets/hooks/aria-pre-tool-gate.mjs +60 -1
  13. package/dist/assets/hooks/aria-stop-gate.mjs +69 -3
  14. package/dist/assets/hooks/doctrine_trigger_map.json +43 -0
  15. package/dist/assets/hooks/lib/domain-output-quality.mjs +103 -0
  16. package/dist/assets/hooks/lib/skill-autoload-gate.mjs +14 -0
  17. package/dist/assets/opencode-plugins/harness-context/index.js +1 -1
  18. package/dist/assets/opencode-plugins/harness-gate/index.js +114 -10
  19. package/dist/assets/opencode-plugins/harness-gate/lib/skill-autoload-gate.js +14 -0
  20. package/dist/assets/opencode-plugins/harness-outcome/index.js +39 -0
  21. package/dist/assets/opencode-plugins/harness-stop/index.js +234 -139
  22. package/dist/assets/opencode-plugins/harness-stop/lib/domain-output-quality.js +103 -0
  23. package/dist/assets/opencode-plugins/harness-stop/lib/skill-autoload-gate.js +14 -0
  24. package/dist/runtime/codex-bridge.mjs +71 -8
  25. package/dist/runtime/discipline/CLAUDE.md +2 -2
  26. package/dist/runtime/discipline/doctrine_trigger_map.json +43 -0
  27. package/dist/runtime/discipline/skills/aria-harness/aria-harness-onboarding/SKILL.md +3 -3
  28. package/dist/runtime/doctrine_trigger_map.json +43 -0
  29. package/dist/runtime/harness-daemon.mjs +50 -2
  30. package/dist/runtime/hooks/aria-agent-handoff.mjs +247 -0
  31. package/dist/runtime/hooks/aria-agent-ledger-merge.mjs +164 -0
  32. package/dist/runtime/hooks/aria-architect-fallback.mjs +267 -0
  33. package/dist/runtime/hooks/aria-cognition-substrate-binding.mjs +761 -0
  34. package/dist/runtime/hooks/aria-discovery-record.mjs +101 -0
  35. package/dist/runtime/hooks/aria-harness-via-sdk.mjs +544 -0
  36. package/dist/runtime/hooks/aria-import-resolution-gate.mjs +330 -0
  37. package/dist/runtime/hooks/aria-outcome-record.mjs +84 -0
  38. package/dist/runtime/hooks/aria-pre-emit-dryrun.mjs +329 -0
  39. package/dist/runtime/hooks/aria-pre-text-gate.mjs +112 -0
  40. package/dist/runtime/hooks/aria-pre-tool-gate.mjs +2482 -0
  41. package/dist/runtime/hooks/aria-preprompt-consult.mjs +464 -0
  42. package/dist/runtime/hooks/aria-preturn-memory-gate.mjs +647 -0
  43. package/dist/runtime/hooks/aria-repo-doctrine-gate.mjs +429 -0
  44. package/dist/runtime/hooks/aria-stop-gate.mjs +1882 -0
  45. package/dist/runtime/hooks/aria-trigger-autolearn.mjs +229 -0
  46. package/dist/runtime/hooks/aria-userprompt-abandon-detect.mjs +192 -0
  47. package/dist/runtime/hooks/doctrine_trigger_map.json +577 -0
  48. package/dist/runtime/hooks/lib/canonical-lenses.mjs +65 -0
  49. package/dist/runtime/hooks/lib/domain-output-quality.mjs +103 -0
  50. package/dist/runtime/hooks/lib/gate-audit.mjs +43 -0
  51. package/dist/runtime/hooks/lib/gate-loop-state.mjs +50 -0
  52. package/dist/runtime/hooks/lib/hook-message-window.mjs +121 -0
  53. package/dist/runtime/hooks/lib/skill-autoload-gate.mjs +14 -0
  54. package/dist/runtime/hooks/test-aria-preturn-memory-gate.mjs +245 -0
  55. package/dist/runtime/hooks/test-tier-lens-labeling.mjs +367 -0
  56. package/dist/runtime/manifest.json +2 -2
  57. package/dist/runtime/sdk/BUNDLED.json +2 -2
  58. package/dist/runtime/sdk/index.d.ts +48 -0
  59. package/dist/runtime/sdk/index.js +140 -1
  60. package/dist/runtime/sdk/index.js.map +1 -1
  61. package/dist/runtime/sdk/runWithGovernance.d.ts +16 -0
  62. package/dist/runtime/sdk/runWithGovernance.js +54 -0
  63. package/dist/runtime/sdk/runWithGovernance.js.map +1 -0
  64. package/dist/runtime/service.mjs +339 -10
  65. package/dist/sdk/BUNDLED.json +2 -2
  66. package/dist/sdk/index.d.ts +48 -0
  67. package/dist/sdk/index.js +140 -1
  68. package/dist/sdk/index.js.map +1 -1
  69. package/dist/sdk/runWithGovernance.d.ts +16 -0
  70. package/dist/sdk/runWithGovernance.js +54 -0
  71. package/dist/sdk/runWithGovernance.js.map +1 -0
  72. package/hooks/aria-harness-via-sdk.mjs +26 -8
  73. package/hooks/aria-pre-tool-gate.mjs +60 -1
  74. package/hooks/aria-stop-gate.mjs +69 -3
  75. package/hooks/doctrine_trigger_map.json +43 -0
  76. package/hooks/lib/domain-output-quality.mjs +103 -0
  77. package/hooks/lib/skill-autoload-gate.mjs +14 -0
  78. package/opencode-plugins/harness-context/index.js +1 -1
  79. package/opencode-plugins/harness-gate/index.js +114 -10
  80. package/opencode-plugins/harness-gate/lib/skill-autoload-gate.js +14 -0
  81. package/opencode-plugins/harness-outcome/index.js +39 -0
  82. package/opencode-plugins/harness-stop/index.js +234 -139
  83. package/opencode-plugins/harness-stop/lib/domain-output-quality.js +103 -0
  84. package/opencode-plugins/harness-stop/lib/skill-autoload-gate.js +14 -0
  85. package/package.json +12 -5
  86. package/runtime-src/codex-bridge.mjs +71 -8
  87. package/runtime-src/harness-daemon.mjs +50 -2
  88. package/runtime-src/service.mjs +339 -10
  89. package/scripts/bundle-sdk.mjs +2 -0
  90. package/scripts/self-test-harness-gates.mjs +79 -0
  91. package/src/connectors/codebase-awareness.ts +141 -77
  92. package/src/connectors/codex.ts +98 -0
  93. package/src/setup-wizard.ts +105 -25
@@ -0,0 +1,367 @@
1
+ #!/usr/bin/env node
2
+ // Smoke test: Phase 11 #59 — canonical lens labeling
3
+ //
4
+ // Verifies that aria-pre-tool-gate.mjs and aria-stop-gate.mjs:
5
+ // 1. Show canonical Arabic lens names (nur, mizan, etc.) when the harness
6
+ // packet has isHamza/hamza=true (OWNER tier).
7
+ // 2. Preserve those same canonical labels on client-surface execution too.
8
+ // 3. Gate enforcement (block on insufficient cognition) fires in both
9
+ // tiers without renaming the lenses.
10
+ //
11
+ // Usage: node hooks/test-tier-lens-labeling.mjs
12
+ // Exit: 0 = all assertions passed, 1 = failure
13
+
14
+ import { spawnSync } from 'node:child_process';
15
+ import { writeFileSync, mkdirSync, existsSync, unlinkSync, readFileSync } from 'node:fs';
16
+ import * as path from 'node:path';
17
+ import { fileURLToPath } from 'node:url';
18
+
19
+ const HERE = path.dirname(fileURLToPath(import.meta.url));
20
+ const PRE_TOOL_HOOK = path.join(HERE, 'aria-pre-tool-gate.mjs');
21
+ const STOP_HOOK = path.join(HERE, 'aria-stop-gate.mjs');
22
+ const HOME = process.env.HOME || '/tmp';
23
+ const CLAUDE_DIR = `${HOME}/.claude`;
24
+ const PACKET_PATH = `${CLAUDE_DIR}/.aria-harness-last-packet.json`;
25
+
26
+ // ── Canonical label set ────────────────────────────────────────────────────
27
+ const CANONICAL = ['nur', 'mizan', 'hikma', 'tafakkur', 'tadabbur', 'ilham', 'wahi', 'firasah'];
28
+
29
+ // ── Assertion helpers ───────────────────────────────────────────────────────
30
+ let passed = 0;
31
+ let failed = 0;
32
+
33
+ function assert(label, condition, detail) {
34
+ if (condition) {
35
+ console.log(` PASS ${label}`);
36
+ passed++;
37
+ } else {
38
+ console.error(` FAIL ${label}`);
39
+ if (detail !== undefined) console.error(` detail: ${String(detail).slice(0, 300)}`);
40
+ failed++;
41
+ }
42
+ }
43
+
44
+ // ── Packet helpers ──────────────────────────────────────────────────────────
45
+ // Save/restore the real packet so running this test doesn't corrupt live state.
46
+ let originalPacketContent = null;
47
+
48
+ function savePacket() {
49
+ try {
50
+ if (existsSync(PACKET_PATH)) {
51
+ originalPacketContent = readFileSync(PACKET_PATH, 'utf8');
52
+ } else {
53
+ originalPacketContent = null;
54
+ }
55
+ } catch { originalPacketContent = null; }
56
+ }
57
+
58
+ function restorePacket() {
59
+ try {
60
+ if (originalPacketContent !== null) {
61
+ writeFileSync(PACKET_PATH, originalPacketContent);
62
+ } else if (existsSync(PACKET_PATH)) {
63
+ unlinkSync(PACKET_PATH);
64
+ }
65
+ } catch {}
66
+ }
67
+
68
+ function writeOwnerPacket() {
69
+ // contractGate.signals.hamza === true → OWNER tier
70
+ const packet = {
71
+ ok: true,
72
+ stage: 'preflight',
73
+ harness: 'surface=platform:hamza group:false hamza:true',
74
+ contractGate: {
75
+ signals: { hamza: true },
76
+ },
77
+ };
78
+ if (!existsSync(CLAUDE_DIR)) mkdirSync(CLAUDE_DIR, { recursive: true });
79
+ writeFileSync(PACKET_PATH, JSON.stringify(packet));
80
+ }
81
+
82
+ function writeClientPacket() {
83
+ // contractGate.signals.hamza === "false" (string) → CLIENT tier
84
+ const packet = {
85
+ ok: true,
86
+ stage: 'preflight',
87
+ harness: 'surface=platform:client group:false hamza:false',
88
+ contractGate: {
89
+ signals: { hamza: 'false' },
90
+ },
91
+ };
92
+ if (!existsSync(CLAUDE_DIR)) mkdirSync(CLAUDE_DIR, { recursive: true });
93
+ writeFileSync(PACKET_PATH, JSON.stringify(packet));
94
+ }
95
+
96
+ // ── Transcript helpers ──────────────────────────────────────────────────────
97
+ // Write a minimal transcript where the most recent assistant turn has NO
98
+ // cognition block — triggering a block decision.
99
+ function writeEmptyTranscript(transcriptPath) {
100
+ const entries = [
101
+ // User message
102
+ JSON.stringify({
103
+ message: { role: 'user', content: [{ type: 'text', text: 'Run a build command' }] },
104
+ }),
105
+ // Assistant text with no cognition
106
+ JSON.stringify({
107
+ message: {
108
+ role: 'assistant',
109
+ content: [{ type: 'text', text: 'I will run the build.' }],
110
+ },
111
+ }),
112
+ ];
113
+ writeFileSync(transcriptPath, entries.join('\n'));
114
+ }
115
+
116
+ // Write a transcript with a Stop-gate-triggering assistant response (long,
117
+ // decision-signal, but no cognition).
118
+ function writeNoCognitionStopTranscript(transcriptPath) {
119
+ const longText = 'I recommend shipping this feature immediately because the test suite is green and the build passed. Let me proceed with the deployment now. ' +
120
+ 'The plan is as follows: first we build, then we deploy, then we verify. I would suggest we move forward without delay.';
121
+ const entries = [
122
+ JSON.stringify({
123
+ message: { role: 'user', content: [{ type: 'text', text: 'Should I ship?' }] },
124
+ }),
125
+ JSON.stringify({
126
+ message: {
127
+ role: 'assistant',
128
+ content: [{ type: 'text', text: longText }],
129
+ },
130
+ }),
131
+ ];
132
+ writeFileSync(transcriptPath, entries.join('\n'));
133
+ }
134
+
135
+ // ── Run hook helpers ────────────────────────────────────────────────────────
136
+ // Use a non-destructive but non-trivial command that skips the verify path
137
+ // and goes straight to cognition-missing, where lens labels appear.
138
+ function runPreToolGate(transcriptPath, command = 'npm run build --workspace=packages/aria-connector') {
139
+ const event = JSON.stringify({
140
+ tool_name: 'Bash',
141
+ tool_input: { command },
142
+ transcript_path: transcriptPath,
143
+ session_id: `test-tier-${Date.now()}`,
144
+ });
145
+ return spawnSync(process.execPath, [PRE_TOOL_HOOK], {
146
+ input: event,
147
+ encoding: 'utf8',
148
+ timeout: 10000,
149
+ env: {
150
+ ...process.env,
151
+ HOME,
152
+ ARIA_COGNITION_PUSH: 'off', // silence network push
153
+ ARIA_HARNESS_TOKEN: '', // no outbound harness calls
154
+ ARIA_BINDING_ENABLED: 'false', // disable binding gate — isolate cognition test
155
+ },
156
+ });
157
+ }
158
+
159
+ function runStopGate(transcriptPath) {
160
+ const event = JSON.stringify({
161
+ tool_name: 'Stop',
162
+ transcript_path: transcriptPath,
163
+ session_id: `test-tier-${Date.now()}`,
164
+ });
165
+ return spawnSync(process.execPath, [STOP_HOOK], {
166
+ input: event,
167
+ encoding: 'utf8',
168
+ timeout: 15000,
169
+ env: {
170
+ ...process.env,
171
+ HOME,
172
+ ARIA_COGNITION_PUSH: 'off',
173
+ ARIA_HARNESS_TOKEN: '',
174
+ },
175
+ });
176
+ }
177
+
178
+ // ── Test utilities ──────────────────────────────────────────────────────────
179
+ const tmpTranscript = `/tmp/test-tier-transcript-${Date.now()}.jsonl`;
180
+ const tmpTranscriptStop = `/tmp/test-tier-stop-transcript-${Date.now()}.jsonl`;
181
+
182
+ function cleanup() {
183
+ [tmpTranscript, tmpTranscriptStop].forEach((p) => {
184
+ try { if (existsSync(p)) unlinkSync(p); } catch {}
185
+ });
186
+ restorePacket();
187
+ }
188
+
189
+ // ── Suite ───────────────────────────────────────────────────────────────────
190
+
191
+ console.log('\n=== Phase 11 #59 — Tier-aware lens labeling smoke tests ===\n');
192
+
193
+ // Save existing packet so we can restore after test run.
194
+ savePacket();
195
+
196
+ // ── Test 1: pre-tool-gate, OWNER tier → canonical labels in block reason ──
197
+ console.log('Test 1: aria-pre-tool-gate — OWNER tier shows canonical lens names');
198
+ {
199
+ writeOwnerPacket();
200
+ writeEmptyTranscript(tmpTranscript);
201
+ const result = runPreToolGate(tmpTranscript);
202
+
203
+ // Gate should block (exit 2) — no cognition in transcript
204
+ assert(
205
+ 'T1: gate blocks (exit 2)',
206
+ result.status === 2,
207
+ `exit=${result.status} stderr=${result.stderr?.slice(0, 200)}`,
208
+ );
209
+
210
+ let blockReason = '';
211
+ try {
212
+ const parsed = JSON.parse(result.stdout);
213
+ blockReason = parsed.reason || '';
214
+ } catch {
215
+ blockReason = result.stdout || '';
216
+ }
217
+
218
+ // Must mention at least one canonical label
219
+ const hasCanonical = CANONICAL.some((name) => blockReason.includes(`${name}:`));
220
+ assert(
221
+ 'T1: block reason mentions canonical label (e.g. nur:)',
222
+ hasCanonical,
223
+ blockReason.slice(0, 400),
224
+ );
225
+
226
+ // The first visible lens label must be canonical.
227
+ const firstCanonicalIdx = blockReason.indexOf(`${CANONICAL[0]}:`);
228
+ assert(
229
+ 'T1: first lens label is canonical (nur:)',
230
+ firstCanonicalIdx >= 0,
231
+ `firstCanonicalIdx=${firstCanonicalIdx}`,
232
+ );
233
+ }
234
+
235
+ // ── Test 2: pre-tool-gate, CLIENT tier → canonical labels in block reason ──
236
+ console.log('\nTest 2: aria-pre-tool-gate — CLIENT tier keeps canonical lens labels');
237
+ {
238
+ writeClientPacket();
239
+ writeEmptyTranscript(tmpTranscript);
240
+ const result = runPreToolGate(tmpTranscript);
241
+
242
+ assert(
243
+ 'T2: gate blocks (exit 2)',
244
+ result.status === 2,
245
+ `exit=${result.status} stderr=${result.stderr?.slice(0, 200)}`,
246
+ );
247
+
248
+ let blockReason = '';
249
+ try {
250
+ const parsed = JSON.parse(result.stdout);
251
+ blockReason = parsed.reason || '';
252
+ } catch {
253
+ blockReason = result.stdout || '';
254
+ }
255
+
256
+ const hasCanonical = CANONICAL.some((name) => blockReason.includes(`${name}:`));
257
+ assert(
258
+ 'T2: block reason mentions canonical label (e.g. nur:)',
259
+ hasCanonical,
260
+ blockReason.slice(0, 400),
261
+ );
262
+ assert(
263
+ 'T2: first visible lens label is canonical (nur:)',
264
+ blockReason.includes(`${CANONICAL[0]}:`),
265
+ blockReason.slice(0, 400),
266
+ );
267
+ }
268
+
269
+ // ── Test 3: stop-gate, OWNER tier → canonical labels ──
270
+ console.log('\nTest 3: aria-stop-gate — OWNER tier shows canonical lens names');
271
+ {
272
+ writeOwnerPacket();
273
+ writeNoCognitionStopTranscript(tmpTranscriptStop);
274
+ const result = runStopGate(tmpTranscriptStop);
275
+
276
+ assert(
277
+ 'T3: stop-gate blocks (exit 2)',
278
+ result.status === 2,
279
+ `exit=${result.status} stderr=${result.stderr?.slice(0, 200)}`,
280
+ );
281
+
282
+ let blockReason = '';
283
+ try {
284
+ const parsed = JSON.parse(result.stdout);
285
+ blockReason = parsed.reason || '';
286
+ } catch {
287
+ blockReason = result.stdout || '';
288
+ }
289
+
290
+ const hasCanonical = CANONICAL.some((name) => blockReason.includes(`${name}:`));
291
+ assert(
292
+ 'T3: stop-gate block reason mentions canonical label',
293
+ hasCanonical,
294
+ blockReason.slice(0, 400),
295
+ );
296
+ }
297
+
298
+ // ── Test 4: stop-gate, CLIENT tier → canonical labels ──────────────────────
299
+ console.log('\nTest 4: aria-stop-gate — CLIENT tier keeps canonical lens labels');
300
+ {
301
+ writeClientPacket();
302
+ writeNoCognitionStopTranscript(tmpTranscriptStop);
303
+ const result = runStopGate(tmpTranscriptStop);
304
+
305
+ assert(
306
+ 'T4: stop-gate blocks (exit 2)',
307
+ result.status === 2,
308
+ `exit=${result.status} stderr=${result.stderr?.slice(0, 200)}`,
309
+ );
310
+
311
+ let blockReason = '';
312
+ try {
313
+ const parsed = JSON.parse(result.stdout);
314
+ blockReason = parsed.reason || '';
315
+ } catch {
316
+ blockReason = result.stdout || '';
317
+ }
318
+
319
+ const hasCanonical = CANONICAL.some((name) => blockReason.includes(`${name}:`));
320
+ assert(
321
+ 'T4: stop-gate block reason mentions canonical label',
322
+ hasCanonical,
323
+ blockReason.slice(0, 400),
324
+ );
325
+ }
326
+
327
+ // ── Test 5: packet missing → defaults to canonical labels (fail-safe) ─────
328
+ console.log('\nTest 5: missing packet cache → defaults to canonical labels');
329
+ {
330
+ // Remove the packet cache
331
+ try { unlinkSync(PACKET_PATH); } catch {}
332
+ writeEmptyTranscript(tmpTranscript);
333
+ const result = runPreToolGate(tmpTranscript);
334
+
335
+ assert(
336
+ 'T5: gate blocks (exit 2) with no packet',
337
+ result.status === 2,
338
+ `exit=${result.status}`,
339
+ );
340
+
341
+ let blockReason = '';
342
+ try {
343
+ const parsed = JSON.parse(result.stdout);
344
+ blockReason = parsed.reason || '';
345
+ } catch {
346
+ blockReason = result.stdout || '';
347
+ }
348
+
349
+ const hasCanonical = CANONICAL.some((name) => blockReason.includes(`${name}:`));
350
+ assert(
351
+ 'T5: defaults to canonical labels when packet is absent',
352
+ hasCanonical,
353
+ `canonical=${hasCanonical} reason=${blockReason.slice(0, 300)}`,
354
+ );
355
+ }
356
+
357
+ // ── Summary ─────────────────────────────────────────────────────────────────
358
+ cleanup();
359
+ console.log(`\n${'─'.repeat(60)}`);
360
+ console.log(`Results: ${passed} passed, ${failed} failed`);
361
+ if (failed > 0) {
362
+ console.error('\nSome tests FAILED — see FAIL lines above.');
363
+ process.exit(1);
364
+ } else {
365
+ console.log('\nAll tests PASSED.');
366
+ process.exit(0);
367
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
- "bundledAt": "2026-05-01T20:07:31.761Z",
3
- "sdkFiles": 6,
2
+ "bundledAt": "2026-05-03T03:42:17.303Z",
3
+ "sdkFiles": 9,
4
4
  "runtimeTemplate": "/home/hamzaibrahim1/rei-ai-brain/packages/aria-connector/runtime-src",
5
5
  "gateRuntimeSource": "/home/hamzaibrahim1/rei-ai-brain/packages/aria-gate-runtime/dist",
6
6
  "sdkGuideSource": "/home/hamzaibrahim1/rei-ai-brain/harness/packages/harness-http-client/CLAUDE.md",
@@ -1,5 +1,5 @@
1
1
  {
2
- "bundledAt": "2026-05-01T20:07:31.757Z",
2
+ "bundledAt": "2026-05-03T03:42:17.293Z",
3
3
  "sdkSource": "/home/hamzaibrahim1/rei-ai-brain/harness/packages/harness-http-client/dist",
4
- "files": 6
4
+ "files": 9
5
5
  }
@@ -2,6 +2,7 @@ export interface HarnessClientConfig {
2
2
  baseUrl: string;
3
3
  apiKey: string;
4
4
  harnessPacketUrl?: string;
5
+ gardenBaseUrl?: string;
5
6
  workspaceRoot?: string;
6
7
  }
7
8
  export interface OwnerTier {
@@ -103,12 +104,21 @@ export interface HarnessBindingContext {
103
104
  includeAegisLearnings?: boolean;
104
105
  extraBody?: Record<string, unknown>;
105
106
  }
107
+ export interface HarnessEvidenceRef {
108
+ evidenceId: string;
109
+ kind: string;
110
+ at: string;
111
+ sha256: string;
112
+ preview: string;
113
+ metadata?: Record<string, unknown>;
114
+ }
106
115
  export interface BoundHarnessPromptResult {
107
116
  prompt: string;
108
117
  packet: HarnessPacket;
109
118
  harnessText: string;
110
119
  bindingBody: Record<string, unknown>;
111
120
  }
121
+ export declare function createHarnessEvidenceRef(kind: string, value: unknown, metadata?: Record<string, unknown>): HarnessEvidenceRef;
112
122
  export interface RecordDiscoveryArgs {
113
123
  /** Finding text (min 4 chars). */
114
124
  text: string;
@@ -161,6 +171,36 @@ export interface ActionCheck {
161
171
  reason?: string;
162
172
  requiredGates: string[];
163
173
  }
174
+ export interface GardenContinuitySnapshot {
175
+ hydrated: boolean;
176
+ sessionId: string;
177
+ userId?: string;
178
+ query: string;
179
+ contextBlock: string;
180
+ memoryCount: number;
181
+ threadCount: number;
182
+ pulseCount: number;
183
+ snapshotMs: number;
184
+ postgresBound?: boolean;
185
+ qdrantBound?: boolean;
186
+ pulseLoopAlive?: boolean;
187
+ }
188
+ export interface GovernanceOutcomeInput {
189
+ sessionId: string;
190
+ userId?: string;
191
+ sourceRuntime: string;
192
+ action?: string;
193
+ outcome: string;
194
+ evidence?: unknown;
195
+ obligationId?: string;
196
+ }
197
+ export interface GovernanceOutcomeResult {
198
+ ok: boolean;
199
+ pulseId?: string;
200
+ ledgerId?: string;
201
+ threadId?: string;
202
+ message?: string;
203
+ }
164
204
  /**
165
205
  * Result shape for all three Aristotle phases.
166
206
  * Mirrors `AristotleNoorWireResult` in aria-connector's aristotle-noor-wire.ts.
@@ -261,6 +301,7 @@ export declare class HTTPHarnessClient {
261
301
  private readonly baseUrl;
262
302
  private readonly apiKey;
263
303
  private readonly harnessPacketUrl;
304
+ private readonly gardenBaseUrl?;
264
305
  private readonly workspaceRoot;
265
306
  private cachedPacket;
266
307
  private packetLastFetched;
@@ -303,6 +344,12 @@ export declare class HTTPHarnessClient {
303
344
  validateOutput(text: string, sessionId: string): Promise<ValidationResult>;
304
345
  checkAction(action: 'deploy' | 'build' | 'write' | 'delete', target: string): Promise<ActionCheck>;
305
346
  gardenTurn(sessionId: string, message: string, response: string, userId?: string): Promise<void>;
347
+ hydrateGardenContinuity(sessionId: string, query: string, limits?: {
348
+ threadLimit?: number;
349
+ pulseLimit?: number;
350
+ userId?: string;
351
+ }): Promise<GardenContinuitySnapshot>;
352
+ persistGovernanceOutcome(input: GovernanceOutcomeInput): Promise<GovernanceOutcomeResult>;
306
353
  consult(args: {
307
354
  brief: string;
308
355
  sessionId: string;
@@ -487,3 +534,4 @@ export declare const harness: {
487
534
  export declare function bindingContext(role: string, sessionId: string, stage: string, intendedAction: string, rationale: string): HarnessBindingContext;
488
535
  export declare function getBoundHarnessAndPrompt(context: HarnessBindingContext, plan?: Partial<HarnessPlan>, client?: HTTPHarnessClient): Promise<BoundHarnessPromptResult>;
489
536
  export * from './runWithCognition.js';
537
+ export * from './runWithGovernance.js';
@@ -2,7 +2,7 @@ import { readFile } from 'node:fs/promises';
2
2
  import { existsSync, readFileSync, statSync } from 'node:fs';
3
3
  import { homedir as _homedir } from 'node:os';
4
4
  import { resolve, isAbsolute } from 'node:path';
5
- import { randomUUID } from 'node:crypto';
5
+ import { createHash, randomUUID } from 'node:crypto';
6
6
  const CLOUD_RUN_SOUL_URL = 'https://arias-soul-6zp3gtk2ca-uc.a.run.app';
7
7
  const PUBLIC_HARNESS_URL = 'https://harness.ariasos.com';
8
8
  const LOCAL_HARNESS_CANDIDATES = [
@@ -29,6 +29,28 @@ function normalizeHarnessPacketPayload(payload) {
29
29
  ? current
30
30
  : {};
31
31
  }
32
+ function stableEvidenceString(value) {
33
+ if (typeof value === 'string')
34
+ return value;
35
+ try {
36
+ return JSON.stringify(value);
37
+ }
38
+ catch {
39
+ return String(value);
40
+ }
41
+ }
42
+ export function createHarnessEvidenceRef(kind, value, metadata) {
43
+ const raw = stableEvidenceString(value);
44
+ const sha256 = createHash('sha256').update(raw).digest('hex');
45
+ return {
46
+ evidenceId: `ev_${sha256.slice(0, 16)}`,
47
+ kind,
48
+ at: new Date().toISOString(),
49
+ sha256,
50
+ preview: raw.slice(0, 500),
51
+ ...(metadata && Object.keys(metadata).length > 0 ? { metadata } : {}),
52
+ };
53
+ }
32
54
  // ── 8-Lens Cognition Block ─────────────────────────────────────────────────
33
55
  const EIGHT_LENS_BLOCK = `[ARIA SHELL PROTOCOL — You are a controlled surface]
34
56
 
@@ -65,6 +87,7 @@ export class HTTPHarnessClient {
65
87
  baseUrl;
66
88
  apiKey;
67
89
  harnessPacketUrl;
90
+ gardenBaseUrl;
68
91
  workspaceRoot;
69
92
  cachedPacket = null;
70
93
  packetLastFetched = 0;
@@ -77,6 +100,7 @@ export class HTTPHarnessClient {
77
100
  this.harnessPacketUrl = config.harnessPacketUrl ?? (isMountedRuntimeBaseUrl(this.baseUrl)
78
101
  ? `${this.baseUrl}/packet`
79
102
  : `${this.baseUrl}/api/harness/codex`);
103
+ this.gardenBaseUrl = (config.gardenBaseUrl || process.env.ARIA_GARDEN_BASE_URL || '').replace(/\/+$/, '') || undefined;
80
104
  this.workspaceRoot = config.workspaceRoot ?? process.cwd();
81
105
  this.preferredBaseUrl = this.baseUrl;
82
106
  this.baseUrlCandidates = this.buildBaseUrlCandidates(config.baseUrl);
@@ -643,6 +667,120 @@ export class HTTPHarnessClient {
643
667
  throw new Error(`garden/fire failed: ${res.status} ${res.statusText}`);
644
668
  }
645
669
  }
670
+ async hydrateGardenContinuity(sessionId, query, limits = {}) {
671
+ if (this.gardenBaseUrl) {
672
+ const params = new URLSearchParams({
673
+ session_id: sessionId,
674
+ user_id: limits.userId || '',
675
+ query,
676
+ thread_limit: String(limits.threadLimit ?? 5),
677
+ pulse_limit: String(limits.pulseLimit ?? 12),
678
+ });
679
+ const res = await this.fetchWithRetry(`${this.gardenBaseUrl}/continuity?${params}`, {
680
+ method: 'GET',
681
+ headers: {
682
+ Authorization: `Bearer ${this.apiKey}`,
683
+ 'Content-Type': 'application/json',
684
+ },
685
+ });
686
+ if (res.ok) {
687
+ const data = (await res.json());
688
+ const activeThreads = Array.isArray(data.activeThreads) ? data.activeThreads : [];
689
+ const recentPulses = Array.isArray(data.recentPulses) ? data.recentPulses : [];
690
+ const contextBlock = String(data.continuityBlock || data.continuity_block || data.gardenContextBlock || '');
691
+ return {
692
+ hydrated: Boolean(data.ok) && (contextBlock.length > 0 || activeThreads.length > 0 || recentPulses.length > 0),
693
+ sessionId: String(data.sessionId || data.session_id || sessionId),
694
+ userId: String(data.userId || data.user_id || limits.userId || ''),
695
+ query,
696
+ contextBlock,
697
+ memoryCount: recentPulses.length,
698
+ threadCount: activeThreads.length,
699
+ pulseCount: recentPulses.length,
700
+ snapshotMs: Number(data.snapshotMs || data.snapshot_ms || Date.now()),
701
+ postgresBound: Boolean(data.postgresBound ?? data.postgres_bound),
702
+ qdrantBound: Boolean(data.qdrantBound ?? data.qdrant_bound),
703
+ pulseLoopAlive: Boolean(data.pulseLoopAlive ?? data.pulse_loop_alive),
704
+ };
705
+ }
706
+ if (![404, 405, 501].includes(res.status)) {
707
+ throw new Error(`garden continuity failed: ${res.status} ${res.statusText}`);
708
+ }
709
+ }
710
+ const params = new URLSearchParams({
711
+ session_id: sessionId,
712
+ query,
713
+ thread_limit: String(limits.threadLimit ?? 5),
714
+ pulse_limit: String(limits.pulseLimit ?? 12),
715
+ });
716
+ const res = await this.fetchWithRetry(`${this.baseUrl}/api/garden/living?${params}`, {
717
+ method: 'GET',
718
+ headers: {
719
+ Authorization: `Bearer ${this.apiKey}`,
720
+ 'Content-Type': 'application/json',
721
+ },
722
+ });
723
+ if (!res.ok) {
724
+ throw new Error(`garden/living failed: ${res.status} ${res.statusText}`);
725
+ }
726
+ const data = (await res.json());
727
+ const activeThreads = Array.isArray(data.activeThreads) ? data.activeThreads : [];
728
+ const recentPulses = Array.isArray(data.recentPulses) ? data.recentPulses : Array.isArray(data.pulses) ? data.pulses : [];
729
+ const contextBlock = String(data.gardenContextBlock || data.garden_context_block || data.contextBlock || '');
730
+ return {
731
+ hydrated: contextBlock.length > 0 || activeThreads.length > 0 || recentPulses.length > 0,
732
+ sessionId,
733
+ userId: limits.userId,
734
+ query,
735
+ contextBlock,
736
+ memoryCount: recentPulses.length,
737
+ threadCount: activeThreads.length,
738
+ pulseCount: recentPulses.length,
739
+ snapshotMs: Number(data.snapshotMs || data.snapshot_ms || Date.now()),
740
+ };
741
+ }
742
+ async persistGovernanceOutcome(input) {
743
+ if (!input.sessionId || !input.sourceRuntime || !input.outcome) {
744
+ throw new Error('persistGovernanceOutcome requires sessionId, sourceRuntime, and outcome');
745
+ }
746
+ const body = {
747
+ session_id: input.sessionId,
748
+ user_id: input.userId,
749
+ source_runtime: input.sourceRuntime,
750
+ action: input.action || '',
751
+ outcome: input.outcome,
752
+ evidence: input.evidence ?? null,
753
+ obligation_id: input.obligationId || '',
754
+ };
755
+ const targets = this.gardenBaseUrl
756
+ ? [`${this.gardenBaseUrl}/governance-outcome`, `${this.baseUrl}/api/garden/governance-outcome`]
757
+ : [`${this.baseUrl}/api/garden/governance-outcome`];
758
+ let lastStatus = '';
759
+ for (const url of targets) {
760
+ const res = await this.fetchWithRetry(url, {
761
+ method: 'POST',
762
+ headers: {
763
+ Authorization: `Bearer ${this.apiKey}`,
764
+ 'Content-Type': 'application/json',
765
+ },
766
+ body: JSON.stringify(body),
767
+ });
768
+ if (res.ok) {
769
+ const data = (await res.json());
770
+ return {
771
+ ok: Boolean(data.ok),
772
+ pulseId: String(data.pulseId || data.pulse_id || ''),
773
+ ledgerId: String(data.ledgerId || data.ledger_id || ''),
774
+ threadId: String(data.threadId || data.thread_id || ''),
775
+ message: typeof data.message === 'string' ? data.message : undefined,
776
+ };
777
+ }
778
+ lastStatus = `${res.status} ${res.statusText}`;
779
+ if (![404, 405, 501].includes(res.status))
780
+ break;
781
+ }
782
+ throw new Error(`persistGovernanceOutcome failed: ${lastStatus || 'no target available'}`);
783
+ }
646
784
  // ── Consult — delegate to Aria for direction or structured plan ─────────
647
785
  // Routes through /api/harness/delegate (the architect-mode endpoint that
648
786
  // serves preprompt-consult + Aria-as-commander binding plans). Caller
@@ -1572,4 +1710,5 @@ export async function getBoundHarnessAndPrompt(context, plan, client) {
1572
1710
  return sdk.getBoundHarnessAndPrompt(context, plan);
1573
1711
  }
1574
1712
  export * from './runWithCognition.js';
1713
+ export * from './runWithGovernance.js';
1575
1714
  //# sourceMappingURL=index.js.map