@inerrata-corporation/errata 2.0.17-dev.3537 → 2.0.17-dev.3549

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.
@@ -15796,6 +15796,22 @@ var init_project_wire_attrs = __esm({
15796
15796
  }
15797
15797
  });
15798
15798
 
15799
+ // ../../packages/shared/src/edit-placeholder.ts
15800
+ function isEditPlaceholderSolution(node) {
15801
+ if (node.label !== "Solution") return false;
15802
+ const text = node.description.trim().toLowerCase();
15803
+ if (text.startsWith(AUTO_MINT_PREFIX)) return true;
15804
+ return /^fix for [^\r\n]+ \(episode_[^)]+\)$/.test(text) && !(typeof node.attrs?.["rationale"] === "string" && node.attrs["rationale"].trim());
15805
+ }
15806
+ var AUTO_MINT_PREFIX, EDIT_PLACEHOLDER_RETIREMENT;
15807
+ var init_edit_placeholder = __esm({
15808
+ "../../packages/shared/src/edit-placeholder.ts"() {
15809
+ "use strict";
15810
+ AUTO_MINT_PREFIX = "addressed by an edit to ";
15811
+ EDIT_PLACEHOLDER_RETIREMENT = "edit-placeholder-solution";
15812
+ }
15813
+ });
15814
+
15799
15815
  // ../../packages/shared/src/index.ts
15800
15816
  var init_src = __esm({
15801
15817
  "../../packages/shared/src/index.ts"() {
@@ -15827,6 +15843,7 @@ var init_src = __esm({
15827
15843
  init_triage_canon();
15828
15844
  init_history_text();
15829
15845
  init_project_wire_attrs();
15846
+ init_edit_placeholder();
15830
15847
  }
15831
15848
  });
15832
15849
 
@@ -16331,6 +16348,54 @@ function repairSessionEvidence(input, aliases = /* @__PURE__ */ new Map()) {
16331
16348
  return repaired;
16332
16349
  }
16333
16350
 
16351
+ // ../../packages/local-graph/src/edit-placeholder-retirement.ts
16352
+ init_src();
16353
+ var EDIT_PLACEHOLDER_FLOOR_KEY = "edit-placeholder-retirement-1";
16354
+ function installEditPlaceholderRetirement(db) {
16355
+ if (db.prepare("SELECT value FROM store_meta WHERE key=?").get(EDIT_PLACEHOLDER_FLOOR_KEY)) return;
16356
+ const timestamp = `CAST(unixepoch('subsec') * 1000 AS INTEGER)`;
16357
+ const placeholder = (n) => `(${n}.label='Solution' AND (
16358
+ lower(trim(${n}.description)) LIKE '${AUTO_MINT_PREFIX}%'
16359
+ OR (lower(trim(${n}.description)) GLOB 'fix for * (episode_*)'
16360
+ AND instr(${n}.description,char(10))=0 AND instr(${n}.description,char(13))=0
16361
+ AND trim(coalesce(json_extract(${n}.attrs_json,'$.rationale'),''))='')))`;
16362
+ const contaminated = (n) => `(${n}.label='Claim' AND json_extract(${n}.attrs_json,'$.abstractionLevel')>=2
16363
+ AND EXISTS(SELECT 1 FROM json_each(${n}.attrs_json,'$.members') m JOIN nodes s ON s.id=m.value
16364
+ WHERE ${placeholder("s")} OR json_extract(s.attrs_json,'$.retiredReason')='${EDIT_PLACEHOLDER_RETIREMENT}'))`;
16365
+ const retire = (where, reason) => `UPDATE nodes SET valid_to=coalesce(valid_to,${timestamp}),
16366
+ attrs_json=json_set(attrs_json,'$.retiredReason','${reason}','$.retiredAt',${timestamp})
16367
+ WHERE (valid_to IS NULL OR coalesce(json_extract(attrs_json,'$.retiredReason'),'')<>'${reason}') AND (${where});`;
16368
+ const closeEdges = (where) => `UPDATE edges SET valid_to=${timestamp} WHERE valid_to IS NULL AND (${where});`;
16369
+ const retired = `(SELECT id FROM nodes WHERE json_extract(attrs_json,'$.retiredReason') IN ('${EDIT_PLACEHOLDER_RETIREMENT}','edit-placeholder-member'))`;
16370
+ const markParents = `UPDATE nodes SET attrs_json=json_set(attrs_json,'$.retiredEditPlaceholder',json('true'))
16371
+ WHERE label='Problem' AND coalesce(json_extract(attrs_json,'$.retiredEditPlaceholder'),0)<>1
16372
+ AND id IN (SELECT e.from_id FROM edges e JOIN nodes s ON s.id=e.to_id WHERE e.type='SOLVED_BY'
16373
+ AND s.label='Solution' AND json_extract(s.attrs_json,'$.retiredReason')='${EDIT_PLACEHOLDER_RETIREMENT}');`;
16374
+ db.transaction(() => {
16375
+ db.exec(retire(placeholder("nodes"), EDIT_PLACEHOLDER_RETIREMENT));
16376
+ db.exec(retire(contaminated("nodes"), "edit-placeholder-member"));
16377
+ db.exec(markParents);
16378
+ db.exec(closeEdges(`from_id IN ${retired} OR to_id IN ${retired}`));
16379
+ for (const operation of ["INSERT", "UPDATE OF label,description,attrs_json,valid_to"]) {
16380
+ const suffix = operation.startsWith("INSERT") ? "insert" : "update";
16381
+ db.exec(`CREATE TRIGGER edit_placeholder_nodes_${suffix} AFTER ${operation} ON nodes
16382
+ WHEN NEW.valid_to IS NULL AND (${placeholder("NEW")} OR ${contaminated("NEW")}) BEGIN
16383
+ ${retire(`id=NEW.id AND label='Solution'`, EDIT_PLACEHOLDER_RETIREMENT)}
16384
+ ${retire(contaminated("nodes"), "edit-placeholder-member")}
16385
+ ${markParents}
16386
+ ${closeEdges(`from_id IN ${retired} OR to_id IN ${retired}`)}
16387
+ END;`);
16388
+ db.exec(`CREATE TRIGGER edit_placeholder_edges_${suffix} AFTER ${suffix.toUpperCase()} ON edges
16389
+ WHEN NEW.valid_to IS NULL AND EXISTS(SELECT 1 FROM nodes n WHERE n.id IN (NEW.from_id,NEW.to_id)
16390
+ AND json_extract(n.attrs_json,'$.retiredReason') IN ('${EDIT_PLACEHOLDER_RETIREMENT}','edit-placeholder-member')) BEGIN
16391
+ ${markParents}
16392
+ ${closeEdges("id=NEW.id")}
16393
+ END;`);
16394
+ }
16395
+ db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(EDIT_PLACEHOLDER_FLOOR_KEY, "installed");
16396
+ });
16397
+ }
16398
+
16334
16399
  // ../../packages/local-graph/src/store.ts
16335
16400
  var LOCAL_RULE_OVERRIDES = {
16336
16401
  ANCHORED_AT: {
@@ -16582,6 +16647,7 @@ var SqliteGraphStore = class {
16582
16647
  }
16583
16648
  this.db.exec(TEMPORAL_INDEX_SQL);
16584
16649
  installHistoryCacheFloor(this.db);
16650
+ installEditPlaceholderRetirement(this.db);
16585
16651
  if (!this.db.prepare("SELECT value FROM store_meta WHERE key = ?").get(SESSION_REPAIR_KEY)) {
16586
16652
  this.db.transaction(() => {
16587
16653
  this.repairSessionAliases();
@@ -17128,8 +17194,8 @@ var SqliteGraphStore = class {
17128
17194
  qname: typeof r.qname === "string" ? r.qname : null
17129
17195
  }));
17130
17196
  }
17131
- findAllVersionsByLabel(label) {
17132
- const rows = this.stmts.findByLabelAll.all(label);
17197
+ findAllVersionsByLabel(label, attribute) {
17198
+ const rows = attribute ? this.db.prepare("SELECT * FROM nodes WHERE label = ? AND json_extract(attrs_json, ?) = ?").all(label, `$.${attribute.path}`, attribute.value) : this.stmts.findByLabelAll.all(label);
17133
17199
  return rows.map(rowToNode);
17134
17200
  }
17135
17201
  searchNodes(opts) {
@@ -17573,8 +17639,8 @@ init_src();
17573
17639
  init_src();
17574
17640
 
17575
17641
  // ../../packages/local-graph/src/design-problem.ts
17642
+ init_src();
17576
17643
  var RECURRENCE_DEBOUNCE_MS = 60 * 60 * 1e3;
17577
- var AUTO_MINT_PREFIX = "addressed by an edit to ";
17578
17644
 
17579
17645
  // ../../packages/local-graph/src/intent.ts
17580
17646
  init_src();
@@ -17589,6 +17655,7 @@ var STATEMENT_PATH_RE = new RegExp(
17589
17655
 
17590
17656
  // ../../packages/local-graph/src/percolate.ts
17591
17657
  init_src2();
17658
+ init_src();
17592
17659
  var PERCOLATING_LABELS = ["Claim", "Problem", "Solution"];
17593
17660
  var PERCOLATING_EDGES = ["CAUSED_BY", "SOLVED_BY", "CONTRADICTS"];
17594
17661
  var PERCOLATING_DRIFT_EDGES = ["CONTINUES", "REVEALED_BY", "SUPERSEDED_BY", "SPLIT_INTO"];
@@ -17610,6 +17677,10 @@ function percolate(l1, l2, opts) {
17610
17677
  l2.transaction(() => {
17611
17678
  for (const label of PERCOLATING_LABELS) {
17612
17679
  for (const n of l1.findNodesByLabel(label)) {
17680
+ if (isEditPlaceholderSolution(n) || n.attrs["retiredReason"]) {
17681
+ result.nodesSkipped++;
17682
+ continue;
17683
+ }
17613
17684
  if (n.label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) continue;
17614
17685
  if (n.attrs["source"] === "cloud") {
17615
17686
  const raw = l2.getMeta?.(`history-correction:${String(n.attrs["cloudNodeId"] ?? n.id)}`);
@@ -18213,6 +18284,7 @@ function induceAbstractions(l2, opts) {
18213
18284
  const ids = /* @__PURE__ */ new Set();
18214
18285
  for (const label of PERCOLATING_LABELS) {
18215
18286
  for (const n of l2.findNodesByLabel(label)) {
18287
+ if (isEditPlaceholderSolution(n) || n.attrs["retiredReason"] || n.validTo != null) continue;
18216
18288
  if (Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) >= ABSTRACTION_LEVEL.PRINCIPLE) {
18217
18289
  continue;
18218
18290
  }
@@ -18410,6 +18482,7 @@ function buildContextIngest(store, profile, daemonVersion, ignorePatterns = [],
18410
18482
 
18411
18483
  // src/instance-ingest.ts
18412
18484
  init_src();
18485
+ init_src();
18413
18486
  init_src2();
18414
18487
 
18415
18488
  // ../../packages/privacy-edge/src/ontology.ts
@@ -19742,7 +19815,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19742
19815
  semanticEndpoints.set(n.id, contributedWireId(n, opts.destinationKey));
19743
19816
  continue;
19744
19817
  }
19745
- if (label === "Solution" && n.description.startsWith(AUTO_MINT_PREFIX)) {
19818
+ if (isEditPlaceholderSolution(n)) {
19746
19819
  composition.autoMint++;
19747
19820
  continue;
19748
19821
  }
package/errata.mjs CHANGED
@@ -17479,6 +17479,22 @@ var init_project_wire_attrs = __esm({
17479
17479
  }
17480
17480
  });
17481
17481
 
17482
+ // ../../packages/shared/src/edit-placeholder.ts
17483
+ function isEditPlaceholderSolution(node2) {
17484
+ if (node2.label !== "Solution") return false;
17485
+ const text = node2.description.trim().toLowerCase();
17486
+ if (text.startsWith(AUTO_MINT_PREFIX)) return true;
17487
+ return /^fix for [^\r\n]+ \(episode_[^)]+\)$/.test(text) && !(typeof node2.attrs?.["rationale"] === "string" && node2.attrs["rationale"].trim());
17488
+ }
17489
+ var AUTO_MINT_PREFIX, EDIT_PLACEHOLDER_RETIREMENT;
17490
+ var init_edit_placeholder = __esm({
17491
+ "../../packages/shared/src/edit-placeholder.ts"() {
17492
+ "use strict";
17493
+ AUTO_MINT_PREFIX = "addressed by an edit to ";
17494
+ EDIT_PLACEHOLDER_RETIREMENT = "edit-placeholder-solution";
17495
+ }
17496
+ });
17497
+
17482
17498
  // ../../packages/shared/src/index.ts
17483
17499
  var src_exports = {};
17484
17500
  __export(src_exports, {
@@ -17495,6 +17511,7 @@ __export(src_exports, {
17495
17511
  ANCHOR_LABEL_QNAME_RE: () => ANCHOR_LABEL_QNAME_RE,
17496
17512
  ANCHOR_REFUSAL_REASONS: () => ANCHOR_REFUSAL_REASONS,
17497
17513
  ANCHOR_SYMBOL_KINDS: () => ANCHOR_SYMBOL_KINDS,
17514
+ AUTO_MINT_PREFIX: () => AUTO_MINT_PREFIX,
17498
17515
  BELIEF_EDGES: () => BELIEF_EDGES,
17499
17516
  BRIDGE_EDGES: () => BRIDGE_EDGES,
17500
17517
  CAUSAL_EDGES: () => CAUSAL_EDGES,
@@ -17516,6 +17533,7 @@ __export(src_exports, {
17516
17533
  EDGE_CONDUCTANCE_OVERRIDES: () => EDGE_CONDUCTANCE_OVERRIDES,
17517
17534
  EDGE_RULES: () => EDGE_RULES,
17518
17535
  EDGE_WEIGHT: () => EDGE_WEIGHT,
17536
+ EDIT_PLACEHOLDER_RETIREMENT: () => EDIT_PLACEHOLDER_RETIREMENT,
17519
17537
  EVIDENCE_EDGES: () => EVIDENCE_EDGES,
17520
17538
  FILE_ANCHOR_QNAME: () => FILE_ANCHOR_QNAME,
17521
17539
  GIT_EDGES: () => GIT_EDGES,
@@ -17612,6 +17630,7 @@ __export(src_exports, {
17612
17630
  isCloudWritableNodeLabel: () => isCloudWritableNodeLabel,
17613
17631
  isCodeLabel: () => isCodeLabel,
17614
17632
  isContextLabel: () => isContextLabel,
17633
+ isEditPlaceholderSolution: () => isEditPlaceholderSolution,
17615
17634
  isInferredSource: () => isInferredSource,
17616
17635
  isManifestPath: () => isManifestPath,
17617
17636
  isMembraneSaltedId: () => isMembraneSaltedId,
@@ -17709,6 +17728,7 @@ var init_src = __esm({
17709
17728
  init_triage_canon();
17710
17729
  init_history_text();
17711
17730
  init_project_wire_attrs();
17731
+ init_edit_placeholder();
17712
17732
  }
17713
17733
  });
17714
17734
 
@@ -18278,6 +18298,60 @@ var init_session_evidence = __esm({
18278
18298
  }
18279
18299
  });
18280
18300
 
18301
+ // ../../packages/local-graph/src/edit-placeholder-retirement.ts
18302
+ function installEditPlaceholderRetirement(db) {
18303
+ if (db.prepare("SELECT value FROM store_meta WHERE key=?").get(EDIT_PLACEHOLDER_FLOOR_KEY)) return;
18304
+ const timestamp = `CAST(unixepoch('subsec') * 1000 AS INTEGER)`;
18305
+ const placeholder = (n) => `(${n}.label='Solution' AND (
18306
+ lower(trim(${n}.description)) LIKE '${AUTO_MINT_PREFIX}%'
18307
+ OR (lower(trim(${n}.description)) GLOB 'fix for * (episode_*)'
18308
+ AND instr(${n}.description,char(10))=0 AND instr(${n}.description,char(13))=0
18309
+ AND trim(coalesce(json_extract(${n}.attrs_json,'$.rationale'),''))='')))`;
18310
+ const contaminated = (n) => `(${n}.label='Claim' AND json_extract(${n}.attrs_json,'$.abstractionLevel')>=2
18311
+ AND EXISTS(SELECT 1 FROM json_each(${n}.attrs_json,'$.members') m JOIN nodes s ON s.id=m.value
18312
+ WHERE ${placeholder("s")} OR json_extract(s.attrs_json,'$.retiredReason')='${EDIT_PLACEHOLDER_RETIREMENT}'))`;
18313
+ const retire = (where, reason) => `UPDATE nodes SET valid_to=coalesce(valid_to,${timestamp}),
18314
+ attrs_json=json_set(attrs_json,'$.retiredReason','${reason}','$.retiredAt',${timestamp})
18315
+ WHERE (valid_to IS NULL OR coalesce(json_extract(attrs_json,'$.retiredReason'),'')<>'${reason}') AND (${where});`;
18316
+ const closeEdges = (where) => `UPDATE edges SET valid_to=${timestamp} WHERE valid_to IS NULL AND (${where});`;
18317
+ const retired = `(SELECT id FROM nodes WHERE json_extract(attrs_json,'$.retiredReason') IN ('${EDIT_PLACEHOLDER_RETIREMENT}','edit-placeholder-member'))`;
18318
+ const markParents = `UPDATE nodes SET attrs_json=json_set(attrs_json,'$.retiredEditPlaceholder',json('true'))
18319
+ WHERE label='Problem' AND coalesce(json_extract(attrs_json,'$.retiredEditPlaceholder'),0)<>1
18320
+ AND id IN (SELECT e.from_id FROM edges e JOIN nodes s ON s.id=e.to_id WHERE e.type='SOLVED_BY'
18321
+ AND s.label='Solution' AND json_extract(s.attrs_json,'$.retiredReason')='${EDIT_PLACEHOLDER_RETIREMENT}');`;
18322
+ db.transaction(() => {
18323
+ db.exec(retire(placeholder("nodes"), EDIT_PLACEHOLDER_RETIREMENT));
18324
+ db.exec(retire(contaminated("nodes"), "edit-placeholder-member"));
18325
+ db.exec(markParents);
18326
+ db.exec(closeEdges(`from_id IN ${retired} OR to_id IN ${retired}`));
18327
+ for (const operation of ["INSERT", "UPDATE OF label,description,attrs_json,valid_to"]) {
18328
+ const suffix = operation.startsWith("INSERT") ? "insert" : "update";
18329
+ db.exec(`CREATE TRIGGER edit_placeholder_nodes_${suffix} AFTER ${operation} ON nodes
18330
+ WHEN NEW.valid_to IS NULL AND (${placeholder("NEW")} OR ${contaminated("NEW")}) BEGIN
18331
+ ${retire(`id=NEW.id AND label='Solution'`, EDIT_PLACEHOLDER_RETIREMENT)}
18332
+ ${retire(contaminated("nodes"), "edit-placeholder-member")}
18333
+ ${markParents}
18334
+ ${closeEdges(`from_id IN ${retired} OR to_id IN ${retired}`)}
18335
+ END;`);
18336
+ db.exec(`CREATE TRIGGER edit_placeholder_edges_${suffix} AFTER ${suffix.toUpperCase()} ON edges
18337
+ WHEN NEW.valid_to IS NULL AND EXISTS(SELECT 1 FROM nodes n WHERE n.id IN (NEW.from_id,NEW.to_id)
18338
+ AND json_extract(n.attrs_json,'$.retiredReason') IN ('${EDIT_PLACEHOLDER_RETIREMENT}','edit-placeholder-member')) BEGIN
18339
+ ${markParents}
18340
+ ${closeEdges("id=NEW.id")}
18341
+ END;`);
18342
+ }
18343
+ db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(EDIT_PLACEHOLDER_FLOOR_KEY, "installed");
18344
+ });
18345
+ }
18346
+ var EDIT_PLACEHOLDER_FLOOR_KEY;
18347
+ var init_edit_placeholder_retirement = __esm({
18348
+ "../../packages/local-graph/src/edit-placeholder-retirement.ts"() {
18349
+ "use strict";
18350
+ init_src();
18351
+ EDIT_PLACEHOLDER_FLOOR_KEY = "edit-placeholder-retirement-1";
18352
+ }
18353
+ });
18354
+
18281
18355
  // ../../packages/local-graph/src/store.ts
18282
18356
  function localEdgeViolation(fromLabel, type, toLabel) {
18283
18357
  if (type in LOCAL_RULE_OVERRIDES) {
@@ -18304,7 +18378,7 @@ function graphStoreNeedsPreparation(path2) {
18304
18378
  for (const match2 of (SCHEMA_SQL + TEMPORAL_INDEX_SQL).matchAll(/CREATE INDEX IF NOT EXISTS (\w+)/g)) {
18305
18379
  if (!indexes.has(match2[1])) return true;
18306
18380
  }
18307
- return [SESSION_REPAIR_KEY, HISTORY_CACHE_FLOOR_KEY].some((key) => !db.prepare("SELECT value FROM store_meta WHERE key = ?").get(key));
18381
+ return [SESSION_REPAIR_KEY, HISTORY_CACHE_FLOOR_KEY, EDIT_PLACEHOLDER_FLOOR_KEY].some((key) => !db.prepare("SELECT value FROM store_meta WHERE key = ?").get(key));
18308
18382
  } catch {
18309
18383
  return true;
18310
18384
  } finally {
@@ -18379,6 +18453,7 @@ var init_store = __esm({
18379
18453
  init_src();
18380
18454
  init_history_cache_floor();
18381
18455
  init_session_evidence();
18456
+ init_edit_placeholder_retirement();
18382
18457
  LOCAL_RULE_OVERRIDES = {
18383
18458
  ANCHORED_AT: {
18384
18459
  from: EDGE_RULES["ANCHORED_AT"]?.from,
@@ -18557,6 +18632,7 @@ CREATE INDEX IF NOT EXISTS nodes_anchor_hint_path ON nodes(json_extract(attrs_js
18557
18632
  }
18558
18633
  this.db.exec(TEMPORAL_INDEX_SQL);
18559
18634
  installHistoryCacheFloor(this.db);
18635
+ installEditPlaceholderRetirement(this.db);
18560
18636
  if (!this.db.prepare("SELECT value FROM store_meta WHERE key = ?").get(SESSION_REPAIR_KEY)) {
18561
18637
  this.db.transaction(() => {
18562
18638
  this.repairSessionAliases();
@@ -19103,8 +19179,8 @@ CREATE INDEX IF NOT EXISTS nodes_anchor_hint_path ON nodes(json_extract(attrs_js
19103
19179
  qname: typeof r.qname === "string" ? r.qname : null
19104
19180
  }));
19105
19181
  }
19106
- findAllVersionsByLabel(label) {
19107
- const rows = this.stmts.findByLabelAll.all(label);
19182
+ findAllVersionsByLabel(label, attribute) {
19183
+ const rows = attribute ? this.db.prepare("SELECT * FROM nodes WHERE label = ? AND json_extract(attrs_json, ?) = ?").all(label, `$.${attribute.path}`, attribute.value) : this.stmts.findByLabelAll.all(label);
19108
19184
  return rows.map(rowToNode);
19109
19185
  }
19110
19186
  searchNodes(opts) {
@@ -19840,6 +19916,7 @@ function addDependency(store, opts) {
19840
19916
  }
19841
19917
  function markRevisit(store, node2, reason, ts, answeredWhen) {
19842
19918
  const fresh = store.getNode(node2.id) ?? node2;
19919
+ if (fresh.validTo != null || fresh.attrs["retiredReason"]) return;
19843
19920
  store.updateNode(node2.id, {
19844
19921
  attrs: {
19845
19922
  ...fresh.attrs,
@@ -19900,7 +19977,7 @@ function clearRevisit(store, nodeId, ts) {
19900
19977
  store.updateNode(nodeId, { attrs, lastUpdatedAt: ts });
19901
19978
  }
19902
19979
  function listNeedsRevisit(store, asOf) {
19903
- return store.nodesAsOfWhereTrue(asOf, "revisit").map((n) => ({
19980
+ return store.nodesAsOfWhereTrue(asOf, "revisit").filter((n) => !n.attrs["retiredReason"]).map((n) => ({
19904
19981
  id: n.id,
19905
19982
  label: n.label,
19906
19983
  description: n.description,
@@ -21557,7 +21634,7 @@ function isFragmentFixNote(note) {
21557
21634
  return /^(and|but|or|nor|so|yet|also|plus)\b/i.test(t);
21558
21635
  }
21559
21636
  function isAutoMinted(n) {
21560
- return n.label === "Solution" && String(n.description ?? "").startsWith(AUTO_MINT_PREFIX);
21637
+ return isEditPlaceholderSolution(n);
21561
21638
  }
21562
21639
  function solutionTextKey(text) {
21563
21640
  return text.trim().replace(/\s+/g, " ").toLowerCase();
@@ -21886,7 +21963,7 @@ function reopenAutoClosedProblems(store, t) {
21886
21963
  continue;
21887
21964
  }
21888
21965
  const sols = store.outEdges(p.id, ["SOLVED_BY"]).map((e) => store.getNode(e.to)).filter((n) => n !== null);
21889
- if (sols.length === 0) continue;
21966
+ if (sols.length === 0 && p.attrs["retiredEditPlaceholder"] !== true) continue;
21890
21967
  if (!sols.every((s) => String(s.description ?? "").startsWith(AUTO_MINT_PREFIX))) {
21891
21968
  report.agentDescribed++;
21892
21969
  continue;
@@ -22049,7 +22126,7 @@ function priorExposure(store, nodeId, atSeq) {
22049
22126
  if ((n.attrs["evictedCount"] ?? 0) > 0) return "evicted";
22050
22127
  return "unshown";
22051
22128
  }
22052
- var DESIGN_PROMOTE_AT, STATEMENT_ALIAS_CAP, RECURRENCE_DEBOUNCE_MS, PATTERN_DEDUP_COSINE, PATTERN_ALIAS_CAP, DEDUP_STOPWORDS, SAME_ANCHOR_DEDUP_JACCARD, EMPTY_FOLD_REPORT, SAME_ANCHOR_SCOUT_AUTO_COSINE, SAME_ANCHOR_SCOUT_MIN_COSINE, SAME_ANCHOR_NOMINATE_JACCARD, REOPEN_MIN_SOURCES, RECURRENCE_SOURCES_CAP, CITABLE_PRIOR_LABELS, MAX_ANCHOR_FILES, ENCLOSING_SYMBOL_KINDS, ENCLOSING_WALK_DEPTH, AUTO_MINT_PREFIX, FIX_CANDIDATE_ASK_LIMIT;
22129
+ var DESIGN_PROMOTE_AT, STATEMENT_ALIAS_CAP, RECURRENCE_DEBOUNCE_MS, PATTERN_DEDUP_COSINE, PATTERN_ALIAS_CAP, DEDUP_STOPWORDS, SAME_ANCHOR_DEDUP_JACCARD, EMPTY_FOLD_REPORT, SAME_ANCHOR_SCOUT_AUTO_COSINE, SAME_ANCHOR_SCOUT_MIN_COSINE, SAME_ANCHOR_NOMINATE_JACCARD, REOPEN_MIN_SOURCES, RECURRENCE_SOURCES_CAP, CITABLE_PRIOR_LABELS, MAX_ANCHOR_FILES, ENCLOSING_SYMBOL_KINDS, ENCLOSING_WALK_DEPTH, FIX_CANDIDATE_ASK_LIMIT;
22053
22130
  var init_design_problem = __esm({
22054
22131
  "../../packages/local-graph/src/design-problem.ts"() {
22055
22132
  "use strict";
@@ -22060,6 +22137,7 @@ var init_design_problem = __esm({
22060
22137
  init_src2();
22061
22138
  init_problem_package_link();
22062
22139
  init_problem_dedup();
22140
+ init_src();
22063
22141
  DESIGN_PROMOTE_AT = 1;
22064
22142
  STATEMENT_ALIAS_CAP = 5;
22065
22143
  RECURRENCE_DEBOUNCE_MS = 60 * 60 * 1e3;
@@ -22125,7 +22203,6 @@ var init_design_problem = __esm({
22125
22203
  "Property"
22126
22204
  ]);
22127
22205
  ENCLOSING_WALK_DEPTH = 8;
22128
- AUTO_MINT_PREFIX = "addressed by an edit to ";
22129
22206
  FIX_CANDIDATE_ASK_LIMIT = 5;
22130
22207
  }
22131
22208
  });
@@ -22410,6 +22487,10 @@ function percolate(l1, l2, opts) {
22410
22487
  l2.transaction(() => {
22411
22488
  for (const label of PERCOLATING_LABELS) {
22412
22489
  for (const n of l1.findNodesByLabel(label)) {
22490
+ if (isEditPlaceholderSolution(n) || n.attrs["retiredReason"]) {
22491
+ result.nodesSkipped++;
22492
+ continue;
22493
+ }
22413
22494
  if (n.label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) continue;
22414
22495
  if (n.attrs["source"] === "cloud") {
22415
22496
  const raw2 = l2.getMeta?.(`history-correction:${String(n.attrs["cloudNodeId"] ?? n.id)}`);
@@ -22542,6 +22623,7 @@ var init_percolate = __esm({
22542
22623
  "../../packages/local-graph/src/percolate.ts"() {
22543
22624
  "use strict";
22544
22625
  init_src2();
22626
+ init_src();
22545
22627
  PERCOLATING_LABELS = ["Claim", "Problem", "Solution"];
22546
22628
  PERCOLATING_EDGES = ["CAUSED_BY", "SOLVED_BY", "CONTRADICTS"];
22547
22629
  PERCOLATING_DRIFT_EDGES = ["CONTINUES", "REVEALED_BY", "SUPERSEDED_BY", "SPLIT_INTO"];
@@ -24023,6 +24105,7 @@ function induceAbstractions(l2, opts) {
24023
24105
  const ids = /* @__PURE__ */ new Set();
24024
24106
  for (const label of PERCOLATING_LABELS) {
24025
24107
  for (const n of l2.findNodesByLabel(label)) {
24108
+ if (isEditPlaceholderSolution(n) || n.attrs["retiredReason"] || n.validTo != null) continue;
24026
24109
  if (Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) >= ABSTRACTION_LEVEL.PRINCIPLE) {
24027
24110
  continue;
24028
24111
  }
@@ -24099,6 +24182,10 @@ function pendingAbstractions(l2) {
24099
24182
  if (Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) < ABSTRACTION_LEVEL.PRINCIPLE) continue;
24100
24183
  if (n.attrs["provisional"] !== true) continue;
24101
24184
  const memberIds = Array.isArray(n.attrs["members"]) ? n.attrs["members"] : [];
24185
+ if (memberIds.some((id) => {
24186
+ const m = l2.getNode(id);
24187
+ return !m || m.validTo != null || m.attrs["retiredReason"] || isEditPlaceholderSolution(m);
24188
+ })) continue;
24102
24189
  const members = memberIds.map((id) => {
24103
24190
  const m = l2.getNode(id);
24104
24191
  return m ? { id: m.id, label: m.label, description: m.description } : { id, label: "?", description: "(member missing)" };
@@ -24130,13 +24217,19 @@ function parseAbstractionFences(text) {
24130
24217
  }
24131
24218
  function applyAbstractionFence(l2, fence, ts) {
24132
24219
  const node2 = l2.getNode(fence.candidate);
24133
- if (!node2 || node2.label !== "Claim" || Number(node2.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) < ABSTRACTION_LEVEL.PRINCIPLE) {
24220
+ if (!node2 || node2.validTo != null || node2.attrs["retiredReason"] || node2.label !== "Claim" || Number(node2.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) < ABSTRACTION_LEVEL.PRINCIPLE) {
24134
24221
  return { applied: false, principleId: fence.candidate, reason: "no such abstraction candidate" };
24135
24222
  }
24136
24223
  if (node2.attrs["provisional"] !== true) {
24137
24224
  return { applied: false, principleId: fence.candidate, reason: "candidate already distilled" };
24138
24225
  }
24139
24226
  const members = Array.isArray(node2.attrs["members"]) ? node2.attrs["members"] : [];
24227
+ if (members.some((id) => {
24228
+ const m = l2.getNode(id);
24229
+ return !m || m.validTo != null || m.attrs["retiredReason"] || isEditPlaceholderSolution(m);
24230
+ })) {
24231
+ return { applied: false, principleId: fence.candidate, reason: "candidate contains retired or missing evidence" };
24232
+ }
24140
24233
  const want = new Set(members);
24141
24234
  const got = new Set(fence.covers);
24142
24235
  const missing = members.filter((id) => !got.has(id));
@@ -25568,7 +25661,7 @@ function renderSnapshot(s) {
25568
25661
  lines.push("");
25569
25662
  lines.push("### \u270D\uFE0F CAPTURE PROTOCOL \u2014 tags are the record");
25570
25663
  lines.push(
25571
- "For problems and fixes, errata records inline tags: `[!one line]` for every problem you state, `(fix:[id])` when your edit fixed a shown problem, and to JUDGE a prior shown below \u2014 `(confirm:[id])` if it held, `(refute:[id] why)` if it's wrong or didn't hold. Untagged prose is silently lost \u2014 tag as you write. Requested errata-* answer blocks keep their fences; put them in your turn-final reply."
25664
+ "For ALL project work \u2014 features, UX, refactors, research, not just debugging \u2014 errata records inline tags: `[!one line]` for every problem you state (even in code you just wrote), `(constraint: why)` for each design decision, `(fix:[id])` when your edit fixed a shown problem, and to JUDGE a prior shown below \u2014 `(confirm:[id])` if it held, `(refute:[id] why)` if it's wrong or didn't hold. Untagged prose is silently lost \u2014 tag as you write. Requested errata-* answer blocks keep their fences; put them in your turn-final reply."
25572
25665
  );
25573
25666
  lines.push("");
25574
25667
  lines.push(SEARCH_IMPERATIVE_HEADER);
@@ -26037,7 +26130,7 @@ function diffRenderLedger(before, after) {
26037
26130
  for (const i2 of before) (survived.has(key(i2)) ? shown : evicted).push(i2);
26038
26131
  return { shown, evicted };
26039
26132
  }
26040
- 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, SPAWN_SHARE_HINT, SUBAGENT_OWN_BLOCK_NOTE, EVICTION_ORDER, MOTIF_FLOOR, REMOTE_FLOOR, PROBLEM_FLOOR, REVIEW_ITEM_FLOOR, DEFAULT_AGENT_CONTEXT_BUDGET;
26133
+ 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;
26041
26134
  var init_render = __esm({
26042
26135
  "../../packages/context-writer/src/render.ts"() {
26043
26136
  "use strict";
@@ -26054,7 +26147,8 @@ var init_render = __esm({
26054
26147
 
26055
26148
  ${RECALL_FIRST_BODY}`;
26056
26149
  SEARCH_IMPERATIVE_HEADER = "### \u{1F50E} PRIORS ARE SEEDS \u2014 a sample, not the whole graph";
26057
- SEARCH_IMPERATIVE_BODY = "Everything below is a budgeted slice of a much larger graph, not all errata knows. Starting a piece of work? 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.";
26150
+ 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.";
26151
+ 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.";
26058
26152
  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```";
26059
26153
  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._";
26060
26154
  EVICTION_ORDER = [
@@ -30987,82 +31081,10 @@ function resolveProblem(store, problem, t) {
30987
31081
  if (suppressed) mintSuppressionAntiPattern(store, problem, liveSym, ep, t);
30988
31082
  return null;
30989
31083
  }
30990
- store.mergeEdge({
30991
- id: `edge_${digest({ from: problem.id, type: "FIXED_BY", to: ep.id })}`.slice(0, 24),
30992
- from: problem.id,
30993
- to: ep.id,
30994
- type: "FIXED_BY",
30995
- confidence: 0.7,
30996
- extractionSource: "daemon-extracted",
30997
- createdAt: t,
30998
- lastSeenAt: t,
30999
- navSuccesses: 0,
31000
- navFailures: 0,
31001
- attrs: { resolvedAt: t }
31002
- });
31003
- const solId = `solution_${digest({ logicalId: anchorLogicalId, ep: ep.id }).slice(0, 16)}`;
31004
- const solSeq = store.nextIngestSeq();
31005
- store.mergeNode({
31006
- id: solId,
31007
- label: "Solution",
31008
- description: `fix for ${liveSym.description} (${ep.id})`,
31009
- extractionConfidence: 0.7,
31010
- extractionSource: "daemon-extracted",
31011
- embedding: [],
31012
- cumulativeSurprise: 0,
31013
- peakSurprise: 0,
31014
- cumulativeHits: 1,
31015
- lastUpdatedAt: t,
31016
- createdAt: t,
31017
- createdAtSeq: solSeq,
31018
- lastReinforcedAtSeq: solSeq,
31019
- memoryTier: "short-term",
31020
- pageRank: 0,
31021
- isLandmark: false,
31022
- community: null,
31023
- stability: "forming",
31024
- attrs: {
31025
- episodeId: ep.id,
31026
- anchorLogicalId,
31027
- editSurprise: ep.attrs["editSurprise"] ?? 0,
31028
- workspaceId: problem.attrs["workspaceId"],
31029
- // Resolution-checkpoint marker (Phase 8): this fresh Solution awaits the
31030
- // agent's one-question enrichment pull. Cleared by annotateResolution.
31031
- // Lives on the Solution (a live node) so it survives the Problem's close
31032
- // and is visible cross-process via the shared store.
31033
- enrichmentPending: true,
31034
- problemId: problem.id,
31035
- problemDescription: problem.description,
31036
- symbolName: liveSym.description
31037
- }
31038
- });
31039
- store.mergeEdge({
31040
- id: `edge_${digest({ from: problem.id, type: "SOLVED_BY", to: solId })}`.slice(0, 24),
31041
- from: problem.id,
31042
- to: solId,
31043
- type: "SOLVED_BY",
31044
- confidence: 0.7,
31045
- extractionSource: "daemon-extracted",
31046
- createdAt: t,
31047
- lastSeenAt: t,
31048
- navSuccesses: 0,
31049
- navFailures: 0,
31050
- attrs: {}
31051
- });
31052
- store.mergeEdge({
31053
- id: `edge_${digest({ from: solId, type: "ANCHORED_AT", to: liveSym.id })}`.slice(0, 24),
31054
- from: solId,
31055
- to: liveSym.id,
31056
- type: "ANCHORED_AT",
31057
- confidence: 0.7,
31058
- extractionSource: "daemon-extracted",
31059
- createdAt: t,
31060
- lastSeenAt: t,
31061
- navSuccesses: 0,
31062
- navFailures: 0,
31063
- attrs: {}
31084
+ store.updateNode(problem.id, {
31085
+ attrs: { ...store.getNode(problem.id).attrs, resolvedAs: "edited", resolutionEpisode: ep.id, enrichmentPending: true }
31064
31086
  });
31065
- return solId;
31087
+ return null;
31066
31088
  }
31067
31089
  function mintSuppressionAntiPattern(store, problem, liveSym, ep, t) {
31068
31090
  const code = problem.attrs["diagnosticCode"] ?? "";
@@ -31140,6 +31162,7 @@ function annotateResolution(store, ann, t) {
31140
31162
  for (const pid of ann.problemIds) {
31141
31163
  const problem = store.getNode(pid);
31142
31164
  if (!problem) continue;
31165
+ store.updateNode(pid, { attrs: { ...problem.attrs, enrichmentPending: false } });
31143
31166
  const cause = ann.sharedRootCause ?? ann.perProblem?.find((p) => p.problemId === pid)?.rootCause;
31144
31167
  if (cause) {
31145
31168
  const rc = store.outEdges(pid, ["CAUSED_BY"]).map((e) => store.getNode(e.to)).find((n) => n?.label === "RootCause");
@@ -31210,6 +31233,60 @@ function annotateResolution(store, ann, t) {
31210
31233
  }
31211
31234
  }
31212
31235
  const sol = store.outEdges(pid, ["SOLVED_BY"]).map((e) => store.getNode(e.to)).find((n) => n?.label === "Solution");
31236
+ if (!sol && ann.solutionRationale?.trim()) {
31237
+ const rationale = ann.solutionRationale.trim();
31238
+ const id = `solution_${digest({ rationale }).slice(0, 16)}`;
31239
+ const seq = store.nextIngestSeq();
31240
+ store.mergeNode({
31241
+ id,
31242
+ label: "Solution",
31243
+ description: rationale,
31244
+ extractionSource: "agent-observed",
31245
+ extractionConfidence: conf,
31246
+ validFrom: t,
31247
+ validTo: null,
31248
+ createdAt: t,
31249
+ lastUpdatedAt: t,
31250
+ createdAtSeq: seq,
31251
+ lastReinforcedAtSeq: seq,
31252
+ embedding: [],
31253
+ cumulativeHits: 1,
31254
+ pageRank: 0,
31255
+ cumulativeSurprise: 0,
31256
+ peakSurprise: 0,
31257
+ isLandmark: false,
31258
+ community: null,
31259
+ memoryTier: "short-term",
31260
+ stability: "forming",
31261
+ attrs: { rationale, problemId: pid, enrichmentPending: false, workspaceId: problem.attrs["workspaceId"] }
31262
+ });
31263
+ store.mergeEdge({
31264
+ id: `edge_${digest({ from: pid, type: "SOLVED_BY", to: id }).slice(0, 16)}`,
31265
+ from: pid,
31266
+ to: id,
31267
+ type: "SOLVED_BY",
31268
+ confidence: conf,
31269
+ extractionSource: "agent-observed",
31270
+ createdAt: t,
31271
+ lastSeenAt: t,
31272
+ navSuccesses: 0,
31273
+ navFailures: 0,
31274
+ attrs: {}
31275
+ });
31276
+ const anchor = store.outEdges(pid, ["ANCHORED_AT"])[0];
31277
+ if (anchor) store.mergeEdge({
31278
+ ...anchor,
31279
+ id: `edge_${digest({ from: id, type: "ANCHORED_AT", to: anchor.to }).slice(0, 16)}`,
31280
+ from: id,
31281
+ confidence: conf,
31282
+ extractionSource: "agent-observed",
31283
+ createdAt: t,
31284
+ lastSeenAt: t,
31285
+ navSuccesses: 0,
31286
+ navFailures: 0,
31287
+ attrs: {}
31288
+ });
31289
+ }
31213
31290
  if (sol) {
31214
31291
  const attrs = { ...sol.attrs, enrichmentPending: false };
31215
31292
  if (ann.solutionRationale) attrs["rationale"] = ann.solutionRationale;
@@ -32244,7 +32321,7 @@ function buildAgentInstruction(opts = {}) {
32244
32321
  const signals = opts.signals ?? ["prior", "problem", "vulnerability", "domain", "fix", "constraint", "triage", "attempt", "link"];
32245
32322
  const ref = opts.referent ?? "its-handle";
32246
32323
  const token = (s) => s === "problem" ? TAG_EXAMPLE.problem() : s === "constraint" ? TAG_EXAMPLE.constraint() : s === "attempt" ? TAG_EXAMPLE.tried() : s === "domain" ? TAG_EXAMPLE.domain() : s === "link" ? TAG_EXAMPLE.pattern() : s === "verdict" ? TAG_EXAMPLE.confirm(ref) : TAG_EXAMPLE[s](ref);
32247
- const head2 = "Tag inline (no fences or backticks). Untagged findings are silently lost. Cite short handles; tag everything, we filter downstream. Requested errata-* answer blocks are the exception: keep their fences in your turn-final reply:";
32324
+ const head2 = "Tag inline (no fences/backticks) on ALL work, not just bugs. Untagged findings are silently lost. Cite short handles; we filter downstream. Requested errata-* answer blocks are the exception: keep their fences in your turn-final reply:";
32248
32325
  const tail = "Restate mid-turn tags in your final reply; the harness can drop mid-turn text. EXCEPT one already shown with an id: cite [its-handle] instead of retyping (drift mints a duplicate).";
32249
32326
  return [
32250
32327
  head2,
@@ -43637,7 +43714,7 @@ function collectEnrichmentPulls(store, opts = {}) {
43637
43714
  const byEpisode = /* @__PURE__ */ new Map();
43638
43715
  for (const s of pending) {
43639
43716
  const ep = s.attrs["episodeId"] ?? s.id;
43640
- const e = byEpisode.get(ep) ?? { episodeId: ep, problems: [], solutionIds: [] };
43717
+ const e = byEpisode.get(ep) ?? { episodeId: ep, problems: [], solutionIds: [], problemIds: [] };
43641
43718
  e.problems.push({
43642
43719
  solutionId: s.id,
43643
43720
  problemId: s.attrs["problemId"] ?? null,
@@ -43647,13 +43724,22 @@ function collectEnrichmentPulls(store, opts = {}) {
43647
43724
  e.solutionIds.push(s.id);
43648
43725
  byEpisode.set(ep, e);
43649
43726
  }
43727
+ for (const p of store.findAllVersionsByLabel("Problem", { path: "enrichmentPending", value: 1 })) {
43728
+ if (p.validTo == null || p.attrs["retiredReason"] || p.attrs["resolvedAs"] !== "edited") continue;
43729
+ if (opts.onlyUnsurfaced && p.attrs["enrichmentSurfaced"] === true) continue;
43730
+ const ep = String(p.attrs["resolutionEpisode"] ?? p.id);
43731
+ const e = byEpisode.get(ep) ?? { episodeId: ep, problems: [], solutionIds: [], problemIds: [] };
43732
+ e.problems.push({ solutionId: null, problemId: p.id, problem: p.description });
43733
+ e.problemIds.push(p.id);
43734
+ byEpisode.set(ep, e);
43735
+ }
43650
43736
  return [...byEpisode.values()];
43651
43737
  }
43652
43738
  function takeEnrichmentNudge(store) {
43653
43739
  const pulls = collectEnrichmentPulls(store, { onlyUnsurfaced: true });
43654
43740
  if (pulls.length === 0) return null;
43655
43741
  for (const pull of pulls) {
43656
- for (const id of pull.solutionIds) {
43742
+ for (const id of [...pull.solutionIds, ...pull.problemIds]) {
43657
43743
  const sol = store.getNode(id);
43658
43744
  if (sol) store.updateNode(id, { attrs: { ...sol.attrs, enrichmentSurfaced: true } });
43659
43745
  }
@@ -43661,9 +43747,9 @@ function takeEnrichmentNudge(store) {
43661
43747
  const items = pulls.map((p) => {
43662
43748
  const what = p.problems.map((x) => `${x["fixed"] ? `\`${x["fixed"]}\`` : "a symbol"}${x["problem"] ? ` (${x["problem"]})` : ""}`).join(", ");
43663
43749
  const ids = p.problems.map((x) => x["problemId"]).filter(Boolean);
43664
- return `\u2022 fixed ${what} \u2014 what was the root cause? a pattern? \u2192 errata.annotate_resolution problemIds:${JSON.stringify(ids)}`;
43750
+ return `\u2022 observed ${what} stop failing \u2014 was this fixed? If known, give the root cause and solutionRationale \u2192 errata.annotate_resolution problemIds:${JSON.stringify(ids)}`;
43665
43751
  }).join("\n");
43666
- return `\u26A1 errata \u2014 ${pulls.length} recent fix(es) await a one-line root cause (optional, answer in-flow):
43752
+ return `\u26A1 errata \u2014 ${pulls.length} observed resolution(s) await a one-line root cause and fix explanation (optional, answer in-flow):
43667
43753
  ` + items;
43668
43754
  }
43669
43755
  function takeDiscriminatorNudge(path2) {
@@ -45112,7 +45198,7 @@ var init_mcp = __esm({
45112
45198
  const pulls = collectEnrichmentPulls(store).map((p) => ({
45113
45199
  episodeId: p.episodeId,
45114
45200
  problems: p.problems,
45115
- question: "You just resolved the above. For each (or shared): what was the root cause, and is this an instance of a pattern? One line each."
45201
+ question: "The above stopped failing. If you know why, provide the root cause and solutionRationale (the actual fix); optionally name a pattern. Do not guess."
45116
45202
  }));
45117
45203
  return { count: pulls.length, pulls };
45118
45204
  }
@@ -53386,7 +53472,7 @@ function decideContextInject(args2) {
53386
53472
  if (event === "SessionStart" || event === "SubagentStart") {
53387
53473
  if (sessionId) lastInjectedHash.set(sessionId, block.hash);
53388
53474
  } else if (sessionId && lastInjectedHash.get(sessionId) === block.hash) {
53389
- return null;
53475
+ return event === "UserPromptSubmit" ? { hookEventName: event, additionalContext: PROMPT_RECUE } : null;
53390
53476
  } else {
53391
53477
  if (sessionId) lastInjectedHash.set(sessionId, block.hash);
53392
53478
  }
@@ -53835,13 +53921,14 @@ function buildWebUi(deps) {
53835
53921
  });
53836
53922
  if (decision && subagent !== null) lastSubagentInjectAt.set(contextKey2, Date.now());
53837
53923
  let systemMessage = null;
53838
- if (sid && block && recallCardEnabled() && (decision || atPrompt)) {
53924
+ const delivered = decision !== null && decision.additionalContext !== PROMPT_RECUE;
53925
+ if (sid && block && recallCardEnabled() && (delivered || atPrompt)) {
53839
53926
  const card = storedCard && subagent !== null ? forSubagent(storedCard, subagent) : storedCard;
53840
53927
  if (card) {
53841
53928
  if (subagent !== null && storedCard) rememberAgentCard(sid, agentId, storedCard);
53842
53929
  else rememberCard(sid, card);
53843
- if (decision && hookEvent === "SubagentStart") systemMessage = renderRecallLine(card);
53844
- else if (decision && sid.startsWith("codex:")) systemMessage = renderRecallLine(card);
53930
+ if (delivered && hookEvent === "SubagentStart") systemMessage = renderRecallLine(card);
53931
+ else if (delivered && sid.startsWith("codex:")) systemMessage = renderRecallLine(card);
53845
53932
  }
53846
53933
  }
53847
53934
  if (!decision) return c.json({});
@@ -82432,7 +82519,7 @@ function createWatchBreaker(deps) {
82432
82519
  }
82433
82520
 
82434
82521
  // src/engine.ts
82435
- var DAEMON_VERSION = true ? "2.0.17-dev.3537" : "2.0.0-alpha.0";
82522
+ var DAEMON_VERSION = true ? "2.0.17-dev.3549" : "2.0.0-alpha.0";
82436
82523
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
82437
82524
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
82438
82525
  var GIT_OP_MUTE_MS = 4e3;
@@ -85648,8 +85735,8 @@ function runLockfilePass(opts) {
85648
85735
 
85649
85736
  // src/instance-ingest.ts
85650
85737
  init_src();
85738
+ init_src();
85651
85739
  init_src2();
85652
- init_src5();
85653
85740
  init_src10();
85654
85741
  init_src();
85655
85742
 
@@ -86064,7 +86151,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
86064
86151
  semanticEndpoints.set(n.id, contributedWireId(n, opts.destinationKey));
86065
86152
  continue;
86066
86153
  }
86067
- if (label === "Solution" && n.description.startsWith(AUTO_MINT_PREFIX)) {
86154
+ if (isEditPlaceholderSolution(n)) {
86068
86155
  composition.autoMint++;
86069
86156
  continue;
86070
86157
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.17-dev.3537",
3
+ "version": "2.0.17-dev.3549",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -16206,6 +16206,22 @@ var init_project_wire_attrs = __esm({
16206
16206
  }
16207
16207
  });
16208
16208
 
16209
+ // ../../packages/shared/src/edit-placeholder.ts
16210
+ function isEditPlaceholderSolution(node) {
16211
+ if (node.label !== "Solution") return false;
16212
+ const text = node.description.trim().toLowerCase();
16213
+ if (text.startsWith(AUTO_MINT_PREFIX)) return true;
16214
+ return /^fix for [^\r\n]+ \(episode_[^)]+\)$/.test(text) && !(typeof node.attrs?.["rationale"] === "string" && node.attrs["rationale"].trim());
16215
+ }
16216
+ var AUTO_MINT_PREFIX, EDIT_PLACEHOLDER_RETIREMENT;
16217
+ var init_edit_placeholder = __esm({
16218
+ "../../packages/shared/src/edit-placeholder.ts"() {
16219
+ "use strict";
16220
+ AUTO_MINT_PREFIX = "addressed by an edit to ";
16221
+ EDIT_PLACEHOLDER_RETIREMENT = "edit-placeholder-solution";
16222
+ }
16223
+ });
16224
+
16209
16225
  // ../../packages/shared/src/index.ts
16210
16226
  var init_src = __esm({
16211
16227
  "../../packages/shared/src/index.ts"() {
@@ -16237,6 +16253,7 @@ var init_src = __esm({
16237
16253
  init_triage_canon();
16238
16254
  init_history_text();
16239
16255
  init_project_wire_attrs();
16256
+ init_edit_placeholder();
16240
16257
  }
16241
16258
  });
16242
16259
 
@@ -25360,6 +25377,54 @@ function repairSessionEvidence(input, aliases = /* @__PURE__ */ new Map()) {
25360
25377
  return repaired;
25361
25378
  }
25362
25379
 
25380
+ // ../../packages/local-graph/src/edit-placeholder-retirement.ts
25381
+ init_src();
25382
+ var EDIT_PLACEHOLDER_FLOOR_KEY = "edit-placeholder-retirement-1";
25383
+ function installEditPlaceholderRetirement(db) {
25384
+ if (db.prepare("SELECT value FROM store_meta WHERE key=?").get(EDIT_PLACEHOLDER_FLOOR_KEY)) return;
25385
+ const timestamp = `CAST(unixepoch('subsec') * 1000 AS INTEGER)`;
25386
+ const placeholder = (n) => `(${n}.label='Solution' AND (
25387
+ lower(trim(${n}.description)) LIKE '${AUTO_MINT_PREFIX}%'
25388
+ OR (lower(trim(${n}.description)) GLOB 'fix for * (episode_*)'
25389
+ AND instr(${n}.description,char(10))=0 AND instr(${n}.description,char(13))=0
25390
+ AND trim(coalesce(json_extract(${n}.attrs_json,'$.rationale'),''))='')))`;
25391
+ const contaminated = (n) => `(${n}.label='Claim' AND json_extract(${n}.attrs_json,'$.abstractionLevel')>=2
25392
+ AND EXISTS(SELECT 1 FROM json_each(${n}.attrs_json,'$.members') m JOIN nodes s ON s.id=m.value
25393
+ WHERE ${placeholder("s")} OR json_extract(s.attrs_json,'$.retiredReason')='${EDIT_PLACEHOLDER_RETIREMENT}'))`;
25394
+ const retire = (where, reason) => `UPDATE nodes SET valid_to=coalesce(valid_to,${timestamp}),
25395
+ attrs_json=json_set(attrs_json,'$.retiredReason','${reason}','$.retiredAt',${timestamp})
25396
+ WHERE (valid_to IS NULL OR coalesce(json_extract(attrs_json,'$.retiredReason'),'')<>'${reason}') AND (${where});`;
25397
+ const closeEdges = (where) => `UPDATE edges SET valid_to=${timestamp} WHERE valid_to IS NULL AND (${where});`;
25398
+ const retired = `(SELECT id FROM nodes WHERE json_extract(attrs_json,'$.retiredReason') IN ('${EDIT_PLACEHOLDER_RETIREMENT}','edit-placeholder-member'))`;
25399
+ const markParents = `UPDATE nodes SET attrs_json=json_set(attrs_json,'$.retiredEditPlaceholder',json('true'))
25400
+ WHERE label='Problem' AND coalesce(json_extract(attrs_json,'$.retiredEditPlaceholder'),0)<>1
25401
+ AND id IN (SELECT e.from_id FROM edges e JOIN nodes s ON s.id=e.to_id WHERE e.type='SOLVED_BY'
25402
+ AND s.label='Solution' AND json_extract(s.attrs_json,'$.retiredReason')='${EDIT_PLACEHOLDER_RETIREMENT}');`;
25403
+ db.transaction(() => {
25404
+ db.exec(retire(placeholder("nodes"), EDIT_PLACEHOLDER_RETIREMENT));
25405
+ db.exec(retire(contaminated("nodes"), "edit-placeholder-member"));
25406
+ db.exec(markParents);
25407
+ db.exec(closeEdges(`from_id IN ${retired} OR to_id IN ${retired}`));
25408
+ for (const operation of ["INSERT", "UPDATE OF label,description,attrs_json,valid_to"]) {
25409
+ const suffix = operation.startsWith("INSERT") ? "insert" : "update";
25410
+ db.exec(`CREATE TRIGGER edit_placeholder_nodes_${suffix} AFTER ${operation} ON nodes
25411
+ WHEN NEW.valid_to IS NULL AND (${placeholder("NEW")} OR ${contaminated("NEW")}) BEGIN
25412
+ ${retire(`id=NEW.id AND label='Solution'`, EDIT_PLACEHOLDER_RETIREMENT)}
25413
+ ${retire(contaminated("nodes"), "edit-placeholder-member")}
25414
+ ${markParents}
25415
+ ${closeEdges(`from_id IN ${retired} OR to_id IN ${retired}`)}
25416
+ END;`);
25417
+ db.exec(`CREATE TRIGGER edit_placeholder_edges_${suffix} AFTER ${suffix.toUpperCase()} ON edges
25418
+ WHEN NEW.valid_to IS NULL AND EXISTS(SELECT 1 FROM nodes n WHERE n.id IN (NEW.from_id,NEW.to_id)
25419
+ AND json_extract(n.attrs_json,'$.retiredReason') IN ('${EDIT_PLACEHOLDER_RETIREMENT}','edit-placeholder-member')) BEGIN
25420
+ ${markParents}
25421
+ ${closeEdges("id=NEW.id")}
25422
+ END;`);
25423
+ }
25424
+ db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(EDIT_PLACEHOLDER_FLOOR_KEY, "installed");
25425
+ });
25426
+ }
25427
+
25363
25428
  // ../../packages/local-graph/src/store.ts
25364
25429
  var LOCAL_RULE_OVERRIDES = {
25365
25430
  ANCHORED_AT: {
@@ -25611,6 +25676,7 @@ var SqliteGraphStore = class {
25611
25676
  }
25612
25677
  this.db.exec(TEMPORAL_INDEX_SQL);
25613
25678
  installHistoryCacheFloor(this.db);
25679
+ installEditPlaceholderRetirement(this.db);
25614
25680
  if (!this.db.prepare("SELECT value FROM store_meta WHERE key = ?").get(SESSION_REPAIR_KEY)) {
25615
25681
  this.db.transaction(() => {
25616
25682
  this.repairSessionAliases();
@@ -26157,8 +26223,8 @@ var SqliteGraphStore = class {
26157
26223
  qname: typeof r.qname === "string" ? r.qname : null
26158
26224
  }));
26159
26225
  }
26160
- findAllVersionsByLabel(label) {
26161
- const rows = this.stmts.findByLabelAll.all(label);
26226
+ findAllVersionsByLabel(label, attribute) {
26227
+ const rows = attribute ? this.db.prepare("SELECT * FROM nodes WHERE label = ? AND json_extract(attrs_json, ?) = ?").all(label, `$.${attribute.path}`, attribute.value) : this.stmts.findByLabelAll.all(label);
26162
26228
  return rows.map(rowToNode);
26163
26229
  }
26164
26230
  searchNodes(opts) {
@@ -26598,6 +26664,7 @@ function addDependency(store2, opts) {
26598
26664
  }
26599
26665
  function markRevisit(store2, node, reason, ts, answeredWhen) {
26600
26666
  const fresh = store2.getNode(node.id) ?? node;
26667
+ if (fresh.validTo != null || fresh.attrs["retiredReason"]) return;
26601
26668
  store2.updateNode(node.id, {
26602
26669
  attrs: {
26603
26670
  ...fresh.attrs,
@@ -26663,7 +26730,7 @@ function clearRevisit(store2, nodeId, ts) {
26663
26730
  store2.updateNode(nodeId, { attrs, lastUpdatedAt: ts });
26664
26731
  }
26665
26732
  function listNeedsRevisit(store2, asOf) {
26666
- return store2.nodesAsOfWhereTrue(asOf, "revisit").map((n) => ({
26733
+ return store2.nodesAsOfWhereTrue(asOf, "revisit").filter((n) => !n.attrs["retiredReason"]).map((n) => ({
26667
26734
  id: n.id,
26668
26735
  label: n.label,
26669
26736
  description: n.description,
@@ -27078,6 +27145,7 @@ function foldDuplicateProblem(store2, dup, survivor, ts) {
27078
27145
  }
27079
27146
 
27080
27147
  // ../../packages/local-graph/src/design-problem.ts
27148
+ init_src();
27081
27149
  function isConstraintProblem(node) {
27082
27150
  return node.attrs["kind"] === "constraint";
27083
27151
  }
@@ -27098,7 +27166,7 @@ var CITABLE_PRIOR_LABELS = /* @__PURE__ */ new Set([
27098
27166
  "AntiPattern"
27099
27167
  ]);
27100
27168
  function isAutoMinted(n) {
27101
- return n.label === "Solution" && String(n.description ?? "").startsWith(AUTO_MINT_PREFIX);
27169
+ return isEditPlaceholderSolution(n);
27102
27170
  }
27103
27171
  function priorsForFile(store2, relPath) {
27104
27172
  const want = relPath.trim().replace(/^\.?\//, "");
@@ -27343,7 +27411,7 @@ function reopenAutoClosedProblems(store2, t) {
27343
27411
  continue;
27344
27412
  }
27345
27413
  const sols = store2.outEdges(p.id, ["SOLVED_BY"]).map((e) => store2.getNode(e.to)).filter((n) => n !== null);
27346
- if (sols.length === 0) continue;
27414
+ if (sols.length === 0 && p.attrs["retiredEditPlaceholder"] !== true) continue;
27347
27415
  if (!sols.every((s) => String(s.description ?? "").startsWith(AUTO_MINT_PREFIX))) {
27348
27416
  report.agentDescribed++;
27349
27417
  continue;
@@ -27358,7 +27426,6 @@ function reopenAutoClosedProblems(store2, t) {
27358
27426
  }
27359
27427
  return report;
27360
27428
  }
27361
- var AUTO_MINT_PREFIX = "addressed by an edit to ";
27362
27429
  function markFixCandidates(store2, t) {
27363
27430
  let resolved = 0;
27364
27431
  for (const p of store2.findNodesByLabel("Problem")) {
@@ -27624,6 +27691,7 @@ function backfillLegacyAnchors(store2, ts) {
27624
27691
 
27625
27692
  // ../../packages/local-graph/src/percolate.ts
27626
27693
  init_src2();
27694
+ init_src();
27627
27695
 
27628
27696
  // ../../packages/local-graph/src/abstraction.ts
27629
27697
  init_src();