@askexenow/exe-os 0.9.62 → 0.9.63

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.
@@ -313,6 +313,15 @@ var init_memory = __esm({
313
313
  });
314
314
 
315
315
  // src/lib/daemon-protocol.ts
316
+ var daemon_protocol_exports = {};
317
+ __export(daemon_protocol_exports, {
318
+ deserializeArgs: () => deserializeArgs,
319
+ deserializeResultSet: () => deserializeResultSet,
320
+ deserializeValue: () => deserializeValue,
321
+ serializeArgs: () => serializeArgs,
322
+ serializeResultSet: () => serializeResultSet,
323
+ serializeValue: () => serializeValue
324
+ });
316
325
  function serializeValue(v) {
317
326
  if (v === null || v === void 0) return null;
318
327
  if (typeof v === "bigint") return Number(v);
@@ -337,6 +346,9 @@ function deserializeValue(v) {
337
346
  }
338
347
  return v;
339
348
  }
349
+ function serializeArgs(args) {
350
+ return args.map(serializeValue);
351
+ }
340
352
  function deserializeArgs(args) {
341
353
  return args.map(deserializeValue);
342
354
  }
@@ -20991,6 +21003,218 @@ var init_conflict_detector = __esm({
20991
21003
  }
20992
21004
  });
20993
21005
 
21006
+ // src/adapters/runtime-hook-manifest.ts
21007
+ function manifestEntryForCommand(command) {
21008
+ return EXE_HOOK_MANIFEST.find((entry) => command.includes(entry.commandMarker));
21009
+ }
21010
+ var EXE_HOOKS, EXE_HOOK_MANIFEST, LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS;
21011
+ var init_runtime_hook_manifest = __esm({
21012
+ "src/adapters/runtime-hook-manifest.ts"() {
21013
+ "use strict";
21014
+ EXE_HOOKS = {
21015
+ postToolCombined: "dist/hooks/post-tool-combined.js",
21016
+ sessionStart: "dist/hooks/session-start.js",
21017
+ promptSubmit: "dist/hooks/prompt-submit.js",
21018
+ heartbeat: "dist/hooks/exe-heartbeat-hook.js",
21019
+ stop: "dist/hooks/stop.js",
21020
+ preToolUse: "dist/hooks/pre-tool-use.js",
21021
+ subagentStop: "dist/hooks/subagent-stop.js",
21022
+ preCompact: "dist/hooks/pre-compact.js",
21023
+ postCompact: "dist/hooks/post-compact.js",
21024
+ sessionEnd: "dist/hooks/session-end.js",
21025
+ notification: "dist/hooks/notification.js",
21026
+ instructionsLoaded: "dist/hooks/instructions-loaded.js"
21027
+ };
21028
+ EXE_HOOK_MANIFEST = [
21029
+ {
21030
+ key: "postToolCombined",
21031
+ event: "PostToolUse",
21032
+ commandMarker: EXE_HOOKS.postToolCombined,
21033
+ owner: "exe-os",
21034
+ purpose: "Single PostToolUse entrypoint for ingestion, error recall, summaries, and bug detection.",
21035
+ runtimes: ["claude", "codex", "opencode"],
21036
+ checkpointRole: "none"
21037
+ },
21038
+ {
21039
+ key: "sessionStart",
21040
+ event: "SessionStart",
21041
+ commandMarker: EXE_HOOKS.sessionStart,
21042
+ owner: "exe-os",
21043
+ purpose: "Loads agent identity, procedures, and boot context.",
21044
+ runtimes: ["claude", "codex", "opencode"],
21045
+ checkpointRole: "none"
21046
+ },
21047
+ {
21048
+ key: "promptSubmit",
21049
+ event: "UserPromptSubmit",
21050
+ commandMarker: EXE_HOOKS.promptSubmit,
21051
+ owner: "exe-os",
21052
+ purpose: "Injects current tasks, pending reviews, and local context before each prompt.",
21053
+ runtimes: ["claude", "codex", "opencode"],
21054
+ checkpointRole: "none"
21055
+ },
21056
+ {
21057
+ key: "heartbeat",
21058
+ event: "UserPromptSubmit",
21059
+ commandMarker: EXE_HOOKS.heartbeat,
21060
+ owner: "exe-os",
21061
+ purpose: "Lightweight heartbeat/status sidecar for Claude Code sessions.",
21062
+ runtimes: ["claude"],
21063
+ checkpointRole: "none"
21064
+ },
21065
+ {
21066
+ key: "stop",
21067
+ event: "Stop",
21068
+ commandMarker: EXE_HOOKS.stop,
21069
+ owner: "exe-os",
21070
+ purpose: "Finalizes task state, capacity signals, and emergency checkpointing.",
21071
+ runtimes: ["claude", "codex", "opencode"],
21072
+ checkpointRole: "capacity_checkpoint"
21073
+ },
21074
+ {
21075
+ key: "preToolUse",
21076
+ event: "PreToolUse",
21077
+ commandMarker: EXE_HOOKS.preToolUse,
21078
+ owner: "exe-os",
21079
+ purpose: "Preflight guardrails before shell/tool execution.",
21080
+ runtimes: ["claude", "codex", "opencode"],
21081
+ checkpointRole: "none"
21082
+ },
21083
+ {
21084
+ key: "subagentStop",
21085
+ event: "SubagentStop",
21086
+ commandMarker: EXE_HOOKS.subagentStop,
21087
+ owner: "exe-os",
21088
+ purpose: "Captures subagent completion context.",
21089
+ runtimes: ["claude"],
21090
+ checkpointRole: "none"
21091
+ },
21092
+ {
21093
+ key: "preCompact",
21094
+ event: "PreCompact",
21095
+ commandMarker: EXE_HOOKS.preCompact,
21096
+ owner: "exe-os",
21097
+ purpose: "Writes active-task snapshot and compaction recovery context.",
21098
+ runtimes: ["claude"],
21099
+ checkpointRole: "recovery_context"
21100
+ },
21101
+ {
21102
+ key: "postCompact",
21103
+ event: "PostCompact",
21104
+ commandMarker: EXE_HOOKS.postCompact,
21105
+ owner: "exe-os",
21106
+ purpose: "Rehydrates recovery context after compaction.",
21107
+ runtimes: ["claude"],
21108
+ checkpointRole: "recovery_context"
21109
+ },
21110
+ {
21111
+ key: "sessionEnd",
21112
+ event: "SessionEnd",
21113
+ commandMarker: EXE_HOOKS.sessionEnd,
21114
+ owner: "exe-os",
21115
+ purpose: "Stores session-end checkpoint and triages orphaned in-progress tasks.",
21116
+ runtimes: ["claude"],
21117
+ checkpointRole: "session_summary"
21118
+ },
21119
+ {
21120
+ key: "notification",
21121
+ event: "Notification",
21122
+ commandMarker: EXE_HOOKS.notification,
21123
+ owner: "exe-os",
21124
+ purpose: "Captures runtime notifications and nudges.",
21125
+ runtimes: ["claude"],
21126
+ checkpointRole: "none"
21127
+ },
21128
+ {
21129
+ key: "instructionsLoaded",
21130
+ event: "InstructionsLoaded",
21131
+ commandMarker: EXE_HOOKS.instructionsLoaded,
21132
+ owner: "exe-os",
21133
+ purpose: "Applies runtime instruction post-processing.",
21134
+ runtimes: ["claude"],
21135
+ checkpointRole: "none"
21136
+ }
21137
+ ];
21138
+ LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS = [
21139
+ "dist/hooks/ingest.js",
21140
+ "dist/hooks/error-recall.js",
21141
+ "dist/hooks/ingest-worker.js"
21142
+ ];
21143
+ }
21144
+ });
21145
+
21146
+ // src/bin/fast-db-init.ts
21147
+ var fast_db_init_exports = {};
21148
+ __export(fast_db_init_exports, {
21149
+ fastDbInit: () => fastDbInit
21150
+ });
21151
+ async function fastDbInit() {
21152
+ const { isInitialized: isInitialized2, getClient: getClient2, setExternalClient: setExternalClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
21153
+ if (isInitialized2()) {
21154
+ return getClient2();
21155
+ }
21156
+ try {
21157
+ const { connectEmbedDaemon: connectEmbedDaemon2, sendDaemonRequest: sendDaemonRequest2, isClientConnected: isClientConnected2 } = await Promise.resolve().then(() => (init_exe_daemon_client(), exe_daemon_client_exports));
21158
+ const { deserializeResultSet: deserializeResultSet2 } = await Promise.resolve().then(() => (init_daemon_protocol(), daemon_protocol_exports));
21159
+ await connectEmbedDaemon2();
21160
+ if (isClientConnected2()) {
21161
+ const daemonClient = {
21162
+ async execute(stmt) {
21163
+ const sql = typeof stmt === "string" ? stmt : stmt.sql;
21164
+ const args = typeof stmt === "string" ? [] : Array.isArray(stmt.args) ? stmt.args : [];
21165
+ const resp = await sendDaemonRequest2({ type: "db-execute", sql, args });
21166
+ if (resp.error) throw new Error(String(resp.error));
21167
+ if (resp.db) return deserializeResultSet2(resp.db);
21168
+ throw new Error("Unexpected daemon response");
21169
+ },
21170
+ async batch(stmts, mode) {
21171
+ const statements = stmts.map((s) => {
21172
+ const sql = typeof s === "string" ? s : s.sql;
21173
+ const args = typeof s === "string" ? [] : Array.isArray(s.args) ? s.args : [];
21174
+ return { sql, args };
21175
+ });
21176
+ const resp = await sendDaemonRequest2({ type: "db-batch", statements, mode: mode ?? "deferred" });
21177
+ if (resp.error) throw new Error(String(resp.error));
21178
+ const batchResults = resp["db-batch"];
21179
+ if (batchResults) return batchResults.map(deserializeResultSet2);
21180
+ throw new Error("Unexpected daemon batch response");
21181
+ },
21182
+ async transaction(_mode) {
21183
+ throw new Error("Transactions not supported via daemon socket");
21184
+ },
21185
+ async executeMultiple(_sql) {
21186
+ throw new Error("executeMultiple not supported via daemon socket");
21187
+ },
21188
+ async migrate(_stmts) {
21189
+ throw new Error("migrate not supported via daemon socket");
21190
+ },
21191
+ sync() {
21192
+ return Promise.resolve(void 0);
21193
+ },
21194
+ close() {
21195
+ },
21196
+ get closed() {
21197
+ return false;
21198
+ },
21199
+ get protocol() {
21200
+ return "file";
21201
+ }
21202
+ };
21203
+ setExternalClient2(daemonClient);
21204
+ return daemonClient;
21205
+ }
21206
+ } catch {
21207
+ }
21208
+ const { initStore: initStore2 } = await Promise.resolve().then(() => (init_store(), store_exports));
21209
+ await initStore2({ lightweight: true });
21210
+ return getClient2();
21211
+ }
21212
+ var init_fast_db_init = __esm({
21213
+ "src/bin/fast-db-init.ts"() {
21214
+ "use strict";
21215
+ }
21216
+ });
21217
+
20994
21218
  // src/lib/db-backup.ts
20995
21219
  var db_backup_exports = {};
20996
21220
  __export(db_backup_exports, {
@@ -21297,6 +21521,121 @@ function auditHookHealth() {
21297
21521
  const topPatterns = [...patternCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([pattern, count]) => ({ pattern, count }));
21298
21522
  return { logExists: true, totalLines, errorsLastHour, topPatterns };
21299
21523
  }
21524
+ function safeReadJson(filePath) {
21525
+ if (!existsSync31(filePath)) return null;
21526
+ try {
21527
+ return JSON.parse(readFileSync23(filePath, "utf-8"));
21528
+ } catch {
21529
+ return null;
21530
+ }
21531
+ }
21532
+ function collectHookCommandsFromClaudeSettings(settings) {
21533
+ const hooks = settings?.hooks;
21534
+ if (!hooks || typeof hooks !== "object") return [];
21535
+ const commands = [];
21536
+ for (const [event, groups] of Object.entries(hooks)) {
21537
+ if (!Array.isArray(groups)) continue;
21538
+ for (const group of groups) {
21539
+ const hooksForGroup = group?.hooks;
21540
+ if (!Array.isArray(hooksForGroup)) continue;
21541
+ for (const hook of hooksForGroup) {
21542
+ const command = hook?.command;
21543
+ if (typeof command === "string") commands.push({ event, command });
21544
+ }
21545
+ }
21546
+ }
21547
+ return commands;
21548
+ }
21549
+ function collectHookCommandsFromCodexHooks(config2) {
21550
+ const commands = [];
21551
+ if (!config2 || typeof config2 !== "object") return commands;
21552
+ const root = config2;
21553
+ for (const [event, value] of Object.entries(root)) {
21554
+ const entries = Array.isArray(value) ? value : value && typeof value === "object" ? Object.values(value) : [];
21555
+ for (const entry of entries) {
21556
+ if (typeof entry === "string") commands.push({ event, command: entry });
21557
+ const command = entry?.command;
21558
+ if (typeof command === "string") commands.push({ event, command });
21559
+ }
21560
+ }
21561
+ return commands;
21562
+ }
21563
+ function buildHookOwnershipIssues(runtime, commands) {
21564
+ const issues = [];
21565
+ for (const marker of LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS) {
21566
+ const count = commands.filter((cmd) => cmd.command.includes(marker)).length;
21567
+ if (count > 0) {
21568
+ issues.push({
21569
+ runtime,
21570
+ event: "PostToolUse",
21571
+ marker,
21572
+ count,
21573
+ message: `Legacy split PostToolUse hook still installed: ${marker}`
21574
+ });
21575
+ }
21576
+ }
21577
+ for (const entry of EXE_HOOK_MANIFEST.filter((hook) => hook.runtimes.includes(runtime))) {
21578
+ const matching = commands.filter((cmd) => cmd.command.includes(entry.commandMarker));
21579
+ if (matching.length > 1) {
21580
+ issues.push({
21581
+ runtime,
21582
+ event: entry.event,
21583
+ marker: entry.commandMarker,
21584
+ count: matching.length,
21585
+ message: `Duplicate exe-os hook owner for ${entry.event}: ${entry.commandMarker}`
21586
+ });
21587
+ }
21588
+ for (const cmd of matching) {
21589
+ if (cmd.event !== entry.event) {
21590
+ issues.push({
21591
+ runtime,
21592
+ event: cmd.event,
21593
+ marker: entry.commandMarker,
21594
+ count: 1,
21595
+ message: `exe-os hook ${entry.commandMarker} is registered under ${cmd.event}, expected ${entry.event}`
21596
+ });
21597
+ }
21598
+ }
21599
+ }
21600
+ for (const cmd of commands) {
21601
+ if (!cmd.command.includes("dist/hooks/")) continue;
21602
+ if (!cmd.command.includes("exe-os")) continue;
21603
+ const entry = manifestEntryForCommand(cmd.command);
21604
+ const isLegacy = LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS.some((marker) => cmd.command.includes(marker));
21605
+ if (!entry && !isLegacy) {
21606
+ issues.push({
21607
+ runtime,
21608
+ event: cmd.event,
21609
+ marker: "dist/hooks/",
21610
+ count: 1,
21611
+ message: `Unknown exe-os hook command not present in ownership manifest: ${cmd.command.slice(0, 160)}`
21612
+ });
21613
+ }
21614
+ }
21615
+ return issues;
21616
+ }
21617
+ function auditHookOwnership() {
21618
+ const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
21619
+ const checkedFiles = [];
21620
+ const issues = [];
21621
+ const claudeSettingsPath = path36.join(home, ".claude", "settings.json");
21622
+ const claudeSettings = safeReadJson(claudeSettingsPath);
21623
+ if (claudeSettings) {
21624
+ checkedFiles.push(claudeSettingsPath);
21625
+ issues.push(...buildHookOwnershipIssues("claude", collectHookCommandsFromClaudeSettings(claudeSettings)));
21626
+ }
21627
+ const codexHooksPath = path36.join(home, ".codex", "hooks.json");
21628
+ const codexHooks = safeReadJson(codexHooksPath);
21629
+ if (codexHooks) {
21630
+ checkedFiles.push(codexHooksPath);
21631
+ issues.push(...buildHookOwnershipIssues("codex", collectHookCommandsFromCodexHooks(codexHooks)));
21632
+ }
21633
+ return {
21634
+ checkedFiles,
21635
+ issues,
21636
+ staleLegacyHooks: issues.filter((issue) => issue.message.includes("Legacy split"))
21637
+ };
21638
+ }
21300
21639
  async function auditShards() {
21301
21640
  try {
21302
21641
  const { auditShardHealth: auditShardHealth2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
@@ -21341,7 +21680,8 @@ async function runAudit(client, flags) {
21341
21680
  }
21342
21681
  const duplicateCount = duplicates.reduce((sum, d) => sum + d.delete_ids.length, 0);
21343
21682
  const hookHealth = auditHookHealth();
21344
- return { stats, nullVectors, duplicates, duplicateCount, bloated, fts, orphanedProjects, conflicts, hookHealth, shards };
21683
+ const hookOwnership = auditHookOwnership();
21684
+ return { stats, nullVectors, duplicates, duplicateCount, bloated, fts, orphanedProjects, conflicts, hookHealth, hookOwnership, shards };
21345
21685
  }
21346
21686
  function indicator(value, warn) {
21347
21687
  if (value === 0) return "\u{1F7E2}";
@@ -21420,6 +21760,15 @@ function formatReport(report, flags) {
21420
21760
  lines.push(` ${p.count}x: ${p.pattern}`);
21421
21761
  }
21422
21762
  }
21763
+ const ho = report.hookOwnership;
21764
+ if (ho.issues.length === 0) {
21765
+ lines.push(`\u{1F7E2} Hook ownership: ${ho.checkedFiles.length > 0 ? "manifest clean" : "no local hook config found"}`);
21766
+ } else {
21767
+ lines.push(`\u{1F534} Hook ownership: ${fmtNum(ho.issues.length)} issue(s)`);
21768
+ for (const issue of ho.issues.slice(0, 5)) {
21769
+ lines.push(` [${issue.runtime}/${issue.event}] ${issue.message}`);
21770
+ }
21771
+ }
21423
21772
  const sh = report.shards;
21424
21773
  if (sh.total > 0) {
21425
21774
  if (sh.unreadable === 0) {
@@ -21489,6 +21838,9 @@ function formatReport(report, flags) {
21489
21838
  if (report.conflicts.superseded > 0) {
21490
21839
  recs.push(`${fmtNum(report.conflicts.superseded)} superseded memories can be deactivated`);
21491
21840
  }
21841
+ if (report.hookOwnership.issues.length > 0) {
21842
+ recs.push(`Run exe-os install to refresh hook config; remove stale exe-os hook commands if they remain`);
21843
+ }
21492
21844
  if (recs.length > 0) {
21493
21845
  lines.push("Recommendations:");
21494
21846
  for (const r of recs) {
@@ -21622,8 +21974,8 @@ function splitAtSentences(text3, maxChunkSize) {
21622
21974
  }
21623
21975
  async function main(argv = process.argv.slice(2)) {
21624
21976
  const flags = parseFlags(argv);
21625
- await initStore();
21626
- const client = getClient();
21977
+ const { fastDbInit: fastDbInit2 } = await Promise.resolve().then(() => (init_fast_db_init(), fast_db_init_exports));
21978
+ const client = await fastDbInit2();
21627
21979
  const report = await runAudit(client, flags);
21628
21980
  console.log(formatReport(report, flags));
21629
21981
  if (flags.fix || flags.dryRun) {
@@ -21683,10 +22035,9 @@ ${mode} Complete.`);
21683
22035
  var init_exe_doctor = __esm({
21684
22036
  "src/bin/exe-doctor.ts"() {
21685
22037
  "use strict";
21686
- init_store();
21687
- init_database();
21688
22038
  init_is_main();
21689
22039
  init_conflict_detector();
22040
+ init_runtime_hook_manifest();
21690
22041
  if (isMainModule(import.meta.url) && (process.argv[1] ?? "").includes("exe-doctor")) {
21691
22042
  main().catch((err) => {
21692
22043
  console.error(err instanceof Error ? err.message : String(err));