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