@inerrata-corporation/errata 2.0.0-dev.92 → 2.0.0-dev.94

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/errata.mjs CHANGED
@@ -18299,6 +18299,23 @@ function mintPatternNode(store, name2, ts) {
18299
18299
  }
18300
18300
  return id;
18301
18301
  }
18302
+ function titleCaseDomain(name2) {
18303
+ return name2.replace(/\s+/g, " ").trim().split(" ").map((w) => w.length > 0 ? w[0].toUpperCase() + w.slice(1) : w).join(" ");
18304
+ }
18305
+ function mintDomainNode(store, name2, ts) {
18306
+ const display = titleCaseDomain(name2);
18307
+ const id = `dom_${digest({ domain: display.toLowerCase() })}`.slice(0, 56);
18308
+ if (!store.getNode(id)) {
18309
+ store.mergeNode(
18310
+ buildNode(id, "Domain", display, ts, {
18311
+ source: "convo",
18312
+ provisional: true,
18313
+ canonicalId: genericCanonicalId("dom", { type: "Domain", description: display })
18314
+ })
18315
+ );
18316
+ }
18317
+ return id;
18318
+ }
18302
18319
  function resolveFileNode(store, path2, workspaceId2) {
18303
18320
  const want = path2.trim().replace(/^\.?\//, "");
18304
18321
  for (const n of store.findNodesByLabel("File")) {
@@ -20749,6 +20766,7 @@ __export(src_exports2, {
20749
20766
  matchSymbolsInText: () => matchSymbolsInText,
20750
20767
  mergeCloudCounts: () => mergeCloudCounts,
20751
20768
  mergeDuplicateProblems: () => mergeDuplicateProblems,
20769
+ mintDomainNode: () => mintDomainNode,
20752
20770
  mintPatternNode: () => mintPatternNode,
20753
20771
  openGraphStore: () => openGraphStore,
20754
20772
  osNodeId: () => osNodeId,
@@ -20881,12 +20899,19 @@ function buildSnapshot(opts) {
20881
20899
  const causalNudge = recent.length >= 2 && recent.every(
20882
20900
  (r) => opts.store.outEdges(r.node.id, ["CAUSED_BY"]).length === 0 && opts.store.inEdges(r.node.id, ["CAUSED_BY"]).length === 0
20883
20901
  );
20902
+ const abstractUndomained = recent.filter((r) => {
20903
+ const grounded = opts.store.outEdges(r.node.id, ["ANCHORED_AT", "OCCURS_IN", "DEPENDS_ON"]).length > 0;
20904
+ const hasDomain = opts.store.outEdges(r.node.id, ["PERTAIN_TO"]).length > 0;
20905
+ return !grounded && !hasDomain;
20906
+ });
20907
+ const domainNudge = abstractUndomained.length >= 2;
20884
20908
  return {
20885
20909
  profile: opts.profile,
20886
20910
  profileContext,
20887
20911
  recentProblems: recent,
20888
20912
  recentResolved,
20889
20913
  ...causalNudge ? { causalNudge } : {},
20914
+ ...domainNudge ? { domainNudge } : {},
20890
20915
  motifs,
20891
20916
  reviewCount: opts.reviewCount,
20892
20917
  reviewUiUrl: opts.reviewUiUrl,
@@ -21047,6 +21072,11 @@ function renderSnapshot(s) {
21047
21072
  "_None of these problems are causally linked yet \u2014 if one caused another (or your report says so in prose), bind them with `(cause:#slug \u2026)` / `(cause:[handle])`. Trace can only follow edges you declare._"
21048
21073
  );
21049
21074
  }
21075
+ if (s.domainNudge) {
21076
+ lines.push(
21077
+ "_Some of these are abstract (no code anchor) and belong to no topic \u2014 name the area each is about with `(domain: The Area)` (e.g. `(domain: Observability)`). Without it an abstract problem is an invisible island; the Domain is where problems in the same area cluster and stay findable._"
21078
+ );
21079
+ }
21050
21080
  }
21051
21081
  if (s.recentResolved.length > 0) {
21052
21082
  lines.push("_Recently resolved \u2014 solved here; jumping-off points, not live defects:_");
@@ -24928,6 +24958,9 @@ function linkBullet(ref) {
24928
24958
  ` \xB7 ${TAG_EXAMPLE.pattern()} \u2014 name the general shape it instantiates (e.g. (pattern: unbounded`,
24929
24959
  " queue growth under backpressure)) \u2014 this works with NO code anchor, and two agents naming",
24930
24960
  " the same pattern converge on one node. Cite a shown Pattern by handle: (pattern:[handle]).",
24961
+ ` \xB7 ${TAG_EXAMPLE.domain()} \u2014 name the ABSTRACT AREA it's about (e.g. (domain: Observability),`,
24962
+ " (domain: Community Detection)). An abstract problem with no code anchor NEEDS this or it's",
24963
+ " an invisible island: the Domain is the topic other problems in the area cluster on. Title Case.",
24931
24964
  ` \xB7 (aids:[${ref}],\u2026) \u2014 your FIX could also help these other, even unrelated, problems.`,
24932
24965
  " A hypothesis, not a claim \u2014 it's recorded as may-resolve and checked by whoever tries it.",
24933
24966
  ` \xB7 when your fix relates to a PRIOR solution you were primed with (a problem's`,
@@ -24996,6 +25029,9 @@ var init_agent_signals = __esm({
24996
25029
  // DIFFERENT relevant priors is the target shape (see linkBullet).
24997
25030
  instance: (ref) => `(instance:[${ref}],[another],[a-third])`,
24998
25031
  pattern: () => `(pattern: name the general shape)`,
25032
+ // DOMAIN — the abstract area a problem is about; the concept layer an
25033
+ // anchor-less problem clusters on. Mints/resolves a Domain by name.
25034
+ domain: () => `(domain: The Area)`,
24999
25035
  aids: (ref) => `(aids:[${ref}])`
25000
25036
  };
25001
25037
  GLOSS = {
@@ -49331,6 +49367,7 @@ var SUPERSEDES_PREFIX = /^\s*supersedes:(?:#([a-z][\w-]{0,63}))?\s*/i;
49331
49367
  var ALTERNATIVE_PREFIX = /^\s*alternative:(?:#([a-z][\w-]{0,63}))?\s*/i;
49332
49368
  var INSTANCE_PREFIX = /^\s*instance:\s*/i;
49333
49369
  var PATTERN_RE = /\(\s*pattern:\s*([^()\n]{3,}?)\s*\)/gi;
49370
+ var DOMAIN_RE = /\(\s*domain:\s*([^()\n]{3,}?)\s*\)/gi;
49334
49371
  var CAUSE_TEXT_MIN = 8;
49335
49372
  var FLAG_RE = /\[([!?])(?:#([a-z][\w-]{0,63})\s+)?\s*([^\]\n]{8,}?)\s*(?:@\s*([^\s\]]+?)(?::(\d+))?\s*)?\]/g;
49336
49373
  var CONSTRAINT_MIN = 8;
@@ -49520,6 +49557,12 @@ function parseInlineTags(text) {
49520
49557
  }
49521
49558
  }
49522
49559
  }
49560
+ DOMAIN_RE.lastIndex = 0;
49561
+ let dm;
49562
+ while ((dm = DOMAIN_RE.exec(sentence)) !== null) {
49563
+ const raw3 = dm[1].replace(/\s+/g, " ").trim();
49564
+ if (raw3.length >= 3) out2.push({ kind: "domain", domainText: raw3, sentence: sfield });
49565
+ }
49523
49566
  CONSTRAINT_RE.lastIndex = 0;
49524
49567
  let c;
49525
49568
  while ((c = CONSTRAINT_RE.exec(sentence)) !== null) {
@@ -49653,7 +49696,7 @@ function harvestInlineTags(store, text, opts) {
49653
49696
  const source = opts.sourceId ? store.getNode(opts.sourceId) : null;
49654
49697
  const mintPriors = opts.mintPriors ?? true;
49655
49698
  const touched = opts.sessionTouchedIds ?? /* @__PURE__ */ new Set();
49656
- const plan = { priorEdges: 0, problems: [], fixes: [], triages: [], attempts: [], unresolvedFixes: [], transfers: [], solutionLinks: [], instances: [], patterns: [], refutes: [], corroborations: [] };
49699
+ const plan = { priorEdges: 0, problems: [], fixes: [], triages: [], attempts: [], unresolvedFixes: [], transfers: [], solutionLinks: [], instances: [], patterns: [], domains: [], refutes: [], corroborations: [] };
49657
49700
  const tags = parseInlineTags(text);
49658
49701
  const symptomSeqs = tags.filter((t) => (t.kind === "problem" || t.kind === "todo" || t.kind === "constraint") && t.statement).map((t) => ({ seq: t.seq ?? -1, statement: t.statement, threadId: t.threadId })).sort((a, b) => a.seq - b.seq);
49659
49702
  const bindSymptom = (seq, threadId) => {
@@ -49784,6 +49827,15 @@ function harvestInlineTags(store, text, opts) {
49784
49827
  } else if (tag.patternText) {
49785
49828
  plan.patterns.push({ patternText: tag.patternText, ...bound });
49786
49829
  }
49830
+ } else if (tag.kind === "domain") {
49831
+ const b = bindSymptom(tag.seq, tag.threadId);
49832
+ plan.domains.push({
49833
+ domainText: tag.domainText,
49834
+ ...b.statement ? { boundStatement: b.statement } : {},
49835
+ ...b.problemId ? { problemId: b.problemId } : {},
49836
+ ...tag.threadId ? { threadId: tag.threadId } : {},
49837
+ evidence: b.evidence
49838
+ });
49787
49839
  } else if (tag.kind === "attempt" || tag.kind === "failure") {
49788
49840
  for (const h of tag.refuteHandles ?? []) {
49789
49841
  const nodeId = resolveHandle(store, h, opts.handleMap);
@@ -51386,7 +51438,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
51386
51438
  }
51387
51439
 
51388
51440
  // src/engine.ts
51389
- var DAEMON_VERSION = true ? "2.0.0-dev.92" : "2.0.0-alpha.0";
51441
+ var DAEMON_VERSION = true ? "2.0.0-dev.94" : "2.0.0-alpha.0";
51390
51442
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
51391
51443
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
51392
51444
  var GIT_OP_MUTE_MS = 4e3;
@@ -52213,6 +52265,13 @@ function createWorkspaceEngine(opts) {
52213
52265
  if (!patternId || patternId === pid) continue;
52214
52266
  mintCiteEdge(pid, patternId, "INSTANCE_OF", pt.evidence === "witnessed" ? 0.4 : 0.3, { patternCite: true, evidence: pt.evidence });
52215
52267
  }
52268
+ for (const d of plan.domains) {
52269
+ const pid = bindPid(d);
52270
+ if (!pid) continue;
52271
+ const domainId = mintDomainNode(store, d.domainText, t);
52272
+ if (domainId === pid) continue;
52273
+ mintCiteEdge(pid, domainId, "PERTAIN_TO", d.evidence === "witnessed" ? 0.4 : 0.3, { domainCite: true, evidence: d.evidence });
52274
+ }
52216
52275
  for (const inst of plan.instances) {
52217
52276
  const pid = bindPid(inst);
52218
52277
  if (!pid) continue;
@@ -53067,8 +53126,8 @@ function noveltyAgainst(node2, neighbors, opts = {}) {
53067
53126
  // src/instance-ingest.ts
53068
53127
  var INSTANCE_LABELS = ["Problem", "Solution", "RootCause"];
53069
53128
  var INSTANCE_EDGES = ["CAUSED_BY", "SOLVED_BY"];
53070
- var ANCHOR_EDGES = ["OCCURS_IN", "DEPENDS_ON"];
53071
- var ANCHOR_TARGET_LABELS = ["Language", "Package"];
53129
+ var ANCHOR_EDGES = ["OCCURS_IN", "DEPENDS_ON", "PERTAIN_TO"];
53130
+ var ANCHOR_TARGET_LABELS = ["Language", "Package", "Domain"];
53072
53131
  function stripCodebaseScope(scope) {
53073
53132
  const s = { ...scope ?? {} };
53074
53133
  delete s["codebase"];
@@ -53079,21 +53138,20 @@ function wireContextId(n) {
53079
53138
  const name2 = String(n.attrs["name"] ?? "").trim() || n.description.trim() || n.id.replace(/^lang:/, "");
53080
53139
  return languageCanonicalId(name2);
53081
53140
  }
53141
+ if (n.label === "Domain" && n.attrs["source"] !== "cloud") {
53142
+ return String(n.attrs["canonicalId"] ?? n.id);
53143
+ }
53082
53144
  return n.id;
53083
53145
  }
53084
53146
  function shareableContext(n, wireId) {
53085
- return {
53086
- ...n,
53087
- id: wireId,
53088
- embedding: [],
53089
- attrs: n.label === "Package" ? {
53090
- purl: n.attrs["purl"],
53091
- name: n.attrs["name"],
53092
- version: n.attrs["version"],
53093
- ecosystem: n.attrs["ecosystem"],
53094
- resolved: n.attrs["resolved"]
53095
- } : { name: n.attrs["name"] }
53096
- };
53147
+ const attrs = n.label === "Package" ? {
53148
+ purl: n.attrs["purl"],
53149
+ name: n.attrs["name"],
53150
+ version: n.attrs["version"],
53151
+ ecosystem: n.attrs["ecosystem"],
53152
+ resolved: n.attrs["resolved"]
53153
+ } : n.label === "Domain" ? { name: n.description, canonicalId: n.attrs["canonicalId"] } : { name: n.attrs["name"] };
53154
+ return { ...n, id: wireId, embedding: [], attrs };
53097
53155
  }
53098
53156
  function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [], opts = {}) {
53099
53157
  const level = opts.level ?? 1;
@@ -53149,6 +53207,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
53149
53207
  if (!t || !ANCHOR_TARGET_LABELS.includes(t.label)) continue;
53150
53208
  if (e.type === "OCCURS_IN" && t.label !== "Language") continue;
53151
53209
  if (e.type === "DEPENDS_ON" && t.label !== "Package") continue;
53210
+ if (e.type === "PERTAIN_TO" && t.label !== "Domain") continue;
53152
53211
  if (t.label === "Package" && opts.includePackages !== true) continue;
53153
53212
  if (ignored(t.description) || ignored(String(t.attrs["name"] ?? ""))) continue;
53154
53213
  targets.push({ e, t, wireId: wireContextId(t) });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.0-dev.92",
3
+ "version": "2.0.0-dev.94",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -26091,12 +26091,19 @@ function buildSnapshot(opts) {
26091
26091
  const causalNudge = recent.length >= 2 && recent.every(
26092
26092
  (r) => opts.store.outEdges(r.node.id, ["CAUSED_BY"]).length === 0 && opts.store.inEdges(r.node.id, ["CAUSED_BY"]).length === 0
26093
26093
  );
26094
+ const abstractUndomained = recent.filter((r) => {
26095
+ const grounded = opts.store.outEdges(r.node.id, ["ANCHORED_AT", "OCCURS_IN", "DEPENDS_ON"]).length > 0;
26096
+ const hasDomain = opts.store.outEdges(r.node.id, ["PERTAIN_TO"]).length > 0;
26097
+ return !grounded && !hasDomain;
26098
+ });
26099
+ const domainNudge = abstractUndomained.length >= 2;
26094
26100
  return {
26095
26101
  profile: opts.profile,
26096
26102
  profileContext,
26097
26103
  recentProblems: recent,
26098
26104
  recentResolved,
26099
26105
  ...causalNudge ? { causalNudge } : {},
26106
+ ...domainNudge ? { domainNudge } : {},
26100
26107
  motifs,
26101
26108
  reviewCount: opts.reviewCount,
26102
26109
  reviewUiUrl: opts.reviewUiUrl,