@aria_asi/cli 0.2.25 → 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 +111 -21
- 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 +317 -0
- package/dist/sdk/index.js +827 -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 +267 -0
- package/hooks/aria-cognition-substrate-binding.mjs +676 -0
- package/hooks/aria-discovery-record.mjs +101 -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 +84 -0
- package/hooks/aria-pre-emit-dryrun.mjs +294 -0
- package/hooks/aria-pre-tool-gate.mjs +985 -40
- 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 +840 -75
- 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 +115 -26
- 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
|
@@ -36,6 +36,23 @@ const HOOK_FILES = [
|
|
|
36
36
|
// Pre-text gate — validates state-dependent claims in prose against
|
|
37
37
|
// probe evidence before emission. Closes "WHEN TO LOOK before speaking" gap.
|
|
38
38
|
'aria-pre-text-gate.mjs',
|
|
39
|
+
// Discovery-ledger write primitive (#83) — sub-agents pipe findings here;
|
|
40
|
+
// outcome-record fires on every state-mutating tool PostToolUse.
|
|
41
|
+
'aria-discovery-record.mjs',
|
|
42
|
+
'aria-outcome-record.mjs',
|
|
43
|
+
// Substrate-binding gate — validates cognition lenses cite real loaded
|
|
44
|
+
// substrate (axioms, frames, memories) not forged/generic anchors.
|
|
45
|
+
// Writes ~/.claude/.aria-loaded-substrate.json manifest (#142).
|
|
46
|
+
'aria-cognition-substrate-binding.mjs',
|
|
47
|
+
// Repo-side doctrine gate — scans edited/staged source files for
|
|
48
|
+
// mock/stub/pending semantics in doctrine-bound packages.
|
|
49
|
+
'aria-repo-doctrine-gate.mjs',
|
|
50
|
+
// Pre-emit dry-run validator (#140) — model self-checks draft against
|
|
51
|
+
// substrate-binding + drift-triggers before emit. CLI tool, not auto-hook.
|
|
52
|
+
'aria-pre-emit-dryrun.mjs',
|
|
53
|
+
];
|
|
54
|
+
const HOOK_DIRS = [
|
|
55
|
+
'lib',
|
|
39
56
|
];
|
|
40
57
|
// Compiled location: <pkg>/dist/aria-connector/src/connectors/claude-code.js
|
|
41
58
|
// (tsc preserves the src/ rooted layout under outDir). From this file:
|
|
@@ -53,7 +70,12 @@ const HOOK_FILES = [
|
|
|
53
70
|
// the fix lands in the same turn as the discovery.
|
|
54
71
|
function packageHooksDir(): string {
|
|
55
72
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
56
|
-
|
|
73
|
+
const candidates = [
|
|
74
|
+
path.resolve(here, '..', '..', '..', '..', 'hooks'),
|
|
75
|
+
path.resolve(here, '..', '..', '..', 'assets', 'hooks'),
|
|
76
|
+
];
|
|
77
|
+
const found = candidates.find((candidate) => existsSync(candidate));
|
|
78
|
+
return found || candidates[0];
|
|
57
79
|
}
|
|
58
80
|
|
|
59
81
|
function packageSdkDir(): string {
|
|
@@ -162,15 +184,35 @@ const HOOKS_BLOCK = {
|
|
|
162
184
|
}],
|
|
163
185
|
},
|
|
164
186
|
],
|
|
165
|
-
PostToolUse: [
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
187
|
+
PostToolUse: [
|
|
188
|
+
{
|
|
189
|
+
matcher: 'Agent',
|
|
190
|
+
hooks: [{
|
|
191
|
+
type: 'command',
|
|
192
|
+
command: 'node $HOME/.claude/hooks/aria-agent-ledger-merge.mjs',
|
|
193
|
+
timeout: 8,
|
|
194
|
+
statusMessage: 'Merging sub-agent ledger...',
|
|
195
|
+
}],
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
matcher: 'Bash|Edit|Write|NotebookEdit',
|
|
199
|
+
hooks: [
|
|
200
|
+
{
|
|
201
|
+
type: 'command',
|
|
202
|
+
command: 'node $HOME/.claude/hooks/aria-repo-doctrine-gate.mjs',
|
|
203
|
+
timeout: 5,
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
// Outcome-record: fires on every state-mutating tool to accumulate the
|
|
207
|
+
// outcome ledger (Sonnet H's #76 endpoint). Fire-and-forget — HTTP
|
|
208
|
+
// failures in the hook do not block the tool pipeline.
|
|
209
|
+
type: 'command',
|
|
210
|
+
command: 'node $HOME/.claude/hooks/aria-outcome-record.mjs',
|
|
211
|
+
timeout: 3,
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
},
|
|
215
|
+
],
|
|
174
216
|
Stop: [{
|
|
175
217
|
// Stop gate — text-decision boundary. Reflexive replies fail this
|
|
176
218
|
// gate the same way reflexive Bash does. Mirrors PreToolUse
|
|
@@ -180,6 +222,11 @@ const HOOKS_BLOCK = {
|
|
|
180
222
|
// against probe evidence in this turn's tool results. Closes the
|
|
181
223
|
// "WHEN TO LOOK before speaking" gap left open by both existing gates.
|
|
182
224
|
hooks: [
|
|
225
|
+
{
|
|
226
|
+
type: 'command',
|
|
227
|
+
command: 'node $HOME/.claude/hooks/aria-cognition-substrate-binding.mjs',
|
|
228
|
+
timeout: 3,
|
|
229
|
+
},
|
|
183
230
|
{
|
|
184
231
|
type: 'command',
|
|
185
232
|
command: 'node $HOME/.claude/hooks/aria-stop-gate.mjs',
|
|
@@ -200,6 +247,25 @@ function installHooks(claudeDir: string, logs: string[], opts: { force?: boolean
|
|
|
200
247
|
mkdirSync(hooksTargetDir, { recursive: true, mode: 0o700 });
|
|
201
248
|
}
|
|
202
249
|
const sourceDir = packageHooksDir();
|
|
250
|
+
for (const dirName of HOOK_DIRS) {
|
|
251
|
+
const srcDir = path.join(sourceDir, dirName);
|
|
252
|
+
if (!existsSync(srcDir)) continue;
|
|
253
|
+
const dstDir = path.join(hooksTargetDir, dirName);
|
|
254
|
+
if (!existsSync(dstDir)) {
|
|
255
|
+
mkdirSync(dstDir, { recursive: true, mode: 0o700 });
|
|
256
|
+
}
|
|
257
|
+
for (const child of readdirSync(srcDir)) {
|
|
258
|
+
const src = path.join(srcDir, child);
|
|
259
|
+
const stat = statSync(src);
|
|
260
|
+
if (!stat.isFile()) continue;
|
|
261
|
+
const dst = path.join(dstDir, child);
|
|
262
|
+
copyFileSync(src, dst);
|
|
263
|
+
if (child.endsWith('.mjs') || child.endsWith('.js')) {
|
|
264
|
+
try { chmodSync(dst, 0o755); } catch {}
|
|
265
|
+
}
|
|
266
|
+
logs.push(`Installed hook helper: ${dirName}/${child}`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
203
269
|
for (const name of HOOK_FILES) {
|
|
204
270
|
const src = path.join(sourceDir, name);
|
|
205
271
|
if (!existsSync(src)) {
|
|
@@ -277,29 +343,34 @@ function wireHooksBlock(settings: Record<string, unknown>, logs: string[]): void
|
|
|
277
343
|
}
|
|
278
344
|
const hooks = settings.hooks as Record<string, unknown[]>;
|
|
279
345
|
let mergedEvents = 0;
|
|
346
|
+
|
|
347
|
+
const isManagedAriaCommand = (command: string): boolean =>
|
|
348
|
+
command.includes('$HOME/.claude/hooks/aria-');
|
|
349
|
+
|
|
350
|
+
const isSameManagedEntry = (entry: unknown, matcher: string, commands: string[]): boolean => {
|
|
351
|
+
if (typeof entry !== 'object' || entry === null) return false;
|
|
352
|
+
const eMatcher = (entry as { matcher?: string }).matcher ?? '';
|
|
353
|
+
if (eMatcher !== matcher) return false;
|
|
354
|
+
const eCommands = ((entry as { hooks?: Array<{ command?: string }> }).hooks ?? [])
|
|
355
|
+
.map((h) => h.command)
|
|
356
|
+
.filter((c): c is string => typeof c === 'string');
|
|
357
|
+
if (eCommands.length === 0) return false;
|
|
358
|
+
return eCommands.every(isManagedAriaCommand) || commands.every((c) => eCommands.includes(c));
|
|
359
|
+
};
|
|
360
|
+
|
|
280
361
|
for (const [event, ourEntries] of Object.entries(HOOKS_BLOCK)) {
|
|
281
362
|
const existingEntries = Array.isArray(hooks[event]) ? hooks[event] : [];
|
|
363
|
+
const normalizedEntries = [...existingEntries];
|
|
282
364
|
for (const ourEntry of ourEntries) {
|
|
283
365
|
const ourMatcher = (ourEntry as { matcher?: string }).matcher ?? '';
|
|
284
366
|
const ourCommands = ((ourEntry as { hooks?: Array<{ command?: string }> }).hooks ?? [])
|
|
285
367
|
.map((h) => h.command)
|
|
286
368
|
.filter((c): c is string => typeof c === 'string');
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
if (typeof e !== 'object' || e === null) return false;
|
|
291
|
-
const eMatcher = (e as { matcher?: string }).matcher ?? '';
|
|
292
|
-
if (eMatcher !== ourMatcher) return false;
|
|
293
|
-
const eCommands = ((e as { hooks?: Array<{ command?: string }> }).hooks ?? [])
|
|
294
|
-
.map((h) => h.command)
|
|
295
|
-
.filter((c): c is string => typeof c === 'string');
|
|
296
|
-
return ourCommands.every((c) => eCommands.includes(c));
|
|
297
|
-
});
|
|
298
|
-
if (!alreadyPresent) {
|
|
299
|
-
existingEntries.push(ourEntry);
|
|
300
|
-
}
|
|
369
|
+
const filteredEntries = normalizedEntries.filter((e) => !isSameManagedEntry(e, ourMatcher, ourCommands));
|
|
370
|
+
normalizedEntries.length = 0;
|
|
371
|
+
normalizedEntries.push(...filteredEntries, ourEntry);
|
|
301
372
|
}
|
|
302
|
-
hooks[event] =
|
|
373
|
+
hooks[event] = normalizedEntries;
|
|
303
374
|
mergedEvents++;
|
|
304
375
|
}
|
|
305
376
|
settings.hooks = hooks;
|
|
@@ -307,9 +378,25 @@ function wireHooksBlock(settings: Record<string, unknown>, logs: string[]): void
|
|
|
307
378
|
if (!settings.$schema) {
|
|
308
379
|
settings.$schema = 'https://json.schemastore.org/claude-code-settings.json';
|
|
309
380
|
}
|
|
310
|
-
logs.push(`Wired hooks into settings.json (${mergedEvents} events: SessionStart, UserPromptSubmit, PreToolUse [cognition+memory-gate+Agent-handoff], PostToolUse [Agent-ledger-merge], Stop) — merge-safe, preserves third-party entries`);
|
|
381
|
+
logs.push(`Wired hooks into settings.json (${mergedEvents} events: SessionStart, UserPromptSubmit, PreToolUse [cognition+memory-gate+Agent-handoff], PostToolUse [repo-doctrine-gate + Agent-ledger-merge + outcome-record], Stop) — merge-safe, preserves third-party entries`);
|
|
311
382
|
}
|
|
312
383
|
|
|
384
|
+
// Layer 2 (#84): hard prefix injected into every Agent dispatch so sub-agents
|
|
385
|
+
// know to load the harness packet before ANY tool call. This text appears in
|
|
386
|
+
// the system-prompt-prefix which Claude Code copies into spawned Agent contexts.
|
|
387
|
+
const ARIA_HARNESS_BINDING_PREFIX = `[ARIA_HARNESS_BINDING — MANDATORY FIRST ACTION]
|
|
388
|
+
Before any tool call, Read the harness packet at: $ARIA_HARNESS_PACKET_PATH
|
|
389
|
+
(path is also in your environment as ARIA_HARNESS_PACKET_PATH variable)
|
|
390
|
+
Cite it in your first cognition block — reference at least one axiom + one frame + one memory class from the packet.
|
|
391
|
+
Without packet-citation in your first cognition block, your output will be rejected by aria-pre-tool-gate.mjs in your sub-process.
|
|
392
|
+
[/ARIA_HARNESS_BINDING]
|
|
393
|
+
|
|
394
|
+
[ARIA_DISCOVERY_RECORDING — when you find a defect, doctrine violation, or notable observation during work]
|
|
395
|
+
Record findings to your session ledger via:
|
|
396
|
+
echo '{"text":"<finding>","kind":"defect|observation|principle","refs":["<file:line>"]}' | node $HOME/.claude/hooks/aria-discovery-record.mjs
|
|
397
|
+
This makes findings visible to the parent session's ledger-merge hook + the auto-fix spawner.
|
|
398
|
+
[/ARIA_DISCOVERY_RECORDING]`;
|
|
399
|
+
|
|
313
400
|
function buildAriaSystemBlock(config: AriaConfig): string {
|
|
314
401
|
const repoList = config.repositories.map((r) => `- ${r.name} (${r.path})`).join('\n');
|
|
315
402
|
const schemaText = Object.entries(config.schemaImages)
|
|
@@ -322,6 +409,8 @@ You are augmented with Aria's cognitive harness. This provides:
|
|
|
322
409
|
- Garden memory: persistent project memory across sessions
|
|
323
410
|
- 8-lens cognition: multi-perspective analysis for every decision
|
|
324
411
|
|
|
412
|
+
${ARIA_HARNESS_BINDING_PREFIX}
|
|
413
|
+
|
|
325
414
|
[SELF-GATE PROTOCOL]
|
|
326
415
|
Before emitting any claim, verify against these hard constraints:
|
|
327
416
|
1. Truth over deception — always.
|
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
import { execFileSync } from 'child_process';
|
|
2
|
+
import { createHash } from 'crypto';
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
4
|
+
import { homedir } from 'os';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import type { AriaConfig, LinkedRepo } from '../config.js';
|
|
8
|
+
import { loadConfig, saveConfig } from '../config.js';
|
|
9
|
+
import { scanCodebase, schemaImageToText, watchCodebase } from '../codebase-scanner.js';
|
|
10
|
+
|
|
11
|
+
const ARIA_DIR = path.join(homedir(), '.aria');
|
|
12
|
+
const BIN_DIR = path.join(ARIA_DIR, 'bin');
|
|
13
|
+
const ENV_PATH = path.join(ARIA_DIR, 'codebase-awareness.env');
|
|
14
|
+
const STATE_PATH = path.join(ARIA_DIR, 'codebase-awareness-state.json');
|
|
15
|
+
const INDEX_PATH = path.join(ARIA_DIR, 'codebase-awareness-index.json');
|
|
16
|
+
|
|
17
|
+
type AwarenessStatus = 'idle' | 'watching' | 'scanning' | 'error';
|
|
18
|
+
|
|
19
|
+
interface RepoSnapshot {
|
|
20
|
+
path: string;
|
|
21
|
+
name: string;
|
|
22
|
+
scanHash: string;
|
|
23
|
+
lastScan: string;
|
|
24
|
+
fileCount: number;
|
|
25
|
+
language: string;
|
|
26
|
+
framework: string | null;
|
|
27
|
+
packageManager: string | null;
|
|
28
|
+
database: string | null;
|
|
29
|
+
orm: string | null;
|
|
30
|
+
architecture: string | null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface AwarenessState {
|
|
34
|
+
status: AwarenessStatus;
|
|
35
|
+
watchedRepos: string[];
|
|
36
|
+
repoSnapshots: RepoSnapshot[];
|
|
37
|
+
lastError: string | null;
|
|
38
|
+
updatedAt: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function connectorPackageRoot(): string {
|
|
42
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
43
|
+
const candidates = [
|
|
44
|
+
path.resolve(here, '..', '..'),
|
|
45
|
+
path.resolve(here, '..', '..', '..', '..'),
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
for (const candidate of candidates) {
|
|
49
|
+
if (existsSync(path.join(candidate, 'bin', 'aria.js')) && existsSync(path.join(candidate, 'package.json'))) {
|
|
50
|
+
return candidate;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return candidates[candidates.length - 1];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function writeWrapper(binPath: string, args: string[]): void {
|
|
58
|
+
const ariaBin = path.join(connectorPackageRoot(), 'bin', 'aria.js');
|
|
59
|
+
writeFileSync(
|
|
60
|
+
binPath,
|
|
61
|
+
`#!/usr/bin/env bash\nexec node "${ariaBin}" ${args.join(' ')} "$@"\n`,
|
|
62
|
+
{ mode: 0o755 },
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function defaultState(): AwarenessState {
|
|
67
|
+
return {
|
|
68
|
+
status: 'idle',
|
|
69
|
+
watchedRepos: [],
|
|
70
|
+
repoSnapshots: [],
|
|
71
|
+
lastError: null,
|
|
72
|
+
updatedAt: new Date(0).toISOString(),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function readState(): AwarenessState {
|
|
77
|
+
try {
|
|
78
|
+
const parsed = JSON.parse(readFileSync(STATE_PATH, 'utf8')) as Partial<AwarenessState>;
|
|
79
|
+
return {
|
|
80
|
+
status: parsed.status || 'idle',
|
|
81
|
+
watchedRepos: Array.isArray(parsed.watchedRepos) ? parsed.watchedRepos : [],
|
|
82
|
+
repoSnapshots: Array.isArray(parsed.repoSnapshots) ? parsed.repoSnapshots as RepoSnapshot[] : [],
|
|
83
|
+
lastError: parsed.lastError || null,
|
|
84
|
+
updatedAt: parsed.updatedAt || new Date(0).toISOString(),
|
|
85
|
+
};
|
|
86
|
+
} catch {
|
|
87
|
+
return defaultState();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function writeState(update: Partial<AwarenessState>): AwarenessState {
|
|
92
|
+
const current = readState();
|
|
93
|
+
const next: AwarenessState = {
|
|
94
|
+
...current,
|
|
95
|
+
...update,
|
|
96
|
+
updatedAt: new Date().toISOString(),
|
|
97
|
+
};
|
|
98
|
+
mkdirSync(ARIA_DIR, { recursive: true, mode: 0o700 });
|
|
99
|
+
writeFileSync(STATE_PATH, JSON.stringify(next, null, 2) + '\n', { mode: 0o600 });
|
|
100
|
+
return next;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function writeIndex(payload: Record<string, unknown>): void {
|
|
104
|
+
mkdirSync(ARIA_DIR, { recursive: true, mode: 0o700 });
|
|
105
|
+
writeFileSync(INDEX_PATH, JSON.stringify(payload, null, 2) + '\n', { mode: 0o600 });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function looksLikeRepoRoot(candidate: string): boolean {
|
|
109
|
+
return existsSync(path.join(candidate, '.git'));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function findRepoRoot(startDir: string): string | null {
|
|
113
|
+
let current = path.resolve(startDir);
|
|
114
|
+
while (true) {
|
|
115
|
+
if (looksLikeRepoRoot(current)) return current;
|
|
116
|
+
const parent = path.dirname(current);
|
|
117
|
+
if (parent === current) return null;
|
|
118
|
+
current = parent;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function resolveRepos(config?: AriaConfig, explicit?: string[], fallbackRepoPath?: string): string[] {
|
|
123
|
+
if (explicit?.length) return explicit.map((repo) => path.resolve(repo)).filter(looksLikeRepoRoot);
|
|
124
|
+
|
|
125
|
+
const envRepos = process.env.ARIA_CODEBASE_AWARENESS_REPOS?.split(path.delimiter)
|
|
126
|
+
.map((repo) => repo.trim())
|
|
127
|
+
.filter(Boolean) || [];
|
|
128
|
+
if (envRepos.length) return envRepos.map((repo) => path.resolve(repo)).filter(looksLikeRepoRoot);
|
|
129
|
+
|
|
130
|
+
const loaded = config || loadConfig();
|
|
131
|
+
const configured = (loaded.repositories || [])
|
|
132
|
+
.map((repo) => path.resolve(repo.path))
|
|
133
|
+
.filter(looksLikeRepoRoot);
|
|
134
|
+
if (configured.length) return configured;
|
|
135
|
+
|
|
136
|
+
if (fallbackRepoPath) {
|
|
137
|
+
const resolvedFallback = findRepoRoot(fallbackRepoPath);
|
|
138
|
+
if (resolvedFallback) return [resolvedFallback];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const cwd = findRepoRoot(process.cwd());
|
|
142
|
+
return cwd ? [cwd] : [];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function hashSchema(text: string): string {
|
|
146
|
+
return createHash('sha256').update(text).digest('hex').slice(0, 16);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function architectureSummary(image: {
|
|
150
|
+
architecture?: unknown;
|
|
151
|
+
}): string | null {
|
|
152
|
+
if (Array.isArray(image.architecture) && image.architecture.length > 0) {
|
|
153
|
+
const first = image.architecture[0];
|
|
154
|
+
if (typeof first === 'string' && first.trim()) return first.trim();
|
|
155
|
+
if (first && typeof first === 'object' && typeof first.pattern === 'string' && first.pattern.trim()) {
|
|
156
|
+
return first.pattern.trim();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (typeof image.architecture === 'string' && image.architecture.trim()) return image.architecture.trim();
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async function applyRepoScan(repoRoot: string): Promise<RepoSnapshot> {
|
|
164
|
+
const image = await scanCodebase(repoRoot);
|
|
165
|
+
const schemaText = schemaImageToText(image);
|
|
166
|
+
const scanHash = hashSchema(schemaText);
|
|
167
|
+
const lastScan = new Date().toISOString();
|
|
168
|
+
|
|
169
|
+
const config = loadConfig();
|
|
170
|
+
const nextRepo: LinkedRepo = {
|
|
171
|
+
path: repoRoot,
|
|
172
|
+
name: image.projectName,
|
|
173
|
+
scanHash,
|
|
174
|
+
lastScan,
|
|
175
|
+
};
|
|
176
|
+
const repositories = [
|
|
177
|
+
...(config.repositories || []).filter((repo) => path.resolve(repo.path) !== repoRoot),
|
|
178
|
+
nextRepo,
|
|
179
|
+
];
|
|
180
|
+
|
|
181
|
+
saveConfig({
|
|
182
|
+
...config,
|
|
183
|
+
repositories,
|
|
184
|
+
schemaImages: {
|
|
185
|
+
...(config.schemaImages || {}),
|
|
186
|
+
[image.projectName]: schemaText,
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const snapshot: RepoSnapshot = {
|
|
191
|
+
path: repoRoot,
|
|
192
|
+
name: image.projectName,
|
|
193
|
+
scanHash,
|
|
194
|
+
lastScan,
|
|
195
|
+
fileCount: image.fileCount,
|
|
196
|
+
language: image.language,
|
|
197
|
+
framework: image.framework || null,
|
|
198
|
+
packageManager: image.packageManager || null,
|
|
199
|
+
database: image.database || null,
|
|
200
|
+
orm: image.orm || null,
|
|
201
|
+
architecture: architectureSummary(image),
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const current = readState();
|
|
205
|
+
const nextSnapshots = [
|
|
206
|
+
snapshot,
|
|
207
|
+
...current.repoSnapshots.filter((entry) => path.resolve(entry.path) !== repoRoot),
|
|
208
|
+
];
|
|
209
|
+
writeState({
|
|
210
|
+
status: 'watching',
|
|
211
|
+
watchedRepos: Array.from(new Set([repoRoot, ...current.watchedRepos])),
|
|
212
|
+
repoSnapshots: nextSnapshots,
|
|
213
|
+
lastError: null,
|
|
214
|
+
});
|
|
215
|
+
writeIndex({
|
|
216
|
+
generatedAt: new Date().toISOString(),
|
|
217
|
+
watchedRepos: Array.from(new Set([repoRoot, ...current.watchedRepos])),
|
|
218
|
+
repoSnapshots: nextSnapshots,
|
|
219
|
+
schemaImages: loadConfig().schemaImages || {},
|
|
220
|
+
});
|
|
221
|
+
return snapshot;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export function readCodebaseAwarenessState(): AwarenessState {
|
|
225
|
+
return readState();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export async function runCodebaseAwarenessScan(options: {
|
|
229
|
+
repos?: string[];
|
|
230
|
+
fallbackRepoPath?: string;
|
|
231
|
+
} = {}): Promise<{ ok: true; repos: RepoSnapshot[] }> {
|
|
232
|
+
const repos = resolveRepos(undefined, options.repos, options.fallbackRepoPath);
|
|
233
|
+
if (!repos.length) {
|
|
234
|
+
writeState({ status: 'error', watchedRepos: [], lastError: 'No git repositories configured for codebase awareness.' });
|
|
235
|
+
throw new Error('No git repositories configured for codebase awareness.');
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
writeState({ status: 'scanning', watchedRepos: repos, lastError: null });
|
|
239
|
+
const snapshots: RepoSnapshot[] = [];
|
|
240
|
+
for (const repo of repos) {
|
|
241
|
+
snapshots.push(await applyRepoScan(repo));
|
|
242
|
+
}
|
|
243
|
+
writeState({ status: 'watching', watchedRepos: repos, repoSnapshots: snapshots, lastError: null });
|
|
244
|
+
writeIndex({
|
|
245
|
+
generatedAt: new Date().toISOString(),
|
|
246
|
+
watchedRepos: repos,
|
|
247
|
+
repoSnapshots: snapshots,
|
|
248
|
+
schemaImages: loadConfig().schemaImages || {},
|
|
249
|
+
});
|
|
250
|
+
return { ok: true, repos: snapshots };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export async function startCodebaseAwarenessDaemon(options: {
|
|
254
|
+
repos?: string[];
|
|
255
|
+
fallbackRepoPath?: string;
|
|
256
|
+
} = {}): Promise<void> {
|
|
257
|
+
const repos = resolveRepos(undefined, options.repos, options.fallbackRepoPath);
|
|
258
|
+
if (!repos.length) {
|
|
259
|
+
writeState({ status: 'error', watchedRepos: [], lastError: 'No git repositories configured for codebase awareness.' });
|
|
260
|
+
throw new Error('No git repositories configured for codebase awareness.');
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
await runCodebaseAwarenessScan({ repos });
|
|
264
|
+
writeState({ status: 'watching', watchedRepos: repos, lastError: null });
|
|
265
|
+
|
|
266
|
+
for (const repo of repos) {
|
|
267
|
+
watchCodebase(
|
|
268
|
+
repo,
|
|
269
|
+
(image) => {
|
|
270
|
+
const schemaText = schemaImageToText(image);
|
|
271
|
+
const scanHash = hashSchema(schemaText);
|
|
272
|
+
const lastScan = new Date().toISOString();
|
|
273
|
+
const config = loadConfig();
|
|
274
|
+
const repositories = [
|
|
275
|
+
...(config.repositories || []).filter((entry) => path.resolve(entry.path) !== repo),
|
|
276
|
+
{
|
|
277
|
+
path: repo,
|
|
278
|
+
name: image.projectName,
|
|
279
|
+
scanHash,
|
|
280
|
+
lastScan,
|
|
281
|
+
},
|
|
282
|
+
];
|
|
283
|
+
const nextConfig = {
|
|
284
|
+
...config,
|
|
285
|
+
repositories,
|
|
286
|
+
schemaImages: {
|
|
287
|
+
...(config.schemaImages || {}),
|
|
288
|
+
[image.projectName]: schemaText,
|
|
289
|
+
},
|
|
290
|
+
};
|
|
291
|
+
saveConfig(nextConfig);
|
|
292
|
+
|
|
293
|
+
const current = readState();
|
|
294
|
+
const snapshot: RepoSnapshot = {
|
|
295
|
+
path: repo,
|
|
296
|
+
name: image.projectName,
|
|
297
|
+
scanHash,
|
|
298
|
+
lastScan,
|
|
299
|
+
fileCount: image.fileCount,
|
|
300
|
+
language: image.language,
|
|
301
|
+
framework: image.framework || null,
|
|
302
|
+
packageManager: image.packageManager || null,
|
|
303
|
+
database: image.database || null,
|
|
304
|
+
orm: image.orm || null,
|
|
305
|
+
architecture: architectureSummary(image),
|
|
306
|
+
};
|
|
307
|
+
const repoSnapshots = [
|
|
308
|
+
snapshot,
|
|
309
|
+
...current.repoSnapshots.filter((entry) => path.resolve(entry.path) !== repo),
|
|
310
|
+
];
|
|
311
|
+
writeState({
|
|
312
|
+
status: 'watching',
|
|
313
|
+
watchedRepos: repos,
|
|
314
|
+
repoSnapshots,
|
|
315
|
+
lastError: null,
|
|
316
|
+
});
|
|
317
|
+
writeIndex({
|
|
318
|
+
generatedAt: new Date().toISOString(),
|
|
319
|
+
watchedRepos: repos,
|
|
320
|
+
repoSnapshots,
|
|
321
|
+
schemaImages: nextConfig.schemaImages || {},
|
|
322
|
+
});
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
debounceMs: 800,
|
|
326
|
+
pollIntervalMs: 4000,
|
|
327
|
+
onError: ({ error }) => {
|
|
328
|
+
writeState({
|
|
329
|
+
status: 'error',
|
|
330
|
+
watchedRepos: repos,
|
|
331
|
+
lastError: error.message,
|
|
332
|
+
});
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
await new Promise(() => {});
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function writeEnv(repos: string[]): string {
|
|
342
|
+
mkdirSync(ARIA_DIR, { recursive: true, mode: 0o700 });
|
|
343
|
+
writeFileSync(
|
|
344
|
+
ENV_PATH,
|
|
345
|
+
[
|
|
346
|
+
`ARIA_CODEBASE_AWARENESS_REPOS=${repos.join(path.delimiter)}`,
|
|
347
|
+
'',
|
|
348
|
+
].join('\n'),
|
|
349
|
+
{ mode: 0o600 },
|
|
350
|
+
);
|
|
351
|
+
return ENV_PATH;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function installSystemdUserService(logs: string[]): void {
|
|
355
|
+
const systemctlPath = '/bin/systemctl';
|
|
356
|
+
if (process.platform !== 'linux' || !existsSync(systemctlPath)) return;
|
|
357
|
+
|
|
358
|
+
const serviceDir = path.join(homedir(), '.config', 'systemd', 'user');
|
|
359
|
+
const servicePath = path.join(serviceDir, 'aria-codebase-awareness.service');
|
|
360
|
+
mkdirSync(serviceDir, { recursive: true, mode: 0o755 });
|
|
361
|
+
|
|
362
|
+
const unit = [
|
|
363
|
+
'[Unit]',
|
|
364
|
+
'Description=Aria Codebase Awareness',
|
|
365
|
+
'After=network.target',
|
|
366
|
+
'',
|
|
367
|
+
'[Service]',
|
|
368
|
+
'Type=simple',
|
|
369
|
+
`EnvironmentFile=-${ENV_PATH}`,
|
|
370
|
+
`ExecStart=${path.join(BIN_DIR, 'aria-codebase-awareness')} start`,
|
|
371
|
+
'Restart=always',
|
|
372
|
+
'RestartSec=2',
|
|
373
|
+
'',
|
|
374
|
+
'[Install]',
|
|
375
|
+
'WantedBy=default.target',
|
|
376
|
+
'',
|
|
377
|
+
].join('\n');
|
|
378
|
+
|
|
379
|
+
writeFileSync(servicePath, unit, { mode: 0o644 });
|
|
380
|
+
logs.push(`Installed systemd user unit → ${servicePath}`);
|
|
381
|
+
|
|
382
|
+
try {
|
|
383
|
+
execFileSync(systemctlPath, ['--user', 'daemon-reload'], { stdio: 'ignore' });
|
|
384
|
+
execFileSync(systemctlPath, ['--user', 'enable', '--now', 'aria-codebase-awareness.service'], { stdio: 'ignore' });
|
|
385
|
+
logs.push('Enabled and started systemd user service: aria-codebase-awareness.service');
|
|
386
|
+
} catch (error) {
|
|
387
|
+
logs.push(`⚠ codebase awareness service installed but not activated: ${error instanceof Error ? error.message : String(error)}`);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
export async function installCodebaseAwarenessDaemon(config?: AriaConfig, fallbackRepoPath?: string): Promise<string[]> {
|
|
392
|
+
const repos = resolveRepos(config, undefined, fallbackRepoPath);
|
|
393
|
+
const logs: string[] = [];
|
|
394
|
+
if (!repos.length) {
|
|
395
|
+
logs.push('Skipped codebase awareness install: no git repositories configured.');
|
|
396
|
+
return logs;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
mkdirSync(BIN_DIR, { recursive: true, mode: 0o755 });
|
|
400
|
+
const envPath = writeEnv(repos);
|
|
401
|
+
writeWrapper(path.join(BIN_DIR, 'aria-codebase-awareness'), ['codebase-awareness']);
|
|
402
|
+
installSystemdUserService(logs);
|
|
403
|
+
|
|
404
|
+
logs.push(`Installed codebase awareness wrapper → ${path.join(BIN_DIR, 'aria-codebase-awareness')}`);
|
|
405
|
+
logs.push(`Installed codebase awareness env → ${envPath}`);
|
|
406
|
+
logs.push(`Codebase awareness watching ${repos.length} repos`);
|
|
407
|
+
return logs;
|
|
408
|
+
}
|