@nirnex/cli 2.0.3 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/index.js +2 -2
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/query.js +2 -2
- package/dist/commands/query.js.map +1 -1
- package/dist/commands/runtime.d.ts +2 -0
- package/dist/commands/runtime.d.ts.map +1 -0
- package/dist/commands/runtime.js +60 -0
- package/dist/commands/runtime.js.map +1 -0
- package/dist/commands/setup.d.ts +6 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +395 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/status.d.ts +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +151 -20
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/trace.d.ts.map +1 -1
- package/dist/commands/trace.js +74 -1
- package/dist/commands/trace.js.map +1 -1
- package/dist/index.js +21 -10
- package/dist/index.js.map +1 -1
- package/dist/runtime/bootstrap.d.ts +2 -0
- package/dist/runtime/bootstrap.d.ts.map +1 -0
- package/dist/runtime/bootstrap.js +90 -0
- package/dist/runtime/bootstrap.js.map +1 -0
- package/dist/runtime/entry.d.ts +2 -0
- package/dist/runtime/entry.d.ts.map +1 -0
- package/dist/runtime/entry.js +86 -0
- package/dist/runtime/entry.js.map +1 -0
- package/dist/runtime/envelope.d.ts +4 -0
- package/dist/runtime/envelope.d.ts.map +1 -0
- package/dist/runtime/envelope.js +113 -0
- package/dist/runtime/envelope.js.map +1 -0
- package/dist/runtime/guard.d.ts +2 -0
- package/dist/runtime/guard.d.ts.map +1 -0
- package/dist/runtime/guard.js +114 -0
- package/dist/runtime/guard.js.map +1 -0
- package/dist/runtime/session.d.ts +13 -0
- package/dist/runtime/session.d.ts.map +1 -0
- package/dist/runtime/session.js +111 -0
- package/dist/runtime/session.js.map +1 -0
- package/dist/runtime/trace-hook.d.ts +2 -0
- package/dist/runtime/trace-hook.d.ts.map +1 -0
- package/dist/runtime/trace-hook.js +102 -0
- package/dist/runtime/trace-hook.js.map +1 -0
- package/dist/runtime/types.d.ts +108 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +3 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/runtime/validate.d.ts +2 -0
- package/dist/runtime/validate.d.ts.map +1 -0
- package/dist/runtime/validate.js +91 -0
- package/dist/runtime/validate.js.map +1 -0
- package/package.json +1 -1
package/dist/commands/status.js
CHANGED
|
@@ -1,31 +1,162 @@
|
|
|
1
|
-
// Command:
|
|
2
|
-
//
|
|
3
|
-
// and prints a one-line index summary.
|
|
1
|
+
// Command: nirnex status
|
|
2
|
+
// Shows project readiness, index health, and freshness.
|
|
4
3
|
import { openDb, indexStats } from '@nirnex/core';
|
|
5
4
|
import path from 'node:path';
|
|
6
|
-
import { existsSync } from 'node:fs';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
6
|
+
import { execSync } from 'node:child_process';
|
|
7
|
+
function tick(msg) {
|
|
8
|
+
process.stdout.write(` \x1b[32m✔\x1b[0m ${msg}\n`);
|
|
9
|
+
}
|
|
10
|
+
function cross(msg) {
|
|
11
|
+
process.stdout.write(` \x1b[31m✘\x1b[0m ${msg}\n`);
|
|
12
|
+
}
|
|
13
|
+
function warn(msg) {
|
|
14
|
+
process.stdout.write(` \x1b[33m!\x1b[0m ${msg}\n`);
|
|
15
|
+
}
|
|
16
|
+
export function statusCommand(_args) {
|
|
17
|
+
const cwd = process.cwd();
|
|
18
|
+
const configPath = path.join(cwd, 'nirnex.config.json');
|
|
19
|
+
const dbPath = path.join(cwd, '.aidos.db');
|
|
20
|
+
console.log('\n\x1b[1mNirnex Status\x1b[0m\n');
|
|
21
|
+
// Check if project is Nirnex-enabled
|
|
22
|
+
const isEnabled = existsSync(configPath);
|
|
23
|
+
if (!isEnabled) {
|
|
24
|
+
cross('nirnex.config.json not found — project is not Nirnex-enabled');
|
|
25
|
+
console.log('\n Run \x1b[1mnirnex setup\x1b[0m to initialize this project.\n');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
let config = {};
|
|
29
|
+
try {
|
|
30
|
+
config = JSON.parse(readFileSync(configPath, 'utf8'));
|
|
31
|
+
tick(`Project: \x1b[1m${config.projectName ?? path.basename(cwd)}\x1b[0m`);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
warn('nirnex.config.json is malformed');
|
|
35
|
+
}
|
|
36
|
+
// Check .ai/ structure
|
|
37
|
+
const aiDir = path.join(cwd, '.ai');
|
|
38
|
+
existsSync(aiDir)
|
|
39
|
+
? tick('.ai/ workspace present')
|
|
40
|
+
: cross('.ai/ workspace missing — re-run nirnex setup');
|
|
41
|
+
const promptsDir = path.join(aiDir, 'prompts');
|
|
42
|
+
existsSync(path.join(promptsDir, 'analyst.md')) && existsSync(path.join(promptsDir, 'implementer.md'))
|
|
43
|
+
? tick('.ai/prompts/ configured')
|
|
44
|
+
: warn('.ai/prompts/ missing analyst.md or implementer.md');
|
|
45
|
+
// Check index
|
|
46
|
+
const dbExists = existsSync(dbPath);
|
|
47
|
+
if (!dbExists) {
|
|
48
|
+
cross('Index not found — run \x1b[1mnirnex index --rebuild\x1b[0m');
|
|
13
49
|
}
|
|
14
|
-
else
|
|
15
|
-
|
|
50
|
+
else {
|
|
51
|
+
try {
|
|
52
|
+
const db = openDb(dbPath);
|
|
53
|
+
const stats = indexStats(db);
|
|
54
|
+
db.close();
|
|
55
|
+
if (stats.moduleCount === 0) {
|
|
56
|
+
warn(`Index empty (0 modules) — run \x1b[1mnirnex index --rebuild\x1b[0m`);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
tick(`Index: ${stats.moduleCount} modules, ${stats.edgeCount} edges, schema v${stats.schemaVersion}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
warn(`Index read error: ${e instanceof Error ? e.message : String(e)}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Check freshness
|
|
67
|
+
try {
|
|
68
|
+
const currentHead = execSync('git rev-parse HEAD', { cwd, encoding: 'utf8' }).trim();
|
|
69
|
+
if (dbExists) {
|
|
70
|
+
try {
|
|
71
|
+
const db = openDb(dbPath);
|
|
72
|
+
const meta = db.prepare('SELECT value FROM _meta WHERE key = ?').get('commit_hash');
|
|
73
|
+
db.close();
|
|
74
|
+
if (meta?.value === currentHead) {
|
|
75
|
+
tick('Index is fresh (matches current HEAD)');
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
warn('Index is stale — run \x1b[1mnirnex index\x1b[0m to refresh');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch { }
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// not a git repo or git not available
|
|
86
|
+
}
|
|
87
|
+
// Check git hook
|
|
88
|
+
const hookPath = path.join(cwd, '.git', 'hooks', 'post-commit');
|
|
89
|
+
existsSync(hookPath)
|
|
90
|
+
? tick('Git post-commit hook installed')
|
|
91
|
+
: warn('Git post-commit hook not installed (index may drift)');
|
|
92
|
+
// Check Claude hooks
|
|
93
|
+
console.log('');
|
|
94
|
+
console.log('\x1b[1mClaude Hooks\x1b[0m');
|
|
95
|
+
const claudeSettingsPath = path.join(cwd, '.claude', 'settings.json');
|
|
96
|
+
if (!existsSync(claudeSettingsPath)) {
|
|
97
|
+
warn('.claude/settings.json not found — run nirnex setup to install hooks');
|
|
16
98
|
}
|
|
17
99
|
else {
|
|
18
|
-
|
|
100
|
+
try {
|
|
101
|
+
const settings = JSON.parse(readFileSync(claudeSettingsPath, 'utf8'));
|
|
102
|
+
settings.hooks
|
|
103
|
+
? tick('.claude/settings.json hook bindings present')
|
|
104
|
+
: warn('.claude/settings.json has no hooks section — re-run nirnex setup');
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
warn('.claude/settings.json is malformed');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const claudeHooks = [
|
|
111
|
+
'nirnex-bootstrap.sh',
|
|
112
|
+
'nirnex-entry.sh',
|
|
113
|
+
'nirnex-guard.sh',
|
|
114
|
+
'nirnex-trace.sh',
|
|
115
|
+
'nirnex-validate.sh',
|
|
116
|
+
];
|
|
117
|
+
const hooksDir = path.join(cwd, '.claude', 'hooks');
|
|
118
|
+
let hooksMissing = 0;
|
|
119
|
+
for (const h of claudeHooks) {
|
|
120
|
+
if (!existsSync(path.join(hooksDir, h)))
|
|
121
|
+
hooksMissing++;
|
|
19
122
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
123
|
+
hooksMissing === 0
|
|
124
|
+
? tick('All 5 Claude hook scripts present')
|
|
125
|
+
: warn(`${hooksMissing} Claude hook script(s) missing in .claude/hooks/ — re-run nirnex setup`);
|
|
126
|
+
// Check runtime state
|
|
127
|
+
const runtimeDir = path.join(cwd, '.ai-index', 'runtime');
|
|
128
|
+
const sessionsDir = path.join(runtimeDir, 'sessions');
|
|
129
|
+
const envelopesDir = path.join(runtimeDir, 'envelopes');
|
|
130
|
+
if (existsSync(sessionsDir)) {
|
|
131
|
+
try {
|
|
132
|
+
const sessions = readdirSync(sessionsDir).filter(f => f.endsWith('.json'));
|
|
133
|
+
tick(`Runtime sessions: ${sessions.length} recorded`);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
warn('Could not read runtime sessions dir');
|
|
137
|
+
}
|
|
26
138
|
}
|
|
27
139
|
else {
|
|
28
|
-
|
|
140
|
+
tick('Runtime sessions: none yet (hooks not yet triggered)');
|
|
141
|
+
}
|
|
142
|
+
if (existsSync(envelopesDir)) {
|
|
143
|
+
try {
|
|
144
|
+
const envelopes = readdirSync(envelopesDir).filter(f => f.endsWith('.json'));
|
|
145
|
+
const activeCount = envelopes.filter(f => {
|
|
146
|
+
try {
|
|
147
|
+
const e = JSON.parse(readFileSync(path.join(envelopesDir, f), 'utf8'));
|
|
148
|
+
return e.status === 'active';
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
}).length;
|
|
154
|
+
tick(`Task envelopes: ${envelopes.length} total, ${activeCount} active`);
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
warn('Could not read envelopes dir');
|
|
158
|
+
}
|
|
29
159
|
}
|
|
160
|
+
console.log('');
|
|
30
161
|
}
|
|
31
162
|
//# sourceMappingURL=status.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/commands/trace.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/commands/trace.ts"],"names":[],"mappings":"AA6BA,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAiEjD"}
|
package/dist/commands/trace.js
CHANGED
|
@@ -1,4 +1,77 @@
|
|
|
1
|
+
// Command: nirnex trace
|
|
2
|
+
// View execution traces from .ai-index/traces/
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
import { listTraces, readTrace } from '@nirnex/core/dist/trace.js';
|
|
6
|
+
function tick(msg) {
|
|
7
|
+
process.stdout.write(` \x1b[32m✔\x1b[0m ${msg}\n`);
|
|
8
|
+
}
|
|
9
|
+
function info(msg) {
|
|
10
|
+
process.stdout.write(` \x1b[90m·\x1b[0m ${msg}\n`);
|
|
11
|
+
}
|
|
12
|
+
function warn(msg) {
|
|
13
|
+
process.stdout.write(` \x1b[33m!\x1b[0m ${msg}\n`);
|
|
14
|
+
}
|
|
15
|
+
const TRACE_USAGE = `
|
|
16
|
+
nirnex trace [options]
|
|
17
|
+
|
|
18
|
+
Options:
|
|
19
|
+
--last Show the most recent trace in full
|
|
20
|
+
--list List recent traces (default)
|
|
21
|
+
--id <trace_id> Show a specific trace by ID
|
|
22
|
+
--limit <n> Number of traces to list (default: 20)
|
|
23
|
+
`.trimStart();
|
|
1
24
|
export function traceCommand(args) {
|
|
2
|
-
|
|
25
|
+
const cwd = process.cwd();
|
|
26
|
+
const configPath = path.join(cwd, 'nirnex.config.json');
|
|
27
|
+
if (!existsSync(configPath)) {
|
|
28
|
+
warn('Not a Nirnex project. Run nirnex setup first.');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
// Parse flags
|
|
32
|
+
const showLast = args.includes('--last');
|
|
33
|
+
const idIdx = args.indexOf('--id');
|
|
34
|
+
const traceId = idIdx !== -1 ? args[idIdx + 1] : undefined;
|
|
35
|
+
const limitIdx = args.indexOf('--limit');
|
|
36
|
+
const limit = limitIdx !== -1 ? parseInt(args[limitIdx + 1], 10) || 20 : 20;
|
|
37
|
+
const help = args.includes('--help') || args.includes('-h');
|
|
38
|
+
if (help) {
|
|
39
|
+
process.stdout.write(TRACE_USAGE + '\n');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
// Show specific trace by ID
|
|
43
|
+
if (traceId) {
|
|
44
|
+
const trace = readTrace(cwd, traceId);
|
|
45
|
+
if (!trace) {
|
|
46
|
+
warn(`Trace not found: ${traceId}`);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
console.log(JSON.stringify(trace, null, 2));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// List traces
|
|
53
|
+
const traces = listTraces(cwd, showLast ? 1 : limit);
|
|
54
|
+
if (traces.length === 0) {
|
|
55
|
+
info('No traces found in .ai-index/traces/');
|
|
56
|
+
info('Traces are written by nirnex plan and the runtime entry hook.');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (showLast) {
|
|
60
|
+
// Print full JSON of most recent trace
|
|
61
|
+
const full = readTrace(cwd, traces[0].trace_id);
|
|
62
|
+
console.log(JSON.stringify(full ?? traces[0], null, 2));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
// Print table
|
|
66
|
+
console.log('\n\x1b[1mNirnex Traces\x1b[0m\n');
|
|
67
|
+
console.log(` ${'Trace ID'.padEnd(34)} ${'Date'.padEnd(12)} ${'Intent'.padEnd(20)} ${'Conf'.padEnd(6)} ${'Lane'}`);
|
|
68
|
+
console.log(' ' + '─'.repeat(80));
|
|
69
|
+
for (const t of traces) {
|
|
70
|
+
const intent = (t.intent ?? 'unknown').slice(0, 18);
|
|
71
|
+
const score = t.confidence_score != null ? String(t.confidence_score) : '—';
|
|
72
|
+
const lane = t.lane ?? '—';
|
|
73
|
+
console.log(` ${t.trace_id.padEnd(34)} ${t.date.padEnd(12)} ${intent.padEnd(20)} ${score.padEnd(6)} ${lane}`);
|
|
74
|
+
}
|
|
75
|
+
console.log('');
|
|
3
76
|
}
|
|
4
77
|
//# sourceMappingURL=trace.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trace.js","sourceRoot":"","sources":["../../src/commands/trace.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,IAAc;IACzC,OAAO,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"trace.js","sourceRoot":"","sources":["../../src/commands/trace.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,26 +1,34 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
//
|
|
3
|
-
// Usage:
|
|
4
|
-
// Commands: plan | query | status | replay
|
|
2
|
+
// Nirnex CLI — Decision Intelligence for software delivery
|
|
3
|
+
// Usage: nirnex <command> [args]
|
|
5
4
|
import { planCommand } from './commands/plan.js';
|
|
6
5
|
import { queryCommand } from './commands/query.js';
|
|
7
6
|
import { statusCommand } from './commands/status.js';
|
|
8
7
|
import { replayCommand } from './commands/replay.js';
|
|
9
8
|
import { indexCommand } from './commands/index.js';
|
|
10
9
|
import { traceCommand } from './commands/trace.js';
|
|
10
|
+
import { setupCommand } from './commands/setup.js';
|
|
11
|
+
import { runtimeCommand } from './commands/runtime.js';
|
|
11
12
|
const [, , command = '', ...rest] = process.argv;
|
|
12
13
|
const USAGE = `
|
|
13
|
-
|
|
14
|
+
Nirnex — Decision Intelligence for software delivery
|
|
14
15
|
|
|
15
16
|
Usage:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
nirnex setup [options] Initialize Nirnex in this repository
|
|
18
|
+
nirnex index [options] Index the codebase into the knowledge graph
|
|
19
|
+
nirnex plan [options] Generate a delivery plan from a spec or query
|
|
20
|
+
nirnex query [options] Query the knowledge graph
|
|
21
|
+
nirnex status [options] Show index and project health
|
|
22
|
+
nirnex trace [options] View execution traces
|
|
23
|
+
nirnex replay [options] Replay a past analysis run
|
|
24
|
+
nirnex runtime <sub> Claude hook pipeline commands (machine-facing)
|
|
25
|
+
|
|
26
|
+
Run \`nirnex setup\` to get started.
|
|
22
27
|
`.trimStart();
|
|
23
28
|
switch (command) {
|
|
29
|
+
case 'setup':
|
|
30
|
+
setupCommand(rest).catch(console.error);
|
|
31
|
+
break;
|
|
24
32
|
case 'index':
|
|
25
33
|
indexCommand(rest);
|
|
26
34
|
break;
|
|
@@ -39,6 +47,9 @@ switch (command) {
|
|
|
39
47
|
case 'trace':
|
|
40
48
|
traceCommand(rest);
|
|
41
49
|
break;
|
|
50
|
+
case 'runtime':
|
|
51
|
+
runtimeCommand(rest).catch(console.error);
|
|
52
|
+
break;
|
|
42
53
|
default:
|
|
43
54
|
console.log(USAGE);
|
|
44
55
|
if (command && command !== '--help' && command !== '-h') {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,2DAA2D;AAC3D,iCAAiC;AAEjC,OAAO,EAAE,WAAW,EAAE,MAAS,oBAAoB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAQ,qBAAqB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAO,sBAAsB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAO,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAQ,qBAAqB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAQ,qBAAqB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAQ,qBAAqB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,CAAC,EAAE,AAAD,EAAG,OAAO,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;AAEjD,MAAM,KAAK,GAAG;;;;;;;;;;;;;;CAcb,CAAC,SAAS,EAAE,CAAC;AAEd,QAAQ,OAAO,EAAE,CAAC;IAChB,KAAK,OAAO;QACV,YAAY,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM;IACR,KAAK,OAAO;QACV,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,MAAM;IACR,KAAK,MAAM;QACT,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM;IACR,KAAK,OAAO;QACV,YAAY,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM;IACR,KAAK,QAAQ;QACX,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,MAAM;IACR,KAAK,QAAQ;QACX,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,MAAM;IACR,KAAK,OAAO;QACV,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,MAAM;IACR,KAAK,SAAS;QACZ,cAAc,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM;IACR;QACE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACnB,IAAI,OAAO,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACxD,OAAO,CAAC,KAAK,CAAC,qBAAqB,OAAO,GAAG,CAAC,CAAC;YAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM;AACV,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/runtime/bootstrap.ts"],"names":[],"mappings":"AAsCA,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CA8DlD"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// SessionStart hook handler.
|
|
2
|
+
// Called by .claude/hooks/nirnex-bootstrap.sh at the start of each Claude session.
|
|
3
|
+
// Reads nirnex.config.json, checks index freshness, writes env vars to CLAUDE_ENV_FILE,
|
|
4
|
+
// and creates a session state file.
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { execSync } from 'node:child_process';
|
|
8
|
+
import { createSession, saveSession, loadSession } from './session.js';
|
|
9
|
+
function readStdin() {
|
|
10
|
+
return new Promise(resolve => {
|
|
11
|
+
let buf = '';
|
|
12
|
+
process.stdin.setEncoding('utf8');
|
|
13
|
+
process.stdin.on('data', chunk => { buf += chunk; });
|
|
14
|
+
process.stdin.on('end', () => resolve(buf));
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function getIndexFreshness(repoRoot) {
|
|
18
|
+
try {
|
|
19
|
+
const head = execSync('git rev-parse HEAD', { cwd: repoRoot, encoding: 'utf8' }).trim();
|
|
20
|
+
const dbPath = path.join(repoRoot, '.aidos.db');
|
|
21
|
+
if (!fs.existsSync(dbPath))
|
|
22
|
+
return { freshness: 'unknown', head };
|
|
23
|
+
// Read stored commit hash from DB
|
|
24
|
+
const { openDb } = require('@nirnex/core/dist/db.js');
|
|
25
|
+
const db = openDb(dbPath);
|
|
26
|
+
const meta = db.prepare('SELECT value FROM _meta WHERE key = ?').get('commit_hash');
|
|
27
|
+
db.close();
|
|
28
|
+
return { freshness: meta?.value === head ? 'fresh' : 'stale', head };
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return { freshness: 'unknown', head: '' };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export async function runBootstrap() {
|
|
35
|
+
const raw = await readStdin();
|
|
36
|
+
let hookData = { session_id: 'unknown' };
|
|
37
|
+
try {
|
|
38
|
+
hookData = JSON.parse(raw || '{}');
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// Non-fatal: proceed with generated session id
|
|
42
|
+
}
|
|
43
|
+
const sessionId = hookData.session_id || `sess_${Date.now().toString(36)}`;
|
|
44
|
+
const repoRoot = process.cwd();
|
|
45
|
+
// Verify project is Nirnex-enabled
|
|
46
|
+
const configPath = path.join(repoRoot, 'nirnex.config.json');
|
|
47
|
+
if (!fs.existsSync(configPath)) {
|
|
48
|
+
// Not a Nirnex project — exit silently
|
|
49
|
+
process.exit(0);
|
|
50
|
+
}
|
|
51
|
+
let config = {};
|
|
52
|
+
try {
|
|
53
|
+
config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
process.exit(0);
|
|
57
|
+
}
|
|
58
|
+
const { freshness, head } = getIndexFreshness(repoRoot);
|
|
59
|
+
// Create or update session
|
|
60
|
+
const existing = loadSession(repoRoot, sessionId);
|
|
61
|
+
const session = existing ?? createSession(repoRoot, sessionId, {
|
|
62
|
+
index_freshness: freshness,
|
|
63
|
+
current_head: head,
|
|
64
|
+
policy_mode: config.hooks?.policyMode ?? 'standard',
|
|
65
|
+
});
|
|
66
|
+
if (!existing) {
|
|
67
|
+
saveSession(repoRoot, session);
|
|
68
|
+
}
|
|
69
|
+
// Write env vars to CLAUDE_ENV_FILE if set
|
|
70
|
+
const envFile = process.env.CLAUDE_ENV_FILE;
|
|
71
|
+
if (envFile) {
|
|
72
|
+
const envVars = [
|
|
73
|
+
`NIRNEX_REPO_ROOT=${repoRoot}`,
|
|
74
|
+
`NIRNEX_DB_PATH=${path.join(repoRoot, '.aidos.db')}`,
|
|
75
|
+
`NIRNEX_INDEX_FRESHNESS=${freshness}`,
|
|
76
|
+
`NIRNEX_CURRENT_HEAD=${head}`,
|
|
77
|
+
`NIRNEX_POLICY_MODE=${session.policy_mode}`,
|
|
78
|
+
`NIRNEX_SESSION_ID=${sessionId}`,
|
|
79
|
+
].join('\n') + '\n';
|
|
80
|
+
try {
|
|
81
|
+
fs.writeFileSync(envFile, envVars, 'utf8');
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// Non-fatal
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// No JSON output needed for SessionStart (env vars are the output)
|
|
88
|
+
process.exit(0);
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/runtime/bootstrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/runtime/entry.ts"],"names":[],"mappings":"AAoBA,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CA6E9C"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// UserPromptSubmit hook handler.
|
|
2
|
+
// Called before Claude processes each user prompt.
|
|
3
|
+
// Builds ECO from the prompt, creates a task envelope, writes session state,
|
|
4
|
+
// and returns additionalContext so Claude sees the envelope before acting.
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { buildEnvelope, formatEnvelopeContext } from './envelope.js';
|
|
8
|
+
import { loadSession, saveSession, saveEnvelope } from './session.js';
|
|
9
|
+
function readStdin() {
|
|
10
|
+
return new Promise(resolve => {
|
|
11
|
+
let buf = '';
|
|
12
|
+
process.stdin.setEncoding('utf8');
|
|
13
|
+
process.stdin.on('data', chunk => { buf += chunk; });
|
|
14
|
+
process.stdin.on('end', () => resolve(buf));
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
export async function runEntry() {
|
|
18
|
+
const raw = await readStdin();
|
|
19
|
+
let hookData = {
|
|
20
|
+
session_id: 'unknown',
|
|
21
|
+
hook_event_name: 'UserPromptSubmit',
|
|
22
|
+
prompt: '',
|
|
23
|
+
};
|
|
24
|
+
try {
|
|
25
|
+
hookData = JSON.parse(raw || '{}');
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Non-fatal: proceed with empty prompt
|
|
29
|
+
}
|
|
30
|
+
const repoRoot = process.env.NIRNEX_REPO_ROOT ?? process.cwd();
|
|
31
|
+
const sessionId = hookData.session_id ?? process.env.NIRNEX_SESSION_ID ?? `sess_${Date.now().toString(36)}`;
|
|
32
|
+
const prompt = hookData.prompt ?? '';
|
|
33
|
+
// Skip if not a Nirnex project
|
|
34
|
+
if (!fs.existsSync(path.join(repoRoot, 'nirnex.config.json'))) {
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
// Skip very short or empty prompts (e.g. clarifications, single words)
|
|
38
|
+
if (prompt.trim().length < 10) {
|
|
39
|
+
process.exit(0);
|
|
40
|
+
}
|
|
41
|
+
let eco = {};
|
|
42
|
+
try {
|
|
43
|
+
const { buildECO } = await import('@nirnex/core/dist/eco.js');
|
|
44
|
+
eco = buildECO(null, repoRoot, { query: prompt });
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Degraded mode: use a minimal ECO
|
|
48
|
+
eco = {
|
|
49
|
+
recommended_lane: 'A',
|
|
50
|
+
forced_lane_minimum: 'A',
|
|
51
|
+
confidence_score: 50,
|
|
52
|
+
forced_unknown: false,
|
|
53
|
+
blocked: false,
|
|
54
|
+
intent: { primary: 'unknown' },
|
|
55
|
+
modules_touched: [],
|
|
56
|
+
penalties: [],
|
|
57
|
+
escalation_reasons: [],
|
|
58
|
+
boundary_warnings: [],
|
|
59
|
+
eco_dimensions: {},
|
|
60
|
+
evidence_checkpoints: {},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const envelope = buildEnvelope(eco, prompt, sessionId);
|
|
64
|
+
// Persist envelope and link to session
|
|
65
|
+
saveEnvelope(repoRoot, envelope);
|
|
66
|
+
const session = loadSession(repoRoot, sessionId);
|
|
67
|
+
if (session) {
|
|
68
|
+
session.active_task_id = envelope.task_id;
|
|
69
|
+
session.tasks.push(envelope.task_id);
|
|
70
|
+
saveSession(repoRoot, session);
|
|
71
|
+
}
|
|
72
|
+
// Block if ECO says blocked
|
|
73
|
+
if (eco.blocked) {
|
|
74
|
+
const output = {
|
|
75
|
+
blockMessage: `[Nirnex] Task blocked by ECO. Reasons: ${(eco.escalation_reasons ?? []).join('; ') || 'unknown'}. Please revise the spec or run nirnex plan for details.`,
|
|
76
|
+
};
|
|
77
|
+
process.stdout.write(JSON.stringify(output));
|
|
78
|
+
process.exit(0);
|
|
79
|
+
}
|
|
80
|
+
// Return envelope context to Claude
|
|
81
|
+
const contextText = formatEnvelopeContext(envelope);
|
|
82
|
+
const output = { additionalContext: contextText };
|
|
83
|
+
process.stdout.write(JSON.stringify(output));
|
|
84
|
+
process.exit(0);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.js","sourceRoot":"","sources":["../../src/runtime/entry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { TaskEnvelope } from './types.js';
|
|
2
|
+
export declare function buildEnvelope(eco: Record<string, any>, prompt: string, sessionId: string): TaskEnvelope;
|
|
3
|
+
export declare function formatEnvelopeContext(envelope: TaskEnvelope): string;
|
|
4
|
+
//# sourceMappingURL=envelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../../src/runtime/envelope.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAQ,MAAM,YAAY,CAAC;AAyBhD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,CAmEvG;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CA0BpE"}
|