@scotthamilton77/sidekick 0.1.8 → 0.1.10

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/daemon.js CHANGED
@@ -54,7 +54,7 @@ var require_events = __commonJS({
54
54
  "../types/dist/events.js"(exports2) {
55
55
  "use strict";
56
56
  Object.defineProperty(exports2, "__esModule", { value: true });
57
- exports2.HOOK_NAMES = void 0;
57
+ exports2.UI_EVENT_VISIBILITY = exports2.UI_EVENT_TYPES = exports2.HOOK_NAMES = void 0;
58
58
  exports2.isHookEvent = isHookEvent;
59
59
  exports2.isTranscriptEvent = isTranscriptEvent;
60
60
  exports2.isSessionStartEvent = isSessionStartEvent;
@@ -116,6 +116,92 @@ var require_events = __commonJS({
116
116
  function isTranscriptLoggingEvent(event) {
117
117
  return event.source === "transcript";
118
118
  }
119
+ exports2.UI_EVENT_TYPES = [
120
+ // Reminder events
121
+ "reminder:staged",
122
+ "reminder:unstaged",
123
+ "reminder:consumed",
124
+ "reminder:cleared",
125
+ "reminder:not-staged",
126
+ // Decision events
127
+ "decision:recorded",
128
+ // Session summary events
129
+ "session-summary:start",
130
+ "session-summary:finish",
131
+ // Session state change events
132
+ "session-title:changed",
133
+ "intent:changed",
134
+ // Snarky message events
135
+ "snarky-message:start",
136
+ "snarky-message:finish",
137
+ // Resume message events
138
+ "resume-message:start",
139
+ "resume-message:finish",
140
+ // Persona events
141
+ "persona:selected",
142
+ "persona:changed",
143
+ // Statusline events
144
+ "statusline:rendered",
145
+ // Hook lifecycle events
146
+ "hook:received",
147
+ "hook:completed",
148
+ // Daemon event processing
149
+ "event:received",
150
+ "event:processed",
151
+ // Daemon lifecycle events
152
+ "daemon:starting",
153
+ "daemon:started",
154
+ "ipc:started",
155
+ "config:watcher-started",
156
+ "session:eviction-started",
157
+ // Skipped operation events
158
+ "session-summary:skipped",
159
+ "resume-message:skipped",
160
+ // Error events
161
+ "statusline:error",
162
+ // Transcript events
163
+ "transcript:emitted",
164
+ "transcript:pre-compact",
165
+ // General error
166
+ "error:occurred"
167
+ ];
168
+ exports2.UI_EVENT_VISIBILITY = {
169
+ // Timeline events (user-visible state changes)
170
+ "reminder:staged": "timeline",
171
+ "reminder:unstaged": "timeline",
172
+ "reminder:consumed": "timeline",
173
+ "reminder:cleared": "timeline",
174
+ "reminder:not-staged": "log",
175
+ "decision:recorded": "timeline",
176
+ "session-summary:start": "timeline",
177
+ "session-summary:finish": "timeline",
178
+ "session-title:changed": "timeline",
179
+ "intent:changed": "timeline",
180
+ "snarky-message:start": "timeline",
181
+ "snarky-message:finish": "timeline",
182
+ "resume-message:start": "timeline",
183
+ "resume-message:finish": "timeline",
184
+ "persona:selected": "timeline",
185
+ "persona:changed": "timeline",
186
+ "statusline:rendered": "timeline",
187
+ // Both (timeline + log viewer)
188
+ "hook:received": "both",
189
+ "hook:completed": "both",
190
+ "statusline:error": "both",
191
+ "error:occurred": "both",
192
+ // Log-only (internal machinery)
193
+ "event:received": "log",
194
+ "event:processed": "log",
195
+ "daemon:starting": "log",
196
+ "daemon:started": "log",
197
+ "ipc:started": "log",
198
+ "config:watcher-started": "log",
199
+ "session:eviction-started": "log",
200
+ "session-summary:skipped": "log",
201
+ "resume-message:skipped": "log",
202
+ "transcript:emitted": "log",
203
+ "transcript:pre-compact": "log"
204
+ };
119
205
  }
120
206
  });
121
207
 
@@ -16252,6 +16338,7 @@ var require_state = __commonJS({
16252
16338
  exports2.createDefaultLLMMetrics = createDefaultLLMMetrics;
16253
16339
  var zod_1 = require_zod();
16254
16340
  var events_js_1 = require_events();
16341
+ var staging_js_1 = require_staging();
16255
16342
  exports2.SessionSummaryStateSchema = zod_1.z.object({
16256
16343
  /** Session identifier */
16257
16344
  session_id: zod_1.z.string(),
@@ -16413,16 +16500,7 @@ var require_state = __commonJS({
16413
16500
  lastMatchedScope: zod_1.z.enum(["project", "package", "file"]).nullable().optional()
16414
16501
  });
16415
16502
  exports2.VerificationToolsStateSchema = zod_1.z.record(zod_1.z.string(), exports2.VerificationToolStatusSchema);
16416
- exports2.CachedReminderSchema = zod_1.z.object({
16417
- name: zod_1.z.string(),
16418
- blocking: zod_1.z.boolean(),
16419
- priority: zod_1.z.number(),
16420
- persistent: zod_1.z.boolean(),
16421
- throttle: zod_1.z.boolean().optional(),
16422
- userMessage: zod_1.z.string().optional(),
16423
- additionalContext: zod_1.z.string().optional(),
16424
- reason: zod_1.z.string().optional()
16425
- });
16503
+ exports2.CachedReminderSchema = staging_js_1.StagedReminderSchema.omit({ stagedAt: true });
16426
16504
  exports2.ReminderThrottleEntrySchema = zod_1.z.object({
16427
16505
  /** Number of conversation messages since the reminder was last staged */
16428
16506
  messagesSinceLastStaging: zod_1.z.number().int().nonnegative(),
@@ -17003,6 +17081,24 @@ var require_setup_status = __commonJS({
17003
17081
  }
17004
17082
  });
17005
17083
 
17084
+ // ../types/dist/state.js
17085
+ var require_state2 = __commonJS({
17086
+ "../types/dist/state.js"(exports2) {
17087
+ "use strict";
17088
+ Object.defineProperty(exports2, "__esModule", { value: true });
17089
+ exports2.ProjectRegistryEntrySchema = void 0;
17090
+ var zod_1 = require_zod();
17091
+ exports2.ProjectRegistryEntrySchema = zod_1.z.object({
17092
+ /** Absolute filesystem path to the project root */
17093
+ path: zod_1.z.string(),
17094
+ /** Human-readable project name (derived from directory name) */
17095
+ displayName: zod_1.z.string(),
17096
+ /** ISO 8601 timestamp of last daemon activity */
17097
+ lastActive: zod_1.z.iso.datetime()
17098
+ });
17099
+ }
17100
+ });
17101
+
17006
17102
  // ../types/dist/index.js
17007
17103
  var require_dist = __commonJS({
17008
17104
  "../types/dist/index.js"(exports2) {
@@ -17034,6 +17130,7 @@ var require_dist = __commonJS({
17034
17130
  __exportStar(require_tasks(), exports2);
17035
17131
  __exportStar(require_hook_input(), exports2);
17036
17132
  __exportStar(require_setup_status(), exports2);
17133
+ __exportStar(require_state2(), exports2);
17037
17134
  }
17038
17135
  });
17039
17136
 
@@ -26779,9 +26876,13 @@ var require_config2 = __commonJS({
26779
26876
  state: v4_1.z.string(),
26780
26877
  assets: v4_1.z.string().optional()
26781
26878
  }).strict();
26879
+ var ProjectsSchema = v4_1.z.object({
26880
+ retentionDays: v4_1.z.number().min(1)
26881
+ }).strict();
26782
26882
  var DaemonSchema = v4_1.z.object({
26783
26883
  idleTimeoutMs: v4_1.z.number().min(0),
26784
- shutdownTimeoutMs: v4_1.z.number().min(0)
26884
+ shutdownTimeoutMs: v4_1.z.number().min(0),
26885
+ projects: ProjectsSchema.default({ retentionDays: 30 })
26785
26886
  }).strict();
26786
26887
  var IpcSchema = v4_1.z.object({
26787
26888
  connectTimeoutMs: v4_1.z.number().min(0),
@@ -44685,7 +44786,7 @@ var require_structured_logging = __commonJS({
44685
44786
  */
44686
44787
  hookReceived(context, metadata) {
44687
44788
  return {
44688
- type: "HookReceived",
44789
+ type: "hook:received",
44689
44790
  time: Date.now(),
44690
44791
  source: "cli",
44691
44792
  context: {
@@ -44695,7 +44796,9 @@ var require_structured_logging = __commonJS({
44695
44796
  hook: context.hook
44696
44797
  },
44697
44798
  payload: {
44698
- metadata
44799
+ hook: context.hook,
44800
+ cwd: metadata.cwd,
44801
+ mode: metadata.mode
44699
44802
  }
44700
44803
  };
44701
44804
  },
@@ -44704,7 +44807,7 @@ var require_structured_logging = __commonJS({
44704
44807
  */
44705
44808
  hookCompleted(context, metadata, state) {
44706
44809
  return {
44707
- type: "HookCompleted",
44810
+ type: "hook:completed",
44708
44811
  time: Date.now(),
44709
44812
  source: "cli",
44710
44813
  context: {
@@ -44714,8 +44817,10 @@ var require_structured_logging = __commonJS({
44714
44817
  hook: context.hook
44715
44818
  },
44716
44819
  payload: {
44717
- state,
44718
- metadata
44820
+ hook: context.hook,
44821
+ durationMs: metadata.durationMs,
44822
+ reminderReturned: state?.reminderReturned,
44823
+ responseType: state?.responseType
44719
44824
  }
44720
44825
  };
44721
44826
  },
@@ -44725,7 +44830,7 @@ var require_structured_logging = __commonJS({
44725
44830
  */
44726
44831
  eventReceived(context, metadata) {
44727
44832
  return {
44728
- type: "EventReceived",
44833
+ type: "event:received",
44729
44834
  time: Date.now(),
44730
44835
  source: "daemon",
44731
44836
  context: {
@@ -44736,7 +44841,9 @@ var require_structured_logging = __commonJS({
44736
44841
  taskId: context.taskId
44737
44842
  },
44738
44843
  payload: {
44739
- metadata
44844
+ eventKind: metadata.eventKind,
44845
+ ...metadata.eventType !== void 0 && { eventType: metadata.eventType },
44846
+ ...metadata.hook !== void 0 && { hook: metadata.hook }
44740
44847
  }
44741
44848
  };
44742
44849
  },
@@ -44746,7 +44853,7 @@ var require_structured_logging = __commonJS({
44746
44853
  */
44747
44854
  eventProcessed(context, state, metadata) {
44748
44855
  return {
44749
- type: "EventProcessed",
44856
+ type: "event:processed",
44750
44857
  time: Date.now(),
44751
44858
  source: "daemon",
44752
44859
  context: {
@@ -44757,17 +44864,19 @@ var require_structured_logging = __commonJS({
44757
44864
  taskId: context.taskId
44758
44865
  },
44759
44866
  payload: {
44760
- state,
44761
- metadata
44867
+ handlerId: state.handlerId,
44868
+ success: state.success,
44869
+ durationMs: metadata.durationMs,
44870
+ error: metadata.error
44762
44871
  }
44763
44872
  };
44764
44873
  },
44765
44874
  /**
44766
44875
  * Create a ReminderStaged event (logged when Daemon stages a reminder file).
44767
44876
  */
44768
- reminderStaged(context, state, metadata) {
44877
+ reminderStaged(context, state, _metadata) {
44769
44878
  return {
44770
- type: "ReminderStaged",
44879
+ type: "reminder:staged",
44771
44880
  time: Date.now(),
44772
44881
  source: "daemon",
44773
44882
  context: {
@@ -44778,8 +44887,14 @@ var require_structured_logging = __commonJS({
44778
44887
  taskId: context.taskId
44779
44888
  },
44780
44889
  payload: {
44781
- state,
44782
- metadata
44890
+ reminderName: state.reminderName,
44891
+ hookName: state.hookName,
44892
+ blocking: state.blocking,
44893
+ priority: state.priority,
44894
+ persistent: state.persistent,
44895
+ ...state.reason !== void 0 && { reason: state.reason },
44896
+ ...state.triggeredBy !== void 0 && { triggeredBy: state.triggeredBy },
44897
+ ...state.thresholdState !== void 0 && { thresholdState: state.thresholdState }
44783
44898
  }
44784
44899
  };
44785
44900
  },
@@ -44789,14 +44904,15 @@ var require_structured_logging = __commonJS({
44789
44904
  */
44790
44905
  daemonStarting(metadata) {
44791
44906
  return {
44792
- type: "DaemonStarting",
44907
+ type: "daemon:starting",
44793
44908
  time: Date.now(),
44794
44909
  source: "daemon",
44795
44910
  context: {
44796
44911
  sessionId: ""
44797
44912
  },
44798
44913
  payload: {
44799
- metadata
44914
+ projectDir: metadata.projectDir,
44915
+ pid: metadata.pid
44800
44916
  }
44801
44917
  };
44802
44918
  },
@@ -44805,14 +44921,14 @@ var require_structured_logging = __commonJS({
44805
44921
  */
44806
44922
  daemonStarted(metadata) {
44807
44923
  return {
44808
- type: "DaemonStarted",
44924
+ type: "daemon:started",
44809
44925
  time: Date.now(),
44810
44926
  source: "daemon",
44811
44927
  context: {
44812
44928
  sessionId: ""
44813
44929
  },
44814
44930
  payload: {
44815
- metadata
44931
+ startupDurationMs: metadata.startupDurationMs
44816
44932
  }
44817
44933
  };
44818
44934
  },
@@ -44821,14 +44937,14 @@ var require_structured_logging = __commonJS({
44821
44937
  */
44822
44938
  ipcServerStarted(metadata) {
44823
44939
  return {
44824
- type: "IpcServerStarted",
44940
+ type: "ipc:started",
44825
44941
  time: Date.now(),
44826
44942
  source: "daemon",
44827
44943
  context: {
44828
44944
  sessionId: ""
44829
44945
  },
44830
44946
  payload: {
44831
- metadata
44947
+ socketPath: metadata.socketPath
44832
44948
  }
44833
44949
  };
44834
44950
  },
@@ -44837,14 +44953,15 @@ var require_structured_logging = __commonJS({
44837
44953
  */
44838
44954
  configWatcherStarted(metadata) {
44839
44955
  return {
44840
- type: "ConfigWatcherStarted",
44956
+ type: "config:watcher-started",
44841
44957
  time: Date.now(),
44842
44958
  source: "daemon",
44843
44959
  context: {
44844
44960
  sessionId: ""
44845
44961
  },
44846
44962
  payload: {
44847
- metadata
44963
+ projectDir: metadata.projectDir,
44964
+ watchedFiles: metadata.watchedFiles
44848
44965
  }
44849
44966
  };
44850
44967
  },
@@ -44853,14 +44970,14 @@ var require_structured_logging = __commonJS({
44853
44970
  */
44854
44971
  sessionEvictionStarted(metadata) {
44855
44972
  return {
44856
- type: "SessionEvictionStarted",
44973
+ type: "session:eviction-started",
44857
44974
  time: Date.now(),
44858
44975
  source: "daemon",
44859
44976
  context: {
44860
44977
  sessionId: ""
44861
44978
  },
44862
44979
  payload: {
44863
- metadata
44980
+ intervalMs: metadata.intervalMs
44864
44981
  }
44865
44982
  };
44866
44983
  },
@@ -44871,7 +44988,7 @@ var require_structured_logging = __commonJS({
44871
44988
  */
44872
44989
  statuslineRendered(context, state, metadata) {
44873
44990
  return {
44874
- type: "StatuslineRendered",
44991
+ type: "statusline:rendered",
44875
44992
  time: Date.now(),
44876
44993
  source: "cli",
44877
44994
  context: {
@@ -44882,8 +44999,11 @@ var require_structured_logging = __commonJS({
44882
44999
  taskId: context.taskId
44883
45000
  },
44884
45001
  payload: {
44885
- state,
44886
- metadata
45002
+ displayMode: state.displayMode,
45003
+ staleData: state.staleData,
45004
+ model: metadata.model,
45005
+ tokens: metadata.tokens,
45006
+ durationMs: metadata.durationMs
44887
45007
  }
44888
45008
  };
44889
45009
  },
@@ -44893,7 +45013,7 @@ var require_structured_logging = __commonJS({
44893
45013
  */
44894
45014
  statuslineError(context, reason, metadata) {
44895
45015
  return {
44896
- type: "StatuslineError",
45016
+ type: "statusline:error",
44897
45017
  time: Date.now(),
44898
45018
  source: "cli",
44899
45019
  context: {
@@ -44905,7 +45025,9 @@ var require_structured_logging = __commonJS({
44905
45025
  },
44906
45026
  payload: {
44907
45027
  reason,
44908
- metadata
45028
+ file: metadata.file,
45029
+ fallbackUsed: metadata.fallbackUsed,
45030
+ error: metadata.error
44909
45031
  }
44910
45032
  };
44911
45033
  },
@@ -44916,7 +45038,7 @@ var require_structured_logging = __commonJS({
44916
45038
  */
44917
45039
  resumeGenerating(context, metadata) {
44918
45040
  return {
44919
- type: "ResumeGenerating",
45041
+ type: "resume-message:start",
44920
45042
  time: Date.now(),
44921
45043
  source: "daemon",
44922
45044
  context: {
@@ -44927,8 +45049,8 @@ var require_structured_logging = __commonJS({
44927
45049
  taskId: context.taskId
44928
45050
  },
44929
45051
  payload: {
44930
- metadata,
44931
- reason: "pivot_detected"
45052
+ title_confidence: metadata.title_confidence,
45053
+ intent_confidence: metadata.intent_confidence
44932
45054
  }
44933
45055
  };
44934
45056
  },
@@ -44938,7 +45060,7 @@ var require_structured_logging = __commonJS({
44938
45060
  */
44939
45061
  resumeUpdated(context, state) {
44940
45062
  return {
44941
- type: "ResumeUpdated",
45063
+ type: "resume-message:finish",
44942
45064
  time: Date.now(),
44943
45065
  source: "daemon",
44944
45066
  context: {
@@ -44949,8 +45071,8 @@ var require_structured_logging = __commonJS({
44949
45071
  taskId: context.taskId
44950
45072
  },
44951
45073
  payload: {
44952
- state,
44953
- reason: "generation_complete"
45074
+ snarky_comment: state.snarky_comment,
45075
+ timestamp: state.timestamp
44954
45076
  }
44955
45077
  };
44956
45078
  },
@@ -44960,7 +45082,7 @@ var require_structured_logging = __commonJS({
44960
45082
  */
44961
45083
  resumeSkipped(context, metadata, reason) {
44962
45084
  return {
44963
- type: "ResumeSkipped",
45085
+ type: "resume-message:skipped",
44964
45086
  time: Date.now(),
44965
45087
  source: "daemon",
44966
45088
  context: {
@@ -44971,11 +45093,50 @@ var require_structured_logging = __commonJS({
44971
45093
  taskId: context.taskId
44972
45094
  },
44973
45095
  payload: {
44974
- metadata,
45096
+ title_confidence: metadata.title_confidence,
45097
+ intent_confidence: metadata.intent_confidence,
45098
+ min_confidence: metadata.min_confidence,
44975
45099
  reason
44976
45100
  }
44977
45101
  };
44978
45102
  },
45103
+ // --- Persona Events ---
45104
+ /**
45105
+ * Create a PersonaSelected event (logged when a persona is selected for a session).
45106
+ */
45107
+ personaSelected(context, payload) {
45108
+ return {
45109
+ type: "persona:selected",
45110
+ time: Date.now(),
45111
+ source: "daemon",
45112
+ context: {
45113
+ sessionId: context.sessionId,
45114
+ correlationId: context.correlationId,
45115
+ traceId: context.traceId,
45116
+ hook: context.hook,
45117
+ taskId: context.taskId
45118
+ },
45119
+ payload
45120
+ };
45121
+ },
45122
+ /**
45123
+ * Create a PersonaChanged event (logged when persona changes mid-session).
45124
+ */
45125
+ personaChanged(context, payload) {
45126
+ return {
45127
+ type: "persona:changed",
45128
+ time: Date.now(),
45129
+ source: "daemon",
45130
+ context: {
45131
+ sessionId: context.sessionId,
45132
+ correlationId: context.correlationId,
45133
+ traceId: context.traceId,
45134
+ hook: context.hook,
45135
+ taskId: context.taskId
45136
+ },
45137
+ payload
45138
+ };
45139
+ },
44979
45140
  // --- Transcript Events (logged to transcript-events.log) ---
44980
45141
  /**
44981
45142
  * Create a TranscriptEventEmitted event (logged when TranscriptService emits an event).
@@ -44983,7 +45144,7 @@ var require_structured_logging = __commonJS({
44983
45144
  */
44984
45145
  transcriptEventEmitted(context, state, metadata) {
44985
45146
  return {
44986
- type: "TranscriptEventEmitted",
45147
+ type: "transcript:emitted",
44987
45148
  time: Date.now(),
44988
45149
  source: "transcript",
44989
45150
  context: {
@@ -44994,8 +45155,13 @@ var require_structured_logging = __commonJS({
44994
45155
  taskId: context.taskId
44995
45156
  },
44996
45157
  payload: {
44997
- state,
44998
- metadata
45158
+ eventType: state.eventType,
45159
+ lineNumber: state.lineNumber,
45160
+ uuid: state.uuid,
45161
+ toolName: state.toolName,
45162
+ transcriptPath: metadata.transcriptPath,
45163
+ contentPreview: metadata.contentPreview,
45164
+ metrics: metadata.metrics
44999
45165
  }
45000
45166
  };
45001
45167
  },
@@ -45005,7 +45171,7 @@ var require_structured_logging = __commonJS({
45005
45171
  */
45006
45172
  preCompactCaptured(context, state, metadata) {
45007
45173
  return {
45008
- type: "PreCompactCaptured",
45174
+ type: "transcript:pre-compact",
45009
45175
  time: Date.now(),
45010
45176
  source: "transcript",
45011
45177
  context: {
@@ -45016,18 +45182,67 @@ var require_structured_logging = __commonJS({
45016
45182
  taskId: context.taskId
45017
45183
  },
45018
45184
  payload: {
45019
- state,
45020
- metadata,
45021
- reason: "pre_compact_hook"
45185
+ snapshotPath: state.snapshotPath,
45186
+ lineCount: state.lineCount,
45187
+ transcriptPath: metadata.transcriptPath,
45188
+ metrics: metadata.metrics
45189
+ }
45190
+ };
45191
+ },
45192
+ // --- Error Events ---
45193
+ /**
45194
+ * Create a daemon ErrorOccurred event.
45195
+ * @see packages/sidekick-daemon/src/daemon.ts — HookableLogger error hook calls this factory.
45196
+ */
45197
+ daemonErrorOccurred(context, state) {
45198
+ return {
45199
+ type: "error:occurred",
45200
+ time: Date.now(),
45201
+ source: "daemon",
45202
+ context: {
45203
+ sessionId: context.sessionId,
45204
+ correlationId: context.correlationId,
45205
+ traceId: context.traceId,
45206
+ hook: context.hook,
45207
+ taskId: context.taskId
45208
+ },
45209
+ payload: {
45210
+ errorMessage: state.errorMessage,
45211
+ errorStack: state.errorStack
45212
+ }
45213
+ };
45214
+ },
45215
+ /**
45216
+ * Create a CLI ErrorOccurred event.
45217
+ * Available for CLI error hook implementations.
45218
+ */
45219
+ cliErrorOccurred(context, state) {
45220
+ return {
45221
+ type: "error:occurred",
45222
+ time: Date.now(),
45223
+ source: "cli",
45224
+ context: {
45225
+ sessionId: context.sessionId,
45226
+ correlationId: context.correlationId,
45227
+ traceId: context.traceId,
45228
+ hook: context.hook,
45229
+ taskId: context.taskId
45230
+ },
45231
+ payload: {
45232
+ errorMessage: state.errorMessage,
45233
+ errorStack: state.errorStack
45022
45234
  }
45023
45235
  };
45024
45236
  }
45025
45237
  };
45026
45238
  function logEvent(logger, event) {
45027
- logger.info(event.payload.reason ?? `${event.type}`, {
45239
+ const payload = event.payload;
45240
+ const meta = payload != null && typeof payload === "object" ? payload : {};
45241
+ const reason = "reason" in meta ? String(meta.reason) : void 0;
45242
+ logger.info(reason ?? `${event.type}`, {
45028
45243
  type: event.type,
45029
45244
  source: event.source,
45030
- ...event.payload
45245
+ ...meta
45031
45246
  });
45032
45247
  }
45033
45248
  function setupGlobalErrorHandlers(logger) {
@@ -57064,7 +57279,7 @@ var require_staging_service = __commonJS({
57064
57279
  *
57065
57280
  * @throws Error if hookName or reminderName contain path traversal characters
57066
57281
  */
57067
- async stageReminder(sessionId, hookName, reminderName, data) {
57282
+ async stageReminder(sessionId, hookName, reminderName, data, enrichment) {
57068
57283
  (0, staging_paths_js_1.validatePathSegment)(hookName, "hookName");
57069
57284
  (0, staging_paths_js_1.validatePathSegment)(reminderName, "reminderName");
57070
57285
  const hookDir = this.getHookDirPath(sessionId, hookName);
@@ -57093,7 +57308,8 @@ var require_staging_service = __commonJS({
57093
57308
  hookName,
57094
57309
  blocking: data.blocking,
57095
57310
  priority: data.priority,
57096
- persistent: data.persistent
57311
+ persistent: data.persistent,
57312
+ ...enrichment
57097
57313
  }, { stagingPath: reminderPath });
57098
57314
  (0, structured_logging_1.logEvent)(this.options.logger, event);
57099
57315
  }
@@ -57237,8 +57453,8 @@ var require_staging_service = __commonJS({
57237
57453
  // ============================================================================
57238
57454
  // StagingService Interface Implementation (delegates to core)
57239
57455
  // ============================================================================
57240
- async stageReminder(hookName, reminderName, data) {
57241
- return this.core.stageReminder(this.sessionId, hookName, reminderName, data);
57456
+ async stageReminder(hookName, reminderName, data, enrichment) {
57457
+ return this.core.stageReminder(this.sessionId, hookName, reminderName, data, enrichment);
57242
57458
  }
57243
57459
  async readReminder(hookName, reminderName) {
57244
57460
  return this.core.readReminder(this.sessionId, hookName, reminderName);
@@ -60160,7 +60376,7 @@ var require_log_metrics_descriptors = __commonJS({
60160
60376
  });
60161
60377
 
60162
60378
  // ../sidekick-core/dist/state/index.js
60163
- var require_state2 = __commonJS({
60379
+ var require_state3 = __commonJS({
60164
60380
  "../sidekick-core/dist/state/index.js"(exports2) {
60165
60381
  "use strict";
60166
60382
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -60259,7 +60475,7 @@ var require_transcript_service = __commonJS({
60259
60475
  var node_readline_1 = require("node:readline");
60260
60476
  var node_path_1 = require("node:path");
60261
60477
  var structured_logging_js_1 = require_structured_logging();
60262
- var index_js_1 = require_state2();
60478
+ var index_js_1 = require_state3();
60263
60479
  var EXCLUDED_BUILTIN_COMMANDS = /* @__PURE__ */ new Set([
60264
60480
  "/add-dir",
60265
60481
  "/agents",
@@ -62229,6 +62445,120 @@ var require_hookable_logger = __commonJS({
62229
62445
  }
62230
62446
  });
62231
62447
 
62448
+ // ../sidekick-core/dist/project-registry.js
62449
+ var require_project_registry = __commonJS({
62450
+ "../sidekick-core/dist/project-registry.js"(exports2) {
62451
+ "use strict";
62452
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
62453
+ return mod && mod.__esModule ? mod : { "default": mod };
62454
+ };
62455
+ Object.defineProperty(exports2, "__esModule", { value: true });
62456
+ exports2.ProjectRegistryService = void 0;
62457
+ exports2.encodeProjectDir = encodeProjectDir;
62458
+ var node_fs_1 = require("node:fs");
62459
+ var promises_1 = __importDefault(require("node:fs/promises"));
62460
+ var node_crypto_1 = require("node:crypto");
62461
+ var node_path_1 = require("node:path");
62462
+ var types_1 = require_dist();
62463
+ function encodeProjectDir(absPath) {
62464
+ return absPath.replace(/\//g, "-");
62465
+ }
62466
+ var REGISTRY_FILE = "registry.json";
62467
+ var ProjectRegistryService = class {
62468
+ registryRoot;
62469
+ constructor(registryRoot) {
62470
+ this.registryRoot = registryRoot;
62471
+ }
62472
+ /**
62473
+ * Register or update a project in the registry.
62474
+ * Creates the directory and writes registry.json with current timestamp.
62475
+ */
62476
+ async register(projectDir2) {
62477
+ const encoded = encodeProjectDir(projectDir2);
62478
+ const entryDir = (0, node_path_1.join)(this.registryRoot, encoded);
62479
+ const entryFile = (0, node_path_1.join)(entryDir, REGISTRY_FILE);
62480
+ await promises_1.default.mkdir(entryDir, { recursive: true });
62481
+ const entry = {
62482
+ path: projectDir2,
62483
+ displayName: (0, node_path_1.basename)(projectDir2),
62484
+ lastActive: (/* @__PURE__ */ new Date()).toISOString()
62485
+ };
62486
+ const tmpPath = `${entryFile}.${(0, node_crypto_1.randomBytes)(6).toString("hex")}.tmp`;
62487
+ try {
62488
+ await promises_1.default.writeFile(tmpPath, JSON.stringify(entry, null, 2), "utf-8");
62489
+ await promises_1.default.rename(tmpPath, entryFile);
62490
+ } catch (err) {
62491
+ await promises_1.default.unlink(tmpPath).catch(() => {
62492
+ });
62493
+ throw err;
62494
+ }
62495
+ }
62496
+ /**
62497
+ * List all valid registered projects.
62498
+ * Skips entries with missing/invalid registry.json.
62499
+ */
62500
+ async list() {
62501
+ if (!(0, node_fs_1.existsSync)(this.registryRoot)) {
62502
+ return [];
62503
+ }
62504
+ const entries = [];
62505
+ const dirents = await promises_1.default.readdir(this.registryRoot, { withFileTypes: true });
62506
+ for (const dirent of dirents) {
62507
+ if (!dirent.isDirectory())
62508
+ continue;
62509
+ const entryFile = (0, node_path_1.join)(this.registryRoot, dirent.name, REGISTRY_FILE);
62510
+ try {
62511
+ const raw = await promises_1.default.readFile(entryFile, "utf-8");
62512
+ const parsed = types_1.ProjectRegistryEntrySchema.parse(JSON.parse(raw));
62513
+ entries.push(parsed);
62514
+ } catch {
62515
+ }
62516
+ }
62517
+ return entries;
62518
+ }
62519
+ /**
62520
+ * Prune stale registry entries.
62521
+ * Removes entries where the project path no longer exists
62522
+ * or lastActive is older than retentionDays.
62523
+ */
62524
+ async prune(options) {
62525
+ if (!(0, node_fs_1.existsSync)(this.registryRoot)) {
62526
+ return [];
62527
+ }
62528
+ const pruned = [];
62529
+ const cutoff = Date.now() - options.retentionDays * 24 * 60 * 60 * 1e3;
62530
+ const dirents = await promises_1.default.readdir(this.registryRoot, { withFileTypes: true });
62531
+ for (const dirent of dirents) {
62532
+ if (!dirent.isDirectory())
62533
+ continue;
62534
+ const entryDir = (0, node_path_1.join)(this.registryRoot, dirent.name);
62535
+ const entryFile = (0, node_path_1.join)(entryDir, REGISTRY_FILE);
62536
+ let entry;
62537
+ try {
62538
+ const raw = await promises_1.default.readFile(entryFile, "utf-8");
62539
+ entry = types_1.ProjectRegistryEntrySchema.parse(JSON.parse(raw));
62540
+ } catch {
62541
+ await promises_1.default.rm(entryDir, { recursive: true, force: true });
62542
+ continue;
62543
+ }
62544
+ let reason = null;
62545
+ if (!(0, node_fs_1.existsSync)(entry.path)) {
62546
+ reason = "path-missing";
62547
+ } else if (new Date(entry.lastActive).getTime() < cutoff) {
62548
+ reason = "age-exceeded";
62549
+ }
62550
+ if (reason) {
62551
+ await promises_1.default.rm(entryDir, { recursive: true, force: true });
62552
+ pruned.push({ path: entry.path, reason });
62553
+ }
62554
+ }
62555
+ return pruned;
62556
+ }
62557
+ };
62558
+ exports2.ProjectRegistryService = ProjectRegistryService;
62559
+ }
62560
+ });
62561
+
62232
62562
  // ../sidekick-core/dist/daemon-health.js
62233
62563
  var require_daemon_health = __commonJS({
62234
62564
  "../sidekick-core/dist/daemon-health.js"(exports2) {
@@ -62472,7 +62802,7 @@ var require_dist4 = __commonJS({
62472
62802
  };
62473
62803
  Object.defineProperty(exports2, "__esModule", { value: true });
62474
62804
  exports2.SIDEKICK_SECTION_START = exports2.detectGitignoreStatus = exports2.removeGitignoreSection = exports2.installGitignoreSection = exports2.validateOpenAIKey = exports2.validateOpenRouterKey = exports2.createSetupStatusService = exports2.SetupStatusService = exports2.DaemonClient = exports2.findZombieDaemons = exports2.killZombieDaemons = exports2.killAllDaemons = exports2.logEvent = exports2.LogEvents = exports2.DEFAULT_MAX_FILES = exports2.DEFAULT_ROTATE_SIZE_BYTES = exports2.getComponentLogLevel = exports2.setupGlobalErrorHandlers = exports2.createLoggerFacade = exports2.createLogManager = exports2.createConsoleLogger = exports2.getUserDaemonsDir = exports2.getUserPidPath = exports2.getTokenPath = exports2.getSocketPath = exports2.getProjectHash = exports2.getPidPath = exports2.getLockPath = exports2.IpcService = exports2.IpcServer = exports2.loadPersonaFile = exports2.getDefaultPersonasDir = exports2.discoverPersonas = exports2.createPersonaLoader = exports2.reconstructTranscriptPath = exports2.encodeProjectPath = exports2.isPreCompactEvent = exports2.isStopEvent = exports2.isPostToolUseEvent = exports2.isPreToolUseEvent = exports2.isUserPromptSubmitEvent = exports2.isSessionEndEvent = exports2.isSessionStartEvent = exports2.isTranscriptEvent = exports2.isHookEvent = exports2.MetricsPersistPayloadSchema = exports2.CleanupPayloadSchema = exports2.ResumeGenerationPayloadSchema = exports2.SessionSummaryPayloadSchema = exports2.TaskTypes = void 0;
62475
- exports2.loadUserProfile = exports2.parseGitStatusOutput = exports2.getGitFileStatus = exports2.isInSandbox = exports2.updateDaemonHealth = exports2.readDaemonHealth = exports2.DaemonGlobalLogMetricsDescriptor = exports2.CliLogMetricsDescriptor = exports2.DaemonLogMetricsDescriptor = exports2.CompactionHistoryDescriptor = exports2.TranscriptMetricsDescriptor = exports2.GlobalStateAccessor = exports2.SessionStateAccessor = exports2.globalState = exports2.sessionState = exports2.StateCorruptError = exports2.StateNotFoundError = exports2.StateService = exports2.createHookableLogger = exports2.InstrumentedProfileProviderFactory = exports2.InstrumentedLLMProvider = exports2.ServiceFactoryImpl = exports2.TranscriptServiceImpl = exports2.createDefaultTokenUsage = exports2.createDefaultMetrics = exports2.copyWithTimestampSync = exports2.renameWithTimestampSync = exports2.renameWithTimestamp = exports2.copyWithTimestamp = exports2.getTimestampedPath = exports2.extractToolResultPreview = exports2.extractToolCallPreview = exports2.extractTextFromContent = exports2.extractContentPreview = exports2.HandlerRegistryImpl = exports2.extractConsumedTimestamp = exports2.createConsumedFilePattern = exports2.CONSUMED_FILE_PATTERN = exports2.filterActiveReminderFiles = exports2.validatePathSegment = exports2.isValidPathSegment = exports2.getReminderPath = exports2.getHookDir = exports2.getStagingRoot = exports2.SessionScopedStagingService = exports2.StagingServiceCore = exports2.GITIGNORE_ENTRIES = exports2.SIDEKICK_SECTION_END = void 0;
62805
+ exports2.loadUserProfile = exports2.parseGitStatusOutput = exports2.getGitFileStatus = exports2.isInSandbox = exports2.updateDaemonHealth = exports2.readDaemonHealth = exports2.ProjectRegistryService = exports2.encodeProjectDir = exports2.DaemonGlobalLogMetricsDescriptor = exports2.CliLogMetricsDescriptor = exports2.DaemonLogMetricsDescriptor = exports2.CompactionHistoryDescriptor = exports2.TranscriptMetricsDescriptor = exports2.GlobalStateAccessor = exports2.SessionStateAccessor = exports2.globalState = exports2.sessionState = exports2.StateCorruptError = exports2.StateNotFoundError = exports2.StateService = exports2.createHookableLogger = exports2.InstrumentedProfileProviderFactory = exports2.InstrumentedLLMProvider = exports2.ServiceFactoryImpl = exports2.TranscriptServiceImpl = exports2.createDefaultTokenUsage = exports2.createDefaultMetrics = exports2.copyWithTimestampSync = exports2.renameWithTimestampSync = exports2.renameWithTimestamp = exports2.copyWithTimestamp = exports2.getTimestampedPath = exports2.extractToolResultPreview = exports2.extractToolCallPreview = exports2.extractTextFromContent = exports2.extractContentPreview = exports2.HandlerRegistryImpl = exports2.extractConsumedTimestamp = exports2.createConsumedFilePattern = exports2.CONSUMED_FILE_PATTERN = exports2.filterActiveReminderFiles = exports2.validatePathSegment = exports2.isValidPathSegment = exports2.getReminderPath = exports2.getHookDir = exports2.getStagingRoot = exports2.SessionScopedStagingService = exports2.StagingServiceCore = exports2.GITIGNORE_ENTRIES = exports2.SIDEKICK_SECTION_END = void 0;
62476
62806
  var types_1 = require_dist();
62477
62807
  Object.defineProperty(exports2, "TaskTypes", { enumerable: true, get: function() {
62478
62808
  return types_1.TaskTypes;
@@ -62745,7 +63075,7 @@ var require_dist4 = __commonJS({
62745
63075
  Object.defineProperty(exports2, "createHookableLogger", { enumerable: true, get: function() {
62746
63076
  return hookable_logger_1.createHookableLogger;
62747
63077
  } });
62748
- var index_js_1 = require_state2();
63078
+ var index_js_1 = require_state3();
62749
63079
  Object.defineProperty(exports2, "StateService", { enumerable: true, get: function() {
62750
63080
  return index_js_1.StateService;
62751
63081
  } });
@@ -62782,6 +63112,13 @@ var require_dist4 = __commonJS({
62782
63112
  Object.defineProperty(exports2, "DaemonGlobalLogMetricsDescriptor", { enumerable: true, get: function() {
62783
63113
  return index_js_1.DaemonGlobalLogMetricsDescriptor;
62784
63114
  } });
63115
+ var project_registry_1 = require_project_registry();
63116
+ Object.defineProperty(exports2, "encodeProjectDir", { enumerable: true, get: function() {
63117
+ return project_registry_1.encodeProjectDir;
63118
+ } });
63119
+ Object.defineProperty(exports2, "ProjectRegistryService", { enumerable: true, get: function() {
63120
+ return project_registry_1.ProjectRegistryService;
63121
+ } });
62785
63122
  var daemon_health_1 = require_daemon_health();
62786
63123
  Object.defineProperty(exports2, "readDaemonHealth", { enumerable: true, get: function() {
62787
63124
  return daemon_health_1.readDaemonHealth;
@@ -69829,7 +70166,6 @@ var require_reminder_utils = __commonJS({
69829
70166
  blocking: zod_1.z.boolean(),
69830
70167
  priority: zod_1.z.number(),
69831
70168
  persistent: zod_1.z.boolean(),
69832
- throttle: zod_1.z.boolean().optional(),
69833
70169
  userMessage: zod_1.z.string().optional(),
69834
70170
  additionalContext: zod_1.z.string().optional(),
69835
70171
  reason: zod_1.z.string().optional()
@@ -69880,7 +70216,6 @@ var require_reminder_utils = __commonJS({
69880
70216
  blocking: def.blocking,
69881
70217
  priority: def.priority,
69882
70218
  persistent: def.persistent,
69883
- throttle: def.throttle,
69884
70219
  userMessage: def.userMessage ? interpolateTemplate(def.userMessage, context) : void 0,
69885
70220
  additionalContext: def.additionalContext ? interpolateTemplate(def.additionalContext, context) : void 0,
69886
70221
  reason: def.reason ? interpolateTemplate(def.reason, context) : void 0
@@ -69890,8 +70225,8 @@ var require_reminder_utils = __commonJS({
69890
70225
  return null;
69891
70226
  }
69892
70227
  }
69893
- async function stageReminder(ctx, hookName, reminder) {
69894
- await ctx.staging.stageReminder(hookName, reminder.name, reminder);
70228
+ async function stageReminder(ctx, hookName, reminder, enrichment) {
70229
+ await ctx.staging.stageReminder(hookName, reminder.name, reminder, enrichment);
69895
70230
  ctx.logger.debug("Staged reminder", { hookName, reminderName: reminder.name, priority: reminder.priority });
69896
70231
  }
69897
70232
  async function consumeReminder(ctx, hookName) {
@@ -70205,7 +70540,7 @@ var require_types2 = __commonJS({
70205
70540
  });
70206
70541
 
70207
70542
  // ../feature-reminders/dist/state.js
70208
- var require_state3 = __commonJS({
70543
+ var require_state4 = __commonJS({
70209
70544
  "../feature-reminders/dist/state.js"(exports2) {
70210
70545
  "use strict";
70211
70546
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -70246,7 +70581,7 @@ var require_throttle_utils = __commonJS({
70246
70581
  Object.defineProperty(exports2, "__esModule", { value: true });
70247
70582
  exports2.registerThrottledReminder = registerThrottledReminder;
70248
70583
  exports2.resetThrottleCounters = resetThrottleCounters;
70249
- var state_js_1 = require_state3();
70584
+ var state_js_1 = require_state4();
70250
70585
  async function registerThrottledReminder(ctx, sessionId, reminderId, targetHook, resolvedReminder) {
70251
70586
  const remindersState = (0, state_js_1.createRemindersState)(ctx.stateService);
70252
70587
  const result = await remindersState.reminderThrottle.read(sessionId);
@@ -70281,7 +70616,7 @@ var require_stage_default_user_prompt = __commonJS({
70281
70616
  var staging_handler_utils_js_1 = require_staging_handler_utils();
70282
70617
  var types_js_1 = require_types2();
70283
70618
  var reminder_utils_js_1 = require_reminder_utils();
70284
- var state_js_1 = require_state3();
70619
+ var state_js_1 = require_state4();
70285
70620
  var throttle_utils_js_1 = require_throttle_utils();
70286
70621
  function registerStageDefaultUserPrompt(context) {
70287
70622
  (0, staging_handler_utils_js_1.createStagingHandler)(context, {
@@ -70437,16 +70772,128 @@ var require_stage_default_user_prompt = __commonJS({
70437
70772
  }
70438
70773
  });
70439
70774
 
70775
+ // ../feature-reminders/dist/events.js
70776
+ var require_events2 = __commonJS({
70777
+ "../feature-reminders/dist/events.js"(exports2) {
70778
+ "use strict";
70779
+ Object.defineProperty(exports2, "__esModule", { value: true });
70780
+ exports2.ReminderEvents = void 0;
70781
+ exports2.ReminderEvents = {
70782
+ /**
70783
+ * Create a ReminderConsumed event (logged when CLI returns a staged reminder).
70784
+ */
70785
+ reminderConsumed(context, state, _metadata) {
70786
+ return {
70787
+ type: "reminder:consumed",
70788
+ time: Date.now(),
70789
+ source: "cli",
70790
+ context: {
70791
+ sessionId: context.sessionId,
70792
+ correlationId: context.correlationId,
70793
+ traceId: context.traceId,
70794
+ hook: context.hook,
70795
+ taskId: context.taskId
70796
+ },
70797
+ payload: {
70798
+ reminderName: state.reminderName,
70799
+ reminderReturned: state.reminderReturned,
70800
+ blocking: state.blocking,
70801
+ priority: state.priority,
70802
+ persistent: state.persistent,
70803
+ ...state.classificationResult !== void 0 && {
70804
+ classificationResult: state.classificationResult
70805
+ }
70806
+ }
70807
+ };
70808
+ },
70809
+ // Note: reminderStaged stays in @sidekick/core (used by staging-service.ts, circular dep)
70810
+ /**
70811
+ * Create a ReminderUnstaged event (logged when a reminder is removed from staging).
70812
+ */
70813
+ reminderUnstaged(context, state) {
70814
+ return {
70815
+ type: "reminder:unstaged",
70816
+ time: Date.now(),
70817
+ source: "daemon",
70818
+ context: {
70819
+ sessionId: context.sessionId,
70820
+ correlationId: context.correlationId,
70821
+ traceId: context.traceId,
70822
+ hook: context.hook,
70823
+ taskId: context.taskId
70824
+ },
70825
+ payload: {
70826
+ reminderName: state.reminderName,
70827
+ hookName: state.hookName,
70828
+ reason: state.reason,
70829
+ ...state.triggeredBy !== void 0 && { triggeredBy: state.triggeredBy },
70830
+ ...state.toolState !== void 0 && { toolState: state.toolState }
70831
+ }
70832
+ };
70833
+ },
70834
+ /**
70835
+ * Create a RemindersCleared event (logged when staging directory is cleaned).
70836
+ */
70837
+ remindersCleared(context, state, reason) {
70838
+ return {
70839
+ type: "reminder:cleared",
70840
+ time: Date.now(),
70841
+ source: "daemon",
70842
+ context: {
70843
+ sessionId: context.sessionId,
70844
+ correlationId: context.correlationId,
70845
+ traceId: context.traceId,
70846
+ hook: context.hook,
70847
+ taskId: context.taskId
70848
+ },
70849
+ payload: {
70850
+ clearedCount: state.clearedCount,
70851
+ hookNames: state.hookNames,
70852
+ reason
70853
+ }
70854
+ };
70855
+ },
70856
+ /**
70857
+ * Create a ReminderNotStaged event (logged when daemon evaluates but decides not to stage).
70858
+ */
70859
+ reminderNotStaged(context, state) {
70860
+ return {
70861
+ type: "reminder:not-staged",
70862
+ time: Date.now(),
70863
+ source: "daemon",
70864
+ context: {
70865
+ sessionId: context.sessionId,
70866
+ correlationId: context.correlationId,
70867
+ traceId: context.traceId,
70868
+ hook: context.hook,
70869
+ taskId: context.taskId
70870
+ },
70871
+ payload: {
70872
+ reminderName: state.reminderName,
70873
+ hookName: state.hookName,
70874
+ reason: state.reason,
70875
+ ...state.threshold !== void 0 && { threshold: state.threshold },
70876
+ ...state.currentValue !== void 0 && { currentValue: state.currentValue },
70877
+ ...state.triggeredBy !== void 0 && { triggeredBy: state.triggeredBy }
70878
+ }
70879
+ };
70880
+ }
70881
+ };
70882
+ }
70883
+ });
70884
+
70440
70885
  // ../feature-reminders/dist/handlers/staging/stage-pause-and-reflect.js
70441
70886
  var require_stage_pause_and_reflect = __commonJS({
70442
70887
  "../feature-reminders/dist/handlers/staging/stage-pause-and-reflect.js"(exports2) {
70443
70888
  "use strict";
70444
70889
  Object.defineProperty(exports2, "__esModule", { value: true });
70445
70890
  exports2.registerStagePauseAndReflect = registerStagePauseAndReflect;
70891
+ var core_1 = require_dist4();
70446
70892
  var types_1 = require_dist();
70893
+ var events_js_1 = require_events2();
70447
70894
  var staging_handler_utils_js_1 = require_staging_handler_utils();
70448
70895
  var types_js_1 = require_types2();
70449
- var state_js_1 = require_state3();
70896
+ var state_js_1 = require_state4();
70450
70897
  function registerStagePauseAndReflect(context) {
70451
70898
  (0, staging_handler_utils_js_1.createStagingHandler)(context, {
70452
70899
  id: "reminders:stage-pause-and-reflect",
@@ -70457,15 +70904,17 @@ var require_stage_pause_and_reflect = __commonJS({
70457
70904
  return void 0;
70458
70905
  const metrics = event.metadata.metrics;
70459
70906
  const sessionId = event.context?.sessionId;
70907
+ if (!sessionId) {
70908
+ ctx.logger.warn("[stage-pause-and-reflect] No sessionId available, skipping");
70909
+ return void 0;
70910
+ }
70460
70911
  const featureConfig = context.config.getFeature("reminders");
70461
70912
  const config = { ...types_js_1.DEFAULT_REMINDERS_SETTINGS, ...featureConfig.settings };
70462
70913
  let prBaseline = null;
70463
- if (sessionId) {
70464
- const remindersState = (0, state_js_1.createRemindersState)(ctx.stateService);
70465
- const result = await remindersState.prBaseline.read(sessionId);
70466
- if (result.source !== "default") {
70467
- prBaseline = result.data;
70468
- }
70914
+ const remindersState = (0, state_js_1.createRemindersState)(ctx.stateService);
70915
+ const result = await remindersState.prBaseline.read(sessionId);
70916
+ if (result.source !== "default") {
70917
+ prBaseline = result.data;
70469
70918
  }
70470
70919
  let effectiveBaseline = 0;
70471
70920
  if (prBaseline && prBaseline.turnCount === metrics.turnCount) {
@@ -70477,12 +70926,28 @@ var require_stage_pause_and_reflect = __commonJS({
70477
70926
  effectiveBaseline = Math.max(effectiveBaseline, lastConsumed.stagedAt.toolsThisTurn);
70478
70927
  }
70479
70928
  const shouldReactivate = metrics.turnCount > lastConsumed.stagedAt.turnCount || metrics.toolsThisTurn >= effectiveBaseline + config.pause_and_reflect_threshold;
70480
- if (!shouldReactivate)
70929
+ if (!shouldReactivate) {
70930
+ (0, core_1.logEvent)(ctx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
70931
+ reminderName: "pause-and-reflect",
70932
+ hookName: "PreToolUse",
70933
+ reason: "same_turn",
70934
+ triggeredBy: "tool_result"
70935
+ }));
70481
70936
  return void 0;
70937
+ }
70482
70938
  }
70483
70939
  const toolsSinceBaseline = metrics.toolsThisTurn - effectiveBaseline;
70484
- if (toolsSinceBaseline < config.pause_and_reflect_threshold)
70940
+ if (toolsSinceBaseline < config.pause_and_reflect_threshold) {
70941
+ (0, core_1.logEvent)(ctx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
70942
+ reminderName: "pause-and-reflect",
70943
+ hookName: "PreToolUse",
70944
+ reason: "below_threshold",
70945
+ threshold: config.pause_and_reflect_threshold,
70946
+ currentValue: toolsSinceBaseline,
70947
+ triggeredBy: "tool_result"
70948
+ }));
70485
70949
  return void 0;
70950
+ }
70486
70951
  return {
70487
70952
  reminderId: types_js_1.ReminderIds.PAUSE_AND_REFLECT,
70488
70953
  targetHook: "PreToolUse",
@@ -72064,12 +72529,14 @@ var require_track_verification_tools = __commonJS({
72064
72529
  Object.defineProperty(exports2, "__esModule", { value: true });
72065
72530
  exports2.registerTrackVerificationTools = registerTrackVerificationTools;
72066
72531
  exports2.stageToolsForFiles = stageToolsForFiles;
72532
+ var core_1 = require_dist4();
72533
+ var events_js_1 = require_events2();
72067
72534
  var types_1 = require_dist();
72068
72535
  var picomatch_1 = __importDefault(require_picomatch2());
72069
72536
  var tool_pattern_matcher_js_1 = require_tool_pattern_matcher();
72070
72537
  var reminder_utils_js_1 = require_reminder_utils();
72071
72538
  var types_js_1 = require_types2();
72072
- var state_js_1 = require_state3();
72539
+ var state_js_1 = require_state4();
72073
72540
  var FILE_EDIT_TOOLS = ["Write", "Edit", "MultiEdit"];
72074
72541
  var TOOL_REMINDER_MAP = {
72075
72542
  build: types_js_1.ReminderIds.VC_BUILD,
@@ -72117,22 +72584,48 @@ var require_track_verification_tools = __commonJS({
72117
72584
  }
72118
72585
  });
72119
72586
  }
72120
- async function stageToolsForFiles(filePaths, daemonCtx, sessionId, verificationTools, toolsState, remindersState) {
72587
+ async function stageToolsForFiles(filePaths, daemonCtx, sessionId, verificationTools, toolsState, remindersState, triggeredBy = "file_edit") {
72121
72588
  const existingReminders = await daemonCtx.staging.listReminders("Stop");
72122
72589
  const stagedNames = new Set(existingReminders.map((r) => r.name));
72123
72590
  let anyStaged = false;
72591
+ const emittedNotStaged = /* @__PURE__ */ new Set();
72124
72592
  for (const filePath of filePaths) {
72125
72593
  for (const [toolName, toolConfig] of Object.entries(verificationTools)) {
72126
- if (!toolConfig.enabled)
72127
- continue;
72128
72594
  const reminderId = TOOL_REMINDER_MAP[toolName];
72129
72595
  if (!reminderId)
72130
72596
  continue;
72131
- if (!picomatch_1.default.isMatch(filePath, toolConfig.clearing_patterns))
72597
+ if (!toolConfig.enabled) {
72598
+ const emitKey = `${reminderId}:feature_disabled`;
72599
+ if (!emittedNotStaged.has(emitKey)) {
72600
+ emittedNotStaged.add(emitKey);
72601
+ (0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
72602
+ reminderName: reminderId,
72603
+ hookName: "Stop",
72604
+ reason: "feature_disabled",
72605
+ triggeredBy
72606
+ }));
72607
+ }
72608
+ continue;
72609
+ }
72610
+ if (!picomatch_1.default.isMatch(filePath, toolConfig.clearing_patterns)) {
72611
+ const emitKey = `${reminderId}:pattern_mismatch`;
72612
+ if (!emittedNotStaged.has(emitKey)) {
72613
+ emittedNotStaged.add(emitKey);
72614
+ (0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
72615
+ reminderName: reminderId,
72616
+ hookName: "Stop",
72617
+ reason: "pattern_mismatch",
72618
+ triggeredBy
72619
+ }));
72620
+ }
72132
72621
  continue;
72622
+ }
72133
72623
  const current = toolsState[toolName];
72134
72624
  if (!current || current.status === "staged") {
72135
- const staged = await ensureToolReminderStaged(daemonCtx, reminderId, stagedNames);
72625
+ const staged = await ensureToolReminderStaged(daemonCtx, reminderId, stagedNames, {
72626
+ reason: current ? "re-staged" : "initial",
72627
+ triggeredBy: "file_edit"
72628
+ });
72136
72629
  if (staged) {
72137
72630
  if (!current) {
72138
72631
  toolsState[toolName] = {
@@ -72148,7 +72641,11 @@ var require_track_verification_tools = __commonJS({
72148
72641
  } else {
72149
72642
  const newEdits = current.editsSinceVerified + 1;
72150
72643
  if (newEdits >= toolConfig.clearing_threshold) {
72151
- const staged = await ensureToolReminderStaged(daemonCtx, reminderId, stagedNames);
72644
+ const staged = await ensureToolReminderStaged(daemonCtx, reminderId, stagedNames, {
72645
+ reason: "threshold_reached",
72646
+ triggeredBy: "file_edit",
72647
+ thresholdState: { current: newEdits, threshold: toolConfig.clearing_threshold }
72648
+ });
72152
72649
  if (staged) {
72153
72650
  toolsState[toolName] = {
72154
72651
  ...current,
@@ -72165,6 +72662,14 @@ var require_track_verification_tools = __commonJS({
72165
72662
  status: "cooldown",
72166
72663
  editsSinceVerified: newEdits
72167
72664
  };
72665
+ (0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
72666
+ reminderName: reminderId,
72667
+ hookName: "Stop",
72668
+ reason: "below_threshold",
72669
+ threshold: toolConfig.clearing_threshold,
72670
+ currentValue: newEdits,
72671
+ triggeredBy
72672
+ }));
72168
72673
  }
72169
72674
  }
72170
72675
  }
@@ -72210,6 +72715,16 @@ var require_track_verification_tools = __commonJS({
72210
72715
  lastMatchedScope: match.scope
72211
72716
  };
72212
72717
  await daemonCtx.staging.deleteReminder("Stop", reminderId);
72718
+ (0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderUnstaged({ sessionId }, {
72719
+ reminderName: reminderId,
72720
+ hookName: "Stop",
72721
+ reason: "tool_verified",
72722
+ triggeredBy: "verification_passed",
72723
+ toolState: {
72724
+ status: toolsState[toolName].status,
72725
+ editsSinceVerified: toolsState[toolName].editsSinceVerified
72726
+ }
72727
+ }));
72213
72728
  anyUnstaged = true;
72214
72729
  daemonCtx.logger.debug("VC tool verified", {
72215
72730
  toolName,
@@ -72224,12 +72739,18 @@ var require_track_verification_tools = __commonJS({
72224
72739
  const hasPerToolReminders = remaining.some((r) => VC_TOOL_NAME_SET.has(r.name));
72225
72740
  if (!hasPerToolReminders) {
72226
72741
  await daemonCtx.staging.deleteReminder("Stop", types_js_1.ReminderIds.VERIFY_COMPLETION);
72742
+ (0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderUnstaged({ sessionId }, {
72743
+ reminderName: types_js_1.ReminderIds.VERIFY_COMPLETION,
72744
+ hookName: "Stop",
72745
+ reason: "all_tools_verified",
72746
+ triggeredBy: "verification_passed"
72747
+ }));
72227
72748
  daemonCtx.logger.info("All VC tools verified, unstaged wrapper", { sessionId });
72228
72749
  }
72229
72750
  await remindersState.verificationTools.write(sessionId, toolsState);
72230
72751
  }
72231
72752
  }
72232
- async function ensureToolReminderStaged(daemonCtx, reminderId, stagedNames) {
72753
+ async function ensureToolReminderStaged(daemonCtx, reminderId, stagedNames, enrichment) {
72233
72754
  if (stagedNames.has(reminderId))
72234
72755
  return true;
72235
72756
  const reminder = (0, reminder_utils_js_1.resolveReminder)(reminderId, {
@@ -72243,7 +72764,7 @@ var require_track_verification_tools = __commonJS({
72243
72764
  await (0, reminder_utils_js_1.stageReminder)(daemonCtx, "Stop", {
72244
72765
  ...reminder,
72245
72766
  stagedAt: { timestamp: Date.now(), turnCount: 0, toolsThisTurn: 0, toolCount: 0 }
72246
- });
72767
+ }, enrichment);
72247
72768
  return true;
72248
72769
  }
72249
72770
  }
@@ -72259,11 +72780,12 @@ var require_stage_stop_bash_changes = __commonJS({
72259
72780
  Object.defineProperty(exports2, "__esModule", { value: true });
72260
72781
  exports2.registerStageBashChanges = registerStageBashChanges;
72261
72782
  var core_1 = require_dist4();
72783
+ var events_js_1 = require_events2();
72262
72784
  var types_1 = require_dist();
72263
72785
  var picomatch_1 = __importDefault(require_picomatch2());
72264
72786
  var track_verification_tools_js_1 = require_track_verification_tools();
72265
72787
  var types_js_1 = require_types2();
72266
- var state_js_1 = require_state3();
72788
+ var state_js_1 = require_state4();
72267
72789
  var GIT_STATUS_TIMEOUT_MS = 200;
72268
72790
  var MAX_BASELINES = 50;
72269
72791
  function registerStageBashChanges(context) {
@@ -72328,6 +72850,12 @@ var require_stage_stop_bash_changes = __commonJS({
72328
72850
  if (lastConsumed?.stagedAt) {
72329
72851
  const shouldReactivate = metrics.turnCount > lastConsumed.stagedAt.turnCount;
72330
72852
  if (!shouldReactivate) {
72853
+ (0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
72854
+ reminderName: "verify-completion",
72855
+ hookName: "Stop",
72856
+ reason: "same_turn",
72857
+ triggeredBy: "bash_command"
72858
+ }));
72331
72859
  daemonCtx.logger.debug("Bash VC: skipped (already consumed this turn)", {
72332
72860
  currentTurn: metrics.turnCount,
72333
72861
  lastConsumedTurn: lastConsumed.stagedAt.turnCount
@@ -72343,12 +72871,25 @@ var require_stage_stop_bash_changes = __commonJS({
72343
72871
  currentCount: current.length,
72344
72872
  newFileCount: newFiles.length
72345
72873
  });
72346
- if (newFiles.length === 0)
72874
+ if (newFiles.length === 0) {
72875
+ (0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
72876
+ reminderName: "verify-completion",
72877
+ hookName: "Stop",
72878
+ reason: "no_changes_detected",
72879
+ triggeredBy: "bash_command"
72880
+ }));
72347
72881
  return;
72882
+ }
72348
72883
  const featureConfig = context.config.getFeature("reminders");
72349
72884
  const config = { ...types_js_1.DEFAULT_REMINDERS_SETTINGS, ...featureConfig.settings };
72350
72885
  const sourceMatches = newFiles.filter((f) => picomatch_1.default.isMatch(f, config.source_code_patterns));
72351
72886
  if (sourceMatches.length === 0) {
72887
+ (0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
72888
+ reminderName: "verify-completion",
72889
+ hookName: "Stop",
72890
+ reason: "pattern_mismatch",
72891
+ triggeredBy: "bash_command"
72892
+ }));
72352
72893
  daemonCtx.logger.debug("Bash VC: new files found but no source code matches", { newFiles });
72353
72894
  return;
72354
72895
  }
@@ -72362,7 +72903,7 @@ var require_stage_stop_bash_changes = __commonJS({
72362
72903
  const remindersState = (0, state_js_1.createRemindersState)(daemonCtx.stateService);
72363
72904
  const stateResult = await remindersState.verificationTools.read(sessionId);
72364
72905
  const toolsState = { ...stateResult.data };
72365
- await (0, track_verification_tools_js_1.stageToolsForFiles)(sourceMatches, daemonCtx, sessionId, verificationTools, toolsState, remindersState);
72906
+ await (0, track_verification_tools_js_1.stageToolsForFiles)(sourceMatches, daemonCtx, sessionId, verificationTools, toolsState, remindersState, "bash_command");
72366
72907
  }
72367
72908
  });
72368
72909
  }
@@ -72375,10 +72916,12 @@ var require_unstage_verify_completion = __commonJS({
72375
72916
  "use strict";
72376
72917
  Object.defineProperty(exports2, "__esModule", { value: true });
72377
72918
  exports2.registerUnstageVerifyCompletion = registerUnstageVerifyCompletion;
72919
+ var core_1 = require_dist4();
72920
+ var events_js_1 = require_events2();
72378
72921
  var types_1 = require_dist();
72379
72922
  var types_js_1 = require_types2();
72380
72923
  var reminder_utils_js_1 = require_reminder_utils();
72381
- var state_js_1 = require_state3();
72924
+ var state_js_1 = require_state4();
72382
72925
  function registerUnstageVerifyCompletion(context) {
72383
72926
  if (!(0, types_1.isDaemonContext)(context))
72384
72927
  return;
@@ -72397,6 +72940,7 @@ var require_unstage_verify_completion = __commonJS({
72397
72940
  if (!sessionId) {
72398
72941
  daemonCtx.logger.warn("No sessionId in UserPromptSubmit event");
72399
72942
  await daemonCtx.staging.deleteReminder("Stop", types_js_1.ReminderIds.VERIFY_COMPLETION);
72943
+ (0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderUnstaged({ sessionId: "" }, { reminderName: types_js_1.ReminderIds.VERIFY_COMPLETION, hookName: "Stop", reason: "no_session_id" }));
72400
72944
  return;
72401
72945
  }
72402
72946
  const remindersState = (0, state_js_1.createRemindersState)(daemonCtx.stateService);
@@ -72472,13 +73016,26 @@ var require_unstage_verify_completion = __commonJS({
72472
73016
  await remindersState.vcUnverified.delete(sessionId);
72473
73017
  }
72474
73018
  } else {
73019
+ (0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
73020
+ reminderName: "verify-completion",
73021
+ hookName: "Stop",
73022
+ reason: "no_unverified_changes"
73023
+ }));
72475
73024
  daemonCtx.logger.info("VC unstage: no unverified changes, clearing reminder", {
72476
73025
  sessionId,
72477
73026
  hadState: unverifiedState !== null
72478
73027
  });
72479
73028
  }
73029
+ const eventContext = { sessionId };
73030
+ const reason = unverifiedState?.hasUnverifiedChanges ? "cycle_limit_reached" : "no_unverified_changes";
72480
73031
  for (const vcId of types_js_1.ALL_VC_REMINDER_IDS) {
72481
73032
  await daemonCtx.staging.deleteReminder("Stop", vcId);
73033
+ (0, core_1.logEvent)(daemonCtx.logger, events_js_1.ReminderEvents.reminderUnstaged(eventContext, {
73034
+ reminderName: vcId,
73035
+ hookName: "Stop",
73036
+ reason,
73037
+ triggeredBy: unverifiedState?.hasUnverifiedChanges ? "cycle_limit" : "no_unverified_changes"
73038
+ }));
72482
73039
  }
72483
73040
  daemonCtx.logger.debug("VC unstage: deleted all VC reminders");
72484
73041
  }
@@ -72496,6 +73053,7 @@ var require_stage_persona_reminders = __commonJS({
72496
73053
  exports2.stagePersonaRemindersForSession = stagePersonaRemindersForSession;
72497
73054
  exports2.registerStagePersonaReminders = registerStagePersonaReminders;
72498
73055
  var core_1 = require_dist4();
73056
+ var events_js_1 = require_events2();
72499
73057
  var types_1 = require_dist();
72500
73058
  var reminder_utils_js_1 = require_reminder_utils();
72501
73059
  var types_js_1 = require_types2();
@@ -72516,10 +73074,21 @@ var require_stage_persona_reminders = __commonJS({
72516
73074
  }
72517
73075
  var PERSONA_REMINDER_HOOKS = ["UserPromptSubmit", "SessionStart"];
72518
73076
  async function clearPersonaReminders(ctx, sessionId) {
73077
+ const eventContext = { sessionId };
72519
73078
  for (const hook of PERSONA_REMINDER_HOOKS) {
72520
73079
  await ctx.staging.deleteReminder(hook, types_js_1.ReminderIds.REMEMBER_YOUR_PERSONA);
73080
+ (0, core_1.logEvent)(ctx.logger, events_js_1.ReminderEvents.reminderUnstaged(eventContext, {
73081
+ reminderName: types_js_1.ReminderIds.REMEMBER_YOUR_PERSONA,
73082
+ hookName: hook,
73083
+ reason: "persona_cleared"
73084
+ }));
72521
73085
  }
72522
73086
  await ctx.staging.deleteReminder("UserPromptSubmit", types_js_1.ReminderIds.PERSONA_CHANGED);
73087
+ (0, core_1.logEvent)(ctx.logger, events_js_1.ReminderEvents.reminderUnstaged(eventContext, {
73088
+ reminderName: types_js_1.ReminderIds.PERSONA_CHANGED,
73089
+ hookName: "UserPromptSubmit",
73090
+ reason: "persona_cleared"
73091
+ }));
72523
73092
  const lastStaged = await readLastStagedPersona(ctx, sessionId);
72524
73093
  if (lastStaged !== null) {
72525
73094
  await writeLastStagedPersona(ctx, sessionId, null);
@@ -72564,12 +73133,22 @@ var require_stage_persona_reminders = __commonJS({
72564
73133
  }
72565
73134
  async function stagePersonaRemindersForSession(ctx, sessionId, options) {
72566
73135
  if (!isPersonaInjectionEnabled(ctx)) {
73136
+ (0, core_1.logEvent)(ctx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
73137
+ reminderName: "remember-your-persona",
73138
+ hookName: "PreToolUse",
73139
+ reason: "feature_disabled"
73140
+ }));
72567
73141
  await clearPersonaReminders(ctx, sessionId);
72568
73142
  ctx.logger.debug("Persona injection disabled by config, cleaned up reminders", { sessionId });
72569
73143
  return;
72570
73144
  }
72571
73145
  const persona = await loadPersonaForSession(ctx, sessionId);
72572
73146
  if (!persona) {
73147
+ (0, core_1.logEvent)(ctx.logger, events_js_1.ReminderEvents.reminderNotStaged({ sessionId }, {
73148
+ reminderName: "remember-your-persona",
73149
+ hookName: "PreToolUse",
73150
+ reason: "no_persona"
73151
+ }));
72573
73152
  await clearPersonaReminders(ctx, sessionId);
72574
73153
  ctx.logger.debug("Persona cleared or disabled, unstaged persona reminders", { sessionId });
72575
73154
  return;
@@ -72598,6 +73177,11 @@ var require_stage_persona_reminders = __commonJS({
72598
73177
  const isGenuineChange = lastStaged !== null && // null = never staged (initialization) → skip
72599
73178
  lastStaged.personaId !== persona.id;
72600
73179
  if (isGenuineChange) {
73180
+ (0, core_1.logEvent)(ctx.logger, core_1.LogEvents.personaChanged({ sessionId }, {
73181
+ personaFrom: lastStaged.personaId ?? "none",
73182
+ personaTo: persona.id,
73183
+ reason: "mid_session_change"
73184
+ }));
72601
73185
  const changedReminder = (0, reminder_utils_js_1.resolveReminder)(types_js_1.ReminderIds.PERSONA_CHANGED, {
72602
73186
  context: templateContext,
72603
73187
  assets: ctx.assets
@@ -72655,6 +73239,7 @@ var require_stage_user_profile_reminders = __commonJS({
72655
73239
  exports2.stageUserProfileRemindersForSession = stageUserProfileRemindersForSession;
72656
73240
  exports2.registerStageUserProfileReminders = registerStageUserProfileReminders;
72657
73241
  var core_1 = require_dist4();
73242
+ var events_js_1 = require_events2();
72658
73243
  var types_1 = require_dist();
72659
73244
  var reminder_utils_js_1 = require_reminder_utils();
72660
73245
  var types_js_1 = require_types2();
@@ -72662,8 +73247,14 @@ var require_stage_user_profile_reminders = __commonJS({
72662
73247
  async function stageUserProfileRemindersForSession(ctx, sessionId) {
72663
73248
  const profile = (0, core_1.loadUserProfile)({ logger: ctx.logger });
72664
73249
  if (!profile) {
73250
+ const eventContext = { sessionId };
72665
73251
  for (const hook of USER_PROFILE_REMINDER_HOOKS) {
72666
73252
  await ctx.staging.deleteReminder(hook, types_js_1.ReminderIds.USER_PROFILE);
73253
+ (0, core_1.logEvent)(ctx.logger, events_js_1.ReminderEvents.reminderUnstaged(eventContext, {
73254
+ reminderName: types_js_1.ReminderIds.USER_PROFILE,
73255
+ hookName: hook,
73256
+ reason: "no_user_profile"
73257
+ }));
72667
73258
  }
72668
73259
  return;
72669
73260
  }
@@ -72732,60 +73323,6 @@ var require_staging2 = __commonJS({
72732
73323
  }
72733
73324
  });
72734
73325
 
72735
- // ../feature-reminders/dist/events.js
72736
- var require_events2 = __commonJS({
72737
- "../feature-reminders/dist/events.js"(exports2) {
72738
- "use strict";
72739
- Object.defineProperty(exports2, "__esModule", { value: true });
72740
- exports2.ReminderEvents = void 0;
72741
- exports2.ReminderEvents = {
72742
- /**
72743
- * Create a ReminderConsumed event (logged when CLI returns a staged reminder).
72744
- */
72745
- reminderConsumed(context, state, metadata) {
72746
- return {
72747
- type: "ReminderConsumed",
72748
- time: Date.now(),
72749
- source: "cli",
72750
- context: {
72751
- sessionId: context.sessionId,
72752
- correlationId: context.correlationId,
72753
- traceId: context.traceId,
72754
- hook: context.hook,
72755
- taskId: context.taskId
72756
- },
72757
- payload: {
72758
- state,
72759
- metadata
72760
- }
72761
- };
72762
- },
72763
- // Note: reminderStaged stays in @sidekick/core (used by staging-service.ts, circular dep)
72764
- /**
72765
- * Create a RemindersCleared event (logged when staging directory is cleaned).
72766
- */
72767
- remindersCleared(context, state, reason) {
72768
- return {
72769
- type: "RemindersCleared",
72770
- time: Date.now(),
72771
- source: "daemon",
72772
- context: {
72773
- sessionId: context.sessionId,
72774
- correlationId: context.correlationId,
72775
- traceId: context.traceId,
72776
- hook: context.hook,
72777
- taskId: context.taskId
72778
- },
72779
- payload: {
72780
- state,
72781
- reason
72782
- }
72783
- };
72784
- }
72785
- };
72786
- }
72787
- });
72788
-
72789
73326
  // ../feature-reminders/dist/cli-staging-reader.js
72790
73327
  var require_cli_staging_reader = __commonJS({
72791
73328
  "../feature-reminders/dist/cli-staging-reader.js"(exports2) {
@@ -72911,7 +73448,19 @@ var require_consumption_handler_factory = __commonJS({
72911
73448
  reader.renameReminder(hook, reminder.name);
72912
73449
  }
72913
73450
  }
72914
- let response = buildResponse ? await buildResponse({ reminder: primary, reader, cliCtx, sessionId, event, supportsBlocking }) : buildDefaultResponse(primary, supportsBlocking);
73451
+ let enrichment;
73452
+ let response;
73453
+ if (buildResponse) {
73454
+ const result = await buildResponse({ reminder: primary, reader, cliCtx, sessionId, event, supportsBlocking });
73455
+ if ("response" in result && typeof result.response === "object") {
73456
+ response = result.response;
73457
+ enrichment = result.enrichment;
73458
+ } else {
73459
+ response = result;
73460
+ }
73461
+ } else {
73462
+ response = buildDefaultResponse(primary, supportsBlocking);
73463
+ }
72915
73464
  const secondaryContexts = reminders.slice(1).map((r) => r.additionalContext).filter((ctx2) => !!ctx2);
72916
73465
  if (secondaryContexts.length > 0) {
72917
73466
  const existing = response.additionalContext;
@@ -72929,7 +73478,8 @@ var require_consumption_handler_factory = __commonJS({
72929
73478
  reminderReturned: true,
72930
73479
  blocking: response.blocking ?? false,
72931
73480
  priority: primary.priority,
72932
- persistent: primary.persistent
73481
+ persistent: primary.persistent,
73482
+ ...enrichment
72933
73483
  }));
72934
73484
  return { response };
72935
73485
  }
@@ -73031,6 +73581,13 @@ var require_inject_stop = __commonJS({
73031
73581
  shouldBlock: classification.shouldBlock,
73032
73582
  reasoning: classification.reasoning?.slice(0, 200)
73033
73583
  });
73584
+ const classificationEnrichment = {
73585
+ classificationResult: {
73586
+ category: classification.category,
73587
+ confidence: classification.confidence,
73588
+ shouldBlock: classification.shouldBlock
73589
+ }
73590
+ };
73034
73591
  if (classification.shouldBlock) {
73035
73592
  cliCtx.logger.info("VC inject-stop: BLOCKING (claiming completion)", { sessionId });
73036
73593
  try {
@@ -73040,7 +73597,10 @@ var require_inject_stop = __commonJS({
73040
73597
  error: String(clearErr)
73041
73598
  });
73042
73599
  }
73043
- return (0, consumption_handler_factory_js_1.buildDefaultResponse)(reminder, supportsBlocking);
73600
+ return {
73601
+ response: (0, consumption_handler_factory_js_1.buildDefaultResponse)(reminder, supportsBlocking),
73602
+ enrichment: classificationEnrichment
73603
+ };
73044
73604
  } else {
73045
73605
  cliCtx.logger.info("VC inject-stop: NOT BLOCKING", {
73046
73606
  sessionId,
@@ -73066,13 +73626,13 @@ var require_inject_stop = __commonJS({
73066
73626
  });
73067
73627
  }
73068
73628
  if (classification.category === "ASKING_QUESTION" || classification.category === "ANSWERING_QUESTION") {
73069
- return {};
73629
+ return { response: {}, enrichment: classificationEnrichment };
73070
73630
  } else {
73071
73631
  const response = {};
73072
73632
  if (classification.userMessage) {
73073
73633
  response.userMessage = classification.userMessage;
73074
73634
  }
73075
- return response;
73635
+ return { response, enrichment: classificationEnrichment };
73076
73636
  }
73077
73637
  }
73078
73638
  } catch (err) {
@@ -73328,7 +73888,7 @@ var require_reminder_consumed = __commonJS({
73328
73888
  "use strict";
73329
73889
  Object.defineProperty(exports2, "__esModule", { value: true });
73330
73890
  exports2.handleReminderConsumed = handleReminderConsumed;
73331
- var state_js_1 = require_state3();
73891
+ var state_js_1 = require_state4();
73332
73892
  var types_js_1 = require_types2();
73333
73893
  async function handleReminderConsumed(params, ctx) {
73334
73894
  const { sessionId, reminderName, metrics } = params;
@@ -73353,7 +73913,7 @@ var require_vc_unverified = __commonJS({
73353
73913
  Object.defineProperty(exports2, "__esModule", { value: true });
73354
73914
  exports2.handleVCUnverifiedSet = handleVCUnverifiedSet;
73355
73915
  exports2.handleVCUnverifiedClear = handleVCUnverifiedClear;
73356
- var state_js_1 = require_state3();
73916
+ var state_js_1 = require_state4();
73357
73917
  async function handleVCUnverifiedSet(params, ctx) {
73358
73918
  const { sessionId, classification, metrics } = params;
73359
73919
  const remindersState = (0, state_js_1.createRemindersState)(ctx.stateService);
@@ -73416,7 +73976,9 @@ var require_orchestrator = __commonJS({
73416
73976
  "use strict";
73417
73977
  Object.defineProperty(exports2, "__esModule", { value: true });
73418
73978
  exports2.ReminderOrchestrator = void 0;
73419
- var state_js_1 = require_state3();
73979
+ var core_1 = require_dist4();
73980
+ var events_js_1 = require_events2();
73981
+ var state_js_1 = require_state4();
73420
73982
  var types_js_1 = require_types2();
73421
73983
  var ReminderOrchestrator = class {
73422
73984
  deps;
@@ -73435,8 +73997,15 @@ var require_orchestrator = __commonJS({
73435
73997
  if (reminder.name === types_js_1.ReminderIds.PAUSE_AND_REFLECT) {
73436
73998
  try {
73437
73999
  const staging = this.deps.getStagingService(sessionId);
74000
+ const eventContext = { sessionId };
73438
74001
  for (const vcId of types_js_1.ALL_VC_REMINDER_IDS) {
73439
74002
  await staging.deleteReminder("Stop", vcId);
74003
+ (0, core_1.logEvent)(this.deps.logger, events_js_1.ReminderEvents.reminderUnstaged(eventContext, {
74004
+ reminderName: vcId,
74005
+ hookName: "Stop",
74006
+ reason: "pause_and_reflect_cascade",
74007
+ triggeredBy: "cascade_from_pause_and_reflect"
74008
+ }));
73440
74009
  }
73441
74010
  this.deps.logger.debug("Unstaged all VC reminders after P&R staged", { sessionId });
73442
74011
  } catch (err) {
@@ -73472,6 +74041,12 @@ var require_orchestrator = __commonJS({
73472
74041
  try {
73473
74042
  const staging = this.deps.getStagingService(sessionId);
73474
74043
  await staging.deleteReminder("PreToolUse", types_js_1.ReminderIds.PAUSE_AND_REFLECT);
74044
+ (0, core_1.logEvent)(this.deps.logger, events_js_1.ReminderEvents.reminderUnstaged({ sessionId }, {
74045
+ reminderName: types_js_1.ReminderIds.PAUSE_AND_REFLECT,
74046
+ hookName: "PreToolUse",
74047
+ reason: "vc_consumed_cascade",
74048
+ triggeredBy: "cascade_from_verify_completion"
74049
+ }));
73475
74050
  this.deps.logger.debug("Unstaged P&R after VC consumed", { sessionId });
73476
74051
  } catch (err) {
73477
74052
  this.deps.logger.warn("Failed to unstage P&R after VC consumed", {
@@ -73597,7 +74172,7 @@ var require_dist5 = __commonJS({
73597
74172
  Object.defineProperty(exports2, "ReminderOrchestrator", { enumerable: true, get: function() {
73598
74173
  return orchestrator_js_1.ReminderOrchestrator;
73599
74174
  } });
73600
- var state_js_1 = require_state3();
74175
+ var state_js_1 = require_state4();
73601
74176
  Object.defineProperty(exports2, "createRemindersState", { enumerable: true, get: function() {
73602
74177
  return state_js_1.createRemindersState;
73603
74178
  } });
@@ -73605,7 +74180,7 @@ var require_dist5 = __commonJS({
73605
74180
  });
73606
74181
 
73607
74182
  // ../feature-session-summary/dist/state.js
73608
- var require_state4 = __commonJS({
74183
+ var require_state5 = __commonJS({
73609
74184
  "../feature-session-summary/dist/state.js"(exports2) {
73610
74185
  "use strict";
73611
74186
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -73710,7 +74285,7 @@ var require_persona_selection = __commonJS({
73710
74285
  exports2.selectPersonaForSession = selectPersonaForSession;
73711
74286
  exports2.ensurePersonaForSession = ensurePersonaForSession;
73712
74287
  var core_1 = require_dist4();
73713
- var state_js_1 = require_state4();
74288
+ var state_js_1 = require_state5();
73714
74289
  var types_js_1 = require_types3();
73715
74290
  function parsePersonaList(list) {
73716
74291
  if (!list || !list.trim()) {
@@ -73793,11 +74368,11 @@ var require_persona_selection = __commonJS({
73793
74368
  };
73794
74369
  const summaryState2 = (0, state_js_1.createSessionSummaryState)(ctx.stateService);
73795
74370
  await summaryState2.sessionPersona.write(sessionId, personaState2);
73796
- ctx.logger.info("Using pinned persona for session", {
73797
- sessionId,
74371
+ (0, core_1.logEvent)(ctx.logger, core_1.LogEvents.personaSelected({ sessionId }, {
73798
74372
  personaId: pinned.id,
73799
- personaName: pinned.display_name
73800
- });
74373
+ selectionMethod: "pinned",
74374
+ poolSize: 1
74375
+ }));
73801
74376
  return pinned.id;
73802
74377
  }
73803
74378
  ctx.logger.warn("Pinned persona not found, falling back to random selection", {
@@ -73807,13 +74382,18 @@ var require_persona_selection = __commonJS({
73807
74382
  });
73808
74383
  }
73809
74384
  const persistThroughClear = personaConfig.persistThroughClear ?? true;
73810
- ctx.logger.debug("Persona clear handoff check", {
74385
+ ctx.logger.info("[persona-lifecycle] ClearHandoff: checking clear cache", {
74386
+ sessionId,
73811
74387
  persistThroughClear,
73812
74388
  startType: options?.startType,
73813
74389
  hasClearCache: !!ctx.personaClearCache
73814
74390
  });
73815
74391
  if (persistThroughClear && options?.startType === "clear" && ctx.personaClearCache) {
73816
74392
  const cachedPersonaId = ctx.personaClearCache.consume();
74393
+ ctx.logger.info("[persona-lifecycle] ClearHandoff: consumed cache", {
74394
+ sessionId,
74395
+ cachedPersonaId: cachedPersonaId ?? null
74396
+ });
73817
74397
  if (cachedPersonaId) {
73818
74398
  const cachedPersona = allPersonas.get(cachedPersonaId);
73819
74399
  if (cachedPersona) {
@@ -73824,11 +74404,11 @@ var require_persona_selection = __commonJS({
73824
74404
  };
73825
74405
  const summaryState2 = (0, state_js_1.createSessionSummaryState)(ctx.stateService);
73826
74406
  await summaryState2.sessionPersona.write(sessionId, personaState2);
73827
- ctx.logger.info("Preserved persona through clear", {
73828
- sessionId,
74407
+ (0, core_1.logEvent)(ctx.logger, core_1.LogEvents.personaSelected({ sessionId }, {
73829
74408
  personaId: cachedPersona.id,
73830
- personaName: cachedPersona.display_name
73831
- });
74409
+ selectionMethod: "handoff",
74410
+ poolSize: 1
74411
+ }));
73832
74412
  return cachedPersona.id;
73833
74413
  } else {
73834
74414
  ctx.logger.warn("Cached persona from clear not found in available personas, falling back to selection", {
@@ -73866,12 +74446,11 @@ var require_persona_selection = __commonJS({
73866
74446
  };
73867
74447
  const summaryState = (0, state_js_1.createSessionSummaryState)(ctx.stateService);
73868
74448
  await summaryState.sessionPersona.write(sessionId, personaState);
73869
- ctx.logger.info("Selected persona for session", {
73870
- sessionId,
74449
+ (0, core_1.logEvent)(ctx.logger, core_1.LogEvents.personaSelected({ sessionId }, {
73871
74450
  personaId: selected.id,
73872
- personaName: selected.display_name,
74451
+ selectionMethod: "random",
73873
74452
  poolSize: eligiblePersonas.length
73874
- });
74453
+ }));
73875
74454
  return selected.id;
73876
74455
  }
73877
74456
  async function ensurePersonaForSession(sessionId, ctx) {
@@ -73901,7 +74480,7 @@ var require_create_first_summary = __commonJS({
73901
74480
  Object.defineProperty(exports2, "__esModule", { value: true });
73902
74481
  exports2.createFirstSessionSummary = createFirstSessionSummary;
73903
74482
  var types_1 = require_dist();
73904
- var state_js_1 = require_state4();
74483
+ var state_js_1 = require_state5();
73905
74484
  var persona_selection_js_1 = require_persona_selection();
73906
74485
  var types_js_1 = require_types3();
73907
74486
  async function createFirstSessionSummary(event, ctx) {
@@ -73934,15 +74513,12 @@ var require_events3 = __commonJS({
73934
74513
  "../feature-session-summary/dist/events.js"(exports2) {
73935
74514
  "use strict";
73936
74515
  Object.defineProperty(exports2, "__esModule", { value: true });
73937
- exports2.SessionSummaryEvents = void 0;
74516
+ exports2.DecisionEvents = exports2.SessionSummaryEvents = void 0;
73938
74517
  exports2.SessionSummaryEvents = {
73939
- /**
73940
- * Create a SummaryUpdated event (logged when session summary is recalculated).
73941
- * @see docs/design/FEATURE-SESSION-SUMMARY.md §3.4
73942
- */
73943
- summaryUpdated(context, state, metadata, reason) {
74518
+ /** Emitted when summary generation begins. */
74519
+ summaryStart(context, payload) {
73944
74520
  return {
73945
- type: "SummaryUpdated",
74521
+ type: "session-summary:start",
73946
74522
  time: Date.now(),
73947
74523
  source: "daemon",
73948
74524
  context: {
@@ -73952,11 +74528,87 @@ var require_events3 = __commonJS({
73952
74528
  hook: context.hook,
73953
74529
  taskId: context.taskId
73954
74530
  },
73955
- payload: {
73956
- state,
73957
- metadata,
73958
- reason
73959
- }
74531
+ payload
74532
+ };
74533
+ },
74534
+ /** Emitted when summary generation completes. */
74535
+ summaryFinish(context, payload) {
74536
+ return {
74537
+ type: "session-summary:finish",
74538
+ time: Date.now(),
74539
+ source: "daemon",
74540
+ context: {
74541
+ sessionId: context.sessionId,
74542
+ correlationId: context.correlationId,
74543
+ traceId: context.traceId,
74544
+ hook: context.hook,
74545
+ taskId: context.taskId
74546
+ },
74547
+ payload
74548
+ };
74549
+ },
74550
+ /** Emitted when session title changes. */
74551
+ titleChanged(context, payload) {
74552
+ return {
74553
+ type: "session-title:changed",
74554
+ time: Date.now(),
74555
+ source: "daemon",
74556
+ context: {
74557
+ sessionId: context.sessionId,
74558
+ correlationId: context.correlationId,
74559
+ traceId: context.traceId,
74560
+ hook: context.hook,
74561
+ taskId: context.taskId
74562
+ },
74563
+ payload
74564
+ };
74565
+ },
74566
+ /** Emitted when latest intent changes. */
74567
+ intentChanged(context, payload) {
74568
+ return {
74569
+ type: "intent:changed",
74570
+ time: Date.now(),
74571
+ source: "daemon",
74572
+ context: {
74573
+ sessionId: context.sessionId,
74574
+ correlationId: context.correlationId,
74575
+ traceId: context.traceId,
74576
+ hook: context.hook,
74577
+ taskId: context.taskId
74578
+ },
74579
+ payload
74580
+ };
74581
+ },
74582
+ /** Emitted when snarky message generation begins. */
74583
+ snarkyMessageStart(context, payload) {
74584
+ return {
74585
+ type: "snarky-message:start",
74586
+ time: Date.now(),
74587
+ source: "daemon",
74588
+ context: {
74589
+ sessionId: context.sessionId,
74590
+ correlationId: context.correlationId,
74591
+ traceId: context.traceId,
74592
+ hook: context.hook,
74593
+ taskId: context.taskId
74594
+ },
74595
+ payload
74596
+ };
74597
+ },
74598
+ /** Emitted when snarky message generation completes. */
74599
+ snarkyMessageFinish(context, payload) {
74600
+ return {
74601
+ type: "snarky-message:finish",
74602
+ time: Date.now(),
74603
+ source: "daemon",
74604
+ context: {
74605
+ sessionId: context.sessionId,
74606
+ correlationId: context.correlationId,
74607
+ traceId: context.traceId,
74608
+ hook: context.hook,
74609
+ taskId: context.taskId
74610
+ },
74611
+ payload
73960
74612
  };
73961
74613
  },
73962
74614
  /**
@@ -73965,7 +74617,7 @@ var require_events3 = __commonJS({
73965
74617
  */
73966
74618
  summarySkipped(context, metadata) {
73967
74619
  return {
73968
- type: "SummarySkipped",
74620
+ type: "session-summary:skipped",
73969
74621
  time: Date.now(),
73970
74622
  source: "daemon",
73971
74623
  context: {
@@ -73976,12 +74628,31 @@ var require_events3 = __commonJS({
73976
74628
  taskId: context.taskId
73977
74629
  },
73978
74630
  payload: {
73979
- metadata,
74631
+ countdown: metadata.countdown,
74632
+ countdown_threshold: metadata.countdown_threshold,
73980
74633
  reason: "countdown_active"
73981
74634
  }
73982
74635
  };
73983
74636
  }
73984
74637
  };
74638
+ exports2.DecisionEvents = {
74639
+ /** Emitted when an LLM decision is recorded. */
74640
+ decisionRecorded(context, payload) {
74641
+ return {
74642
+ type: "decision:recorded",
74643
+ time: Date.now(),
74644
+ source: "daemon",
74645
+ context: {
74646
+ sessionId: context.sessionId,
74647
+ correlationId: context.correlationId,
74648
+ traceId: context.traceId,
74649
+ hook: context.hook,
74650
+ taskId: context.taskId
74651
+ },
74652
+ payload
74653
+ };
74654
+ }
74655
+ };
73985
74656
  }
73986
74657
  });
73987
74658
 
@@ -74001,7 +74672,7 @@ var require_persona_utils = __commonJS({
74001
74672
  exports2.mergePersonaConfig = mergePersonaConfig;
74002
74673
  exports2.getEffectiveProfile = getEffectiveProfile;
74003
74674
  var core_1 = require_dist4();
74004
- var state_js_1 = require_state4();
74675
+ var state_js_1 = require_state5();
74005
74676
  var types_js_1 = require_types3();
74006
74677
  var DEFAULT_PERSONA_SITUATION = "You are watching over the shoulder of a software developer as they work.";
74007
74678
  function buildUserProfileContext(profile) {
@@ -74143,7 +74814,7 @@ var require_update_summary = __commonJS({
74143
74814
  var events_js_1 = require_events3();
74144
74815
  var zod_1 = require_zod();
74145
74816
  var types_js_1 = require_types3();
74146
- var state_js_1 = require_state4();
74817
+ var state_js_1 = require_state5();
74147
74818
  var persona_utils_js_1 = require_persona_utils();
74148
74819
  var persona_selection_js_1 = require_persona_selection();
74149
74820
  var PROMPT_FILE = "prompts/session-summary.prompt.txt";
@@ -74196,47 +74867,47 @@ var require_update_summary = __commonJS({
74196
74867
  await (0, persona_selection_js_1.ensurePersonaForSession)(sessionId, ctx);
74197
74868
  const metrics = ctx.transcript.getMetrics();
74198
74869
  if (metrics.turnCount === 0) {
74199
- ctx.logger.info("LLM call: session-summary analysis", {
74200
- sessionId,
74870
+ (0, core_1.logEvent)(ctx.logger, events_js_1.DecisionEvents.decisionRecorded(event.context, {
74201
74871
  decision: "skipped",
74202
- reason: "BulkProcessingComplete with no user turns (turnCount=0)"
74203
- });
74872
+ reason: "BulkProcessingComplete with no user turns (turnCount=0)",
74873
+ detail: "session-summary analysis"
74874
+ }));
74204
74875
  return;
74205
74876
  }
74206
- ctx.logger.info("LLM call: session-summary analysis", {
74207
- sessionId,
74877
+ (0, core_1.logEvent)(ctx.logger, events_js_1.DecisionEvents.decisionRecorded(event.context, {
74208
74878
  decision: "calling",
74209
- reason: "BulkProcessingComplete - analyzing full transcript"
74210
- });
74879
+ reason: "BulkProcessingComplete - analyzing full transcript",
74880
+ detail: "session-summary analysis"
74881
+ }));
74211
74882
  const countdown2 = await loadCountdownState(summaryState, sessionId);
74212
74883
  void performAnalysis(event, ctx, summaryState, countdown2, "user_prompt_forced");
74213
74884
  return;
74214
74885
  }
74215
74886
  const countdown = await loadCountdownState(summaryState, sessionId);
74216
74887
  if (isUserPrompt) {
74217
- ctx.logger.info("LLM call: session-summary analysis", {
74218
- sessionId,
74888
+ (0, core_1.logEvent)(ctx.logger, events_js_1.DecisionEvents.decisionRecorded(event.context, {
74219
74889
  decision: "calling",
74220
- reason: "UserPrompt event forces immediate analysis"
74221
- });
74890
+ reason: "UserPrompt event forces immediate analysis",
74891
+ detail: "session-summary analysis"
74892
+ }));
74222
74893
  void performAnalysis(event, ctx, summaryState, countdown, "user_prompt_forced");
74223
74894
  return;
74224
74895
  }
74225
74896
  if (countdown.countdown > 0) {
74226
- ctx.logger.info("LLM call: session-summary analysis", {
74227
- sessionId,
74897
+ (0, core_1.logEvent)(ctx.logger, events_js_1.DecisionEvents.decisionRecorded(event.context, {
74228
74898
  decision: "skipped",
74229
- reason: `countdown not reached (${countdown.countdown} tool results remaining)`
74230
- });
74899
+ reason: `countdown not reached (${countdown.countdown} tool results remaining)`,
74900
+ detail: "session-summary analysis"
74901
+ }));
74231
74902
  countdown.countdown--;
74232
74903
  await saveCountdownState(summaryState, sessionId, countdown);
74233
74904
  return;
74234
74905
  }
74235
- ctx.logger.info("LLM call: session-summary analysis", {
74236
- sessionId,
74906
+ (0, core_1.logEvent)(ctx.logger, events_js_1.DecisionEvents.decisionRecorded(event.context, {
74237
74907
  decision: "calling",
74238
- reason: "countdown reached zero after ToolResult"
74239
- });
74908
+ reason: "countdown reached zero after ToolResult",
74909
+ detail: "session-summary analysis"
74910
+ }));
74240
74911
  void performAnalysis(event, ctx, summaryState, countdown, "countdown_reached");
74241
74912
  }
74242
74913
  async function loadCountdownState(summaryState, sessionId) {
@@ -74270,6 +74941,10 @@ var require_update_summary = __commonJS({
74270
74941
  const { sessionId } = event.context;
74271
74942
  try {
74272
74943
  const startTime = Date.now();
74944
+ (0, core_1.logEvent)(ctx.logger, events_js_1.SessionSummaryEvents.summaryStart(event.context, {
74945
+ reason,
74946
+ countdown: countdown.countdown
74947
+ }));
74273
74948
  const featureConfig = ctx.config.getFeature("session-summary");
74274
74949
  const config = { ...types_js_1.DEFAULT_SESSION_SUMMARY_CONFIG, ...featureConfig.settings };
74275
74950
  const currentSummary = await loadCurrentSummary(summaryState, sessionId);
@@ -74373,19 +75048,28 @@ var require_update_summary = __commonJS({
74373
75048
  if (sideEffects.length > 0) {
74374
75049
  await Promise.all(sideEffects);
74375
75050
  }
74376
- (0, core_1.logEvent)(ctx.logger, events_js_1.SessionSummaryEvents.summaryUpdated(event.context, {
75051
+ (0, core_1.logEvent)(ctx.logger, events_js_1.SessionSummaryEvents.summaryFinish(event.context, {
74377
75052
  session_title: updatedSummary.session_title,
74378
75053
  session_title_confidence: updatedSummary.session_title_confidence,
74379
75054
  latest_intent: updatedSummary.latest_intent,
74380
- latest_intent_confidence: updatedSummary.latest_intent_confidence
74381
- }, {
74382
- countdown_reset_to: newCountdown,
74383
- tokens_used: tokensUsed,
75055
+ latest_intent_confidence: updatedSummary.latest_intent_confidence,
74384
75056
  processing_time_ms: updatedSummary.stats?.processing_time_ms ?? 0,
74385
- pivot_detected: updatedSummary.pivot_detected ?? false,
74386
- old_title: currentSummary?.session_title,
74387
- old_intent: currentSummary?.latest_intent
74388
- }, reason));
75057
+ pivot_detected: updatedSummary.pivot_detected ?? false
75058
+ }));
75059
+ if (currentSummary && updatedSummary.session_title !== currentSummary.session_title) {
75060
+ (0, core_1.logEvent)(ctx.logger, events_js_1.SessionSummaryEvents.titleChanged(event.context, {
75061
+ previousValue: currentSummary.session_title,
75062
+ newValue: updatedSummary.session_title,
75063
+ confidence: updatedSummary.session_title_confidence
75064
+ }));
75065
+ }
75066
+ if (currentSummary && updatedSummary.latest_intent !== currentSummary.latest_intent) {
75067
+ (0, core_1.logEvent)(ctx.logger, events_js_1.SessionSummaryEvents.intentChanged(event.context, {
75068
+ previousValue: currentSummary.latest_intent,
75069
+ newValue: updatedSummary.latest_intent,
75070
+ confidence: updatedSummary.latest_intent_confidence
75071
+ }));
75072
+ }
74389
75073
  ctx.logger.info("Updated session summary", {
74390
75074
  sessionId,
74391
75075
  reason,
@@ -74451,6 +75135,7 @@ var require_update_summary = __commonJS({
74451
75135
  return;
74452
75136
  }
74453
75137
  const provider = ctx.profileFactory.createForProfile(profileResult.profileId, llmConfig.fallbackProfile);
75138
+ (0, core_1.logEvent)(ctx.logger, events_js_1.SessionSummaryEvents.snarkyMessageStart({ sessionId }, { sessionId }));
74454
75139
  try {
74455
75140
  const response = await provider.complete({
74456
75141
  messages: [{ role: "user", content: prompt }]
@@ -74461,6 +75146,7 @@ var require_update_summary = __commonJS({
74461
75146
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
74462
75147
  };
74463
75148
  await summaryState.snarkyMessage.write(sessionId, snarkyState);
75149
+ (0, core_1.logEvent)(ctx.logger, events_js_1.SessionSummaryEvents.snarkyMessageFinish({ sessionId }, { generatedMessage: snarkyMessage }));
74464
75150
  ctx.logger.debug("Generated snarky message", {
74465
75151
  sessionId,
74466
75152
  personaId: persona?.id ?? "none",
@@ -74569,8 +75255,10 @@ var require_on_demand_generation = __commonJS({
74569
75255
  exports2.generateSnarkyMessageOnDemand = generateSnarkyMessageOnDemand;
74570
75256
  exports2.generateResumeMessageOnDemand = generateResumeMessageOnDemand;
74571
75257
  var types_js_1 = require_types3();
74572
- var state_js_1 = require_state4();
75258
+ var state_js_1 = require_state5();
74573
75259
  var core_1 = require_dist4();
75260
+ var core_2 = require_dist4();
75261
+ var events_js_1 = require_events3();
74574
75262
  var update_summary_js_1 = require_update_summary();
74575
75263
  var persona_utils_js_1 = require_persona_utils();
74576
75264
  var SNARKY_PROMPT_FILE = "prompts/snarky-message.prompt.txt";
@@ -74647,6 +75335,7 @@ var require_on_demand_generation = __commonJS({
74647
75335
  return { success: false, error: profileResult.errorMessage };
74648
75336
  }
74649
75337
  const provider = ctx.profileFactory.createForProfile(profileResult.profileId, llmConfig.fallbackProfile);
75338
+ (0, core_2.logEvent)(ctx.logger, events_js_1.SessionSummaryEvents.snarkyMessageStart({ sessionId }, { sessionId }));
74650
75339
  try {
74651
75340
  const response = await provider.complete({
74652
75341
  messages: [{ role: "user", content: prompt }]
@@ -74657,6 +75346,7 @@ var require_on_demand_generation = __commonJS({
74657
75346
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
74658
75347
  };
74659
75348
  await summaryState.snarkyMessage.write(sessionId, snarkyState);
75349
+ (0, core_2.logEvent)(ctx.logger, events_js_1.SessionSummaryEvents.snarkyMessageFinish({ sessionId }, { generatedMessage: snarkyMessage }));
74660
75350
  ctx.logger.info("Generated snarky message on-demand", {
74661
75351
  sessionId,
74662
75352
  personaId: persona?.id ?? "none"
@@ -74863,7 +75553,7 @@ var require_dist6 = __commonJS({
74863
75553
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
74864
75554
  };
74865
75555
  Object.defineProperty(exports2, "__esModule", { value: true });
74866
- exports2.SessionSummaryEvents = exports2.manifest = void 0;
75556
+ exports2.DecisionEvents = exports2.SessionSummaryEvents = exports2.manifest = void 0;
74867
75557
  exports2.register = register;
74868
75558
  var index_js_1 = require_handlers();
74869
75559
  exports2.manifest = {
@@ -74880,11 +75570,14 @@ var require_dist6 = __commonJS({
74880
75570
  exports2.default = feature;
74881
75571
  __exportStar(require_types3(), exports2);
74882
75572
  __exportStar(require_handlers(), exports2);
74883
- __exportStar(require_state4(), exports2);
75573
+ __exportStar(require_state5(), exports2);
74884
75574
  var events_js_1 = require_events3();
74885
75575
  Object.defineProperty(exports2, "SessionSummaryEvents", { enumerable: true, get: function() {
74886
75576
  return events_js_1.SessionSummaryEvents;
74887
75577
  } });
75578
+ Object.defineProperty(exports2, "DecisionEvents", { enumerable: true, get: function() {
75579
+ return events_js_1.DecisionEvents;
75580
+ } });
74888
75581
  }
74889
75582
  });
74890
75583
 
@@ -75166,7 +75859,11 @@ var require_session_persona_watcher = __commonJS({
75166
75859
  }
75167
75860
  const timer = setTimeout(() => {
75168
75861
  this.debounceTimers.delete(filePath);
75169
- this.logger.info("Session persona changed", { sessionId, eventType });
75862
+ this.logger.info("[persona-lifecycle] PersonaWatcher: debounce fired, dispatching change event", {
75863
+ sessionId,
75864
+ eventType,
75865
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
75866
+ });
75170
75867
  try {
75171
75868
  this.onChange({
75172
75869
  sessionId,
@@ -76366,7 +77063,7 @@ var require_daemon = __commonJS({
76366
77063
  var VERSION = require_package3().version;
76367
77064
  var IDLE_CHECK_INTERVAL_MS = 30 * 1e3;
76368
77065
  var HEARTBEAT_INTERVAL_MS = 5 * 1e3;
76369
- var Daemon = class {
77066
+ var Daemon = class _Daemon {
76370
77067
  projectDir;
76371
77068
  configService;
76372
77069
  logger;
@@ -76404,6 +77101,8 @@ var require_daemon = __commonJS({
76404
77101
  idleCheckInterval = null;
76405
77102
  heartbeatInterval = null;
76406
77103
  evictionTimer = null;
77104
+ registryHeartbeatInterval = null;
77105
+ registryService;
76407
77106
  startTime = Date.now();
76408
77107
  /** Cache persona for handoff on clear. */
76409
77108
  cachePersonaForClear(personaId) {
@@ -76454,7 +77153,7 @@ var require_daemon = __commonJS({
76454
77153
  });
76455
77154
  this.logger = (0, core_1.createHookableLogger)(this.logManager.getLogger(), {
76456
77155
  levels: ["warn", "error", "fatal"],
76457
- hook: (level, _msg, meta) => {
77156
+ hook: (level, msg, meta) => {
76458
77157
  const sessionId = meta?.context?.sessionId ?? meta?.sessionId;
76459
77158
  if (sessionId) {
76460
77159
  const counters = this.logCounters.get(sessionId);
@@ -76470,6 +77169,23 @@ var require_daemon = __commonJS({
76470
77169
  else
76471
77170
  this.globalLogCounters.errors++;
76472
77171
  }
77172
+ if (level === "error" || level === "fatal") {
77173
+ const errorObj = meta?.error ?? meta?.err;
77174
+ const errorMessage = errorObj?.message ?? msg;
77175
+ const errorStack = errorObj?.stack;
77176
+ const metaContext = meta?.context ?? {};
77177
+ const event = core_1.LogEvents.daemonErrorOccurred({
77178
+ sessionId: sessionId ?? "",
77179
+ correlationId: metaContext.correlationId,
77180
+ traceId: metaContext.traceId,
77181
+ hook: metaContext.hook,
77182
+ taskId: metaContext.taskId
77183
+ }, {
77184
+ errorMessage,
77185
+ errorStack
77186
+ });
77187
+ (0, core_1.logEvent)(this.logManager.getLogger(), event);
77188
+ }
76473
77189
  }
76474
77190
  });
76475
77191
  this.stateService = new core_1.StateService(projectDir2, {
@@ -76484,6 +77200,8 @@ var require_daemon = __commonJS({
76484
77200
  logger: this.logger,
76485
77201
  config: () => this.configService.getAll()
76486
77202
  });
77203
+ const registryRoot = path_1.default.join((0, os_1.homedir)(), ".sidekick", "projects");
77204
+ this.registryService = new core_1.ProjectRegistryService(registryRoot);
76487
77205
  this.stagingStateService = new core_1.StateService(projectDir2, {
76488
77206
  cache: false,
76489
77207
  logger: this.logger,
@@ -76532,6 +77250,7 @@ var require_daemon = __commonJS({
76532
77250
  async start() {
76533
77251
  try {
76534
77252
  this.logger.info("Daemon starting", { projectDir: this.projectDir, pid: process.pid });
77253
+ (0, core_1.logEvent)(this.logger, core_1.LogEvents.daemonStarting({ projectDir: this.projectDir, pid: process.pid }));
76535
77254
  this.setupErrorHandlers();
76536
77255
  await this.writePid();
76537
77256
  await this.writeToken();
@@ -76543,12 +77262,22 @@ var require_daemon = __commonJS({
76543
77262
  }
76544
77263
  (0, task_handlers_js_1.registerStandardTaskHandlers)(this.taskEngine, this.stateService, this.projectDir, this.logger, this.configService.getAll(), this.assetResolver);
76545
77264
  await this.ipcServer.start();
77265
+ (0, core_1.logEvent)(this.logger, core_1.LogEvents.ipcServerStarted({ socketPath: (0, core_1.getSocketPath)(this.projectDir) }));
76546
77266
  this.configWatcher.start();
77267
+ const watchedFiles = [
77268
+ this.stateService.rootDir(),
77269
+ path_1.default.join((0, os_1.homedir)(), ".sidekick"),
77270
+ ...this.configService.core.development.enabled ? [(0, core_1.getDefaultAssetsDir)()] : []
77271
+ ];
77272
+ (0, core_1.logEvent)(this.logger, core_1.LogEvents.configWatcherStarted({ projectDir: this.projectDir, watchedFiles }));
76547
77273
  this.personaWatcher.start();
76548
77274
  this.startIdleCheck();
76549
77275
  this.startHeartbeat();
76550
77276
  this.startEvictionTimer();
77277
+ await this.registerProject();
77278
+ this.startRegistryHeartbeat();
76551
77279
  this.logger.info("Daemon started successfully");
77280
+ (0, core_1.logEvent)(this.logger, core_1.LogEvents.daemonStarted({ startupDurationMs: Date.now() - this.startTime }));
76552
77281
  await (0, core_1.updateDaemonHealth)(this.projectDir, "healthy", this.logger);
76553
77282
  } catch (err) {
76554
77283
  this.logger.fatal("Failed to start daemon", { error: err });
@@ -76561,6 +77290,7 @@ var require_daemon = __commonJS({
76561
77290
  this.stopIdleCheck();
76562
77291
  this.stopHeartbeat();
76563
77292
  this.stopEvictionTimer();
77293
+ this.stopRegistryHeartbeat();
76564
77294
  this.configWatcher.stop();
76565
77295
  this.personaWatcher.stop();
76566
77296
  try {
@@ -76653,9 +77383,10 @@ var require_daemon = __commonJS({
76653
77383
  * On 'unlink' (persona cleared), skips regeneration since there's no persona to voice.
76654
77384
  */
76655
77385
  handlePersonaChange(event) {
76656
- this.logger.info("Session persona changed via file", {
77386
+ this.logger.info("[persona-lifecycle] PersonaWatcher: file change received by daemon handler", {
76657
77387
  sessionId: event.sessionId,
76658
- eventType: event.eventType
77388
+ eventType: event.eventType,
77389
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
76659
77390
  });
76660
77391
  const personaPath = this.stateService.sessionStatePath(event.sessionId, "session-persona.json");
76661
77392
  this.stateService.invalidateCache(personaPath);
@@ -76889,13 +77620,29 @@ var require_daemon = __commonJS({
76889
77620
  const sessionId = event.context?.sessionId;
76890
77621
  if (sessionId) {
76891
77622
  const payload = event.payload;
76892
- log.debug("handleSessionEnd entered", { sessionId, endReason: payload.endReason });
77623
+ log.info("[persona-lifecycle] ClearHandoff: handleSessionEnd entered", {
77624
+ sessionId,
77625
+ endReason: payload.endReason
77626
+ });
76893
77627
  if (payload.endReason === "clear") {
76894
77628
  try {
76895
77629
  const summaryState = (0, feature_session_summary_1.createSessionSummaryState)(this.stateService);
77630
+ const personaPath = this.stateService.sessionStatePath(sessionId, "session-persona.json");
77631
+ this.stateService.invalidateCache(personaPath);
77632
+ log.info("[persona-lifecycle] ClearHandoff: invalidated StateService cache before persona read", {
77633
+ sessionId,
77634
+ personaPath
77635
+ });
76896
77636
  const result = await summaryState.sessionPersona.read(sessionId);
77637
+ log.info("[persona-lifecycle] ClearHandoff: read persona from disk", {
77638
+ sessionId,
77639
+ personaId: result.data?.persona_id ?? null
77640
+ });
76897
77641
  if (result.data?.persona_id) {
76898
- log.debug("Caching persona for clear handoff", { personaId: result.data.persona_id });
77642
+ log.info("[persona-lifecycle] ClearHandoff: caching persona for clear handoff", {
77643
+ sessionId,
77644
+ personaId: result.data.persona_id
77645
+ });
76899
77646
  this.cachePersonaForClear(result.data.persona_id);
76900
77647
  }
76901
77648
  } catch (err) {
@@ -76904,7 +77651,10 @@ var require_daemon = __commonJS({
76904
77651
  });
76905
77652
  }
76906
77653
  } else {
76907
- log.debug("SessionEnd reason is not clear, skipping persona cache", { endReason: payload.endReason });
77654
+ log.info("[persona-lifecycle] ClearHandoff: SessionEnd reason is not clear, skipping persona cache", {
77655
+ sessionId,
77656
+ endReason: payload.endReason
77657
+ });
76908
77658
  }
76909
77659
  const instrumentedProvider = this.instrumentedProviders.get(sessionId);
76910
77660
  if (instrumentedProvider) {
@@ -77493,6 +78243,7 @@ var require_daemon = __commonJS({
77493
78243
  }, EVICTION_INTERVAL_MS);
77494
78244
  this.evictionTimer.unref();
77495
78245
  this.logger.info("Session eviction timer started", { intervalMs: EVICTION_INTERVAL_MS });
78246
+ (0, core_1.logEvent)(this.logger, core_1.LogEvents.sessionEvictionStarted({ intervalMs: EVICTION_INTERVAL_MS }));
77496
78247
  }
77497
78248
  stopEvictionTimer() {
77498
78249
  if (this.evictionTimer) {
@@ -77500,6 +78251,34 @@ var require_daemon = __commonJS({
77500
78251
  this.evictionTimer = null;
77501
78252
  }
77502
78253
  }
78254
+ // --- Project Registry ---
78255
+ static REGISTRY_HEARTBEAT_INTERVAL_MS = 60 * 60 * 1e3;
78256
+ // 1 hour
78257
+ async registerProject() {
78258
+ try {
78259
+ await this.registryService.register(this.projectDir);
78260
+ this.logger.info("Project registered for UI discovery", { projectDir: this.projectDir });
78261
+ } catch (err) {
78262
+ this.logger.warn("Failed to register project", {
78263
+ error: err instanceof Error ? err.message : String(err)
78264
+ });
78265
+ }
78266
+ }
78267
+ startRegistryHeartbeat() {
78268
+ this.registryHeartbeatInterval = setInterval(() => {
78269
+ void this.registerProject();
78270
+ }, _Daemon.REGISTRY_HEARTBEAT_INTERVAL_MS);
78271
+ this.registryHeartbeatInterval.unref();
78272
+ this.logger.debug("Registry heartbeat started", {
78273
+ intervalMs: _Daemon.REGISTRY_HEARTBEAT_INTERVAL_MS
78274
+ });
78275
+ }
78276
+ stopRegistryHeartbeat() {
78277
+ if (this.registryHeartbeatInterval) {
78278
+ clearInterval(this.registryHeartbeatInterval);
78279
+ this.registryHeartbeatInterval = null;
78280
+ }
78281
+ }
77503
78282
  /**
77504
78283
  * Write current daemon status to state file.
77505
78284
  * Per design/DAEMON.md §4.6: Includes timestamp, pid, uptime, memory, queue stats.