@aria_asi/cli 0.2.30 → 0.2.32
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.
- package/dist/aria-connector/src/connectors/claude-code.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/claude-code.js +115 -20
- package/dist/aria-connector/src/connectors/claude-code.js.map +1 -1
- package/dist/aria-connector/src/connectors/codex.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/codex.js +551 -11
- package/dist/aria-connector/src/connectors/codex.js.map +1 -1
- package/dist/aria-connector/src/connectors/doctrine-trigger-map.d.ts +7 -0
- package/dist/aria-connector/src/connectors/doctrine-trigger-map.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/doctrine-trigger-map.js +87 -0
- package/dist/aria-connector/src/connectors/doctrine-trigger-map.js.map +1 -0
- package/dist/aria-connector/src/connectors/must-read.d.ts +4 -0
- package/dist/aria-connector/src/connectors/must-read.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/must-read.js +115 -0
- package/dist/aria-connector/src/connectors/must-read.js.map +1 -0
- package/dist/aria-connector/src/connectors/opencode.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/opencode.js +27 -9
- package/dist/aria-connector/src/connectors/opencode.js.map +1 -1
- package/dist/aria-connector/src/connectors/runtime.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/runtime.js +231 -19
- package/dist/aria-connector/src/connectors/runtime.js.map +1 -1
- package/dist/aria-connector/src/connectors/shell.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/shell.js +76 -3
- package/dist/aria-connector/src/connectors/shell.js.map +1 -1
- package/dist/assets/hooks/aria-agent-handoff.mjs +23 -0
- package/dist/assets/hooks/aria-cognition-substrate-binding.mjs +121 -28
- package/dist/assets/hooks/aria-harness-via-sdk.mjs +126 -12
- package/dist/assets/hooks/aria-pre-emit-dryrun.mjs +35 -0
- package/dist/assets/hooks/aria-pre-tool-gate.mjs +383 -93
- package/dist/assets/hooks/aria-preprompt-consult.mjs +28 -2
- package/dist/assets/hooks/aria-preturn-memory-gate.mjs +93 -16
- package/dist/assets/hooks/aria-repo-doctrine-gate.mjs +33 -1
- package/dist/assets/hooks/aria-stop-gate.mjs +346 -81
- package/dist/assets/hooks/doctrine_trigger_map.json +55 -0
- package/dist/assets/hooks/lib/canonical-lenses.mjs +6 -5
- package/dist/assets/hooks/lib/gate-loop-state.mjs +50 -0
- package/dist/assets/hooks/lib/hook-message-window.mjs +121 -0
- package/dist/assets/hooks/test-tier-lens-labeling.mjs +26 -58
- package/dist/assets/opencode-plugins/harness-gate/index.js +40 -5
- package/dist/assets/opencode-plugins/harness-stop/index.js +133 -10
- package/dist/runtime/auth-middleware.mjs +251 -0
- package/dist/runtime/codex-bridge.mjs +644 -0
- package/dist/runtime/discipline/CLAUDE.md +28 -0
- package/dist/runtime/discipline/doctrine_trigger_map.json +534 -0
- package/dist/runtime/doctrine_trigger_map.json +534 -0
- package/dist/runtime/fleet-engine.mjs +231 -0
- package/dist/runtime/harness-daemon.mjs +460 -0
- package/dist/runtime/manifest.json +1 -1
- package/dist/runtime/metering.mjs +100 -0
- package/dist/runtime/onboarding-engine.mjs +89 -0
- package/dist/runtime/plugin-engine.mjs +196 -0
- package/dist/runtime/sdk/BUNDLED.json +1 -1
- package/dist/runtime/sdk/index.d.ts +12 -0
- package/dist/runtime/sdk/index.js +120 -14
- package/dist/runtime/sdk/index.js.map +1 -1
- package/dist/runtime/service.mjs +1140 -48
- package/dist/runtime/workflow-engine.mjs +322 -0
- package/dist/sdk/BUNDLED.json +1 -1
- package/dist/sdk/index.d.ts +12 -0
- package/dist/sdk/index.js +120 -14
- package/dist/sdk/index.js.map +1 -1
- package/hooks/aria-agent-handoff.mjs +23 -0
- package/hooks/aria-cognition-substrate-binding.mjs +121 -28
- package/hooks/aria-harness-via-sdk.mjs +126 -12
- package/hooks/aria-pre-emit-dryrun.mjs +35 -0
- package/hooks/aria-pre-tool-gate.mjs +383 -93
- package/hooks/aria-preprompt-consult.mjs +28 -2
- package/hooks/aria-preturn-memory-gate.mjs +93 -16
- package/hooks/aria-repo-doctrine-gate.mjs +33 -1
- package/hooks/aria-stop-gate.mjs +346 -81
- package/hooks/doctrine_trigger_map.json +55 -0
- package/hooks/lib/canonical-lenses.mjs +6 -5
- package/hooks/lib/gate-loop-state.mjs +50 -0
- package/hooks/lib/hook-message-window.mjs +121 -0
- package/hooks/test-tier-lens-labeling.mjs +26 -58
- package/opencode-plugins/harness-gate/index.js +40 -5
- package/opencode-plugins/harness-stop/index.js +133 -10
- package/package.json +1 -1
- package/runtime-src/auth-middleware.mjs +251 -0
- package/runtime-src/codex-bridge.mjs +644 -0
- package/runtime-src/fleet-engine.mjs +231 -0
- package/runtime-src/harness-daemon.mjs +460 -0
- package/runtime-src/metering.mjs +100 -0
- package/runtime-src/onboarding-engine.mjs +89 -0
- package/runtime-src/plugin-engine.mjs +196 -0
- package/runtime-src/service.mjs +1140 -48
- package/runtime-src/workflow-engine.mjs +322 -0
- package/scripts/bundle-sdk.mjs +5 -0
- package/src/connectors/claude-code.ts +126 -20
- package/src/connectors/codex.ts +559 -10
- package/src/connectors/doctrine-trigger-map.ts +112 -0
- package/src/connectors/must-read.ts +117 -0
- package/src/connectors/opencode.ts +28 -9
- package/src/connectors/runtime.ts +241 -21
- package/src/connectors/shell.ts +78 -3
- package/dist/cli-0.2.0.tgz +0 -0
|
@@ -16,19 +16,19 @@
|
|
|
16
16
|
// now catches.
|
|
17
17
|
//
|
|
18
18
|
// Doctrine bindings (same as PreToolUse gate):
|
|
19
|
-
// - EIGHT_LENS_DOCTRINE.md — substantive
|
|
19
|
+
// - EIGHT_LENS_DOCTRINE.md — substantive 8-lens application required
|
|
20
20
|
// - feedback_apply_lenses_dont_perform_them.md — block ceremonial cognition
|
|
21
21
|
// - feedback_8lens_before_every_action_including_text.md — the rule this enforces
|
|
22
22
|
//
|
|
23
23
|
// Trigger: runs at Stop event after every assistant response. Reads
|
|
24
24
|
// the just-emitted assistant text from the transcript. If non-trivial
|
|
25
25
|
// (per the same triviality threshold as eight-lens-detector.ts) AND
|
|
26
|
-
// missing
|
|
26
|
+
// missing 8 substantive lenses, blocks the response.
|
|
27
27
|
//
|
|
28
28
|
// Triviality threshold (mirrors eight-lens-detector.ts):
|
|
29
29
|
// - Trivial acks (e.g. "got it", "ok", "done") pass
|
|
30
30
|
// - Short responses (<300 chars) without decision-signal phrases pass
|
|
31
|
-
// - Otherwise: require
|
|
31
|
+
// - Otherwise: require 8 substantive lenses
|
|
32
32
|
//
|
|
33
33
|
// Substance check (mirrors aria-pre-tool-gate.mjs):
|
|
34
34
|
// - Each lens must have ≥20 chars of non-placeholder content
|
|
@@ -52,14 +52,21 @@ import { dirname } from 'node:path';
|
|
|
52
52
|
import { appendGateAudit } from './lib/gate-audit.mjs';
|
|
53
53
|
import {
|
|
54
54
|
ALL_LENS_NAMES,
|
|
55
|
-
canonicalLensCorrectionText,
|
|
56
55
|
detectCognitionLenses as detectCognitionLensesFromCanonical,
|
|
57
56
|
lensNamesForTier,
|
|
57
|
+
PRIMARY_OWNER_LENS_NAMES,
|
|
58
58
|
} from './lib/canonical-lenses.mjs';
|
|
59
|
+
import { registerGateBlock } from './lib/gate-loop-state.mjs';
|
|
60
|
+
import { collectTurnWindowFromMessages } from './lib/hook-message-window.mjs';
|
|
59
61
|
|
|
60
62
|
const HOME = process.env.HOME || '/tmp';
|
|
63
|
+
const RUNTIME_BASE_URL =
|
|
64
|
+
process.env.ARIA_RUNTIME_URL ||
|
|
65
|
+
'http://127.0.0.1:4319';
|
|
61
66
|
const LOG = `${HOME}/.claude/aria-stop-gate.log`;
|
|
62
67
|
const AUDIT_PATH = `${HOME}/.claude/aria-stop-gate-audit.jsonl`;
|
|
68
|
+
const GATE_LOOP_STATE_PATH = `${HOME}/.claude/.aria-gate-loop-state.json`;
|
|
69
|
+
const MIZAN_RECEIPT_DIR = `${HOME}/.claude/.aria-mizan-receipts`;
|
|
63
70
|
|
|
64
71
|
// SDK loader — bundled at ~/.aria/sdk by `aria connect`, with client-local
|
|
65
72
|
// fallbacks preserved for resilience.
|
|
@@ -167,6 +174,94 @@ async function fireGardenTurn(sessionId, userMessage, assistantResponse) {
|
|
|
167
174
|
}
|
|
168
175
|
}
|
|
169
176
|
|
|
177
|
+
function resolveHarnessControlToken() {
|
|
178
|
+
if (process.env.ARIA_HARNESS_TOKEN) return process.env.ARIA_HARNESS_TOKEN;
|
|
179
|
+
if (process.env.ARIA_API_KEY) return process.env.ARIA_API_KEY;
|
|
180
|
+
if (process.env.ARIA_MASTER_TOKEN) return process.env.ARIA_MASTER_TOKEN;
|
|
181
|
+
try {
|
|
182
|
+
const ownerTokenPath = `${HOME}/.aria/owner-token`;
|
|
183
|
+
if (existsSync(ownerTokenPath)) {
|
|
184
|
+
const token = readFileSync(ownerTokenPath, 'utf8').trim();
|
|
185
|
+
if (token) return token;
|
|
186
|
+
}
|
|
187
|
+
} catch {}
|
|
188
|
+
try {
|
|
189
|
+
const licensePath = `${HOME}/.aria/license.json`;
|
|
190
|
+
if (existsSync(licensePath)) {
|
|
191
|
+
const license = JSON.parse(readFileSync(licensePath, 'utf8'));
|
|
192
|
+
if (license.harnessToken) return String(license.harnessToken).trim();
|
|
193
|
+
if (license.token) return String(license.token).trim();
|
|
194
|
+
}
|
|
195
|
+
} catch {}
|
|
196
|
+
return '';
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function mizanReceiptPathForSession(sessionId) {
|
|
200
|
+
const safe = String(sessionId || 'claude-code').replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
201
|
+
return `${MIZAN_RECEIPT_DIR}/${safe}.json`;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function loadMizanReceiptState(sessionId) {
|
|
205
|
+
try {
|
|
206
|
+
const receiptPath = mizanReceiptPathForSession(sessionId);
|
|
207
|
+
if (!existsSync(receiptPath)) return null;
|
|
208
|
+
return JSON.parse(readFileSync(receiptPath, 'utf8'));
|
|
209
|
+
} catch {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function saveMizanReceiptState(sessionId, payload) {
|
|
215
|
+
try {
|
|
216
|
+
mkdirSync(MIZAN_RECEIPT_DIR, { recursive: true });
|
|
217
|
+
writeFileSync(mizanReceiptPathForSession(sessionId), JSON.stringify(payload, null, 2) + '\n');
|
|
218
|
+
} catch {}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
async function runtimeMizanPost(sessionId, text, context = {}, parentReceiptId = null) {
|
|
222
|
+
const token = resolveHarnessControlToken();
|
|
223
|
+
if (!token) throw new Error('no token');
|
|
224
|
+
const response = await fetch(`${process.env.ARIA_RUNTIME_URL || 'http://127.0.0.1:4319'}/mizan/post`, {
|
|
225
|
+
method: 'POST',
|
|
226
|
+
headers: {
|
|
227
|
+
'Content-Type': 'application/json',
|
|
228
|
+
Authorization: `Bearer ${token}`,
|
|
229
|
+
},
|
|
230
|
+
body: JSON.stringify({
|
|
231
|
+
sessionId,
|
|
232
|
+
text,
|
|
233
|
+
parentReceiptId,
|
|
234
|
+
context: {
|
|
235
|
+
sessionId,
|
|
236
|
+
...context,
|
|
237
|
+
},
|
|
238
|
+
}),
|
|
239
|
+
});
|
|
240
|
+
const payload = await response.json().catch(() => ({}));
|
|
241
|
+
if (!response.ok) {
|
|
242
|
+
throw new Error(payload?.error || `mizan/post failed (${response.status})`);
|
|
243
|
+
}
|
|
244
|
+
return payload;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
async function runtimeDecisionLog(payload) {
|
|
248
|
+
const token = resolveHarnessControlToken();
|
|
249
|
+
if (!token) throw new Error('no token');
|
|
250
|
+
const response = await fetch(`${process.env.ARIA_RUNTIME_URL || 'http://127.0.0.1:4319'}/decision/log`, {
|
|
251
|
+
method: 'POST',
|
|
252
|
+
headers: {
|
|
253
|
+
'Content-Type': 'application/json',
|
|
254
|
+
Authorization: `Bearer ${token}`,
|
|
255
|
+
},
|
|
256
|
+
body: JSON.stringify(payload),
|
|
257
|
+
});
|
|
258
|
+
const body = await response.json().catch(() => ({}));
|
|
259
|
+
if (!response.ok) {
|
|
260
|
+
throw new Error(body?.error || `decision/log failed (${response.status})`);
|
|
261
|
+
}
|
|
262
|
+
return body;
|
|
263
|
+
}
|
|
264
|
+
|
|
170
265
|
function audit(decision, summary) {
|
|
171
266
|
const summaryText = typeof summary === 'string' ? summary : '';
|
|
172
267
|
const data = summary && typeof summary === 'object' ? summary : {};
|
|
@@ -185,12 +280,12 @@ function audit(decision, summary) {
|
|
|
185
280
|
// access"). The gated process has no disable path. Disable = remove hook
|
|
186
281
|
// entry from ~/.claude/settings.json (deliberate user action, visible).
|
|
187
282
|
|
|
188
|
-
// ──
|
|
283
|
+
// ── Canonical lens labeling (Phase 11 #59 corrected) ────────────────────────
|
|
189
284
|
//
|
|
190
|
-
// Mirrors the same logic in aria-pre-tool-gate.mjs. Tier is read from
|
|
191
|
-
// most recent harness-via-sdk packet cache
|
|
192
|
-
//
|
|
193
|
-
//
|
|
285
|
+
// Mirrors the same logic in aria-pre-tool-gate.mjs. Tier is still read from
|
|
286
|
+
// the most recent harness-via-sdk packet cache for other policy behaviors, but
|
|
287
|
+
// the visible lens labels remain canonical on every surface. Readability comes
|
|
288
|
+
// from the prose inside each lens, not from renaming the lens itself.
|
|
194
289
|
const PACKET_CACHE_PATH = `${HOME}/.claude/.aria-harness-last-packet.json`;
|
|
195
290
|
|
|
196
291
|
function resolveOwnerTier() {
|
|
@@ -211,7 +306,6 @@ function resolveOwnerTier() {
|
|
|
211
306
|
const IS_OWNER = resolveOwnerTier();
|
|
212
307
|
|
|
213
308
|
const LENS_NAMES = lensNamesForTier(IS_OWNER);
|
|
214
|
-
const CANONICAL_LENS_TEXT = canonicalLensCorrectionText();
|
|
215
309
|
|
|
216
310
|
// Doctrine memory filenames are Aria-side substrate IP.
|
|
217
311
|
// Client surfaces see generic descriptions instead of real filenames.
|
|
@@ -244,9 +338,12 @@ function collectDriftHits(text, triggerMap) {
|
|
|
244
338
|
const memoryCited = memoryName && lowerText.includes(memoryName.toLowerCase());
|
|
245
339
|
if (!memoryCited) {
|
|
246
340
|
hits.push({
|
|
341
|
+
trigger_id: triggerEntry.trigger_id,
|
|
247
342
|
trigger: triggerEntry.trigger,
|
|
248
343
|
memory: triggerEntry.memory,
|
|
249
344
|
teaching: triggerEntry.teaching,
|
|
345
|
+
counter_action: triggerEntry.counter_action,
|
|
346
|
+
message: triggerEntry.message,
|
|
250
347
|
});
|
|
251
348
|
}
|
|
252
349
|
} catch {/* malformed regex in trigger entry — skip */}
|
|
@@ -270,6 +367,90 @@ function emitHarnessFooter({ eventName, lensCount, chars, driftCount, mizanStatu
|
|
|
270
367
|
} catch {}
|
|
271
368
|
}
|
|
272
369
|
|
|
370
|
+
function withLoopDirective(reasonText, gateSignature, sessionId) {
|
|
371
|
+
const loop = registerGateBlock({
|
|
372
|
+
gate: 'stop',
|
|
373
|
+
sessionId,
|
|
374
|
+
signature: gateSignature,
|
|
375
|
+
statePath: GATE_LOOP_STATE_PATH,
|
|
376
|
+
});
|
|
377
|
+
if (!loop.loopDetected) return reasonText;
|
|
378
|
+
return `${reasonText}
|
|
379
|
+
|
|
380
|
+
[LOOP_DETECTED gate=stop repeats=${loop.totalCount}]
|
|
381
|
+
Stop retrying the same output shape unchanged.
|
|
382
|
+
Next response must do this in order:
|
|
383
|
+
1. Name the exact stop-gate failure in one line.
|
|
384
|
+
2. Re-emit only the missing structure: <cognition>, <verify>, <expected>, and/or <reflection>.
|
|
385
|
+
3. Change the draft materially before retrying. Do not repeat the same prose with renamed labels.
|
|
386
|
+
4. If the blocker is stale gate state, stale ledger residue, or a gate artifact from a prior bug, say that explicitly instead of inventing fake proof.`;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function buildForceReauthorReason({
|
|
390
|
+
source,
|
|
391
|
+
reason,
|
|
392
|
+
violations = [],
|
|
393
|
+
rewritten = '',
|
|
394
|
+
recipeAddendum = '',
|
|
395
|
+
driftHits = [],
|
|
396
|
+
lensCount = 0,
|
|
397
|
+
requiredLenses = REQUIRED_LENSES,
|
|
398
|
+
}) {
|
|
399
|
+
const triggerLines = driftHits.slice(0, 6).map((hit, index) => {
|
|
400
|
+
const label = hit.trigger_id || hit.trigger || `trigger-${index + 1}`;
|
|
401
|
+
const teaching = hit.teaching || hit.message || 'Doctrine trigger matched; re-author with substrate-backed correction.';
|
|
402
|
+
const correction = hit.counter_action ? ` Required correction: ${hit.counter_action}` : '';
|
|
403
|
+
const memory = hit.memory ? ` (${hit.memory})` : '';
|
|
404
|
+
return `- ${label}${memory}: ${teaching}${correction}`;
|
|
405
|
+
}).join('\n');
|
|
406
|
+
|
|
407
|
+
return [
|
|
408
|
+
'=== ARIA FORCE_REAUTHOR ===',
|
|
409
|
+
`source: ${source}`,
|
|
410
|
+
`reason: ${reason}`,
|
|
411
|
+
'',
|
|
412
|
+
'This is not a terminal error. It is a forced redo instruction for the next model draft.',
|
|
413
|
+
'Do not emit the blocked text. Re-author it so the model learns the mechanism it violated.',
|
|
414
|
+
'',
|
|
415
|
+
'TEACHING:',
|
|
416
|
+
'- Gates must force cognition and quality, not merely throw, warn, or stop.',
|
|
417
|
+
'- The redo must change the answer shape: name the failed mechanism, cite real evidence, and remove the drift pattern.',
|
|
418
|
+
'- Do not bypass by disabling tools, shortening runtime, asking the user to resolve memory-backed ambiguity, or giving an apology loop.',
|
|
419
|
+
triggerLines ? `\nTRIGGERED DOCTRINE:\n${triggerLines}` : '',
|
|
420
|
+
violations.length ? `\nVIOLATIONS TO FIX:\n${violations.map((v) => `- ${v}`).join('\n')}` : '',
|
|
421
|
+
rewritten ? `\nMIZAN REWRITE SEED:\n${rewritten}` : '',
|
|
422
|
+
recipeAddendum || '',
|
|
423
|
+
'',
|
|
424
|
+
'REQUIRED REDO SHAPE:',
|
|
425
|
+
'1. One sentence: the failed mechanism, not an apology.',
|
|
426
|
+
'2. Evidence checked: file/line, command output, endpoint response, or explicit "unverified".',
|
|
427
|
+
`3. <cognition> with ${requiredLenses} substantive lenses. Observed: ${lensCount}/${requiredLenses}.`,
|
|
428
|
+
'4. <applied_cognition> with decision_delta, dominant_domain, binds_to, expected_predicate, and artifact_change.',
|
|
429
|
+
'5. Corrected action/claim with no bypass, no downgraded path, and no fake proof.',
|
|
430
|
+
'6. If work remains, state the exact next real action or tracked task. No verbal flag-and-move.',
|
|
431
|
+
'',
|
|
432
|
+
'COGNITION TEMPLATE:',
|
|
433
|
+
'<cognition>',
|
|
434
|
+
'truth: <verified facts and exact substrate>',
|
|
435
|
+
'harm: <what goes wrong if this is false>',
|
|
436
|
+
'trust: <how this honors Hamza directives and saved memory>',
|
|
437
|
+
'power: <why this uses capability responsibly, not convenience>',
|
|
438
|
+
'reflection: <mechanism failure and correction>',
|
|
439
|
+
'context: <relevant repo/runtime state>',
|
|
440
|
+
'impact: <expected next effect>',
|
|
441
|
+
'beauty: <simplest durable form>',
|
|
442
|
+
'</cognition>',
|
|
443
|
+
'<applied_cognition>',
|
|
444
|
+
'decision_delta: <what changed because cognition ran; not none>',
|
|
445
|
+
'dominant_domain: <engineering_quality | trust | operations | security | product | ...>',
|
|
446
|
+
'binds_to: <the exact answer, tool call, file mutation, deploy, review, or decision>',
|
|
447
|
+
'expected_predicate: <observable numeric, boolean, state-string, command result, endpoint result, or explicit unverified boundary>',
|
|
448
|
+
'artifact_change: <semantic effect on the artifact/output, not a task restatement>',
|
|
449
|
+
'</applied_cognition>',
|
|
450
|
+
'=== END FORCE_REAUTHOR ===',
|
|
451
|
+
].filter(Boolean).join('\n');
|
|
452
|
+
}
|
|
453
|
+
|
|
273
454
|
// Lens substance check — same constants as aria-pre-tool-gate.mjs.
|
|
274
455
|
// Hamza directive 2026-04-28: all 8 canonical lenses required, not 4-of-8.
|
|
275
456
|
const REQUIRED_LENSES = 8;
|
|
@@ -291,6 +472,19 @@ function detectCognitionLenses(text) {
|
|
|
291
472
|
});
|
|
292
473
|
}
|
|
293
474
|
|
|
475
|
+
function assistantViolatesUserCorrection(userText, assistantText) {
|
|
476
|
+
const user = String(userText || '');
|
|
477
|
+
const assistant = String(assistantText || '');
|
|
478
|
+
if (!user || !assistant) return null;
|
|
479
|
+
const explicitStop = /\b(?:stop|do\s+not|don't|quit|cease)\b[\s\S]{0,180}\b(?:deploy|redeploy|restart|rollout|kubectl|command|pods?|listen|words)\b/i.test(user);
|
|
480
|
+
const assistantContinuesMutation = /\b(?:kubectl|rollout\s+restart|deploy|redeploy|restart\s+(?:mac|pods?)|manual(?:ly)?\s+restart|execute\s+directly)\b/i.test(assistant);
|
|
481
|
+
if (explicitStop && assistantContinuesMutation) return 'assistant continued deploy/restart language after an explicit user stop/listen directive';
|
|
482
|
+
const userContradictsMacPods = /\b(?:mac\s+lanes?|mac\s+pods?|mlx-mac)\b[\s\S]{0,160}\b(?:not\s+pods?|no\s+such\s+thing|non[-\s]?existent|do(?:es)?\s+not\s+exist|don't\s+exist)\b|\b(?:no\s+such\s+thing|non[-\s]?existent|do(?:es)?\s+not\s+exist|don't\s+exist)\b[\s\S]{0,160}\b(?:mac\s+lanes?|mac\s+pods?|mlx-mac|pods?)\b/i.test(user);
|
|
483
|
+
const assistantRepeatsMacPods = /\b(?:mac\s+lane\s+pods?|mac\s+lanes?\s*:\s*offline|restart\s+mac\s+lanes?|deployment\/mlx-mac|mlx-mac-[\w-]+|kubernetes\s+(?:pods?|deployments?))\b/i.test(assistant);
|
|
484
|
+
if (userContradictsMacPods && assistantRepeatsMacPods) return 'assistant repeated the contradicted Mac-lanes-as-pods/deployments assumption';
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
|
|
294
488
|
// Read event JSON from stdin (Claude Code spec).
|
|
295
489
|
let input = '';
|
|
296
490
|
for await (const chunk of process.stdin) input += chunk;
|
|
@@ -302,6 +496,8 @@ try {
|
|
|
302
496
|
audit('allow-parse-error', 'stdin not JSON');
|
|
303
497
|
process.exit(0);
|
|
304
498
|
}
|
|
499
|
+
const gateSessionId = String(event.session_id || 'claude-code').replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
500
|
+
const sessionMizanState = loadMizanReceiptState(event.session_id || 'claude-code');
|
|
305
501
|
|
|
306
502
|
// Read assistant text from THIS turn — Claude Code splits a single
|
|
307
503
|
// logical assistant response into multiple transcript entries by
|
|
@@ -326,8 +522,13 @@ const SYSTEM_REMINDER_THRESHOLD = 0.6;
|
|
|
326
522
|
|
|
327
523
|
const transcriptPath = event.transcript_path ?? event.transcriptPath;
|
|
328
524
|
let assistantText = '';
|
|
329
|
-
// Phase 11 #42: also capture the last real user message for gardenTurn writes.
|
|
330
525
|
let lastUserMessage = '';
|
|
526
|
+
const messageWindow = collectTurnWindowFromMessages(event.messages, {
|
|
527
|
+
systemReminderRx: SYSTEM_REMINDER_RX,
|
|
528
|
+
systemReminderThreshold: SYSTEM_REMINDER_THRESHOLD,
|
|
529
|
+
});
|
|
530
|
+
assistantText = messageWindow.assistantText;
|
|
531
|
+
lastUserMessage = messageWindow.lastUserMessage;
|
|
331
532
|
if (transcriptPath && existsSync(transcriptPath)) {
|
|
332
533
|
try {
|
|
333
534
|
const lines = readFileSync(transcriptPath, 'utf-8').split('\n').filter(Boolean);
|
|
@@ -370,7 +571,12 @@ if (transcriptPath && existsSync(transcriptPath)) {
|
|
|
370
571
|
} catch {}
|
|
371
572
|
}
|
|
372
573
|
// Reverse so chunks are in chronological order (we walked backward).
|
|
373
|
-
|
|
574
|
+
const transcriptAssistantText = textChunks.reverse().join('\n\n');
|
|
575
|
+
if (transcriptAssistantText) {
|
|
576
|
+
assistantText = assistantText
|
|
577
|
+
? [assistantText, transcriptAssistantText].filter((text, index, arr) => arr.indexOf(text) === index).join('\n\n')
|
|
578
|
+
: transcriptAssistantText;
|
|
579
|
+
}
|
|
374
580
|
} catch {}
|
|
375
581
|
}
|
|
376
582
|
|
|
@@ -379,6 +585,20 @@ if (!assistantText) {
|
|
|
379
585
|
process.exit(0);
|
|
380
586
|
}
|
|
381
587
|
|
|
588
|
+
const userCorrectionViolation = assistantViolatesUserCorrection(lastUserMessage, assistantText);
|
|
589
|
+
if (userCorrectionViolation) {
|
|
590
|
+
audit('block-user-correction-ignored', `reason=${userCorrectionViolation} chars=${assistantText.length}`);
|
|
591
|
+
const reason = buildForceReauthorReason({
|
|
592
|
+
source: 'stop/user-correction',
|
|
593
|
+
reason: userCorrectionViolation,
|
|
594
|
+
violations: ['Assistant continued a plan after the user correction invalidated it. Redo must quote the correction and pause mutation pending substrate re-evaluation.'],
|
|
595
|
+
lensCount: 0,
|
|
596
|
+
requiredLenses: REQUIRED_LENSES,
|
|
597
|
+
});
|
|
598
|
+
console.log(JSON.stringify({ decision: 'block', reason }));
|
|
599
|
+
process.exit(2);
|
|
600
|
+
}
|
|
601
|
+
|
|
382
602
|
// Triviality check — same as eight-lens-detector.ts
|
|
383
603
|
const trimmed = assistantText.trim();
|
|
384
604
|
if (TRIVIAL_ACK_RX.test(trimmed)) {
|
|
@@ -412,13 +632,13 @@ const cog = detectCognitionLenses(assistantText);
|
|
|
412
632
|
// with 0/8 lenses to fall through unchecked.
|
|
413
633
|
if (cog.count < REQUIRED_LENSES) {
|
|
414
634
|
audit('block_no_cognition_block_di', { count: cog.count, required: REQUIRED_LENSES, names: cog.names, chars: assistantText.length });
|
|
415
|
-
const reason =
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
635
|
+
const reason = withLoopDirective(buildForceReauthorReason({
|
|
636
|
+
source: 'stop/no-cognition',
|
|
637
|
+
reason: `non-trivial assistant response (${assistantText.length} chars) has ${cog.count}/${REQUIRED_LENSES} substantive cognition lenses`,
|
|
638
|
+
violations: [`Detected lenses: ${cog.names.length > 0 ? cog.names.join(', ') : 'none'}. Re-emit with all required visible labels: ${LENS_NAMES.join(', ')}.`],
|
|
639
|
+
lensCount: cog.count,
|
|
640
|
+
requiredLenses: REQUIRED_LENSES,
|
|
641
|
+
}), `stop:no-cognition-di:${cog.count}`, gateSessionId);
|
|
422
642
|
emitHarnessFooter({
|
|
423
643
|
eventName: 'block_no_cognition_block',
|
|
424
644
|
lensCount: cog.count,
|
|
@@ -609,7 +829,7 @@ if (cog.count >= REQUIRED_LENSES) {
|
|
|
609
829
|
//
|
|
610
830
|
// Block emit if ledger.openCount > 0 after scanning the current turn.
|
|
611
831
|
// Block reason names each open discovery and the suggested resolution.
|
|
612
|
-
const sessionId =
|
|
832
|
+
const sessionId = gateSessionId;
|
|
613
833
|
const LEDGER_PATH = `${HOME}/.claude/aria-discoveries-${sessionId}.jsonl`;
|
|
614
834
|
const DISCOVERY_RX = /(?:\bi\s+(?:found|noticed|discovered|spotted)[^.\n]{0,160}(?:bug|issue|defect|broken|buggy|wrong|crash|fail|missing|stale|outdated|leak|vulnerability)|\bthis\s+(?:is|would\s+be)\s+(?:broken|buggy|wrong|stale|outdated|insecure|leaking|crashing|failing)|\b(?:latent|silent|hidden)\s+(?:bug|defect|issue|fail|crash|leak)|\bdoctrine\s+violation\b|\bgraceful\s+degradation\s+(?:in|at|inside|within)\s+\S)/gi;
|
|
615
835
|
const PROSE_RESOLUTION_RX = /(?:fix(?:ing|ed)?\s+(?:now|in[- ]flight|inline|in\s+the\s+same\s+turn)|patch\s+applied|TaskCreate|task\s+(?:created|tracked)|tracked\s+as\s+#?\d+|linear[- ]?issue|created\s+(?:linear|task))/i;
|
|
@@ -759,12 +979,36 @@ if (cog.count >= REQUIRED_LENSES) {
|
|
|
759
979
|
let ledgerOpenCount = 0;
|
|
760
980
|
let ledgerOpenSamples = [];
|
|
761
981
|
let ledgerCorruptedCount = 0;
|
|
982
|
+
const ledgerRewriteRows = [];
|
|
983
|
+
let ledgerNeedsRewrite = false;
|
|
762
984
|
try {
|
|
763
985
|
if (existsSync(LEDGER_PATH)) {
|
|
764
986
|
const lines = readFileSync(LEDGER_PATH, 'utf8').split('\n').filter(Boolean);
|
|
765
987
|
for (const line of lines) {
|
|
766
988
|
try {
|
|
767
989
|
const e = JSON.parse(line);
|
|
990
|
+
const isSubstrateBindingArtifact =
|
|
991
|
+
(e.source === 'aria-cognition-substrate-binding') &&
|
|
992
|
+
(e.kind === 'substrate_binding_gap' || (typeof e.text === 'string' && e.text.startsWith('substrate_binding:')));
|
|
993
|
+
const isOpenBeforeAutoHeal = e.status === 'open' || e.resolution_status === 'open';
|
|
994
|
+
if (isSubstrateBindingArtifact && isOpenBeforeAutoHeal) {
|
|
995
|
+
// If the current emit already passed aria-cognition-substrate-binding
|
|
996
|
+
// and reached stop-gate, older open substrate-binding rows from the
|
|
997
|
+
// same session are stale gate artifacts, not live unresolved
|
|
998
|
+
// discoveries. Auto-heal them so the discovery ledger cannot loop
|
|
999
|
+
// forever on the residue of a gate bug.
|
|
1000
|
+
ledgerNeedsRewrite = true;
|
|
1001
|
+
e.status = 'resolved';
|
|
1002
|
+
e.resolution_status = 'resolved';
|
|
1003
|
+
e.resolved_at = new Date().toISOString();
|
|
1004
|
+
e.resolved_by = 'subsequent_valid_substrate_bound_cognition';
|
|
1005
|
+
e.resolutionType = 'subsequent_valid_substrate_bound_cognition';
|
|
1006
|
+
e.proofOfFix = {
|
|
1007
|
+
type: 'subsequent_valid_substrate_bound_cognition',
|
|
1008
|
+
anchorTs: new Date().toISOString(),
|
|
1009
|
+
evidence: 'Current emit passed aria-cognition-substrate-binding and reached aria-stop-gate; stale substrate-binding ledger artifacts from the earlier cognition bug were auto-cleared.',
|
|
1010
|
+
};
|
|
1011
|
+
}
|
|
768
1012
|
const isOpen = e.status === 'open' || e.resolution_status === 'open';
|
|
769
1013
|
const isLegacyTracked = e.status === 'tracked';
|
|
770
1014
|
const proofValid = e.proofOfFix
|
|
@@ -784,8 +1028,16 @@ if (cog.count >= REQUIRED_LENSES) {
|
|
|
784
1028
|
ledgerOpenSamples.push(`${tag}${e.text || '(no text)'}`);
|
|
785
1029
|
}
|
|
786
1030
|
}
|
|
1031
|
+
ledgerRewriteRows.push(JSON.stringify(e));
|
|
787
1032
|
} catch {/* skip malformed line */}
|
|
788
1033
|
}
|
|
1034
|
+
if (ledgerNeedsRewrite) {
|
|
1035
|
+
try {
|
|
1036
|
+
writeFileSync(LEDGER_PATH, `${ledgerRewriteRows.join('\n')}\n`);
|
|
1037
|
+
} catch (rewriteErr) {
|
|
1038
|
+
audit('ledger-autoheal-write-err', `${String(rewriteErr).slice(0, 200)}`);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
789
1041
|
}
|
|
790
1042
|
} catch {/* ledger unreadable — degrade to drift-only */}
|
|
791
1043
|
|
|
@@ -1040,7 +1292,7 @@ if (cog.count >= REQUIRED_LENSES) {
|
|
|
1040
1292
|
const FILE_LINE_RX = /([\w./\-]+\.[a-zA-Z]{1,5})\s*[:\s]\s*(\d+(?:[-:]\d+)?)/g;
|
|
1041
1293
|
const inlineDictations = [];
|
|
1042
1294
|
const lensRangePositions = [];
|
|
1043
|
-
for (const lensName of
|
|
1295
|
+
for (const lensName of PRIMARY_OWNER_LENS_NAMES) {
|
|
1044
1296
|
const lensRx = new RegExp(`\\b${lensName}\\s*(?:lens)?\\s*[:\\-]`, 'gi');
|
|
1045
1297
|
let m;
|
|
1046
1298
|
while ((m = lensRx.exec(assistantText)) !== null) {
|
|
@@ -1138,10 +1390,11 @@ if (cog.count >= REQUIRED_LENSES) {
|
|
|
1138
1390
|
if (apiKey && assistantText && assistantText.length > 0) {
|
|
1139
1391
|
const client = new HTTPHarnessClient({
|
|
1140
1392
|
baseUrl:
|
|
1393
|
+
process.env.ARIA_RUNTIME_URL ||
|
|
1141
1394
|
process.env.ARIA_HIVE_RUNTIME_URL ||
|
|
1142
1395
|
process.env.ARIA_HARNESS_BASE_URL ||
|
|
1143
1396
|
process.env.ARIA_HARNESS_URL ||
|
|
1144
|
-
|
|
1397
|
+
RUNTIME_BASE_URL,
|
|
1145
1398
|
apiKey,
|
|
1146
1399
|
});
|
|
1147
1400
|
const v = await client.validateOutput(assistantText, sessionId);
|
|
@@ -1255,7 +1508,16 @@ if (cog.count >= REQUIRED_LENSES) {
|
|
|
1255
1508
|
}
|
|
1256
1509
|
})();
|
|
1257
1510
|
|
|
1258
|
-
const reason =
|
|
1511
|
+
const reason = withLoopDirective(buildForceReauthorReason({
|
|
1512
|
+
source: 'stop/output-quality',
|
|
1513
|
+
reason: `cognition passed (${cog.count}/${REQUIRED_LENSES}) but output failed quality gates`,
|
|
1514
|
+
violations,
|
|
1515
|
+
rewritten,
|
|
1516
|
+
recipeAddendum,
|
|
1517
|
+
driftHits,
|
|
1518
|
+
lensCount: cog.count,
|
|
1519
|
+
requiredLenses: REQUIRED_LENSES,
|
|
1520
|
+
}), `stop:output-qc:${violations.join('|').slice(0, 240)}`, gateSessionId);
|
|
1259
1521
|
|
|
1260
1522
|
audit(`block-output-qc`, `mizan=${mizanBlock?'y':'n'} warn-reflect=${compelReflection?'y':'n'} drift=${driftHits.length} code=${codeQualityHits.length} discoveries-open=${ledgerOpenCount} impl-coupling=${implCouplingHits.length}`);
|
|
1261
1523
|
emitHarnessFooter({
|
|
@@ -1398,31 +1660,20 @@ const dalioHasMeasurablePredicate = dalioExpectedText
|
|
|
1398
1660
|
|
|
1399
1661
|
// Block stop if non-trivial action taken AND expected block is missing
|
|
1400
1662
|
if (hadNonTrivialAction && (!dalioExpectedMatch || !dalioHasMeasurablePredicate)) {
|
|
1401
|
-
const missingReason =
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
:
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
Add to your assistant text:
|
|
1417
|
-
|
|
1418
|
-
<expected>
|
|
1419
|
-
predicate: <exact measurable assertion — e.g. "exit_code==0", "status=running", "count=3 of 3">
|
|
1420
|
-
measurable_type: numeric | boolean | state_string
|
|
1421
|
-
threshold: <optional>
|
|
1422
|
-
eval_window_minutes: <optional>
|
|
1423
|
-
</expected>
|
|
1424
|
-
|
|
1425
|
-
No bypass — pre-tool-gate enforces this BEFORE the action; stop-gate enforces it AFTER. Both gates are now wired.`;
|
|
1663
|
+
const missingReason = withLoopDirective(buildForceReauthorReason({
|
|
1664
|
+
source: 'stop/dalio-expected',
|
|
1665
|
+
reason: dalioExpectedMatch
|
|
1666
|
+
? 'action had an <expected> block, but it was qualitative instead of measurable'
|
|
1667
|
+
: `non-trivial action (${lastActionSummary.slice(0, 120)}) had no <expected> block`,
|
|
1668
|
+
violations: [
|
|
1669
|
+
dalioExpectedMatch
|
|
1670
|
+
? 'Rejected qualitative expected phrases: better, improved, should work, more reliable, cleaner. Expected outcome must be numeric, boolean, or state-string.'
|
|
1671
|
+
: 'Missing <expected> block after non-trivial action. Dalio feedback loop cannot compare outcome without a measurable predicate.',
|
|
1672
|
+
'Required block: <expected> predicate: "exit_code==0" | "status=running" | "count=3 of 3"; measurable_type: numeric | boolean | state_string; threshold/eval_window optional.',
|
|
1673
|
+
],
|
|
1674
|
+
lensCount: cog.count,
|
|
1675
|
+
requiredLenses: REQUIRED_LENSES,
|
|
1676
|
+
}), `stop:dalio-expected:${hadNonTrivialAction}:${!!dalioExpectedMatch}:${dalioHasMeasurablePredicate}`, gateSessionId);
|
|
1426
1677
|
|
|
1427
1678
|
audit('block-dalio-expected-missing', `hadNonTrivialAction=${hadNonTrivialAction} expectedPresent=${!!dalioExpectedMatch} measurable=${dalioHasMeasurablePredicate}`);
|
|
1428
1679
|
emitHarnessFooter({
|
|
@@ -1445,7 +1696,37 @@ No bypass — pre-tool-gate enforces this BEFORE the action; stop-gate enforces
|
|
|
1445
1696
|
// Per feedback_no_timeouts_doctrine.md: no AbortController/setTimeout timeout.
|
|
1446
1697
|
{
|
|
1447
1698
|
const DALIO_LEDGER_PATH = `${HOME}/.claude/.aria-dalio-ledger.jsonl`;
|
|
1448
|
-
|
|
1699
|
+
let postReceipt = null;
|
|
1700
|
+
try {
|
|
1701
|
+
const post = await runtimeMizanPost(
|
|
1702
|
+
event.session_id || 'claude-code',
|
|
1703
|
+
assistantText.slice(0, 8000),
|
|
1704
|
+
{
|
|
1705
|
+
message: lastUserMessage || `stop-gate turn (${assistantText.length} chars)`,
|
|
1706
|
+
plannedApproach: lastActionSummary || 'Finalize and validate the just-emitted Claude response.',
|
|
1707
|
+
platform: 'claude-code',
|
|
1708
|
+
stage: 'hook-stop-post',
|
|
1709
|
+
},
|
|
1710
|
+
sessionMizanState?.receipt?.receiptId || null,
|
|
1711
|
+
);
|
|
1712
|
+
postReceipt = post?.receipt || null;
|
|
1713
|
+
if (postReceipt) {
|
|
1714
|
+
saveMizanReceiptState(event.session_id || 'claude-code', {
|
|
1715
|
+
...(sessionMizanState || {}),
|
|
1716
|
+
updatedAt: new Date().toISOString(),
|
|
1717
|
+
sessionId: event.session_id || 'claude-code',
|
|
1718
|
+
postReceipt,
|
|
1719
|
+
postResult: post?.result || null,
|
|
1720
|
+
postContract: post?.contract || null,
|
|
1721
|
+
postSummary: post?.summary || null,
|
|
1722
|
+
});
|
|
1723
|
+
}
|
|
1724
|
+
} catch (postErr) {
|
|
1725
|
+
console.error(
|
|
1726
|
+
`[aria-stop-gate] MIZAN POST FAILED — runtime receipt not recorded. Error: ${postErr instanceof Error ? postErr.message : String(postErr)}`,
|
|
1727
|
+
);
|
|
1728
|
+
audit('mizan-post-failed', `session=${event.session_id || 'claude-code'} err=${String(postErr).slice(0, 200)}`);
|
|
1729
|
+
}
|
|
1449
1730
|
|
|
1450
1731
|
const ledgerEntry = {
|
|
1451
1732
|
ts: new Date().toISOString(),
|
|
@@ -1469,7 +1750,11 @@ No bypass — pre-tool-gate enforces this BEFORE the action; stop-gate enforces
|
|
|
1469
1750
|
measurable_type: 'state_string',
|
|
1470
1751
|
}
|
|
1471
1752
|
: null,
|
|
1472
|
-
|
|
1753
|
+
metadata: {
|
|
1754
|
+
pre_receipt_id: sessionMizanState?.receipt?.receiptId || null,
|
|
1755
|
+
post_receipt_id: postReceipt?.receiptId || null,
|
|
1756
|
+
},
|
|
1757
|
+
source: 'claude-code-stop-gate-runtime',
|
|
1473
1758
|
model_used: 'claude-opus-4-7',
|
|
1474
1759
|
};
|
|
1475
1760
|
|
|
@@ -1484,40 +1769,20 @@ No bypass — pre-tool-gate enforces this BEFORE the action; stop-gate enforces
|
|
|
1484
1769
|
);
|
|
1485
1770
|
}
|
|
1486
1771
|
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
fetch(ARIA_SOUL_DECISIONS_URL, {
|
|
1492
|
-
method: 'POST',
|
|
1493
|
-
headers: {
|
|
1494
|
-
'Content-Type': 'application/json',
|
|
1495
|
-
...(dalioHarnessToken ? { Authorization: `Bearer ${dalioHarnessToken}` } : {}),
|
|
1496
|
-
},
|
|
1497
|
-
body: JSON.stringify(ledgerEntry),
|
|
1498
|
-
}).then((resp) => {
|
|
1499
|
-
if (!resp.ok) {
|
|
1500
|
-
// LOUD telemetry per feedback_canonical_secrets_governance.md
|
|
1501
|
-
console.error(
|
|
1502
|
-
`[aria-stop-gate] DALIO POST FAILED — aria-soul responded HTTP ${resp.status}. ` +
|
|
1503
|
-
`Local mirror written to ${DALIO_LEDGER_PATH}. Session: ${ledgerEntry.session_id}`,
|
|
1504
|
-
);
|
|
1505
|
-
audit('dalio-post-failed', `http=${resp.status} session=${ledgerEntry.session_id}`);
|
|
1506
|
-
} else {
|
|
1507
|
-
audit('dalio-post-ok', `session=${ledgerEntry.session_id} action=${lastActionSummary.slice(0, 80)}`);
|
|
1508
|
-
}
|
|
1509
|
-
}).catch((err) => {
|
|
1510
|
-
// Network failure — LOUD, never silent
|
|
1772
|
+
try {
|
|
1773
|
+
await runtimeDecisionLog(ledgerEntry);
|
|
1774
|
+
audit('dalio-post-ok', `session=${ledgerEntry.session_id} action=${lastActionSummary.slice(0, 80)}`);
|
|
1775
|
+
} catch (err) {
|
|
1511
1776
|
console.error(
|
|
1512
|
-
`[aria-stop-gate] DALIO POST
|
|
1777
|
+
`[aria-stop-gate] DALIO POST FAILED — runtime /decision/log rejected or unreachable. ` +
|
|
1513
1778
|
`Local mirror written to ${DALIO_LEDGER_PATH}. Error: ${err instanceof Error ? err.message : String(err)}`,
|
|
1514
1779
|
);
|
|
1515
|
-
audit('dalio-post-
|
|
1516
|
-
}
|
|
1780
|
+
audit('dalio-post-runtime-err', `err=${String(err).slice(0, 200)} session=${ledgerEntry.session_id}`);
|
|
1781
|
+
}
|
|
1517
1782
|
}
|
|
1518
1783
|
|
|
1519
|
-
// Block — non-trivial response without
|
|
1520
|
-
const reason = `Aria Stop-gate: non-trivial assistant response without
|
|
1784
|
+
// Block — non-trivial response without all required substantive lenses.
|
|
1785
|
+
const reason = withLoopDirective(`Aria Stop-gate: non-trivial assistant response without all required substantive cognition lenses. Found ${cog.count}/${REQUIRED_LENSES} (lenses: ${cog.names.join(', ') || 'none'}). Doctrine is action-coupled — text decisions ARE actions, and reflexive replies fail this gate the same way reflexive Bash does.
|
|
1521
1786
|
|
|
1522
1787
|
Re-emit the response with substantive lens application BEFORE drafting. Each lens must have ≥${SUBSTANCE_MIN_CHARS} chars of non-placeholder content:
|
|
1523
1788
|
|
|
@@ -1534,7 +1799,7 @@ Re-emit the response with substantive lens application BEFORE drafting. Each len
|
|
|
1534
1799
|
|
|
1535
1800
|
The block reflects work done BEFORE drafting. Don't emit it as ceremony; apply each lens as a thinking tool. Substance check defeats ritual emission.
|
|
1536
1801
|
|
|
1537
|
-
No per-command bypass (mirrors aria-pre-tool-gate.mjs v3 doctrine). No env-var disable path either — gates are unconditional from the gated process per Hamza directive 2026-04-27. If the gate misfires on legitimate cognition, fix the gate
|
|
1802
|
+
No per-command bypass (mirrors aria-pre-tool-gate.mjs v3 doctrine). No env-var disable path either — gates are unconditional from the gated process per Hamza directive 2026-04-27. If the gate misfires on legitimate cognition, fix the gate.`, `stop:lens-missing:${cog.count}`, gateSessionId);
|
|
1538
1803
|
|
|
1539
1804
|
audit(`block`, `lenses=${cog.count}/${REQUIRED_LENSES} chars=${assistantText.length}`);
|
|
1540
1805
|
emitHarnessFooter({
|
|
@@ -1547,5 +1812,5 @@ emitHarnessFooter({
|
|
|
1547
1812
|
codeCount: 0,
|
|
1548
1813
|
implCouplingCount: 0,
|
|
1549
1814
|
});
|
|
1550
|
-
console.log(JSON.stringify({ decision: 'block', reason }));
|
|
1815
|
+
console.log(JSON.stringify({ decision: 'block', reason: buildForceReauthorReason({ source: 'stop/lens-missing', reason, lensCount: cog.count, requiredLenses: REQUIRED_LENSES }) }));
|
|
1551
1816
|
process.exit(2);
|