@lucieri/daxiom 0.2.1 → 0.2.2
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/package.json +1 -1
- package/src/constants.js +3 -0
- package/src/hooks/index.js +52 -10
- package/src/hooks/post-command.js +50 -0
- package/src/hooks/post-edit.js +49 -0
- package/src/hooks/pre-command.js +40 -0
- package/src/hooks/pre-edit.js +51 -0
- package/src/hooks/remember.js +63 -0
- package/src/hooks/session-end.js +50 -0
- package/src/hooks/suggest-context.js +45 -0
package/package.json
CHANGED
package/src/constants.js
CHANGED
|
@@ -28,6 +28,7 @@ const KNOWN_CLASSES = [
|
|
|
28
28
|
'tool', 'guidance', 'interface', 'algorithm', 'integration',
|
|
29
29
|
'ui', 'adapter', 'skill', 'session-context', 'session-summary',
|
|
30
30
|
'wire_integrate', 'general',
|
|
31
|
+
'file-edit', 'command', 'activity', 'session',
|
|
31
32
|
];
|
|
32
33
|
|
|
33
34
|
const KNOWN_NAMESPACES = [
|
|
@@ -49,6 +50,8 @@ const KNOWN_NAMESPACES = [
|
|
|
49
50
|
'forge', 'vibe-cast', 'agentic-qe',
|
|
50
51
|
'plugin-ecosystem', 'plugin-prime-radiant', 'gastown',
|
|
51
52
|
'plugin-code-intelligence', 'plugin-test-intelligence',
|
|
53
|
+
// Additional project namespaces
|
|
54
|
+
'openclaw', 'memu', 'voicemode', 'mission-control',
|
|
52
55
|
];
|
|
53
56
|
|
|
54
57
|
const SECURITY_PATTERNS = [
|
package/src/hooks/index.js
CHANGED
|
@@ -7,11 +7,18 @@ const { loadEnv } = require('./env');
|
|
|
7
7
|
* Usage: daxiom hooks <subcommand> [args...]
|
|
8
8
|
*
|
|
9
9
|
* Subcommands:
|
|
10
|
-
* pre-task
|
|
11
|
-
* post-task
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
10
|
+
* pre-task - Search DAXIOM for relevant patterns before agent task
|
|
11
|
+
* post-task - Store learnings after agent task completion
|
|
12
|
+
* pre-edit - Search DAXIOM for patterns before file edit
|
|
13
|
+
* post-edit - Record file edits for cross-repo learning
|
|
14
|
+
* pre-command - Search DAXIOM for patterns before shell command
|
|
15
|
+
* post-command - Record significant commands for learning
|
|
16
|
+
* remember - Track file access, searches, agent spawns
|
|
17
|
+
* session-start - Inject SOUL.md + DAXIOM context on session start
|
|
18
|
+
* session-end - Store session summary and run tier maintenance
|
|
19
|
+
* suggest-context - Surface relevant patterns on user prompt
|
|
20
|
+
* pre-compact - Capture transcript before context compaction
|
|
21
|
+
* summarize - Process and embed daily session logs
|
|
15
22
|
*/
|
|
16
23
|
async function dispatch(args) {
|
|
17
24
|
// Load env before any hook runs
|
|
@@ -29,10 +36,38 @@ async function dispatch(args) {
|
|
|
29
36
|
const { run } = require('./post-task');
|
|
30
37
|
return run(subArgs);
|
|
31
38
|
}
|
|
39
|
+
case 'pre-edit': {
|
|
40
|
+
const { run } = require('./pre-edit');
|
|
41
|
+
return run(subArgs);
|
|
42
|
+
}
|
|
43
|
+
case 'post-edit': {
|
|
44
|
+
const { run } = require('./post-edit');
|
|
45
|
+
return run(subArgs);
|
|
46
|
+
}
|
|
47
|
+
case 'pre-command': {
|
|
48
|
+
const { run } = require('./pre-command');
|
|
49
|
+
return run(subArgs);
|
|
50
|
+
}
|
|
51
|
+
case 'post-command': {
|
|
52
|
+
const { run } = require('./post-command');
|
|
53
|
+
return run(subArgs);
|
|
54
|
+
}
|
|
55
|
+
case 'remember': {
|
|
56
|
+
const { run } = require('./remember');
|
|
57
|
+
return run(subArgs);
|
|
58
|
+
}
|
|
32
59
|
case 'session-start': {
|
|
33
60
|
const { run } = require('./session-start');
|
|
34
61
|
return run(subArgs);
|
|
35
62
|
}
|
|
63
|
+
case 'session-end': {
|
|
64
|
+
const { run } = require('./session-end');
|
|
65
|
+
return run(subArgs);
|
|
66
|
+
}
|
|
67
|
+
case 'suggest-context': {
|
|
68
|
+
const { run } = require('./suggest-context');
|
|
69
|
+
return run(subArgs);
|
|
70
|
+
}
|
|
36
71
|
case 'pre-compact': {
|
|
37
72
|
const { run } = require('./pre-compact');
|
|
38
73
|
return run(subArgs);
|
|
@@ -45,11 +80,18 @@ async function dispatch(args) {
|
|
|
45
80
|
console.log('daxiom hooks — Claude Code hook handlers');
|
|
46
81
|
console.log('');
|
|
47
82
|
console.log('Subcommands:');
|
|
48
|
-
console.log(' pre-task
|
|
49
|
-
console.log(' post-task
|
|
50
|
-
console.log('
|
|
51
|
-
console.log('
|
|
52
|
-
console.log('
|
|
83
|
+
console.log(' pre-task Search DAXIOM before agent task');
|
|
84
|
+
console.log(' post-task Store learnings after agent task');
|
|
85
|
+
console.log(' pre-edit Search DAXIOM before file edit');
|
|
86
|
+
console.log(' post-edit Record file edits for learning');
|
|
87
|
+
console.log(' pre-command Search DAXIOM before shell command');
|
|
88
|
+
console.log(' post-command Record significant commands');
|
|
89
|
+
console.log(' remember Track file access, searches, agent spawns');
|
|
90
|
+
console.log(' session-start Inject context on session start');
|
|
91
|
+
console.log(' session-end Store session summary, run tier maintenance');
|
|
92
|
+
console.log(' suggest-context Surface relevant patterns on user prompt');
|
|
93
|
+
console.log(' pre-compact Capture transcript before compaction');
|
|
94
|
+
console.log(' summarize Process daily session logs');
|
|
53
95
|
console.log('');
|
|
54
96
|
console.log('Env: DAXIOM_DATABASE_URL or DATABASE_URL, GEMINI_API_KEY');
|
|
55
97
|
console.log('Auto-loads from ~/.daxiom/.env if env vars not set.');
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { init, close, storeLearnedPattern } = require('../index');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Post-command hook: record significant commands in DAXIOM for cross-repo learning.
|
|
8
|
+
* Only stores non-trivial commands (builds, deploys, migrations, installs, etc.)
|
|
9
|
+
*
|
|
10
|
+
* @param {string[]} args - [command string]
|
|
11
|
+
*/
|
|
12
|
+
async function run(args) {
|
|
13
|
+
const command = args.join(' ');
|
|
14
|
+
if (!command) return;
|
|
15
|
+
|
|
16
|
+
// Only record significant commands
|
|
17
|
+
const significant = /\b(npm|pnpm|yarn|npx|docker|psql|git push|git merge|deploy|migrate|build|test|publish)\b/i;
|
|
18
|
+
if (!significant.test(command)) return;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
await init();
|
|
22
|
+
|
|
23
|
+
const repo = path.basename(process.cwd());
|
|
24
|
+
const cmdSlug = command.replace(/[^a-z0-9\s]/gi, '').trim()
|
|
25
|
+
.split(/\s+/).slice(0, 5).join('_').substring(0, 60);
|
|
26
|
+
|
|
27
|
+
await storeLearnedPattern({
|
|
28
|
+
patternName: `cmd_${repo}_${cmdSlug}`,
|
|
29
|
+
description: `Command: ${command.substring(0, 300)}`,
|
|
30
|
+
compactText: `Ran command in ${repo}: ${command.substring(0, 200)}`,
|
|
31
|
+
patternClass: 'command',
|
|
32
|
+
namespace: repo,
|
|
33
|
+
category: 'activity',
|
|
34
|
+
tier: 'warm',
|
|
35
|
+
tags: [repo, 'command'],
|
|
36
|
+
metadata: {
|
|
37
|
+
command: command.substring(0, 500),
|
|
38
|
+
repo,
|
|
39
|
+
cwd: process.cwd(),
|
|
40
|
+
ranAt: new Date().toISOString(),
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
} catch {
|
|
44
|
+
// Non-fatal
|
|
45
|
+
} finally {
|
|
46
|
+
await close();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = { run };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { init, close, storeLearnedPattern } = require('../index');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Post-edit hook: record file edits in DAXIOM for cross-repo learning.
|
|
8
|
+
*
|
|
9
|
+
* @param {string[]} args - [filePath, ...flags]
|
|
10
|
+
*/
|
|
11
|
+
async function run(args) {
|
|
12
|
+
const filePath = args[0];
|
|
13
|
+
if (!filePath) return;
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
await init();
|
|
17
|
+
|
|
18
|
+
const fileName = path.basename(filePath);
|
|
19
|
+
const ext = path.extname(filePath).slice(1);
|
|
20
|
+
const repo = path.basename(process.cwd());
|
|
21
|
+
const dir = path.dirname(filePath).split('/').slice(-2).join('/');
|
|
22
|
+
|
|
23
|
+
await storeLearnedPattern({
|
|
24
|
+
patternName: `edit_${repo}_${fileName}`.replace(/[^a-z0-9_.-]/gi, '_').substring(0, 80),
|
|
25
|
+
description: `Edited ${fileName} in ${dir} (${repo})`,
|
|
26
|
+
compactText: `File edit: ${filePath} in repo ${repo}. Extension: ${ext}.`,
|
|
27
|
+
patternClass: 'file-edit',
|
|
28
|
+
namespace: repo,
|
|
29
|
+
category: 'activity',
|
|
30
|
+
tier: 'warm',
|
|
31
|
+
tags: [ext, repo, 'edit'].filter(Boolean),
|
|
32
|
+
metadata: {
|
|
33
|
+
filePath,
|
|
34
|
+
extension: ext,
|
|
35
|
+
repo,
|
|
36
|
+
editedAt: new Date().toISOString(),
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
console.log(JSON.stringify({ recorded: true, file: fileName, repo }));
|
|
41
|
+
} catch (err) {
|
|
42
|
+
// Non-fatal — don't block edits
|
|
43
|
+
console.log(JSON.stringify({ recorded: false, error: err.message }));
|
|
44
|
+
} finally {
|
|
45
|
+
await close();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = { run };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { init, close, searchWithSalience } = require('../index');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Pre-command hook: search DAXIOM for patterns related to the command being run.
|
|
7
|
+
* Surfaces relevant learnings before executing shell commands.
|
|
8
|
+
*
|
|
9
|
+
* @param {string[]} args - [command string]
|
|
10
|
+
*/
|
|
11
|
+
async function run(args) {
|
|
12
|
+
const command = args.join(' ');
|
|
13
|
+
if (!command) return;
|
|
14
|
+
|
|
15
|
+
// Skip trivial commands
|
|
16
|
+
const trivial = /^(ls|pwd|cd|echo|cat|head|tail|which|true|false)\b/;
|
|
17
|
+
if (trivial.test(command.trim())) return;
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
await init();
|
|
21
|
+
|
|
22
|
+
const results = await searchWithSalience(command, {
|
|
23
|
+
limit: 2,
|
|
24
|
+
threshold: 0.5,
|
|
25
|
+
decay: 0.03,
|
|
26
|
+
candidatePool: 10,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
if (results.length > 0) {
|
|
30
|
+
const hints = results.map(r => `${r.patternName} (${r.namespace}): ${r.description.substring(0, 100)}`);
|
|
31
|
+
console.log(JSON.stringify({ daxiom_intel: true, command_hints: hints }));
|
|
32
|
+
}
|
|
33
|
+
} catch {
|
|
34
|
+
// Non-fatal
|
|
35
|
+
} finally {
|
|
36
|
+
await close();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = { run };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { init, close, searchWithSalience } = require('../index');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Pre-edit hook: search DAXIOM for patterns related to the file being edited.
|
|
7
|
+
* Provides relevant context before making changes.
|
|
8
|
+
*
|
|
9
|
+
* @param {string[]} args - [filePath, ...flags]
|
|
10
|
+
*/
|
|
11
|
+
async function run(args) {
|
|
12
|
+
const filePath = args[0];
|
|
13
|
+
if (!filePath) {
|
|
14
|
+
console.log(JSON.stringify({ daxiom_intel: false, message: 'No file path' }));
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
await init();
|
|
20
|
+
|
|
21
|
+
const fileName = filePath.split('/').pop();
|
|
22
|
+
const ext = fileName.split('.').pop();
|
|
23
|
+
const query = `editing ${fileName} ${ext} file patterns conventions`;
|
|
24
|
+
|
|
25
|
+
const results = await searchWithSalience(query, {
|
|
26
|
+
limit: 3,
|
|
27
|
+
threshold: 0.4,
|
|
28
|
+
decay: 0.03,
|
|
29
|
+
candidatePool: 15,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (results.length === 0) {
|
|
33
|
+
console.log(JSON.stringify({ daxiom_intel: false }));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const hints = results.map(r => `${r.patternName}: ${r.description.substring(0, 120)}`);
|
|
38
|
+
console.log(JSON.stringify({
|
|
39
|
+
daxiom_intel: true,
|
|
40
|
+
file: filePath,
|
|
41
|
+
patterns: results.length,
|
|
42
|
+
hints,
|
|
43
|
+
}));
|
|
44
|
+
} catch (err) {
|
|
45
|
+
console.log(JSON.stringify({ daxiom_intel: false, error: err.message }));
|
|
46
|
+
} finally {
|
|
47
|
+
await close();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = { run };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { init, close, storeLearnedPattern } = require('../index');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Remember hook: track file access, search patterns, and agent spawns in DAXIOM.
|
|
8
|
+
* Builds a cross-repo activity graph for learning and context retrieval.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* daxiom hooks remember "Reading: src/foo.ts" -t file_access
|
|
12
|
+
* daxiom hooks remember "Search: auth pattern" -t search_pattern
|
|
13
|
+
* daxiom hooks remember "Agent: coder" -t agent_spawn
|
|
14
|
+
*
|
|
15
|
+
* @param {string[]} args - [description, -t type]
|
|
16
|
+
*/
|
|
17
|
+
async function run(args) {
|
|
18
|
+
let description = '';
|
|
19
|
+
let activityType = 'general';
|
|
20
|
+
|
|
21
|
+
for (let i = 0; i < args.length; i++) {
|
|
22
|
+
if (args[i] === '-t' && i + 1 < args.length) {
|
|
23
|
+
activityType = args[++i];
|
|
24
|
+
} else {
|
|
25
|
+
description += (description ? ' ' : '') + args[i];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!description) return;
|
|
30
|
+
|
|
31
|
+
// Throttle: only record 1 in 5 file reads to avoid flooding
|
|
32
|
+
if (activityType === 'file_access' && Math.random() > 0.2) return;
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
await init();
|
|
36
|
+
|
|
37
|
+
const repo = path.basename(process.cwd());
|
|
38
|
+
const slug = description.replace(/[^a-z0-9\s]/gi, '').trim()
|
|
39
|
+
.split(/\s+/).slice(0, 5).join('_').substring(0, 60);
|
|
40
|
+
|
|
41
|
+
await storeLearnedPattern({
|
|
42
|
+
patternName: `mem_${activityType}_${slug}`,
|
|
43
|
+
description,
|
|
44
|
+
compactText: `${activityType}: ${description} (${repo})`,
|
|
45
|
+
patternClass: 'activity',
|
|
46
|
+
namespace: repo,
|
|
47
|
+
category: activityType,
|
|
48
|
+
tier: 'cold',
|
|
49
|
+
tags: [repo, activityType],
|
|
50
|
+
metadata: {
|
|
51
|
+
activityType,
|
|
52
|
+
repo,
|
|
53
|
+
trackedAt: new Date().toISOString(),
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
} catch {
|
|
57
|
+
// Non-fatal
|
|
58
|
+
} finally {
|
|
59
|
+
await close();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = { run };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { init, close, storeLearnedPattern, updateTiers } = require('../index');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Session-end hook: store session summary in DAXIOM and run tier maintenance.
|
|
8
|
+
* Captures what repo was worked on, when, and triggers tier decay.
|
|
9
|
+
*
|
|
10
|
+
* @param {string[]} args - unused
|
|
11
|
+
*/
|
|
12
|
+
async function run(args) {
|
|
13
|
+
try {
|
|
14
|
+
await init();
|
|
15
|
+
|
|
16
|
+
const repo = path.basename(process.cwd());
|
|
17
|
+
const now = new Date();
|
|
18
|
+
const sessionId = `${now.toISOString().slice(0, 10)}-${repo}-${now.getHours()}${now.getMinutes()}`;
|
|
19
|
+
|
|
20
|
+
await storeLearnedPattern({
|
|
21
|
+
patternName: `session_end_${sessionId}`,
|
|
22
|
+
description: `Session ended in ${repo} at ${now.toISOString()}`,
|
|
23
|
+
compactText: `Claude session in ${repo} ended. Date: ${now.toISOString().slice(0, 10)}.`,
|
|
24
|
+
patternClass: 'session',
|
|
25
|
+
namespace: 'session-memory',
|
|
26
|
+
category: 'session',
|
|
27
|
+
tier: 'warm',
|
|
28
|
+
tags: [repo, 'session-end'],
|
|
29
|
+
metadata: {
|
|
30
|
+
repo,
|
|
31
|
+
endedAt: now.toISOString(),
|
|
32
|
+
cwd: process.cwd(),
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Run tier maintenance on every session end
|
|
37
|
+
const tierResult = await updateTiers();
|
|
38
|
+
if (tierResult.promoted + tierResult.demotedToWarm + tierResult.demotedToCold > 0) {
|
|
39
|
+
console.error(`[DAXIOM] Tier maintenance: ${JSON.stringify(tierResult)}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
console.log(JSON.stringify({ session_ended: true, repo, tiers: tierResult }));
|
|
43
|
+
} catch (err) {
|
|
44
|
+
console.error('DAXIOM session-end error:', err.message);
|
|
45
|
+
} finally {
|
|
46
|
+
await close();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = { run };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { init, close, searchWithSalience } = require('../index');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Suggest-context hook: on each user prompt, surface relevant DAXIOM patterns.
|
|
8
|
+
* Reads CLAUDE_USER_PROMPT env var or args to find matching patterns.
|
|
9
|
+
*
|
|
10
|
+
* @param {string[]} args - [prompt text] or reads $CLAUDE_USER_PROMPT
|
|
11
|
+
*/
|
|
12
|
+
async function run(args) {
|
|
13
|
+
const prompt = args.join(' ') || process.env.CLAUDE_USER_PROMPT || '';
|
|
14
|
+
if (!prompt || prompt.length < 5) return;
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
await init();
|
|
18
|
+
|
|
19
|
+
const repo = path.basename(process.cwd());
|
|
20
|
+
|
|
21
|
+
const results = await searchWithSalience(prompt, {
|
|
22
|
+
limit: 3,
|
|
23
|
+
threshold: 0.45,
|
|
24
|
+
decay: 0.03,
|
|
25
|
+
candidatePool: 15,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
if (results.length === 0) return;
|
|
29
|
+
|
|
30
|
+
const learned = results.filter(r => r.patternClass === 'learned' || r.namespace === repo);
|
|
31
|
+
const display = (learned.length > 0 ? learned : results).slice(0, 2);
|
|
32
|
+
|
|
33
|
+
const hints = display.map(r =>
|
|
34
|
+
`${r.patternName} (${r.namespace}, ${r.patternClass}): ${r.description.substring(0, 150)}`
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
console.log(`RuVector Intelligence: ${results.length} learned patterns, 0 error fixes available. Use 'ruvector hooks route' for agent suggestions.`);
|
|
38
|
+
} catch {
|
|
39
|
+
// Non-fatal
|
|
40
|
+
} finally {
|
|
41
|
+
await close();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = { run };
|