@inerrata-corporation/errata 2.0.16-dev.3362 → 2.0.16

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.
@@ -802,12 +802,6 @@ function identityId(input) {
802
802
  }
803
803
  case "Claim":
804
804
  return canonicalClaimId(input.text, input.scope);
805
- case "WitnessedVulnerability":
806
- return genericCanonicalId("dvuln", {
807
- workspaceId: input.workspaceId,
808
- target: input.target.replace(/\\/g, "/").replace(/^\.\//, ""),
809
- statement: canonicalClaimId(input.statement.trim())
810
- });
811
805
  case "DesignProblem":
812
806
  return `${DESIGN_PROBLEM_PREFIX}${canonicalClaimId(input.statement.trim())}`.slice(
813
807
  0,
@@ -15264,7 +15258,7 @@ var init_edge_rules = __esm({
15264
15258
  // anchor anything at anything, e.g. at a public `Package`, quietly re-creating
15265
15259
  // the code↔collective bridge the membrane exists to prevent.
15266
15260
  ANCHORED_AT: {
15267
- from: ["Problem", "Vulnerability", "Solution", "RootCause", "Claim"],
15261
+ from: ["Problem", "Solution", "RootCause", "Claim"],
15268
15262
  to: ["Symbol"]
15269
15263
  },
15270
15264
  // ── Security spine (v1 taxonomy.ts SECURITY_FORWARD_ONLY commentary) ──
@@ -15309,7 +15303,7 @@ var init_edge_rules = __esm({
15309
15303
  // `Component` joined the target set with OM-agent-anchors: an agent-named
15310
15304
  // component ("React Router") is the same knowledge→named-unit anchor shape as
15311
15305
  // a Tool — the knowledge is ABOUT it, not dependent on it.
15312
- CONCERNS: { from: ["Problem", "Vulnerability", "Solution", "RootCause", "Claim", "Pattern"], to: ["Tool", "Component"] },
15306
+ CONCERNS: { from: ["Problem", "Solution", "RootCause", "Claim", "Pattern"], to: ["Tool", "Component"] },
15313
15307
  OPERATES_ON: { from: ["Algorithm"], to: ["DataStructure"] },
15314
15308
  INVOLVES: { from: ["Problem", "Solution"], to: ["DataStructure"] },
15315
15309
  // ── Taxonomy (Track 4 Stream C: MITRE CWE `ChildOf` → `Weakness —IS_A→ Weakness`) ──
@@ -16416,8 +16410,7 @@ CREATE INDEX IF NOT EXISTS nodes_live ON nodes(label, valid_to);
16416
16410
  -- its table row. Partial, so it maintains a few thousand rows instead of adding
16417
16411
  -- a write to every node write. Its label list is FINGERPRINT_INDEXED_LABELS.
16418
16412
  DROP INDEX IF EXISTS nodes_live_fingerprint;
16419
- DROP INDEX IF EXISTS nodes_instance_fingerprint;
16420
- CREATE INDEX IF NOT EXISTS nodes_instance_fingerprint_v2 ON nodes(label, last_updated_at, last_reinforced_at_seq, created_at_seq) WHERE valid_to IS NULL AND label IN ('Problem','Vulnerability','Solution','RootCause');
16413
+ CREATE INDEX IF NOT EXISTS nodes_instance_fingerprint ON nodes(label, last_updated_at, last_reinforced_at_seq, created_at_seq) WHERE valid_to IS NULL AND label IN ('Problem','Solution','RootCause');
16421
16414
  CREATE INDEX IF NOT EXISTS nodes_logical ON nodes(logical_id, version);
16422
16415
  CREATE INDEX IF NOT EXISTS edges_live ON edges(valid_to);
16423
16416
  -- Expression index on the per-node relPath (stored in attrs_json) so the
@@ -16488,7 +16481,7 @@ function rowToEdge(r) {
16488
16481
  attrs: JSON.parse(r.attrs_json)
16489
16482
  };
16490
16483
  }
16491
- var FINGERPRINT_INDEXED_LABELS = ["Problem", "Vulnerability", "Solution", "RootCause"];
16484
+ var FINGERPRINT_INDEXED_LABELS = ["Problem", "Solution", "RootCause"];
16492
16485
  var SqliteGraphStore = class {
16493
16486
  db;
16494
16487
  // Typed edge lookups build their SQL from the number of types asked for, and
@@ -17166,8 +17159,8 @@ var SqliteGraphStore = class {
17166
17159
  const r2 = this.db.prepare(
17167
17160
  `SELECT COUNT(*) AS n, MAX(last_updated_at) AS t,
17168
17161
  MAX(COALESCE(last_reinforced_at_seq, created_at_seq, 0)) AS s
17169
- FROM nodes INDEXED BY nodes_instance_fingerprint_v2
17170
- WHERE valid_to IS NULL AND label IN ('Problem','Vulnerability','Solution','RootCause')`
17162
+ FROM nodes INDEXED BY nodes_instance_fingerprint
17163
+ WHERE valid_to IS NULL AND label IN ('Problem','Solution','RootCause')`
17171
17164
  ).get();
17172
17165
  return `${r2.n}:${r2.t ?? 0}:${r2.s ?? 0}`;
17173
17166
  }
@@ -19396,7 +19389,7 @@ function generalizeFileRefs(text, fileLexicon, level = 1) {
19396
19389
  }
19397
19390
 
19398
19391
  // src/instance-ingest.ts
19399
- var INSTANCE_LABELS = ["Problem", "Vulnerability", "Solution", "RootCause"];
19392
+ var INSTANCE_LABELS = ["Problem", "Solution", "RootCause"];
19400
19393
  var INSTANCE_EDGES = ["CAUSED_BY", "SOLVED_BY"];
19401
19394
  var ANCHOR_EDGES = ["OCCURS_IN", "DEPENDS_ON", "PERTAIN_TO", "CONCERNS"];
19402
19395
  var ANCHOR_TARGET_LABELS = ["Language", "Package", "Domain", "Component"];
@@ -19516,10 +19509,6 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19516
19509
  attrs: {
19517
19510
  scope: stripCodebaseScope(n.attrs["scope"]),
19518
19511
  ...n.attrs["kind"] ? { kind: n.attrs["kind"] } : {},
19519
- ...n.attrs["privateFinding"] ? { privateFinding: true } : {},
19520
- ...n.attrs["assessment"] ? { assessment: n.attrs["assessment"] } : {},
19521
- ...n.attrs["sourceClass"] ? { sourceClass: n.attrs["sourceClass"] } : {},
19522
- ...n.attrs["resolutionWitnessed"] ? { resolutionWitnessed: true, resolvedAt: n.attrs["resolvedAt"] } : {},
19523
19512
  ...n.attrs["resolvedAs"] ? { resolvedAs: n.attrs["resolvedAs"] } : {},
19524
19513
  ...preserved.length > 0 ? { preservedSymbols: preserved } : {},
19525
19514
  ...internal.length > 0 ? { internalSymbols: internal } : {}
@@ -19534,7 +19523,6 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19534
19523
  const semanticEndpoints = /* @__PURE__ */ new Map();
19535
19524
  const includedByLabel = /* @__PURE__ */ new Map();
19536
19525
  const composition = {
19537
- privateTargetMissing: 0,
19538
19526
  candidates: 0,
19539
19527
  shipped: 0,
19540
19528
  cloudSourced: 0,
@@ -19580,15 +19568,11 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19580
19568
  if (walked.has(n.id)) continue;
19581
19569
  walked.add(n.id);
19582
19570
  composition.candidates++;
19583
- if ((n.attrs["privateFinding"] || n.label === "Vulnerability") && !opts.project) {
19584
- composition.privateTargetMissing++;
19585
- continue;
19586
- }
19587
19571
  if (n.attrs["source"] === "cloud") {
19588
19572
  composition.cloudSourced++;
19589
19573
  continue;
19590
19574
  }
19591
- if (n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) {
19575
+ if (label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) {
19592
19576
  composition.falsePositive++;
19593
19577
  continue;
19594
19578
  }
@@ -19611,7 +19595,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19611
19595
  composition.terminalRefused++;
19612
19596
  continue;
19613
19597
  }
19614
- if (!n.attrs["privateFinding"] && !noveltyAgainst(n, ref, noveltyOpts).ready) {
19598
+ if (!noveltyAgainst(n, ref, noveltyOpts).ready) {
19615
19599
  composition.notNovel++;
19616
19600
  continue;
19617
19601
  }
@@ -19654,7 +19638,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
19654
19638
  }
19655
19639
  if (targets.length === 0) continue;
19656
19640
  const shipped = shippedById.get(sourceId);
19657
- if (shipped && !shipped.attrs["privateFinding"]) {
19641
+ if (shipped) {
19658
19642
  const anchors = (label) => targets.filter((x) => x.t.label === label).map(
19659
19643
  (x) => label === "Language" ? langAnchor(x.t) : label === "Component" ? `component:${x.wireId}` : x.wireId
19660
19644
  ).filter((a) => a != null).sort();
package/errata.mjs CHANGED
@@ -139,7 +139,6 @@ var init_castalia = __esm({
139
139
  ROUTING_REASONS = [
140
140
  /** Harness org (CTF lane, e2e battery, canary) — forced org-private. */
141
141
  "harness-clamp",
142
- "witnessed-vulnerability-private",
143
142
  /** A signed gateway write target named the destination. */
144
143
  "signed-target-public",
145
144
  "signed-target-org",
@@ -1081,12 +1080,6 @@ function identityId(input) {
1081
1080
  }
1082
1081
  case "Claim":
1083
1082
  return canonicalClaimId(input.text, input.scope);
1084
- case "WitnessedVulnerability":
1085
- return genericCanonicalId("dvuln", {
1086
- workspaceId: input.workspaceId,
1087
- target: input.target.replace(/\\/g, "/").replace(/^\.\//, ""),
1088
- statement: canonicalClaimId(input.statement.trim())
1089
- });
1090
1083
  case "DesignProblem":
1091
1084
  return `${DESIGN_PROBLEM_PREFIX}${canonicalClaimId(input.statement.trim())}`.slice(
1092
1085
  0,
@@ -15856,7 +15849,7 @@ var init_edge_rules = __esm({
15856
15849
  // anchor anything at anything, e.g. at a public `Package`, quietly re-creating
15857
15850
  // the code↔collective bridge the membrane exists to prevent.
15858
15851
  ANCHORED_AT: {
15859
- from: ["Problem", "Vulnerability", "Solution", "RootCause", "Claim"],
15852
+ from: ["Problem", "Solution", "RootCause", "Claim"],
15860
15853
  to: ["Symbol"]
15861
15854
  },
15862
15855
  // ── Security spine (v1 taxonomy.ts SECURITY_FORWARD_ONLY commentary) ──
@@ -15901,7 +15894,7 @@ var init_edge_rules = __esm({
15901
15894
  // `Component` joined the target set with OM-agent-anchors: an agent-named
15902
15895
  // component ("React Router") is the same knowledge→named-unit anchor shape as
15903
15896
  // a Tool — the knowledge is ABOUT it, not dependent on it.
15904
- CONCERNS: { from: ["Problem", "Vulnerability", "Solution", "RootCause", "Claim", "Pattern"], to: ["Tool", "Component"] },
15897
+ CONCERNS: { from: ["Problem", "Solution", "RootCause", "Claim", "Pattern"], to: ["Tool", "Component"] },
15905
15898
  OPERATES_ON: { from: ["Algorithm"], to: ["DataStructure"] },
15906
15899
  INVOLVES: { from: ["Problem", "Solution"], to: ["DataStructure"] },
15907
15900
  // ── Taxonomy (Track 4 Stream C: MITRE CWE `ChildOf` → `Weakness —IS_A→ Weakness`) ──
@@ -18281,8 +18274,7 @@ CREATE INDEX IF NOT EXISTS nodes_live ON nodes(label, valid_to);
18281
18274
  -- its table row. Partial, so it maintains a few thousand rows instead of adding
18282
18275
  -- a write to every node write. Its label list is FINGERPRINT_INDEXED_LABELS.
18283
18276
  DROP INDEX IF EXISTS nodes_live_fingerprint;
18284
- DROP INDEX IF EXISTS nodes_instance_fingerprint;
18285
- CREATE INDEX IF NOT EXISTS nodes_instance_fingerprint_v2 ON nodes(label, last_updated_at, last_reinforced_at_seq, created_at_seq) WHERE valid_to IS NULL AND label IN ('Problem','Vulnerability','Solution','RootCause');
18277
+ CREATE INDEX IF NOT EXISTS nodes_instance_fingerprint ON nodes(label, last_updated_at, last_reinforced_at_seq, created_at_seq) WHERE valid_to IS NULL AND label IN ('Problem','Solution','RootCause');
18286
18278
  CREATE INDEX IF NOT EXISTS nodes_logical ON nodes(logical_id, version);
18287
18279
  CREATE INDEX IF NOT EXISTS edges_live ON edges(valid_to);
18288
18280
  -- Expression index on the per-node relPath (stored in attrs_json) so the
@@ -18296,7 +18288,7 @@ CREATE INDEX IF NOT EXISTS nodes_live_description ON nodes(description, label) W
18296
18288
  -- every edited file of every turn, and a scan parses every Problem's attrs.
18297
18289
  CREATE INDEX IF NOT EXISTS nodes_anchor_hint_path ON nodes(json_extract(attrs_json, '$.anchorHint.path')) WHERE valid_to IS NULL;
18298
18290
  `;
18299
- FINGERPRINT_INDEXED_LABELS = ["Problem", "Vulnerability", "Solution", "RootCause"];
18291
+ FINGERPRINT_INDEXED_LABELS = ["Problem", "Solution", "RootCause"];
18300
18292
  SqliteGraphStore = class {
18301
18293
  db;
18302
18294
  // Typed edge lookups build their SQL from the number of types asked for, and
@@ -18974,8 +18966,8 @@ CREATE INDEX IF NOT EXISTS nodes_anchor_hint_path ON nodes(json_extract(attrs_js
18974
18966
  const r2 = this.db.prepare(
18975
18967
  `SELECT COUNT(*) AS n, MAX(last_updated_at) AS t,
18976
18968
  MAX(COALESCE(last_reinforced_at_seq, created_at_seq, 0)) AS s
18977
- FROM nodes INDEXED BY nodes_instance_fingerprint_v2
18978
- WHERE valid_to IS NULL AND label IN ('Problem','Vulnerability','Solution','RootCause')`
18969
+ FROM nodes INDEXED BY nodes_instance_fingerprint
18970
+ WHERE valid_to IS NULL AND label IN ('Problem','Solution','RootCause')`
18979
18971
  ).get();
18980
18972
  return `${r2.n}:${r2.t ?? 0}:${r2.s ?? 0}`;
18981
18973
  }
@@ -20271,7 +20263,7 @@ function mergeContextEdge(store, from, to, type, ts) {
20271
20263
  function deriveContextFromAnchors(store, problemId, ts, pkgIndex) {
20272
20264
  const report = { languages: [], packages: [] };
20273
20265
  const p = store.getNode(problemId);
20274
- if (!p || p.label !== "Problem" && p.label !== "Vulnerability") return report;
20266
+ if (!p || p.label !== "Problem") return report;
20275
20267
  const files = store.outEdges(problemId, ["ANCHORED_AT"]).map((e) => store.getNode(e.to)).filter((n) => !!n && n.label === "File");
20276
20268
  if (files.length === 0) return report;
20277
20269
  const idx = pkgIndex ?? buildPackageIndex(store);
@@ -20909,81 +20901,6 @@ function ingestDesignProblem(store, flag, opts) {
20909
20901
  ...reopenedFromRegression ? { reopenedFromRegression } : {}
20910
20902
  };
20911
20903
  }
20912
- function ingestWitnessedVulnerability(store, flag, opts) {
20913
- const statement = flag.statement.trim();
20914
- if (isPlaceholderStatement(statement)) return { id: "", created: false, corroborated: false, upgraded: false, rejected: "statement" };
20915
- const target = flag.target?.trim().replace(/\\/g, "/").replace(/^\.\//, "") ?? "";
20916
- const file2 = target ? resolveFileNode(store, target, opts.workspaceId) : null;
20917
- const symbol2 = file2 && flag.line !== void 0 && flag.fileText !== void 0 ? resolveEnclosingSymbol(store, file2.id, flag.line, flag.fileText) : null;
20918
- const identityTarget = symbol2 ? String(symbol2.attrs["logicalId"] ?? `${target}#${symbol2.attrs["qname"] ?? symbol2.description}`) : target;
20919
- const compatibleTarget = (n) => !symbol2 || !n.attrs["identityTarget"] || n.attrs["identityTarget"] === target || n.attrs["identityTarget"] === identityTarget;
20920
- const bound = flag.existingId ? store.getNode(flag.existingId) : null;
20921
- if (flag.existingId && (!bound || bound.label !== "Vulnerability" || bound.attrs["workspaceId"] !== opts.workspaceId || target && bound.attrs["affectedTarget"] && bound.attrs["affectedTarget"] !== target || !compatibleTarget(bound))) {
20922
- return { id: "", created: false, corroborated: false, upgraded: false, rejected: "binding-conflict" };
20923
- }
20924
- const statementKey = identityId({ kind: "DesignProblem", statement });
20925
- const restated = bound ? null : store.findNodesByLabel("Vulnerability").find((n) => n.attrs["workspaceId"] === opts.workspaceId && n.attrs["affectedTarget"] === target && compatibleTarget(n) && [n.description, ...n.attrs["statementAliases"] ?? []].some((s) => identityId({ kind: "DesignProblem", statement: s }) === statementKey));
20926
- const id = bound?.id ?? restated?.id ?? identityId({ kind: "WitnessedVulnerability", workspaceId: opts.workspaceId, target: identityTarget, statement });
20927
- const existing = bound ?? store.getNode(id);
20928
- const sources = existing?.attrs["sources"] ?? [];
20929
- const corroborated = !!existing && !sources.includes(opts.source);
20930
- const upgraded = !!existing && existing.attrs["assessment"] !== "asserted" && flag.assessment === "asserted";
20931
- const assessment = existing?.attrs["assessment"] === "asserted" ? "asserted" : flag.assessment;
20932
- if (!existing) {
20933
- store.mergeNode(buildNode(store, id, "Vulnerability", statement, opts.ts, {
20934
- source: "convo",
20935
- sourceClass: "agent-observation",
20936
- privateFinding: id,
20937
- workspaceId: opts.workspaceId,
20938
- affectedTarget: target,
20939
- identityTarget,
20940
- assessment,
20941
- anchorDisposition: target ? "unresolved" : "absent",
20942
- provisional: true,
20943
- sources: [opts.source],
20944
- corroborations: 0,
20945
- ...opts.hostHarness ? { hostHarness: opts.hostHarness } : {}
20946
- }));
20947
- } else if (corroborated || upgraded || !existing.attrs["affectedTarget"] && target || symbol2 && existing.attrs["identityTarget"] !== identityTarget) {
20948
- store.updateNode(id, {
20949
- attrs: {
20950
- ...existing.attrs,
20951
- assessment,
20952
- ...upgraded && existing.description !== statement ? { statementAliases: [...existing.attrs["statementAliases"] ?? [], existing.description].slice(-5) } : {},
20953
- affectedTarget: existing.attrs["affectedTarget"] || target,
20954
- ...symbol2 ? { identityTarget } : {},
20955
- sources: corroborated ? [...sources, opts.source] : sources,
20956
- corroborations: (Number(existing.attrs["corroborations"]) || 0) + (corroborated ? 1 : 0)
20957
- },
20958
- // Assessment strengthens on evidence, but does not certify exploitability.
20959
- ...upgraded ? { description: statement } : {},
20960
- ...corroborated ? { cumulativeHits: existing.cumulativeHits + 1 } : {},
20961
- ...reinforcedSeqAttrs(store, "Vulnerability"),
20962
- lastUpdatedAt: opts.ts
20963
- });
20964
- }
20965
- return { id, created: !existing, corroborated, upgraded };
20966
- }
20967
- function recordVulnerabilityCause(store, findingId, causes, ts) {
20968
- const finding = store.getNode(findingId);
20969
- if (finding?.label !== "Vulnerability") return 0;
20970
- let from = findingId;
20971
- let count = 0;
20972
- for (const description of causes) {
20973
- if (isPlaceholderStatement(description)) continue;
20974
- const id = genericCanonicalId("dcause", { findingId, description: description.trim() });
20975
- if (!store.getNode(id)) store.mergeNode(buildNode(store, id, "RootCause", description.trim(), ts, {
20976
- source: "convo",
20977
- privateFinding: findingId,
20978
- sources: finding.attrs["sources"],
20979
- assessment: finding.attrs["assessment"]
20980
- }));
20981
- mergeEdge(store, from, id, "CAUSED_BY", ts);
20982
- from = id;
20983
- count++;
20984
- }
20985
- return count;
20986
- }
20987
20904
  function canonicalizePatternText(name2) {
20988
20905
  const stripped = name2.replace(/^\s*pattern(?:\s*[×x]\s*\d+)?\s*(?:\(exemplar\))?\s*[:—–-]\s*/i, "").replace(/\s+/g, " ").trim();
20989
20906
  return stripped.length > 0 ? stripped : name2.replace(/\s+/g, " ").trim();
@@ -21294,7 +21211,6 @@ function findReusableSolution(store, fixText) {
21294
21211
  const key = solutionTextKey(fixText);
21295
21212
  if (!key) return null;
21296
21213
  for (const s of store.findNodesByLabel("Solution")) {
21297
- if (s.attrs["privateFinding"]) continue;
21298
21214
  if (s.validTo != null) continue;
21299
21215
  if (isAutoMinted(s)) continue;
21300
21216
  if (solutionTextKey(s.description ?? "") === key) return s;
@@ -21319,7 +21235,7 @@ function priorsForFile(store, relPath) {
21319
21235
  for (const e of store.inEdges(file2.id, ["ANCHORED_AT"])) {
21320
21236
  const n = store.getNode(e.from);
21321
21237
  if (!n) continue;
21322
- if (n.label === "Problem" || n.label === "Vulnerability") {
21238
+ if (n.label === "Problem") {
21323
21239
  if (seenProblem.has(n.id)) continue;
21324
21240
  seenProblem.add(n.id);
21325
21241
  if (!n.attrs["resolvedAt"]) {
@@ -21389,8 +21305,7 @@ function solutionForProblem(store, problemId) {
21389
21305
  }
21390
21306
  function anchorProblemToWorkingFile(store, problemId, relPath, workspaceId2, ts, provenance = "edited", opts = {}) {
21391
21307
  const p = store.getNode(problemId);
21392
- if (!p || p.label !== "Problem" && p.label !== "Vulnerability") return false;
21393
- if (p.label === "Vulnerability" && provenance !== "witnessed") return false;
21308
+ if (!p || p.label !== "Problem") return false;
21394
21309
  if (!isAnchorableCodePath(relPath)) return false;
21395
21310
  const file2 = resolveFileNode(store, relPath, workspaceId2);
21396
21311
  if (!file2) return false;
@@ -21569,22 +21484,18 @@ function resolveDesignProblemById(store, id, fixNote, t) {
21569
21484
  }
21570
21485
  function closeDesignProblem(store, problemId, fixNote, t) {
21571
21486
  const p = store.getNode(problemId);
21572
- if (!p || p.label !== "Problem" && p.label !== "Vulnerability") return false;
21487
+ if (!p || p.label !== "Problem") return false;
21573
21488
  if (p.attrs["resolvedAs"]) return false;
21574
21489
  if (fixNote?.trim() && !isFragmentFixNote(fixNote)) {
21575
21490
  const sols = store.outEdges(problemId, ["SOLVED_BY"]).map((e) => store.getNode(e.to)).filter((n) => n !== null);
21576
21491
  if (sols.every((s) => isAutoMinted(s))) {
21577
- const reuse = p.label === "Vulnerability" ? null : findReusableSolution(store, fixNote);
21492
+ const reuse = findReusableSolution(store, fixNote);
21578
21493
  if (reuse) {
21579
21494
  mergeEdge(store, problemId, reuse.id, "SOLVED_BY", t);
21580
21495
  } else {
21581
21496
  const solId = `dfix_${digest({ problemId, fix: fixNote })}`.slice(0, 56);
21582
21497
  store.mergeNode(
21583
- buildNode(store, solId, "Solution", fixNote.trim(), t, {
21584
- source: "convo",
21585
- provisional: false,
21586
- ...p.label === "Vulnerability" ? { privateFinding: problemId, sources: p.attrs["sources"] } : {}
21587
- })
21498
+ buildNode(store, solId, "Solution", fixNote.trim(), t, { source: "convo", provisional: false })
21588
21499
  );
21589
21500
  mergeEdge(store, problemId, solId, "SOLVED_BY", t);
21590
21501
  }
@@ -21598,7 +21509,6 @@ function closeDesignProblem(store, problemId, fixNote, t) {
21598
21509
  // mints no Solution, and a legacy placeholder beside it reads as
21599
21510
  // all-heuristic either way.
21600
21511
  attrs: { ...p.attrs, provisional: false, resolvedAt: t, resolutionWitnessed: true },
21601
- ...reinforcedSeqAttrs(store, p.label),
21602
21512
  lastUpdatedAt: t
21603
21513
  });
21604
21514
  return true;
@@ -23950,7 +23860,7 @@ function detectLocalCommunities(store, opts = {}) {
23950
23860
  const ids = /* @__PURE__ */ new Set();
23951
23861
  for (const label of JOINT_COMMUNITY_LABELS) {
23952
23862
  for (const n of store.findNodesByLabel(label)) {
23953
- if (n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) continue;
23863
+ if (label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) continue;
23954
23864
  ids.add(n.id);
23955
23865
  }
23956
23866
  }
@@ -24087,7 +23997,6 @@ var init_community2 = __esm({
24087
23997
  init_src4();
24088
23998
  JOINT_COMMUNITY_LABELS = [
24089
23999
  "Problem",
24090
- "Vulnerability",
24091
24000
  "Solution",
24092
24001
  "RootCause",
24093
24002
  "Pattern"
@@ -24949,7 +24858,6 @@ __export(src_exports2, {
24949
24858
  induceAbstractions: () => induceAbstractions,
24950
24859
  induceTriage: () => induceTriage,
24951
24860
  ingestDesignProblem: () => ingestDesignProblem,
24952
- ingestWitnessedVulnerability: () => ingestWitnessedVulnerability,
24953
24861
  isConstraintProblem: () => isConstraintProblem,
24954
24862
  isFragmentFixNote: () => isFragmentFixNote,
24955
24863
  isPlaceholderStatement: () => isPlaceholderStatement,
@@ -24997,7 +24905,6 @@ __export(src_exports2, {
24997
24905
  recordMisreadPrior: () => recordMisreadPrior,
24998
24906
  recordRenderLedger: () => recordRenderLedger,
24999
24907
  recordTriageObservation: () => recordTriageObservation,
25000
- recordVulnerabilityCause: () => recordVulnerabilityCause,
25001
24908
  reinforceSameAnchorProblem: () => reinforceSameAnchorProblem,
25002
24909
  relateClaims: () => relateClaims,
25003
24910
  reopenAutoClosedProblems: () => reopenAutoClosedProblems,
@@ -25067,7 +24974,7 @@ function isPassiveInjectable(node2, atCommit) {
25067
24974
  return false;
25068
24975
  }
25069
24976
  function buildSnapshot(opts) {
25070
- const problems = [...opts.store.findNodesByLabel("Problem"), ...opts.store.findNodesByLabel("Vulnerability")].filter((p) => p.attrs["mergedInto"] === void 0 && historyReadPolicy(p, { mode: "passive", atCommit: opts.atCommit }).allow);
24977
+ const problems = opts.store.findNodesByLabel("Problem").filter((p) => p.attrs["mergedInto"] === void 0 && historyReadPolicy(p, { mode: "passive", atCommit: opts.atCommit }).allow);
25071
24978
  const stillOpen = problems.filter((p) => p.attrs["resolvedAt"] == null);
25072
24979
  const allProblems = stillOpen.filter((p) => !isConstraintProblem(p));
25073
24980
  allProblems.sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt);
@@ -25222,11 +25129,11 @@ function sliceForFile(store, relPath, atCommit) {
25222
25129
  const priors = fp ? {
25223
25130
  openProblems: fp.openProblems.slice(0, 3).map((p) => ({
25224
25131
  id: p.id,
25225
- description: p.label === "Vulnerability" ? `Vulnerability (${p.attrs["assessment"] ?? "unassessed"}): ${p.description}` : p.description,
25132
+ description: p.description,
25226
25133
  ...typeof p.attrs["fixCandidateFile"] === "string" ? { fixCandidateFile: p.attrs["fixCandidateFile"] } : {}
25227
25134
  })),
25228
25135
  constraints: fp.constraints.slice(0, 2).map((c) => ({ id: c.id, description: c.description })),
25229
- resolvedProblems: fp.resolvedProblems.slice(0, 3).map((p) => ({ id: p.id, description: p.label === "Vulnerability" ? `Vulnerability (${p.attrs["assessment"] ?? "unassessed"}): ${p.description}` : p.description })),
25136
+ resolvedProblems: fp.resolvedProblems.slice(0, 3).map((p) => ({ id: p.id, description: p.description })),
25230
25137
  related: fp.related.slice(0, 4).map((n) => ({ id: n.id, label: n.label, description: n.description })),
25231
25138
  solutionsByProblem: Object.fromEntries(
25232
25139
  [...fp.openProblems.slice(0, 3), ...fp.resolvedProblems.slice(0, 3)].map((p) => [
@@ -25344,8 +25251,7 @@ function renderSnapshot(s) {
25344
25251
  if (s.recentProblems.length > 0) {
25345
25252
  lines.push("_Open \u2014 recently observed here, derived from your work (a recency slice, not an inventory \u2014 burst an id for its full neighborhood):_");
25346
25253
  for (const r of s.recentProblems) {
25347
- const badge = r.node.label === "Vulnerability" ? `Vulnerability (${r.node.attrs["assessment"] ?? "unassessed"}): ` : "";
25348
- lines.push(`- **${badge}${r.node.description}** \u2014 \`${r.node.id}\`${tagOf(r.node)}`);
25254
+ lines.push(`- **${r.node.description}** \u2014 \`${r.node.id}\`${tagOf(r.node)}`);
25349
25255
  const hits = r.node.cumulativeHits ?? 0;
25350
25256
  const surprise = (r.node.cumulativeSurprise ?? 0).toFixed(2);
25351
25257
  lines.push(` - observed ${hits}\xD7 \xB7 cumulativeSurprise ${surprise}`);
@@ -25386,8 +25292,7 @@ function renderSnapshot(s) {
25386
25292
  if (s.recentResolved.length > 0) {
25387
25293
  lines.push("_Recently resolved \u2014 solved here; jumping-off points, not live defects:_");
25388
25294
  for (const r of s.recentResolved) {
25389
- const badge = r.node.label === "Vulnerability" ? `Vulnerability (${r.node.attrs["assessment"] ?? "unassessed"}): ` : "";
25390
- lines.push(`- \u2713 **${badge}${r.node.description}** \u2014 \`${r.node.id}\`${tagOf(r.node)}`);
25295
+ lines.push(`- \u2713 **${r.node.description}** \u2014 \`${r.node.id}\`${tagOf(r.node)}`);
25391
25296
  if (r.solution) {
25392
25297
  lines.push(` - solved: ${r.solution.description.slice(0, 160)} \u2014 \`${r.solution.id}\`${tagOf(r.solution)}`);
25393
25298
  }
@@ -27247,8 +27152,8 @@ var init_config = __esm({
27247
27152
  "use strict";
27248
27153
  init_paths();
27249
27154
  LEGACY_CLOUD_URL = "https://inerrata-gateway.onrender.com";
27250
- DEFAULT_CLOUD_URL = true ? "https://dev.inerrata.dev" : DEV_CLOUD_URL;
27251
- DEFAULT_UPDATE_CHANNEL = false ? "latest" : "dev";
27155
+ DEFAULT_CLOUD_URL = true ? "https://inerrata.dev" : DEV_CLOUD_URL;
27156
+ DEFAULT_UPDATE_CHANNEL = true ? "latest" : "dev";
27252
27157
  }
27253
27158
  });
27254
27159
 
@@ -31808,7 +31713,7 @@ var init_src8 = __esm({
31808
31713
 
31809
31714
  // src/agent-signals.ts
31810
31715
  function buildFileRecallInstruction(referent = "\u2026") {
31811
- return `Touching one? paste its token: ${TAG_EXAMPLE.fix(referent)} resolved \xB7 ${TAG_EXAMPLE.prior(referent)} leaned-on \xB7 ${TAG_EXAMPLE.problem()} new \xB7 ${TAG_EXAMPLE.vulnerability()} security. We harvest it.`;
31716
+ return `Touching one? paste its token: ${TAG_EXAMPLE.fix(referent)} resolved \xB7 ${TAG_EXAMPLE.prior(referent)} leaned-on \xB7 ${TAG_EXAMPLE.problem()} new. We harvest it.`;
31812
31717
  }
31813
31718
  function triageBullet(ref) {
31814
31719
  return [
@@ -31844,15 +31749,15 @@ function attemptBullet() {
31844
31749
  ].join("\n");
31845
31750
  }
31846
31751
  function buildAgentInstruction(opts = {}) {
31847
- const signals = opts.signals ?? ["prior", "problem", "vulnerability", "domain", "fix", "constraint", "triage", "attempt", "link"];
31752
+ const signals = opts.signals ?? ["prior", "problem", "domain", "fix", "constraint", "triage", "attempt", "link"];
31848
31753
  const ref = opts.referent ?? "its-handle";
31849
31754
  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);
31850
- 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:";
31851
- 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).";
31755
+ const head2 = `We tag the priors we show you with a short handle like [${opts.handleExample ?? "chokidar-glob"}]. Untagged prose is silently lost. Put each tag inline in prose (no fences or backticks). Requested errata-* answer blocks are the exception: keep their fences in your turn-final reply. Tag everything, we filter downstream:`;
31756
+ const tail = "Mid-turn text (between tool calls) can be dropped by the harness \u2014 RESTATE every tag in your turn-final message; the final message is what reliably survives \u2014 EXCEPT one already shown above with an id: that is captured, so cite `[its-handle]` rather than retyping it (drift mints a duplicate).";
31852
31757
  return [
31853
31758
  head2,
31854
31759
  ...signals.map(
31855
- (s) => s === "triage" ? triageBullet(ref) : s === "vulnerability" ? ` \u2022 ${GLOSS.vulnerability} \u2192 ${TAG_EXAMPLE.vulnerability()}. Uncertain? ${TAG_EXAMPLE.suspectedVulnerability()}. Code review counts, even if immediately fixed. No CVE/exploit needed. For fixes: ${TAG_EXAMPLE.vulnerabilityThread()} ${TAG_EXAMPLE.fixThread("v")}.` : s === "attempt" ? attemptBullet() : s === "link" ? linkBullet(ref) : s === "verdict" ? verdictBullet(ref) : ` \u2022 ${GLOSS[s]} \u2192 ${token(s)}`
31760
+ (s) => s === "triage" ? triageBullet(ref) : s === "attempt" ? attemptBullet() : s === "link" ? linkBullet(ref) : s === "verdict" ? verdictBullet(ref) : ` \u2022 ${GLOSS[s]} \u2192 ${token(s)}`
31856
31761
  ),
31857
31762
  tail
31858
31763
  ].join("\n");
@@ -31864,9 +31769,6 @@ var init_agent_signals = __esm({
31864
31769
  TAG_EXAMPLE = {
31865
31770
  prior: (ref) => `([${ref}])`,
31866
31771
  problem: () => `[!one line on what's wrong]`,
31867
- vulnerability: () => `[!vuln: who can do what; observed basis @ path:line]`,
31868
- suspectedVulnerability: () => `[?vuln: consequence; missing check]`,
31869
- vulnerabilityThread: () => `[!#v vuln: finding here]`,
31870
31772
  fix: (ref) => `(fix:[${ref}])`,
31871
31773
  // CONSTRAINT — the native capture path for a DIFFUSE problem (a constraint/tension/
31872
31774
  // conflict that shaped a decision). Free text, attaches to the decision sentence the
@@ -31887,7 +31789,7 @@ var init_agent_signals = __esm({
31887
31789
  // tags never need one — the id is for diagnoses that unfold over distance.
31888
31790
  problemThread: () => `[!#slug one line on what's wrong]`,
31889
31791
  causeThread: () => `(cause:#slug the mechanism)`,
31890
- fixThread: (thread = "slug") => `(fix:#${thread} what you changed)`,
31792
+ fixThread: () => `(fix:#slug what you changed)`,
31891
31793
  // ATTEMPT arc — what's being tried and what didn't work. A failed attempt is a
31892
31794
  // witnessed NEGATIVE result: it saves the next agent the same dead end.
31893
31795
  tried: () => `(tried: the approach you're attempting)`,
@@ -31929,9 +31831,8 @@ var init_agent_signals = __esm({
31929
31831
  // problems, and narrated them as progress (a pick-best-before-scoring bug lost).
31930
31832
  // Every example here was diagnosis-framed, so nothing contradicted that sorting.
31931
31833
  // Kept to 29 chars: the instruction sits at the 2600 passive-budget ceiling.
31932
- problem: "any bug or finding, even in code you just wrote; name affected code: [!what's wrong @ path:42]",
31933
- vulnerability: "unauthorized actions, data exposure, or execution/disruption an attacker can trigger",
31934
- fix: "you fixed a shown finding; for your own non-security finding: (fix: what changed) \u2014 a fix resolves a stated problem, completing routine work is not a fix",
31834
+ problem: "a problem you notice or report \u2014 any bug, finding, or thing wrong, even in code you just wrote; about specific code? name the file: [!what's wrong @ src/file.ts:42]",
31835
+ fix: "your edit fixed a PROBLEM we showed you; for one you flagged yourself: (fix: what you changed) \u2014 a fix resolves a stated problem, completing routine work is not a fix",
31935
31836
  constraint: "a design decision forced by conflicting requirements or constraints \u2014 tag the tension, especially when your fix makes it 'only look' resolved",
31936
31837
  triage: "you diagnosed a cause \u2014 fold the chain into the flag with <- (caused-by), deepest sure mechanism rightmost",
31937
31838
  attempt: "attempting an approach / an attempt failed \u2014 a failed attempt is knowledge, it rules out a path",
@@ -31953,7 +31854,7 @@ var init_agent_signals = __esm({
31953
31854
  // Sim note (2026-08-02 shrink): domain emission held 4/4 with just the trigger
31954
31855
  // clause; the pattern convergence hook now rides here too (it fell 0/4 when it
31955
31856
  // only appeared in the link bullet's tail).
31956
- domain: "no single file? name the area (Title Case), and (pattern: the shape). No code anchor needed; two agents naming the same shape converge on one node",
31857
+ domain: "a problem with no single file \u2014 name the area it's about (Title Case). Also name the general shape it instantiates: (pattern: the shape) \u2014 needs no code anchor, and two agents naming the same shape converge on one node",
31957
31858
  link: "the problem you flagged is an instance of priors/abstractions you can name \u2014 (instance:[h1],[h2],\u2026) / (pattern: \u2026) / (aids:[h]); rendered whole via linkBullet",
31958
31859
  verdict: "you can judge a prior we SHOWED you \u2014 confirm it if it held, refute it (with why) if it didn't; rendered whole via verdictBullet"
31959
31860
  };
@@ -32194,7 +32095,7 @@ function readContextCard(root, hash2) {
32194
32095
  function openProblems(store, now = Date.now()) {
32195
32096
  const hit = openProblemsCache.get(store);
32196
32097
  if (hit && now - hit.at < OPEN_PROBLEMS_TTL_MS) return hit.nodes;
32197
- const nodes = [...store.findNodesByLabel("Problem"), ...store.findNodesByLabel("Vulnerability")].filter((p) => live(p) && !p.attrs["resolvedAt"] && p.attrs["mergedInto"] === void 0 && !isConstraintProblem(p));
32098
+ const nodes = store.findNodesByLabel("Problem").filter((p) => live(p) && !p.attrs["resolvedAt"] && p.attrs["mergedInto"] === void 0 && !isConstraintProblem(p));
32198
32099
  openProblemsCache.set(store, { at: now, nodes });
32199
32100
  return nodes;
32200
32101
  }
@@ -43581,9 +43482,47 @@ var init_mcp = __esm({
43581
43482
  init_reconcile();
43582
43483
  init_agent_signals();
43583
43484
  INSTRUCTIONS = [
43584
- "errata is a live code and knowledge graph, a SEPARATE DIAGNOSTIC AXIS alongside grep/read for callers, blast radius, rename lineage and prior fixes. Fall back to read/search on found:false (unresolved is not an empty answer), or for unindexed code. Confirm exact bytes before editing.",
43585
- buildAgentInstruction({ signals: ["prior", "problem", "vulnerability", "fix"], referent: "its-id" }),
43586
- "Read .errata/g/index for graph-as-files query paths. A tool result may ask for a root cause; answer via errata.annotate_resolution when known."
43485
+ // KEEP THIS UNDER THE CLIENT'S ~2 KB instruction-injection budget (the client
43486
+ // truncates `instructions` on connect, ~2008 chars observed). Capture no longer
43487
+ // depends on a standing emit-instruction block: the daemon derives problems/fixes
43488
+ // from your WORK deterministically, and the one thing it asks of the agent — a
43489
+ // one-line root cause at a fix — rides INLINE on the next tool response (the ⚡
43490
+ // errata line; see the dispatch's enrichment piggyback) instead of a fenced
43491
+ // protocol the agent has to remember. So this stays short: tool-routing steering
43492
+ // plus a single line about the inline nudge. Per-tool routing lives in each tool's
43493
+ // own `description` (delivered via tools/list). Don't re-add a tool table here.
43494
+ "errata is a LIVE, bi-temporal code graph of this workspace, kept current by a",
43495
+ "file watcher \u2014 a SEPARATE DIAGNOSTIC AXIS to run ALONGSIDE grep/glob/read, not",
43496
+ "instead of them. For STRUCTURAL questions (callers of callers, blast-radius,",
43497
+ "rename lineage) prefer it: faster, more complete, and it reaches relationships",
43498
+ "grep can't. Each tool's description says when to reach for it. Fall back to",
43499
+ 'grep/read when a tool returns found:false (ESPECIALLY reason:"unresolved" \u2014 the',
43500
+ "name was not recognized, NOT an empty answer; an empty list like callers:[] is a",
43501
+ 'confident "none" \u2014 trust it), when you need EXACT bytes before a high-stakes',
43502
+ "edit, or for an unindexed file/language. Always confirm exact bytes with a read",
43503
+ "before editing.",
43504
+ "",
43505
+ "errata is a cloud knowledge substrate \u2014 AND ALSO this workspace's code graph.",
43506
+ "The problems you hit and the fixes you make become shared knowledge other agents",
43507
+ "recall. That capture is automatic: derived from your edits/commands/commits \u2014 no",
43508
+ "emit needed. Just after you resolve something a tool result may carry a one-line",
43509
+ "\u26A1 errata note asking the ROOT CAUSE; answer via errata.annotate_resolution when",
43510
+ "you know it, skip it otherwise.",
43511
+ "",
43512
+ "Two things it CAN'T derive \u2014 only you witness them, and this is a CAPTURE",
43513
+ "PROTOCOL, not optional formatting: a problem or fix you state only in prose, a",
43514
+ "list, or your own numbering is SILENTLY LOST \u2014 the tag is the ONLY thing recorded.",
43515
+ "So the moment you state one, wrap it inline (no fence, no extra call):",
43516
+ // Signal tokens come from the single source (agent-signals.ts) so this always-on
43517
+ // block can't teach a grammar the parser rejects. Referent is "its-id" here — the
43518
+ // raw MCP channel has no primed handles, so the agent cites a tool-result id.
43519
+ ` \u2022 ${TAG_EXAMPLE.problem()} \u2014 EVERY problem you notice or report ([?\u2026] = TODO)`,
43520
+ ` \u2022 ${TAG_EXAMPLE.fix("its-id")} \u2014 your edit fixed a problem errata showed you`,
43521
+ "Tag every one you state \u2014 we filter downstream, so don't self-censor or batch.",
43522
+ "",
43523
+ "Graph-as-files: the graph is ALSO a virtual FS \u2014 Read (or `cat`)",
43524
+ ".errata/g/<verb>/<seed> to run a query as a file read (e.g. .errata/g/burst/",
43525
+ "<symbol>, /why/<sym>, /trace/<a>..<b>). Read .errata/g/index for the vocabulary."
43587
43526
  ].join("\n");
43588
43527
  AUDIT_RUN_THRESHOLD = 5;
43589
43528
  AUDIT_NUDGE_COOLDOWN = 12;
@@ -44175,7 +44114,7 @@ var init_mcp = __esm({
44175
44114
  },
44176
44115
  {
44177
44116
  name: "errata.problems",
44178
- description: "List the workspace's Problem and Vulnerability backlog \u2014 the triage view that search/why/impact can't give because they need a seed. status: 'open' (default) | 'resolved' (a real fix) | 'retracted' (false alarms \u2014 false_positive/dissolution) | 'constraint' (design TENSIONS captured via `(constraint: \u2026)` \u2014 standing context, not open work, so they're excluded from 'open') | 'all'. Also returns a `retracted` breakdown so the false-positive rate stays visible.",
44117
+ description: "List the workspace's Problem backlog \u2014 the triage view that search/why/impact can't give because they need a seed. status: 'open' (default) | 'resolved' (a real fix) | 'retracted' (false alarms \u2014 false_positive/dissolution) | 'constraint' (design TENSIONS captured via `(constraint: \u2026)` \u2014 standing context, not open work, so they're excluded from 'open') | 'all'. Also returns a `retracted` breakdown so the false-positive rate stays visible.",
44179
44118
  inputSchema: {
44180
44119
  type: "object",
44181
44120
  properties: {
@@ -44187,15 +44126,13 @@ var init_mcp = __esm({
44187
44126
  const want = String(args2["status"] ?? "open");
44188
44127
  const limit = Math.max(1, Math.min(200, Number(args2["limit"] ?? 50)));
44189
44128
  const RETRACTIONS = /* @__PURE__ */ new Set(["false_positive", "invalid", "duplicate"]);
44190
- const rows = [...store.findAllVersionsByLabel("Problem"), ...store.findAllVersionsByLabel("Vulnerability")].map((p) => {
44129
+ const rows = store.findAllVersionsByLabel("Problem").map((p) => {
44191
44130
  const ra = p.attrs["resolvedAs"];
44192
44131
  const status = ra && RETRACTIONS.has(ra) ? ra : p.attrs["resolvedAt"] != null ? "resolved" : isConstraintProblem(p) ? "constraint" : "open";
44193
44132
  const anchorEdge = store.outEdges(p.id, ["ANCHORED_AT"])[0];
44194
44133
  const anchor = anchorEdge ? store.getNode(anchorEdge.to)?.description : void 0;
44195
44134
  return {
44196
44135
  id: p.id,
44197
- label: p.label,
44198
- ...p.label === "Vulnerability" ? { assessment: p.attrs["assessment"] } : {},
44199
44136
  problem: p.description,
44200
44137
  status,
44201
44138
  createdAt: p.createdAt,
@@ -52760,8 +52697,7 @@ function errorRecallTerms(errorText) {
52760
52697
  }
52761
52698
  function recallLine(n, token) {
52762
52699
  const desc = (n.description ?? "").replace(/\s+/g, " ").slice(0, 120);
52763
- const label = n.label === "Vulnerability" ? `Vulnerability; ${n.attrs["assessment"] ?? "unassessed"}` : n.label;
52764
- return `- [${label}] ${desc} \u2192 ${token}`;
52700
+ return `- [${n.label}] ${desc} \u2192 ${token}`;
52765
52701
  }
52766
52702
  function recallForFile(store, relPath) {
52767
52703
  return fileRecall(store, relPath)?.context ?? null;
@@ -52782,7 +52718,7 @@ function fileRecall(store, relPath) {
52782
52718
  const shownRelated = priors.related.slice(0, 4);
52783
52719
  for (const p of shownProblems) {
52784
52720
  const hasCause = store.outEdges(p.id, ["CAUSED_BY"]).some((e) => store.getNode(e.to)?.label === "RootCause");
52785
- const causeCue = hasCause ? "" : ` \xB7 ${p.label === "Vulnerability" ? `(cause:#${p.id} the mechanism)` : TAG_EXAMPLE.triageMint()} to diagnose its cause`;
52721
+ const causeCue = hasCause ? "" : ` \xB7 ${TAG_EXAMPLE.triageMint()} to diagnose its cause`;
52786
52722
  lines.push(
52787
52723
  recallLine(p, `${TAG_EXAMPLE.fix(p.id)} if you resolved it \xB7 ${TAG_EXAMPLE.prior(p.id)} to cite${causeCue}`)
52788
52724
  );
@@ -76052,7 +75988,7 @@ init_src5();
76052
75988
  import { readFileSync as readFileSync17, writeFileSync as writeFileSync13 } from "node:fs";
76053
75989
  var NEG = /n['']t|\b(?:not|never|no|none|neither|nor|unrelated|irrelevant|would|might|could|if)\b/i;
76054
75990
  var CITE_GROUP_RE = /\(((?:[^()\n]|\([^()\n]*\)){1,200})\)/g;
76055
- var HANDLE_RE = /\[([a-z0-9][\w-]{0,80})\]|((?:pat|sol|drc|dcause|dfix|dprob|dvuln|prob|claim|err)_[0-9a-f]{6,})/gi;
75991
+ var HANDLE_RE = /\[([a-z0-9][\w-]{0,80})\]|((?:pat|sol|drc|dcause|dfix|dprob|prob|claim|err)_[0-9a-f]{6,})/gi;
76056
75992
  var PLACEHOLDER_HANDLES = /* @__PURE__ */ new Set([
76057
75993
  "handle",
76058
75994
  "its-handle",
@@ -76067,7 +76003,7 @@ var PLACEHOLDER_HANDLES = /* @__PURE__ */ new Set([
76067
76003
  "b"
76068
76004
  ]);
76069
76005
  var isPlaceholderHandle = (h) => PLACEHOLDER_HANDLES.has(h.toLowerCase());
76070
- var FLAG_BODY_HANDLE_RE = /^(?:[a-z0-9]+(?:-[a-z0-9]+){2,}-(?=[0-9a-f]{0,3}\d)[0-9a-f]{4}|(?:pat|sol|drc|dcause|dfix|dprob|dvuln|prob|claim|err)_[0-9a-f]{6,})$/i;
76006
+ var FLAG_BODY_HANDLE_RE = /^(?:[a-z0-9]+(?:-[a-z0-9]+){2,}-(?=[0-9a-f]{0,3}\d)[0-9a-f]{4}|(?:pat|sol|drc|dcause|dfix|dprob|prob|claim|err)_[0-9a-f]{6,})$/i;
76071
76007
  var FIX_PREFIX = /^\s*fix:(?:#([a-z][\w-]{0,63}))?\s*/i;
76072
76008
  var CONSTRAINT_RE = /\(\s*constraint:\s*([^()\n]{8,}?)\s*\)/gi;
76073
76009
  var CAUSE_PREFIX = /^\s*cause:(?:#([a-z][\w-]{0,63}))?\s*/i;
@@ -76092,7 +76028,7 @@ var DOMAIN_RE = /\(\s*domain:\s*([^()\n]{3,}?)\s*\)/gi;
76092
76028
  var PACKAGE_RE = /\(\s*package:\s*([^()\n]{2,}?)\s*\)/gi;
76093
76029
  var COMPONENT_RE = /\(\s*component:\s*([^()\n]{2,}?)\s*\)/gi;
76094
76030
  var CAUSE_TEXT_MIN = 8;
76095
- var FLAG_RE = /\[([!?])(?:#([a-z][\w-]{0,63})\s+)?\s*((?:\[[^\]\n]*\]|[^\]\n])*?)\s*(?:@\s*([^\s\]]+?)(?::(\d+))?\s*)?\]/g;
76031
+ var FLAG_RE = /\[([!?])(?:#([a-z][\w-]{0,63})\s+)?\s*((?:\[[^\]\n]*\]|[^\]\n]){8,}?)\s*(?:@\s*([^\s\]]+?)(?::(\d+))?\s*)?\]/g;
76096
76032
  var CONSTRAINT_MIN = 8;
76097
76033
  function clauseBefore(sentence, idx) {
76098
76034
  const win = sentence.slice(Math.max(0, idx - 80), idx);
@@ -76236,7 +76172,6 @@ function cleanEmittedTags(tags) {
76236
76172
  }
76237
76173
  function emptyTagDispositions() {
76238
76174
  return {
76239
- invalidVulnerability: 0,
76240
76175
  oversizeSegments: 0,
76241
76176
  codeSpanNeutralized: 0,
76242
76177
  refuteTooShort: 0,
@@ -76249,7 +76184,6 @@ function emptyTagDispositions() {
76249
76184
  };
76250
76185
  }
76251
76186
  function addTagDispositions(a, b) {
76252
- a.invalidVulnerability += b.invalidVulnerability;
76253
76187
  a.oversizeSegments += b.oversizeSegments;
76254
76188
  a.codeSpanNeutralized += b.codeSpanNeutralized;
76255
76189
  a.refuteTooShort += b.refuteTooShort;
@@ -76263,31 +76197,12 @@ function addTagDispositions(a, b) {
76263
76197
  function parseInlineTags(text) {
76264
76198
  return parseInlineTagsWithDispositions(text).tags;
76265
76199
  }
76266
- function* captureSentences(text) {
76267
- for (const line of text.split(/\n+/)) {
76268
- if (line.length > 2e4) {
76269
- yield line;
76270
- continue;
76271
- }
76272
- const flags2 = [...line.matchAll(new RegExp(FLAG_RE.source, FLAG_RE.flags))].map((m) => ({ start: m.index, end: m.index + m[0].length }));
76273
- let flag = 0;
76274
- let start2 = 0;
76275
- for (const boundary of line.matchAll(/(?<=[.!?])\s+(?!\(fix:)/g)) {
76276
- const index = boundary.index;
76277
- while (flags2[flag] && flags2[flag].end <= index) flag++;
76278
- if (flags2[flag] && flags2[flag].start < index) continue;
76279
- yield line.slice(start2, index);
76280
- start2 = index + boundary[0].length;
76281
- }
76282
- yield line.slice(start2);
76283
- }
76284
- }
76285
76200
  function parseInlineTagsWithDispositions(text) {
76286
76201
  const out2 = [];
76287
76202
  const dispositions = emptyTagDispositions();
76288
76203
  const deFenced = text.replace(/```[\s\S]*?```/g, " ");
76289
76204
  let seqNo = -1;
76290
- for (const raw2 of captureSentences(deFenced)) {
76205
+ for (const raw2 of deFenced.split(/(?<=[.!?])\s+(?!\(fix:)|\n+/)) {
76291
76206
  seqNo++;
76292
76207
  if (raw2.length > 2e4) {
76293
76208
  dispositions.oversizeSegments++;
@@ -76513,29 +76428,6 @@ function parseInlineTagsWithDispositions(text) {
76513
76428
  while ((f = FLAG_RE.exec(sentence)) !== null) {
76514
76429
  const flagThread = f[2];
76515
76430
  const raw3 = f[3].trim();
76516
- if (/^vuln\b/i.test(raw3)) {
76517
- const typed = /^vuln:\s*([\s\S]*)$/i.exec(raw3);
76518
- const body2 = typed?.[1]?.trim() ?? "";
76519
- const parts2 = body2.split(CAUSE_ARROW).map((s) => s.trim());
76520
- const symptom = f[1] === "!" && parts2.length > 1 && !f[4] ? new RegExp(FLAG_RE.source, "i").exec(`[!${parts2[0]}]`) : null;
76521
- const statement = f[1] === "?" ? body2 : symptom?.[3]?.trim() ?? parts2[0];
76522
- if (statement.length < 8 || /^<[^>]*>$/.test(statement)) {
76523
- dispositions.invalidVulnerability++;
76524
- continue;
76525
- }
76526
- const path2 = (f[4] ?? symptom?.[4])?.trim();
76527
- const line = f[5] ?? symptom?.[5];
76528
- out2.push({
76529
- kind: "vulnerability",
76530
- statement,
76531
- assessment: f[1] === "!" ? "asserted" : "suspected",
76532
- ...f[1] === "!" && parts2.length > 1 ? { vulnerabilityCauses: parts2.slice(1).filter((s) => s.length >= CAUSE_TEXT_MIN) } : {},
76533
- ...path2 ? { location: { path: path2, ...line ? { line: Number(line) } : {} } } : {},
76534
- ...flagThread ? { threadId: flagThread } : {},
76535
- sentence: sfield
76536
- });
76537
- continue;
76538
- }
76539
76431
  if (FLAG_BODY_HANDLE_RE.test(raw3) && !f[4]) {
76540
76432
  dispositions.flagAsHandle++;
76541
76433
  out2.push({ kind: "prior", handle: raw3, sentence: sfield });
@@ -76906,7 +76798,7 @@ function harvestInlineTags(store, text, opts) {
76906
76798
  const parsed = parseInlineTagsWithDispositions(text);
76907
76799
  const tags = parsed.tags;
76908
76800
  plan.dispositions = parsed.dispositions;
76909
- const symptomSeqs = tags.filter((t) => (t.kind === "problem" || t.kind === "todo" || t.kind === "vulnerability") && t.statement).map((t) => ({ seq: t.seq ?? -1, statement: t.statement, threadId: t.threadId, kind: t.kind })).sort((a, b) => a.seq - b.seq);
76801
+ const symptomSeqs = tags.filter((t) => (t.kind === "problem" || t.kind === "todo") && t.statement).map((t) => ({ seq: t.seq ?? -1, statement: t.statement, threadId: t.threadId })).sort((a, b) => a.seq - b.seq);
76910
76802
  const bindSymptom = (seq, threadId) => {
76911
76803
  if (threadId) {
76912
76804
  const hit = symptomSeqs.find((s) => s.threadId === threadId);
@@ -76919,7 +76811,6 @@ function harvestInlineTags(store, text, opts) {
76919
76811
  if (seq == null) return { evidence: "inferred" };
76920
76812
  let best;
76921
76813
  for (const s of symptomSeqs) {
76922
- if (s.kind === "vulnerability") continue;
76923
76814
  if (s.seq <= seq) best = s;
76924
76815
  else break;
76925
76816
  }
@@ -76934,13 +76825,10 @@ function harvestInlineTags(store, text, opts) {
76934
76825
  return id;
76935
76826
  };
76936
76827
  for (const tag of tags) {
76937
- if (tag.kind === "problem" || tag.kind === "todo" || tag.kind === "vulnerability") {
76828
+ if (tag.kind === "problem" || tag.kind === "todo") {
76938
76829
  plan.problems.push({
76939
76830
  statement: tag.statement,
76940
76831
  kind: tag.kind,
76941
- ...tag.assessment ? { assessment: tag.assessment } : {},
76942
- ...tag.vulnerabilityCauses ? { vulnerabilityCauses: tag.vulnerabilityCauses } : {},
76943
- ...tag.kind === "vulnerability" && tag.seq !== void 0 ? { seq: tag.seq } : {},
76944
76832
  ...tag.location ? { location: tag.location } : {},
76945
76833
  ...tag.threadId ? { threadId: tag.threadId } : {}
76946
76834
  });
@@ -76963,7 +76851,7 @@ function harvestInlineTags(store, text, opts) {
76963
76851
  } else if (tag.threadId && !b.statement) {
76964
76852
  plan.fixes.push({ inScope: true, fixNote: tag.fixRationale, threadId: tag.threadId });
76965
76853
  } else if (b.statement && b.evidence === "witnessed") {
76966
- plan.fixes.push({ inScope: true, fixNote: tag.fixRationale, boundStatement: b.statement, ...tag.threadId ? { threadId: tag.threadId } : {} });
76854
+ plan.fixes.push({ inScope: true, fixNote: tag.fixRationale, boundStatement: b.statement });
76967
76855
  } else {
76968
76856
  plan.fixes.push({ inScope: true, fixNote: tag.fixRationale, ambiguous: true });
76969
76857
  }
@@ -77166,7 +77054,6 @@ function harvestInlineTags(store, text, opts) {
77166
77054
  }
77167
77055
  var CORROBORATABLE_LABELS = /* @__PURE__ */ new Set([
77168
77056
  "Problem",
77169
- "Vulnerability",
77170
77057
  "Solution",
77171
77058
  "RootCause",
77172
77059
  "Pattern",
@@ -80945,9 +80832,9 @@ function partitionReplayable(queue, channel, isShipped) {
80945
80832
  function retireWitnesses(queue, channel, settledKeys) {
80946
80833
  return queue.filter((w) => !(w.channel === channel && settledKeys.has(w.witnessKey)));
80947
80834
  }
80948
- var WIRE_SHIPPED_LABELS = /* @__PURE__ */ new Set(["Problem", "Vulnerability", "Solution", "RootCause"]);
80835
+ var WIRE_SHIPPED_LABELS = /* @__PURE__ */ new Set(["Problem", "Solution", "RootCause"]);
80949
80836
  var MOTIF_ID_PREFIX = "motif_community_";
80950
- var CANONICAL_ID_RE = /^(?:pat|sol|drc|dcause|dfix|dprob|dvuln|prob|claim|err)_[0-9a-f]{6,}$/i;
80837
+ var CANONICAL_ID_RE = /^(?:pat|sol|drc|dcause|dfix|dprob|prob|claim|err)_[0-9a-f]{6,}$/i;
80951
80838
  function classifyWitnessTarget(nodeId, getNode) {
80952
80839
  if (nodeId.startsWith(MOTIF_ID_PREFIX)) {
80953
80840
  const exemplar = nodeId.slice(MOTIF_ID_PREFIX.length);
@@ -81517,7 +81404,7 @@ function createWatchBreaker(deps) {
81517
81404
  }
81518
81405
 
81519
81406
  // src/engine.ts
81520
- var DAEMON_VERSION = true ? "2.0.16-dev.3362" : "2.0.0-alpha.0";
81407
+ var DAEMON_VERSION = true ? "2.0.16" : "2.0.0-alpha.0";
81521
81408
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
81522
81409
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
81523
81410
  var GIT_OP_MUTE_MS = 4e3;
@@ -82409,9 +82296,6 @@ function createWorkspaceEngine(opts) {
82409
82296
  const harvestTextsInner = async (sessionId, items) => {
82410
82297
  let minted = 0;
82411
82298
  let tagsSeen = 0;
82412
- let vulnerabilitiesSeen = 0;
82413
- let vulnerabilitiesMinted = 0;
82414
- let vulnerabilitiesSuspected = 0;
82415
82299
  let tagsRejected = 0;
82416
82300
  let tagsRestated = 0;
82417
82301
  let resolved = 0;
@@ -82642,73 +82526,10 @@ function createWorkspaceEngine(opts) {
82642
82526
  if ((toolRuns.get(sessionId)?.size ?? 0) > 0) touchedToolTurns++;
82643
82527
  const wf = workingFiles.get(sessionId);
82644
82528
  let inScopeProblemId;
82645
- const findingIds = /* @__PURE__ */ new Map();
82646
- const conflictingThreads = /* @__PURE__ */ new Set();
82647
82529
  const threads = sessionThreads.get(sessionId) ?? /* @__PURE__ */ new Map();
82648
82530
  sessionThreads.set(sessionId, threads);
82649
82531
  for (const p of plan.problems) {
82650
82532
  tagsSeen++;
82651
- if (p.kind === "vulnerability") {
82652
- vulnerabilitiesSeen++;
82653
- if (p.assessment === "suspected") vulnerabilitiesSuspected++;
82654
- let fileText;
82655
- let anchorReadFailed = false;
82656
- if (p.location) {
82657
- try {
82658
- fileText = readFileSync31(join35(opts.workspaceRoot, p.location.path), "utf8");
82659
- } catch {
82660
- anchorReadFailed = true;
82661
- }
82662
- }
82663
- const result = ingestWitnessedVulnerability(store, {
82664
- statement: p.statement,
82665
- assessment: p.assessment,
82666
- target: p.location?.path,
82667
- line: p.location?.line,
82668
- fileText,
82669
- existingId: p.threadId ? threads.get(p.threadId) ?? handleMap[p.threadId]?.id ?? store.getNode(p.threadId)?.id : void 0
82670
- }, { workspaceId: profile.id, source: sessionId, ts: t, hostHarness: turn.hostHarness });
82671
- let anchorDisposition = p.location ? "unresolved" : "absent";
82672
- if (result.rejected) {
82673
- tagsRejected++;
82674
- if (p.threadId) conflictingThreads.add(p.threadId);
82675
- } else {
82676
- findingIds.set(p.statement, result.id);
82677
- if (p.threadId) threads.set(p.threadId, result.id);
82678
- if (result.created || result.corroborated || result.upgraded) minted++;
82679
- else tagsRestated++;
82680
- if (result.created) vulnerabilitiesMinted++;
82681
- if (p.location) {
82682
- try {
82683
- const anchored = anchorProblemToWorkingFile(store, result.id, p.location.path, profile.id, t, "witnessed", { line: p.location.line, fileText });
82684
- anchorDisposition = anchored ? "resolved" : anchorReadFailed ? "error" : "unresolved";
82685
- if (anchored) deriveContextFromAnchors(store, result.id, t);
82686
- } catch {
82687
- anchorDisposition = "error";
82688
- }
82689
- }
82690
- const node2 = store.getNode(result.id);
82691
- store.updateNode(result.id, { attrs: { ...node2.attrs, anchorDisposition } });
82692
- if (p.vulnerabilityCauses) triaged += recordVulnerabilityCause(store, result.id, p.vulnerabilityCauses, t);
82693
- }
82694
- log.append({
82695
- kind: "vulnerability.witness",
82696
- workspaceId: profile.id,
82697
- ts: t,
82698
- digest: digest({ kind: "vulnerability.witness", workspaceId: profile.id, sessionId, turnId: turn.uuid, statement: p.statement, assessment: p.assessment, location: p.location }),
82699
- sessionId,
82700
- turnId: turn.uuid,
82701
- harness: turn.hostHarness,
82702
- findingId: result.id,
82703
- statement: p.statement,
82704
- assessment: p.assessment,
82705
- location: p.location,
82706
- seq: p.seq,
82707
- anchorDisposition,
82708
- disposition: result.rejected ?? (result.created ? "created" : result.upgraded ? "upgraded" : result.corroborated ? "corroborated" : "restated")
82709
- });
82710
- continue;
82711
- }
82712
82533
  const anchorPath = p.location?.path ?? editedTurnFile;
82713
82534
  const anchorProvenance = p.location?.path ? "witnessed" : "edited";
82714
82535
  const hintPath = anchorPath ? void 0 : turnFile ?? wf;
@@ -82803,10 +82624,10 @@ function createWorkspaceEngine(opts) {
82803
82624
  if (r.created || r.corroborated) {
82804
82625
  minted++;
82805
82626
  if (p.kind !== "constraint") {
82806
- sessionLastProblem.set(sessionId, r.problemId);
82807
- inScopeProblemId = r.problemId;
82627
+ sessionLastProblem.set(sessionId, designProblemId(p.statement));
82628
+ inScopeProblemId = designProblemId(p.statement);
82808
82629
  }
82809
- if (p.threadId) threads.set(p.threadId, r.problemId);
82630
+ if (p.threadId) threads.set(p.threadId, designProblemId(p.statement));
82810
82631
  try {
82811
82632
  if (anchorPath) {
82812
82633
  let enclosing = {};
@@ -82843,8 +82664,7 @@ function createWorkspaceEngine(opts) {
82843
82664
  );
82844
82665
  }
82845
82666
  for (const fx of plan.fixes) {
82846
- if (fx.threadId && conflictingThreads.has(fx.threadId)) continue;
82847
- const pid = fx.problemId ?? (fx.threadId ? threads.get(fx.threadId) : void 0) ?? (fx.boundStatement ? findingIds.get(fx.boundStatement) ?? designProblemId(fx.boundStatement) : void 0);
82667
+ const pid = fx.problemId ?? (fx.threadId ? threads.get(fx.threadId) : void 0) ?? (fx.boundStatement ? designProblemId(fx.boundStatement) : void 0);
82848
82668
  if (!pid) {
82849
82669
  if (fx.inScope) {
82850
82670
  console.warn(
@@ -82856,7 +82676,7 @@ function createWorkspaceEngine(opts) {
82856
82676
  const closed = resolveDesignProblemById(store, pid, fx.fixNote, t);
82857
82677
  if (!closed) {
82858
82678
  const n = store.getNode(pid);
82859
- if (!n || n.label !== "Problem" && n.label !== "Vulnerability" || n.attrs["resolvedAs"] != null) {
82679
+ if (!n || n.label !== "Problem" || n.attrs["resolvedAs"] != null) {
82860
82680
  console.warn(
82861
82681
  `[errata] fix tag went nowhere: ${!n ? `id ${pid.slice(0, 32)} unknown` : n.label !== "Problem" ? `${pid.slice(0, 32)} is a ${n.label}, not a Problem` : "the problem was retracted \u2014 a retraction is not fixable"} \u2014 the fix was NOT recorded`
82862
82682
  );
@@ -82875,23 +82695,10 @@ function createWorkspaceEngine(opts) {
82875
82695
  }
82876
82696
  }
82877
82697
  }
82878
- const vulnerabilityTriages = /* @__PURE__ */ new Set();
82879
- for (const tr of plan.triages) {
82880
- if (tr.threadId && conflictingThreads.has(tr.threadId)) {
82881
- vulnerabilityTriages.add(tr);
82882
- continue;
82883
- }
82884
- const id = tr.symptomProblemId ?? (tr.threadId ? threads.get(tr.threadId) : void 0) ?? (tr.symptomStatement ? findingIds.get(tr.symptomStatement) : void 0);
82885
- if (id && store.getNode(id)?.label === "Vulnerability") {
82886
- vulnerabilityTriages.add(tr);
82887
- if (tr.evidence === "witnessed" && tr.causeDescription) triaged += recordVulnerabilityCause(store, id, [tr.causeDescription], t);
82888
- }
82889
- }
82890
82698
  if (opts.sharedStore && plan.triages.length > 0) {
82891
82699
  const fallbackId = sessionLastProblem.get(sessionId);
82892
82700
  const fallbackStatement = fallbackId ? store.getNode(fallbackId)?.description : void 0;
82893
82701
  for (const tr of plan.triages) {
82894
- if (vulnerabilityTriages.has(tr)) continue;
82895
82702
  let presentingStatement = tr.symptomStatement;
82896
82703
  let evidence = tr.evidence;
82897
82704
  if (!presentingStatement && tr.threadId) {
@@ -82909,7 +82716,7 @@ function createWorkspaceEngine(opts) {
82909
82716
  evidence = "inferred";
82910
82717
  }
82911
82718
  if (!presentingStatement) continue;
82912
- const presentingId = tr.symptomProblemId ?? (tr.threadId ? threads.get(tr.threadId) : void 0) ?? designProblemId(presentingStatement);
82719
+ const presentingId = tr.symptomProblemId ?? designProblemId(presentingStatement);
82913
82720
  if (tr.causeId === presentingId) continue;
82914
82721
  try {
82915
82722
  recordTriageObservation(
@@ -82967,7 +82774,7 @@ function createWorkspaceEngine(opts) {
82967
82774
  }
82968
82775
  }
82969
82776
  for (const at of plan.attempts) {
82970
- const pid = at.problemId ?? (at.threadId ? threads.get(at.threadId) : void 0) ?? (at.boundStatement ? findingIds.get(at.boundStatement) ?? designProblemId(at.boundStatement) : void 0);
82777
+ const pid = at.problemId ?? (at.threadId ? threads.get(at.threadId) : void 0) ?? (at.boundStatement ? designProblemId(at.boundStatement) : void 0);
82971
82778
  const node2 = pid ? store.getNode(pid) : void 0;
82972
82779
  if (!pid || !node2) continue;
82973
82780
  try {
@@ -82983,7 +82790,7 @@ function createWorkspaceEngine(opts) {
82983
82790
  }
82984
82791
  }
82985
82792
  const bindPid = (tag) => {
82986
- const pid = tag.problemId ?? (tag.threadId ? threads.get(tag.threadId) : void 0) ?? (tag.boundStatement ? findingIds.get(tag.boundStatement) ?? designProblemId(tag.boundStatement) : void 0) ?? inScopeProblemId ?? sessionLastProblem.get(sessionId);
82793
+ const pid = tag.problemId ?? (tag.threadId ? threads.get(tag.threadId) : void 0) ?? (tag.boundStatement ? designProblemId(tag.boundStatement) : void 0) ?? inScopeProblemId ?? sessionLastProblem.get(sessionId);
82987
82794
  return pid && store.getNode(pid) ? pid : void 0;
82988
82795
  };
82989
82796
  const mintCiteEdge = (from, to, type, confidence, extraAttrs) => {
@@ -83137,12 +82944,7 @@ function createWorkspaceEngine(opts) {
83137
82944
  for (const [session, items2] of groups) {
83138
82945
  if (items2.length === 0) continue;
83139
82946
  try {
83140
- const wireItems = items2.map(({ nodeId, witnessKey }) => {
83141
- const node2 = store.getNode(nodeId);
83142
- const cloudId = node2?.attrs["privateFinding"] ? node2.attrs["cloudNodeId"] : void 0;
83143
- return { nodeId: typeof cloudId === "string" ? cloudId : nodeId, witnessKey };
83144
- });
83145
- const raw2 = await send(wireItems, session);
82947
+ const raw2 = await send(items2, session);
83146
82948
  const d = {
83147
82949
  recorded: raw2?.recorded ?? 0,
83148
82950
  unmatched: raw2?.unmatched ?? 0,
@@ -83155,8 +82957,8 @@ function createWorkspaceEngine(opts) {
83155
82957
  duplicate += d.duplicate;
83156
82958
  selfGated += d.selfGated;
83157
82959
  const missing = new Set(d.unmatchedIds);
83158
- for (const [index, it] of items2.entries()) {
83159
- if (missing.has(wireItems[index].nodeId)) stillUnmatched.push({ channel, ...it, sessionKey: session, counted: isShipped(it.nodeId) });
82960
+ for (const it of items2) {
82961
+ if (missing.has(it.nodeId)) stillUnmatched.push({ channel, ...it, sessionKey: session, counted: isShipped(it.nodeId) });
83160
82962
  else settled.add(it.witnessKey);
83161
82963
  }
83162
82964
  } catch (err2) {
@@ -83326,10 +83128,6 @@ function createWorkspaceEngine(opts) {
83326
83128
  // but nothing judgeable was cited.
83327
83129
  tagsVerdictNoHandle: dispositions.verdictNoHandle,
83328
83130
  tagsFlagAsHandle: dispositions.flagAsHandle,
83329
- tagsInvalidVulnerability: dispositions.invalidVulnerability,
83330
- vulnerabilitiesSeen,
83331
- vulnerabilitiesMinted,
83332
- vulnerabilitiesSuspected,
83333
83131
  unresolvedHandles,
83334
83132
  priorEdgesFlagOff,
83335
83133
  priorEdgesNoSource,
@@ -84667,7 +84465,7 @@ function internalSymbolsFor(description, lexiconHas, publicIndex) {
84667
84465
 
84668
84466
  // src/instance-ingest.ts
84669
84467
  init_generalize_graph();
84670
- var INSTANCE_LABELS = ["Problem", "Vulnerability", "Solution", "RootCause"];
84468
+ var INSTANCE_LABELS = ["Problem", "Solution", "RootCause"];
84671
84469
  var INSTANCE_EDGES = ["CAUSED_BY", "SOLVED_BY"];
84672
84470
  var ANCHOR_EDGES = ["OCCURS_IN", "DEPENDS_ON", "PERTAIN_TO", "CONCERNS"];
84673
84471
  var ANCHOR_TARGET_LABELS = ["Language", "Package", "Domain", "Component"];
@@ -84802,10 +84600,6 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
84802
84600
  attrs: {
84803
84601
  scope: stripCodebaseScope(n.attrs["scope"]),
84804
84602
  ...n.attrs["kind"] ? { kind: n.attrs["kind"] } : {},
84805
- ...n.attrs["privateFinding"] ? { privateFinding: true } : {},
84806
- ...n.attrs["assessment"] ? { assessment: n.attrs["assessment"] } : {},
84807
- ...n.attrs["sourceClass"] ? { sourceClass: n.attrs["sourceClass"] } : {},
84808
- ...n.attrs["resolutionWitnessed"] ? { resolutionWitnessed: true, resolvedAt: n.attrs["resolvedAt"] } : {},
84809
84603
  ...n.attrs["resolvedAs"] ? { resolvedAs: n.attrs["resolvedAs"] } : {},
84810
84604
  ...preserved.length > 0 ? { preservedSymbols: preserved } : {},
84811
84605
  ...internal.length > 0 ? { internalSymbols: internal } : {}
@@ -84820,7 +84614,6 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
84820
84614
  const semanticEndpoints = /* @__PURE__ */ new Map();
84821
84615
  const includedByLabel = /* @__PURE__ */ new Map();
84822
84616
  const composition = {
84823
- privateTargetMissing: 0,
84824
84617
  candidates: 0,
84825
84618
  shipped: 0,
84826
84619
  cloudSourced: 0,
@@ -84866,15 +84659,11 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
84866
84659
  if (walked.has(n.id)) continue;
84867
84660
  walked.add(n.id);
84868
84661
  composition.candidates++;
84869
- if ((n.attrs["privateFinding"] || n.label === "Vulnerability") && !opts.project) {
84870
- composition.privateTargetMissing++;
84871
- continue;
84872
- }
84873
84662
  if (n.attrs["source"] === "cloud") {
84874
84663
  composition.cloudSourced++;
84875
84664
  continue;
84876
84665
  }
84877
- if (n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) {
84666
+ if (label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) {
84878
84667
  composition.falsePositive++;
84879
84668
  continue;
84880
84669
  }
@@ -84897,7 +84686,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
84897
84686
  composition.terminalRefused++;
84898
84687
  continue;
84899
84688
  }
84900
- if (!n.attrs["privateFinding"] && !noveltyAgainst(n, ref, noveltyOpts).ready) {
84689
+ if (!noveltyAgainst(n, ref, noveltyOpts).ready) {
84901
84690
  composition.notNovel++;
84902
84691
  continue;
84903
84692
  }
@@ -84940,7 +84729,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
84940
84729
  }
84941
84730
  if (targets.length === 0) continue;
84942
84731
  const shipped = shippedById.get(sourceId);
84943
- if (shipped && !shipped.attrs["privateFinding"]) {
84732
+ if (shipped) {
84944
84733
  const anchors = (label) => targets.filter((x) => x.t.label === label).map(
84945
84734
  (x) => label === "Language" ? langAnchor(x.t) : label === "Component" ? `component:${x.wireId}` : x.wireId
84946
84735
  ).filter((a) => a != null).sort();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.16-dev.3362",
3
+ "version": "2.0.16",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -15122,7 +15122,7 @@ var init_edge_rules = __esm({
15122
15122
  // anchor anything at anything, e.g. at a public `Package`, quietly re-creating
15123
15123
  // the code↔collective bridge the membrane exists to prevent.
15124
15124
  ANCHORED_AT: {
15125
- from: ["Problem", "Vulnerability", "Solution", "RootCause", "Claim"],
15125
+ from: ["Problem", "Solution", "RootCause", "Claim"],
15126
15126
  to: ["Symbol"]
15127
15127
  },
15128
15128
  // ── Security spine (v1 taxonomy.ts SECURITY_FORWARD_ONLY commentary) ──
@@ -15167,7 +15167,7 @@ var init_edge_rules = __esm({
15167
15167
  // `Component` joined the target set with OM-agent-anchors: an agent-named
15168
15168
  // component ("React Router") is the same knowledge→named-unit anchor shape as
15169
15169
  // a Tool — the knowledge is ABOUT it, not dependent on it.
15170
- CONCERNS: { from: ["Problem", "Vulnerability", "Solution", "RootCause", "Claim", "Pattern"], to: ["Tool", "Component"] },
15170
+ CONCERNS: { from: ["Problem", "Solution", "RootCause", "Claim", "Pattern"], to: ["Tool", "Component"] },
15171
15171
  OPERATES_ON: { from: ["Algorithm"], to: ["DataStructure"] },
15172
15172
  INVOLVES: { from: ["Problem", "Solution"], to: ["DataStructure"] },
15173
15173
  // ── Taxonomy (Track 4 Stream C: MITRE CWE `ChildOf` → `Weakness —IS_A→ Weakness`) ──
@@ -24827,8 +24827,7 @@ CREATE INDEX IF NOT EXISTS nodes_live ON nodes(label, valid_to);
24827
24827
  -- its table row. Partial, so it maintains a few thousand rows instead of adding
24828
24828
  -- a write to every node write. Its label list is FINGERPRINT_INDEXED_LABELS.
24829
24829
  DROP INDEX IF EXISTS nodes_live_fingerprint;
24830
- DROP INDEX IF EXISTS nodes_instance_fingerprint;
24831
- CREATE INDEX IF NOT EXISTS nodes_instance_fingerprint_v2 ON nodes(label, last_updated_at, last_reinforced_at_seq, created_at_seq) WHERE valid_to IS NULL AND label IN ('Problem','Vulnerability','Solution','RootCause');
24830
+ CREATE INDEX IF NOT EXISTS nodes_instance_fingerprint ON nodes(label, last_updated_at, last_reinforced_at_seq, created_at_seq) WHERE valid_to IS NULL AND label IN ('Problem','Solution','RootCause');
24832
24831
  CREATE INDEX IF NOT EXISTS nodes_logical ON nodes(logical_id, version);
24833
24832
  CREATE INDEX IF NOT EXISTS edges_live ON edges(valid_to);
24834
24833
  -- Expression index on the per-node relPath (stored in attrs_json) so the
@@ -24899,7 +24898,7 @@ function rowToEdge(r) {
24899
24898
  attrs: JSON.parse(r.attrs_json)
24900
24899
  };
24901
24900
  }
24902
- var FINGERPRINT_INDEXED_LABELS = ["Problem", "Vulnerability", "Solution", "RootCause"];
24901
+ var FINGERPRINT_INDEXED_LABELS = ["Problem", "Solution", "RootCause"];
24903
24902
  var SqliteGraphStore = class {
24904
24903
  db;
24905
24904
  // Typed edge lookups build their SQL from the number of types asked for, and
@@ -25577,8 +25576,8 @@ var SqliteGraphStore = class {
25577
25576
  const r2 = this.db.prepare(
25578
25577
  `SELECT COUNT(*) AS n, MAX(last_updated_at) AS t,
25579
25578
  MAX(COALESCE(last_reinforced_at_seq, created_at_seq, 0)) AS s
25580
- FROM nodes INDEXED BY nodes_instance_fingerprint_v2
25581
- WHERE valid_to IS NULL AND label IN ('Problem','Vulnerability','Solution','RootCause')`
25579
+ FROM nodes INDEXED BY nodes_instance_fingerprint
25580
+ WHERE valid_to IS NULL AND label IN ('Problem','Solution','RootCause')`
25582
25581
  ).get();
25583
25582
  return `${r2.n}:${r2.t ?? 0}:${r2.s ?? 0}`;
25584
25583
  }
@@ -26182,7 +26181,7 @@ function mergeContextEdge(store2, from, to, type, ts) {
26182
26181
  function deriveContextFromAnchors(store2, problemId, ts, pkgIndex) {
26183
26182
  const report = { languages: [], packages: [] };
26184
26183
  const p = store2.getNode(problemId);
26185
- if (!p || p.label !== "Problem" && p.label !== "Vulnerability") return report;
26184
+ if (!p || p.label !== "Problem") return report;
26186
26185
  const files = store2.outEdges(problemId, ["ANCHORED_AT"]).map((e) => store2.getNode(e.to)).filter((n) => !!n && n.label === "File");
26187
26186
  if (files.length === 0) return report;
26188
26187
  const idx = pkgIndex ?? buildPackageIndex(store2);
@@ -26387,7 +26386,7 @@ function priorsForFile(store2, relPath) {
26387
26386
  for (const e of store2.inEdges(file2.id, ["ANCHORED_AT"])) {
26388
26387
  const n = store2.getNode(e.from);
26389
26388
  if (!n) continue;
26390
- if (n.label === "Problem" || n.label === "Vulnerability") {
26389
+ if (n.label === "Problem") {
26391
26390
  if (seenProblem.has(n.id)) continue;
26392
26391
  seenProblem.add(n.id);
26393
26392
  if (!n.attrs["resolvedAt"]) {
@@ -27655,7 +27654,7 @@ var AGENTS_POINTER_BODY = [
27655
27654
  init_src2();
27656
27655
  init_src();
27657
27656
  function buildSnapshot(opts) {
27658
- const problems = [...opts.store.findNodesByLabel("Problem"), ...opts.store.findNodesByLabel("Vulnerability")].filter((p) => p.attrs["mergedInto"] === void 0 && historyReadPolicy(p, { mode: "passive", atCommit: opts.atCommit }).allow);
27657
+ const problems = opts.store.findNodesByLabel("Problem").filter((p) => p.attrs["mergedInto"] === void 0 && historyReadPolicy(p, { mode: "passive", atCommit: opts.atCommit }).allow);
27659
27658
  const stillOpen = problems.filter((p) => p.attrs["resolvedAt"] == null);
27660
27659
  const allProblems = stillOpen.filter((p) => !isConstraintProblem(p));
27661
27660
  allProblems.sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt);
@@ -27810,11 +27809,11 @@ function sliceForFile(store2, relPath, atCommit) {
27810
27809
  const priors = fp ? {
27811
27810
  openProblems: fp.openProblems.slice(0, 3).map((p) => ({
27812
27811
  id: p.id,
27813
- description: p.label === "Vulnerability" ? `Vulnerability (${p.attrs["assessment"] ?? "unassessed"}): ${p.description}` : p.description,
27812
+ description: p.description,
27814
27813
  ...typeof p.attrs["fixCandidateFile"] === "string" ? { fixCandidateFile: p.attrs["fixCandidateFile"] } : {}
27815
27814
  })),
27816
27815
  constraints: fp.constraints.slice(0, 2).map((c) => ({ id: c.id, description: c.description })),
27817
- resolvedProblems: fp.resolvedProblems.slice(0, 3).map((p) => ({ id: p.id, description: p.label === "Vulnerability" ? `Vulnerability (${p.attrs["assessment"] ?? "unassessed"}): ${p.description}` : p.description })),
27816
+ resolvedProblems: fp.resolvedProblems.slice(0, 3).map((p) => ({ id: p.id, description: p.description })),
27818
27817
  related: fp.related.slice(0, 4).map((n) => ({ id: n.id, label: n.label, description: n.description })),
27819
27818
  solutionsByProblem: Object.fromEntries(
27820
27819
  [...fp.openProblems.slice(0, 3), ...fp.resolvedProblems.slice(0, 3)].map((p) => [