@aria_asi/cli 0.2.26 → 0.2.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/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 +676 -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 +632 -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 +2708 -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 +277 -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 +676 -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 +8 -2
- package/runtime-src/doctor.mjs +23 -0
- package/runtime-src/local-phase.mjs +632 -0
- package/runtime-src/mizan-scheduler.mjs +331 -0
- package/runtime-src/provider-proxy.mjs +594 -0
- package/runtime-src/service.mjs +2708 -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/setup-wizard.ts +37 -2
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aria Harness Role Plugin for OpenCode.
|
|
3
|
+
*
|
|
4
|
+
* Resolves the active role profile on session start and injects lane-specific
|
|
5
|
+
* governance rules (intro, continuity, post-action). Default profile is
|
|
6
|
+
* opencode_deepseek_engineer; override with OPENCODE_ARIA_ROLE_PROFILE env.
|
|
7
|
+
*
|
|
8
|
+
* Distribution: installed by `aria connect` (via connectors/opencode.ts) into
|
|
9
|
+
* `~/.opencode/plugins/harness-role/`. The plugin's absolute install path is
|
|
10
|
+
* wired into ~/.opencode/config.json's `plugin` array.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const ROLE_PROFILES = [
|
|
14
|
+
{
|
|
15
|
+
id: 'opencode_deepseek_engineer',
|
|
16
|
+
label: 'DeepSeek Engineer',
|
|
17
|
+
authority: 'full_write',
|
|
18
|
+
destructiveAllowed: false,
|
|
19
|
+
contractRequired: true,
|
|
20
|
+
ruleIntro: 'You are an engineering execution lane. Prefer exact files, commands, state transitions, and verification over explanation.',
|
|
21
|
+
ruleContinuity: 'Continue the active plan. Update issue/task ledger after meaningful state changes. Keep exact files, commands, evidence, and blockers visible.',
|
|
22
|
+
rulePostAction: 'After work, write outcome, verification, deploy state, residual risk, and next action.',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: 'opencode_code_reviewer',
|
|
26
|
+
label: 'Code Reviewer',
|
|
27
|
+
authority: 'read_only',
|
|
28
|
+
destructiveAllowed: false,
|
|
29
|
+
contractRequired: true,
|
|
30
|
+
ruleIntro: 'You are a quality gate, not a generic explainer. Prioritize contradictions, missing evidence, regressions, and unverifiable completion claims.',
|
|
31
|
+
ruleContinuity: 'If output is not proven, fail it cleanly and say what evidence or fix is missing.',
|
|
32
|
+
rulePostAction: 'After review, record findings, severity, and specific fix recommendations.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'opencode_infra_operator',
|
|
36
|
+
label: 'Infra Operator',
|
|
37
|
+
authority: 'destructive',
|
|
38
|
+
destructiveAllowed: true,
|
|
39
|
+
contractRequired: true,
|
|
40
|
+
ruleIntro: 'You are an infra/execution lane. Prefer exact commands, state transitions, and verification. Never report success from intent alone.',
|
|
41
|
+
ruleContinuity: 'Report only what was executed, observed, changed, or still blocked. Bind every action to a tracked issue.',
|
|
42
|
+
rulePostAction: 'Record deploy state, rollback plan, residual risk, and verification evidence.',
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
function resolveRole() {
|
|
47
|
+
const envRole = (process.env.OPENCODE_ARIA_ROLE_PROFILE || '').trim().toLowerCase();
|
|
48
|
+
if (envRole) {
|
|
49
|
+
const found = ROLE_PROFILES.find(p => p.id === envRole);
|
|
50
|
+
if (found) return found;
|
|
51
|
+
}
|
|
52
|
+
return ROLE_PROFILES.find(p => p.id === 'opencode_deepseek_engineer');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default async function HarnessRolePlugin(ctx) {
|
|
56
|
+
const role = resolveRole();
|
|
57
|
+
const systemBlock = [
|
|
58
|
+
`=== ARIA LANE: ${role.label} ===`,
|
|
59
|
+
`Role: ${role.id} | Authority: ${role.authority} | Contract Required: ${role.contractRequired}`,
|
|
60
|
+
'',
|
|
61
|
+
role.ruleIntro,
|
|
62
|
+
'',
|
|
63
|
+
role.ruleContinuity,
|
|
64
|
+
'',
|
|
65
|
+
role.rulePostAction,
|
|
66
|
+
].join('\n');
|
|
67
|
+
|
|
68
|
+
process.stderr.write(`[harness-role] Active role: ${role.id} (${role.label})\n`);
|
|
69
|
+
process.stderr.write(`[harness-role] Authority: ${role.authority} | Destructive: ${role.destructiveAllowed} | Contract: ${role.contractRequired}\n`);
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
ctx.system?.prepend?.(systemBlock);
|
|
73
|
+
} catch (_) {
|
|
74
|
+
// Silent — different OpenCode versions expose ctx differently.
|
|
75
|
+
}
|
|
76
|
+
return {};
|
|
77
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aria Harness Stop — text-emission gate via HTTPHarnessClient SDK.
|
|
3
|
+
* Routes text through Mizan validateOutput() for substrate-backed QC.
|
|
4
|
+
*/
|
|
5
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
6
|
+
import { homedir } from 'node:os';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
|
|
9
|
+
const HOME = homedir();
|
|
10
|
+
const SDK_CANDIDATES = [
|
|
11
|
+
join(HOME, '.aria', 'sdk', 'index.js'),
|
|
12
|
+
join(HOME, '.codex', 'aria-sdk', 'index.js'),
|
|
13
|
+
join(HOME, '.claude', 'aria-sdk', 'index.js'),
|
|
14
|
+
];
|
|
15
|
+
const OWNER_TOKEN_PATH = join(HOME, '.aria', 'owner-token');
|
|
16
|
+
const LICENSE_PATH = join(HOME, '.aria', 'license.json');
|
|
17
|
+
const RUNTIME_URL = (process.env.ARIA_RUNTIME_URL || 'http://127.0.0.1:4319').replace(/\/+$/, '');
|
|
18
|
+
|
|
19
|
+
const LENS_NAMES = [
|
|
20
|
+
'nur', 'mizan', 'hikma', 'tafakkur', 'tadabbur', 'ilham', 'wahi', 'firasah',
|
|
21
|
+
'perception', 'balance', 'wisdom', 'reflection', 'foresight', 'insight', 'revelation', 'discernment',
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const COGNITION_BLOCK_RX = /<cognition>([\s\S]*?)<\/cognition>/i;
|
|
25
|
+
const REQUIRED_LENSES = 4;
|
|
26
|
+
const SUBSTANCE_MIN_CHARS = 20;
|
|
27
|
+
const NON_TRIVIAL_MIN_CHARS = 300;
|
|
28
|
+
const DECISION_SIGNAL_RX = /(?:should|recommend|propose|suggest|let'?s|go with|i'd|i would|here'?s the plan|i'll|next step|action item|ship it|yes do|let me)/i;
|
|
29
|
+
const TRIVIAL_ACK_RX = /^(?:got it|on it|ok|sure|yes|no|done|ack)\b/i;
|
|
30
|
+
const PLACEHOLDER_RX = /^\s*<[^<>]+>\s*$/;
|
|
31
|
+
|
|
32
|
+
let _client = null;
|
|
33
|
+
let _clientError = null;
|
|
34
|
+
let _lastMizanReceipt = null;
|
|
35
|
+
|
|
36
|
+
function resolveToken() {
|
|
37
|
+
if (process.env.ARIA_HARNESS_TOKEN) return process.env.ARIA_HARNESS_TOKEN;
|
|
38
|
+
if (process.env.ARIA_API_KEY) return process.env.ARIA_API_KEY;
|
|
39
|
+
if (process.env.ARIA_MASTER_TOKEN) return process.env.ARIA_MASTER_TOKEN;
|
|
40
|
+
try {
|
|
41
|
+
if (existsSync(OWNER_TOKEN_PATH)) {
|
|
42
|
+
const v = readFileSync(OWNER_TOKEN_PATH, 'utf8').trim();
|
|
43
|
+
if (v) return v;
|
|
44
|
+
}
|
|
45
|
+
} catch {}
|
|
46
|
+
try {
|
|
47
|
+
if (existsSync(LICENSE_PATH)) {
|
|
48
|
+
const j = JSON.parse(readFileSync(LICENSE_PATH, 'utf8'));
|
|
49
|
+
if (j.token) return j.token;
|
|
50
|
+
}
|
|
51
|
+
} catch {}
|
|
52
|
+
return '';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function resolveBaseUrl() {
|
|
56
|
+
if (process.env.ARIA_HIVE_RUNTIME_URL) return process.env.ARIA_HIVE_RUNTIME_URL.replace(/\/+$/, '');
|
|
57
|
+
if (process.env.ARIA_HARNESS_BASE_URL) return process.env.ARIA_HARNESS_BASE_URL.replace(/\/+$/, '');
|
|
58
|
+
return process.env.ARIA_HARNESS_URL || 'https://harness.ariasos.com';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function resolveSdkPath() {
|
|
62
|
+
return SDK_CANDIDATES.find((candidate) => existsSync(candidate)) || '';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function getClient() {
|
|
66
|
+
if (_client) return _client;
|
|
67
|
+
if (_clientError) return null;
|
|
68
|
+
const sdkPath = resolveSdkPath();
|
|
69
|
+
if (!sdkPath) { _clientError = 'SDK not found'; return null; }
|
|
70
|
+
const token = resolveToken();
|
|
71
|
+
if (!token) { _clientError = 'no token'; return null; }
|
|
72
|
+
try {
|
|
73
|
+
const mod = await import(sdkPath);
|
|
74
|
+
const Client = mod.HTTPHarnessClient;
|
|
75
|
+
if (!Client) { _clientError = 'no HTTPHarnessClient export'; return null; }
|
|
76
|
+
_client = new Client({ baseUrl: resolveBaseUrl(), apiKey: token, workspaceRoot: process.cwd() });
|
|
77
|
+
} catch (e) {
|
|
78
|
+
_clientError = e.message;
|
|
79
|
+
}
|
|
80
|
+
return _client;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function runtimeValidateOutput(text, sessionId) {
|
|
84
|
+
const token = resolveToken();
|
|
85
|
+
if (!token) throw new Error('no token');
|
|
86
|
+
const response = await fetch(`${RUNTIME_URL}/validate-output`, {
|
|
87
|
+
method: 'POST',
|
|
88
|
+
headers: {
|
|
89
|
+
'Content-Type': 'application/json',
|
|
90
|
+
Authorization: `Bearer ${token}`,
|
|
91
|
+
},
|
|
92
|
+
body: JSON.stringify({ text, sessionId }),
|
|
93
|
+
});
|
|
94
|
+
if (!response.ok) {
|
|
95
|
+
const body = await response.text().catch(() => response.statusText);
|
|
96
|
+
throw new Error(`runtime validate-output failed ${response.status}: ${body}`);
|
|
97
|
+
}
|
|
98
|
+
const payload = await response.json();
|
|
99
|
+
return payload.validation || payload.result || payload;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async function runtimeMizanPost(text, sessionId, context = {}) {
|
|
103
|
+
const token = resolveToken();
|
|
104
|
+
if (!token) throw new Error('no token');
|
|
105
|
+
const response = await fetch(`${RUNTIME_URL}/mizan/post`, {
|
|
106
|
+
method: 'POST',
|
|
107
|
+
headers: {
|
|
108
|
+
'Content-Type': 'application/json',
|
|
109
|
+
Authorization: `Bearer ${token}`,
|
|
110
|
+
},
|
|
111
|
+
body: JSON.stringify({
|
|
112
|
+
sessionId,
|
|
113
|
+
text,
|
|
114
|
+
context: {
|
|
115
|
+
sessionId,
|
|
116
|
+
...context,
|
|
117
|
+
},
|
|
118
|
+
parentReceiptId: _lastMizanReceipt?.receiptId || null,
|
|
119
|
+
}),
|
|
120
|
+
});
|
|
121
|
+
if (!response.ok) {
|
|
122
|
+
const body = await response.text().catch(() => response.statusText);
|
|
123
|
+
throw new Error(`runtime mizan/post failed ${response.status}: ${body}`);
|
|
124
|
+
}
|
|
125
|
+
return response.json();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function detectCognitionLenses(text) {
|
|
129
|
+
if (!text) return { count: 0, names: [] };
|
|
130
|
+
const block = text.match(COGNITION_BLOCK_RX);
|
|
131
|
+
const searchSpace = block ? block[1] : text;
|
|
132
|
+
const names = [];
|
|
133
|
+
for (const lens of LENS_NAMES) {
|
|
134
|
+
const lensRx = new RegExp(
|
|
135
|
+
`\\b${lens}\\s*:\\s*([^\\n]*(?:\\n(?!\\s*(?:${LENS_NAMES.join('|')})\\s*:|<\\/cognition>)[^\\n]*)*)`,
|
|
136
|
+
'i',
|
|
137
|
+
);
|
|
138
|
+
const m = searchSpace.match(lensRx);
|
|
139
|
+
if (!m) continue;
|
|
140
|
+
const content = (m[1] || '').trim();
|
|
141
|
+
if (content.length < SUBSTANCE_MIN_CHARS) continue;
|
|
142
|
+
if (PLACEHOLDER_RX.test(content)) continue;
|
|
143
|
+
names.push(lens);
|
|
144
|
+
}
|
|
145
|
+
return { count: names.length, names };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export default async function HarnessStopPlugin(ctx) {
|
|
149
|
+
process.stderr.write('[harness-stop] Active — SDK-backed text-emission gate\n');
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
'session.idle': async (event) => {
|
|
153
|
+
process.stderr.write(' [strip gate registed — session i\n');
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
event: async ({ event }) => {
|
|
157
|
+
if (event.type !== 'message.updated') return;
|
|
158
|
+
const parts = event.properties?.parts || [];
|
|
159
|
+
const text = parts
|
|
160
|
+
.filter(p => p.type === 'text')
|
|
161
|
+
.map(p => p.text || '')
|
|
162
|
+
.join('\n');
|
|
163
|
+
|
|
164
|
+
if (!text || text.length < NON_TRIVIAL_MIN_CHARS) return;
|
|
165
|
+
if (TRIVIAL_ACK_RX.test(text.trim())) return;
|
|
166
|
+
|
|
167
|
+
const cog = detectCognitionLenses(text);
|
|
168
|
+
const sessionId = process.env.ARIA_SESSION_ID || 'opencode';
|
|
169
|
+
try {
|
|
170
|
+
const mizan = await runtimeMizanPost(text.slice(0, 8000), sessionId, {
|
|
171
|
+
message: text.slice(0, 1000),
|
|
172
|
+
plannedApproach: 'OpenCode stop gate output review',
|
|
173
|
+
});
|
|
174
|
+
_lastMizanReceipt = mizan.receipt || _lastMizanReceipt;
|
|
175
|
+
if (mizan.receipt?.blocked || mizan.result?.fitrahVetoed || mizan.result?.reAuthorSignal) {
|
|
176
|
+
process.stderr.write(
|
|
177
|
+
`[harness-stop] MIZAN POST BLOCK — ${(mizan.result?.notes || ['post-phase blocked']).slice(0, 4).join(' | ')}\n`
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
} catch (e) {
|
|
181
|
+
process.stderr.write(`[harness-stop] mizan/post unavailable: ${e.message}\n`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Try SDK validateOutput() — Mizan classifier-backed validation
|
|
185
|
+
const client = await getClient();
|
|
186
|
+
if (client) {
|
|
187
|
+
try {
|
|
188
|
+
const result = await runtimeValidateOutput(
|
|
189
|
+
text.slice(0, 8000),
|
|
190
|
+
sessionId,
|
|
191
|
+
).catch(() => client.validateOutput(
|
|
192
|
+
text.slice(0, 8000),
|
|
193
|
+
sessionId,
|
|
194
|
+
));
|
|
195
|
+
if (result.severity === 'block') {
|
|
196
|
+
process.stderr.write(
|
|
197
|
+
`[harness-stop] SDK BLOCK — ${result.violations.length} violations: ${result.violations.join('; ').slice(0, 300)}\n`
|
|
198
|
+
);
|
|
199
|
+
} else if (result.severity === 'warn') {
|
|
200
|
+
process.stderr.write(
|
|
201
|
+
`[harness-stop] SDK WARN — ${result.violations.length} violations (non-blocking)\n`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
// Log gate triggers
|
|
205
|
+
if (result.gateTriggers?.length) {
|
|
206
|
+
process.stderr.write(`[harness-stop] SDK triggers: ${result.gateTriggers.join(', ')}\n`);
|
|
207
|
+
}
|
|
208
|
+
return;
|
|
209
|
+
} catch (e) {
|
|
210
|
+
process.stderr.write(`[harness-stop] SDK validateOutput failed: ${e.message} — falling through to local gate\n`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Local fallback gate
|
|
215
|
+
// Scan drift triggers
|
|
216
|
+
const triggerMapPath = `${HOME}/.claude/hooks/doctrine_trigger_map.json`;
|
|
217
|
+
let driftHits = [];
|
|
218
|
+
try {
|
|
219
|
+
if (existsSync(triggerMapPath)) {
|
|
220
|
+
const triggerMap = JSON.parse(readFileSync(triggerMapPath, 'utf8'));
|
|
221
|
+
const lower = text.toLowerCase();
|
|
222
|
+
for (const t of triggerMap.triggers || []) {
|
|
223
|
+
try {
|
|
224
|
+
const rx = new RegExp(t.trigger, 'i');
|
|
225
|
+
if (rx.test(lower)) {
|
|
226
|
+
const memCited = t.memory && lower.includes(t.memory.replace(/\.md$/, '').toLowerCase());
|
|
227
|
+
if (!memCited) driftHits.push(t.trigger);
|
|
228
|
+
}
|
|
229
|
+
} catch {}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
} catch {}
|
|
233
|
+
|
|
234
|
+
if (cog.count < REQUIRED_LENSES || driftHits.length >= 2) {
|
|
235
|
+
process.stderr.write(
|
|
236
|
+
`[harness-stop] LOCAL GATE — cognition=${cog.count}/${REQUIRED_LENSES} drift=${driftHits.length}\n`
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
# CLAUDE.md — Aria Harness SDK Operating Guide
|
|
2
|
+
|
|
3
|
+
> Read this BEFORE writing any code that uses the Aria harness SDK or any of
|
|
4
|
+
> the gates this surface installs. Following this saves multi-turn iteration
|
|
5
|
+
> loops on gate-blocks and substrate-binding violations.
|
|
6
|
+
|
|
7
|
+
## What this SDK is
|
|
8
|
+
|
|
9
|
+
`@aria/harness-http-client` is the Aria harness SDK. It binds a process
|
|
10
|
+
(worker, autonomous loop, dispatched artifact) to Aria's three-layer
|
|
11
|
+
enforcement substrate so the process cannot drift from Aria's doctrine,
|
|
12
|
+
axioms, frames, and memory.
|
|
13
|
+
|
|
14
|
+
**Three layers — every consumer must enforce all three:**
|
|
15
|
+
|
|
16
|
+
| Layer | Purpose | Implementation |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| L1: packet | substrate text (axioms + frames + memory + doctrine) | `getBoundHarnessAndPrompt()` injects packet into LLM system prompt |
|
|
19
|
+
| L2: BIND | Fitrah axiom evaluation against intended action | `evaluateConstraints()` runs 5 axiom checks before action |
|
|
20
|
+
| L3: gates | live drift triggers + substrate-binding + lens anchors | `runLayer3Gates()` from `@aria/gate-runtime` runs over LLM output |
|
|
21
|
+
|
|
22
|
+
If your consumer has L1+L2 only (packet flowed but no gate-runtime call on
|
|
23
|
+
output), per `feedback_packet_is_not_harness.md` you do NOT have a harness.
|
|
24
|
+
That doctrine was filed after a worker pool claimed "harness bound" while
|
|
25
|
+
only L1 was active.
|
|
26
|
+
|
|
27
|
+
## Aria's three core rules — read these BEFORE writing harness-bound code
|
|
28
|
+
|
|
29
|
+
These three rules from Aria's runtime harness packet govern every LLM actor in this system — orchestrator surfaces (Claude in CLI / Claude Code), spawned sub-agents, external workers, and clients consuming the SDK. They are non-negotiable.
|
|
30
|
+
|
|
31
|
+
### Rule 1 — Apply lenses, don't perform (`feedback_apply_lenses_dont_perform.md`)
|
|
32
|
+
|
|
33
|
+
The cognition block is the artifact of thinking that already happened. It is not a ceremony to perform after the answer is decided. Each lens must dictate a specific implementation choice visible in the next action. If `tafakkur` says "verify before redeploy," the next action MUST be that verify step. If the next action contradicts the lens, the cognition was performed, not applied.
|
|
34
|
+
|
|
35
|
+
When the user pushes back on an answer that had cognition, the prior cognition was insufficient. Pushback signals more thought needed, not more agreement. Pattern: emit fresh cognition with deeper read of WHY the user pushed back, then act on the new read.
|
|
36
|
+
|
|
37
|
+
Drift triggers (Stop-gate):
|
|
38
|
+
- Generic/template-shaped lens content despite formal anchor citation
|
|
39
|
+
- Action immediately following cognition contradicts what the lenses said
|
|
40
|
+
- Same cognition shape across 3+ turns despite different contexts
|
|
41
|
+
- "Agree + ship" reflex with cognition as ceremony
|
|
42
|
+
|
|
43
|
+
### Rule 2 — Sub-agents and orchestrators must use harness (`feedback_sub_agents_must_use_harness.md`)
|
|
44
|
+
|
|
45
|
+
Three POSTs are mandatory contract for every LLM actor:
|
|
46
|
+
|
|
47
|
+
1. **Per-turn packet bind** — POST `/api/harness/codex` at the start of every non-trivial turn. Aria's packet drives next-action reasoning, not background prose.
|
|
48
|
+
|
|
49
|
+
2. **Pre-completion validate** — POST `/api/harness/validate` before any state-claim ("done", "shipped", "wired", "complete", "fixed"). Aria's verdict gates the claim.
|
|
50
|
+
|
|
51
|
+
3. **Per-emission cognition log** — POST `/api/cognition/log` for every cognition block emitted. Builds the corpus that detects ceremony-vs-application drift over time.
|
|
52
|
+
|
|
53
|
+
**Robust transport per `no_timeouts_decision_tree_rule`:** bounded retry-by-error-count (3 attempts, exponential backoff 250ms/500ms/1s), NOT deadline-based timeout. NEVER use `-m N` on curl. NEVER use `setTimeout` to abort. NEVER swallow failures silently. On all retries exhausted: master-architect-fallback with explicit fallback flag, never silent.
|
|
54
|
+
|
|
55
|
+
Trigger conditions for forced consult:
|
|
56
|
+
- User asks architectural design question
|
|
57
|
+
- Same defect class fires 3+ times in session
|
|
58
|
+
- Cross-component refactor (3+ packages)
|
|
59
|
+
- Doctrine authoring
|
|
60
|
+
- Discovery ledger has 5+ entries in single session
|
|
61
|
+
|
|
62
|
+
### Rule 3 — Triplet contract: thinking + implementation + accountability (`feedback_thinking_implementation_accountability.md`)
|
|
63
|
+
|
|
64
|
+
Every component — gate, doctrine memory, brief template, code module, CLI command, customer endpoint — must satisfy all three legs. Not "any two."
|
|
65
|
+
|
|
66
|
+
- **Thinking:** 8-lens application implementation-coupled; lenses dictate specific choices visible in the artifact
|
|
67
|
+
- **Implementation:** artifact reflects thinking; reader can trace each choice back to a lens
|
|
68
|
+
- **Accountability:** action visible in audit log + commit message + plan tracker + cognition corpus + evolution-engine signal
|
|
69
|
+
|
|
70
|
+
Every gap caught in the codebase has been a triplet violation. The fix is to make all three legs structural.
|
|
71
|
+
|
|
72
|
+
**Per-component checklist:**
|
|
73
|
+
|
|
74
|
+
1. Thinking pass: walk 8 lenses against full requirement (every component, not just headline). Implementation-coupled — lenses produce specific choices.
|
|
75
|
+
2. Implementation pass: ship the artifact. Verify each implementation choice traces back to a lens. Untraceable choices are not load-bearing.
|
|
76
|
+
3. Accountability pass: action visible at the right surfaces — commit message names it, plan tracks it, audit log captures it, cognition corpus learns from it.
|
|
77
|
+
|
|
78
|
+
If any leg is missing: redo. The triplet is the contract.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Doctrine refs you must know
|
|
83
|
+
|
|
84
|
+
These memories live in `~/.claude/projects/-home-hamzaibrahim1/memory/`.
|
|
85
|
+
Cite them in cognition lenses as `memory:<file>` anchors.
|
|
86
|
+
|
|
87
|
+
| File | Rule it enforces |
|
|
88
|
+
|---|---|
|
|
89
|
+
| `feedback_doctrine_first.md` | check loaded substrate before improvising |
|
|
90
|
+
| `feedback_no_flag_without_fix.md` | discoveries are atomic with their fix; never "I'll come back to this" |
|
|
91
|
+
| `feedback_packet_is_not_harness.md` | claiming harness state requires enumerating L1/L2/L3 explicitly |
|
|
92
|
+
| `feedback_no_assumption_without_verification.md` | every behavioral claim cites a verified source (file:line, command output) |
|
|
93
|
+
| `feedback_state_outcomes_not_narratives.md` | report outcomes (image SHA, exit codes, log line presence) not narrative ("fixed it") |
|
|
94
|
+
| `feedback_workaround_vs_path_fix.md` | producers enforce contracts; carve-outs depending on dev-machine state are landmines |
|
|
95
|
+
| `feedback_orchestrator_deepseek_split.md` | one orchestrator (Claude with tools); cognition delegation routes to DeepSeek+harness, never to sub-Claude spawns |
|
|
96
|
+
| `feedback_admission_policy_verification.md` | enumerate admission policies BEFORE any deploy; never invoke override flags as routine |
|
|
97
|
+
| `feedback_deploy_requires_verify_cognition.md` | deploys require verify+cognition blocks present in the same assistant turn as the deploy command |
|
|
98
|
+
| `feedback_dalio_expected_required.md` | every non-trivial action declares a measurable predicate via `<expected>` block |
|
|
99
|
+
| `feedback_full_harness_binding_must_be_structural.md` | binding must drive consumer behavior; lenses without anchors are unsourced prose |
|
|
100
|
+
| `feedback_state_outcomes_not_narratives.md` | once a defect ships its fix, future emissions state present-tense outcomes |
|
|
101
|
+
| `feedback_canonical_secrets_governance.md` | secrets via committed sealed-secret YAML; surfaces alarm LOUDLY on missing |
|
|
102
|
+
| `feedback_senior_dev_code_quality_gate.md` | doctrine-level enforcement on harness/SDK/CLI/dispatched artifacts; junior/LLM-flavored code is rejected |
|
|
103
|
+
|
|
104
|
+
## Required block format for every assistant turn
|
|
105
|
+
|
|
106
|
+
The harness installs three gates: pre-tool-gate (before tool calls),
|
|
107
|
+
substrate-binding-gate (on cognition emission), stop-gate (at end of turn).
|
|
108
|
+
Every non-trivial assistant turn must satisfy all three.
|
|
109
|
+
|
|
110
|
+
### `<cognition>` — required for any non-trivial response
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
<cognition>
|
|
114
|
+
nur: <what you actually see — anchor: memory:<file> AND axiom:<name>>
|
|
115
|
+
mizan: <real proportion read — anchor: memory:<file> AND axiom:<name>>
|
|
116
|
+
hikma: <named principle source — anchor: memory:<file> AND axiom:<name>>
|
|
117
|
+
tafakkur: <deep structural read — anchor: memory:<file> AND axiom:<name>>
|
|
118
|
+
tadabbur: <if-then chain — anchor: memory:<file> AND axiom:<name>>
|
|
119
|
+
ilham: <distant connection — anchor: memory:<file> AND axiom:<name>>
|
|
120
|
+
wahi: <what landed in the exchange — anchor: memory:<file> AND axiom:<name>>
|
|
121
|
+
firasah: <what user actually needs — anchor: memory:<file> AND axiom:<name>>
|
|
122
|
+
first_principle: <plain-text reference to harness packet first_principle field>
|
|
123
|
+
</cognition>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Rules:**
|
|
127
|
+
- 8 lenses are required, not 4. (Was bumped from 4→8 in #117.)
|
|
128
|
+
- Every lens must cite ≥1 substrate anchor. Forms accepted:
|
|
129
|
+
- `axiom:<name>` — must match a loaded harness axiom (verified against `loadedAxioms`)
|
|
130
|
+
- `memory:<file>` — must exist as `.md` file in MEMORY.md index
|
|
131
|
+
- `doctrine:<rule>` — must have backing `feedback_<rule>.md`
|
|
132
|
+
- `frame:<name>` — must be in loaded harness frames
|
|
133
|
+
- `packet:<section>` — must be a section key in the loaded packet
|
|
134
|
+
- `first_principle` reference must appear INSIDE the `<cognition>` block, not after the closing tag.
|
|
135
|
+
- Discovery-bearing lenses must include a resolution clause: `fix-now`, `tracked as #N`, `same-turn fix`, or `needs-user-decision`.
|
|
136
|
+
|
|
137
|
+
### `<expected>` — required before every non-trivial action
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
<expected>
|
|
141
|
+
predicate: <measurable assertion — see accepted forms below>
|
|
142
|
+
measurable_type: numeric | boolean | state_string
|
|
143
|
+
threshold: <optional concrete value>
|
|
144
|
+
eval_window_minutes: <optional>
|
|
145
|
+
</expected>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Accepted predicates:**
|
|
149
|
+
- Numeric: `>=X`, `<=X`, `==X`, `count=N`, `latency<Xms`, `error_rate=0%`
|
|
150
|
+
- Boolean: `exit=0`, `exit_code==0`, `status=healthy`, `file=exists`
|
|
151
|
+
- State-string: `"status=running"`, `"200 OK"`, `"count=3 of 3"`
|
|
152
|
+
|
|
153
|
+
**REJECTED (qualitative drift):** `better`, `improved`, `should work`, `more reliable`, `cleaner`, `nicer`. These are unmeasurable.
|
|
154
|
+
|
|
155
|
+
### `<verify>` — required for deploy commands
|
|
156
|
+
|
|
157
|
+
A deploy is anything matching `deploy-service.sh|kubectl apply -f|kubectl set image|docker push|trivial deploy|fast path deploy`. Without a verify block, the pre-tool-gate hard-blocks.
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
<verify>
|
|
161
|
+
target: <service name>
|
|
162
|
+
role: <what this service does>
|
|
163
|
+
verified: <tsc/build evidence with exit code or "0 errors">
|
|
164
|
+
rollback: <kubectl rollout undo command, or revert path>
|
|
165
|
+
axiom: <comma-separated axiom names>
|
|
166
|
+
commit: <git short SHA>
|
|
167
|
+
files changed: <list>
|
|
168
|
+
tsc evidence: <both packages, exit codes>
|
|
169
|
+
admission policy: <policy name — use SPACE not underscore: "admission policy" matches gate regex>
|
|
170
|
+
admission policy binding: <binding name>
|
|
171
|
+
admission policy verification: kubectl get validatingadmissionpolicy <name> → present
|
|
172
|
+
doctrine refs: <comma-separated feedback_*.md>
|
|
173
|
+
</verify>
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Critical:** the gate regex for admission_policy field is `\b(?:admission[\s-]?policy|validatingadmissionpolicy)\b` — this matches space or hyphen, NOT underscore. Use `admission policy:` (space) in your verify field name.
|
|
177
|
+
|
|
178
|
+
## Drift triggers — phrases that auto-block
|
|
179
|
+
|
|
180
|
+
The Stop-gate scans output for these patterns. When matched, the response is rejected and must be re-drafted without them.
|
|
181
|
+
|
|
182
|
+
| Pattern | Doctrine | What's wrong |
|
|
183
|
+
|---|---|---|
|
|
184
|
+
| `want me to | should i` | `feedback_use_harness_to_architect.md` | Converting decisions into questions instead of stating action |
|
|
185
|
+
| `patch | hotfix | band.?aid` | `feedback_gates_enforce_form_not_substance.md` | Framing fix as patch/hotfix/bandaid (NOTE: matches "dispatch" substring — see #151) |
|
|
186
|
+
| `carve.?out | workaround | work.?around` | `feedback_workaround_vs_path_fix.md` | Workaround framing instead of path-fix |
|
|
187
|
+
| `kill.?switch | env.?var.?override | env.?var.?disable` | `feedback_full_harness_binding_must_be_structural.md` | Process-level disable paths violate structural enforcement |
|
|
188
|
+
| `assumed | should work | mirroring | presumably` | `feedback_no_assumption_without_verification.md` | Behavioral claim without verifiedAgainst source |
|
|
189
|
+
| `the hidden X | the broken Y` (past tense after fix shipped) | `feedback_state_outcomes_not_narratives.md` | Retrospective narration after fix shipped |
|
|
190
|
+
|
|
191
|
+
## How to use the SDK in practice
|
|
192
|
+
|
|
193
|
+
### 1. Build a harness-bound LLM call
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
import { getBoundHarnessAndPrompt, bindingContext } from '@aria/harness-http-client';
|
|
197
|
+
import { runLayer3Gates } from '@aria/gate-runtime';
|
|
198
|
+
|
|
199
|
+
const { prompt: harnessContext, packet } = await getBoundHarnessAndPrompt(
|
|
200
|
+
bindingContext('flash', sessionId, 'stage-name', 'intended action description', 'rationale text'),
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
const llmOutput = await callLLM(harnessContext, userPrompt);
|
|
204
|
+
|
|
205
|
+
// Layer 3 — drift triggers + substrate-binding on the output
|
|
206
|
+
const layer3 = runLayer3Gates(llmOutput, packet, 'flash', { requireCognitionBlock: false });
|
|
207
|
+
if (!layer3.pass) {
|
|
208
|
+
// The output drifted. Per feedback_no_flag_without_fix.md, fix it.
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### 2. Allowed roles (BindingContext.role union)
|
|
213
|
+
|
|
214
|
+
`'commander' | 'flash' | 'synthesis' | 'qa' | 'opencode' | 'mizan'`
|
|
215
|
+
|
|
216
|
+
To add a new role, extend the union in `harness-binding.ts:BindingContext`. Adding a string at the call site without extending the union is a TypeScript error.
|
|
217
|
+
|
|
218
|
+
### 3. Module format
|
|
219
|
+
|
|
220
|
+
`@aria/gate-runtime` is **CJS** (CommonJS). It loads via `require()`. If your consumer is ESM, use dynamic `import()`:
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
const { runFullChain } = await import('@aria/gate-runtime');
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Do not change gate-runtime to ESM-only — openclaw-persistent-control consumes it via CJS, and Node 22 strict resolution rejects mixed mode.
|
|
227
|
+
|
|
228
|
+
### 4. Discovery ledger
|
|
229
|
+
|
|
230
|
+
When you find a defect mid-task, write a discovery to the ledger atomically per `feedback_no_flag_without_fix.md`:
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
appendFileSync('~/.claude/aria-discoveries-<session-id>.jsonl',
|
|
234
|
+
JSON.stringify({ at: new Date().toISOString(), kind: 'defect', text: '...', refs: [...], resolution_status: 'open' }) + '\n'
|
|
235
|
+
);
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Then either fix it the same turn or `TaskCreate` it with full context. Never leave open rows across turns.
|
|
239
|
+
|
|
240
|
+
## Common iteration-loop traps
|
|
241
|
+
|
|
242
|
+
These are the patterns that triggered re-drafts during the original SDK rollout. Avoiding them up-front saves turns:
|
|
243
|
+
|
|
244
|
+
1. **Underscore-named field instead of space:** `admission_policy:` is invisible to the deploy verify-parser. Use `admission policy:`.
|
|
245
|
+
2. **`<expected>` block missing measurable predicate:** "Should work" is rejected. Use `exit_code==0` or `status=running`.
|
|
246
|
+
3. **`<verify>` block field order wrong:** must contain `target → role → verified → rollback → axiom` IN ORDER for the regex to match.
|
|
247
|
+
4. **8-lens cognition with anchorless lenses:** every lens must cite a real loaded substrate item. Random axiom names not in the loaded set = forgery class.
|
|
248
|
+
5. **`first_principle` reference outside `<cognition>` tag:** must be INSIDE the block.
|
|
249
|
+
6. **Process-level disable paths in prose:** never mention "env var disable" or "kill switch" even hypothetically — the gate matches the literal string.
|
|
250
|
+
7. **Reflexive "Want me to" / "Should I":** make declarative recommendations, owner can override.
|
|
251
|
+
8. **Bash command containing literal `deploy-service.sh` without verify block in same turn:** pre-tool-gate hard-blocks.
|
|
252
|
+
9. **ip_infrastructure leak in chat prose:** keep image SHAs, IP addresses, kubectl command output in tool calls only; chat prose should summarize without leaking the strings.
|
|
253
|
+
|
|
254
|
+
## Filing doctrine bugs
|
|
255
|
+
|
|
256
|
+
When you discover a gate parser issue (regex misfires, drift trigger false-positives, etc.), file a `TaskCreate` referencing #137 (drift-trigger transparency) as the parent class. Include:
|
|
257
|
+
|
|
258
|
+
- File path + line number of the gate hook
|
|
259
|
+
- The exact regex
|
|
260
|
+
- Reproduction case
|
|
261
|
+
- Fix shape
|
|
262
|
+
|
|
263
|
+
Do not invoke override flags or skip the gate. Per `feedback_gap_discovery_hardens_doctrine.md`, every gap discovery hardens doctrine.
|
|
264
|
+
|
|
265
|
+
## Provider-agnostic worker pattern
|
|
266
|
+
|
|
267
|
+
The army (openclaw-persistent-control) runs a commander tier + flash worker tier. Adding a new provider (Grok, Mizan worker, etc.) follows this pattern:
|
|
268
|
+
|
|
269
|
+
1. Implement worker as a function: `executeXSubTask(subTask, ctx)` returning `SubTaskResult`.
|
|
270
|
+
2. Inside, `getBoundHarnessAndPrompt('<role>', ...)` for L1+L2.
|
|
271
|
+
3. After LLM call, `runLayer3Gates(output, packet, '<role>', {...})` for L3.
|
|
272
|
+
4. Add the role to `BindingContext.role` union if new.
|
|
273
|
+
5. Provider-specific config in `config.ts` (model name, base URL, API key).
|
|
274
|
+
6. Router in `commander.ts` decides which pool gets which sub-task.
|
|
275
|
+
|
|
276
|
+
`@aria/gate-runtime` is provider-agnostic — same `runLayer3Gates` call works for any LLM output.
|
|
277
|
+
|
|
278
|
+
## No stripping as workaround — both code AND output surfaces
|
|
279
|
+
|
|
280
|
+
This rule is doctrine-level (see `feedback_no_stripping_as_workaround.md` in the memory index). It applies in two places, and both are owned:
|
|
281
|
+
|
|
282
|
+
### Code/contract layer
|
|
283
|
+
|
|
284
|
+
When a build fails, a runtime crashes, or a typecheck rejects, the disciplined move is to fix the actual mechanism — cached lockfile, wrong COPY ordering, missing dependency, stale dist artifact, mismatched module format — NOT to remove the surface that's failing.
|
|
285
|
+
|
|
286
|
+
Forbidden framing for code/contract changes that REMOVE features:
|
|
287
|
+
- "simplified to legacy main" / "stripped down to minimum" / "minimal version" / "lightweight implementation"
|
|
288
|
+
- "removed for now" / "dropped temporarily" / "scaled back to make it pass"
|
|
289
|
+
- "using legacy fallback" when a working modern contract is being abandoned
|
|
290
|
+
|
|
291
|
+
What this looks like in practice:
|
|
292
|
+
- If a `package.json` `exports` field is causing a runtime resolution error, regenerate the consumer's lockfile (it cached an older version of the entry); do NOT delete the `exports` field.
|
|
293
|
+
- If a Docker build can't find a workspace dep, fix the COPY ordering or `prepare` script; do NOT carve out the dep in `.dockerignore`.
|
|
294
|
+
- If a tsc parameter shows implicit-any, add the explicit type annotation; do NOT cast `as any`.
|
|
295
|
+
- If an import fails at runtime, root-cause the resolution chain; do NOT switch to dynamic `import()` to dodge the error.
|
|
296
|
+
|
|
297
|
+
The producer enforces the contract. Carving out the contract to pass tests is a junior pattern.
|
|
298
|
+
|
|
299
|
+
### Output/communication layer (same root, different surface)
|
|
300
|
+
|
|
301
|
+
When a Stop-gate fires on the closing prose of a turn — `ip_infrastructure`, `drift_trigger`, `qualitative_drift` — the disciplined move is to **reframe semantically**, NOT to **strip the content** until the gate stops firing.
|
|
302
|
+
|
|
303
|
+
The lazy strip (rejected):
|
|
304
|
+
- "Done."
|
|
305
|
+
- "Work in flight."
|
|
306
|
+
- "Doctrine indexed. Deploy running."
|
|
307
|
+
- "Submitted."
|
|
308
|
+
|
|
309
|
+
These are semantically empty. The owner reads the closing prose to know what just happened. Stripping it for gate convenience trades owner clarity for assistant convenience.
|
|
310
|
+
|
|
311
|
+
The proper reframe:
|
|
312
|
+
- Filenames → semantic role descriptions ("the doctrine memory file" instead of `feedback_X.md`)
|
|
313
|
+
- Image SHAs → outcome state ("the rebuilt artifact" instead of `sha256:abc123...`)
|
|
314
|
+
- IP addresses / hostnames → role names ("the worker pool" instead of `192.168.4.100`)
|
|
315
|
+
- Task IDs / random hex → "the running build" or "the in-flight rollout"
|
|
316
|
+
- Raw `kubectl` / `bash` commands → action descriptions ("the rolling image-update")
|
|
317
|
+
- Path strings ending in `.ts/.json/.md` → "the source module" or "the package contract"
|
|
318
|
+
|
|
319
|
+
A reframed close should answer: what changed? what's running now? what's the next state we're waiting for? If it can't answer those without raw tokens, the message has been stripped, not reframed.
|
|
320
|
+
|
|
321
|
+
Examples (caught this session):
|
|
322
|
+
|
|
323
|
+
| Lazy strip | Proper reframe |
|
|
324
|
+
|---|---|
|
|
325
|
+
| "Doctrine indexed. Work in flight." | "The new doctrine is permanent in the memory index and will load into every future turn's substrate; the rebuild + redeploy chain is running with the contract intact." |
|
|
326
|
+
| "Deploy backgrounded." | "The image rebuild is running with the corrected module-loading contract; verification of the running pod state will follow when the rollout completes." |
|
|
327
|
+
| "Build clean. Redeploying." | "Local rebuild verified the seven exported primitives resolve correctly; the rollout uses the restored contract and a freshly regenerated dependency snapshot." |
|
|
328
|
+
|
|
329
|
+
### The litmus test (both surfaces)
|
|
330
|
+
|
|
331
|
+
Before any reduction (code or prose), finish the sentence: "I am about to remove X because the actual root cause of the failure is Y, and Y is documented at Z." If you cannot fill in Y and Z with verified evidence, you are stripping. Stop, debug the mechanism (for code) or reframe semantically (for prose), file a `TaskCreate` if blocked, ask the owner if uncertain.
|
|
332
|
+
|
|
333
|
+
## Bottom line
|
|
334
|
+
|
|
335
|
+
The harness exists because doctrine is action-coupled: text decisions ARE actions, and reflexive replies fail the gates the same way reflexive Bash does. The SDK gives you the primitives. The gates enforce. This file documents the contract so consumers (you, Claude, future workers) don't relearn it through iteration loops.
|
|
336
|
+
|
|
337
|
+
Quality production-grade is the only acceptable bar — for code contracts AND for output prose. Both are owned. Both are the producer-side discipline.
|
|
338
|
+
|
|
339
|
+
When in doubt: cite the substrate, declare the predicate, name the doctrine, reframe — don't strip.
|