@scotthamilton77/sidekick 0.1.9 → 0.1.11
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/bin.js +327 -132
- package/dist/daemon.js +336 -131
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -1098,6 +1098,7 @@ var require_events = __commonJS({
|
|
|
1098
1098
|
"reminder:unstaged",
|
|
1099
1099
|
"reminder:consumed",
|
|
1100
1100
|
"reminder:cleared",
|
|
1101
|
+
"reminder:not-staged",
|
|
1101
1102
|
// Decision events
|
|
1102
1103
|
"decision:recorded",
|
|
1103
1104
|
// Session summary events
|
|
@@ -1146,6 +1147,7 @@ var require_events = __commonJS({
|
|
|
1146
1147
|
"reminder:unstaged": "timeline",
|
|
1147
1148
|
"reminder:consumed": "timeline",
|
|
1148
1149
|
"reminder:cleared": "timeline",
|
|
1150
|
+
"reminder:not-staged": "log",
|
|
1149
1151
|
"decision:recorded": "timeline",
|
|
1150
1152
|
"session-summary:start": "timeline",
|
|
1151
1153
|
"session-summary:finish": "timeline",
|
|
@@ -45865,7 +45867,10 @@ var require_structured_logging = __commonJS({
|
|
|
45865
45867
|
hookName: state.hookName,
|
|
45866
45868
|
blocking: state.blocking,
|
|
45867
45869
|
priority: state.priority,
|
|
45868
|
-
persistent: state.persistent
|
|
45870
|
+
persistent: state.persistent,
|
|
45871
|
+
...state.reason !== void 0 && { reason: state.reason },
|
|
45872
|
+
...state.triggeredBy !== void 0 && { triggeredBy: state.triggeredBy },
|
|
45873
|
+
...state.thresholdState !== void 0 && { thresholdState: state.thresholdState }
|
|
45869
45874
|
}
|
|
45870
45875
|
};
|
|
45871
45876
|
},
|
|
@@ -46162,8 +46167,8 @@ var require_structured_logging = __commonJS({
|
|
|
46162
46167
|
},
|
|
46163
46168
|
// --- Error Events ---
|
|
46164
46169
|
/**
|
|
46165
|
-
* Create
|
|
46166
|
-
*
|
|
46170
|
+
* Create a daemon ErrorOccurred event.
|
|
46171
|
+
* @see packages/sidekick-daemon/src/daemon.ts — HookableLogger error hook calls this factory.
|
|
46167
46172
|
*/
|
|
46168
46173
|
daemonErrorOccurred(context, state) {
|
|
46169
46174
|
return {
|
|
@@ -46182,6 +46187,28 @@ var require_structured_logging = __commonJS({
|
|
|
46182
46187
|
errorStack: state.errorStack
|
|
46183
46188
|
}
|
|
46184
46189
|
};
|
|
46190
|
+
},
|
|
46191
|
+
/**
|
|
46192
|
+
* Create a CLI ErrorOccurred event.
|
|
46193
|
+
* Available for CLI error hook implementations.
|
|
46194
|
+
*/
|
|
46195
|
+
cliErrorOccurred(context, state) {
|
|
46196
|
+
return {
|
|
46197
|
+
type: "error:occurred",
|
|
46198
|
+
time: Date.now(),
|
|
46199
|
+
source: "cli",
|
|
46200
|
+
context: {
|
|
46201
|
+
sessionId: context.sessionId,
|
|
46202
|
+
correlationId: context.correlationId,
|
|
46203
|
+
traceId: context.traceId,
|
|
46204
|
+
hook: context.hook,
|
|
46205
|
+
taskId: context.taskId
|
|
46206
|
+
},
|
|
46207
|
+
payload: {
|
|
46208
|
+
errorMessage: state.errorMessage,
|
|
46209
|
+
errorStack: state.errorStack
|
|
46210
|
+
}
|
|
46211
|
+
};
|
|
46185
46212
|
}
|
|
46186
46213
|
};
|
|
46187
46214
|
function logEvent(logger, event) {
|
|
@@ -58137,24 +58164,20 @@ var require_staging_paths = __commonJS({
|
|
|
58137
58164
|
function getReminderPath(stateDir, sessionId, hookName, reminderName) {
|
|
58138
58165
|
return (0, node_path_1.join)(getHookDir(stateDir, sessionId, hookName), `${reminderName}.json`);
|
|
58139
58166
|
}
|
|
58140
|
-
function isValidPathSegment(
|
|
58141
|
-
if (
|
|
58167
|
+
function isValidPathSegment(s) {
|
|
58168
|
+
if (s === "")
|
|
58142
58169
|
return false;
|
|
58143
|
-
if (
|
|
58170
|
+
if (s === "." || s === "..")
|
|
58144
58171
|
return false;
|
|
58145
|
-
if (
|
|
58172
|
+
if (s.includes("/") || s.includes("\\"))
|
|
58146
58173
|
return false;
|
|
58147
|
-
|
|
58174
|
+
if ((0, node_path_1.basename)(s) !== s)
|
|
58175
|
+
return false;
|
|
58176
|
+
return /^[a-zA-Z0-9._-]+$/.test(s);
|
|
58148
58177
|
}
|
|
58149
58178
|
function validatePathSegment(segment, name) {
|
|
58150
|
-
if (!segment) {
|
|
58151
|
-
throw new Error(
|
|
58152
|
-
}
|
|
58153
|
-
if (segment.includes("..") || segment.includes("/") || segment.includes("\\")) {
|
|
58154
|
-
throw new Error(`Invalid ${name}: path traversal characters not allowed`);
|
|
58155
|
-
}
|
|
58156
|
-
if (segment.startsWith(".")) {
|
|
58157
|
-
throw new Error(`Invalid ${name}: cannot start with '.'`);
|
|
58179
|
+
if (!isValidPathSegment(segment)) {
|
|
58180
|
+
throw new Error(`Invalid ${name}: must be a non-empty alphanumeric string without path separators`);
|
|
58158
58181
|
}
|
|
58159
58182
|
}
|
|
58160
58183
|
exports2.CONSUMED_FILE_PATTERN = /\.\d+\.json$/;
|
|
@@ -58228,7 +58251,7 @@ var require_staging_service = __commonJS({
|
|
|
58228
58251
|
*
|
|
58229
58252
|
* @throws Error if hookName or reminderName contain path traversal characters
|
|
58230
58253
|
*/
|
|
58231
|
-
async stageReminder(sessionId, hookName, reminderName, data) {
|
|
58254
|
+
async stageReminder(sessionId, hookName, reminderName, data, enrichment) {
|
|
58232
58255
|
(0, staging_paths_js_1.validatePathSegment)(hookName, "hookName");
|
|
58233
58256
|
(0, staging_paths_js_1.validatePathSegment)(reminderName, "reminderName");
|
|
58234
58257
|
const hookDir = this.getHookDirPath(sessionId, hookName);
|
|
@@ -58257,9 +58280,10 @@ var require_staging_service = __commonJS({
|
|
|
58257
58280
|
hookName,
|
|
58258
58281
|
blocking: data.blocking,
|
|
58259
58282
|
priority: data.priority,
|
|
58260
|
-
persistent: data.persistent
|
|
58283
|
+
persistent: data.persistent,
|
|
58284
|
+
...enrichment
|
|
58261
58285
|
}, { stagingPath: reminderPath });
|
|
58262
|
-
(0, structured_logging_1.logEvent)(this.options.logger, event);
|
|
58286
|
+
(0, structured_logging_1.logEvent)(this.options.logger.child({ context: { sessionId } }), event);
|
|
58263
58287
|
}
|
|
58264
58288
|
/**
|
|
58265
58289
|
* Read a staged reminder.
|
|
@@ -58401,8 +58425,8 @@ var require_staging_service = __commonJS({
|
|
|
58401
58425
|
// ============================================================================
|
|
58402
58426
|
// StagingService Interface Implementation (delegates to core)
|
|
58403
58427
|
// ============================================================================
|
|
58404
|
-
async stageReminder(hookName, reminderName, data) {
|
|
58405
|
-
return this.core.stageReminder(this.sessionId, hookName, reminderName, data);
|
|
58428
|
+
async stageReminder(hookName, reminderName, data, enrichment) {
|
|
58429
|
+
return this.core.stageReminder(this.sessionId, hookName, reminderName, data, enrichment);
|
|
58406
58430
|
}
|
|
58407
58431
|
async readReminder(hookName, reminderName) {
|
|
58408
58432
|
return this.core.readReminder(this.sessionId, hookName, reminderName);
|
|
@@ -71350,8 +71374,8 @@ var require_reminder_utils = __commonJS({
|
|
|
71350
71374
|
return null;
|
|
71351
71375
|
}
|
|
71352
71376
|
}
|
|
71353
|
-
async function stageReminder(ctx, hookName, reminder) {
|
|
71354
|
-
await ctx.staging.stageReminder(hookName, reminder.name, reminder);
|
|
71377
|
+
async function stageReminder(ctx, hookName, reminder, enrichment) {
|
|
71378
|
+
await ctx.staging.stageReminder(hookName, reminder.name, reminder, enrichment);
|
|
71355
71379
|
ctx.logger.debug("Staged reminder", { hookName, reminderName: reminder.name, priority: reminder.priority });
|
|
71356
71380
|
}
|
|
71357
71381
|
async function consumeReminder(ctx, hookName) {
|
|
@@ -71897,13 +71921,125 @@ var require_stage_default_user_prompt = __commonJS({
|
|
|
71897
71921
|
}
|
|
71898
71922
|
});
|
|
71899
71923
|
|
|
71924
|
+
// ../feature-reminders/dist/events.js
|
|
71925
|
+
var require_events2 = __commonJS({
|
|
71926
|
+
"../feature-reminders/dist/events.js"(exports2) {
|
|
71927
|
+
"use strict";
|
|
71928
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
71929
|
+
exports2.ReminderEvents = void 0;
|
|
71930
|
+
exports2.ReminderEvents = {
|
|
71931
|
+
/**
|
|
71932
|
+
* Create a ReminderConsumed event (logged when CLI returns a staged reminder).
|
|
71933
|
+
*/
|
|
71934
|
+
reminderConsumed(context, state, _metadata) {
|
|
71935
|
+
return {
|
|
71936
|
+
type: "reminder:consumed",
|
|
71937
|
+
time: Date.now(),
|
|
71938
|
+
source: "cli",
|
|
71939
|
+
context: {
|
|
71940
|
+
sessionId: context.sessionId,
|
|
71941
|
+
correlationId: context.correlationId,
|
|
71942
|
+
traceId: context.traceId,
|
|
71943
|
+
hook: context.hook,
|
|
71944
|
+
taskId: context.taskId
|
|
71945
|
+
},
|
|
71946
|
+
payload: {
|
|
71947
|
+
reminderName: state.reminderName,
|
|
71948
|
+
reminderReturned: state.reminderReturned,
|
|
71949
|
+
blocking: state.blocking,
|
|
71950
|
+
priority: state.priority,
|
|
71951
|
+
persistent: state.persistent,
|
|
71952
|
+
...state.classificationResult !== void 0 && {
|
|
71953
|
+
classificationResult: state.classificationResult
|
|
71954
|
+
}
|
|
71955
|
+
}
|
|
71956
|
+
};
|
|
71957
|
+
},
|
|
71958
|
+
// Note: reminderStaged stays in @sidekick/core (used by staging-service.ts, circular dep)
|
|
71959
|
+
/**
|
|
71960
|
+
* Create a ReminderUnstaged event (logged when a reminder is removed from staging).
|
|
71961
|
+
*/
|
|
71962
|
+
reminderUnstaged(context, state) {
|
|
71963
|
+
return {
|
|
71964
|
+
type: "reminder:unstaged",
|
|
71965
|
+
time: Date.now(),
|
|
71966
|
+
source: "daemon",
|
|
71967
|
+
context: {
|
|
71968
|
+
sessionId: context.sessionId,
|
|
71969
|
+
correlationId: context.correlationId,
|
|
71970
|
+
traceId: context.traceId,
|
|
71971
|
+
hook: context.hook,
|
|
71972
|
+
taskId: context.taskId
|
|
71973
|
+
},
|
|
71974
|
+
payload: {
|
|
71975
|
+
reminderName: state.reminderName,
|
|
71976
|
+
hookName: state.hookName,
|
|
71977
|
+
reason: state.reason,
|
|
71978
|
+
...state.triggeredBy !== void 0 && { triggeredBy: state.triggeredBy },
|
|
71979
|
+
...state.toolState !== void 0 && { toolState: state.toolState }
|
|
71980
|
+
}
|
|
71981
|
+
};
|
|
71982
|
+
},
|
|
71983
|
+
/**
|
|
71984
|
+
* Create a RemindersCleared event (logged when staging directory is cleaned).
|
|
71985
|
+
*/
|
|
71986
|
+
remindersCleared(context, state, reason) {
|
|
71987
|
+
return {
|
|
71988
|
+
type: "reminder:cleared",
|
|
71989
|
+
time: Date.now(),
|
|
71990
|
+
source: "daemon",
|
|
71991
|
+
context: {
|
|
71992
|
+
sessionId: context.sessionId,
|
|
71993
|
+
correlationId: context.correlationId,
|
|
71994
|
+
traceId: context.traceId,
|
|
71995
|
+
hook: context.hook,
|
|
71996
|
+
taskId: context.taskId
|
|
71997
|
+
},
|
|
71998
|
+
payload: {
|
|
71999
|
+
clearedCount: state.clearedCount,
|
|
72000
|
+
hookNames: state.hookNames,
|
|
72001
|
+
reason
|
|
72002
|
+
}
|
|
72003
|
+
};
|
|
72004
|
+
},
|
|
72005
|
+
/**
|
|
72006
|
+
* Create a ReminderNotStaged event (logged when daemon evaluates but decides not to stage).
|
|
72007
|
+
*/
|
|
72008
|
+
reminderNotStaged(context, state) {
|
|
72009
|
+
return {
|
|
72010
|
+
type: "reminder:not-staged",
|
|
72011
|
+
time: Date.now(),
|
|
72012
|
+
source: "daemon",
|
|
72013
|
+
context: {
|
|
72014
|
+
sessionId: context.sessionId,
|
|
72015
|
+
correlationId: context.correlationId,
|
|
72016
|
+
traceId: context.traceId,
|
|
72017
|
+
hook: context.hook,
|
|
72018
|
+
taskId: context.taskId
|
|
72019
|
+
},
|
|
72020
|
+
payload: {
|
|
72021
|
+
reminderName: state.reminderName,
|
|
72022
|
+
hookName: state.hookName,
|
|
72023
|
+
reason: state.reason,
|
|
72024
|
+
...state.threshold !== void 0 && { threshold: state.threshold },
|
|
72025
|
+
...state.currentValue !== void 0 && { currentValue: state.currentValue },
|
|
72026
|
+
...state.triggeredBy !== void 0 && { triggeredBy: state.triggeredBy }
|
|
72027
|
+
}
|
|
72028
|
+
};
|
|
72029
|
+
}
|
|
72030
|
+
};
|
|
72031
|
+
}
|
|
72032
|
+
});
|
|
72033
|
+
|
|
71900
72034
|
// ../feature-reminders/dist/handlers/staging/stage-pause-and-reflect.js
|
|
71901
72035
|
var require_stage_pause_and_reflect = __commonJS({
|
|
71902
72036
|
"../feature-reminders/dist/handlers/staging/stage-pause-and-reflect.js"(exports2) {
|
|
71903
72037
|
"use strict";
|
|
71904
72038
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
71905
72039
|
exports2.registerStagePauseAndReflect = registerStagePauseAndReflect;
|
|
72040
|
+
var core_1 = require_dist4();
|
|
71906
72041
|
var types_1 = require_dist();
|
|
72042
|
+
var events_js_1 = require_events2();
|
|
71907
72043
|
var staging_handler_utils_js_1 = require_staging_handler_utils();
|
|
71908
72044
|
var types_js_1 = require_types2();
|
|
71909
72045
|
var state_js_1 = require_state4();
|
|
@@ -71917,15 +72053,17 @@ var require_stage_pause_and_reflect = __commonJS({
|
|
|
71917
72053
|
return void 0;
|
|
71918
72054
|
const metrics = event.metadata.metrics;
|
|
71919
72055
|
const sessionId = event.context?.sessionId;
|
|
72056
|
+
if (!sessionId) {
|
|
72057
|
+
ctx.logger.warn("[stage-pause-and-reflect] No sessionId available, skipping");
|
|
72058
|
+
return void 0;
|
|
72059
|
+
}
|
|
71920
72060
|
const featureConfig = context.config.getFeature("reminders");
|
|
71921
72061
|
const config = { ...types_js_1.DEFAULT_REMINDERS_SETTINGS, ...featureConfig.settings };
|
|
71922
72062
|
let prBaseline = null;
|
|
71923
|
-
|
|
71924
|
-
|
|
71925
|
-
|
|
71926
|
-
|
|
71927
|
-
prBaseline = result.data;
|
|
71928
|
-
}
|
|
72063
|
+
const remindersState = (0, state_js_1.createRemindersState)(ctx.stateService);
|
|
72064
|
+
const result = await remindersState.prBaseline.read(sessionId);
|
|
72065
|
+
if (result.source !== "default") {
|
|
72066
|
+
prBaseline = result.data;
|
|
71929
72067
|
}
|
|
71930
72068
|
let effectiveBaseline = 0;
|
|
71931
72069
|
if (prBaseline && prBaseline.turnCount === metrics.turnCount) {
|
|
@@ -71937,12 +72075,28 @@ var require_stage_pause_and_reflect = __commonJS({
|
|
|
71937
72075
|
effectiveBaseline = Math.max(effectiveBaseline, lastConsumed.stagedAt.toolsThisTurn);
|
|
71938
72076
|
}
|
|
71939
72077
|
const shouldReactivate = metrics.turnCount > lastConsumed.stagedAt.turnCount || metrics.toolsThisTurn >= effectiveBaseline + config.pause_and_reflect_threshold;
|
|
71940
|
-
if (!shouldReactivate)
|
|
72078
|
+
if (!shouldReactivate) {
|
|
72079
|
+
(0, core_1.logEvent)(ctx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
|
|
72080
|
+
reminderName: "pause-and-reflect",
|
|
72081
|
+
hookName: "PreToolUse",
|
|
72082
|
+
reason: "same_turn",
|
|
72083
|
+
triggeredBy: "tool_result"
|
|
72084
|
+
}));
|
|
71941
72085
|
return void 0;
|
|
72086
|
+
}
|
|
71942
72087
|
}
|
|
71943
72088
|
const toolsSinceBaseline = metrics.toolsThisTurn - effectiveBaseline;
|
|
71944
|
-
if (toolsSinceBaseline < config.pause_and_reflect_threshold)
|
|
72089
|
+
if (toolsSinceBaseline < config.pause_and_reflect_threshold) {
|
|
72090
|
+
(0, core_1.logEvent)(ctx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
|
|
72091
|
+
reminderName: "pause-and-reflect",
|
|
72092
|
+
hookName: "PreToolUse",
|
|
72093
|
+
reason: "below_threshold",
|
|
72094
|
+
threshold: config.pause_and_reflect_threshold,
|
|
72095
|
+
currentValue: toolsSinceBaseline,
|
|
72096
|
+
triggeredBy: "tool_result"
|
|
72097
|
+
}));
|
|
71945
72098
|
return void 0;
|
|
72099
|
+
}
|
|
71946
72100
|
return {
|
|
71947
72101
|
reminderId: types_js_1.ReminderIds.PAUSE_AND_REFLECT,
|
|
71948
72102
|
targetHook: "PreToolUse",
|
|
@@ -73472,86 +73626,6 @@ var require_picomatch2 = __commonJS({
|
|
|
73472
73626
|
}
|
|
73473
73627
|
});
|
|
73474
73628
|
|
|
73475
|
-
// ../feature-reminders/dist/events.js
|
|
73476
|
-
var require_events2 = __commonJS({
|
|
73477
|
-
"../feature-reminders/dist/events.js"(exports2) {
|
|
73478
|
-
"use strict";
|
|
73479
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
73480
|
-
exports2.ReminderEvents = void 0;
|
|
73481
|
-
exports2.ReminderEvents = {
|
|
73482
|
-
/**
|
|
73483
|
-
* Create a ReminderConsumed event (logged when CLI returns a staged reminder).
|
|
73484
|
-
*/
|
|
73485
|
-
reminderConsumed(context, state, _metadata) {
|
|
73486
|
-
return {
|
|
73487
|
-
type: "reminder:consumed",
|
|
73488
|
-
time: Date.now(),
|
|
73489
|
-
source: "cli",
|
|
73490
|
-
context: {
|
|
73491
|
-
sessionId: context.sessionId,
|
|
73492
|
-
correlationId: context.correlationId,
|
|
73493
|
-
traceId: context.traceId,
|
|
73494
|
-
hook: context.hook,
|
|
73495
|
-
taskId: context.taskId
|
|
73496
|
-
},
|
|
73497
|
-
payload: {
|
|
73498
|
-
reminderName: state.reminderName,
|
|
73499
|
-
reminderReturned: state.reminderReturned,
|
|
73500
|
-
blocking: state.blocking,
|
|
73501
|
-
priority: state.priority,
|
|
73502
|
-
persistent: state.persistent
|
|
73503
|
-
}
|
|
73504
|
-
};
|
|
73505
|
-
},
|
|
73506
|
-
// Note: reminderStaged stays in @sidekick/core (used by staging-service.ts, circular dep)
|
|
73507
|
-
/**
|
|
73508
|
-
* Create a ReminderUnstaged event (logged when a reminder is removed from staging).
|
|
73509
|
-
*/
|
|
73510
|
-
reminderUnstaged(context, state) {
|
|
73511
|
-
return {
|
|
73512
|
-
type: "reminder:unstaged",
|
|
73513
|
-
time: Date.now(),
|
|
73514
|
-
source: "daemon",
|
|
73515
|
-
context: {
|
|
73516
|
-
sessionId: context.sessionId,
|
|
73517
|
-
correlationId: context.correlationId,
|
|
73518
|
-
traceId: context.traceId,
|
|
73519
|
-
hook: context.hook,
|
|
73520
|
-
taskId: context.taskId
|
|
73521
|
-
},
|
|
73522
|
-
payload: {
|
|
73523
|
-
reminderName: state.reminderName,
|
|
73524
|
-
hookName: state.hookName,
|
|
73525
|
-
reason: state.reason
|
|
73526
|
-
}
|
|
73527
|
-
};
|
|
73528
|
-
},
|
|
73529
|
-
/**
|
|
73530
|
-
* Create a RemindersCleared event (logged when staging directory is cleaned).
|
|
73531
|
-
*/
|
|
73532
|
-
remindersCleared(context, state, reason) {
|
|
73533
|
-
return {
|
|
73534
|
-
type: "reminder:cleared",
|
|
73535
|
-
time: Date.now(),
|
|
73536
|
-
source: "daemon",
|
|
73537
|
-
context: {
|
|
73538
|
-
sessionId: context.sessionId,
|
|
73539
|
-
correlationId: context.correlationId,
|
|
73540
|
-
traceId: context.traceId,
|
|
73541
|
-
hook: context.hook,
|
|
73542
|
-
taskId: context.taskId
|
|
73543
|
-
},
|
|
73544
|
-
payload: {
|
|
73545
|
-
clearedCount: state.clearedCount,
|
|
73546
|
-
hookNames: state.hookNames,
|
|
73547
|
-
reason
|
|
73548
|
-
}
|
|
73549
|
-
};
|
|
73550
|
-
}
|
|
73551
|
-
};
|
|
73552
|
-
}
|
|
73553
|
-
});
|
|
73554
|
-
|
|
73555
73629
|
// ../feature-reminders/dist/tool-pattern-matcher.js
|
|
73556
73630
|
var require_tool_pattern_matcher = __commonJS({
|
|
73557
73631
|
"../feature-reminders/dist/tool-pattern-matcher.js"(exports2) {
|
|
@@ -73659,22 +73733,48 @@ var require_track_verification_tools = __commonJS({
|
|
|
73659
73733
|
}
|
|
73660
73734
|
});
|
|
73661
73735
|
}
|
|
73662
|
-
async function stageToolsForFiles(filePaths, daemonCtx, sessionId, verificationTools, toolsState, remindersState) {
|
|
73736
|
+
async function stageToolsForFiles(filePaths, daemonCtx, sessionId, verificationTools, toolsState, remindersState, triggeredBy = "file_edit") {
|
|
73663
73737
|
const existingReminders = await daemonCtx.staging.listReminders("Stop");
|
|
73664
73738
|
const stagedNames = new Set(existingReminders.map((r) => r.name));
|
|
73665
73739
|
let anyStaged = false;
|
|
73740
|
+
const emittedNotStaged = /* @__PURE__ */ new Set();
|
|
73666
73741
|
for (const filePath of filePaths) {
|
|
73667
73742
|
for (const [toolName, toolConfig] of Object.entries(verificationTools)) {
|
|
73668
|
-
if (!toolConfig.enabled)
|
|
73669
|
-
continue;
|
|
73670
73743
|
const reminderId = TOOL_REMINDER_MAP[toolName];
|
|
73671
73744
|
if (!reminderId)
|
|
73672
73745
|
continue;
|
|
73673
|
-
if (!
|
|
73746
|
+
if (!toolConfig.enabled) {
|
|
73747
|
+
const emitKey = `${reminderId}:feature_disabled`;
|
|
73748
|
+
if (!emittedNotStaged.has(emitKey)) {
|
|
73749
|
+
emittedNotStaged.add(emitKey);
|
|
73750
|
+
(0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
|
|
73751
|
+
reminderName: reminderId,
|
|
73752
|
+
hookName: "Stop",
|
|
73753
|
+
reason: "feature_disabled",
|
|
73754
|
+
triggeredBy
|
|
73755
|
+
}));
|
|
73756
|
+
}
|
|
73757
|
+
continue;
|
|
73758
|
+
}
|
|
73759
|
+
if (!picomatch_1.default.isMatch(filePath, toolConfig.clearing_patterns)) {
|
|
73760
|
+
const emitKey = `${reminderId}:pattern_mismatch`;
|
|
73761
|
+
if (!emittedNotStaged.has(emitKey)) {
|
|
73762
|
+
emittedNotStaged.add(emitKey);
|
|
73763
|
+
(0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
|
|
73764
|
+
reminderName: reminderId,
|
|
73765
|
+
hookName: "Stop",
|
|
73766
|
+
reason: "pattern_mismatch",
|
|
73767
|
+
triggeredBy
|
|
73768
|
+
}));
|
|
73769
|
+
}
|
|
73674
73770
|
continue;
|
|
73771
|
+
}
|
|
73675
73772
|
const current = toolsState[toolName];
|
|
73676
73773
|
if (!current || current.status === "staged") {
|
|
73677
|
-
const staged = await ensureToolReminderStaged(daemonCtx, reminderId, stagedNames
|
|
73774
|
+
const staged = await ensureToolReminderStaged(daemonCtx, reminderId, stagedNames, {
|
|
73775
|
+
reason: current ? "re-staged" : "initial",
|
|
73776
|
+
triggeredBy: "file_edit"
|
|
73777
|
+
});
|
|
73678
73778
|
if (staged) {
|
|
73679
73779
|
if (!current) {
|
|
73680
73780
|
toolsState[toolName] = {
|
|
@@ -73690,7 +73790,11 @@ var require_track_verification_tools = __commonJS({
|
|
|
73690
73790
|
} else {
|
|
73691
73791
|
const newEdits = current.editsSinceVerified + 1;
|
|
73692
73792
|
if (newEdits >= toolConfig.clearing_threshold) {
|
|
73693
|
-
const staged = await ensureToolReminderStaged(daemonCtx, reminderId, stagedNames
|
|
73793
|
+
const staged = await ensureToolReminderStaged(daemonCtx, reminderId, stagedNames, {
|
|
73794
|
+
reason: "threshold_reached",
|
|
73795
|
+
triggeredBy: "file_edit",
|
|
73796
|
+
thresholdState: { current: newEdits, threshold: toolConfig.clearing_threshold }
|
|
73797
|
+
});
|
|
73694
73798
|
if (staged) {
|
|
73695
73799
|
toolsState[toolName] = {
|
|
73696
73800
|
...current,
|
|
@@ -73707,6 +73811,14 @@ var require_track_verification_tools = __commonJS({
|
|
|
73707
73811
|
status: "cooldown",
|
|
73708
73812
|
editsSinceVerified: newEdits
|
|
73709
73813
|
};
|
|
73814
|
+
(0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
|
|
73815
|
+
reminderName: reminderId,
|
|
73816
|
+
hookName: "Stop",
|
|
73817
|
+
reason: "below_threshold",
|
|
73818
|
+
threshold: toolConfig.clearing_threshold,
|
|
73819
|
+
currentValue: newEdits,
|
|
73820
|
+
triggeredBy
|
|
73821
|
+
}));
|
|
73710
73822
|
}
|
|
73711
73823
|
}
|
|
73712
73824
|
}
|
|
@@ -73752,7 +73864,16 @@ var require_track_verification_tools = __commonJS({
|
|
|
73752
73864
|
lastMatchedScope: match.scope
|
|
73753
73865
|
};
|
|
73754
73866
|
await daemonCtx.staging.deleteReminder("Stop", reminderId);
|
|
73755
|
-
(0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderUnstaged({ sessionId }, {
|
|
73867
|
+
(0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderUnstaged({ sessionId }, {
|
|
73868
|
+
reminderName: reminderId,
|
|
73869
|
+
hookName: "Stop",
|
|
73870
|
+
reason: "tool_verified",
|
|
73871
|
+
triggeredBy: "verification_passed",
|
|
73872
|
+
toolState: {
|
|
73873
|
+
status: toolsState[toolName].status,
|
|
73874
|
+
editsSinceVerified: toolsState[toolName].editsSinceVerified
|
|
73875
|
+
}
|
|
73876
|
+
}));
|
|
73756
73877
|
anyUnstaged = true;
|
|
73757
73878
|
daemonCtx.logger.debug("VC tool verified", {
|
|
73758
73879
|
toolName,
|
|
@@ -73767,13 +73888,18 @@ var require_track_verification_tools = __commonJS({
|
|
|
73767
73888
|
const hasPerToolReminders = remaining.some((r) => VC_TOOL_NAME_SET.has(r.name));
|
|
73768
73889
|
if (!hasPerToolReminders) {
|
|
73769
73890
|
await daemonCtx.staging.deleteReminder("Stop", types_js_1.ReminderIds.VERIFY_COMPLETION);
|
|
73770
|
-
(0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderUnstaged({ sessionId }, {
|
|
73891
|
+
(0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderUnstaged({ sessionId }, {
|
|
73892
|
+
reminderName: types_js_1.ReminderIds.VERIFY_COMPLETION,
|
|
73893
|
+
hookName: "Stop",
|
|
73894
|
+
reason: "all_tools_verified",
|
|
73895
|
+
triggeredBy: "verification_passed"
|
|
73896
|
+
}));
|
|
73771
73897
|
daemonCtx.logger.info("All VC tools verified, unstaged wrapper", { sessionId });
|
|
73772
73898
|
}
|
|
73773
73899
|
await remindersState.verificationTools.write(sessionId, toolsState);
|
|
73774
73900
|
}
|
|
73775
73901
|
}
|
|
73776
|
-
async function ensureToolReminderStaged(daemonCtx, reminderId, stagedNames) {
|
|
73902
|
+
async function ensureToolReminderStaged(daemonCtx, reminderId, stagedNames, enrichment) {
|
|
73777
73903
|
if (stagedNames.has(reminderId))
|
|
73778
73904
|
return true;
|
|
73779
73905
|
const reminder = (0, reminder_utils_js_1.resolveReminder)(reminderId, {
|
|
@@ -73787,7 +73913,7 @@ var require_track_verification_tools = __commonJS({
|
|
|
73787
73913
|
await (0, reminder_utils_js_1.stageReminder)(daemonCtx, "Stop", {
|
|
73788
73914
|
...reminder,
|
|
73789
73915
|
stagedAt: { timestamp: Date.now(), turnCount: 0, toolsThisTurn: 0, toolCount: 0 }
|
|
73790
|
-
});
|
|
73916
|
+
}, enrichment);
|
|
73791
73917
|
return true;
|
|
73792
73918
|
}
|
|
73793
73919
|
}
|
|
@@ -73803,6 +73929,7 @@ var require_stage_stop_bash_changes = __commonJS({
|
|
|
73803
73929
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
73804
73930
|
exports2.registerStageBashChanges = registerStageBashChanges;
|
|
73805
73931
|
var core_1 = require_dist4();
|
|
73932
|
+
var events_js_1 = require_events2();
|
|
73806
73933
|
var types_1 = require_dist();
|
|
73807
73934
|
var picomatch_1 = __importDefault2(require_picomatch2());
|
|
73808
73935
|
var track_verification_tools_js_1 = require_track_verification_tools();
|
|
@@ -73872,6 +73999,12 @@ var require_stage_stop_bash_changes = __commonJS({
|
|
|
73872
73999
|
if (lastConsumed?.stagedAt) {
|
|
73873
74000
|
const shouldReactivate = metrics.turnCount > lastConsumed.stagedAt.turnCount;
|
|
73874
74001
|
if (!shouldReactivate) {
|
|
74002
|
+
(0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
|
|
74003
|
+
reminderName: "verify-completion",
|
|
74004
|
+
hookName: "Stop",
|
|
74005
|
+
reason: "same_turn",
|
|
74006
|
+
triggeredBy: "bash_command"
|
|
74007
|
+
}));
|
|
73875
74008
|
daemonCtx.logger.debug("Bash VC: skipped (already consumed this turn)", {
|
|
73876
74009
|
currentTurn: metrics.turnCount,
|
|
73877
74010
|
lastConsumedTurn: lastConsumed.stagedAt.turnCount
|
|
@@ -73887,12 +74020,25 @@ var require_stage_stop_bash_changes = __commonJS({
|
|
|
73887
74020
|
currentCount: current.length,
|
|
73888
74021
|
newFileCount: newFiles.length
|
|
73889
74022
|
});
|
|
73890
|
-
if (newFiles.length === 0)
|
|
74023
|
+
if (newFiles.length === 0) {
|
|
74024
|
+
(0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
|
|
74025
|
+
reminderName: "verify-completion",
|
|
74026
|
+
hookName: "Stop",
|
|
74027
|
+
reason: "no_changes_detected",
|
|
74028
|
+
triggeredBy: "bash_command"
|
|
74029
|
+
}));
|
|
73891
74030
|
return;
|
|
74031
|
+
}
|
|
73892
74032
|
const featureConfig = context.config.getFeature("reminders");
|
|
73893
74033
|
const config = { ...types_js_1.DEFAULT_REMINDERS_SETTINGS, ...featureConfig.settings };
|
|
73894
74034
|
const sourceMatches = newFiles.filter((f) => picomatch_1.default.isMatch(f, config.source_code_patterns));
|
|
73895
74035
|
if (sourceMatches.length === 0) {
|
|
74036
|
+
(0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
|
|
74037
|
+
reminderName: "verify-completion",
|
|
74038
|
+
hookName: "Stop",
|
|
74039
|
+
reason: "pattern_mismatch",
|
|
74040
|
+
triggeredBy: "bash_command"
|
|
74041
|
+
}));
|
|
73896
74042
|
daemonCtx.logger.debug("Bash VC: new files found but no source code matches", { newFiles });
|
|
73897
74043
|
return;
|
|
73898
74044
|
}
|
|
@@ -73906,7 +74052,7 @@ var require_stage_stop_bash_changes = __commonJS({
|
|
|
73906
74052
|
const remindersState = (0, state_js_1.createRemindersState)(daemonCtx.stateService);
|
|
73907
74053
|
const stateResult = await remindersState.verificationTools.read(sessionId);
|
|
73908
74054
|
const toolsState = { ...stateResult.data };
|
|
73909
|
-
await (0, track_verification_tools_js_1.stageToolsForFiles)(sourceMatches, daemonCtx, sessionId, verificationTools, toolsState, remindersState);
|
|
74055
|
+
await (0, track_verification_tools_js_1.stageToolsForFiles)(sourceMatches, daemonCtx, sessionId, verificationTools, toolsState, remindersState, "bash_command");
|
|
73910
74056
|
}
|
|
73911
74057
|
});
|
|
73912
74058
|
}
|
|
@@ -74019,6 +74165,11 @@ var require_unstage_verify_completion = __commonJS({
|
|
|
74019
74165
|
await remindersState.vcUnverified.delete(sessionId);
|
|
74020
74166
|
}
|
|
74021
74167
|
} else {
|
|
74168
|
+
(0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
|
|
74169
|
+
reminderName: "verify-completion",
|
|
74170
|
+
hookName: "Stop",
|
|
74171
|
+
reason: "no_unverified_changes"
|
|
74172
|
+
}));
|
|
74022
74173
|
daemonCtx.logger.info("VC unstage: no unverified changes, clearing reminder", {
|
|
74023
74174
|
sessionId,
|
|
74024
74175
|
hadState: unverifiedState !== null
|
|
@@ -74028,7 +74179,12 @@ var require_unstage_verify_completion = __commonJS({
|
|
|
74028
74179
|
const reason = unverifiedState?.hasUnverifiedChanges ? "cycle_limit_reached" : "no_unverified_changes";
|
|
74029
74180
|
for (const vcId of types_js_1.ALL_VC_REMINDER_IDS) {
|
|
74030
74181
|
await daemonCtx.staging.deleteReminder("Stop", vcId);
|
|
74031
|
-
(0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderUnstaged(eventContext, {
|
|
74182
|
+
(0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderUnstaged(eventContext, {
|
|
74183
|
+
reminderName: vcId,
|
|
74184
|
+
hookName: "Stop",
|
|
74185
|
+
reason,
|
|
74186
|
+
triggeredBy: unverifiedState?.hasUnverifiedChanges ? "cycle_limit" : "no_unverified_changes"
|
|
74187
|
+
}));
|
|
74032
74188
|
}
|
|
74033
74189
|
daemonCtx.logger.debug("VC unstage: deleted all VC reminders");
|
|
74034
74190
|
}
|
|
@@ -74126,12 +74282,22 @@ var require_stage_persona_reminders = __commonJS({
|
|
|
74126
74282
|
}
|
|
74127
74283
|
async function stagePersonaRemindersForSession(ctx, sessionId, options) {
|
|
74128
74284
|
if (!isPersonaInjectionEnabled(ctx)) {
|
|
74285
|
+
(0, core_1.logEvent)(ctx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
|
|
74286
|
+
reminderName: "remember-your-persona",
|
|
74287
|
+
hookName: "PreToolUse",
|
|
74288
|
+
reason: "feature_disabled"
|
|
74289
|
+
}));
|
|
74129
74290
|
await clearPersonaReminders(ctx, sessionId);
|
|
74130
74291
|
ctx.logger.debug("Persona injection disabled by config, cleaned up reminders", { sessionId });
|
|
74131
74292
|
return;
|
|
74132
74293
|
}
|
|
74133
74294
|
const persona = await loadPersonaForSession(ctx, sessionId);
|
|
74134
74295
|
if (!persona) {
|
|
74296
|
+
(0, core_1.logEvent)(ctx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
|
|
74297
|
+
reminderName: "remember-your-persona",
|
|
74298
|
+
hookName: "PreToolUse",
|
|
74299
|
+
reason: "no_persona"
|
|
74300
|
+
}));
|
|
74135
74301
|
await clearPersonaReminders(ctx, sessionId);
|
|
74136
74302
|
ctx.logger.debug("Persona cleared or disabled, unstaged persona reminders", { sessionId });
|
|
74137
74303
|
return;
|
|
@@ -74431,7 +74597,19 @@ var require_consumption_handler_factory = __commonJS({
|
|
|
74431
74597
|
reader.renameReminder(hook, reminder.name);
|
|
74432
74598
|
}
|
|
74433
74599
|
}
|
|
74434
|
-
let
|
|
74600
|
+
let enrichment;
|
|
74601
|
+
let response;
|
|
74602
|
+
if (buildResponse) {
|
|
74603
|
+
const result = await buildResponse({ reminder: primary, reader, cliCtx, sessionId, event, supportsBlocking });
|
|
74604
|
+
if ("response" in result && typeof result.response === "object") {
|
|
74605
|
+
response = result.response;
|
|
74606
|
+
enrichment = result.enrichment;
|
|
74607
|
+
} else {
|
|
74608
|
+
response = result;
|
|
74609
|
+
}
|
|
74610
|
+
} else {
|
|
74611
|
+
response = buildDefaultResponse(primary, supportsBlocking);
|
|
74612
|
+
}
|
|
74435
74613
|
const secondaryContexts = reminders.slice(1).map((r) => r.additionalContext).filter((ctx2) => !!ctx2);
|
|
74436
74614
|
if (secondaryContexts.length > 0) {
|
|
74437
74615
|
const existing = response.additionalContext;
|
|
@@ -74449,7 +74627,8 @@ var require_consumption_handler_factory = __commonJS({
|
|
|
74449
74627
|
reminderReturned: true,
|
|
74450
74628
|
blocking: response.blocking ?? false,
|
|
74451
74629
|
priority: primary.priority,
|
|
74452
|
-
persistent: primary.persistent
|
|
74630
|
+
persistent: primary.persistent,
|
|
74631
|
+
...enrichment
|
|
74453
74632
|
}));
|
|
74454
74633
|
return { response };
|
|
74455
74634
|
}
|
|
@@ -74551,6 +74730,13 @@ var require_inject_stop = __commonJS({
|
|
|
74551
74730
|
shouldBlock: classification.shouldBlock,
|
|
74552
74731
|
reasoning: classification.reasoning?.slice(0, 200)
|
|
74553
74732
|
});
|
|
74733
|
+
const classificationEnrichment = {
|
|
74734
|
+
classificationResult: {
|
|
74735
|
+
category: classification.category,
|
|
74736
|
+
confidence: classification.confidence,
|
|
74737
|
+
shouldBlock: classification.shouldBlock
|
|
74738
|
+
}
|
|
74739
|
+
};
|
|
74554
74740
|
if (classification.shouldBlock) {
|
|
74555
74741
|
cliCtx.logger.info("VC inject-stop: BLOCKING (claiming completion)", { sessionId });
|
|
74556
74742
|
try {
|
|
@@ -74560,7 +74746,10 @@ var require_inject_stop = __commonJS({
|
|
|
74560
74746
|
error: String(clearErr)
|
|
74561
74747
|
});
|
|
74562
74748
|
}
|
|
74563
|
-
return
|
|
74749
|
+
return {
|
|
74750
|
+
response: (0, consumption_handler_factory_js_1.buildDefaultResponse)(reminder, supportsBlocking),
|
|
74751
|
+
enrichment: classificationEnrichment
|
|
74752
|
+
};
|
|
74564
74753
|
} else {
|
|
74565
74754
|
cliCtx.logger.info("VC inject-stop: NOT BLOCKING", {
|
|
74566
74755
|
sessionId,
|
|
@@ -74586,13 +74775,13 @@ var require_inject_stop = __commonJS({
|
|
|
74586
74775
|
});
|
|
74587
74776
|
}
|
|
74588
74777
|
if (classification.category === "ASKING_QUESTION" || classification.category === "ANSWERING_QUESTION") {
|
|
74589
|
-
return {};
|
|
74778
|
+
return { response: {}, enrichment: classificationEnrichment };
|
|
74590
74779
|
} else {
|
|
74591
74780
|
const response = {};
|
|
74592
74781
|
if (classification.userMessage) {
|
|
74593
74782
|
response.userMessage = classification.userMessage;
|
|
74594
74783
|
}
|
|
74595
|
-
return response;
|
|
74784
|
+
return { response, enrichment: classificationEnrichment };
|
|
74596
74785
|
}
|
|
74597
74786
|
}
|
|
74598
74787
|
} catch (err) {
|
|
@@ -74963,7 +75152,8 @@ var require_orchestrator = __commonJS({
|
|
|
74963
75152
|
(0, core_1.logEvent)(this.deps.logger, events_js_1.ReminderEvents.reminderUnstaged(eventContext, {
|
|
74964
75153
|
reminderName: vcId,
|
|
74965
75154
|
hookName: "Stop",
|
|
74966
|
-
reason: "pause_and_reflect_cascade"
|
|
75155
|
+
reason: "pause_and_reflect_cascade",
|
|
75156
|
+
triggeredBy: "cascade_from_pause_and_reflect"
|
|
74967
75157
|
}));
|
|
74968
75158
|
}
|
|
74969
75159
|
this.deps.logger.debug("Unstaged all VC reminders after P&R staged", { sessionId });
|
|
@@ -75000,7 +75190,12 @@ var require_orchestrator = __commonJS({
|
|
|
75000
75190
|
try {
|
|
75001
75191
|
const staging = this.deps.getStagingService(sessionId);
|
|
75002
75192
|
await staging.deleteReminder("PreToolUse", types_js_1.ReminderIds.PAUSE_AND_REFLECT);
|
|
75003
|
-
(0, core_1.logEvent)(this.deps.logger, events_js_1.ReminderEvents.reminderUnstaged({ sessionId }, {
|
|
75193
|
+
(0, core_1.logEvent)(this.deps.logger, events_js_1.ReminderEvents.reminderUnstaged({ sessionId }, {
|
|
75194
|
+
reminderName: types_js_1.ReminderIds.PAUSE_AND_REFLECT,
|
|
75195
|
+
hookName: "PreToolUse",
|
|
75196
|
+
reason: "vc_consumed_cascade",
|
|
75197
|
+
triggeredBy: "cascade_from_verify_completion"
|
|
75198
|
+
}));
|
|
75004
75199
|
this.deps.logger.debug("Unstaged P&R after VC consumed", { sessionId });
|
|
75005
75200
|
} catch (err) {
|
|
75006
75201
|
this.deps.logger.warn("Failed to unstage P&R after VC consumed", {
|
|
@@ -83540,7 +83735,7 @@ var require_cli = __commonJS({
|
|
|
83540
83735
|
var promises_12 = require("node:fs/promises");
|
|
83541
83736
|
var node_stream_1 = require("node:stream");
|
|
83542
83737
|
var yargs_parser_1 = __importDefault2(require_build());
|
|
83543
|
-
var VERSION = true ? "0.1.
|
|
83738
|
+
var VERSION = true ? "0.1.11" : "dev";
|
|
83544
83739
|
var SANDBOX_ERROR_MESSAGE = `Error: Daemon commands cannot run in sandbox mode.
|
|
83545
83740
|
|
|
83546
83741
|
Claude Code's sandbox blocks Unix socket operations required for daemon IPC.
|