caveat-cli 0.19.2 → 0.19.5

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/README.md CHANGED
@@ -115,8 +115,7 @@ Codex and Cursor use native hooks rather than MCP for automatic surfacing. A
115
115
  native reminder inspects an entry with
116
116
  `caveat show <id> --source <source>`, then updates or creates Markdown in the
117
117
  own knowledge repo and runs `caveat index`. Community entries are subscriptions
118
- and are not edited locally. The optional `codex-sidecar` commands remain
119
- available for bounded second opinions, review, risk-check, and isolated work.
118
+ and are not edited locally. Jev-based struggle detection can be explicitly enabled with `caveat jev enable --key-stdin`.
120
119
 
121
120
  ## Pointing at a different knowledge repo
122
121
 
@@ -216,7 +216,7 @@ var require_section_matter = __commonJS({
216
216
  var delim = opts.section_delimiter;
217
217
  var lines = file.content.split(/\r?\n/);
218
218
  var sections = null;
219
- var section2 = createSection();
219
+ var section = createSection();
220
220
  var content = [];
221
221
  var stack = [];
222
222
  function initSections(val) {
@@ -226,11 +226,11 @@ var require_section_matter = __commonJS({
226
226
  }
227
227
  function closeSection(val) {
228
228
  if (stack.length) {
229
- section2.key = getKey(stack[0], delim);
230
- section2.content = val;
231
- opts.parse(section2, sections);
232
- sections.push(section2);
233
- section2 = createSection();
229
+ section.key = getKey(stack[0], delim);
230
+ section.content = val;
231
+ opts.parse(section, sections);
232
+ sections.push(section);
233
+ section = createSection();
234
234
  content = [];
235
235
  stack = [];
236
236
  }
@@ -246,7 +246,7 @@ var require_section_matter = __commonJS({
246
246
  continue;
247
247
  }
248
248
  stack.push(ln);
249
- section2.data = content.join("\n");
249
+ section.data = content.join("\n");
250
250
  content = [];
251
251
  continue;
252
252
  }
@@ -5124,7 +5124,7 @@ var require_truncate = __commonJS({
5124
5124
  var parse2 = require_parse2();
5125
5125
  var constants = require_constants();
5126
5126
  var SemVer = require_semver();
5127
- var truncate2 = (version, truncation, options2) => {
5127
+ var truncate = (version, truncation, options2) => {
5128
5128
  if (!constants.RELEASE_TYPES.includes(truncation)) {
5129
5129
  return null;
5130
5130
  }
@@ -5154,7 +5154,7 @@ var require_truncate = __commonJS({
5154
5154
  var isPrerelease = (type2) => {
5155
5155
  return type2.startsWith("pre");
5156
5156
  };
5157
- module2.exports = truncate2;
5157
+ module2.exports = truncate;
5158
5158
  }
5159
5159
  });
5160
5160
 
@@ -6200,7 +6200,7 @@ var require_semver2 = __commonJS({
6200
6200
  var lte = require_lte();
6201
6201
  var cmp = require_cmp();
6202
6202
  var coerce = require_coerce();
6203
- var truncate2 = require_truncate();
6203
+ var truncate = require_truncate();
6204
6204
  var Comparator = require_comparator();
6205
6205
  var Range = require_range();
6206
6206
  var satisfies = require_satisfies();
@@ -6239,7 +6239,7 @@ var require_semver2 = __commonJS({
6239
6239
  lte,
6240
6240
  cmp,
6241
6241
  coerce,
6242
- truncate: truncate2,
6242
+ truncate,
6243
6243
  Comparator,
6244
6244
  Range,
6245
6245
  satisfies,
@@ -15067,47 +15067,41 @@ function maybeSweepPendingDirs(caveatHome, options2 = {}) {
15067
15067
  }
15068
15068
  return { swept: result };
15069
15069
  }
15070
- function drainPendingRemindersDetailed(caveatHome, sessionId, fs = {}) {
15070
+ function peekPendingRemindersDetailed(caveatHome, sessionId) {
15071
15071
  const dir = pendingDirFor(caveatHome, sessionId);
15072
- if (!existsSync6(dir)) return { reminders: [], cleanupFailures: [] };
15073
- try {
15074
- return withPendingQueueLock(caveatHome, () => {
15075
- let entries;
15072
+ if (!existsSync6(dir)) return { reminders: [], readFailures: [] };
15073
+ return withPendingQueueLock(caveatHome, () => {
15074
+ const reminders = [];
15075
+ const readFailures = [];
15076
+ const entries = readdirSync6(dir).filter((name) => name.endsWith(".txt") || name.endsWith(".ready"));
15077
+ entries.sort((left, right) => {
15078
+ const difference = statSync5(join6(dir, left)).mtimeMs - statSync5(join6(dir, right)).mtimeMs;
15079
+ return difference || left.localeCompare(right);
15080
+ });
15081
+ for (const name of entries) {
15082
+ const path = join6(dir, name);
15076
15083
  try {
15077
- entries = readdirSync6(dir).filter((f) => f.endsWith(".txt") || f.endsWith(".ready"));
15084
+ reminders.push({ path, text: readFileSync5(path, "utf8") });
15078
15085
  } catch {
15079
- return { reminders: [], cleanupFailures: ["pending directory read failed"] };
15086
+ readFailures.push(name);
15080
15087
  }
15081
- const cleanupFailures = [];
15082
- entries.sort((a, b2) => {
15083
- try {
15084
- const diff = statSync5(join6(dir, a)).mtimeMs - statSync5(join6(dir, b2)).mtimeMs;
15085
- return diff || a.localeCompare(b2);
15086
- } catch {
15087
- return a.localeCompare(b2);
15088
- }
15089
- });
15090
- const reminders = [];
15091
- for (const entry of entries) {
15092
- const path = join6(dir, entry);
15093
- try {
15094
- reminders.push(fs.read ? fs.read(path) : readFileSync5(path, "utf-8"));
15095
- } catch {
15096
- cleanupFailures.push(entry);
15097
- continue;
15098
- }
15099
- try {
15100
- if (fs.unlink) fs.unlink(path);
15101
- else unlinkSync2(path);
15102
- } catch {
15103
- cleanupFailures.push(entry);
15104
- }
15088
+ }
15089
+ return { reminders, readFailures };
15090
+ });
15091
+ }
15092
+ function acknowledgePendingReminders(caveatHome, paths) {
15093
+ if (paths.length === 0) return;
15094
+ const root = join6(caveatHome, "pending");
15095
+ withPendingQueueLock(caveatHome, () => {
15096
+ for (const path of paths) {
15097
+ if (!path.startsWith(`${root}/`) && !path.startsWith(`${root}\\`)) throw new Error("pending path outside root");
15098
+ try {
15099
+ unlinkSync2(path);
15100
+ } catch (error) {
15101
+ if (!(error && typeof error === "object" && error.code === "ENOENT")) throw error;
15105
15102
  }
15106
- return { reminders, cleanupFailures };
15107
- });
15108
- } catch {
15109
- return { reminders: [], cleanupFailures: ["pending queue lock unavailable"] };
15110
- }
15103
+ }
15104
+ });
15111
15105
  }
15112
15106
 
15113
15107
  // ../../packages/core/dist/sealedKeys.js
@@ -15907,7 +15901,8 @@ var DEFAULT_CONFIG = {
15907
15901
  publishTarget: null,
15908
15902
  sealedKeyId: "v1",
15909
15903
  sealedKeyserverUrl: null,
15910
- runtimeErrors: false
15904
+ runtimeErrors: false,
15905
+ jevEnabled: false
15911
15906
  };
15912
15907
  function loadConfig(userConfigPath) {
15913
15908
  const userCfg = existsSync11(userConfigPath) ? JSON.parse(readFileSync9(userConfigPath, "utf-8")) : {};
@@ -15999,6 +15994,10 @@ function buildPromptCandidates(prompt) {
15999
15994
  }
16000
15995
  return unique.slice(0, PROMPT_MAX_CANDIDATE_TOKENS);
16001
15996
  }
15997
+ function extractPromptCandidates(prompt) {
15998
+ if (typeof prompt !== "string" || prompt.length === 0) return [];
15999
+ return buildPromptCandidates(prompt).map((c3) => c3.token);
16000
+ }
16002
16001
  function defaultSelfIdentityTokens() {
16003
16002
  const out = /* @__PURE__ */ new Set();
16004
16003
  try {
@@ -16333,9 +16332,6 @@ function readSessionSignals(transcriptPath) {
16333
16332
  function hasAnyStruggleSignal(s) {
16334
16333
  return s.toolFailureCount > 0 || s.fileEditCounts.length > 0 || s.webSearchCount > 0 || s.webFetchCount > 0 || s.bashRetryCount > 0;
16335
16334
  }
16336
- function struggleSearchText(s) {
16337
- return [...s.errorSnippets, ...s.searchQueries].join(" ");
16338
- }
16339
16335
 
16340
16336
  // ../../packages/core/dist/codexTranscriptSignals.js
16341
16337
  import { existsSync as existsSync13, readFileSync as readFileSync11 } from "node:fs";
@@ -16508,18 +16504,6 @@ function readCodexSessionSignals(transcriptPath) {
16508
16504
  };
16509
16505
  }
16510
16506
 
16511
- // ../../packages/core/dist/markHit.js
16512
- function markHit(db, keys, now2 = () => (/* @__PURE__ */ new Date()).toISOString()) {
16513
- if (keys.length === 0) return;
16514
- const ts = now2();
16515
- const stmt = db.prepare(
16516
- "UPDATE entries SET last_hit_at = ? WHERE source = ? AND id = ?"
16517
- );
16518
- for (const k2 of keys) {
16519
- stmt.run(ts, k2.source, k2.id);
16520
- }
16521
- }
16522
-
16523
16507
  // ../../packages/core/dist/stale.js
16524
16508
  function listStale(db, opts = {}) {
16525
16509
  const days = opts.days ?? 90;
@@ -17069,17 +17053,7 @@ ${collected.invalid.map((x2) => `${x2.relPath}: ${x2.reason}`).join("\n")}`);
17069
17053
  const question = `publish ${changes.lines.length} entry change(s)? [y/N]`;
17070
17054
  if (!opts.yes) {
17071
17055
  if (!(opts.isTty ?? (() => Boolean(process.stdin.isTTY)))()) throw new Error(`${question}; rerun with --yes to approve non-interactively`);
17072
- let advisory;
17073
- try {
17074
- advisory = opts.advisory?.(changes);
17075
- } catch (err) {
17076
- const message = err instanceof Error ? err.message : String(err);
17077
- opts.logger.warn(`publish advisory unavailable: ${message.replace(/\s+/g, " ").trim() || "unknown error"}`);
17078
- }
17079
- const questionWithAdvisory = advisory ? `${advisory}
17080
-
17081
- ${question}` : question;
17082
- if (!opts.confirmImpl(questionWithAdvisory)) throw new Error("publish cancelled");
17056
+ if (!opts.confirmImpl(question)) throw new Error("publish cancelled");
17083
17057
  }
17084
17058
  await checkoutOrphan(git);
17085
17059
  writeSealedMirror({ mirrorDir: opts.paths.publishMirrorDir, bundle, readme });
@@ -17101,217 +17075,6 @@ ${question}` : question;
17101
17075
  return { fileCount: verified.fileCount, changed: true, dryRun: false };
17102
17076
  }
17103
17077
 
17104
- // ../../packages/core/dist/codexSidecar.js
17105
- function buildHookSignalSidecarContextBlock(signal) {
17106
- if (signal.type === "tool-error") {
17107
- const tool = normalizeHookToolName(signal.toolName);
17108
- return {
17109
- kind: "manual_note",
17110
- source: "caveat-hook-signal",
17111
- trust: "local",
17112
- summary: `Hook signal: ${hookToolLabel(tool)} tool error (${signal.failureKind}).`,
17113
- data: { type: "tool-error", tool, failure_kind: signal.failureKind }
17114
- };
17115
- }
17116
- const counts = {
17117
- toolFailureCount: boundedCount(signal.toolFailureCount),
17118
- reeditedFileCount: boundedCount(signal.reeditedFileCount),
17119
- webSearchCount: boundedCount(signal.webSearchCount),
17120
- webFetchCount: boundedCount(signal.webFetchCount),
17121
- bashRetryCount: boundedCount(signal.bashRetryCount),
17122
- durationMinutes: boundedCount(signal.durationMinutes)
17123
- };
17124
- return {
17125
- kind: "manual_note",
17126
- source: "caveat-hook-signal",
17127
- trust: "local",
17128
- summary: `Hook signal: ${counts.toolFailureCount} tool failures, ${counts.reeditedFileCount} re-edited files, ${counts.webSearchCount} web searches, ${counts.webFetchCount} web fetches, ${counts.bashRetryCount} Bash retries, ${counts.durationMinutes} elapsed minutes.`,
17129
- data: {
17130
- type: "stop",
17131
- tool_failure_count: counts.toolFailureCount,
17132
- reedited_file_count: counts.reeditedFileCount,
17133
- web_search_count: counts.webSearchCount,
17134
- web_fetch_count: counts.webFetchCount,
17135
- bash_retry_count: counts.bashRetryCount,
17136
- duration_minutes: counts.durationMinutes
17137
- }
17138
- };
17139
- }
17140
- function caveatEntryToSidecarContextBlock(entry) {
17141
- const fm = entry.frontmatter;
17142
- return {
17143
- kind: "caveat_entry",
17144
- source: "caveat",
17145
- trust: "local",
17146
- summary: summarizeEntry(entry),
17147
- references: [
17148
- {
17149
- path: caveatEntryReferencePath(entry),
17150
- label: "source caveat"
17151
- }
17152
- ],
17153
- data: {
17154
- id: fm.id,
17155
- source: entry.source,
17156
- title: fm.title,
17157
- tags: fm.tags ?? [],
17158
- confidence: fm.confidence,
17159
- visibility: fm.visibility,
17160
- ...fm.outcome ? { outcome: fm.outcome } : {},
17161
- environment: fm.environment ?? {},
17162
- ...fm.last_verified ? { last_verified: fm.last_verified } : {}
17163
- }
17164
- };
17165
- }
17166
- function caveatEntriesToSidecarContextBlocks(entries) {
17167
- return entries.map((entry) => caveatEntryToSidecarContextBlock(entry));
17168
- }
17169
- function caveatEntryReferencePath(entry) {
17170
- const path = entry.path.replace(/\\/g, "/").replace(/^\/+/, "");
17171
- if (entry.source === "own") return prefixPath("entries", path);
17172
- return `${entry.source} (sealed or cloned bundle; no local file reference)`;
17173
- }
17174
- function decideCodexSidecarExecution(input) {
17175
- if (input.sidecarAgent === "disabled" || input.availability === "disabled") {
17176
- return {
17177
- useSidecar: false,
17178
- route: "disabled",
17179
- reason: "Codex sidecar is explicitly disabled."
17180
- };
17181
- }
17182
- if (input.availability === "unavailable") {
17183
- return {
17184
- useSidecar: false,
17185
- route: input.hostAgent === "claude" ? "claude-compatibility" : "unavailable",
17186
- reason: "codex-sidecar is not available for this repository."
17187
- };
17188
- }
17189
- if ((input.hostAgent === "automation" || input.hostAgent === "unknown") && input.sidecarAgent !== "codex") {
17190
- return {
17191
- useSidecar: false,
17192
- route: "requires-explicit-config",
17193
- reason: "Automation and unknown hosts must set sidecar_agent before delegating."
17194
- };
17195
- }
17196
- if (!availabilityCanRunWorkflow(input.availability, input.workflow)) {
17197
- return {
17198
- useSidecar: false,
17199
- route: input.hostAgent === "claude" ? "claude-compatibility" : "unavailable",
17200
- reason: input.workflow === "work" ? "codex_work requires work-capable sidecar availability." : "Read-only sidecar execution requires operational availability."
17201
- };
17202
- }
17203
- if (input.hostAgent === "codex" && !hasCodexOnCodexBoundary(input)) {
17204
- return {
17205
- useSidecar: false,
17206
- route: "current-codex-session",
17207
- reason: "Codex hosts should not call another Codex unless isolation, structured output, or an explicit second pass is required."
17208
- };
17209
- }
17210
- return {
17211
- useSidecar: true,
17212
- route: "codex-sidecar",
17213
- reason: input.hostAgent === "claude" ? "Claude hosts prefer Codex sidecar for independent review, exploration, and risk checks." : "The request has a distinct sidecar execution boundary."
17214
- };
17215
- }
17216
- function buildCodexSidecarDiagnosticsCommand(input) {
17217
- const cli = input.cli ?? { command: "codex-sidecar" };
17218
- return {
17219
- command: cli.command,
17220
- args: [
17221
- ...cli.argsPrefix ?? [],
17222
- "diagnostics",
17223
- "--project",
17224
- input.projectRoot,
17225
- "--preset",
17226
- input.preset ?? "review"
17227
- ]
17228
- };
17229
- }
17230
- function buildCodexSidecarReadOnlySmokeCommand(input) {
17231
- const cli = input.cli ?? { command: "codex-sidecar" };
17232
- return {
17233
- command: cli.command,
17234
- args: [
17235
- ...cli.argsPrefix ?? [],
17236
- "explore",
17237
- "--project",
17238
- input.projectRoot,
17239
- "--preset",
17240
- input.preset ?? "explore",
17241
- input.prompt ?? "Smoke test only: identify the package that contains Caveat core types. Return one sentence."
17242
- ]
17243
- };
17244
- }
17245
- function buildCodexSidecarRunCommand(input) {
17246
- const cli = input.cli ?? { command: "codex-sidecar" };
17247
- return {
17248
- command: cli.command,
17249
- args: [
17250
- ...cli.argsPrefix ?? [],
17251
- workflowCommand(input.workflow),
17252
- "--project",
17253
- input.projectRoot,
17254
- ...input.preset ? ["--preset", input.preset] : [],
17255
- ...input.contextFile ? ["--context-file", input.contextFile] : [],
17256
- ...input.preserveWorktree === false ? ["--remove-worktree"] : [],
17257
- ...input.prompt ? [input.prompt] : []
17258
- ]
17259
- };
17260
- }
17261
- function availabilityCanRunWorkflow(availability, workflow) {
17262
- if (workflow === "work") return availability === "work-capable";
17263
- return availability === "operational" || availability === "work-capable";
17264
- }
17265
- function hasCodexOnCodexBoundary(input) {
17266
- return input.workflow === "work" || input.requiresIsolation === true || input.structuredResultRequired === true || input.explicitSecondPass === true;
17267
- }
17268
- function workflowCommand(workflow) {
17269
- return workflow === "risk-check" ? "risk-check" : workflow;
17270
- }
17271
- function summarizeEntry(entry) {
17272
- const title = entry.frontmatter.title.trim();
17273
- const symptom = section(entry, "Symptom").replace(/\s+/g, " ").trim();
17274
- if (!symptom) return title;
17275
- return truncate(`${title}: ${symptom}`, 220);
17276
- }
17277
- function section(entry, name) {
17278
- const key = Object.keys(entry.sections).find(
17279
- (candidate) => candidate.trim().toLowerCase() === name.toLowerCase()
17280
- );
17281
- return key ? entry.sections[key] ?? "" : "";
17282
- }
17283
- function prefixPath(prefix, path) {
17284
- if (!path) return prefix;
17285
- if (path === prefix || path.startsWith(`${prefix}/`)) return path;
17286
- return `${prefix}/${path}`;
17287
- }
17288
- function truncate(value, maxLength) {
17289
- if (value.length <= maxLength) return value;
17290
- return `${value.slice(0, maxLength - 1).trimEnd()}...`;
17291
- }
17292
- function normalizeHookToolName(value) {
17293
- if (typeof value !== "string") return "other";
17294
- const tools = {
17295
- Bash: "bash",
17296
- Edit: "edit",
17297
- Write: "write",
17298
- Read: "read",
17299
- Glob: "glob",
17300
- Grep: "grep",
17301
- WebSearch: "web-search",
17302
- WebFetch: "web-fetch",
17303
- NotebookEdit: "notebook-edit"
17304
- };
17305
- return tools[value] ?? "other";
17306
- }
17307
- function hookToolLabel(tool) {
17308
- return tool === "web-search" ? "WebSearch" : tool === "web-fetch" ? "WebFetch" : tool === "notebook-edit" ? "NotebookEdit" : tool === "other" ? "Other" : tool[0].toUpperCase() + tool.slice(1);
17309
- }
17310
- function boundedCount(value) {
17311
- if (!Number.isFinite(value)) return 0;
17312
- return Math.min(1e4, Math.max(0, Math.floor(value)));
17313
- }
17314
-
17315
17078
  // ../../packages/core/dist/runtimeErrors.js
17316
17079
  import { spawnSync } from "node:child_process";
17317
17080
  import { createHash as createHash7, randomBytes as randomBytes3 } from "node:crypto";
@@ -17495,7 +17258,7 @@ function snapshot(options2 = {}) {
17495
17258
  if (afterCursor > store.next_sequence - 1) throw Error("invalid_cursor");
17496
17259
  const all = store.records.filter((r2) => r2.sequence > afterCursor);
17497
17260
  const rows = all.slice(0, limit);
17498
- return { schema: RUNTIME_ERRORS_SCHEMA, product: "caveat", version: options2.version ?? "unknown", state_schema_version: STATE_VERSION, cursor: { high_watermark: store.next_sequence - 1, acknowledged_through: store.acknowledged_through, next: rows.at(-1)?.sequence ?? afterCursor }, runtime_errors: rows.filter((r2) => r2.status === "open").map(({ error_code, component, status, severity, fingerprint: fingerprint22, message_template, count, first_seen, last_seen, state_schema_version }) => ({ error_code, component, status, severity, fingerprint: fingerprint22, message_template, occurrence_count: count, first_seen, last_seen, state_schema_version })), resolutions: rows.filter((r2) => r2.status === "resolved").map(({ fingerprint: fingerprint22, resolved_at, reason_code }) => ({ fingerprint: fingerprint22, resolved_at, reason_code })), diagnostics: { collection: enabled ? "enabled" : "disabled", status: enabled ? "ready" : "not_applicable", total_count: store.records.length, pending_count: store.records.filter((r2) => r2.sequence > store.acknowledged_through).length, truncated: all.length > rows.length } };
17261
+ return { schema: RUNTIME_ERRORS_SCHEMA, product: "caveat", version: options2.version ?? "unknown", state_schema_version: STATE_VERSION, cursor: { high_watermark: store.next_sequence - 1, acknowledged_through: store.acknowledged_through, next: rows.at(-1)?.sequence ?? afterCursor }, runtime_errors: rows.filter((r2) => r2.status === "open").map(({ error_code, component, status, severity, fingerprint: fingerprint22, message_template, count, first_seen, last_seen, product_version, state_schema_version }) => ({ error_code, component, status, severity, fingerprint: fingerprint22, message_template, occurrence_count: count, first_seen, last_seen, product_version, state_schema_version })), resolutions: rows.filter((r2) => r2.status === "resolved").map(({ fingerprint: fingerprint22, resolved_at, reason_code }) => ({ fingerprint: fingerprint22, resolved_at, reason_code })), diagnostics: { collection: enabled ? "enabled" : "disabled", status: enabled ? "ready" : "not_applicable", total_count: store.records.length, pending_count: store.records.filter((r2) => r2.sequence > store.acknowledged_through).length, truncated: all.length > rows.length } };
17499
17262
  }
17500
17263
  function runtimeErrorsDiagnostics(options2 = {}) {
17501
17264
  if (!collectionEnabled(options2)) return { schema: "caveat.runtime_error_diagnostics.v1", collection: "disabled", status: "not_applicable", total_count: 0, open_count: 0, pending_count: 0, high_watermark: 0, acknowledged_through: 0 };
@@ -17606,6 +17369,28 @@ function fingerprint2() {
17606
17369
  node: process.versions.node ?? ""
17607
17370
  };
17608
17371
  }
17372
+ function normalizeTargetOs(value) {
17373
+ const lower = value.toLowerCase();
17374
+ if (lower === "win32" || lower === "windows") return "windows";
17375
+ if (lower === "darwin" || lower === "macos") return "macos";
17376
+ if (lower === "linux") return "linux";
17377
+ return null;
17378
+ }
17379
+ function environmentAppliesToTask(environment, taskText, hostPlatform2) {
17380
+ const requiredRaw = environment.applies_to_os;
17381
+ if (!requiredRaw) return true;
17382
+ const required = normalizeTargetOs(requiredRaw);
17383
+ if (!required) throw new Error(`invalid applies_to_os: ${requiredRaw}`);
17384
+ const targets = /* @__PURE__ */ new Set();
17385
+ if (/\b(?:windows|win32)\b/iu.test(taskText)) targets.add("windows");
17386
+ if (/\b(?:mac|macos|darwin)\b/iu.test(taskText)) targets.add("macos");
17387
+ if (/\b(?:linux|ubuntu|wsl)\b/iu.test(taskText)) targets.add("linux");
17388
+ if (targets.size === 0) {
17389
+ const host = normalizeTargetOs(hostPlatform2);
17390
+ if (host) targets.add(host);
17391
+ }
17392
+ return targets.has(required);
17393
+ }
17609
17394
 
17610
17395
  // ../../packages/core/dist/id.js
17611
17396
  import { randomBytes as randomBytes4 } from "node:crypto";
@@ -17814,6 +17599,18 @@ function formatYmd2(d) {
17814
17599
  return `${yyyy}-${mm}-${dd}`;
17815
17600
  }
17816
17601
 
17602
+ // ../../packages/core/dist/markHit.js
17603
+ function markHit(db, keys, now2 = () => (/* @__PURE__ */ new Date()).toISOString()) {
17604
+ if (keys.length === 0) return;
17605
+ const ts = now2();
17606
+ const stmt = db.prepare(
17607
+ "UPDATE entries SET last_hit_at = ? WHERE source = ? AND id = ?"
17608
+ );
17609
+ for (const k2 of keys) {
17610
+ stmt.run(ts, k2.source, k2.id);
17611
+ }
17612
+ }
17613
+
17817
17614
  // ../../packages/core/dist/hookQueryLog.js
17818
17615
  import { appendFileSync, chmodSync as chmodSync2, mkdirSync as mkdirSync10, renameSync as renameSync5, statSync as statSync10, unlinkSync as unlinkSync3 } from "node:fs";
17819
17616
  import { join as join16, resolve as resolve3 } from "node:path";
@@ -17898,6 +17695,8 @@ export {
17898
17695
  __toESM,
17899
17696
  stderrLogger,
17900
17697
  openDb,
17698
+ fingerprint2 as fingerprint,
17699
+ environmentAppliesToTask,
17901
17700
  rebuildAll,
17902
17701
  prewarmSealedKeys,
17903
17702
  computeEntriesDigest,
@@ -17907,6 +17706,7 @@ export {
17907
17706
  releaseReindexLock,
17908
17707
  reindexAllSources,
17909
17708
  isWindows,
17709
+ isWindowsEnv,
17910
17710
  isPrivateOwnerStat,
17911
17711
  powershellCallPrefix,
17912
17712
  nodeExecutableNames,
@@ -17918,7 +17718,8 @@ export {
17918
17718
  buildAndPublishPendingReminder,
17919
17719
  cleanupStalePendingDirs,
17920
17720
  maybeSweepPendingDirs,
17921
- drainPendingRemindersDetailed,
17721
+ peekPendingRemindersDetailed,
17722
+ acknowledgePendingReminders,
17922
17723
  createKeyserverKeyProvider,
17923
17724
  syncOwn,
17924
17725
  KNOWLEDGE_GITIGNORE,
@@ -17939,6 +17740,7 @@ export {
17939
17740
  loadConfig,
17940
17741
  ensureUserConfig,
17941
17742
  writeUserConfigPatch,
17743
+ extractPromptCandidates,
17942
17744
  defaultSelfIdentityTokens,
17943
17745
  findCaveatsForHook,
17944
17746
  findCaveatsForHookSegments,
@@ -17947,19 +17749,13 @@ export {
17947
17749
  stopReminderText,
17948
17750
  readSessionSignals,
17949
17751
  hasAnyStruggleSignal,
17950
- struggleSearchText,
17951
17752
  readCodexSessionSignals,
17952
17753
  markHit,
17953
17754
  logHookQueryMiss,
17954
17755
  listStale,
17955
17756
  PublishScanError,
17956
17757
  publishOwn,
17957
- buildHookSignalSidecarContextBlock,
17958
- caveatEntriesToSidecarContextBlocks,
17959
- decideCodexSidecarExecution,
17960
- buildCodexSidecarDiagnosticsCommand,
17961
- buildCodexSidecarReadOnlySmokeCommand,
17962
- buildCodexSidecarRunCommand,
17758
+ runWindowsAcl,
17963
17759
  runtimeErrorsDiagnostics,
17964
17760
  observeRuntimeError,
17965
17761
  runtimeErrorsSnapshot,
@@ -17988,4 +17784,4 @@ strip-bom-string/index.js:
17988
17784
  js-yaml/dist/js-yaml.mjs:
17989
17785
  (*! js-yaml 4.1.1 https://github.com/nodeca/js-yaml @license MIT *)
17990
17786
  */
17991
- //# sourceMappingURL=chunk-NZD3FHU6.js.map
17787
+ //# sourceMappingURL=chunk-EMGYSGFX.js.map