@massu/core 2.4.0 → 2.5.1
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/CHANGELOG.md +126 -0
- package/commands/massu-bearings.md +1 -1
- package/commands/massu-recap.md +16 -5
- package/dist/cli.js +291 -80
- package/dist/hooks/auto-learning-pipeline.js +53 -9
- package/dist/hooks/classify-failure.js +55 -11
- package/dist/hooks/cost-tracker.js +23 -9
- package/dist/hooks/fix-detector.js +54 -9
- package/dist/hooks/incident-pipeline.js +53 -9
- package/dist/hooks/intent-suggester.js +53 -9
- package/dist/hooks/memory-recall.js +53 -9
- package/dist/hooks/post-edit-context.js +53 -9
- package/dist/hooks/post-tool-use.js +19 -6
- package/dist/hooks/pre-compact.js +19 -6
- package/dist/hooks/pre-delete-check.js +53 -9
- package/dist/hooks/pre-tool-use-gate.js +57 -11
- package/dist/hooks/quality-event.js +23 -9
- package/dist/hooks/rule-enforcement-pipeline.js +53 -9
- package/dist/hooks/security-gate.js +53 -9
- package/dist/hooks/session-end.js +19 -6
- package/dist/hooks/session-start.js +120 -37
- package/dist/hooks/user-prompt.js +19 -6
- package/package.json +1 -1
|
@@ -1339,6 +1339,16 @@ var init_memory_vector = __esm({
|
|
|
1339
1339
|
}
|
|
1340
1340
|
});
|
|
1341
1341
|
|
|
1342
|
+
// src/lib/timestamps.ts
|
|
1343
|
+
function nowIso() {
|
|
1344
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
1345
|
+
}
|
|
1346
|
+
var init_timestamps = __esm({
|
|
1347
|
+
"src/lib/timestamps.ts"() {
|
|
1348
|
+
"use strict";
|
|
1349
|
+
}
|
|
1350
|
+
});
|
|
1351
|
+
|
|
1342
1352
|
// src/db-backup.ts
|
|
1343
1353
|
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readdirSync, statSync, unlinkSync, copyFileSync, rmSync as rmSync4 } from "fs";
|
|
1344
1354
|
import { resolve as resolve3, join as join3, basename, dirname as dirname4 } from "path";
|
|
@@ -3599,8 +3609,8 @@ function linkSessionToTask(db, sessionId, taskId) {
|
|
|
3599
3609
|
}
|
|
3600
3610
|
function addConversationTurn(db, sessionId, turnNumber, userPrompt, assistantResponse, toolCallsJson, toolCallCount, promptTokens, responseTokens) {
|
|
3601
3611
|
const result = db.prepare(`
|
|
3602
|
-
INSERT INTO conversation_turns (session_id, turn_number, user_prompt, assistant_response, tool_calls_json, tool_call_count, prompt_tokens, response_tokens)
|
|
3603
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
3612
|
+
INSERT INTO conversation_turns (session_id, turn_number, user_prompt, assistant_response, tool_calls_json, tool_call_count, prompt_tokens, response_tokens, created_at)
|
|
3613
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3604
3614
|
`).run(
|
|
3605
3615
|
sessionId,
|
|
3606
3616
|
turnNumber,
|
|
@@ -3609,14 +3619,15 @@ function addConversationTurn(db, sessionId, turnNumber, userPrompt, assistantRes
|
|
|
3609
3619
|
toolCallsJson,
|
|
3610
3620
|
toolCallCount,
|
|
3611
3621
|
promptTokens,
|
|
3612
|
-
responseTokens
|
|
3622
|
+
responseTokens,
|
|
3623
|
+
nowIso()
|
|
3613
3624
|
);
|
|
3614
3625
|
return Number(result.lastInsertRowid);
|
|
3615
3626
|
}
|
|
3616
3627
|
function addToolCallDetail(db, sessionId, turnNumber, toolName, inputSummary, inputSize, outputSize, success, filesInvolved) {
|
|
3617
3628
|
db.prepare(`
|
|
3618
|
-
INSERT INTO tool_call_details (session_id, turn_number, tool_name, tool_input_summary, tool_input_size, tool_output_size, tool_success, files_involved)
|
|
3619
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
3629
|
+
INSERT INTO tool_call_details (session_id, turn_number, tool_name, tool_input_summary, tool_input_size, tool_output_size, tool_success, files_involved, created_at)
|
|
3630
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3620
3631
|
`).run(
|
|
3621
3632
|
sessionId,
|
|
3622
3633
|
turnNumber,
|
|
@@ -3625,7 +3636,8 @@ function addToolCallDetail(db, sessionId, turnNumber, toolName, inputSummary, in
|
|
|
3625
3636
|
inputSize,
|
|
3626
3637
|
outputSize,
|
|
3627
3638
|
success ? 1 : 0,
|
|
3628
|
-
filesInvolved ? JSON.stringify(filesInvolved) : null
|
|
3639
|
+
filesInvolved ? JSON.stringify(filesInvolved) : null,
|
|
3640
|
+
nowIso()
|
|
3629
3641
|
);
|
|
3630
3642
|
}
|
|
3631
3643
|
function getLastProcessedLine(db, sessionId) {
|
|
@@ -3884,6 +3896,7 @@ var init_memory_db = __esm({
|
|
|
3884
3896
|
init_db_driver();
|
|
3885
3897
|
init_config();
|
|
3886
3898
|
init_memory_vector();
|
|
3899
|
+
init_timestamps();
|
|
3887
3900
|
init_db_backup();
|
|
3888
3901
|
init_rule_delivery();
|
|
3889
3902
|
init_rule_candidate_store();
|
|
@@ -3973,12 +3986,43 @@ var init_hook_failure_signal = __esm({
|
|
|
3973
3986
|
});
|
|
3974
3987
|
|
|
3975
3988
|
// src/hooks/lib/write-hook-message.ts
|
|
3976
|
-
|
|
3977
|
-
|
|
3989
|
+
var HOOK_EVENTS = [
|
|
3990
|
+
"UserPromptSubmit",
|
|
3991
|
+
"UserPromptExpansion",
|
|
3992
|
+
"SessionStart",
|
|
3993
|
+
"PreToolUse",
|
|
3994
|
+
"PostToolUse",
|
|
3995
|
+
"Stop",
|
|
3996
|
+
"SubagentStop",
|
|
3997
|
+
"PreCompact"
|
|
3998
|
+
];
|
|
3999
|
+
var ADDITIONAL_CONTEXT_MAX_CHARS = 1e4;
|
|
4000
|
+
function isHookEvent(value) {
|
|
4001
|
+
return typeof value === "string" && HOOK_EVENTS.includes(value);
|
|
4002
|
+
}
|
|
4003
|
+
function writeHookContext(hookEventName, message) {
|
|
4004
|
+
if (!isHookEvent(hookEventName)) {
|
|
4005
|
+
process.stderr.write(
|
|
4006
|
+
`[massu] writeHookContext: refusing to emit \u2014 unrecognised hook event ${JSON.stringify(hookEventName)}. Known: ${HOOK_EVENTS.join(", ")}.
|
|
4007
|
+
`
|
|
4008
|
+
);
|
|
4009
|
+
return;
|
|
4010
|
+
}
|
|
4011
|
+
if (typeof message !== "string" || message.length === 0) return;
|
|
4012
|
+
let additionalContext = message;
|
|
4013
|
+
if (additionalContext.length > ADDITIONAL_CONTEXT_MAX_CHARS) {
|
|
4014
|
+
const marker = `
|
|
4015
|
+
[massu] \u2026truncated at ${ADDITIONAL_CONTEXT_MAX_CHARS} chars (spec cap).`;
|
|
4016
|
+
additionalContext = additionalContext.slice(0, ADDITIONAL_CONTEXT_MAX_CHARS - marker.length) + marker;
|
|
4017
|
+
}
|
|
4018
|
+
process.stdout.write(
|
|
4019
|
+
JSON.stringify({ hookSpecificOutput: { hookEventName, additionalContext } }) + "\n"
|
|
4020
|
+
);
|
|
3978
4021
|
}
|
|
3979
4022
|
|
|
3980
4023
|
// src/hooks/intent-suggester.ts
|
|
3981
4024
|
init_hook_failure_signal();
|
|
4025
|
+
var HOOK_EVENT = "UserPromptSubmit";
|
|
3982
4026
|
var COMMAND_MAPPINGS = [
|
|
3983
4027
|
{
|
|
3984
4028
|
keywords: ["test", "failing"],
|
|
@@ -4056,7 +4100,7 @@ async function main() {
|
|
|
4056
4100
|
process.exit(0);
|
|
4057
4101
|
return;
|
|
4058
4102
|
}
|
|
4059
|
-
|
|
4103
|
+
writeHookContext(HOOK_EVENT, `Tip: Use ${match.command} to ${match.description}.`);
|
|
4060
4104
|
} catch (err) {
|
|
4061
4105
|
recordHookFailure("intent-suggester", err);
|
|
4062
4106
|
}
|
|
@@ -1360,6 +1360,16 @@ var init_memory_vector = __esm({
|
|
|
1360
1360
|
}
|
|
1361
1361
|
});
|
|
1362
1362
|
|
|
1363
|
+
// src/lib/timestamps.ts
|
|
1364
|
+
function nowIso() {
|
|
1365
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
1366
|
+
}
|
|
1367
|
+
var init_timestamps = __esm({
|
|
1368
|
+
"src/lib/timestamps.ts"() {
|
|
1369
|
+
"use strict";
|
|
1370
|
+
}
|
|
1371
|
+
});
|
|
1372
|
+
|
|
1363
1373
|
// src/db-backup.ts
|
|
1364
1374
|
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readdirSync, statSync, unlinkSync, copyFileSync, rmSync as rmSync4 } from "fs";
|
|
1365
1375
|
import { resolve as resolve3, join as join3, basename, dirname as dirname4 } from "path";
|
|
@@ -3706,8 +3716,8 @@ function linkSessionToTask(db, sessionId, taskId) {
|
|
|
3706
3716
|
}
|
|
3707
3717
|
function addConversationTurn(db, sessionId, turnNumber, userPrompt, assistantResponse, toolCallsJson, toolCallCount, promptTokens, responseTokens) {
|
|
3708
3718
|
const result = db.prepare(`
|
|
3709
|
-
INSERT INTO conversation_turns (session_id, turn_number, user_prompt, assistant_response, tool_calls_json, tool_call_count, prompt_tokens, response_tokens)
|
|
3710
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
3719
|
+
INSERT INTO conversation_turns (session_id, turn_number, user_prompt, assistant_response, tool_calls_json, tool_call_count, prompt_tokens, response_tokens, created_at)
|
|
3720
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3711
3721
|
`).run(
|
|
3712
3722
|
sessionId,
|
|
3713
3723
|
turnNumber,
|
|
@@ -3716,14 +3726,15 @@ function addConversationTurn(db, sessionId, turnNumber, userPrompt, assistantRes
|
|
|
3716
3726
|
toolCallsJson,
|
|
3717
3727
|
toolCallCount,
|
|
3718
3728
|
promptTokens,
|
|
3719
|
-
responseTokens
|
|
3729
|
+
responseTokens,
|
|
3730
|
+
nowIso()
|
|
3720
3731
|
);
|
|
3721
3732
|
return Number(result.lastInsertRowid);
|
|
3722
3733
|
}
|
|
3723
3734
|
function addToolCallDetail(db, sessionId, turnNumber, toolName, inputSummary, inputSize, outputSize, success, filesInvolved) {
|
|
3724
3735
|
db.prepare(`
|
|
3725
|
-
INSERT INTO tool_call_details (session_id, turn_number, tool_name, tool_input_summary, tool_input_size, tool_output_size, tool_success, files_involved)
|
|
3726
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
3736
|
+
INSERT INTO tool_call_details (session_id, turn_number, tool_name, tool_input_summary, tool_input_size, tool_output_size, tool_success, files_involved, created_at)
|
|
3737
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3727
3738
|
`).run(
|
|
3728
3739
|
sessionId,
|
|
3729
3740
|
turnNumber,
|
|
@@ -3732,7 +3743,8 @@ function addToolCallDetail(db, sessionId, turnNumber, toolName, inputSummary, in
|
|
|
3732
3743
|
inputSize,
|
|
3733
3744
|
outputSize,
|
|
3734
3745
|
success ? 1 : 0,
|
|
3735
|
-
filesInvolved ? JSON.stringify(filesInvolved) : null
|
|
3746
|
+
filesInvolved ? JSON.stringify(filesInvolved) : null,
|
|
3747
|
+
nowIso()
|
|
3736
3748
|
);
|
|
3737
3749
|
}
|
|
3738
3750
|
function getLastProcessedLine(db, sessionId) {
|
|
@@ -3991,6 +4003,7 @@ var init_memory_db = __esm({
|
|
|
3991
4003
|
init_db_driver();
|
|
3992
4004
|
init_config();
|
|
3993
4005
|
init_memory_vector();
|
|
4006
|
+
init_timestamps();
|
|
3994
4007
|
init_db_backup();
|
|
3995
4008
|
init_rule_delivery();
|
|
3996
4009
|
init_rule_candidate_store();
|
|
@@ -4520,14 +4533,45 @@ function pendingPointer(db) {
|
|
|
4520
4533
|
init_memory_embedder();
|
|
4521
4534
|
|
|
4522
4535
|
// src/hooks/lib/write-hook-message.ts
|
|
4523
|
-
|
|
4524
|
-
|
|
4536
|
+
var HOOK_EVENTS = [
|
|
4537
|
+
"UserPromptSubmit",
|
|
4538
|
+
"UserPromptExpansion",
|
|
4539
|
+
"SessionStart",
|
|
4540
|
+
"PreToolUse",
|
|
4541
|
+
"PostToolUse",
|
|
4542
|
+
"Stop",
|
|
4543
|
+
"SubagentStop",
|
|
4544
|
+
"PreCompact"
|
|
4545
|
+
];
|
|
4546
|
+
var ADDITIONAL_CONTEXT_MAX_CHARS = 1e4;
|
|
4547
|
+
function isHookEvent(value) {
|
|
4548
|
+
return typeof value === "string" && HOOK_EVENTS.includes(value);
|
|
4549
|
+
}
|
|
4550
|
+
function writeHookContext(hookEventName, message) {
|
|
4551
|
+
if (!isHookEvent(hookEventName)) {
|
|
4552
|
+
process.stderr.write(
|
|
4553
|
+
`[massu] writeHookContext: refusing to emit \u2014 unrecognised hook event ${JSON.stringify(hookEventName)}. Known: ${HOOK_EVENTS.join(", ")}.
|
|
4554
|
+
`
|
|
4555
|
+
);
|
|
4556
|
+
return;
|
|
4557
|
+
}
|
|
4558
|
+
if (typeof message !== "string" || message.length === 0) return;
|
|
4559
|
+
let additionalContext = message;
|
|
4560
|
+
if (additionalContext.length > ADDITIONAL_CONTEXT_MAX_CHARS) {
|
|
4561
|
+
const marker = `
|
|
4562
|
+
[massu] \u2026truncated at ${ADDITIONAL_CONTEXT_MAX_CHARS} chars (spec cap).`;
|
|
4563
|
+
additionalContext = additionalContext.slice(0, ADDITIONAL_CONTEXT_MAX_CHARS - marker.length) + marker;
|
|
4564
|
+
}
|
|
4565
|
+
process.stdout.write(
|
|
4566
|
+
JSON.stringify({ hookSpecificOutput: { hookEventName, additionalContext } }) + "\n"
|
|
4567
|
+
);
|
|
4525
4568
|
}
|
|
4526
4569
|
|
|
4527
4570
|
// src/hooks/memory-recall.ts
|
|
4528
4571
|
init_db_driver();
|
|
4529
4572
|
init_hook_failure_signal();
|
|
4530
4573
|
import { existsSync as existsSync9 } from "fs";
|
|
4574
|
+
var HOOK_EVENT = "UserPromptSubmit";
|
|
4531
4575
|
var DEFAULTS = {
|
|
4532
4576
|
enabled: true,
|
|
4533
4577
|
maxTokens: 1200,
|
|
@@ -4581,7 +4625,7 @@ async function main() {
|
|
|
4581
4625
|
cfg.timeoutMs
|
|
4582
4626
|
);
|
|
4583
4627
|
if (block && block.trim()) {
|
|
4584
|
-
|
|
4628
|
+
writeHookContext(HOOK_EVENT, block);
|
|
4585
4629
|
}
|
|
4586
4630
|
} catch {
|
|
4587
4631
|
} finally {
|
|
@@ -1339,6 +1339,16 @@ var init_memory_vector = __esm({
|
|
|
1339
1339
|
}
|
|
1340
1340
|
});
|
|
1341
1341
|
|
|
1342
|
+
// src/lib/timestamps.ts
|
|
1343
|
+
function nowIso() {
|
|
1344
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
1345
|
+
}
|
|
1346
|
+
var init_timestamps = __esm({
|
|
1347
|
+
"src/lib/timestamps.ts"() {
|
|
1348
|
+
"use strict";
|
|
1349
|
+
}
|
|
1350
|
+
});
|
|
1351
|
+
|
|
1342
1352
|
// src/db-backup.ts
|
|
1343
1353
|
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readdirSync, statSync, unlinkSync, copyFileSync, rmSync as rmSync4 } from "fs";
|
|
1344
1354
|
import { resolve as resolve3, join as join3, basename, dirname as dirname4 } from "path";
|
|
@@ -3599,8 +3609,8 @@ function linkSessionToTask(db, sessionId, taskId) {
|
|
|
3599
3609
|
}
|
|
3600
3610
|
function addConversationTurn(db, sessionId, turnNumber, userPrompt, assistantResponse, toolCallsJson, toolCallCount, promptTokens, responseTokens) {
|
|
3601
3611
|
const result = db.prepare(`
|
|
3602
|
-
INSERT INTO conversation_turns (session_id, turn_number, user_prompt, assistant_response, tool_calls_json, tool_call_count, prompt_tokens, response_tokens)
|
|
3603
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
3612
|
+
INSERT INTO conversation_turns (session_id, turn_number, user_prompt, assistant_response, tool_calls_json, tool_call_count, prompt_tokens, response_tokens, created_at)
|
|
3613
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3604
3614
|
`).run(
|
|
3605
3615
|
sessionId,
|
|
3606
3616
|
turnNumber,
|
|
@@ -3609,14 +3619,15 @@ function addConversationTurn(db, sessionId, turnNumber, userPrompt, assistantRes
|
|
|
3609
3619
|
toolCallsJson,
|
|
3610
3620
|
toolCallCount,
|
|
3611
3621
|
promptTokens,
|
|
3612
|
-
responseTokens
|
|
3622
|
+
responseTokens,
|
|
3623
|
+
nowIso()
|
|
3613
3624
|
);
|
|
3614
3625
|
return Number(result.lastInsertRowid);
|
|
3615
3626
|
}
|
|
3616
3627
|
function addToolCallDetail(db, sessionId, turnNumber, toolName, inputSummary, inputSize, outputSize, success, filesInvolved) {
|
|
3617
3628
|
db.prepare(`
|
|
3618
|
-
INSERT INTO tool_call_details (session_id, turn_number, tool_name, tool_input_summary, tool_input_size, tool_output_size, tool_success, files_involved)
|
|
3619
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
3629
|
+
INSERT INTO tool_call_details (session_id, turn_number, tool_name, tool_input_summary, tool_input_size, tool_output_size, tool_success, files_involved, created_at)
|
|
3630
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3620
3631
|
`).run(
|
|
3621
3632
|
sessionId,
|
|
3622
3633
|
turnNumber,
|
|
@@ -3625,7 +3636,8 @@ function addToolCallDetail(db, sessionId, turnNumber, toolName, inputSummary, in
|
|
|
3625
3636
|
inputSize,
|
|
3626
3637
|
outputSize,
|
|
3627
3638
|
success ? 1 : 0,
|
|
3628
|
-
filesInvolved ? JSON.stringify(filesInvolved) : null
|
|
3639
|
+
filesInvolved ? JSON.stringify(filesInvolved) : null,
|
|
3640
|
+
nowIso()
|
|
3629
3641
|
);
|
|
3630
3642
|
}
|
|
3631
3643
|
function getLastProcessedLine(db, sessionId) {
|
|
@@ -3884,6 +3896,7 @@ var init_memory_db = __esm({
|
|
|
3884
3896
|
init_db_driver();
|
|
3885
3897
|
init_config();
|
|
3886
3898
|
init_memory_vector();
|
|
3899
|
+
init_timestamps();
|
|
3887
3900
|
init_db_backup();
|
|
3888
3901
|
init_rule_delivery();
|
|
3889
3902
|
init_rule_candidate_store();
|
|
@@ -4013,12 +4026,43 @@ function isInMiddlewareTree(dataDb, file) {
|
|
|
4013
4026
|
init_config();
|
|
4014
4027
|
|
|
4015
4028
|
// src/hooks/lib/write-hook-message.ts
|
|
4016
|
-
|
|
4017
|
-
|
|
4029
|
+
var HOOK_EVENTS = [
|
|
4030
|
+
"UserPromptSubmit",
|
|
4031
|
+
"UserPromptExpansion",
|
|
4032
|
+
"SessionStart",
|
|
4033
|
+
"PreToolUse",
|
|
4034
|
+
"PostToolUse",
|
|
4035
|
+
"Stop",
|
|
4036
|
+
"SubagentStop",
|
|
4037
|
+
"PreCompact"
|
|
4038
|
+
];
|
|
4039
|
+
var ADDITIONAL_CONTEXT_MAX_CHARS = 1e4;
|
|
4040
|
+
function isHookEvent(value) {
|
|
4041
|
+
return typeof value === "string" && HOOK_EVENTS.includes(value);
|
|
4042
|
+
}
|
|
4043
|
+
function writeHookContext(hookEventName, message) {
|
|
4044
|
+
if (!isHookEvent(hookEventName)) {
|
|
4045
|
+
process.stderr.write(
|
|
4046
|
+
`[massu] writeHookContext: refusing to emit \u2014 unrecognised hook event ${JSON.stringify(hookEventName)}. Known: ${HOOK_EVENTS.join(", ")}.
|
|
4047
|
+
`
|
|
4048
|
+
);
|
|
4049
|
+
return;
|
|
4050
|
+
}
|
|
4051
|
+
if (typeof message !== "string" || message.length === 0) return;
|
|
4052
|
+
let additionalContext = message;
|
|
4053
|
+
if (additionalContext.length > ADDITIONAL_CONTEXT_MAX_CHARS) {
|
|
4054
|
+
const marker = `
|
|
4055
|
+
[massu] \u2026truncated at ${ADDITIONAL_CONTEXT_MAX_CHARS} chars (spec cap).`;
|
|
4056
|
+
additionalContext = additionalContext.slice(0, ADDITIONAL_CONTEXT_MAX_CHARS - marker.length) + marker;
|
|
4057
|
+
}
|
|
4058
|
+
process.stdout.write(
|
|
4059
|
+
JSON.stringify({ hookSpecificOutput: { hookEventName, additionalContext } }) + "\n"
|
|
4060
|
+
);
|
|
4018
4061
|
}
|
|
4019
4062
|
|
|
4020
4063
|
// src/hooks/post-edit-context.ts
|
|
4021
4064
|
init_hook_failure_signal();
|
|
4065
|
+
var HOOK_EVENT = "PostToolUse";
|
|
4022
4066
|
async function main() {
|
|
4023
4067
|
try {
|
|
4024
4068
|
const input = await readStdin();
|
|
@@ -4055,7 +4099,7 @@ async function main() {
|
|
|
4055
4099
|
} catch (_e) {
|
|
4056
4100
|
}
|
|
4057
4101
|
if (warnings.length > 0) {
|
|
4058
|
-
|
|
4102
|
+
writeHookContext(HOOK_EVENT, `[Massu] ${warnings.join(" | ")}`);
|
|
4059
4103
|
}
|
|
4060
4104
|
} catch (err) {
|
|
4061
4105
|
recordHookFailure("post-edit-context", err);
|
|
@@ -1345,6 +1345,16 @@ var init_memory_vector = __esm({
|
|
|
1345
1345
|
}
|
|
1346
1346
|
});
|
|
1347
1347
|
|
|
1348
|
+
// src/lib/timestamps.ts
|
|
1349
|
+
function nowIso() {
|
|
1350
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
1351
|
+
}
|
|
1352
|
+
var init_timestamps = __esm({
|
|
1353
|
+
"src/lib/timestamps.ts"() {
|
|
1354
|
+
"use strict";
|
|
1355
|
+
}
|
|
1356
|
+
});
|
|
1357
|
+
|
|
1348
1358
|
// src/db-backup.ts
|
|
1349
1359
|
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readdirSync, statSync, unlinkSync, copyFileSync, rmSync as rmSync4 } from "fs";
|
|
1350
1360
|
import { resolve as resolve3, join as join3, basename, dirname as dirname4 } from "path";
|
|
@@ -3676,8 +3686,8 @@ function linkSessionToTask(db, sessionId, taskId) {
|
|
|
3676
3686
|
}
|
|
3677
3687
|
function addConversationTurn(db, sessionId, turnNumber, userPrompt, assistantResponse, toolCallsJson, toolCallCount, promptTokens, responseTokens) {
|
|
3678
3688
|
const result = db.prepare(`
|
|
3679
|
-
INSERT INTO conversation_turns (session_id, turn_number, user_prompt, assistant_response, tool_calls_json, tool_call_count, prompt_tokens, response_tokens)
|
|
3680
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
3689
|
+
INSERT INTO conversation_turns (session_id, turn_number, user_prompt, assistant_response, tool_calls_json, tool_call_count, prompt_tokens, response_tokens, created_at)
|
|
3690
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3681
3691
|
`).run(
|
|
3682
3692
|
sessionId,
|
|
3683
3693
|
turnNumber,
|
|
@@ -3686,14 +3696,15 @@ function addConversationTurn(db, sessionId, turnNumber, userPrompt, assistantRes
|
|
|
3686
3696
|
toolCallsJson,
|
|
3687
3697
|
toolCallCount,
|
|
3688
3698
|
promptTokens,
|
|
3689
|
-
responseTokens
|
|
3699
|
+
responseTokens,
|
|
3700
|
+
nowIso()
|
|
3690
3701
|
);
|
|
3691
3702
|
return Number(result.lastInsertRowid);
|
|
3692
3703
|
}
|
|
3693
3704
|
function addToolCallDetail(db, sessionId, turnNumber, toolName, inputSummary, inputSize, outputSize, success, filesInvolved) {
|
|
3694
3705
|
db.prepare(`
|
|
3695
|
-
INSERT INTO tool_call_details (session_id, turn_number, tool_name, tool_input_summary, tool_input_size, tool_output_size, tool_success, files_involved)
|
|
3696
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
3706
|
+
INSERT INTO tool_call_details (session_id, turn_number, tool_name, tool_input_summary, tool_input_size, tool_output_size, tool_success, files_involved, created_at)
|
|
3707
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3697
3708
|
`).run(
|
|
3698
3709
|
sessionId,
|
|
3699
3710
|
turnNumber,
|
|
@@ -3702,7 +3713,8 @@ function addToolCallDetail(db, sessionId, turnNumber, toolName, inputSummary, in
|
|
|
3702
3713
|
inputSize,
|
|
3703
3714
|
outputSize,
|
|
3704
3715
|
success ? 1 : 0,
|
|
3705
|
-
filesInvolved ? JSON.stringify(filesInvolved) : null
|
|
3716
|
+
filesInvolved ? JSON.stringify(filesInvolved) : null,
|
|
3717
|
+
nowIso()
|
|
3706
3718
|
);
|
|
3707
3719
|
}
|
|
3708
3720
|
function getLastProcessedLine(db, sessionId) {
|
|
@@ -3961,6 +3973,7 @@ var init_memory_db = __esm({
|
|
|
3961
3973
|
init_db_driver();
|
|
3962
3974
|
init_config();
|
|
3963
3975
|
init_memory_vector();
|
|
3976
|
+
init_timestamps();
|
|
3964
3977
|
init_db_backup();
|
|
3965
3978
|
init_rule_delivery();
|
|
3966
3979
|
init_rule_candidate_store();
|
|
@@ -1339,6 +1339,16 @@ var init_memory_vector = __esm({
|
|
|
1339
1339
|
}
|
|
1340
1340
|
});
|
|
1341
1341
|
|
|
1342
|
+
// src/lib/timestamps.ts
|
|
1343
|
+
function nowIso() {
|
|
1344
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
1345
|
+
}
|
|
1346
|
+
var init_timestamps = __esm({
|
|
1347
|
+
"src/lib/timestamps.ts"() {
|
|
1348
|
+
"use strict";
|
|
1349
|
+
}
|
|
1350
|
+
});
|
|
1351
|
+
|
|
1342
1352
|
// src/db-backup.ts
|
|
1343
1353
|
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readdirSync, statSync, unlinkSync, copyFileSync, rmSync as rmSync4 } from "fs";
|
|
1344
1354
|
import { resolve as resolve3, join as join3, basename, dirname as dirname4 } from "path";
|
|
@@ -3670,8 +3680,8 @@ function linkSessionToTask(db, sessionId, taskId) {
|
|
|
3670
3680
|
}
|
|
3671
3681
|
function addConversationTurn(db, sessionId, turnNumber, userPrompt, assistantResponse, toolCallsJson, toolCallCount, promptTokens, responseTokens) {
|
|
3672
3682
|
const result = db.prepare(`
|
|
3673
|
-
INSERT INTO conversation_turns (session_id, turn_number, user_prompt, assistant_response, tool_calls_json, tool_call_count, prompt_tokens, response_tokens)
|
|
3674
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
3683
|
+
INSERT INTO conversation_turns (session_id, turn_number, user_prompt, assistant_response, tool_calls_json, tool_call_count, prompt_tokens, response_tokens, created_at)
|
|
3684
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3675
3685
|
`).run(
|
|
3676
3686
|
sessionId,
|
|
3677
3687
|
turnNumber,
|
|
@@ -3680,14 +3690,15 @@ function addConversationTurn(db, sessionId, turnNumber, userPrompt, assistantRes
|
|
|
3680
3690
|
toolCallsJson,
|
|
3681
3691
|
toolCallCount,
|
|
3682
3692
|
promptTokens,
|
|
3683
|
-
responseTokens
|
|
3693
|
+
responseTokens,
|
|
3694
|
+
nowIso()
|
|
3684
3695
|
);
|
|
3685
3696
|
return Number(result.lastInsertRowid);
|
|
3686
3697
|
}
|
|
3687
3698
|
function addToolCallDetail(db, sessionId, turnNumber, toolName, inputSummary, inputSize, outputSize, success, filesInvolved) {
|
|
3688
3699
|
db.prepare(`
|
|
3689
|
-
INSERT INTO tool_call_details (session_id, turn_number, tool_name, tool_input_summary, tool_input_size, tool_output_size, tool_success, files_involved)
|
|
3690
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
3700
|
+
INSERT INTO tool_call_details (session_id, turn_number, tool_name, tool_input_summary, tool_input_size, tool_output_size, tool_success, files_involved, created_at)
|
|
3701
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3691
3702
|
`).run(
|
|
3692
3703
|
sessionId,
|
|
3693
3704
|
turnNumber,
|
|
@@ -3696,7 +3707,8 @@ function addToolCallDetail(db, sessionId, turnNumber, toolName, inputSummary, in
|
|
|
3696
3707
|
inputSize,
|
|
3697
3708
|
outputSize,
|
|
3698
3709
|
success ? 1 : 0,
|
|
3699
|
-
filesInvolved ? JSON.stringify(filesInvolved) : null
|
|
3710
|
+
filesInvolved ? JSON.stringify(filesInvolved) : null,
|
|
3711
|
+
nowIso()
|
|
3700
3712
|
);
|
|
3701
3713
|
}
|
|
3702
3714
|
function getLastProcessedLine(db, sessionId) {
|
|
@@ -3955,6 +3967,7 @@ var init_memory_db = __esm({
|
|
|
3955
3967
|
init_db_driver();
|
|
3956
3968
|
init_config();
|
|
3957
3969
|
init_memory_vector();
|
|
3970
|
+
init_timestamps();
|
|
3958
3971
|
init_db_backup();
|
|
3959
3972
|
init_rule_delivery();
|
|
3960
3973
|
init_rule_candidate_store();
|
|
@@ -1339,6 +1339,16 @@ var init_memory_vector = __esm({
|
|
|
1339
1339
|
}
|
|
1340
1340
|
});
|
|
1341
1341
|
|
|
1342
|
+
// src/lib/timestamps.ts
|
|
1343
|
+
function nowIso() {
|
|
1344
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
1345
|
+
}
|
|
1346
|
+
var init_timestamps = __esm({
|
|
1347
|
+
"src/lib/timestamps.ts"() {
|
|
1348
|
+
"use strict";
|
|
1349
|
+
}
|
|
1350
|
+
});
|
|
1351
|
+
|
|
1342
1352
|
// src/db-backup.ts
|
|
1343
1353
|
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readdirSync, statSync, unlinkSync, copyFileSync, rmSync as rmSync4 } from "fs";
|
|
1344
1354
|
import { resolve as resolve3, join as join3, basename, dirname as dirname4 } from "path";
|
|
@@ -3670,8 +3680,8 @@ function linkSessionToTask(db, sessionId, taskId) {
|
|
|
3670
3680
|
}
|
|
3671
3681
|
function addConversationTurn(db, sessionId, turnNumber, userPrompt, assistantResponse, toolCallsJson, toolCallCount, promptTokens, responseTokens) {
|
|
3672
3682
|
const result = db.prepare(`
|
|
3673
|
-
INSERT INTO conversation_turns (session_id, turn_number, user_prompt, assistant_response, tool_calls_json, tool_call_count, prompt_tokens, response_tokens)
|
|
3674
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
3683
|
+
INSERT INTO conversation_turns (session_id, turn_number, user_prompt, assistant_response, tool_calls_json, tool_call_count, prompt_tokens, response_tokens, created_at)
|
|
3684
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3675
3685
|
`).run(
|
|
3676
3686
|
sessionId,
|
|
3677
3687
|
turnNumber,
|
|
@@ -3680,14 +3690,15 @@ function addConversationTurn(db, sessionId, turnNumber, userPrompt, assistantRes
|
|
|
3680
3690
|
toolCallsJson,
|
|
3681
3691
|
toolCallCount,
|
|
3682
3692
|
promptTokens,
|
|
3683
|
-
responseTokens
|
|
3693
|
+
responseTokens,
|
|
3694
|
+
nowIso()
|
|
3684
3695
|
);
|
|
3685
3696
|
return Number(result.lastInsertRowid);
|
|
3686
3697
|
}
|
|
3687
3698
|
function addToolCallDetail(db, sessionId, turnNumber, toolName, inputSummary, inputSize, outputSize, success, filesInvolved) {
|
|
3688
3699
|
db.prepare(`
|
|
3689
|
-
INSERT INTO tool_call_details (session_id, turn_number, tool_name, tool_input_summary, tool_input_size, tool_output_size, tool_success, files_involved)
|
|
3690
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
3700
|
+
INSERT INTO tool_call_details (session_id, turn_number, tool_name, tool_input_summary, tool_input_size, tool_output_size, tool_success, files_involved, created_at)
|
|
3701
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3691
3702
|
`).run(
|
|
3692
3703
|
sessionId,
|
|
3693
3704
|
turnNumber,
|
|
@@ -3696,7 +3707,8 @@ function addToolCallDetail(db, sessionId, turnNumber, toolName, inputSummary, in
|
|
|
3696
3707
|
inputSize,
|
|
3697
3708
|
outputSize,
|
|
3698
3709
|
success ? 1 : 0,
|
|
3699
|
-
filesInvolved ? JSON.stringify(filesInvolved) : null
|
|
3710
|
+
filesInvolved ? JSON.stringify(filesInvolved) : null,
|
|
3711
|
+
nowIso()
|
|
3700
3712
|
);
|
|
3701
3713
|
}
|
|
3702
3714
|
function getLastProcessedLine(db, sessionId) {
|
|
@@ -3955,6 +3967,7 @@ var init_memory_db = __esm({
|
|
|
3955
3967
|
init_db_driver();
|
|
3956
3968
|
init_config();
|
|
3957
3969
|
init_memory_vector();
|
|
3970
|
+
init_timestamps();
|
|
3958
3971
|
init_db_backup();
|
|
3959
3972
|
init_rule_delivery();
|
|
3960
3973
|
init_rule_candidate_store();
|
|
@@ -4072,12 +4085,43 @@ function getFeatureImpact(db, filePaths) {
|
|
|
4072
4085
|
init_config();
|
|
4073
4086
|
|
|
4074
4087
|
// src/hooks/lib/write-hook-message.ts
|
|
4075
|
-
|
|
4076
|
-
|
|
4088
|
+
var HOOK_EVENTS = [
|
|
4089
|
+
"UserPromptSubmit",
|
|
4090
|
+
"UserPromptExpansion",
|
|
4091
|
+
"SessionStart",
|
|
4092
|
+
"PreToolUse",
|
|
4093
|
+
"PostToolUse",
|
|
4094
|
+
"Stop",
|
|
4095
|
+
"SubagentStop",
|
|
4096
|
+
"PreCompact"
|
|
4097
|
+
];
|
|
4098
|
+
var ADDITIONAL_CONTEXT_MAX_CHARS = 1e4;
|
|
4099
|
+
function isHookEvent(value) {
|
|
4100
|
+
return typeof value === "string" && HOOK_EVENTS.includes(value);
|
|
4101
|
+
}
|
|
4102
|
+
function writeHookContext(hookEventName, message) {
|
|
4103
|
+
if (!isHookEvent(hookEventName)) {
|
|
4104
|
+
process.stderr.write(
|
|
4105
|
+
`[massu] writeHookContext: refusing to emit \u2014 unrecognised hook event ${JSON.stringify(hookEventName)}. Known: ${HOOK_EVENTS.join(", ")}.
|
|
4106
|
+
`
|
|
4107
|
+
);
|
|
4108
|
+
return;
|
|
4109
|
+
}
|
|
4110
|
+
if (typeof message !== "string" || message.length === 0) return;
|
|
4111
|
+
let additionalContext = message;
|
|
4112
|
+
if (additionalContext.length > ADDITIONAL_CONTEXT_MAX_CHARS) {
|
|
4113
|
+
const marker = `
|
|
4114
|
+
[massu] \u2026truncated at ${ADDITIONAL_CONTEXT_MAX_CHARS} chars (spec cap).`;
|
|
4115
|
+
additionalContext = additionalContext.slice(0, ADDITIONAL_CONTEXT_MAX_CHARS - marker.length) + marker;
|
|
4116
|
+
}
|
|
4117
|
+
process.stdout.write(
|
|
4118
|
+
JSON.stringify({ hookSpecificOutput: { hookEventName, additionalContext } }) + "\n"
|
|
4119
|
+
);
|
|
4077
4120
|
}
|
|
4078
4121
|
|
|
4079
4122
|
// src/hooks/pre-delete-check.ts
|
|
4080
4123
|
init_hook_failure_signal();
|
|
4124
|
+
var HOOK_EVENT = "PreToolUse";
|
|
4081
4125
|
var PROJECT_ROOT2 = getProjectRoot();
|
|
4082
4126
|
var KNOWLEDGE_PROTECTED_FILES = [
|
|
4083
4127
|
"knowledge-db.ts",
|
|
@@ -4221,7 +4265,7 @@ async function main() {
|
|
|
4221
4265
|
const input = await readStdin();
|
|
4222
4266
|
const hookInput = JSON.parse(input);
|
|
4223
4267
|
const messages = runPreDeleteChecks(hookInput);
|
|
4224
|
-
for (const msg of messages)
|
|
4268
|
+
for (const msg of messages) writeHookContext(HOOK_EVENT, msg);
|
|
4225
4269
|
} catch (err) {
|
|
4226
4270
|
recordHookFailure("pre-delete-check", err);
|
|
4227
4271
|
process.stderr.write("MASSU SECURITY GATE \u2014 BLOCKED (gate could not evaluate this call)\n");
|