@inerrata-corporation/errata 2.0.21-dev.3952 → 2.0.21-dev.3975

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/errata.mjs CHANGED
@@ -8591,11 +8591,11 @@ var init_nl = __esm({
8591
8591
  case "too_small": {
8592
8592
  const adj = issue2.inclusive ? ">=" : ">";
8593
8593
  const sizing = getSizing(issue2.origin);
8594
- const shortName = issue2.origin === "date" ? "vroeg" : issue2.origin === "string" ? "kort" : "klein";
8594
+ const shortName2 = issue2.origin === "date" ? "vroeg" : issue2.origin === "string" ? "kort" : "klein";
8595
8595
  if (sizing) {
8596
- return `Te ${shortName}: verwacht dat ${issue2.origin} ${adj}${issue2.minimum.toString()} ${sizing.unit} ${sizing.verb}`;
8596
+ return `Te ${shortName2}: verwacht dat ${issue2.origin} ${adj}${issue2.minimum.toString()} ${sizing.unit} ${sizing.verb}`;
8597
8597
  }
8598
- return `Te ${shortName}: verwacht dat ${issue2.origin} ${adj}${issue2.minimum.toString()} is`;
8598
+ return `Te ${shortName2}: verwacht dat ${issue2.origin} ${adj}${issue2.minimum.toString()} is`;
8599
8599
  }
8600
8600
  case "invalid_format": {
8601
8601
  const _issue = issue2;
@@ -20404,9 +20404,9 @@ CREATE INDEX IF NOT EXISTS nodes_enrichment_pending ON nodes(json_extract(attrs_
20404
20404
  * absent, which is how incremental region assembly drops dead endpoints). */
20405
20405
  ranksForMany(ids) {
20406
20406
  const out2 = /* @__PURE__ */ new Map();
20407
- const CHUNK = 400;
20408
- for (let i2 = 0; i2 < ids.length; i2 += CHUNK) {
20409
- const chunk = ids.slice(i2, i2 + CHUNK);
20407
+ const CHUNK2 = 400;
20408
+ for (let i2 = 0; i2 < ids.length; i2 += CHUNK2) {
20409
+ const chunk = ids.slice(i2, i2 + CHUNK2);
20410
20410
  const placeholders = chunk.map(() => "?").join(", ");
20411
20411
  const rows = this.db.prepare(
20412
20412
  `SELECT id, page_rank FROM nodes WHERE id IN (${placeholders}) AND valid_to IS NULL`
@@ -20437,9 +20437,9 @@ CREATE INDEX IF NOT EXISTS nodes_enrichment_pending ON nodes(json_extract(attrs_
20437
20437
  }
20438
20438
  edgesForMany(ids, col) {
20439
20439
  const out2 = [];
20440
- const CHUNK = 400;
20441
- for (let i2 = 0; i2 < ids.length; i2 += CHUNK) {
20442
- const chunk = ids.slice(i2, i2 + CHUNK);
20440
+ const CHUNK2 = 400;
20441
+ for (let i2 = 0; i2 < ids.length; i2 += CHUNK2) {
20442
+ const chunk = ids.slice(i2, i2 + CHUNK2);
20443
20443
  const placeholders = chunk.map(() => "?").join(", ");
20444
20444
  const rows = this.db.prepare(
20445
20445
  `SELECT from_id, to_id, type FROM edges WHERE ${col} IN (${placeholders}) AND valid_to IS NULL`
@@ -20458,9 +20458,9 @@ CREATE INDEX IF NOT EXISTS nodes_enrichment_pending ON nodes(json_extract(attrs_
20458
20458
  }
20459
20459
  reviveReobserved(relPaths, workspaceId2, since) {
20460
20460
  let revived = 0;
20461
- const CHUNK = 400;
20462
- for (let i2 = 0; i2 < relPaths.length; i2 += CHUNK) {
20463
- const slice = relPaths.slice(i2, i2 + CHUNK);
20461
+ const CHUNK2 = 400;
20462
+ for (let i2 = 0; i2 < relPaths.length; i2 += CHUNK2) {
20463
+ const slice = relPaths.slice(i2, i2 + CHUNK2);
20464
20464
  if (slice.length === 0) continue;
20465
20465
  const r = this.db.prepare(
20466
20466
  `UPDATE nodes SET valid_to = NULL
@@ -20486,9 +20486,9 @@ CREATE INDEX IF NOT EXISTS nodes_enrichment_pending ON nodes(json_extract(attrs_
20486
20486
  }
20487
20487
  liveNodeIdsByCloudNodeId(cloudIds) {
20488
20488
  const out2 = /* @__PURE__ */ new Map();
20489
- const CHUNK = 900;
20490
- for (let i2 = 0; i2 < cloudIds.length; i2 += CHUNK) {
20491
- const slice = cloudIds.slice(i2, i2 + CHUNK);
20489
+ const CHUNK2 = 900;
20490
+ for (let i2 = 0; i2 < cloudIds.length; i2 += CHUNK2) {
20491
+ const slice = cloudIds.slice(i2, i2 + CHUNK2);
20492
20492
  if (slice.length === 0) continue;
20493
20493
  const rows = this.db.prepare(
20494
20494
  `SELECT id, json_extract(attrs_json, '$.cloudNodeId') AS cloud FROM nodes INDEXED BY nodes_cloud_node_id WHERE json_extract(attrs_json, '$.cloudNodeId') IN (${slice.map(() => "?").join(",")}) AND valid_to IS NULL ORDER BY id`
@@ -20499,9 +20499,9 @@ CREATE INDEX IF NOT EXISTS nodes_enrichment_pending ON nodes(json_extract(attrs_
20499
20499
  }
20500
20500
  liveNodeIds(ids) {
20501
20501
  const live3 = /* @__PURE__ */ new Set();
20502
- const CHUNK = 900;
20503
- for (let i2 = 0; i2 < ids.length; i2 += CHUNK) {
20504
- const slice = ids.slice(i2, i2 + CHUNK);
20502
+ const CHUNK2 = 900;
20503
+ for (let i2 = 0; i2 < ids.length; i2 += CHUNK2) {
20504
+ const slice = ids.slice(i2, i2 + CHUNK2);
20505
20505
  if (slice.length === 0) continue;
20506
20506
  const rows = this.db.prepare(
20507
20507
  `SELECT id FROM nodes WHERE valid_to IS NULL AND id IN (${slice.map(() => "?").join(",")})`
@@ -23696,9 +23696,9 @@ function migrateProjectAlias(l2, opts) {
23696
23696
  }
23697
23697
  }
23698
23698
  }
23699
- const CHUNK = 200;
23700
- for (let i2 = 0; i2 < nodeUpdates.length; i2 += CHUNK) {
23701
- const slice = nodeUpdates.slice(i2, i2 + CHUNK);
23699
+ const CHUNK2 = 200;
23700
+ for (let i2 = 0; i2 < nodeUpdates.length; i2 += CHUNK2) {
23701
+ const slice = nodeUpdates.slice(i2, i2 + CHUNK2);
23702
23702
  l2.transaction(() => {
23703
23703
  for (const u of slice) {
23704
23704
  l2.updateNode(u.id, { attrs: u.attrs, lastUpdatedAt: opts.ts });
@@ -23706,8 +23706,8 @@ function migrateProjectAlias(l2, opts) {
23706
23706
  }
23707
23707
  });
23708
23708
  }
23709
- for (let i2 = 0; i2 < edgeUpdates.length; i2 += CHUNK) {
23710
- const slice = edgeUpdates.slice(i2, i2 + CHUNK);
23709
+ for (let i2 = 0; i2 < edgeUpdates.length; i2 += CHUNK2) {
23710
+ const slice = edgeUpdates.slice(i2, i2 + CHUNK2);
23711
23711
  l2.transaction(() => {
23712
23712
  for (const u of slice) {
23713
23713
  l2.updateEdge(u.id, { attrs: u.attrs, lastSeenAt: opts.ts });
@@ -26399,7 +26399,7 @@ function diffRenderLedger(before, after) {
26399
26399
  for (const i2 of before) (survived.has(key(i2)) ? shown : evicted).push(i2);
26400
26400
  return { shown, evicted };
26401
26401
  }
26402
- var RECENT_OPEN, RECENT_RESOLVED, RECENT_CONSTRAINTS, SCOPE_POOL_FACTOR, RECALL_FIRST_HEADER, RECALL_FIRST_BODY, RECALL_FIRST_BLOCK, SEARCH_IMPERATIVE_HEADER, SEARCH_IMPERATIVE_BODY, PROMPT_RECUE, SPAWN_SHARE_HINT, SUBAGENT_OWN_BLOCK_NOTE, EVICTION_ORDER, MOTIF_FLOOR, REMOTE_FLOOR, PROBLEM_FLOOR, REVIEW_ITEM_FLOOR, DEFAULT_AGENT_CONTEXT_BUDGET;
26402
+ var RECENT_OPEN, RECENT_RESOLVED, RECENT_CONSTRAINTS, SCOPE_POOL_FACTOR, RECALL_FIRST_HEADER, RECALL_FIRST_BODY, RECALL_FIRST_BLOCK, SEARCH_IMPERATIVE_HEADER, SEARCH_IMPERATIVE_BODY, PROMPT_INTENT_CUE, PROMPT_RECUE, SPAWN_SHARE_HINT, SUBAGENT_OWN_BLOCK_NOTE, EVICTION_ORDER, MOTIF_FLOOR, REMOTE_FLOOR, PROBLEM_FLOOR, REVIEW_ITEM_FLOOR, DEFAULT_AGENT_CONTEXT_BUDGET;
26403
26403
  var init_render = __esm({
26404
26404
  "../../packages/context-writer/src/render.ts"() {
26405
26405
  "use strict";
@@ -26417,7 +26417,8 @@ var init_render = __esm({
26417
26417
  ${RECALL_FIRST_BODY}`;
26418
26418
  SEARCH_IMPERATIVE_HEADER = "### \u{1F50E} PRIORS ARE SEEDS \u2014 a sample, not the whole graph";
26419
26419
  SEARCH_IMPERATIVE_BODY = "Everything below is a budgeted slice of a much larger graph, not all errata knows. New request \u2014 any task, not just a bug? Say what it is \u2014 we search on it between your tool calls and put what we find here:\n```errata-intent\nintent: <the work in hand, in your words>\n```\nNarration, not a detour: no tool call, no plan change. It is the one signal we cannot derive from your edits \u2014 everything else here is guessed from the files you touched.";
26420
- PROMPT_RECUE = "errata (context block above unchanged): new request \u2192 state it first:\n```errata-intent\nintent: <this request, in your words>\n```\nTag ALL project work, not just bugs \u2014 features, UX, refactors, research: problems you hit (even in code you just wrote) [!\u2026], decisions (constraint: why), approaches (tried: \u2026)/(failed: \u2026), the area (domain: \u2026). Restate tags in your final reply.";
26420
+ PROMPT_INTENT_CUE = "new request \u2192 state it first:\n```errata-intent\nintent: <this request, in your words>\n```\nTag ALL project work, not just bugs \u2014 features, UX, refactors, research: problems you hit (even in code you just wrote) [!\u2026], decisions (constraint: why), approaches (tried: \u2026)/(failed: \u2026), the area (domain: \u2026). Restate tags in your final reply.";
26421
+ PROMPT_RECUE = `errata (context block above unchanged): ${PROMPT_INTENT_CUE}`;
26421
26422
  SPAWN_SHARE_HINT = "_Spawning a subagent? It gets its own errata block, seeded from its task \u2014 none of the priors here. To hand it some, put this in its prompt (or `priors: all` for this whole block):_\n```errata-share\npriors: [handle], [handle]\n```";
26422
26423
  SUBAGENT_OWN_BLOCK_NOTE = "_This block is yours: seeded from the task you were given, then from what you state and touch. The agent that spawned you sees a different one._";
26423
26424
  EVICTION_ORDER = [
@@ -26600,6 +26601,99 @@ var init_select_durable_memory = __esm({
26600
26601
  }
26601
26602
  });
26602
26603
 
26604
+ // ../../packages/context-writer/src/delta.ts
26605
+ function parseSections(body2) {
26606
+ const sections = [{ heading: "", units: [] }];
26607
+ let cur = sections[0];
26608
+ let item2 = null;
26609
+ for (const line of body2.split("\n")) {
26610
+ if (line.startsWith("### ")) {
26611
+ item2 = null;
26612
+ cur = { heading: line, units: [] };
26613
+ sections.push(cur);
26614
+ } else if (ITEM_START.test(line)) {
26615
+ item2 = [line];
26616
+ cur.units.push(item2);
26617
+ } else if (item2 && (line.startsWith(" ") || line.startsWith(" "))) {
26618
+ item2.push(line);
26619
+ } else {
26620
+ item2 = null;
26621
+ cur.units.push([line]);
26622
+ }
26623
+ }
26624
+ return sections;
26625
+ }
26626
+ function itemRef(headline) {
26627
+ const handles = [...headline.matchAll(HANDLE_RE)].map((m) => m[1]);
26628
+ if (handles.length) return `[${handles[handles.length - 1]}]`;
26629
+ const tick = TICK_RE.exec(headline);
26630
+ return tick ? `\`${tick[1]}\`` : null;
26631
+ }
26632
+ function renderContextDelta(prev, next) {
26633
+ const before = parseSections(prev);
26634
+ const after = parseSections(next);
26635
+ const prevByHeading = new Map(before.map((s) => [s.heading, s]));
26636
+ const nextHeadings = new Set(after.map((s) => s.heading));
26637
+ const unchanged = [];
26638
+ const out2 = [];
26639
+ for (const sec of after) {
26640
+ const old = prevByHeading.get(sec.heading);
26641
+ if (old && sectionText(old) === sectionText(sec)) {
26642
+ if (sec.heading) unchanged.push(shortName(sec.heading));
26643
+ continue;
26644
+ }
26645
+ const oldHeadlines = new Set((old?.units ?? []).filter(isItem).map((u) => u[0]));
26646
+ const oldProse = new Set((old?.units ?? []).filter((u) => !isItem(u)).map((u) => u[0]));
26647
+ const body2 = [];
26648
+ const stillCurrent = [];
26649
+ let unnamed = 0;
26650
+ for (const u of sec.units) {
26651
+ if (!isItem(u)) {
26652
+ if (old && u[0].trim() && oldProse.has(u[0])) continue;
26653
+ body2.push(u[0]);
26654
+ continue;
26655
+ }
26656
+ const head2 = u[0];
26657
+ if (!oldHeadlines.has(head2)) {
26658
+ body2.push(...u);
26659
+ continue;
26660
+ }
26661
+ const ref = itemRef(head2);
26662
+ if (ref) stillCurrent.push(ref);
26663
+ else unnamed++;
26664
+ }
26665
+ if (stillCurrent.length || unnamed) {
26666
+ const more = unnamed ? `${stillCurrent.length ? " + " : ""}${unnamed} more as last shown` : "";
26667
+ body2.push(`- _still current, as last shown:_ ${stillCurrent.join(", ")}${more}`);
26668
+ }
26669
+ const content = body2.filter((l) => l.trim()).length ? body2 : ["- _(now empty)_"];
26670
+ if (sec.heading) out2.push(sec.heading);
26671
+ out2.push(...content);
26672
+ if (out2[out2.length - 1] !== "") out2.push("");
26673
+ }
26674
+ const retired = before.filter((s) => s.heading && !nextHeadings.has(s.heading)).map((s) => shortName(s.heading));
26675
+ if (!out2.some((l) => l.trim()) && !retired.length) return null;
26676
+ const lines = [];
26677
+ if (unchanged.length) lines.push(`_Unchanged: ${unchanged.join(" \xB7 ")}._`);
26678
+ if (retired.length) lines.push(`_No longer current: ${retired.join(" \xB7 ")}._`);
26679
+ if (lines.length) lines.push("");
26680
+ return [...lines, ...out2].join("\n").replace(/\n{3,}/g, "\n\n").trim();
26681
+ }
26682
+ var DELTA_MAX_FRACTION, DELTA_PREAMBLE, ITEM_START, HANDLE_RE, TICK_RE, isItem, sectionText, shortName;
26683
+ var init_delta = __esm({
26684
+ "../../packages/context-writer/src/delta.ts"() {
26685
+ "use strict";
26686
+ DELTA_MAX_FRACTION = 2 / 3;
26687
+ DELTA_PREAMBLE = "The errata daemon has updated your live workspace context. Only what CHANGED is below \u2014 the rest of your last errata context block still holds. Sections listed as unchanged are as last shown; in a changed section, items not listed (in full or by `[handle]`) are retired.";
26688
+ ITEM_START = /^- /;
26689
+ HANDLE_RE = /`\[([^\]`]+)\]`/g;
26690
+ TICK_RE = /`([^`\s]+)`/;
26691
+ isItem = (u) => ITEM_START.test(u[0]);
26692
+ sectionText = (s) => s.units.map((u) => u.join("\n")).join("\n").trim();
26693
+ shortName = (heading) => heading.replace(/^###\s+/, "").replace(/\s+—.*$/, "").trim();
26694
+ }
26695
+ });
26696
+
26603
26697
  // ../../packages/context-writer/src/index.ts
26604
26698
  var init_src6 = __esm({
26605
26699
  "../../packages/context-writer/src/index.ts"() {
@@ -26611,6 +26705,7 @@ var init_src6 = __esm({
26611
26705
  init_bleed_memory();
26612
26706
  init_bleed_rules();
26613
26707
  init_select_durable_memory();
26708
+ init_delta();
26614
26709
  }
26615
26710
  });
26616
26711
 
@@ -30654,6 +30749,131 @@ var init_dist = __esm({
30654
30749
  }
30655
30750
  });
30656
30751
 
30752
+ // src/context-baselines.ts
30753
+ import { closeSync, openSync, readSync, statSync } from "node:fs";
30754
+ function deliveryMarker(hash2) {
30755
+ return `<!-- errata-context ${hash2.slice(0, 16)} -->`;
30756
+ }
30757
+ function appendedSince(path2, offset, needle) {
30758
+ let fd;
30759
+ try {
30760
+ fd = openSync(path2, "r");
30761
+ } catch {
30762
+ return { found: false, turnRan: false };
30763
+ }
30764
+ try {
30765
+ const size = statSync(path2).size;
30766
+ const keep = Math.max(needle.length, MODEL_TURN.length);
30767
+ const buf = Buffer.alloc(CHUNK);
30768
+ let carry = "";
30769
+ let turnRan = false;
30770
+ for (let pos = Math.min(offset, size); pos < size; pos += CHUNK) {
30771
+ const n = readSync(fd, buf, 0, CHUNK, pos);
30772
+ const text = carry + buf.toString("utf8", 0, n);
30773
+ if (text.includes(needle)) return { found: true, turnRan: true };
30774
+ turnRan ||= text.includes(MODEL_TURN);
30775
+ carry = text.slice(-keep);
30776
+ }
30777
+ return { found: false, turnRan };
30778
+ } finally {
30779
+ closeSync(fd);
30780
+ }
30781
+ }
30782
+ function sizeOf(path2) {
30783
+ try {
30784
+ return statSync(path2).size;
30785
+ } catch {
30786
+ return 0;
30787
+ }
30788
+ }
30789
+ var CHUNK, UNVERIFIABLE_AFTER, MODEL_TURN, ContextBaselines;
30790
+ var init_context_baselines = __esm({
30791
+ "src/context-baselines.ts"() {
30792
+ "use strict";
30793
+ CHUNK = 1 << 20;
30794
+ UNVERIFIABLE_AFTER = 2;
30795
+ MODEL_TURN = '"type":"assistant"';
30796
+ ContextBaselines = class {
30797
+ /** `hashes` seeds confirmed hashes with no body (as after a daemon restart). */
30798
+ constructor(hashes = /* @__PURE__ */ new Map()) {
30799
+ this.hashes = hashes;
30800
+ }
30801
+ bodies = /* @__PURE__ */ new Map();
30802
+ pending = /* @__PURE__ */ new Map();
30803
+ /** Per key: sends confirmed so far, or a running count of unconfirmed ones while none has been. */
30804
+ track = /* @__PURE__ */ new Map();
30805
+ /** Window resets seen, by SessionStart source. */
30806
+ resets = /* @__PURE__ */ new Map();
30807
+ /** Sends checked against the transcript: arrived, or never showed up. */
30808
+ deliveries = { confirmed: 0, lost: 0 };
30809
+ /** Resolve this key's pending send against its transcript before deciding anything. */
30810
+ settle(key) {
30811
+ const p = this.pending.get(key);
30812
+ if (!p) return;
30813
+ const seen = appendedSince(p.transcript, p.offset, p.marker);
30814
+ if (!seen.found && !seen.turnRan) return;
30815
+ this.pending.delete(key);
30816
+ const t = this.track.get(key) ?? { confirmed: false, lost: 0 };
30817
+ if (seen.found) {
30818
+ this.deliveries.confirmed++;
30819
+ t.confirmed = true;
30820
+ this.confirm(key, p);
30821
+ } else {
30822
+ this.deliveries.lost++;
30823
+ t.lost++;
30824
+ if (!t.confirmed && t.lost >= UNVERIFIABLE_AFTER) this.confirm(key, p);
30825
+ }
30826
+ this.track.set(key, t);
30827
+ }
30828
+ /** What the session is taken to hold: an undecided send, else the last confirmed one. */
30829
+ hash(key) {
30830
+ return this.pending.get(key)?.hash ?? this.hashes.get(key);
30831
+ }
30832
+ body(key) {
30833
+ return this.pending.get(key)?.body ?? this.bodies.get(key);
30834
+ }
30835
+ /** A payload for `block` was sent; with a transcript it waits there to be confirmed. */
30836
+ record(key, block, transcript) {
30837
+ const t = this.track.get(key);
30838
+ if (!transcript || t && !t.confirmed && t.lost >= UNVERIFIABLE_AFTER) {
30839
+ this.pending.delete(key);
30840
+ this.confirm(key, block);
30841
+ return;
30842
+ }
30843
+ this.pending.set(key, {
30844
+ hash: block.hash,
30845
+ body: block.body,
30846
+ marker: deliveryMarker(block.hash),
30847
+ transcript,
30848
+ offset: sizeOf(transcript)
30849
+ });
30850
+ }
30851
+ /**
30852
+ * The harness dropped this session's window (`compact` / `clear` / `resume`),
30853
+ * or the session ended (`end`). Clearing or ending a session also ends its
30854
+ * subagents; a compaction leaves their own windows alone.
30855
+ */
30856
+ reset(key, source) {
30857
+ this.resets.set(source, (this.resets.get(source) ?? 0) + 1);
30858
+ this.drop(key);
30859
+ if ((source === "clear" || source === "end") && !key.includes("#")) {
30860
+ for (const k of /* @__PURE__ */ new Set([...this.hashes.keys(), ...this.pending.keys()])) if (k.startsWith(`${key}#`)) this.drop(k);
30861
+ }
30862
+ }
30863
+ confirm(key, d) {
30864
+ this.hashes.set(key, d.hash);
30865
+ this.bodies.set(key, d.body);
30866
+ }
30867
+ drop(key) {
30868
+ this.hashes.delete(key);
30869
+ this.bodies.delete(key);
30870
+ this.pending.delete(key);
30871
+ this.track.delete(key);
30872
+ }
30873
+ };
30874
+ }
30875
+ });
30876
+
30657
30877
  // ../../packages/generalizer/src/review-detector.ts
30658
30878
  function evaluateForReview(node2, prevTier) {
30659
30879
  if (node2.cumulativeSurprise >= REVIEW_SURPRISE_THRESHOLD) {
@@ -33312,12 +33532,12 @@ var init_consent = __esm({
33312
33532
 
33313
33533
  // src/git-remote.ts
33314
33534
  import { spawnSync } from "node:child_process";
33315
- import { existsSync as existsSync10, readFileSync as readFileSync8, statSync } from "node:fs";
33535
+ import { existsSync as existsSync10, readFileSync as readFileSync8, statSync as statSync2 } from "node:fs";
33316
33536
  import { isAbsolute as isAbsolute2, join as join8, resolve as resolve2 } from "node:path";
33317
33537
  function resolveGitDir(root) {
33318
33538
  const dotGit = join8(root, ".git");
33319
33539
  try {
33320
- const st = statSync(dotGit);
33540
+ const st = statSync2(dotGit);
33321
33541
  if (st.isDirectory()) return dotGit;
33322
33542
  const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync8(dotGit, "utf8"));
33323
33543
  if (!m) return null;
@@ -35550,7 +35770,7 @@ var init_daemon_generalize_client = __esm({
35550
35770
 
35551
35771
  // ../../packages/indexer/src/parse-cache.ts
35552
35772
  import { createHash as createHash6 } from "node:crypto";
35553
- import { existsSync as existsSync15, mkdirSync as mkdirSync6, readFileSync as readFileSync14, readdirSync as readdirSync2, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync11 } from "node:fs";
35773
+ import { existsSync as existsSync15, mkdirSync as mkdirSync6, readFileSync as readFileSync14, readdirSync as readdirSync2, rmSync as rmSync2, statSync as statSync3, writeFileSync as writeFileSync11 } from "node:fs";
35554
35774
  import { homedir as homedir3 } from "node:os";
35555
35775
  import { join as join12 } from "node:path";
35556
35776
  function parseCacheDir() {
@@ -35606,7 +35826,7 @@ function sweepParseCacheOnce(dir, now = Date.now()) {
35606
35826
  for (const name2 of names) {
35607
35827
  const file2 = join12(bucketDir, name2);
35608
35828
  try {
35609
- if (now - statSync2(file2).mtimeMs > ENTRY_TTL_MS) {
35829
+ if (now - statSync3(file2).mtimeMs > ENTRY_TTL_MS) {
35610
35830
  rmSync2(file2, { force: true });
35611
35831
  removed++;
35612
35832
  }
@@ -35852,7 +36072,7 @@ var init_identity3 = __esm({
35852
36072
  });
35853
36073
 
35854
36074
  // ../../packages/indexer/src/pipeline.ts
35855
- import { appendFileSync, readFileSync as readFileSync15, statSync as statSync3 } from "node:fs";
36075
+ import { appendFileSync, readFileSync as readFileSync15, statSync as statSync4 } from "node:fs";
35856
36076
  import { readdir } from "node:fs/promises";
35857
36077
  import { extname, join as join13, relative as relative2, sep } from "node:path";
35858
36078
  import { createHash as createHash7 } from "node:crypto";
@@ -36362,7 +36582,7 @@ async function runIndexer(store, opts) {
36362
36582
  }
36363
36583
  let source;
36364
36584
  try {
36365
- const st = statSync3(f.absPath);
36585
+ const st = statSync4(f.absPath);
36366
36586
  if (st.size > maxBytes) {
36367
36587
  report.filesSkipped++;
36368
36588
  continue;
@@ -36837,7 +37057,7 @@ async function scan(root, current, ignores, providers, out2) {
36837
37057
  let size = 0;
36838
37058
  let mtimeMs;
36839
37059
  try {
36840
- const st = statSync3(abs);
37060
+ const st = statSync4(abs);
36841
37061
  size = st.size;
36842
37062
  mtimeMs = st.mtimeMs;
36843
37063
  } catch {
@@ -36890,7 +37110,7 @@ function gitListFiles(root, ignores, providers) {
36890
37110
  let size;
36891
37111
  let mtimeMs;
36892
37112
  try {
36893
- const st = statSync3(abs);
37113
+ const st = statSync4(abs);
36894
37114
  size = st.size;
36895
37115
  mtimeMs = st.mtimeMs;
36896
37116
  } catch {
@@ -44325,7 +44545,7 @@ var init_src11 = __esm({
44325
44545
 
44326
44546
  // src/reconcile.ts
44327
44547
  import { execFileSync as execFileSync3 } from "node:child_process";
44328
- import { readdirSync as readdirSync4, statSync as statSync4 } from "node:fs";
44548
+ import { readdirSync as readdirSync4, statSync as statSync5 } from "node:fs";
44329
44549
  import { join as join15, relative as relative3, sep as sep2 } from "node:path";
44330
44550
  function indexerWouldScan(rel) {
44331
44551
  for (const seg of rel.split(/[\\/]/)) {
@@ -44389,7 +44609,7 @@ async function findStaleFiles(store, rootPath, workspaceId2) {
44389
44609
  for (const abs of listSourceFiles(rootPath)) {
44390
44610
  try {
44391
44611
  const rel = relative3(rootPath, abs).split(sep2).join("/");
44392
- pending.push({ abs, id: fileNodeId(workspaceId2, rel), mtimeMs: statSync4(abs).mtimeMs });
44612
+ pending.push({ abs, id: fileNodeId(workspaceId2, rel), mtimeMs: statSync5(abs).mtimeMs });
44393
44613
  } catch {
44394
44614
  }
44395
44615
  if (++scanned % SCAN_YIELD_EVERY === 0) {
@@ -54140,9 +54360,11 @@ var init_message_accumulator = __esm({
54140
54360
  // src/webui.ts
54141
54361
  var webui_exports = {};
54142
54362
  __export(webui_exports, {
54363
+ ContextBaselines: () => ContextBaselines,
54143
54364
  SUBAGENT_REFRESH_MIN_MS: () => SUBAGENT_REFRESH_MIN_MS,
54144
54365
  asFailedPostToolUse: () => asFailedPostToolUse,
54145
54366
  buildWebUi: () => buildWebUi,
54367
+ contextDeltaEnabled: () => contextDeltaEnabled,
54146
54368
  decideContextInject: () => decideContextInject,
54147
54369
  editVerdict: () => editVerdict,
54148
54370
  errorRecallTerms: () => errorRecallTerms,
@@ -54327,23 +54549,54 @@ function hookAudience(body2) {
54327
54549
  agentId
54328
54550
  };
54329
54551
  }
54552
+ function contextDeltaEnabled(env2 = process.env) {
54553
+ const v = (env2["ERRATA_CONTEXT_DELTA"] ?? "").trim().toLowerCase();
54554
+ return !(v === "0" || v === "off" || v === "false" || v === "no");
54555
+ }
54330
54556
  function decideContextInject(args2) {
54331
- const { event, sessionId, block, lastInjectedHash } = args2;
54557
+ const { event, source, sessionId, block, transcriptPath } = args2;
54332
54558
  if (!block) return null;
54559
+ const seen = args2.lastInjectedHash instanceof ContextBaselines ? args2.lastInjectedHash : null;
54560
+ const hashes = seen ? null : args2.lastInjectedHash;
54561
+ if (seen && sessionId) seen.settle(sessionId);
54562
+ const hashOf = (k) => seen ? seen.hash(k) : hashes.get(k);
54563
+ const record2 = (k) => {
54564
+ if (seen) seen.record(k, block, transcriptPath);
54565
+ else hashes.set(k, block.hash);
54566
+ };
54567
+ let additionalContext = FULL_BLOCK_PREFIX + block.body;
54333
54568
  if (event === "SessionStart" || event === "SubagentStart") {
54334
- if (sessionId) lastInjectedHash.set(sessionId, block.hash);
54335
- } else if (sessionId && lastInjectedHash.get(sessionId) === block.hash) {
54569
+ if (sessionId && seen && WINDOW_RESET_SOURCES.has(source)) seen.reset(sessionId, source);
54570
+ if (sessionId) record2(sessionId);
54571
+ } else if (sessionId && hashOf(sessionId) === block.hash) {
54336
54572
  return event === "UserPromptSubmit" ? { hookEventName: event, additionalContext: PROMPT_RECUE } : null;
54337
54573
  } else {
54338
- if (sessionId) lastInjectedHash.set(sessionId, block.hash);
54574
+ const prev = sessionId && seen && (args2.delta ?? true) ? seen.body(sessionId) : void 0;
54575
+ if (prev !== void 0) {
54576
+ const delta = renderContextDelta(prev, block.body);
54577
+ if (delta === null) {
54578
+ seen.record(sessionId, block);
54579
+ return event === "UserPromptSubmit" ? { hookEventName: event, additionalContext: PROMPT_RECUE } : null;
54580
+ }
54581
+ const cue = event === "UserPromptSubmit" ? `
54582
+
54583
+ ${PROMPT_INTENT_CUE}` : "";
54584
+ const sent = `${DELTA_PREAMBLE}
54585
+
54586
+ ${delta}${cue}`;
54587
+ if (sent.length <= DELTA_MAX_FRACTION * additionalContext.length) additionalContext = sent;
54588
+ }
54589
+ if (sessionId) record2(sessionId);
54339
54590
  }
54340
- const additionalContext = "The errata daemon has updated your live workspace context. The block below REPLACES any earlier errata context block in this conversation \u2014 treat it as the current source of truth:\n\n" + block.body;
54591
+ if (seen && sessionId && transcriptPath) additionalContext += `
54592
+
54593
+ ${deliveryMarker(block.hash)}`;
54341
54594
  return { hookEventName: event, additionalContext };
54342
54595
  }
54343
54596
  function buildWebUi(deps) {
54344
54597
  const app = new Hono2();
54345
54598
  const B = deps.basePath ?? "";
54346
- const lastInjectedHash = /* @__PURE__ */ new Map();
54599
+ const lastInjectedHash = new ContextBaselines();
54347
54600
  const fileRecallSeen = /* @__PURE__ */ new Map();
54348
54601
  const editVerdictAsked = /* @__PURE__ */ new Map();
54349
54602
  const lastSubagentInjectAt = /* @__PURE__ */ new Map();
@@ -54662,7 +54915,8 @@ function buildWebUi(deps) {
54662
54915
  source: "",
54663
54916
  sessionId: audience.contextKey,
54664
54917
  block: own,
54665
- lastInjectedHash
54918
+ lastInjectedHash,
54919
+ delta: contextDeltaEnabled()
54666
54920
  });
54667
54921
  if (decision) {
54668
54922
  lastSubagentInjectAt.set(audience.contextKey, Date.now());
@@ -54757,8 +55011,29 @@ function buildWebUi(deps) {
54757
55011
  deps.onSessionEnd({ sessionId, transcriptPath });
54758
55012
  }
54759
55013
  noteSessionFrom(c.req.header(ORIGIN_HEADER), body2, true);
55014
+ if (sessionId) lastInjectedHash.reset(sessionId, "end");
54760
55015
  return c.json({ ok: true });
54761
55016
  });
55017
+ app.post("/api/context-delta", async (c) => {
55018
+ let body2;
55019
+ try {
55020
+ body2 = await c.req.json();
55021
+ } catch {
55022
+ return c.json({});
55023
+ }
55024
+ const prev = body2["prev"];
55025
+ const next = body2["next"];
55026
+ if (typeof prev !== "string" || typeof next !== "string" || !contextDeltaEnabled()) return c.json({});
55027
+ const delta = renderContextDelta(prev, next);
55028
+ if (delta === null) return c.json({ unchanged: true });
55029
+ const cue = body2["hook_event_name"] === "UserPromptSubmit" ? `
55030
+
55031
+ ${PROMPT_INTENT_CUE}` : "";
55032
+ const sent = `${DELTA_PREAMBLE}
55033
+
55034
+ ${delta}${cue}`;
55035
+ return sent.length <= DELTA_MAX_FRACTION * next.length ? c.json({ delta: sent }) : c.json({});
55036
+ });
54762
55037
  app.post("/api/context-inject", async (c) => {
54763
55038
  let body2;
54764
55039
  try {
@@ -54800,7 +55075,10 @@ function buildWebUi(deps) {
54800
55075
  source: String(body2["source"] ?? ""),
54801
55076
  sessionId: contextKey2,
54802
55077
  block,
54803
- lastInjectedHash
55078
+ lastInjectedHash,
55079
+ delta: contextDeltaEnabled(),
55080
+ // A subagent's injections land in its own transcript, not the one posted.
55081
+ ...subagent === null && typeof body2["transcript_path"] === "string" && body2["transcript_path"] ? { transcriptPath: body2["transcript_path"] } : {}
54804
55082
  });
54805
55083
  if (decision && subagent !== null) lastSubagentInjectAt.set(contextKey2, Date.now());
54806
55084
  let systemMessage = null;
@@ -54997,11 +55275,12 @@ function proposalToIngest(p, profile, daemonVersion) {
54997
55275
  payloadDigest: p.id
54998
55276
  };
54999
55277
  }
55000
- var messageAccumulator, GENERIC_ERROR_WORDS, wsPackagesCache, WS_PACKAGES_TTL_MS, loggedToolSessions, SUBAGENT_REFRESH_MIN_MS, META_LABELS;
55278
+ var messageAccumulator, GENERIC_ERROR_WORDS, wsPackagesCache, WS_PACKAGES_TTL_MS, loggedToolSessions, SUBAGENT_REFRESH_MIN_MS, WINDOW_RESET_SOURCES, FULL_BLOCK_PREFIX, META_LABELS;
55001
55279
  var init_webui = __esm({
55002
55280
  "src/webui.ts"() {
55003
55281
  "use strict";
55004
55282
  init_dist();
55283
+ init_context_baselines();
55005
55284
  init_src6();
55006
55285
  init_src5();
55007
55286
  init_src8();
@@ -55014,6 +55293,7 @@ var init_webui = __esm({
55014
55293
  init_tool_index();
55015
55294
  init_outbox();
55016
55295
  init_message_accumulator();
55296
+ init_context_baselines();
55017
55297
  messageAccumulator = createMessageAccumulator();
55018
55298
  GENERIC_ERROR_WORDS = /* @__PURE__ */ new Set([
55019
55299
  "cannot",
@@ -55060,6 +55340,8 @@ var init_webui = __esm({
55060
55340
  WS_PACKAGES_TTL_MS = 6e4;
55061
55341
  loggedToolSessions = /* @__PURE__ */ new Set();
55062
55342
  SUBAGENT_REFRESH_MIN_MS = 6e4;
55343
+ WINDOW_RESET_SOURCES = /* @__PURE__ */ new Set(["compact", "clear", "resume"]);
55344
+ FULL_BLOCK_PREFIX = "The errata daemon has updated your live workspace context. The block below REPLACES any earlier errata context block in this conversation \u2014 treat it as the current source of truth:\n\n";
55063
55345
  META_LABELS = /* @__PURE__ */ new Set([
55064
55346
  "Pattern",
55065
55347
  "Technique",
@@ -74315,7 +74597,7 @@ var init_report_render = __esm({
74315
74597
 
74316
74598
  // src/cli.ts
74317
74599
  init_src6();
74318
- import { closeSync as closeSync2, existsSync as existsSync40, openSync as openSync2, readFileSync as readFileSync42, renameSync as renameSync7, statSync as statSync12 } from "node:fs";
74600
+ import { closeSync as closeSync3, existsSync as existsSync40, openSync as openSync3, readFileSync as readFileSync42, renameSync as renameSync7, statSync as statSync13 } from "node:fs";
74319
74601
  import { join as join49, resolve as pathResolve2 } from "node:path";
74320
74602
  import { spawn as spawn5 } from "node:child_process";
74321
74603
 
@@ -74901,7 +75183,7 @@ init_lock();
74901
75183
 
74902
75184
  // src/engine.ts
74903
75185
  import { execFileSync as execFileSync5 } from "node:child_process";
74904
- import { existsSync as existsSync28, statSync as statSync8, appendFileSync as appendFileSync4, readdirSync as readdirSync10, renameSync as renameSync4, readFileSync as readFileSync32, writeFileSync as writeFileSync23 } from "node:fs";
75186
+ import { existsSync as existsSync28, statSync as statSync9, appendFileSync as appendFileSync4, readdirSync as readdirSync10, renameSync as renameSync4, readFileSync as readFileSync32, writeFileSync as writeFileSync23 } from "node:fs";
74905
75187
  import { basename as basename7, join as join35, relative as relative6, sep as sep4 } from "node:path";
74906
75188
 
74907
75189
  // src/coalesced-file-pass.ts
@@ -74946,7 +75228,7 @@ function createCoalescedFilePass(delayMs, run3, onError) {
74946
75228
 
74947
75229
  // src/source-watcher.ts
74948
75230
  import { EventEmitter as EventEmitter2 } from "node:events";
74949
- import { statSync as statSync5, watch as watch2 } from "node:fs";
75231
+ import { statSync as statSync6, watch as watch2 } from "node:fs";
74950
75232
  import { join as join20 } from "node:path";
74951
75233
 
74952
75234
  // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
@@ -76674,7 +76956,7 @@ var NativeSourceWatcher = class extends EventEmitter2 {
76674
76956
  if (this.closed || this.handles.has(target)) return;
76675
76957
  let isDir;
76676
76958
  try {
76677
- isDir = statSync5(target).isDirectory();
76959
+ isDir = statSync6(target).isDirectory();
76678
76960
  } catch {
76679
76961
  return;
76680
76962
  }
@@ -76714,7 +76996,7 @@ var NativeSourceWatcher = class extends EventEmitter2 {
76714
76996
  if (this.closed) return;
76715
76997
  let isFile;
76716
76998
  try {
76717
- const s = statSync5(path2);
76999
+ const s = statSync6(path2);
76718
77000
  if (s.isDirectory()) return;
76719
77001
  isFile = s.isFile();
76720
77002
  } catch {
@@ -77135,7 +77417,7 @@ init_review2();
77135
77417
 
77136
77418
  // src/turn.ts
77137
77419
  init_checkout_root();
77138
- import { closeSync, existsSync as existsSync19, fstatSync, openSync, readdirSync as readdirSync6, readSync, realpathSync as realpathSync2, statSync as statSync6 } from "node:fs";
77420
+ import { closeSync as closeSync2, existsSync as existsSync19, fstatSync, openSync as openSync2, readdirSync as readdirSync6, readSync as readSync2, realpathSync as realpathSync2, statSync as statSync7 } from "node:fs";
77139
77421
  import { basename as basename5, delimiter, dirname as dirname10, join as join21, normalize as normalize3 } from "node:path";
77140
77422
  import { homedir as homedir4 } from "node:os";
77141
77423
  import { createHash as createHash16 } from "node:crypto";
@@ -77152,7 +77434,7 @@ function completeJsonlPrefix(buf) {
77152
77434
  function readFrom(path2, fromByte, maxBytes) {
77153
77435
  let fd;
77154
77436
  try {
77155
- fd = openSync(path2, "r");
77437
+ fd = openSync2(path2, "r");
77156
77438
  } catch {
77157
77439
  return { text: "", nextOffset: fromByte, more: false, ioFailed: true };
77158
77440
  }
@@ -77165,7 +77447,7 @@ function readFrom(path2, fromByte, maxBytes) {
77165
77447
  for (; ; ) {
77166
77448
  const len = Math.min(cap, remaining);
77167
77449
  const buf = Buffer.allocUnsafe(len);
77168
- const read2 = readSync(fd, buf, 0, len, start2);
77450
+ const read2 = readSync2(fd, buf, 0, len, start2);
77169
77451
  if (len >= remaining || read2 < len) {
77170
77452
  const end = completeJsonlPrefix(buf.subarray(0, read2));
77171
77453
  return { text: buf.subarray(0, end).toString("utf8"), nextOffset: start2 + end, more: false, ioFailed: false };
@@ -77184,7 +77466,7 @@ function readFrom(path2, fromByte, maxBytes) {
77184
77466
  } catch {
77185
77467
  return { text: "", nextOffset: fromByte, more: false, ioFailed: true };
77186
77468
  } finally {
77187
- closeSync(fd);
77469
+ closeSync2(fd);
77188
77470
  }
77189
77471
  }
77190
77472
  function readTail(path2, maxBytes) {
@@ -77193,7 +77475,7 @@ function readTail(path2, maxBytes) {
77193
77475
  function readTailWithLosses(path2, maxBytes, completeLinesOnly = false) {
77194
77476
  let fd;
77195
77477
  try {
77196
- fd = openSync(path2, "r");
77478
+ fd = openSync2(path2, "r");
77197
77479
  } catch {
77198
77480
  return { text: "", bytesUnreachable: 0, parseStartByte: 0, ioFailed: true, nextOffset: 0 };
77199
77481
  }
@@ -77203,7 +77485,7 @@ function readTailWithLosses(path2, maxBytes, completeLinesOnly = false) {
77203
77485
  const len = size - start2;
77204
77486
  if (len <= 0) return { text: "", bytesUnreachable: 0, parseStartByte: 0, ioFailed: false, nextOffset: 0 };
77205
77487
  const buf = Buffer.allocUnsafe(len);
77206
- const read2 = readSync(fd, buf, 0, len, start2);
77488
+ const read2 = readSync2(fd, buf, 0, len, start2);
77207
77489
  const end = completeLinesOnly ? completeJsonlPrefix(buf.subarray(0, read2)) : read2;
77208
77490
  const text = buf.subarray(0, end).toString("utf8");
77209
77491
  const firstNewline = buf.indexOf(10);
@@ -77212,7 +77494,7 @@ function readTailWithLosses(path2, maxBytes, completeLinesOnly = false) {
77212
77494
  } catch {
77213
77495
  return { text: "", bytesUnreachable: 0, parseStartByte: 0, ioFailed: true, nextOffset: 0 };
77214
77496
  } finally {
77215
- closeSync(fd);
77497
+ closeSync2(fd);
77216
77498
  }
77217
77499
  }
77218
77500
  function parseDesignFlags(text) {
@@ -77542,7 +77824,7 @@ function recentTranscripts(cwd, opts = {}) {
77542
77824
  const path2 = join21(dir, name2);
77543
77825
  let mtimeMs;
77544
77826
  try {
77545
- mtimeMs = statSync6(path2).mtimeMs;
77827
+ mtimeMs = statSync7(path2).mtimeMs;
77546
77828
  } catch {
77547
77829
  continue;
77548
77830
  }
@@ -77568,7 +77850,7 @@ function subagentTranscripts(mainTranscriptPath, sessionId) {
77568
77850
  const path2 = join21(dir, name2);
77569
77851
  let mtimeMs;
77570
77852
  try {
77571
- mtimeMs = statSync6(path2).mtimeMs;
77853
+ mtimeMs = statSync7(path2).mtimeMs;
77572
77854
  } catch {
77573
77855
  continue;
77574
77856
  }
@@ -77597,7 +77879,7 @@ function readCodexRolloutIdentity(path2) {
77597
77879
  };
77598
77880
  let fd;
77599
77881
  try {
77600
- fd = openSync(path2, "r");
77882
+ fd = openSync2(path2, "r");
77601
77883
  const CAP = 1e6;
77602
77884
  const chunk = 65536;
77603
77885
  let acc = Buffer.alloc(0);
@@ -77605,7 +77887,7 @@ function readCodexRolloutIdentity(path2) {
77605
77887
  let nl = -1;
77606
77888
  while (acc.length < CAP) {
77607
77889
  const buf = Buffer.allocUnsafe(chunk);
77608
- const n = readSync(fd, buf, 0, chunk, pos);
77890
+ const n = readSync2(fd, buf, 0, chunk, pos);
77609
77891
  if (n <= 0) break;
77610
77892
  acc = acc.length === 0 ? buf.subarray(0, n) : Buffer.concat([acc, buf.subarray(0, n)]);
77611
77893
  pos += n;
@@ -77626,7 +77908,7 @@ function readCodexRolloutIdentity(path2) {
77626
77908
  return null;
77627
77909
  } finally {
77628
77910
  if (fd !== void 0) try {
77629
- closeSync(fd);
77911
+ closeSync2(fd);
77630
77912
  } catch {
77631
77913
  }
77632
77914
  }
@@ -77660,7 +77942,7 @@ function codexRolloutsForCwd(cwd, opts = {}) {
77660
77942
  const full = join21(dir, name2);
77661
77943
  let st;
77662
77944
  try {
77663
- st = statSync6(full);
77945
+ st = statSync7(full);
77664
77946
  } catch {
77665
77947
  continue;
77666
77948
  }
@@ -77717,10 +77999,10 @@ function geminiHashesFor(cwd) {
77717
77999
  function readGeminiTranscriptProjectHash(path2) {
77718
78000
  let fd;
77719
78001
  try {
77720
- fd = openSync(path2, "r");
78002
+ fd = openSync2(path2, "r");
77721
78003
  const CAP = 65536;
77722
78004
  const buf = Buffer.allocUnsafe(CAP);
77723
- const n = readSync(fd, buf, 0, CAP, 0);
78005
+ const n = readSync2(fd, buf, 0, CAP, 0);
77724
78006
  const nl = buf.indexOf(10);
77725
78007
  const firstLine = buf.toString("utf8", 0, nl >= 0 && nl < n ? nl : n);
77726
78008
  const o = JSON.parse(firstLine);
@@ -77729,7 +78011,7 @@ function readGeminiTranscriptProjectHash(path2) {
77729
78011
  return null;
77730
78012
  } finally {
77731
78013
  if (fd !== void 0) try {
77732
- closeSync(fd);
78014
+ closeSync2(fd);
77733
78015
  } catch {
77734
78016
  }
77735
78017
  }
@@ -77760,7 +78042,7 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
77760
78042
  const full = join21(chats, name2);
77761
78043
  let st;
77762
78044
  try {
77763
- st = statSync6(full);
78045
+ st = statSync7(full);
77764
78046
  } catch {
77765
78047
  continue;
77766
78048
  }
@@ -77784,9 +78066,9 @@ function opencodeSessionRoots(env2 = process.env, home = homedir4()) {
77784
78066
  function readOpencodeTranscriptDirectory(path2) {
77785
78067
  let fd;
77786
78068
  try {
77787
- fd = openSync(path2, "r");
78069
+ fd = openSync2(path2, "r");
77788
78070
  const buf = Buffer.allocUnsafe(8192);
77789
- const n = readSync(fd, buf, 0, buf.length, 0);
78071
+ const n = readSync2(fd, buf, 0, buf.length, 0);
77790
78072
  const nl = buf.indexOf(10);
77791
78073
  const first = buf.toString("utf8", 0, nl >= 0 && nl < n ? nl : n);
77792
78074
  const o = JSON.parse(first);
@@ -77796,7 +78078,7 @@ function readOpencodeTranscriptDirectory(path2) {
77796
78078
  return null;
77797
78079
  } finally {
77798
78080
  if (fd !== void 0) try {
77799
- closeSync(fd);
78081
+ closeSync2(fd);
77800
78082
  } catch {
77801
78083
  }
77802
78084
  }
@@ -77823,7 +78105,7 @@ function opencodeTranscriptsForCwd(cwd, opts = {}) {
77823
78105
  const full = join21(root, name2);
77824
78106
  let st;
77825
78107
  try {
77826
- st = statSync6(full);
78108
+ st = statSync7(full);
77827
78109
  } catch {
77828
78110
  continue;
77829
78111
  }
@@ -77846,7 +78128,7 @@ init_src5();
77846
78128
  import { readFileSync as readFileSync18, writeFileSync as writeFileSync14 } from "node:fs";
77847
78129
  var NEG = /n['']t|\b(?:not|never|no|none|neither|nor|unrelated|irrelevant|would|might|could|if)\b/i;
77848
78130
  var CITE_GROUP_RE = /\(((?:[^()\n]|\([^()\n]*\)){1,200})\)/g;
77849
- var HANDLE_RE = /\[([a-z0-9][\w-]{0,80})\]|((?:pat|sol|drc|dcause|dfix|dprob|dvuln|prob|claim|err)_[0-9a-f]{6,})/gi;
78131
+ var HANDLE_RE2 = /\[([a-z0-9][\w-]{0,80})\]|((?:pat|sol|drc|dcause|dfix|dprob|dvuln|prob|claim|err)_[0-9a-f]{6,})/gi;
77850
78132
  var PLACEHOLDER_HANDLES = /* @__PURE__ */ new Set([
77851
78133
  "handle",
77852
78134
  "its-handle",
@@ -78065,7 +78347,7 @@ function splitJoinedCause(content, sentence, threadId, dispositions, out2) {
78065
78347
  if (!joined) return content;
78066
78348
  const causeBody = content.slice(joined.index + joined[0].length);
78067
78349
  const fix = content.slice(0, joined.index);
78068
- const fixed = new RegExp(HANDLE_RE.source, "i").exec(fix);
78350
+ const fixed = new RegExp(HANDLE_RE2.source, "i").exec(fix);
78069
78351
  const symptom = fixed && !/^\s*\[/.test(causeBody) ? `${fixed[0]} ` : "";
78070
78352
  const cause = parseCauseTag(`${symptom}${causeBody}`, sentence, threadId, dispositions);
78071
78353
  if (cause) out2.push(cause);
@@ -78073,7 +78355,7 @@ function splitJoinedCause(content, sentence, threadId, dispositions, out2) {
78073
78355
  }
78074
78356
  function parseCauseTag(content, sentence, threadId, dispositions) {
78075
78357
  const body2 = content.replace(/\s+/g, " ").trim();
78076
- const cited = new RegExp(HANDLE_RE.source, "i").exec(body2);
78358
+ const cited = new RegExp(HANDLE_RE2.source, "i").exec(body2);
78077
78359
  const handle2 = cited ? cited[1] ?? cited[2] : void 0;
78078
78360
  const base = { kind: "triage", sentence, ...threadId ? { threadId } : {} };
78079
78361
  if (handle2 && cited) {
@@ -78176,9 +78458,9 @@ function parseInlineTagsWithDispositions(text) {
78176
78458
  const threadMatch = ssM ? ssM.re.exec(content) : null;
78177
78459
  const body2 = content.replace(re, "");
78178
78460
  const handles = [];
78179
- HANDLE_RE.lastIndex = 0;
78461
+ HANDLE_RE2.lastIndex = 0;
78180
78462
  let hh;
78181
- while ((hh = HANDLE_RE.exec(body2)) !== null) {
78463
+ while ((hh = HANDLE_RE2.exec(body2)) !== null) {
78182
78464
  const handle2 = hh[1] ?? hh[2];
78183
78465
  if (!handle2) continue;
78184
78466
  if (isPlaceholderHandle(handle2)) {
@@ -78201,8 +78483,8 @@ function parseInlineTagsWithDispositions(text) {
78201
78483
  }
78202
78484
  if (confirmM || refuteM) {
78203
78485
  const body2 = content.replace(confirmM ? CONFIRM_PREFIX : REFUTE_PREFIX, "");
78204
- HANDLE_RE.lastIndex = 0;
78205
- const h2 = HANDLE_RE.exec(body2);
78486
+ HANDLE_RE2.lastIndex = 0;
78487
+ const h2 = HANDLE_RE2.exec(body2);
78206
78488
  let handle2 = h2 ? h2[1] ?? h2[2] : void 0;
78207
78489
  if (handle2 && isPlaceholderHandle(handle2)) {
78208
78490
  dispositions.placeholderEcho++;
@@ -78210,7 +78492,7 @@ function parseInlineTagsWithDispositions(text) {
78210
78492
  }
78211
78493
  if (handle2) {
78212
78494
  if (refuteM) {
78213
- const reason = body2.replace(new RegExp(HANDLE_RE.source, "gi"), " ").replace(/\s+/g, " ").trim();
78495
+ const reason = body2.replace(new RegExp(HANDLE_RE2.source, "gi"), " ").replace(/\s+/g, " ").trim();
78214
78496
  if (reason.length >= REFUTE_REASON_MIN) out2.push({ kind: "refute", handle: handle2, statement: reason, sentence: sfield });
78215
78497
  else dispositions.refuteTooShort++;
78216
78498
  } else {
@@ -78239,10 +78521,10 @@ function parseInlineTagsWithDispositions(text) {
78239
78521
  const r = deriveFixRationale(sentence, g.index, g.index + g[0].length);
78240
78522
  if (r.length >= FIX_RATIONALE_MIN) fixRationale = r;
78241
78523
  }
78242
- HANDLE_RE.lastIndex = 0;
78524
+ HANDLE_RE2.lastIndex = 0;
78243
78525
  let h;
78244
78526
  let emittedHandle = false;
78245
- while ((h = HANDLE_RE.exec(content)) !== null) {
78527
+ while ((h = HANDLE_RE2.exec(content)) !== null) {
78246
78528
  const handle2 = h[1] ?? h[2];
78247
78529
  if (handle2 && isPlaceholderHandle(handle2)) {
78248
78530
  dispositions.placeholderEcho++;
@@ -78285,20 +78567,20 @@ function parseInlineTagsWithDispositions(text) {
78285
78567
  continue;
78286
78568
  }
78287
78569
  const content = splitJoinedCause(lm[2], sfield, verbThread, dispositions, out2);
78288
- HANDLE_RE.lastIndex = 0;
78289
- const h = HANDLE_RE.exec(content);
78570
+ HANDLE_RE2.lastIndex = 0;
78571
+ const h = HANDLE_RE2.exec(content);
78290
78572
  let handle2 = h ? h[1] ?? h[2] : void 0;
78291
78573
  if (handle2 && isPlaceholderHandle(handle2)) {
78292
78574
  dispositions.placeholderEcho++;
78293
78575
  handle2 = void 0;
78294
78576
  }
78295
78577
  if (handle2) {
78296
- const inGroup = content.replace(new RegExp(HANDLE_RE.source, "gi"), " ").replace(/\s+/g, " ").trim();
78578
+ const inGroup = content.replace(new RegExp(HANDLE_RE2.source, "gi"), " ").replace(/\s+/g, " ").trim();
78297
78579
  const r = inGroup.length >= FIX_RATIONALE_MIN ? inGroup : deriveFixRationale(sentence, lm.index, lm.index + lm[0].length);
78298
78580
  let emitted = false;
78299
- HANDLE_RE.lastIndex = 0;
78581
+ HANDLE_RE2.lastIndex = 0;
78300
78582
  let hh;
78301
- while ((hh = HANDLE_RE.exec(content)) !== null) {
78583
+ while ((hh = HANDLE_RE2.exec(content)) !== null) {
78302
78584
  const hcap = hh[1] ?? hh[2];
78303
78585
  if (hcap) {
78304
78586
  emitted = true;
@@ -78327,8 +78609,8 @@ function parseInlineTagsWithDispositions(text) {
78327
78609
  while ((vm = pass.re.exec(sentence)) !== null) {
78328
78610
  if (citeMatched.has(vm.index)) continue;
78329
78611
  const body2 = vm[1];
78330
- HANDLE_RE.lastIndex = 0;
78331
- const h = HANDLE_RE.exec(body2);
78612
+ HANDLE_RE2.lastIndex = 0;
78613
+ const h = HANDLE_RE2.exec(body2);
78332
78614
  let handle2 = h ? h[1] ?? h[2] : void 0;
78333
78615
  if (handle2 && isPlaceholderHandle(handle2)) {
78334
78616
  dispositions.placeholderEcho++;
@@ -78339,7 +78621,7 @@ function parseInlineTagsWithDispositions(text) {
78339
78621
  continue;
78340
78622
  }
78341
78623
  if (pass.refute) {
78342
- const reason = body2.replace(new RegExp(HANDLE_RE.source, "gi"), " ").replace(/\s+/g, " ").trim();
78624
+ const reason = body2.replace(new RegExp(HANDLE_RE2.source, "gi"), " ").replace(/\s+/g, " ").trim();
78343
78625
  if (reason.length >= REFUTE_REASON_MIN) out2.push({ kind: "refute", handle: handle2, statement: reason, sentence: sfield });
78344
78626
  else dispositions.refuteTooShort++;
78345
78627
  } else {
@@ -78429,10 +78711,10 @@ function parseInlineTagsWithDispositions(text) {
78429
78711
  const isFailure = a[1].toLowerCase() === "failed";
78430
78712
  let refuteHandles;
78431
78713
  if (isFailure) {
78432
- HANDLE_RE.lastIndex = 0;
78714
+ HANDLE_RE2.lastIndex = 0;
78433
78715
  const hs = [];
78434
78716
  let hm;
78435
- while ((hm = HANDLE_RE.exec(statement)) !== null) {
78717
+ while ((hm = HANDLE_RE2.exec(statement)) !== null) {
78436
78718
  const h = hm[1] ?? hm[2];
78437
78719
  if (h && !hs.includes(h)) hs.push(h);
78438
78720
  }
@@ -78451,8 +78733,8 @@ function parseInlineTagsWithDispositions(text) {
78451
78733
  let pm;
78452
78734
  while ((pm = PATTERN_RE.exec(sentence)) !== null) {
78453
78735
  const body2 = pm[1].trim();
78454
- HANDLE_RE.lastIndex = 0;
78455
- const ph = HANDLE_RE.exec(body2);
78736
+ HANDLE_RE2.lastIndex = 0;
78737
+ const ph = HANDLE_RE2.exec(body2);
78456
78738
  const handle2 = ph ? ph[1] ?? ph[2] : void 0;
78457
78739
  if (handle2) {
78458
78740
  out2.push({ kind: "pattern", handle: handle2, sentence: sfield });
@@ -80244,7 +80526,7 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
80244
80526
  // src/retrieval-stack.ts
80245
80527
  init_src();
80246
80528
  import { execFileSync as execFileSync4 } from "node:child_process";
80247
- import { existsSync as existsSync23, readFileSync as readFileSync23, statSync as statSync7 } from "node:fs";
80529
+ import { existsSync as existsSync23, readFileSync as readFileSync23, statSync as statSync8 } from "node:fs";
80248
80530
  import { homedir as homedir6 } from "node:os";
80249
80531
  import { join as join26 } from "node:path";
80250
80532
  var RETRIEVAL_STACK_CAP = 24;
@@ -80764,7 +81046,7 @@ function readDirectDependencies(root) {
80764
81046
  const p = join26(root, c.file);
80765
81047
  if (!existsSync23(p)) continue;
80766
81048
  try {
80767
- const s = statSync7(p);
81049
+ const s = statSync8(p);
80768
81050
  stamps.push(`${c.file}:${s.mtimeMs}:${s.size}`);
80769
81051
  } catch {
80770
81052
  continue;
@@ -80848,7 +81130,7 @@ function scanManifests(root) {
80848
81130
  for (const rel of paths) {
80849
81131
  const abs = join26(root, rel);
80850
81132
  try {
80851
- const s = statSync7(abs);
81133
+ const s = statSync8(abs);
80852
81134
  stamps.push(`${rel}:${s.mtimeMs}:${s.size}`);
80853
81135
  texts.set(rel, readFileSync23(abs, "utf8"));
80854
81136
  } catch {
@@ -83456,7 +83738,7 @@ function createWatchBreaker(deps) {
83456
83738
  }
83457
83739
 
83458
83740
  // src/engine.ts
83459
- var DAEMON_VERSION = true ? "2.0.21-dev.3952" : "2.0.0-alpha.0";
83741
+ var DAEMON_VERSION = true ? "2.0.21-dev.3975" : "2.0.0-alpha.0";
83460
83742
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
83461
83743
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
83462
83744
  var GIT_OP_MUTE_MS = 4e3;
@@ -83468,7 +83750,7 @@ var CODEX_SWEEP_LOOKBACK_MS = 10 * 6e4;
83468
83750
  function appendIdentityAudit(path2, record2, line) {
83469
83751
  if (!record2.accepted && record2.score <= 0) return;
83470
83752
  try {
83471
- if (existsSync28(path2) && statSync8(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
83753
+ if (existsSync28(path2) && statSync9(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
83472
83754
  renameSync4(path2, `${path2}.1`);
83473
83755
  }
83474
83756
  appendFileSync4(path2, line);
@@ -83642,7 +83924,7 @@ function createWorkspaceEngine(opts) {
83642
83924
  }
83643
83925
  let size = 0;
83644
83926
  try {
83645
- size = statSync8(path2).size;
83927
+ size = statSync9(path2).size;
83646
83928
  } catch {
83647
83929
  }
83648
83930
  lastActivityTs = Date.now();
@@ -91203,6 +91485,7 @@ async function startMultiDaemon(opts = {}) {
91203
91485
  app.post("/api/message", (c) => forward(c, cwdOf, { affinity: "follow" }));
91204
91486
  app.post("/api/session-end", (c) => forward(c, cwdOf, { affinity: "follow" }));
91205
91487
  app.post("/api/context-inject", (c) => forward(c, cwdOf, { affinity: "follow" }));
91488
+ app.post("/api/context-delta", (c) => forward(c, cwdOf, { affinity: "follow" }));
91206
91489
  app.post("/api/statusline", async (c) => {
91207
91490
  const body2 = await c.req.json().catch(() => ({}));
91208
91491
  const dir = statuslineDir(body2);
@@ -92804,7 +93087,7 @@ function shouldUseOAuthLogin(flags2, env2 = process.env) {
92804
93087
  import { spawnSync as spawnSync2 } from "node:child_process";
92805
93088
 
92806
93089
  // src/codex-runtime.ts
92807
- import { readdirSync as readdirSync12, statSync as statSync9 } from "node:fs";
93090
+ import { readdirSync as readdirSync12, statSync as statSync10 } from "node:fs";
92808
93091
  import { join as join42 } from "node:path";
92809
93092
  function resolveCodexExecutable(options = {}) {
92810
93093
  const platform = options.platform ?? process.platform;
@@ -92812,7 +93095,7 @@ function resolveCodexExecutable(options = {}) {
92812
93095
  if (platform !== "win32") return "codex";
92813
93096
  const fileTime = (path2) => {
92814
93097
  try {
92815
- const s = statSync9(path2);
93098
+ const s = statSync10(path2);
92816
93099
  return s.isFile() ? s.mtimeMs : null;
92817
93100
  } catch {
92818
93101
  return null;
@@ -92965,7 +93248,7 @@ async function diagnoseInstallation(cfg, dependencies) {
92965
93248
 
92966
93249
  // src/codex-doctor.ts
92967
93250
  import { spawn as spawn4 } from "node:child_process";
92968
- import { readFileSync as readFileSync37, statSync as statSync10 } from "node:fs";
93251
+ import { readFileSync as readFileSync37, statSync as statSync11 } from "node:fs";
92969
93252
  import { join as join44 } from "node:path";
92970
93253
  import { createInterface } from "node:readline";
92971
93254
 
@@ -93064,6 +93347,10 @@ try {
93064
93347
  }
93065
93348
  } catch {}
93066
93349
  let receipt = null;
93350
+ // CTX-delta: the body this session was last handed sits beside its receipt, so
93351
+ // a changed snapshot can go out as only what changed (the daemon renders it).
93352
+ const bodyPath = statePath && statePath.replace(/\.json$/, '.body.md');
93353
+ let emittedBody = null;
93067
93354
  const post = async (endpoint, relay = false) => {
93068
93355
  try {
93069
93356
  const response = await fetch('http://127.0.0.1:' + port + '/api/' + endpoint, {
@@ -93097,14 +93384,44 @@ try {
93097
93384
  // Receipt is local to this graph + session, survives daemon restarts, and
93098
93385
  // records stdout emission, not a server's intention to send a response.
93099
93386
  if (event === 'SessionStart' || previous.hash !== digest) {
93100
- contexts.push('Errata loaded the maintained local workspace context. This block REPLACES any earlier errata context block in this conversation. It is the latest saved snapshot; the daemon maintains it as work proceeds.\n\n' + body);
93101
- if (!/^(0|off|false|no)$/i.test((process.env.ERRATA_RECALL_CARD || '').trim())) {
93387
+ const normalized = body.replace(/\r\n?/g, '\n');
93388
+ // Every SessionStart (startup, resume, compact, clear) sends the whole
93389
+ // block: the window may no longer hold the last one.
93390
+ let delta = null;
93391
+ if (event !== 'SessionStart' && previous.hash && bodyPath) {
93392
+ let prior = '';
93393
+ try { prior = boundedRead(bodyPath, 512 * 1024); } catch {}
93394
+ if (prior && hash(prior).slice(0, 16) === previous.hash) {
93395
+ try {
93396
+ const response = await fetch('http://127.0.0.1:' + port + '/api/context-delta', {
93397
+ method: 'POST', headers: { 'Content-Type': 'application/json' },
93398
+ body: JSON.stringify({ cwd: payload.cwd, hook_event_name: event, prev: prior, next: normalized }),
93399
+ signal: AbortSignal.timeout(2000),
93400
+ });
93401
+ if (response.ok) delta = await response.json();
93402
+ } catch { /* no daemon: the whole block goes, as before */ }
93403
+ }
93404
+ }
93405
+ if (delta && delta.unchanged === true) {
93406
+ // Only bookkeeping moved: nothing to send, but this snapshot is now what the window holds.
93102
93407
  try {
93103
- const card = JSON.parse(boundedRead(join(workspaceRoot, '.errata', 'context-card.json'), 128 * 1024));
93104
- if (card.hash === digest && typeof card.line === 'string' && card.line) messages.push(card.line);
93105
- } catch { /* Never show a card for a different snapshot. */ }
93408
+ mkdirSync(stateDir, { recursive: true });
93409
+ writeFileSync(statePath, JSON.stringify({ hash: digest, at: Date.now() }), { mode: 0o600 });
93410
+ writeFileSync(bodyPath, normalized, { mode: 0o600 });
93411
+ } catch { /* the next change just goes whole */ }
93412
+ } else {
93413
+ contexts.push(delta && typeof delta.delta === 'string' && delta.delta
93414
+ ? delta.delta
93415
+ : 'Errata loaded the maintained local workspace context. This block REPLACES any earlier errata context block in this conversation. It is the latest saved snapshot; the daemon maintains it as work proceeds.\n\n' + body);
93416
+ if (!/^(0|off|false|no)$/i.test((process.env.ERRATA_RECALL_CARD || '').trim())) {
93417
+ try {
93418
+ const card = JSON.parse(boundedRead(join(workspaceRoot, '.errata', 'context-card.json'), 128 * 1024));
93419
+ if (card.hash === digest && typeof card.line === 'string' && card.line) messages.push(card.line);
93420
+ } catch { /* Never show a card for a different snapshot. */ }
93421
+ }
93422
+ receipt = { hash: digest, at: Date.now() };
93423
+ emittedBody = normalized;
93106
93424
  }
93107
- receipt = { hash: digest, at: Date.now() };
93108
93425
  }
93109
93426
  } else if (event === 'SessionStart' || !previous.unavailable) {
93110
93427
  messages.push('errata: workspace priors are unavailable; run errata doctor in this checkout.');
@@ -93126,6 +93443,7 @@ try {
93126
93443
  const temp = statePath + '.' + process.pid + '.tmp';
93127
93444
  writeFileSync(temp, JSON.stringify(receipt), { mode: 0o600 });
93128
93445
  renameSync(temp, statePath);
93446
+ if (emittedBody !== null && bodyPath) writeFileSync(bodyPath, emittedBody, { mode: 0o600 });
93129
93447
  } catch { /* Read-only workspace: retry next time rather than drop context. */ }
93130
93448
  }
93131
93449
  resolve();
@@ -93212,7 +93530,7 @@ function inspectCodexContext(cwd) {
93212
93530
  const root = checkoutRootOf(nearestGitRoot(cwd) ?? cwd);
93213
93531
  try {
93214
93532
  const file2 = join44(root, ".errata", "context.md");
93215
- if (statSync10(file2).size <= 128 * 1024 && readFileSync37(file2, "utf8").trim()) {
93533
+ if (statSync11(file2).size <= 128 * 1024 && readFileSync37(file2, "utf8").trim()) {
93216
93534
  return { id: "codex_context", status: "pass", detail: "Saved workspace context is readable by the relay; this does not prove live daemon freshness" };
93217
93535
  }
93218
93536
  } catch {
@@ -94353,7 +94671,7 @@ function describeStatusLineOutcome(outcome) {
94353
94671
 
94354
94672
  // src/claude-mods.ts
94355
94673
  import { createHash as createHash21 } from "node:crypto";
94356
- import { cpSync as cpSync3, existsSync as existsSync39, mkdirSync as mkdirSync12, readFileSync as readFileSync41, readdirSync as readdirSync14, rmSync as rmSync4, statSync as statSync11, writeFileSync as writeFileSync30 } from "node:fs";
94674
+ import { cpSync as cpSync3, existsSync as existsSync39, mkdirSync as mkdirSync12, readFileSync as readFileSync41, readdirSync as readdirSync14, rmSync as rmSync4, statSync as statSync12, writeFileSync as writeFileSync30 } from "node:fs";
94357
94675
  import { delimiter as delimiter2, dirname as dirname15, join as join48, relative as relative7, resolve as resolve9, sep as sep5 } from "node:path";
94358
94676
  import { fileURLToPath as fileURLToPath3 } from "node:url";
94359
94677
  var CLAUDE_PLUGIN_DIRS_ENV = "CLAUDE_CODE_PLUGIN_DIRS";
@@ -94371,7 +94689,7 @@ function listFiles(root, dir = root) {
94371
94689
  for (const name2 of readdirSync14(dir)) {
94372
94690
  const abs = join48(dir, name2);
94373
94691
  if (isEngineOwned(relative7(root, abs))) continue;
94374
- if (statSync11(abs).isDirectory()) out2.push(...listFiles(root, abs));
94692
+ if (statSync12(abs).isDirectory()) out2.push(...listFiles(root, abs));
94375
94693
  else out2.push(abs);
94376
94694
  }
94377
94695
  return out2;
@@ -96909,10 +97227,10 @@ function spawnDaemonDetached(options = {}) {
96909
97227
  try {
96910
97228
  const logPath = daemonLogPath();
96911
97229
  try {
96912
- if (statSync12(logPath).size > 5 * 1024 * 1024) renameSync7(logPath, `${logPath}.1`);
97230
+ if (statSync13(logPath).size > 5 * 1024 * 1024) renameSync7(logPath, `${logPath}.1`);
96913
97231
  } catch {
96914
97232
  }
96915
- out2 = openSync2(logPath, "a");
97233
+ out2 = openSync3(logPath, "a");
96916
97234
  } catch {
96917
97235
  }
96918
97236
  spawn5(cmd2, args2, {
@@ -96930,7 +97248,7 @@ function spawnDaemonDetached(options = {}) {
96930
97248
  NODE_OPTIONS: `${daemonEnv["NODE_OPTIONS"] ?? ""} --max-old-space-size=${DAEMON_MAX_HEAP_MB}`.trim()
96931
97249
  }
96932
97250
  }).unref();
96933
- if (out2 !== "ignore") closeSync2(out2);
97251
+ if (out2 !== "ignore") closeSync3(out2);
96934
97252
  }
96935
97253
  function ensureSingletonRunning(options = {}) {
96936
97254
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.21-dev.3952",
3
+ "version": "2.0.21-dev.3975",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -29374,11 +29374,16 @@ var RECALL_FIRST_BODY = "Before investigating any bug or error, your FIRST tool
29374
29374
  var RECALL_FIRST_BLOCK = `${RECALL_FIRST_HEADER}
29375
29375
 
29376
29376
  ${RECALL_FIRST_BODY}`;
29377
+ var PROMPT_INTENT_CUE = "new request \u2192 state it first:\n```errata-intent\nintent: <this request, in your words>\n```\nTag ALL project work, not just bugs \u2014 features, UX, refactors, research: problems you hit (even in code you just wrote) [!\u2026], decisions (constraint: why), approaches (tried: \u2026)/(failed: \u2026), the area (domain: \u2026). Restate tags in your final reply.";
29378
+ var PROMPT_RECUE = `errata (context block above unchanged): ${PROMPT_INTENT_CUE}`;
29377
29379
 
29378
29380
  // ../../packages/context-writer/src/select-durable-memory.ts
29379
29381
  init_src2();
29380
29382
  init_src();
29381
29383
 
29384
+ // ../../packages/context-writer/src/delta.ts
29385
+ var DELTA_MAX_FRACTION = 2 / 3;
29386
+
29382
29387
  // src/pass-worker.ts
29383
29388
  init_src3();
29384
29389
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "errata-context",
3
- "version": "2.0.21-dev.3952",
3
+ "version": "2.0.21-dev.3975",
4
4
  "description": "A minimal 3D view of loaded Errata priors and recent graph bursts.",
5
5
  "author": {
6
6
  "name": "inErrata"
@@ -1,4 +1,4 @@
1
- 3d215f693e5b01accb54af90e70aad32c608940d63a1b3beb8854da13d940cd4 .codex-plugin/plugin.json
1
+ a9eb62817aef08b34545572e5b3797a0f0234fd7cdd80b6bac7ccfe295b4207b .codex-plugin/plugin.json
2
2
  a7bebae9fb01c838d6c75fc784129e28be571233fa66ff5ee8039b574f35ccf7 assets/icon.png
3
3
  fc38b64e4df1e0b72c35764bef6c4c05430d97c9009ad0ecc8a9e75b4deab232 configure-local.mjs
4
4
  73dc6028b3b070257c7c31f252d11e55a9e096f4aed0f187f10cb21716e1e6d7 dist/client.js