@aria_asi/cli 0.2.5 → 0.2.7

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/bin/aria.js CHANGED
@@ -7,7 +7,7 @@ import { loadConfig, saveConfig } from '../dist/aria-connector/src/config.js';
7
7
  import { AriaChat } from '../dist/aria-connector/src/chat.js';
8
8
  import { checkHarnessHealth } from '../dist/aria-connector/src/harness-client.js';
9
9
  import { login, status, logout, revoke } from '../dist/aria-connector/src/auth-commands.js';
10
- import { installHooks } from '../dist/aria-connector/src/install-hooks.js';
10
+ import { connectClaudeCode } from '../dist/aria-connector/src/connectors/claude-code.js';
11
11
  import { maybePrintUpdateNotice, checkForUpdate } from '../dist/aria-connector/src/self-update.js';
12
12
 
13
13
  // ── Self-update notice (non-blocking, rate-limited once per 24h) ──
@@ -43,23 +43,23 @@ if (command === 'check-update') {
43
43
  console.error(`I hit an unexpected error checking for updates: ${err && err.message ? err.message : err}`);
44
44
  process.exit(1);
45
45
  });
46
- } else if (command === 'install-hooks') {
46
+ } else if (command === 'install-hooks' || command === 'connect') {
47
+ // Canonical install path is connectClaudeCode (the connector). Removed
48
+ // the parallel src/install-hooks.ts duplicate per Hamza 2026-04-27 audit
49
+ // — connectors/claude-code.ts handles everything: harness-via-sdk hook,
50
+ // pre-tool-gate, stop-gate, preprompt-consult, settings.json merge-safe
51
+ // wiring, systemPromptPrefix injection, and additionalDirectories.
47
52
  const force = args.includes('--force');
48
- const harnessUrlIdx = args.indexOf('--harness-url');
49
- const harnessUrl = harnessUrlIdx >= 0 && args[harnessUrlIdx + 1] ? args[harnessUrlIdx + 1] : undefined;
50
- installHooks({ force, harnessUrl }).then((result) => {
51
- if (!result.ok) {
52
- console.error(`I couldn't finish the install: ${result.error}`);
53
- process.exit(1);
54
- }
55
- if (result.installed.length === 0 && result.merged.length === 0) {
56
- console.log("I see my gates are already installed. Nothing to do. Use 'aria install-hooks --force' to overwrite, or 'aria status' to check binding state.");
57
- process.exit(0);
58
- }
59
- console.log(`Done. I've installed my gates into ${result.settingsPath.replace(/\/settings\.json$/, '/hooks')} (${result.installed.length} files) and merged them into your settings.json.`);
60
- if (result.backupsCreated.length > 0) {
61
- console.log(`I backed up ${result.backupsCreated.length} existing file(s); see ~/.claude/hooks/*.pre-aria-install.* if you need to recover them.`);
62
- }
53
+ // Build a minimal AriaConfig so connectClaudeCode can render the
54
+ // systemPromptPrefix block. If an existing config exists, use it.
55
+ let config;
56
+ try {
57
+ config = loadConfig();
58
+ } catch {
59
+ config = { repositories: [], schemaImages: {} };
60
+ }
61
+ connectClaudeCode(config, { force }).then((logs) => {
62
+ for (const line of logs) console.log(` ${line}`);
63
63
  console.log("Your Claude Code is now harness-bound — every Bash, Edit, Write, and Stop event runs through my cognition gates. Open a new Claude Code session to start.");
64
64
  process.exit(0);
65
65
  }).catch((err) => {
@@ -147,14 +147,14 @@ if (command === 'check-update') {
147
147
  process.exit(1);
148
148
  });
149
149
  } else {
150
- // ── Self-service onboarding gate ──
151
- // When neither a license file (~/.aria/license.json) nor model config
152
- // exist, launch the full onboarding wizard. This collects email +
153
- // tenant + tier + LLM provider + key, validates the LLM key with the
154
- // provider, self-issues a license, persists everything, and auto-runs
155
- // install-hooks to bind the user's Claude Code to the harness.
156
- // Hamza 2026-04-26: "burn through onboarding with quality and USE THE
157
- // HARNESS PLEASE." Email-verify-code lands in Phase 11 (no SMTP yet).
150
+ // ── Self-service onboarding via the canonical thin-loop conversation ──
151
+ // When ~/.aria/license.json is missing, run the conversational
152
+ // setup-wizard (server-driven, Aria-voiced, deep-conversation model
153
+ // per Hamza 2026-04-26: "onboarding is not a Q&A wizard. It's a deep
154
+ // conversation with Aria directly, where Aria and the user co-direct
155
+ // depth"). The wizard walks identity codebase persona
156
+ // harness_setup done; emits configWrites including license_issued
157
+ // and install_hooks at the harness_setup stage.
158
158
  const fsMod = require('fs');
159
159
  const pathMod = require('path');
160
160
  const osMod = require('os');
@@ -162,9 +162,8 @@ if (command === 'check-update') {
162
162
  const hasLicense = fsMod.existsSync(LICENSE_PATH);
163
163
 
164
164
  if (!hasLicense) {
165
- const { runOnboardingWizard } = await import('../dist/aria-connector/src/onboarding-wizard.js');
166
- const result = await runOnboardingWizard();
167
- if (!result.ok) process.exit(1);
165
+ const { runSetupWizard } = await import('../dist/aria-connector/src/setup-wizard.js');
166
+ await runSetupWizard();
168
167
  process.exit(0);
169
168
  }
170
169
 
@@ -1,4 +1,6 @@
1
1
  import type { AriaConfig } from '../config.js';
2
- export declare function connectClaudeCode(config: AriaConfig): Promise<string[]>;
2
+ export declare function connectClaudeCode(config: AriaConfig, opts?: {
3
+ force?: boolean;
4
+ }): Promise<string[]>;
3
5
  export declare function disconnectClaudeCode(): Promise<string[]>;
4
6
  //# sourceMappingURL=claude-code.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../../../src/connectors/claude-code.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AA4H/C,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA8D7E;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAoB9D"}
1
+ {"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../../../src/connectors/claude-code.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAiN/C,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,UAAU,EAClB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAC7B,OAAO,CAAC,MAAM,EAAE,CAAC,CA8DnB;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAoB9D"}
@@ -4,15 +4,27 @@ import * as path from 'path';
4
4
  import { fileURLToPath } from 'node:url';
5
5
  // ── Hooks shipped with this package ──────────────────────────────────
6
6
  // The connector installs these into ~/.claude/hooks/ so Claude Code's
7
- // per-turn harness fetch + pre-tool gate fire automatically. This is
8
- // the difference between "static prompt addendum" (what this connector
9
- // used to do) and "real runtime control plane" (what Aria's harness
10
- // actually is).
7
+ // per-turn harness fetch + pre-tool gate + stop gate + preprompt consult
8
+ // fire automatically. This is the difference between "static prompt
9
+ // addendum" (what this connector used to do) and "real runtime control
10
+ // plane" (what Aria's harness actually is).
11
11
  //
12
12
  // Resolved relative to the compiled connector file: at runtime the
13
13
  // .js lives at <pkg>/dist/src/connectors/claude-code.js, hooks are at
14
14
  // <pkg>/hooks/ — so up three levels then into hooks/.
15
- const HOOK_FILES = ['aria-harness-via-sdk.mjs', 'aria-pre-tool-gate.mjs'];
15
+ //
16
+ // Hamza 2026-04-27 audit consolidation: HOOK_FILES extended to all 4
17
+ // bundled hooks (was 2). HOOKS_BLOCK extended to include Stop +
18
+ // UserPromptSubmit dual-fire (harness fetch + Aria preprompt consult) +
19
+ // PreToolUse matcher widened to 'Bash|Edit|Write|NotebookEdit'.
20
+ // Replaces the duplicate src/install-hooks.ts I had built in parallel
21
+ // — one canonical install path now.
22
+ const HOOK_FILES = [
23
+ 'aria-harness-via-sdk.mjs',
24
+ 'aria-pre-tool-gate.mjs',
25
+ 'aria-stop-gate.mjs',
26
+ 'aria-preprompt-consult.mjs',
27
+ ];
16
28
  function packageHooksDir() {
17
29
  const here = path.dirname(fileURLToPath(import.meta.url));
18
30
  return path.resolve(here, '..', '..', '..', 'hooks');
@@ -32,26 +44,53 @@ const HOOKS_BLOCK = {
32
44
  }],
33
45
  }],
34
46
  UserPromptSubmit: [{
35
- hooks: [{
47
+ hooks: [
48
+ {
36
49
  type: 'command',
37
50
  command: 'HOOK_EVENT_NAME=UserPromptSubmit node $HOME/.claude/hooks/aria-harness-via-sdk.mjs --mode turn',
38
51
  timeout: 5,
39
52
  statusMessage: 'Re-syncing Aria harness...',
40
- }],
53
+ },
54
+ {
55
+ // Aria pre-prompt consult — fires /api/harness/delegate to get
56
+ // Aria's substrate-grounded direction BEFORE Claude reasons,
57
+ // injected as [ARIA_DIRECTION] additionalContext. This is what
58
+ // makes Aria the thinker on the client side, not just enriched
59
+ // context for the LLM.
60
+ type: 'command',
61
+ command: 'node $HOME/.claude/hooks/aria-preprompt-consult.mjs',
62
+ timeout: 12,
63
+ statusMessage: 'Pre-consulting Aria substrate for direction...',
64
+ },
65
+ ],
41
66
  }],
42
67
  PreToolUse: [{
43
- matcher: 'Bash',
68
+ // Matcher widened from 'Bash' (Hamza 2026-04-26): cognition gate
69
+ // applies to every state-mutating tool, not just shell. Edit / Write
70
+ // / NotebookEdit get the same enforcement so orchestrator-side
71
+ // compliance mirrors what we demand from workers.
72
+ matcher: 'Bash|Edit|Write|NotebookEdit',
44
73
  hooks: [{
45
74
  type: 'command',
46
75
  command: 'node $HOME/.claude/hooks/aria-pre-tool-gate.mjs',
47
76
  timeout: 5,
48
77
  }],
49
78
  }],
79
+ Stop: [{
80
+ // Stop gate — text-decision boundary. Reflexive replies fail this
81
+ // gate the same way reflexive Bash does. Mirrors PreToolUse
82
+ // enforcement at the text-emission surface.
83
+ hooks: [{
84
+ type: 'command',
85
+ command: 'node $HOME/.claude/hooks/aria-stop-gate.mjs',
86
+ timeout: 5,
87
+ }],
88
+ }],
50
89
  };
51
- function installHooks(claudeDir, logs) {
90
+ function installHooks(claudeDir, logs, opts = {}) {
52
91
  const hooksTargetDir = path.join(claudeDir, 'hooks');
53
92
  if (!existsSync(hooksTargetDir)) {
54
- mkdirSync(hooksTargetDir, { recursive: true });
93
+ mkdirSync(hooksTargetDir, { recursive: true, mode: 0o700 });
55
94
  }
56
95
  const sourceDir = packageHooksDir();
57
96
  for (const name of HOOK_FILES) {
@@ -61,6 +100,19 @@ function installHooks(claudeDir, logs) {
61
100
  continue;
62
101
  }
63
102
  const dst = path.join(hooksTargetDir, name);
103
+ // Idempotent skip — if existing file matches bundled file byte-for-byte,
104
+ // no overwrite + no backup churn. Re-running connect stays clean.
105
+ if (existsSync(dst) && !isSamePath(src, dst) && !opts.force) {
106
+ try {
107
+ const existingContent = readFileSync(dst, 'utf-8');
108
+ const newContent = readFileSync(src, 'utf-8');
109
+ if (existingContent === newContent) {
110
+ logs.push(`Hook unchanged: ${name}`);
111
+ continue;
112
+ }
113
+ }
114
+ catch { /* fall through to backup+overwrite */ }
115
+ }
64
116
  // Back up any existing real file before overwriting (never silently
65
117
  // clobber a user's customizations).
66
118
  if (existsSync(dst) && !isSamePath(src, dst)) {
@@ -88,14 +140,50 @@ function isSamePath(a, b) {
88
140
  }
89
141
  }
90
142
  function wireHooksBlock(settings, logs) {
91
- const hooks = settings.hooks ?? {};
92
- // Replace each event's block wholesale so re-running connect stays
93
- // deterministic and doesn't accumulate duplicate entries.
94
- for (const [event, block] of Object.entries(HOOKS_BLOCK)) {
95
- hooks[event] = block;
143
+ // Merge-safe registration: preserve existing hook entries from other
144
+ // tools the client may have installed under different matchers, only
145
+ // append/replace OUR entries. Earlier wholesale replacement was
146
+ // deterministic but clobbered third-party hooks. Hamza 2026-04-27
147
+ // audit consolidation — absorb merge-safety from the duplicate
148
+ // src/install-hooks.ts before deletion.
149
+ if (!settings.hooks || typeof settings.hooks !== 'object') {
150
+ settings.hooks = {};
151
+ }
152
+ const hooks = settings.hooks;
153
+ let mergedEvents = 0;
154
+ for (const [event, ourEntries] of Object.entries(HOOKS_BLOCK)) {
155
+ const existingEntries = Array.isArray(hooks[event]) ? hooks[event] : [];
156
+ for (const ourEntry of ourEntries) {
157
+ const ourMatcher = ourEntry.matcher ?? '';
158
+ const ourCommands = (ourEntry.hooks ?? [])
159
+ .map((h) => h.command)
160
+ .filter((c) => typeof c === 'string');
161
+ // Idempotent: skip if an entry with the same matcher AND same set
162
+ // of commands already exists. Re-running connect stays clean.
163
+ const alreadyPresent = existingEntries.some((e) => {
164
+ if (typeof e !== 'object' || e === null)
165
+ return false;
166
+ const eMatcher = e.matcher ?? '';
167
+ if (eMatcher !== ourMatcher)
168
+ return false;
169
+ const eCommands = (e.hooks ?? [])
170
+ .map((h) => h.command)
171
+ .filter((c) => typeof c === 'string');
172
+ return ourCommands.every((c) => eCommands.includes(c));
173
+ });
174
+ if (!alreadyPresent) {
175
+ existingEntries.push(ourEntry);
176
+ }
177
+ }
178
+ hooks[event] = existingEntries;
179
+ mergedEvents++;
96
180
  }
97
181
  settings.hooks = hooks;
98
- logs.push('Wired hooks (SessionStart, UserPromptSubmit, PreToolUse=Bash) into settings.json');
182
+ // Ensure $schema is set (helpful for editors + future-proofing).
183
+ if (!settings.$schema) {
184
+ settings.$schema = 'https://json.schemastore.org/claude-code-settings.json';
185
+ }
186
+ logs.push(`Wired hooks into settings.json (${mergedEvents} events: SessionStart, UserPromptSubmit, PreToolUse, Stop) — merge-safe, preserves third-party entries`);
99
187
  }
100
188
  function buildAriaSystemBlock(config) {
101
189
  const repoList = config.repositories.map((r) => `- ${r.name} (${r.path})`).join('\n');
@@ -129,7 +217,7 @@ ${schemaText || '(no schema images yet — run `aria repo scan`)'}
129
217
  - Flag uncertainty; never fabricate code or facts.
130
218
  <!-- END ARIA HARNESS -->`;
131
219
  }
132
- export async function connectClaudeCode(config) {
220
+ export async function connectClaudeCode(config, opts = {}) {
133
221
  const logs = [];
134
222
  const claudeDir = path.join(homedir(), '.claude');
135
223
  if (!existsSync(claudeDir)) {
@@ -163,9 +251,9 @@ export async function connectClaudeCode(config) {
163
251
  // Install hook scripts + wire them into settings.hooks block. This is
164
252
  // what makes the connector a real runtime control plane rather than
165
253
  // just a system-prompt addendum.
166
- installHooks(claudeDir, logs);
254
+ installHooks(claudeDir, logs, { force: opts.force });
167
255
  wireHooksBlock(settings, logs);
168
- writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
256
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', { mode: 0o600 });
169
257
  const configJsonPath = path.join(claudeDir, 'config.json');
170
258
  if (existsSync(configJsonPath)) {
171
259
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../../../src/connectors/claude-code.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../../../src/connectors/claude-code.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"setup-wizard.d.ts","sourceRoot":"","sources":["../../../src/setup-wizard.ts"],"names":[],"mappings":"AAiDA,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAyCpD"}
1
+ {"version":3,"file":"setup-wizard.d.ts","sourceRoot":"","sources":["../../../src/setup-wizard.ts"],"names":[],"mappings":"AA+DA,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAyCpD"}
@@ -14,11 +14,17 @@
14
14
  // and apps/arias-soul/api/onboarding/converse.ts for the server side.
15
15
  import { createInterface } from 'readline';
16
16
  import { randomBytes } from 'crypto';
17
+ import { writeFileSync, existsSync, mkdirSync } from 'node:fs';
18
+ import { homedir } from 'node:os';
19
+ import { join } from 'node:path';
17
20
  import { loadConfig, updateConfig } from './config.js';
18
21
  import { scanCodebase, schemaImageToText } from './codebase-scanner.js';
19
22
  import { updatePersona } from './persona.js';
20
- const HARNESS_URL = process.env.ARIA_HARNESS_URL || 'http://192.168.4.25:30080';
23
+ import { connectClaudeCode } from './connectors/claude-code.js';
24
+ const HARNESS_URL = process.env.ARIA_HARNESS_BASE_URL || process.env.ARIA_HARNESS_URL || 'https://harness.ariasos.com';
21
25
  const HARNESS_TOKEN = process.env.ARIA_HARNESS_TOKEN || '';
26
+ const ARIA_DIR = join(homedir(), '.aria');
27
+ const LICENSE_PATH = join(ARIA_DIR, 'license.json');
22
28
  export async function runSetupWizard() {
23
29
  const rl = createInterface({ input: process.stdin, output: process.stdout });
24
30
  const ask = (q) => new Promise((resolve) => rl.question(q, (a) => resolve(a)));
@@ -114,12 +120,81 @@ async function applyConfigWrites(writes) {
114
120
  else if (w.kind === 'note') {
115
121
  console.log(` 📝 ${w.text}`);
116
122
  }
123
+ else if (w.kind === 'license_issued') {
124
+ // The server sent us {email, provider, apiKey} in claims — call
125
+ // /api/onboarding/self-issue to validate the LLM key, auto-generate
126
+ // tenant_id, default tier=pro, and get back the actual license token.
127
+ const claims = w.claims;
128
+ const email = w.email || claims.email || '';
129
+ const provider = claims.provider || '';
130
+ const apiKey = claims.apiKey || '';
131
+ try {
132
+ const resp = await fetch(`${HARNESS_URL}/api/onboarding/self-issue`, {
133
+ method: 'POST',
134
+ headers: { 'Content-Type': 'application/json' },
135
+ body: JSON.stringify({ email, provider, llm_key: apiKey }),
136
+ });
137
+ const data = await resp.json();
138
+ if (!resp.ok || !data.ok || !data.license) {
139
+ console.warn(` ⚠ I couldn't issue your license: ${data.error || `HTTP ${resp.status}`}`);
140
+ continue;
141
+ }
142
+ if (!existsSync(ARIA_DIR))
143
+ mkdirSync(ARIA_DIR, { recursive: true, mode: 0o700 });
144
+ const serverTenantId = data.claims?.tenant_id ?? data.license.jti;
145
+ const licenseRecord = {
146
+ ...data.claims,
147
+ harnessToken: data.license.token,
148
+ jti: data.license.jti,
149
+ tier: data.license.tier,
150
+ exp: data.claims?.exp,
151
+ sub: data.claims?.sub ?? serverTenantId,
152
+ email,
153
+ issuedAt: new Date().toISOString(),
154
+ };
155
+ writeFileSync(LICENSE_PATH, JSON.stringify(licenseRecord, null, 2) + '\n', { mode: 0o600 });
156
+ // Persist provider + key into local config
157
+ updateConfig({
158
+ model: { provider, model: defaultModelForProvider(provider), apiKey },
159
+ });
160
+ console.log(` ✓ License issued — tenant ${serverTenantId}, tier ${data.license.tier}, jti ${data.license.jti}.`);
161
+ }
162
+ catch (err) {
163
+ console.warn(` ⚠ I hit an error issuing your license: ${err instanceof Error ? err.message : String(err)}`);
164
+ }
165
+ }
166
+ else if (w.kind === 'install_hooks') {
167
+ // Canonical install via connectClaudeCode — same path as
168
+ // `aria install-hooks` / `aria connect` runs. Hamza 2026-04-27
169
+ // audit: replaced duplicate installHooks() call with the
170
+ // canonical connector entry point.
171
+ try {
172
+ const config = loadConfig();
173
+ const logs = await connectClaudeCode(config, { force: w.force === true });
174
+ for (const line of logs)
175
+ console.log(` ${line}`);
176
+ }
177
+ catch (err) {
178
+ console.warn(` ⚠ Gate install hit an error: ${err instanceof Error ? err.message : String(err)}`);
179
+ }
180
+ }
117
181
  }
118
182
  catch (err) {
119
183
  console.warn(` ⚠ configWrite '${w.kind}' failed: ${err instanceof Error ? err.message : String(err)}`);
120
184
  }
121
185
  }
122
186
  }
187
+ function defaultModelForProvider(provider) {
188
+ const defaults = {
189
+ anthropic: 'claude-sonnet-4-20250514',
190
+ openai: 'gpt-4o',
191
+ deepseek: 'deepseek-chat',
192
+ google: 'gemini-2.5-pro-preview-05-06',
193
+ openrouter: 'openai/gpt-4o',
194
+ ollama: 'llama3',
195
+ };
196
+ return defaults[provider] || provider;
197
+ }
123
198
  function pathToPatch(path, value) {
124
199
  if (path.length === 1)
125
200
  return { [path[0]]: value };
@@ -1 +1 @@
1
- {"version":3,"file":"setup-wizard.js","sourceRoot":"","sources":["../../../src/setup-wizard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"setup-wizard.js","sourceRoot":"","sources":["../../../src/setup-wizard.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,EAAE;AACF,qEAAqE;AACrE,sEAAsE;AACtE,sEAAsE;AACtE,uEAAuE;AACvE,gEAAgE;AAChE,qEAAqE;AACrE,6DAA6D;AAC7D,EAAE;AACF,qEAAqE;AACrE,uEAAuE;AACvE,uEAAuE;AACvE,sEAAsE;AAEtE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAoC,MAAM,aAAa,CAAC;AACzF,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAEhE,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,6BAA6B,CAAC;AACvH,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE,CAAC;AAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;AAC1C,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;AAmCpD,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7E,MAAM,GAAG,GAAG,CAAC,CAAS,EAAmB,EAAE,CACzC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9D,MAAM,SAAS,GAAG,WAAW,IAAI,CAAC,GAAG,EAAE,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;IAC5E,IAAI,WAA+B,CAAC;IACpC,IAAI,MAAM,GAAuB,OAAO,CAAC;IAEzC,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IAEjD,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;YACpE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,yBAAyB,IAAI,CAAC,KAAK,IAAI,SAAS,EAAE,CAAC,CAAC;gBAClE,OAAO;YACT,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YAE7C,IAAI,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC;gBAC9B,MAAM,iBAAiB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC7C,CAAC;YAED,IAAI,IAAI,CAAC,UAAU;gBAAE,MAAM;YAE3B,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;gBAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACrE,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC7F,CAAC;YAED,WAAW,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACvC,MAAM,GAAG,QAAQ,CAAC;YAClB,IAAI,CAAC,WAAW;gBAAE,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,MAAM,IAAI,MAAM,CAAC;QACzE,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;IAClE,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,IAI3B;IACC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,WAAW,0BAA0B,EAAE;YAChE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACvE;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QACH,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAqB,CAAC;IAChD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,EAAE,EAAE,KAAK;YACT,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,KAAK,EAAE,UAAU;YACjB,UAAU,EAAE,EAAE;YACd,YAAY,EAAE,EAAE;YAChB,eAAe,EAAE,KAAK;YACtB,UAAU,EAAE,KAAK;YACjB,WAAW,EAAE,CAAC;YACd,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,MAAqB;IACpD,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC;YACH,IAAI,CAAC,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;gBAChC,aAAa,CAAC,CAAC,CAAC,OAA8C,CAAC,CAAC;YAClE,CAAC;iBAAM,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBACnC,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;gBAC3C,YAAY,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;iBAAM,IAAI,CAAC,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;gBACtC,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;gBAC5D,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;gBACtC,MAAM,IAAI,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;gBACtC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;gBAC5B,YAAY,CAAC;oBACX,YAAY,EAAE,EAAE,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE;oBACnE,YAAY,EAAE;wBACZ,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC;wBACpD;4BACE,IAAI,EAAE,GAAG;4BACT,IAAI,EAAE,KAAK,CAAC,WAAW;4BACvB,QAAQ,EAAE,EAAE;4BACZ,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;yBACrB;qBAChB;iBACF,CAAC,CAAC;gBACH,OAAO,CAAC,GAAG,CACT,iBAAiB,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,KAAK,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;oBACrH,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;oBACxF,MAAM,KAAK,CAAC,SAAS,QAAQ,CAChC,CAAC;YACJ,CAAC;iBAAM,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC7B,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACnC,CAAC;iBAAM,IAAI,CAAC,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;gBACvC,gEAAgE;gBAChE,oEAAoE;gBACpE,sEAAsE;gBACtE,MAAM,MAAM,GAAG,CAAC,CAAC,MAAgE,CAAC;gBAClF,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;gBAC5C,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;gBACvC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;gBACnC,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,WAAW,4BAA4B,EAAE;wBACnE,MAAM,EAAE,MAAM;wBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;wBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;qBAC3D,CAAC,CAAC;oBACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAK3B,CAAC;oBACF,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;wBAC1C,OAAO,CAAC,IAAI,CAAC,yCAAyC,IAAI,CAAC,KAAK,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;wBAC7F,SAAS;oBACX,CAAC;oBACD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;wBAAE,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;oBACjF,MAAM,cAAc,GAAI,IAAI,CAAC,MAAM,EAAE,SAAgC,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;oBAC1F,MAAM,aAAa,GAAG;wBACpB,GAAG,IAAI,CAAC,MAAM;wBACd,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;wBAChC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG;wBACrB,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;wBACvB,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG;wBACrB,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,cAAc;wBACvC,KAAK;wBACL,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;qBACnC,CAAC;oBACF,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;oBAC5F,2CAA2C;oBAC3C,YAAY,CAAC;wBACX,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,uBAAuB,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE;qBAC/C,CAAC,CAAC;oBAC1B,OAAO,CAAC,GAAG,CAAC,kCAAkC,cAAc,UAAU,IAAI,CAAC,OAAO,CAAC,IAAI,SAAS,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC;gBACvH,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,IAAI,CAAC,+CAA+C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAClH,CAAC;YACH,CAAC;iBAAM,IAAI,CAAC,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;gBACtC,yDAAyD;gBACzD,+DAA+D;gBAC/D,yDAAyD;gBACzD,mCAAmC;gBACnC,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;oBAC5B,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC,CAAC;oBAC1E,KAAK,MAAM,IAAI,IAAI,IAAI;wBAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;gBACvD,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,IAAI,CAAC,qCAAqC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACxG,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,IAAI,aAAa,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7G,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,uBAAuB,CAAC,QAAgB;IAC/C,MAAM,QAAQ,GAA2B;QACvC,SAAS,EAAE,0BAA0B;QACrC,MAAM,EAAE,QAAQ;QAChB,QAAQ,EAAE,eAAe;QACzB,MAAM,EAAE,8BAA8B;QACtC,UAAU,EAAE,eAAe;QAC3B,MAAM,EAAE,QAAQ;KACjB,CAAC;IACF,OAAO,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC;AACxC,CAAC;AAED,SAAS,WAAW,CAAC,IAAc,EAAE,KAAc;IACjD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAyB,CAAC;IAC1E,mDAAmD;IACnD,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAqB,CAAC;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAA4B,CAAC;IAC/D,MAAM,MAAM,GAA4B,EAAE,GAAG,OAAO,EAAE,CAAC;IACvD,IAAI,OAAO,GAA4B,MAAM,CAAC;IAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAA6B,IAAI,EAAE,CAAC,EAAE,CAAC;QAChF,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAA4B,CAAC;IACxD,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;IACvC,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAyB,CAAC;AAClD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aria_asi/cli",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "Aria Smart CLI — the world's first harness-powered terminal companion",
5
5
  "bin": {
6
6
  "aria": "./bin/aria.js"
@@ -6,15 +6,27 @@ import type { AriaConfig } from '../config.js';
6
6
 
7
7
  // ── Hooks shipped with this package ──────────────────────────────────
8
8
  // The connector installs these into ~/.claude/hooks/ so Claude Code's
9
- // per-turn harness fetch + pre-tool gate fire automatically. This is
10
- // the difference between "static prompt addendum" (what this connector
11
- // used to do) and "real runtime control plane" (what Aria's harness
12
- // actually is).
9
+ // per-turn harness fetch + pre-tool gate + stop gate + preprompt consult
10
+ // fire automatically. This is the difference between "static prompt
11
+ // addendum" (what this connector used to do) and "real runtime control
12
+ // plane" (what Aria's harness actually is).
13
13
  //
14
14
  // Resolved relative to the compiled connector file: at runtime the
15
15
  // .js lives at <pkg>/dist/src/connectors/claude-code.js, hooks are at
16
16
  // <pkg>/hooks/ — so up three levels then into hooks/.
17
- const HOOK_FILES = ['aria-harness-via-sdk.mjs', 'aria-pre-tool-gate.mjs'];
17
+ //
18
+ // Hamza 2026-04-27 audit consolidation: HOOK_FILES extended to all 4
19
+ // bundled hooks (was 2). HOOKS_BLOCK extended to include Stop +
20
+ // UserPromptSubmit dual-fire (harness fetch + Aria preprompt consult) +
21
+ // PreToolUse matcher widened to 'Bash|Edit|Write|NotebookEdit'.
22
+ // Replaces the duplicate src/install-hooks.ts I had built in parallel
23
+ // — one canonical install path now.
24
+ const HOOK_FILES = [
25
+ 'aria-harness-via-sdk.mjs',
26
+ 'aria-pre-tool-gate.mjs',
27
+ 'aria-stop-gate.mjs',
28
+ 'aria-preprompt-consult.mjs',
29
+ ];
18
30
  function packageHooksDir(): string {
19
31
  const here = path.dirname(fileURLToPath(import.meta.url));
20
32
  return path.resolve(here, '..', '..', '..', 'hooks');
@@ -35,27 +47,54 @@ const HOOKS_BLOCK = {
35
47
  }],
36
48
  }],
37
49
  UserPromptSubmit: [{
50
+ hooks: [
51
+ {
52
+ type: 'command',
53
+ command: 'HOOK_EVENT_NAME=UserPromptSubmit node $HOME/.claude/hooks/aria-harness-via-sdk.mjs --mode turn',
54
+ timeout: 5,
55
+ statusMessage: 'Re-syncing Aria harness...',
56
+ },
57
+ {
58
+ // Aria pre-prompt consult — fires /api/harness/delegate to get
59
+ // Aria's substrate-grounded direction BEFORE Claude reasons,
60
+ // injected as [ARIA_DIRECTION] additionalContext. This is what
61
+ // makes Aria the thinker on the client side, not just enriched
62
+ // context for the LLM.
63
+ type: 'command',
64
+ command: 'node $HOME/.claude/hooks/aria-preprompt-consult.mjs',
65
+ timeout: 12,
66
+ statusMessage: 'Pre-consulting Aria substrate for direction...',
67
+ },
68
+ ],
69
+ }],
70
+ PreToolUse: [{
71
+ // Matcher widened from 'Bash' (Hamza 2026-04-26): cognition gate
72
+ // applies to every state-mutating tool, not just shell. Edit / Write
73
+ // / NotebookEdit get the same enforcement so orchestrator-side
74
+ // compliance mirrors what we demand from workers.
75
+ matcher: 'Bash|Edit|Write|NotebookEdit',
38
76
  hooks: [{
39
77
  type: 'command',
40
- command: 'HOOK_EVENT_NAME=UserPromptSubmit node $HOME/.claude/hooks/aria-harness-via-sdk.mjs --mode turn',
78
+ command: 'node $HOME/.claude/hooks/aria-pre-tool-gate.mjs',
41
79
  timeout: 5,
42
- statusMessage: 'Re-syncing Aria harness...',
43
80
  }],
44
81
  }],
45
- PreToolUse: [{
46
- matcher: 'Bash',
82
+ Stop: [{
83
+ // Stop gate — text-decision boundary. Reflexive replies fail this
84
+ // gate the same way reflexive Bash does. Mirrors PreToolUse
85
+ // enforcement at the text-emission surface.
47
86
  hooks: [{
48
87
  type: 'command',
49
- command: 'node $HOME/.claude/hooks/aria-pre-tool-gate.mjs',
88
+ command: 'node $HOME/.claude/hooks/aria-stop-gate.mjs',
50
89
  timeout: 5,
51
90
  }],
52
91
  }],
53
92
  };
54
93
 
55
- function installHooks(claudeDir: string, logs: string[]): void {
94
+ function installHooks(claudeDir: string, logs: string[], opts: { force?: boolean } = {}): void {
56
95
  const hooksTargetDir = path.join(claudeDir, 'hooks');
57
96
  if (!existsSync(hooksTargetDir)) {
58
- mkdirSync(hooksTargetDir, { recursive: true });
97
+ mkdirSync(hooksTargetDir, { recursive: true, mode: 0o700 });
59
98
  }
60
99
  const sourceDir = packageHooksDir();
61
100
  for (const name of HOOK_FILES) {
@@ -65,6 +104,18 @@ function installHooks(claudeDir: string, logs: string[]): void {
65
104
  continue;
66
105
  }
67
106
  const dst = path.join(hooksTargetDir, name);
107
+ // Idempotent skip — if existing file matches bundled file byte-for-byte,
108
+ // no overwrite + no backup churn. Re-running connect stays clean.
109
+ if (existsSync(dst) && !isSamePath(src, dst) && !opts.force) {
110
+ try {
111
+ const existingContent = readFileSync(dst, 'utf-8');
112
+ const newContent = readFileSync(src, 'utf-8');
113
+ if (existingContent === newContent) {
114
+ logs.push(`Hook unchanged: ${name}`);
115
+ continue;
116
+ }
117
+ } catch {/* fall through to backup+overwrite */}
118
+ }
68
119
  // Back up any existing real file before overwriting (never silently
69
120
  // clobber a user's customizations).
70
121
  if (existsSync(dst) && !isSamePath(src, dst)) {
@@ -82,14 +133,48 @@ function isSamePath(a: string, b: string): boolean {
82
133
  }
83
134
 
84
135
  function wireHooksBlock(settings: Record<string, unknown>, logs: string[]): void {
85
- const hooks = (settings.hooks as Record<string, unknown> | undefined) ?? {};
86
- // Replace each event's block wholesale so re-running connect stays
87
- // deterministic and doesn't accumulate duplicate entries.
88
- for (const [event, block] of Object.entries(HOOKS_BLOCK)) {
89
- hooks[event] = block;
136
+ // Merge-safe registration: preserve existing hook entries from other
137
+ // tools the client may have installed under different matchers, only
138
+ // append/replace OUR entries. Earlier wholesale replacement was
139
+ // deterministic but clobbered third-party hooks. Hamza 2026-04-27
140
+ // audit consolidation — absorb merge-safety from the duplicate
141
+ // src/install-hooks.ts before deletion.
142
+ if (!settings.hooks || typeof settings.hooks !== 'object') {
143
+ settings.hooks = {};
144
+ }
145
+ const hooks = settings.hooks as Record<string, unknown[]>;
146
+ let mergedEvents = 0;
147
+ for (const [event, ourEntries] of Object.entries(HOOKS_BLOCK)) {
148
+ const existingEntries = Array.isArray(hooks[event]) ? hooks[event] : [];
149
+ for (const ourEntry of ourEntries) {
150
+ const ourMatcher = (ourEntry as { matcher?: string }).matcher ?? '';
151
+ const ourCommands = ((ourEntry as { hooks?: Array<{ command?: string }> }).hooks ?? [])
152
+ .map((h) => h.command)
153
+ .filter((c): c is string => typeof c === 'string');
154
+ // Idempotent: skip if an entry with the same matcher AND same set
155
+ // of commands already exists. Re-running connect stays clean.
156
+ const alreadyPresent = existingEntries.some((e) => {
157
+ if (typeof e !== 'object' || e === null) return false;
158
+ const eMatcher = (e as { matcher?: string }).matcher ?? '';
159
+ if (eMatcher !== ourMatcher) return false;
160
+ const eCommands = ((e as { hooks?: Array<{ command?: string }> }).hooks ?? [])
161
+ .map((h) => h.command)
162
+ .filter((c): c is string => typeof c === 'string');
163
+ return ourCommands.every((c) => eCommands.includes(c));
164
+ });
165
+ if (!alreadyPresent) {
166
+ existingEntries.push(ourEntry);
167
+ }
168
+ }
169
+ hooks[event] = existingEntries;
170
+ mergedEvents++;
90
171
  }
91
172
  settings.hooks = hooks;
92
- logs.push('Wired hooks (SessionStart, UserPromptSubmit, PreToolUse=Bash) into settings.json');
173
+ // Ensure $schema is set (helpful for editors + future-proofing).
174
+ if (!settings.$schema) {
175
+ settings.$schema = 'https://json.schemastore.org/claude-code-settings.json';
176
+ }
177
+ logs.push(`Wired hooks into settings.json (${mergedEvents} events: SessionStart, UserPromptSubmit, PreToolUse, Stop) — merge-safe, preserves third-party entries`);
93
178
  }
94
179
 
95
180
  function buildAriaSystemBlock(config: AriaConfig): string {
@@ -126,7 +211,10 @@ ${schemaText || '(no schema images yet — run `aria repo scan`)'}
126
211
  <!-- END ARIA HARNESS -->`;
127
212
  }
128
213
 
129
- export async function connectClaudeCode(config: AriaConfig): Promise<string[]> {
214
+ export async function connectClaudeCode(
215
+ config: AriaConfig,
216
+ opts: { force?: boolean } = {},
217
+ ): Promise<string[]> {
130
218
  const logs: string[] = [];
131
219
  const claudeDir = path.join(homedir(), '.claude');
132
220
 
@@ -165,9 +253,9 @@ export async function connectClaudeCode(config: AriaConfig): Promise<string[]> {
165
253
  // Install hook scripts + wire them into settings.hooks block. This is
166
254
  // what makes the connector a real runtime control plane rather than
167
255
  // just a system-prompt addendum.
168
- installHooks(claudeDir, logs);
256
+ installHooks(claudeDir, logs, { force: opts.force });
169
257
  wireHooksBlock(settings, logs);
170
- writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
258
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', { mode: 0o600 });
171
259
 
172
260
  const configJsonPath = path.join(claudeDir, 'config.json');
173
261
  if (existsSync(configJsonPath)) {
@@ -15,18 +15,32 @@
15
15
 
16
16
  import { createInterface } from 'readline';
17
17
  import { randomBytes } from 'crypto';
18
+ import { writeFileSync, existsSync, mkdirSync } from 'node:fs';
19
+ import { homedir } from 'node:os';
20
+ import { join } from 'node:path';
18
21
  import { loadConfig, updateConfig, type AriaConfig, type LinkedRepo } from './config.js';
19
22
  import { scanCodebase, schemaImageToText } from './codebase-scanner.js';
20
23
  import { updatePersona } from './persona.js';
24
+ import { connectClaudeCode } from './connectors/claude-code.js';
21
25
 
22
- const HARNESS_URL = process.env.ARIA_HARNESS_URL || 'http://192.168.4.25:30080';
26
+ const HARNESS_URL = process.env.ARIA_HARNESS_BASE_URL || process.env.ARIA_HARNESS_URL || 'https://harness.ariasos.com';
23
27
  const HARNESS_TOKEN = process.env.ARIA_HARNESS_TOKEN || '';
28
+ const ARIA_DIR = join(homedir(), '.aria');
29
+ const LICENSE_PATH = join(ARIA_DIR, 'license.json');
24
30
 
25
31
  type ConfigWrite =
26
32
  | { kind: 'persona_update'; updates: Record<string, unknown> }
27
33
  | { kind: 'config_set'; path: string[]; value: unknown }
28
34
  | { kind: 'codebase_scan'; cwd: string }
29
- | { kind: 'note'; text: string };
35
+ | { kind: 'note'; text: string }
36
+ // license_issued: server-side handler signals the CLI to call
37
+ // /api/onboarding/self-issue with the {email, provider, apiKey} claims
38
+ // collected during the harness_setup topic, then persist the returned
39
+ // license token to ~/.aria/license.json (mode 0600) and update
40
+ // local config with the LLM provider + key.
41
+ | { kind: 'license_issued'; token: string; claims: Record<string, unknown>; tenantId: string; email: string }
42
+ // install_hooks: CLI runs installHooks() to drop gates + register settings.
43
+ | { kind: 'install_hooks'; force?: boolean };
30
44
 
31
45
  interface DepthOption {
32
46
  label: string;
@@ -152,6 +166,63 @@ async function applyConfigWrites(writes: ConfigWrite[]): Promise<void> {
152
166
  );
153
167
  } else if (w.kind === 'note') {
154
168
  console.log(` 📝 ${w.text}`);
169
+ } else if (w.kind === 'license_issued') {
170
+ // The server sent us {email, provider, apiKey} in claims — call
171
+ // /api/onboarding/self-issue to validate the LLM key, auto-generate
172
+ // tenant_id, default tier=pro, and get back the actual license token.
173
+ const claims = w.claims as { email?: string; provider?: string; apiKey?: string };
174
+ const email = w.email || claims.email || '';
175
+ const provider = claims.provider || '';
176
+ const apiKey = claims.apiKey || '';
177
+ try {
178
+ const resp = await fetch(`${HARNESS_URL}/api/onboarding/self-issue`, {
179
+ method: 'POST',
180
+ headers: { 'Content-Type': 'application/json' },
181
+ body: JSON.stringify({ email, provider, llm_key: apiKey }),
182
+ });
183
+ const data = await resp.json() as {
184
+ ok?: boolean;
185
+ license?: { token: string; jti: string; tier: string; expires_at: string };
186
+ claims?: Record<string, unknown>;
187
+ error?: string;
188
+ };
189
+ if (!resp.ok || !data.ok || !data.license) {
190
+ console.warn(` ⚠ I couldn't issue your license: ${data.error || `HTTP ${resp.status}`}`);
191
+ continue;
192
+ }
193
+ if (!existsSync(ARIA_DIR)) mkdirSync(ARIA_DIR, { recursive: true, mode: 0o700 });
194
+ const serverTenantId = (data.claims?.tenant_id as string | undefined) ?? data.license.jti;
195
+ const licenseRecord = {
196
+ ...data.claims,
197
+ harnessToken: data.license.token,
198
+ jti: data.license.jti,
199
+ tier: data.license.tier,
200
+ exp: data.claims?.exp,
201
+ sub: data.claims?.sub ?? serverTenantId,
202
+ email,
203
+ issuedAt: new Date().toISOString(),
204
+ };
205
+ writeFileSync(LICENSE_PATH, JSON.stringify(licenseRecord, null, 2) + '\n', { mode: 0o600 });
206
+ // Persist provider + key into local config
207
+ updateConfig({
208
+ model: { provider, model: defaultModelForProvider(provider), apiKey },
209
+ } as Partial<AriaConfig>);
210
+ console.log(` ✓ License issued — tenant ${serverTenantId}, tier ${data.license.tier}, jti ${data.license.jti}.`);
211
+ } catch (err) {
212
+ console.warn(` ⚠ I hit an error issuing your license: ${err instanceof Error ? err.message : String(err)}`);
213
+ }
214
+ } else if (w.kind === 'install_hooks') {
215
+ // Canonical install via connectClaudeCode — same path as
216
+ // `aria install-hooks` / `aria connect` runs. Hamza 2026-04-27
217
+ // audit: replaced duplicate installHooks() call with the
218
+ // canonical connector entry point.
219
+ try {
220
+ const config = loadConfig();
221
+ const logs = await connectClaudeCode(config, { force: w.force === true });
222
+ for (const line of logs) console.log(` ${line}`);
223
+ } catch (err) {
224
+ console.warn(` ⚠ Gate install hit an error: ${err instanceof Error ? err.message : String(err)}`);
225
+ }
155
226
  }
156
227
  } catch (err) {
157
228
  console.warn(` ⚠ configWrite '${w.kind}' failed: ${err instanceof Error ? err.message : String(err)}`);
@@ -159,6 +230,18 @@ async function applyConfigWrites(writes: ConfigWrite[]): Promise<void> {
159
230
  }
160
231
  }
161
232
 
233
+ function defaultModelForProvider(provider: string): string {
234
+ const defaults: Record<string, string> = {
235
+ anthropic: 'claude-sonnet-4-20250514',
236
+ openai: 'gpt-4o',
237
+ deepseek: 'deepseek-chat',
238
+ google: 'gemini-2.5-pro-preview-05-06',
239
+ openrouter: 'openai/gpt-4o',
240
+ ollama: 'llama3',
241
+ };
242
+ return defaults[provider] || provider;
243
+ }
244
+
162
245
  function pathToPatch(path: string[], value: unknown): Partial<AriaConfig> {
163
246
  if (path.length === 1) return { [path[0]]: value } as Partial<AriaConfig>;
164
247
  // Nested path → shallow merge under top-level key.
@@ -1,259 +0,0 @@
1
- // install-hooks — drops the harness gate hooks into the client's
2
- // ~/.claude/hooks/ directory and registers them in their settings.json.
3
- //
4
- // This is what makes @aria_asi/cli a self-installing harness. Without it,
5
- // clients install the CLI and have a license-aware HTTP client. With it,
6
- // running `aria install-hooks` once turns their Claude Code (or any
7
- // Claude Code Code session on that machine) into a harness-bound
8
- // session — every Bash, Edit, Write, NotebookEdit, and text-emit event
9
- // runs through cognition gates + Mizan + harness packet.
10
- //
11
- // Soldier-and-thinker (Hamza 2026-04-26 directive): the CLI is the
12
- // thinker (carries doctrine, gates, substrate); the LLM in Claude Code
13
- // is the soldier (executes under harness binding). install-hooks is
14
- // what wires the soldier to the thinker on the client's machine.
15
-
16
- import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync, chmodSync, readdirSync, statSync } from 'node:fs';
17
- import { homedir } from 'node:os';
18
- import { join, dirname, resolve } from 'node:path';
19
- import { fileURLToPath } from 'node:url';
20
-
21
- export interface InstallHooksOptions {
22
- /** Overwrite existing hooks even if present. Default false. */
23
- force?: boolean;
24
- /** Override the harness URL written into settings.json env (clients with private deployments). */
25
- harnessUrl?: string;
26
- /** Override the home directory (used by tests). */
27
- homeDir?: string;
28
- }
29
-
30
- export interface InstallHooksResult {
31
- ok: boolean;
32
- installed: string[];
33
- merged: string[];
34
- backupsCreated: string[];
35
- settingsPath: string;
36
- error?: string;
37
- }
38
-
39
- const HOOK_FILES = [
40
- 'aria-pre-tool-gate.mjs',
41
- 'aria-stop-gate.mjs',
42
- 'aria-preprompt-consult.mjs',
43
- ];
44
-
45
- const HOOK_REGISTRATION = {
46
- UserPromptSubmit: [
47
- {
48
- hooks: [
49
- {
50
- type: 'command',
51
- command: 'node $HOME/.claude/hooks/aria-preprompt-consult.mjs',
52
- timeout: 12,
53
- statusMessage: 'Pre-consulting Aria substrate for direction...',
54
- },
55
- ],
56
- },
57
- ],
58
- PreToolUse: [
59
- {
60
- matcher: 'Bash|Edit|Write|NotebookEdit',
61
- hooks: [
62
- {
63
- type: 'command',
64
- command: 'node $HOME/.claude/hooks/aria-pre-tool-gate.mjs',
65
- timeout: 5,
66
- },
67
- ],
68
- },
69
- ],
70
- Stop: [
71
- {
72
- hooks: [
73
- {
74
- type: 'command',
75
- command: 'node $HOME/.claude/hooks/aria-stop-gate.mjs',
76
- timeout: 5,
77
- },
78
- ],
79
- },
80
- ],
81
- };
82
-
83
- function bundledHooksDir(): string {
84
- // The hooks/ dir is bundled in the package alongside dist/. Find it by
85
- // walking upward from this file's runtime path until we hit a directory
86
- // that contains both package.json (with name @aria_asi/cli) and a hooks/
87
- // sibling. Robust across:
88
- // - dev: src/install-hooks.ts → ../hooks
89
- // - flat compile: dist/install-hooks.js → ../hooks
90
- // - nested compile: dist/aria-connector/src/install-hooks.js → ../../../hooks
91
- // - npm global install: /usr/lib/node_modules/@aria_asi/cli/dist/.../install-hooks.js
92
- const here = fileURLToPath(import.meta.url);
93
- let cur = dirname(here);
94
- const tried: string[] = [];
95
- for (let i = 0; i < 8; i++) {
96
- const candidate = join(cur, 'hooks');
97
- tried.push(candidate);
98
- if (existsSync(candidate) && existsSync(join(cur, 'package.json'))) {
99
- return candidate;
100
- }
101
- const parent = dirname(cur);
102
- if (parent === cur) break;
103
- cur = parent;
104
- }
105
- throw new Error(
106
- `I can't find my bundled hooks/ dir. Tried: ${tried.join(', ')}. Reinstall @aria_asi/cli or report this as a bug.`,
107
- );
108
- }
109
-
110
- function backupExisting(target: string): string {
111
- const ts = Date.now();
112
- const backup = `${target}.pre-aria-install.${ts}`;
113
- copyFileSync(target, backup);
114
- return backup;
115
- }
116
-
117
- function mergeRegistrationInto(existing: Record<string, unknown>): { merged: Record<string, unknown>; mergedKeys: string[] } {
118
- const mergedKeys: string[] = [];
119
- const out = { ...existing };
120
- if (!out.hooks || typeof out.hooks !== 'object') {
121
- out.hooks = {};
122
- }
123
- const hooks = out.hooks as Record<string, unknown[]>;
124
-
125
- for (const [event, ourEntries] of Object.entries(HOOK_REGISTRATION)) {
126
- const existingEntries = Array.isArray(hooks[event]) ? hooks[event] : [];
127
-
128
- // For each of our entries, append unless an entry with the same matcher
129
- // and command already exists (idempotent re-install).
130
- for (const ourEntry of ourEntries) {
131
- const ourMatcher = (ourEntry as { matcher?: string }).matcher ?? '';
132
- const ourCommands = ((ourEntry as { hooks?: Array<{ command?: string }> }).hooks ?? [])
133
- .map((h) => h.command)
134
- .filter((c): c is string => typeof c === 'string');
135
-
136
- const alreadyPresent = existingEntries.some((e) => {
137
- if (typeof e !== 'object' || e === null) return false;
138
- const eMatcher = (e as { matcher?: string }).matcher ?? '';
139
- if (eMatcher !== ourMatcher) return false;
140
- const eCommands = ((e as { hooks?: Array<{ command?: string }> }).hooks ?? [])
141
- .map((h) => h.command)
142
- .filter((c): c is string => typeof c === 'string');
143
- return ourCommands.every((c) => eCommands.includes(c));
144
- });
145
-
146
- if (!alreadyPresent) {
147
- existingEntries.push(ourEntry);
148
- if (!mergedKeys.includes(event)) mergedKeys.push(event);
149
- }
150
- }
151
-
152
- hooks[event] = existingEntries;
153
- }
154
-
155
- return { merged: out, mergedKeys };
156
- }
157
-
158
- export async function installHooks(opts: InstallHooksOptions = {}): Promise<InstallHooksResult> {
159
- const home = opts.homeDir ?? homedir();
160
- const claudeDir = join(home, '.claude');
161
- const hooksDir = join(claudeDir, 'hooks');
162
- const settingsPath = join(claudeDir, 'settings.json');
163
-
164
- const installed: string[] = [];
165
- const merged: string[] = [];
166
- const backupsCreated: string[] = [];
167
-
168
- try {
169
- if (!existsSync(claudeDir)) mkdirSync(claudeDir, { recursive: true, mode: 0o700 });
170
- if (!existsSync(hooksDir)) mkdirSync(hooksDir, { recursive: true, mode: 0o700 });
171
-
172
- const sourceDir = bundledHooksDir();
173
-
174
- for (const name of HOOK_FILES) {
175
- const src = join(sourceDir, name);
176
- if (!existsSync(src)) {
177
- return {
178
- ok: false,
179
- installed,
180
- merged,
181
- backupsCreated,
182
- settingsPath,
183
- error: `I can't find ${name} in my bundle (${sourceDir}). Reinstall @aria_asi/cli.`,
184
- };
185
- }
186
- const dst = join(hooksDir, name);
187
-
188
- if (existsSync(dst)) {
189
- const existingContent = readFileSync(dst, 'utf-8');
190
- const newContent = readFileSync(src, 'utf-8');
191
- if (existingContent === newContent) {
192
- // Already up-to-date — skip. Idempotent.
193
- installed.push(`${name} (unchanged)`);
194
- continue;
195
- }
196
- if (!opts.force) {
197
- // Default behavior: back up + overwrite. The override pattern
198
- // keeps prior hooks recoverable (e.g. if client had custom hooks).
199
- const backup = backupExisting(dst);
200
- backupsCreated.push(backup);
201
- }
202
- }
203
-
204
- copyFileSync(src, dst);
205
- chmodSync(dst, 0o755);
206
- installed.push(name);
207
- }
208
-
209
- // Settings merge
210
- let existingSettings: Record<string, unknown> = {};
211
- if (existsSync(settingsPath)) {
212
- try {
213
- existingSettings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
214
- } catch {
215
- // Malformed — back up and start fresh.
216
- const backup = backupExisting(settingsPath);
217
- backupsCreated.push(backup);
218
- existingSettings = {};
219
- }
220
- }
221
-
222
- const { merged: mergedSettings, mergedKeys } = mergeRegistrationInto(existingSettings);
223
- merged.push(...mergedKeys);
224
-
225
- // Inject ARIA_HARNESS_URL env into settings.json if the caller specified
226
- // a harness URL override (clients on private deployments).
227
- if (opts.harnessUrl) {
228
- if (!mergedSettings.env || typeof mergedSettings.env !== 'object') {
229
- mergedSettings.env = {};
230
- }
231
- (mergedSettings.env as Record<string, string>).ARIA_HARNESS_URL = opts.harnessUrl;
232
- if (!merged.includes('env.ARIA_HARNESS_URL')) merged.push('env.ARIA_HARNESS_URL');
233
- }
234
-
235
- // Always write settings.json (even if no merges) so the schema field is set.
236
- if (!('$schema' in mergedSettings)) {
237
- mergedSettings['$schema'] = 'https://json.schemastore.org/claude-code-settings.json';
238
- }
239
-
240
- writeFileSync(settingsPath, JSON.stringify(mergedSettings, null, 2) + '\n', { mode: 0o600 });
241
-
242
- return {
243
- ok: true,
244
- installed,
245
- merged,
246
- backupsCreated,
247
- settingsPath,
248
- };
249
- } catch (err) {
250
- return {
251
- ok: false,
252
- installed,
253
- merged,
254
- backupsCreated,
255
- settingsPath,
256
- error: err instanceof Error ? err.message : String(err),
257
- };
258
- }
259
- }
@@ -1,207 +0,0 @@
1
- // onboarding-wizard.ts — interactive self-service onboarding for `aria`
2
- // (no args) when ~/.aria/license.json is missing.
3
- //
4
- // Flow:
5
- // 1. Greet — first-person Aria voice
6
- // 2. Collect email (validated shape, NOT verified via code in v0)
7
- // 3. Collect tenant_id (lowercase + hyphens only)
8
- // 4. Collect tier (free / pro / enterprise)
9
- // 5. Collect LLM provider + API key
10
- // 6. POST /api/onboarding/self-issue (server validates LLM key by
11
- // hitting the provider's identity endpoint, then issues license)
12
- // 7. Persist license to ~/.aria/license.json mode 0600
13
- // 8. Persist provider/model/key to ~/.aria/config.json mode 0600
14
- // 9. Auto-run installHooks() to bind Claude Code to the harness
15
- //
16
- // Email-verify-code is deferred to Phase 11 (no SMTP wired tonight).
17
- // The wizard collects email so future re-verify works without re-onboarding.
18
- //
19
- // Direction: Hamza 2026-04-26 — "burn through onboarding with quality and
20
- // USE THE HARNESS PLEASE". This wizard ships as v0; full onboarding (email
21
- // verify + Anthropic OAuth + per-tenant usage tracking) lands in Phase 11.
22
-
23
- import { createInterface } from 'node:readline';
24
- import { writeFileSync, existsSync, mkdirSync } from 'node:fs';
25
- import { homedir } from 'node:os';
26
- import { join } from 'node:path';
27
- import { installHooks } from './install-hooks.js';
28
-
29
- const HARNESS_URL = process.env.ARIA_HARNESS_BASE_URL ?? 'https://harness.ariasos.com';
30
- const ARIA_DIR = join(homedir(), '.aria');
31
- const LICENSE_PATH = join(ARIA_DIR, 'license.json');
32
- const CONFIG_PATH = join(ARIA_DIR, 'config.json');
33
-
34
- type Provider = 'anthropic' | 'openai' | 'deepseek' | 'google' | 'openrouter' | 'ollama';
35
- type Tier = 'free' | 'pro' | 'enterprise';
36
-
37
- interface SelfIssueResponse {
38
- ok: boolean;
39
- license?: { token: string; jti: string; tier: string; expires_at: string };
40
- claims?: Record<string, unknown>;
41
- error?: string;
42
- }
43
-
44
- function prompt(rl: ReturnType<typeof createInterface>, question: string, hidden = false): Promise<string> {
45
- return new Promise((resolve) => {
46
- if (hidden) {
47
- // Crude hidden-input — node's readline doesn't natively mask; we just
48
- // prompt and accept. For Phase 11 we add proper masking via raw mode.
49
- process.stdout.write(question);
50
- const onData = (chunk: Buffer): void => {
51
- process.stdin.removeListener('data', onData);
52
- resolve(chunk.toString().trim());
53
- };
54
- process.stdin.once('data', onData);
55
- } else {
56
- rl.question(question, (answer) => resolve(answer.trim()));
57
- }
58
- });
59
- }
60
-
61
- function isValidEmail(email: string): boolean {
62
- return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
63
- }
64
-
65
- function isValidTenantId(tenant: string): boolean {
66
- return /^[a-z0-9][a-z0-9-]{1,40}$/.test(tenant);
67
- }
68
-
69
- export async function runOnboardingWizard(): Promise<{ ok: boolean; error?: string }> {
70
- const rl = createInterface({
71
- input: process.stdin,
72
- output: process.stdout,
73
- terminal: true,
74
- });
75
-
76
- try {
77
- console.log('');
78
- console.log(" Hi, I'm Aria. I don't see a license on this machine — let me set you up.");
79
- console.log('');
80
- console.log(" Three minutes, four questions. I'll handle the rest.");
81
- console.log('');
82
-
83
- // ── Step 1: email ──
84
- let email = '';
85
- while (!isValidEmail(email)) {
86
- email = await prompt(rl, ' Email: ');
87
- if (!isValidEmail(email)) {
88
- console.log(" That doesn't look like a valid email. Try again.");
89
- }
90
- }
91
-
92
- // ── Step 2: LLM provider ──
93
- // tenant_id is auto-generated server-side from email domain + random
94
- // suffix; no client prompt needed. tier defaults to 'pro' per
95
- // current pricing policy (Hamza 2026-04-26: "set any new memory for
96
- // now to pro"). Both moved out of the wizard for minimal-friction UX.
97
- const providerOptions: Provider[] = ['anthropic', 'openai', 'deepseek', 'google', 'openrouter', 'ollama'];
98
- let provider: Provider | '' = '';
99
- while (!providerOptions.includes(provider as Provider)) {
100
- const p = (await prompt(rl, ` Which LLM provider? [${providerOptions.join(' / ')}]: `)).toLowerCase();
101
- if (providerOptions.includes(p as Provider)) {
102
- provider = p as Provider;
103
- } else {
104
- console.log(` I don't recognize "${p}". Pick one of: ${providerOptions.join(', ')}.`);
105
- }
106
- }
107
-
108
- // ── Step 5: API key ──
109
- let llmKey = '';
110
- if (provider === 'ollama') {
111
- llmKey = 'local';
112
- console.log(' (Ollama is local — no API key needed.)');
113
- } else {
114
- while (!llmKey) {
115
- llmKey = await prompt(rl, ` Paste your ${provider} API key: `);
116
- if (!llmKey) console.log(' I need the key to set up your provider.');
117
- }
118
- }
119
-
120
- // ── Step 6: POST to server ──
121
- console.log('');
122
- console.log(" Validating your key with the provider...");
123
- let response: SelfIssueResponse;
124
- try {
125
- const resp = await fetch(`${HARNESS_URL}/api/onboarding/self-issue`, {
126
- method: 'POST',
127
- headers: { 'Content-Type': 'application/json' },
128
- // tenant_id omitted — server auto-generates from email domain.
129
- // tier omitted — server defaults to 'pro'.
130
- body: JSON.stringify({ email, provider, llm_key: llmKey }),
131
- });
132
- response = await resp.json() as SelfIssueResponse;
133
- if (!resp.ok || !response.ok || !response.license) {
134
- console.log(` ${response.error || `Server returned ${resp.status} — try again later.`}`);
135
- return { ok: false, error: response.error };
136
- }
137
- } catch (err) {
138
- const msg = err instanceof Error ? err.message : String(err);
139
- console.log(` I couldn't reach the server: ${msg}`);
140
- return { ok: false, error: msg };
141
- }
142
-
143
- // ── Step 7: persist license ──
144
- if (!existsSync(ARIA_DIR)) mkdirSync(ARIA_DIR, { recursive: true, mode: 0o700 });
145
- // tenant_id is whatever the server auto-generated (or what the caller
146
- // passed). Read it back from the license claims.
147
- const serverTenantId = (response.claims?.tenant_id as string | undefined) ?? response.license.jti;
148
- const licenseRecord = {
149
- ...response.claims,
150
- harnessToken: response.license.token,
151
- jti: response.license.jti,
152
- tier: response.license.tier,
153
- exp: response.claims?.exp,
154
- sub: response.claims?.sub ?? serverTenantId,
155
- email,
156
- issuedAt: new Date().toISOString(),
157
- };
158
- writeFileSync(LICENSE_PATH, JSON.stringify(licenseRecord, null, 2) + '\n', { mode: 0o600 });
159
-
160
- // ── Step 8: persist provider/key config ──
161
- // By this point the while-loop above has exited with a valid Provider —
162
- // narrow the union type for TypeScript.
163
- const validatedProvider = provider as Provider;
164
- const configRecord = {
165
- model: { provider: validatedProvider, model: defaultModelFor(validatedProvider), apiKey: llmKey },
166
- tenantId: serverTenantId,
167
- email,
168
- };
169
- writeFileSync(CONFIG_PATH, JSON.stringify(configRecord, null, 2) + '\n', { mode: 0o600 });
170
-
171
- // ── Step 9: install hooks ──
172
- console.log('');
173
- console.log(" License issued. Saving your config and binding my gates to your Claude Code...");
174
- const hookResult = await installHooks({ force: false });
175
- if (!hookResult.ok) {
176
- console.log(` License saved, but I couldn't install the gates: ${hookResult.error}`);
177
- console.log(" Run 'aria install-hooks' manually when you're ready.");
178
- } else {
179
- console.log(` Done. I've installed ${hookResult.installed.length} gate(s) into ~/.claude/hooks and merged them into your settings.json.`);
180
- }
181
-
182
- rl.close();
183
-
184
- console.log('');
185
- console.log(` You're set up. License jti: ${response.license.jti}, tier: ${response.license.tier}, provider: ${provider}.`);
186
- console.log(` Your tenant id is: ${serverTenantId}`);
187
- console.log(" Open a fresh Claude Code session — every Bash, Edit, Write, and Stop event now runs through my cognition gates.");
188
- console.log(" Or talk to me directly: just type 'aria' again.");
189
- console.log('');
190
-
191
- return { ok: true };
192
- } finally {
193
- rl.close();
194
- }
195
- }
196
-
197
- function defaultModelFor(provider: Provider): string {
198
- const defaults: Record<Provider, string> = {
199
- anthropic: 'claude-sonnet-4-20250514',
200
- openai: 'gpt-4o',
201
- deepseek: 'deepseek-chat',
202
- google: 'gemini-2.5-pro-preview-05-06',
203
- openrouter: 'openai/gpt-4o',
204
- ollama: 'llama3',
205
- };
206
- return defaults[provider];
207
- }