@lucieri/daxiom 0.2.2 → 0.2.4
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/cli.js +3 -2
- package/src/hooks/index.js +24 -0
- package/src/hooks/post-failure.js +93 -0
- package/src/hooks/pre-command.js +5 -1
- package/src/hooks/pre-edit.js +8 -6
- package/src/hooks/pre-task.js +17 -1
- package/src/hooks/session-start.js +6 -1
- package/src/hooks/subagent-start.js +72 -0
- package/src/hooks/subagent-stop.js +89 -0
- package/src/hooks/suggest-context.js +4 -1
- package/src/hooks/task-completed.js +57 -0
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -398,7 +398,7 @@ if (cmd === 'hooks') {
|
|
|
398
398
|
}
|
|
399
399
|
|
|
400
400
|
default:
|
|
401
|
-
console.log('daxiom — Self-Learning Second Brain SDK v0.2.
|
|
401
|
+
console.log('daxiom — Self-Learning Second Brain SDK v0.2.4');
|
|
402
402
|
console.log('');
|
|
403
403
|
console.log('Knowledge: search | store | coherence | quality-check | stats');
|
|
404
404
|
console.log('Tiers: tiers | tier-check | tier-promote');
|
|
@@ -407,7 +407,8 @@ if (cmd === 'hooks') {
|
|
|
407
407
|
console.log('Registry: namespaces');
|
|
408
408
|
console.log('Rollback: demote | rollback-check');
|
|
409
409
|
console.log('Decay: decay | drift | decay-preview');
|
|
410
|
-
console.log('Hooks: hooks
|
|
410
|
+
console.log('Hooks: hooks <subcommand> — 16 Claude Code hook handlers');
|
|
411
|
+
console.log(' Run "daxiom hooks" for full list');
|
|
411
412
|
console.log('');
|
|
412
413
|
console.log('All self-mgmt commands accept --namespace <ns> to target a specific repo.');
|
|
413
414
|
console.log('todo/changelog with no args list entries. Use --namespace to filter.');
|
package/src/hooks/index.js
CHANGED
|
@@ -13,10 +13,14 @@ const { loadEnv } = require('./env');
|
|
|
13
13
|
* post-edit - Record file edits for cross-repo learning
|
|
14
14
|
* pre-command - Search DAXIOM for patterns before shell command
|
|
15
15
|
* post-command - Record significant commands for learning
|
|
16
|
+
* post-failure - Learn from tool failures, suggest known fixes
|
|
16
17
|
* remember - Track file access, searches, agent spawns
|
|
17
18
|
* session-start - Inject SOUL.md + DAXIOM context on session start
|
|
18
19
|
* session-end - Store session summary and run tier maintenance
|
|
20
|
+
* subagent-start - Inject DAXIOM patterns into subagent context
|
|
21
|
+
* subagent-stop - Extract learnings from subagent transcript
|
|
19
22
|
* suggest-context - Surface relevant patterns on user prompt
|
|
23
|
+
* task-completed - Record task completions for learning
|
|
20
24
|
* pre-compact - Capture transcript before context compaction
|
|
21
25
|
* summarize - Process and embed daily session logs
|
|
22
26
|
*/
|
|
@@ -52,6 +56,10 @@ async function dispatch(args) {
|
|
|
52
56
|
const { run } = require('./post-command');
|
|
53
57
|
return run(subArgs);
|
|
54
58
|
}
|
|
59
|
+
case 'post-failure': {
|
|
60
|
+
const { run } = require('./post-failure');
|
|
61
|
+
return run(subArgs);
|
|
62
|
+
}
|
|
55
63
|
case 'remember': {
|
|
56
64
|
const { run } = require('./remember');
|
|
57
65
|
return run(subArgs);
|
|
@@ -64,10 +72,22 @@ async function dispatch(args) {
|
|
|
64
72
|
const { run } = require('./session-end');
|
|
65
73
|
return run(subArgs);
|
|
66
74
|
}
|
|
75
|
+
case 'subagent-start': {
|
|
76
|
+
const { run } = require('./subagent-start');
|
|
77
|
+
return run(subArgs);
|
|
78
|
+
}
|
|
79
|
+
case 'subagent-stop': {
|
|
80
|
+
const { run } = require('./subagent-stop');
|
|
81
|
+
return run(subArgs);
|
|
82
|
+
}
|
|
67
83
|
case 'suggest-context': {
|
|
68
84
|
const { run } = require('./suggest-context');
|
|
69
85
|
return run(subArgs);
|
|
70
86
|
}
|
|
87
|
+
case 'task-completed': {
|
|
88
|
+
const { run } = require('./task-completed');
|
|
89
|
+
return run(subArgs);
|
|
90
|
+
}
|
|
71
91
|
case 'pre-compact': {
|
|
72
92
|
const { run } = require('./pre-compact');
|
|
73
93
|
return run(subArgs);
|
|
@@ -86,10 +106,14 @@ async function dispatch(args) {
|
|
|
86
106
|
console.log(' post-edit Record file edits for learning');
|
|
87
107
|
console.log(' pre-command Search DAXIOM before shell command');
|
|
88
108
|
console.log(' post-command Record significant commands');
|
|
109
|
+
console.log(' post-failure Learn from tool failures, suggest fixes');
|
|
89
110
|
console.log(' remember Track file access, searches, agent spawns');
|
|
90
111
|
console.log(' session-start Inject context on session start');
|
|
91
112
|
console.log(' session-end Store session summary, run tier maintenance');
|
|
113
|
+
console.log(' subagent-start Inject DAXIOM patterns into subagent');
|
|
114
|
+
console.log(' subagent-stop Extract learnings from subagent transcript');
|
|
92
115
|
console.log(' suggest-context Surface relevant patterns on user prompt');
|
|
116
|
+
console.log(' task-completed Record task completions for learning');
|
|
93
117
|
console.log(' pre-compact Capture transcript before compaction');
|
|
94
118
|
console.log(' summarize Process daily session logs');
|
|
95
119
|
console.log('');
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { init, close, storeLearnedPattern, searchWithSalience } = require('../index');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* PostToolUseFailure hook: learn from tool failures.
|
|
9
|
+
* Records what failed and why, searches for known fixes.
|
|
10
|
+
*
|
|
11
|
+
* Reads stdin JSON: { tool_name, tool_input, error, is_interrupt }
|
|
12
|
+
* Outputs JSON: { additionalContext: "..." } with known fixes if found
|
|
13
|
+
*
|
|
14
|
+
* @param {string[]} args - unused (stdin-driven)
|
|
15
|
+
*/
|
|
16
|
+
async function run(args) {
|
|
17
|
+
let input = {};
|
|
18
|
+
try {
|
|
19
|
+
const stdin = fs.readFileSync(0, 'utf8').trim();
|
|
20
|
+
if (stdin) input = JSON.parse(stdin);
|
|
21
|
+
} catch { /* No stdin */ }
|
|
22
|
+
|
|
23
|
+
const toolName = input.tool_name || args[0] || '';
|
|
24
|
+
const error = input.error || '';
|
|
25
|
+
const isInterrupt = input.is_interrupt || false;
|
|
26
|
+
|
|
27
|
+
// Skip user interruptions — nothing to learn
|
|
28
|
+
if (isInterrupt || !toolName || !error) {
|
|
29
|
+
process.stdout.write('{}');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
await init();
|
|
35
|
+
|
|
36
|
+
const repo = path.basename(input.cwd || process.cwd());
|
|
37
|
+
const errorSnippet = error.substring(0, 300);
|
|
38
|
+
|
|
39
|
+
// Store the failure for future learning
|
|
40
|
+
const slug = `${toolName}_${error.replace(/[^a-z0-9]/gi, '_').substring(0, 40)}`.toLowerCase();
|
|
41
|
+
await storeLearnedPattern({
|
|
42
|
+
patternName: `failure_${repo}_${slug}`,
|
|
43
|
+
description: `Tool ${toolName} failed in ${repo}: ${errorSnippet}`,
|
|
44
|
+
compactText: `${toolName} failure: ${errorSnippet}`,
|
|
45
|
+
patternClass: 'error-fix',
|
|
46
|
+
namespace: repo,
|
|
47
|
+
category: 'failure',
|
|
48
|
+
tier: 'warm',
|
|
49
|
+
tags: [repo, 'failure', toolName.toLowerCase()],
|
|
50
|
+
metadata: {
|
|
51
|
+
toolName,
|
|
52
|
+
error: error.substring(0, 1000),
|
|
53
|
+
toolInput: JSON.stringify(input.tool_input || {}).substring(0, 500),
|
|
54
|
+
repo,
|
|
55
|
+
failedAt: new Date().toISOString(),
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Search for known fixes to similar errors
|
|
60
|
+
const fixes = await searchWithSalience(`fix ${toolName} error: ${errorSnippet}`, {
|
|
61
|
+
limit: 3,
|
|
62
|
+
threshold: 0.5,
|
|
63
|
+
decay: 0.03,
|
|
64
|
+
candidatePool: 15,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const knownFixes = fixes.filter(r =>
|
|
68
|
+
r.patternClass === 'error-fix' || r.patternClass === 'learned'
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
if (knownFixes.length > 0) {
|
|
72
|
+
const fixText = knownFixes.map((r, i) =>
|
|
73
|
+
`${i + 1}. [${r.namespace}] ${r.patternName}: ${r.description.substring(0, 200)}`
|
|
74
|
+
).join('\n');
|
|
75
|
+
|
|
76
|
+
const fixContext = `DAXIOM found ${knownFixes.length} known fix(es) for this ${toolName} failure:\n${fixText}\nConsider applying these learned solutions.`;
|
|
77
|
+
process.stdout.write(JSON.stringify({
|
|
78
|
+
hookSpecificOutput: {
|
|
79
|
+
hookEventName: 'PostToolUseFailure',
|
|
80
|
+
additionalContext: fixContext,
|
|
81
|
+
},
|
|
82
|
+
}));
|
|
83
|
+
} else {
|
|
84
|
+
process.stdout.write('{}');
|
|
85
|
+
}
|
|
86
|
+
} catch {
|
|
87
|
+
process.stdout.write('{}');
|
|
88
|
+
} finally {
|
|
89
|
+
await close();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = { run };
|
package/src/hooks/pre-command.js
CHANGED
|
@@ -28,7 +28,11 @@ async function run(args) {
|
|
|
28
28
|
|
|
29
29
|
if (results.length > 0) {
|
|
30
30
|
const hints = results.map(r => `${r.patternName} (${r.namespace}): ${r.description.substring(0, 100)}`);
|
|
31
|
-
|
|
31
|
+
const additionalContext = `DAXIOM hints for command: ${hints.join('; ')}`;
|
|
32
|
+
console.log(JSON.stringify({
|
|
33
|
+
hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext },
|
|
34
|
+
daxiom_intel: true,
|
|
35
|
+
}));
|
|
32
36
|
}
|
|
33
37
|
} catch {
|
|
34
38
|
// Non-fatal
|
package/src/hooks/pre-edit.js
CHANGED
|
@@ -35,12 +35,14 @@ async function run(args) {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
const hints = results.map(r => `${r.patternName}: ${r.description.substring(0, 120)}`);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
const additionalContext = hints.length > 0
|
|
39
|
+
? `DAXIOM patterns for ${fileName}: ${hints.join('; ')}`
|
|
40
|
+
: undefined;
|
|
41
|
+
const output = { daxiom_intel: true, file: filePath, patterns: results.length };
|
|
42
|
+
if (additionalContext) {
|
|
43
|
+
output.hookSpecificOutput = { hookEventName: 'PreToolUse', additionalContext };
|
|
44
|
+
}
|
|
45
|
+
console.log(JSON.stringify(output));
|
|
44
46
|
} catch (err) {
|
|
45
47
|
console.log(JSON.stringify({ daxiom_intel: false, error: err.message }));
|
|
46
48
|
} finally {
|
package/src/hooks/pre-task.js
CHANGED
|
@@ -65,7 +65,23 @@ async function run(args) {
|
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
// Build human-readable context for injection into agent
|
|
69
|
+
const patternSummary = results.slice(0, 5).map((r, i) =>
|
|
70
|
+
`${i + 1}. [${r.namespace}/${r.patternClass}] ${r.patternName} (sim=${r.similarity.toFixed(2)}): ${r.description.substring(0, 180)}`
|
|
71
|
+
).join('\n');
|
|
72
|
+
|
|
73
|
+
const additionalContext = [
|
|
74
|
+
`DAXIOM Intelligence: ${results.length} patterns found for this task.`,
|
|
75
|
+
patternSummary,
|
|
76
|
+
'',
|
|
77
|
+
'Apply these learned patterns where relevant.',
|
|
78
|
+
].join('\n');
|
|
79
|
+
|
|
68
80
|
const output = {
|
|
81
|
+
hookSpecificOutput: {
|
|
82
|
+
hookEventName: 'PreToolUse',
|
|
83
|
+
additionalContext,
|
|
84
|
+
},
|
|
69
85
|
daxiom_intel: true,
|
|
70
86
|
ranking: 'salience',
|
|
71
87
|
patterns_found: results.length,
|
|
@@ -80,7 +96,7 @@ async function run(args) {
|
|
|
80
96
|
task: taskDescription,
|
|
81
97
|
};
|
|
82
98
|
|
|
83
|
-
console.log(JSON.stringify(output
|
|
99
|
+
console.log(JSON.stringify(output));
|
|
84
100
|
|
|
85
101
|
// Record usage for top 3 patterns
|
|
86
102
|
for (const r of results.slice(0, 3)) {
|
|
@@ -102,7 +102,12 @@ async function run(args) {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
const context = parts.join('\n\n---\n\n');
|
|
105
|
-
process.stdout.write(JSON.stringify({
|
|
105
|
+
process.stdout.write(JSON.stringify({
|
|
106
|
+
hookSpecificOutput: {
|
|
107
|
+
hookEventName: 'SessionStart',
|
|
108
|
+
additionalContext: context,
|
|
109
|
+
},
|
|
110
|
+
}));
|
|
106
111
|
}
|
|
107
112
|
|
|
108
113
|
module.exports = { run };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { init, close, searchWithSalience } = require('../index');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* SubagentStart hook: inject DAXIOM patterns directly into subagent context.
|
|
9
|
+
* Uses additionalContext field so patterns appear in the subagent's system prompt.
|
|
10
|
+
*
|
|
11
|
+
* Reads stdin JSON: { agent_id, agent_type, session_id, cwd }
|
|
12
|
+
* Outputs JSON: { additionalContext: "..." }
|
|
13
|
+
*
|
|
14
|
+
* @param {string[]} args - unused (stdin-driven)
|
|
15
|
+
*/
|
|
16
|
+
async function run(args) {
|
|
17
|
+
let input = {};
|
|
18
|
+
try {
|
|
19
|
+
const stdin = fs.readFileSync(0, 'utf8').trim();
|
|
20
|
+
if (stdin) input = JSON.parse(stdin);
|
|
21
|
+
} catch { /* No stdin */ }
|
|
22
|
+
|
|
23
|
+
const agentType = input.agent_type || args[0] || '';
|
|
24
|
+
if (!agentType) {
|
|
25
|
+
process.stdout.write('{}');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
await init();
|
|
31
|
+
|
|
32
|
+
const repo = path.basename(input.cwd || process.cwd());
|
|
33
|
+
const query = `${agentType} agent patterns conventions ${repo}`;
|
|
34
|
+
|
|
35
|
+
const results = await searchWithSalience(query, {
|
|
36
|
+
limit: 5,
|
|
37
|
+
threshold: 0.4,
|
|
38
|
+
decay: 0.03,
|
|
39
|
+
candidatePool: 20,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (results.length === 0) {
|
|
43
|
+
process.stdout.write('{}');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Build context string for the subagent
|
|
48
|
+
const patterns = results.map((r, i) =>
|
|
49
|
+
`${i + 1}. [${r.namespace}/${r.patternClass}] ${r.patternName}: ${r.description.substring(0, 200)}`
|
|
50
|
+
).join('\n');
|
|
51
|
+
|
|
52
|
+
const context = [
|
|
53
|
+
`DAXIOM Intelligence (${results.length} patterns for ${agentType} agent in ${repo}):`,
|
|
54
|
+
patterns,
|
|
55
|
+
'',
|
|
56
|
+
'Use these learned patterns to inform your work. They represent cross-repo knowledge.',
|
|
57
|
+
].join('\n');
|
|
58
|
+
|
|
59
|
+
process.stdout.write(JSON.stringify({
|
|
60
|
+
hookSpecificOutput: {
|
|
61
|
+
hookEventName: 'SubagentStart',
|
|
62
|
+
additionalContext: context,
|
|
63
|
+
},
|
|
64
|
+
}));
|
|
65
|
+
} catch {
|
|
66
|
+
process.stdout.write('{}');
|
|
67
|
+
} finally {
|
|
68
|
+
await close();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = { run };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { init, close, storeLearnedPattern } = require('../index');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* SubagentStop hook: extract learnings from subagent transcript.
|
|
9
|
+
* Reads the agent transcript and stores key findings in DAXIOM.
|
|
10
|
+
*
|
|
11
|
+
* Reads stdin JSON: { agent_id, agent_type, agent_transcript_path, session_id, cwd }
|
|
12
|
+
* Outputs JSON: {} (async, non-blocking)
|
|
13
|
+
*
|
|
14
|
+
* @param {string[]} args - unused (stdin-driven)
|
|
15
|
+
*/
|
|
16
|
+
async function run(args) {
|
|
17
|
+
let input = {};
|
|
18
|
+
try {
|
|
19
|
+
const stdin = fs.readFileSync(0, 'utf8').trim();
|
|
20
|
+
if (stdin) input = JSON.parse(stdin);
|
|
21
|
+
} catch { /* No stdin */ }
|
|
22
|
+
|
|
23
|
+
const agentType = input.agent_type || '';
|
|
24
|
+
const transcriptPath = input.agent_transcript_path || '';
|
|
25
|
+
|
|
26
|
+
if (!agentType) return;
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
await init();
|
|
30
|
+
|
|
31
|
+
const repo = path.basename(input.cwd || process.cwd());
|
|
32
|
+
let transcriptSummary = '';
|
|
33
|
+
|
|
34
|
+
// Read last portion of transcript if available
|
|
35
|
+
if (transcriptPath && fs.existsSync(transcriptPath)) {
|
|
36
|
+
try {
|
|
37
|
+
const content = fs.readFileSync(transcriptPath, 'utf8');
|
|
38
|
+
const lines = content.split('\n').filter(Boolean);
|
|
39
|
+
|
|
40
|
+
// Extract assistant messages from last 10 JSONL entries
|
|
41
|
+
const recentEntries = lines.slice(-10);
|
|
42
|
+
const discoveries = [];
|
|
43
|
+
|
|
44
|
+
for (const line of recentEntries) {
|
|
45
|
+
try {
|
|
46
|
+
const entry = JSON.parse(line);
|
|
47
|
+
if (entry.role === 'assistant' && typeof entry.content === 'string') {
|
|
48
|
+
// Look for findings, conclusions, or results
|
|
49
|
+
const text = entry.content.substring(0, 300);
|
|
50
|
+
if (text.length > 30) discoveries.push(text);
|
|
51
|
+
}
|
|
52
|
+
} catch { /* skip malformed lines */ }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (discoveries.length > 0) {
|
|
56
|
+
transcriptSummary = discoveries.slice(0, 3).join(' | ');
|
|
57
|
+
}
|
|
58
|
+
} catch { /* transcript read failed, non-fatal */ }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const description = transcriptSummary
|
|
62
|
+
? `${agentType} agent completed in ${repo}. Key findings: ${transcriptSummary.substring(0, 500)}`
|
|
63
|
+
: `${agentType} agent completed work in ${repo}`;
|
|
64
|
+
|
|
65
|
+
await storeLearnedPattern({
|
|
66
|
+
patternName: `agent_${repo}_${agentType}_${Date.now()}`,
|
|
67
|
+
description,
|
|
68
|
+
compactText: `${agentType} agent finished in ${repo}`,
|
|
69
|
+
patternClass: 'activity',
|
|
70
|
+
namespace: repo,
|
|
71
|
+
category: 'agent-completion',
|
|
72
|
+
tier: 'warm',
|
|
73
|
+
tags: [repo, 'agent-completion', agentType],
|
|
74
|
+
metadata: {
|
|
75
|
+
agentType,
|
|
76
|
+
agentId: input.agent_id,
|
|
77
|
+
repo,
|
|
78
|
+
hadTranscript: !!transcriptSummary,
|
|
79
|
+
completedAt: new Date().toISOString(),
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
} catch {
|
|
83
|
+
// Non-fatal
|
|
84
|
+
} finally {
|
|
85
|
+
await close();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
module.exports = { run };
|
|
@@ -34,7 +34,10 @@ async function run(args) {
|
|
|
34
34
|
`${r.patternName} (${r.namespace}, ${r.patternClass}): ${r.description.substring(0, 150)}`
|
|
35
35
|
);
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
const additionalContext = `DAXIOM Intelligence: ${hints.join('; ')}`;
|
|
38
|
+
console.log(JSON.stringify({
|
|
39
|
+
hookSpecificOutput: { hookEventName: 'UserPromptSubmit', additionalContext },
|
|
40
|
+
}));
|
|
38
41
|
} catch {
|
|
39
42
|
// Non-fatal
|
|
40
43
|
} finally {
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { init, close, storeLearnedPattern } = require('../index');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* TaskCompleted hook: record task completions for learning.
|
|
9
|
+
* Captures what was accomplished for cross-session intelligence.
|
|
10
|
+
*
|
|
11
|
+
* Reads stdin JSON: { task_id, task_subject, task_description }
|
|
12
|
+
* Exit code 2 would block completion (not used currently).
|
|
13
|
+
*
|
|
14
|
+
* @param {string[]} args - unused (stdin-driven)
|
|
15
|
+
*/
|
|
16
|
+
async function run(args) {
|
|
17
|
+
let input = {};
|
|
18
|
+
try {
|
|
19
|
+
const stdin = fs.readFileSync(0, 'utf8').trim();
|
|
20
|
+
if (stdin) input = JSON.parse(stdin);
|
|
21
|
+
} catch { /* No stdin */ }
|
|
22
|
+
|
|
23
|
+
const taskSubject = input.task_subject || args[0] || '';
|
|
24
|
+
if (!taskSubject) return;
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
await init();
|
|
28
|
+
|
|
29
|
+
const repo = path.basename(input.cwd || process.cwd());
|
|
30
|
+
const slug = taskSubject.replace(/[^a-z0-9\s]/gi, '').trim()
|
|
31
|
+
.split(/\s+/).slice(0, 6).join('_').substring(0, 60).toLowerCase();
|
|
32
|
+
|
|
33
|
+
await storeLearnedPattern({
|
|
34
|
+
patternName: `completed_${repo}_${slug}`,
|
|
35
|
+
description: `Completed: ${taskSubject}${input.task_description ? ' — ' + input.task_description.substring(0, 200) : ''}`,
|
|
36
|
+
compactText: `Task completed in ${repo}: ${taskSubject}`,
|
|
37
|
+
patternClass: 'activity',
|
|
38
|
+
namespace: repo,
|
|
39
|
+
category: 'task-completed',
|
|
40
|
+
tier: 'warm',
|
|
41
|
+
tags: [repo, 'completed'],
|
|
42
|
+
metadata: {
|
|
43
|
+
taskId: input.task_id,
|
|
44
|
+
taskSubject,
|
|
45
|
+
taskDescription: (input.task_description || '').substring(0, 500),
|
|
46
|
+
repo,
|
|
47
|
+
completedAt: new Date().toISOString(),
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
} catch {
|
|
51
|
+
// Non-fatal
|
|
52
|
+
} finally {
|
|
53
|
+
await close();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
module.exports = { run };
|