@inerrata-corporation/errata 2.0.0-dev.31 → 2.0.0-dev.33

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.
@@ -14,7 +14,7 @@ var __export = (target, all) => {
14
14
  function isCausalProtected(type) {
15
15
  return CAUSAL_PROTECT_EDGES.includes(type);
16
16
  }
17
- var SEMANTIC_NODE_LABELS, CONTEXT_NODE_LABELS, CODE_NODE_LABELS, ALL_NODE_LABELS, STRUCTURAL_EDGES, CAUSAL_EDGES, RESOLUTION_EDGES, CONCEPTUAL_EDGES, EVIDENCE_EDGES, CODE_EDGES, BRIDGE_EDGES, IDENTITY_EDGES, JUSTIFICATION_EDGES, BELIEF_EDGES, ABSTRACTION_EDGES, DECOMPOSITION_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, EDGE_WEIGHT, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, ABSTRACTION_LEVEL, PROBLEM_RESOLUTION, DRIFT_KIND;
17
+ var SEMANTIC_NODE_LABELS, CONTEXT_NODE_LABELS, CODE_NODE_LABELS, ALL_NODE_LABELS, STRUCTURAL_EDGES, CAUSAL_EDGES, RESOLUTION_EDGES, CONCEPTUAL_EDGES, EVIDENCE_EDGES, CODE_EDGES, BRIDGE_EDGES, IDENTITY_EDGES, JUSTIFICATION_EDGES, BELIEF_EDGES, ABSTRACTION_EDGES, DECOMPOSITION_EDGES, TRANSFER_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, EDGE_WEIGHT, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, ABSTRACTION_LEVEL, PROBLEM_RESOLUTION, DRIFT_KIND;
18
18
  var init_castalia = __esm({
19
19
  "../../packages/shared/src/castalia.ts"() {
20
20
  "use strict";
@@ -164,6 +164,7 @@ var init_castalia = __esm({
164
164
  BELIEF_EDGES = ["CORROBORATES"];
165
165
  ABSTRACTION_EDGES = ["GENERALIZES", "DERIVED_FROM"];
166
166
  DECOMPOSITION_EDGES = ["SPLIT_INTO"];
167
+ TRANSFER_EDGES = ["MAY_RESOLVE"];
167
168
  TAXONOMY_EDGES = ["IS_A"];
168
169
  TRIAGE_EDGES = ["TRIAGED_BY", "CONFIRMS", "INDICATES", "ROUTES_TO"];
169
170
  GIT_EDGES = ["POINTS_AT", "PARENT", "AUTHORED_BY"];
@@ -178,6 +179,7 @@ var init_castalia = __esm({
178
179
  ...IDENTITY_EDGES,
179
180
  ...JUSTIFICATION_EDGES,
180
181
  ...BELIEF_EDGES,
182
+ ...TRANSFER_EDGES,
181
183
  ...ABSTRACTION_EDGES,
182
184
  ...DECOMPOSITION_EDGES,
183
185
  ...TAXONOMY_EDGES,
@@ -273,6 +275,10 @@ var init_castalia = __esm({
273
275
  INDICATES: 0.4,
274
276
  ROUTES_TO: 1,
275
277
  TRIAGED_BY: 0,
278
+ // Transfer — a witnessed could-aid hypothesis (Solution → Problem). Discounted like
279
+ // INDICATES: real signal, but a candidate must not form a hub; promotion mints the
280
+ // full-weight SOLVED_BY/MITIGATES instead of upgrading this edge.
281
+ MAY_RESOLVE: 0.3,
276
282
  // Git — topology/authorship, weightless (not domain signal-flow)
277
283
  POINTS_AT: 0,
278
284
  PARENT: 0,
package/errata.mjs CHANGED
@@ -20,16 +20,51 @@ function pagerankEdgeTypes() {
20
20
  (e) => !PAGERANK_EXCLUSIONS.has(e)
21
21
  );
22
22
  }
23
+ function isInferredSource(source) {
24
+ return source === "bko-inferred" || source === "cold-start-seed";
25
+ }
26
+ function normalizeExtractionSource(value) {
27
+ switch (value) {
28
+ case "agent-observed":
29
+ case "daemon-extracted":
30
+ case "bko-inferred":
31
+ case "cold-start-seed":
32
+ case "user-edited":
33
+ return value;
34
+ default:
35
+ return "cold-start-seed";
36
+ }
37
+ }
38
+ function isSemanticLabel(label) {
39
+ return SEMANTIC_NODE_LABELS.includes(label);
40
+ }
23
41
  function isCodeLabel(label) {
24
42
  return CODE_NODE_LABELS.includes(label);
25
43
  }
44
+ function isContextLabel(label) {
45
+ return CONTEXT_NODE_LABELS.includes(label);
46
+ }
47
+ function isValidEdgeType(type) {
48
+ return ALL_EDGE_TYPES.includes(type);
49
+ }
26
50
  function isTestRelPath(relPath) {
27
51
  return TEST_PATH_RE.test(relPath);
28
52
  }
29
53
  function isTestScopeQname(qname) {
30
54
  return TEST_SCOPE_RE.test(qname);
31
55
  }
32
- var SEMANTIC_NODE_LABELS, CONTEXT_NODE_LABELS, CODE_NODE_LABELS, ALL_NODE_LABELS, STRUCTURAL_EDGES, CAUSAL_EDGES, RESOLUTION_EDGES, CONCEPTUAL_EDGES, EVIDENCE_EDGES, CODE_EDGES, BRIDGE_EDGES, IDENTITY_EDGES, JUSTIFICATION_EDGES, BELIEF_EDGES, ABSTRACTION_EDGES, DECOMPOSITION_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, PAGERANK_EXCLUSIONS, EDGE_WEIGHT, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, ABSTRACTION_LEVEL, PROBLEM_RESOLUTION, DRIFT_KIND, TEST_PATH_RE, TEST_SCOPE_RE;
56
+ function toCloudAttrs(attrs) {
57
+ const rest2 = { ...attrs };
58
+ delete rest2["confidence"];
59
+ const scope = rest2["scope"];
60
+ if (scope && typeof scope === "object" && !Array.isArray(scope)) {
61
+ const scopeCopy = { ...scope };
62
+ delete scopeCopy["codebase"];
63
+ rest2["scope"] = scopeCopy;
64
+ }
65
+ return rest2;
66
+ }
67
+ var SEMANTIC_NODE_LABELS, CONTEXT_NODE_LABELS, CODE_NODE_LABELS, ALL_NODE_LABELS, STRUCTURAL_EDGES, CAUSAL_EDGES, RESOLUTION_EDGES, CONCEPTUAL_EDGES, EVIDENCE_EDGES, CODE_EDGES, BRIDGE_EDGES, IDENTITY_EDGES, JUSTIFICATION_EDGES, BELIEF_EDGES, ABSTRACTION_EDGES, DECOMPOSITION_EDGES, TRANSFER_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, PAGERANK_EXCLUSIONS, EDGE_WEIGHT, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, TRUTH_KIND, ABSTRACTION_LEVEL, PROBLEM_RESOLUTION, DRIFT_KIND, TEST_PATH_RE, TEST_SCOPE_RE;
33
68
  var init_castalia = __esm({
34
69
  "../../packages/shared/src/castalia.ts"() {
35
70
  "use strict";
@@ -179,6 +214,7 @@ var init_castalia = __esm({
179
214
  BELIEF_EDGES = ["CORROBORATES"];
180
215
  ABSTRACTION_EDGES = ["GENERALIZES", "DERIVED_FROM"];
181
216
  DECOMPOSITION_EDGES = ["SPLIT_INTO"];
217
+ TRANSFER_EDGES = ["MAY_RESOLVE"];
182
218
  TAXONOMY_EDGES = ["IS_A"];
183
219
  TRIAGE_EDGES = ["TRIAGED_BY", "CONFIRMS", "INDICATES", "ROUTES_TO"];
184
220
  GIT_EDGES = ["POINTS_AT", "PARENT", "AUTHORED_BY"];
@@ -193,6 +229,7 @@ var init_castalia = __esm({
193
229
  ...IDENTITY_EDGES,
194
230
  ...JUSTIFICATION_EDGES,
195
231
  ...BELIEF_EDGES,
232
+ ...TRANSFER_EDGES,
196
233
  ...ABSTRACTION_EDGES,
197
234
  ...DECOMPOSITION_EDGES,
198
235
  ...TAXONOMY_EDGES,
@@ -319,6 +356,10 @@ var init_castalia = __esm({
319
356
  INDICATES: 0.4,
320
357
  ROUTES_TO: 1,
321
358
  TRIAGED_BY: 0,
359
+ // Transfer — a witnessed could-aid hypothesis (Solution → Problem). Discounted like
360
+ // INDICATES: real signal, but a candidate must not form a hub; promotion mints the
361
+ // full-weight SOLVED_BY/MITIGATES instead of upgrading this edge.
362
+ MAY_RESOLVE: 0.3,
322
363
  // Git — topology/authorship, weightless (not domain signal-flow)
323
364
  POINTS_AT: 0,
324
365
  PARENT: 0,
@@ -331,6 +372,11 @@ var init_castalia = __esm({
331
372
  "agent-observed",
332
373
  "machine-derived"
333
374
  ];
375
+ TRUTH_KIND = {
376
+ OBJECTIVE: "objective",
377
+ CONTEXTUAL: "contextual",
378
+ TASTE: "taste"
379
+ };
334
380
  ABSTRACTION_LEVEL = { CONCRETE: 1, PRINCIPLE: 2 };
335
381
  PROBLEM_RESOLUTION = {
336
382
  FIXED: "fixed",
@@ -478,6 +524,9 @@ function canonicalizeError(raw2) {
478
524
  const sig = { ...canonical, digest: digest(canonical) };
479
525
  return sig;
480
526
  }
527
+ function errorSignatureEqual(a, b) {
528
+ return a.digest === b.digest;
529
+ }
481
530
  function problemIdFromError(sig) {
482
531
  return `prob_${sha256(sig.digest).slice(0, 16)}`;
483
532
  }
@@ -498,6 +547,9 @@ function resolveCanonical(label) {
498
547
  function resolveCanonicalId(label) {
499
548
  return resolveCanonical(label)?.id;
500
549
  }
550
+ function allEntities() {
551
+ return REGISTRY;
552
+ }
501
553
  function aliasesLongestFirst() {
502
554
  const out2 = [];
503
555
  for (const e of REGISTRY) for (const a of e.aliases) out2.push({ alias: a.toLowerCase(), entity: e });
@@ -796,6 +848,26 @@ function genericCanonicalId(prefix, content) {
796
848
  function languageCanonicalId(name2) {
797
849
  return genericCanonicalId("Language", { name: name2.trim().toLowerCase() });
798
850
  }
851
+ function packageCanonicalId(p) {
852
+ const eco = p.ecosystem.toLowerCase();
853
+ const name2 = eco === "npm" ? p.name.toLowerCase() : p.name;
854
+ return `pkg:${eco}/${name2}${p.version ? `@${p.version}` : ""}`;
855
+ }
856
+ function parsePackageRef(ref) {
857
+ let rest2 = ref.trim();
858
+ if (rest2.startsWith("pkg:")) {
859
+ rest2 = rest2.slice(4);
860
+ const slash = rest2.indexOf("/");
861
+ if (slash !== -1) rest2 = rest2.slice(slash + 1);
862
+ const q = rest2.search(/[?#]/);
863
+ if (q !== -1) rest2 = rest2.slice(0, q);
864
+ }
865
+ const at = rest2.lastIndexOf("@");
866
+ const name2 = at > 0 ? rest2.slice(0, at) : rest2;
867
+ const version2 = at > 0 ? rest2.slice(at + 1) || null : null;
868
+ const slug2 = (version2 ? `${name2}@${version2}` : name2).toLowerCase();
869
+ return { name: name2, version: version2, slug: slug2 };
870
+ }
799
871
  var DESIGN_PROBLEM_PREFIX, DESIGN_PROBLEM_ID_LENGTH, DIAGNOSTIC_PROBLEM_PREFIX, DIAGNOSTIC_HASH_LENGTH, TRIAGE_PREFIX, TRIAGE_ID_LENGTH;
800
872
  var init_identity = __esm({
801
873
  "../../packages/shared/src/identity.ts"() {
@@ -15128,13 +15200,113 @@ var init_zod = __esm({
15128
15200
  });
15129
15201
 
15130
15202
  // ../../packages/shared/src/edge-rules.ts
15203
+ function isValidEdge(from, type, to) {
15204
+ const rule = EDGE_RULES[type];
15205
+ if (!rule) return { ok: true };
15206
+ if (from && rule.from && !rule.from.includes(from)) {
15207
+ return {
15208
+ ok: false,
15209
+ reason: `${type} cannot originate from ${from} (allowed: ${rule.from.join(", ")})`
15210
+ };
15211
+ }
15212
+ if (to && rule.to && !rule.to.includes(to)) {
15213
+ return {
15214
+ ok: false,
15215
+ reason: `${type} cannot target ${to} (allowed: ${rule.to.join(", ")})`
15216
+ };
15217
+ }
15218
+ return { ok: true };
15219
+ }
15220
+ var EDGE_RULES;
15131
15221
  var init_edge_rules = __esm({
15132
15222
  "../../packages/shared/src/edge-rules.ts"() {
15133
15223
  "use strict";
15224
+ EDGE_RULES = {
15225
+ // ── Security spine (v1 taxonomy.ts SECURITY_FORWARD_ONLY commentary) ──
15226
+ TARGETS: { from: ["Exploit"], to: ["Vulnerability"] },
15227
+ ENABLES: { from: ["AntiPattern"], to: ["Vulnerability"] },
15228
+ MITIGATES: { from: ["Solution"], to: ["Vulnerability"] },
15229
+ PRESENTS: { from: ["Solution"], to: ["Problem", "Vulnerability"] },
15230
+ // SOLVED_BY sources: Vulnerability (v1 comment) + Problem/RootCause
15231
+ // (upstream design-problem.ts + triage.ts mint both).
15232
+ SOLVED_BY: { from: ["Vulnerability", "Problem", "RootCause"], to: ["Solution"] },
15233
+ FIXED_BY: { to: ["Solution"] },
15234
+ // ── Triage family (upstream castalia.ts: Problem —TRIAGED_BY→ Triage —{INDICATES|CONFIRMS}→ cause) ──
15235
+ // Two-edge differential model (T3-rename): INDICATES = provisional candidate,
15236
+ // CONFIRMS = promoted router (a discriminator exists). Same endpoint matrix.
15237
+ // ROUTES_TO is the deprecated pre-split alias, kept readable during migration.
15238
+ TRIAGED_BY: { from: ["Problem"], to: ["Triage"] },
15239
+ CONFIRMS: { from: ["Triage"], to: ["RootCause", "Problem"] },
15240
+ INDICATES: { from: ["Triage"], to: ["RootCause", "Problem"] },
15241
+ ROUTES_TO: { from: ["Triage"], to: ["RootCause", "Problem"] },
15242
+ // ── Context grounding (v1 taxonomy.ts comments) ──
15243
+ WRITTEN_IN: { from: ["Component", "Package"], to: ["Language"] },
15244
+ OCCURS_IN: { to: ["Language"] },
15245
+ OCCURS_ON: { to: ["OperatingSystem"] },
15246
+ RUNS_ON: { to: ["OperatingSystem"] },
15247
+ OPERATES_ON: { from: ["Algorithm"], to: ["DataStructure"] },
15248
+ INVOLVES: { from: ["Problem", "Solution"], to: ["DataStructure"] },
15249
+ // ── Taxonomy (Track 4 Stream C: MITRE CWE `ChildOf` → `Weakness —IS_A→ Weakness`) ──
15250
+ IS_A: { from: ["Weakness"], to: ["Weakness"] },
15251
+ // ── Conceptual (v1 taxonomy.ts: instance → motif/pattern reference) ──
15252
+ INSTANCE_OF: { to: ["Pattern", "Weakness", "Technique"] },
15253
+ IMPLEMENTS: { from: ["Solution", "Language", "Component"], to: ["Pattern", "Technique"] },
15254
+ MATCHES: { to: ["Pattern"] },
15255
+ // ── Artifact evidence (v1 taxonomy.ts artifact rows) ──
15256
+ PRODUCED: { from: ["Report"], to: ["Artifact"] },
15257
+ MANIFESTED_IN: { from: ["Problem"], to: ["Artifact"] },
15258
+ REVEALED_BY: { from: ["RootCause"], to: ["Artifact"] },
15259
+ // ── Belief / abstraction gradients (upstream castalia.ts) ──
15260
+ CORROBORATES: { from: ["Claim"], to: ["Claim"] },
15261
+ GENERALIZES: { from: ["Claim"] },
15262
+ DERIVED_FROM: { from: ["Claim"] },
15263
+ // ── Decomposition (castalia.ts: a Problem fans out into independent root
15264
+ // problems; §5.1 also attaches SPLIT_INTO to Claim when one conflates two).
15265
+ // `to` left unconstrained — the replacement set's labels vary by case. ──
15266
+ SPLIT_INTO: { from: ["Problem", "Claim"] }
15267
+ };
15134
15268
  }
15135
15269
  });
15136
15270
 
15137
15271
  // ../../packages/shared/src/wire.ts
15272
+ function provenanceBand(source) {
15273
+ switch (source) {
15274
+ case "agent-observed":
15275
+ case "user-edited":
15276
+ return "validated";
15277
+ case "daemon-extracted":
15278
+ case "bko-inferred":
15279
+ return "derived";
15280
+ case "cold-start-seed":
15281
+ return "seed";
15282
+ // Unknown/absent provenance is treated as the weakest band — a node with no
15283
+ // recorded source must never be mistaken for validated knowledge.
15284
+ default:
15285
+ return "seed";
15286
+ }
15287
+ }
15288
+ function isSeedProvenance(source) {
15289
+ return provenanceBand(source) === "seed";
15290
+ }
15291
+ function validateCastaliaPayload(p) {
15292
+ const errors = [];
15293
+ const labelByCid = /* @__PURE__ */ new Map();
15294
+ for (const n of p.nodes) {
15295
+ if (labelByCid.has(n.canonicalId)) errors.push(`duplicate node canonicalId '${n.canonicalId}'`);
15296
+ labelByCid.set(n.canonicalId, n.label);
15297
+ }
15298
+ for (const e of p.edges) {
15299
+ if (e.fromCanonicalId === e.toCanonicalId) {
15300
+ errors.push(`self-loop edge ${e.type} on '${e.fromCanonicalId}'`);
15301
+ continue;
15302
+ }
15303
+ const verdict = isValidEdge(labelByCid.get(e.fromCanonicalId), e.type, labelByCid.get(e.toCanonicalId));
15304
+ if (!verdict.ok) {
15305
+ errors.push(`edge ${e.fromCanonicalId} -${e.type}\u2192 ${e.toCanonicalId}: ${verdict.reason}`);
15306
+ }
15307
+ }
15308
+ return { ok: errors.length === 0, errors };
15309
+ }
15138
15310
  function summarizeIngestResult(r) {
15139
15311
  const all = [...r.nodes, ...r.edges];
15140
15312
  const rejectedItems = all.filter((x) => x.decision === "rejected");
@@ -15145,7 +15317,7 @@ function summarizeIngestResult(r) {
15145
15317
  ...r.patternReconciliation ? { patternReconciliation: r.patternReconciliation } : {}
15146
15318
  };
15147
15319
  }
15148
- var CLOUD_NODE_LABELS, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, MAX_EDGES_PER_PAYLOAD, CastaliaIngestNodeSchema, RouteContextCountWireSchema, CastaliaIngestEdgeSchema, CastaliaIngestPayloadSchema;
15320
+ var CLOUD_NODE_LABELS, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, MAX_NODES_PER_PAYLOAD, MAX_EDGES_PER_PAYLOAD, CastaliaIngestNodeSchema, RouteContextCountWireSchema, CastaliaIngestEdgeSchema, CastaliaIngestPayloadSchema;
15149
15321
  var init_wire = __esm({
15150
15322
  "../../packages/shared/src/wire.ts"() {
15151
15323
  "use strict";
@@ -15167,6 +15339,7 @@ var init_wire = __esm({
15167
15339
  "cold-start-seed",
15168
15340
  "user-edited"
15169
15341
  ];
15342
+ MAX_NODES_PER_PAYLOAD = 200;
15170
15343
  MAX_EDGES_PER_PAYLOAD = 500;
15171
15344
  CastaliaIngestNodeSchema = external_exports.object({
15172
15345
  /** Deterministic content id from identity.ts — the cross-stratum merge key. */
@@ -15211,6 +15384,9 @@ var init_wire = __esm({
15211
15384
  });
15212
15385
 
15213
15386
  // ../../packages/shared/src/nlp/canonicalize.ts
15387
+ function canonicalize(value) {
15388
+ return value.normalize("NFC").trim().toLowerCase().replace(/\s+/g, " ");
15389
+ }
15214
15390
  var init_canonicalize = __esm({
15215
15391
  "../../packages/shared/src/nlp/canonicalize.ts"() {
15216
15392
  "use strict";
@@ -15236,6 +15412,91 @@ var init_triage_canon = __esm({
15236
15412
  });
15237
15413
 
15238
15414
  // ../../packages/shared/src/index.ts
15415
+ var src_exports = {};
15416
+ __export(src_exports, {
15417
+ ABSTRACTION_EDGES: () => ABSTRACTION_EDGES,
15418
+ ABSTRACTION_LEVEL: () => ABSTRACTION_LEVEL,
15419
+ ALL_EDGE_TYPES: () => ALL_EDGE_TYPES,
15420
+ ALL_NODE_LABELS: () => ALL_NODE_LABELS,
15421
+ BELIEF_EDGES: () => BELIEF_EDGES,
15422
+ BRIDGE_EDGES: () => BRIDGE_EDGES,
15423
+ CAUSAL_EDGES: () => CAUSAL_EDGES,
15424
+ CAUSAL_PROTECT_EDGES: () => CAUSAL_PROTECT_EDGES,
15425
+ CLOUD_EDGE_TYPES: () => CLOUD_EDGE_TYPES,
15426
+ CLOUD_NODE_LABELS: () => CLOUD_NODE_LABELS,
15427
+ CODE_EDGES: () => CODE_EDGES,
15428
+ CODE_NODE_LABELS: () => CODE_NODE_LABELS,
15429
+ CONCEPTUAL_EDGES: () => CONCEPTUAL_EDGES,
15430
+ CONTEXT_NODE_LABELS: () => CONTEXT_NODE_LABELS,
15431
+ CastaliaIngestEdgeSchema: () => CastaliaIngestEdgeSchema,
15432
+ CastaliaIngestNodeSchema: () => CastaliaIngestNodeSchema,
15433
+ CastaliaIngestPayloadSchema: () => CastaliaIngestPayloadSchema,
15434
+ DECOMPOSITION_EDGES: () => DECOMPOSITION_EDGES,
15435
+ DRIFT_KIND: () => DRIFT_KIND,
15436
+ EDGE_RULES: () => EDGE_RULES,
15437
+ EDGE_WEIGHT: () => EDGE_WEIGHT,
15438
+ EVIDENCE_EDGES: () => EVIDENCE_EDGES,
15439
+ GIT_EDGES: () => GIT_EDGES,
15440
+ IDENTITY_EDGES: () => IDENTITY_EDGES,
15441
+ INGEST_EXTRACTION_SOURCES: () => INGEST_EXTRACTION_SOURCES,
15442
+ INGEST_SOURCES: () => INGEST_SOURCES,
15443
+ JUSTIFICATION_EDGES: () => JUSTIFICATION_EDGES,
15444
+ MAX_EDGES_PER_PAYLOAD: () => MAX_EDGES_PER_PAYLOAD,
15445
+ MAX_NODES_PER_PAYLOAD: () => MAX_NODES_PER_PAYLOAD,
15446
+ PAGERANK_EXCLUSIONS: () => PAGERANK_EXCLUSIONS,
15447
+ PROBLEM_RESOLUTION: () => PROBLEM_RESOLUTION,
15448
+ RESOLUTION_EDGES: () => RESOLUTION_EDGES,
15449
+ RouteContextCountWireSchema: () => RouteContextCountWireSchema,
15450
+ SEMANTIC_NODE_LABELS: () => SEMANTIC_NODE_LABELS,
15451
+ STRUCTURAL_EDGES: () => STRUCTURAL_EDGES,
15452
+ TAXONOMY_EDGES: () => TAXONOMY_EDGES,
15453
+ TRANSFER_EDGES: () => TRANSFER_EDGES,
15454
+ TRIAGE_EDGES: () => TRIAGE_EDGES,
15455
+ TRUTH_KIND: () => TRUTH_KIND,
15456
+ VALIDATION_SOURCES: () => VALIDATION_SOURCES,
15457
+ aliasesLongestFirst: () => aliasesLongestFirst,
15458
+ allEntities: () => allEntities,
15459
+ canonicalClaimId: () => canonicalClaimId,
15460
+ canonicalJSON: () => canonicalJSON,
15461
+ canonicalize: () => canonicalize,
15462
+ canonicalizeContext: () => canonicalizeContext,
15463
+ canonicalizeError: () => canonicalizeError,
15464
+ canonicalizeToken: () => canonicalizeToken,
15465
+ claimStructure: () => claimStructure,
15466
+ conceptBag: () => conceptBag,
15467
+ conceptTokens: () => conceptTokens,
15468
+ detectStance: () => detectStance,
15469
+ digest: () => digest,
15470
+ errorSignatureEqual: () => errorSignatureEqual,
15471
+ genericCanonicalId: () => genericCanonicalId,
15472
+ identityId: () => identityId,
15473
+ isCausalProtected: () => isCausalProtected,
15474
+ isCodeLabel: () => isCodeLabel,
15475
+ isContextLabel: () => isContextLabel,
15476
+ isInferredSource: () => isInferredSource,
15477
+ isSeedProvenance: () => isSeedProvenance,
15478
+ isSemanticLabel: () => isSemanticLabel,
15479
+ isTestRelPath: () => isTestRelPath,
15480
+ isTestScopeQname: () => isTestScopeQname,
15481
+ isValidEdge: () => isValidEdge,
15482
+ isValidEdgeType: () => isValidEdgeType,
15483
+ languageCanonicalId: () => languageCanonicalId,
15484
+ normalizeExtractionSource: () => normalizeExtractionSource,
15485
+ normalizePredicate: () => normalizePredicate,
15486
+ packageCanonicalId: () => packageCanonicalId,
15487
+ pagerankEdgeTypes: () => pagerankEdgeTypes,
15488
+ parsePackageRef: () => parsePackageRef,
15489
+ prefilterEntities: () => prefilterEntities,
15490
+ problemIdFromError: () => problemIdFromError,
15491
+ provenanceBand: () => provenanceBand,
15492
+ resolveCanonical: () => resolveCanonical,
15493
+ resolveCanonicalId: () => resolveCanonicalId,
15494
+ sha256: () => sha256,
15495
+ sha256Short: () => sha256Short,
15496
+ summarizeIngestResult: () => summarizeIngestResult,
15497
+ toCloudAttrs: () => toCloudAttrs,
15498
+ validateCastaliaPayload: () => validateCastaliaPayload
15499
+ });
15239
15500
  var init_src = __esm({
15240
15501
  "../../packages/shared/src/index.ts"() {
15241
15502
  "use strict";
@@ -17312,6 +17573,16 @@ function ingestDesignProblem(store, flag, opts) {
17312
17573
  const linkedPackages = linkProblemToPackages(store, problemId, linkText, opts.ts).linked;
17313
17574
  return { problemId, created, corroborated, rootCauseId, solutionId, anchored, linkedPackages };
17314
17575
  }
17576
+ function mintPatternNode(store, name2, ts) {
17577
+ const display = name2.replace(/\s+/g, " ").trim();
17578
+ const id = `pat_${digest({ pattern: display.toLowerCase() })}`.slice(0, 56);
17579
+ if (!store.getNode(id)) {
17580
+ store.mergeNode(
17581
+ buildNode(id, "Pattern", display, ts, { source: "convo", provisional: true })
17582
+ );
17583
+ }
17584
+ return id;
17585
+ }
17315
17586
  function resolveFileNode(store, path2, workspaceId2) {
17316
17587
  const want = path2.trim().replace(/^\.?\//, "");
17317
17588
  for (const n of store.findNodesByLabel("File")) {
@@ -17513,12 +17784,14 @@ function resolveDesignProblems(store, t) {
17513
17784
  if (!p.id.startsWith("dprob_")) continue;
17514
17785
  if (p.attrs["resolvedAt"]) continue;
17515
17786
  let symName = "";
17787
+ let symRelPath;
17516
17788
  let edited = false;
17517
17789
  for (const e of store.outEdges(p.id, ["ANCHORED_AT"])) {
17518
17790
  const sym = store.getNode(e.to);
17519
17791
  if (sym && sym.lastUpdatedAt > p.createdAt) {
17520
17792
  edited = true;
17521
17793
  symName = sym.description;
17794
+ symRelPath = sym.attrs["relPath"] ?? void 0;
17522
17795
  break;
17523
17796
  }
17524
17797
  }
@@ -17528,7 +17801,11 @@ function resolveDesignProblems(store, t) {
17528
17801
  store.mergeNode(
17529
17802
  buildNode(solId, "Solution", `addressed by an edit to ${symName}`, t, {
17530
17803
  source: "convo",
17531
- provisional: false
17804
+ provisional: false,
17805
+ // AC-resolution-attrs: the resolving symbol/file as STRUCTURED data, not
17806
+ // just prose — the F2 join key downstream backfills and the viz read.
17807
+ resolvedSymbols: [symName],
17808
+ ...symRelPath ? { resolvedRelPath: symRelPath } : {}
17532
17809
  })
17533
17810
  );
17534
17811
  mergeEdge(store, p.id, solId, "SOLVED_BY", t);
@@ -19503,8 +19780,8 @@ var init_principle_sync = __esm({
19503
19780
  });
19504
19781
 
19505
19782
  // ../../packages/local-graph/src/index.ts
19506
- var src_exports = {};
19507
- __export(src_exports, {
19783
+ var src_exports2 = {};
19784
+ __export(src_exports2, {
19508
19785
  CAUSAL_FAMILY: () => CAUSAL_FAMILY,
19509
19786
  CITABLE_PRIOR_LABELS: () => CITABLE_PRIOR_LABELS,
19510
19787
  CODE_REACH_EDGES: () => CODE_REACH_EDGES,
@@ -19558,6 +19835,7 @@ __export(src_exports, {
19558
19835
  matchPackagesInText: () => matchPackagesInText,
19559
19836
  mergeCloudCounts: () => mergeCloudCounts,
19560
19837
  mergeDuplicateProblems: () => mergeDuplicateProblems,
19838
+ mintPatternNode: () => mintPatternNode,
19561
19839
  openGraphStore: () => openGraphStore,
19562
19840
  parseAbstractionFences: () => parseAbstractionFences,
19563
19841
  parseSemver: () => parseSemver,
@@ -20156,6 +20434,37 @@ async function postToken(fetchFn, tokenEndpoint, params, timeoutMs = 15e3) {
20156
20434
  clearTimeout(tid);
20157
20435
  }
20158
20436
  }
20437
+ async function registerOAuthClient(fetchFn, registrationEndpoint, p, timeoutMs = 15e3) {
20438
+ const ac = new AbortController();
20439
+ const tid = setTimeout(() => ac.abort(), timeoutMs);
20440
+ try {
20441
+ const res = await fetchFn(registrationEndpoint, {
20442
+ method: "POST",
20443
+ headers: {
20444
+ "content-type": "application/json",
20445
+ accept: "application/json"
20446
+ },
20447
+ body: JSON.stringify({
20448
+ redirect_uris: [p.redirectUri],
20449
+ token_endpoint_auth_method: "none",
20450
+ grant_types: ["authorization_code", "refresh_token"],
20451
+ response_types: ["code"],
20452
+ client_name: p.clientName ?? "errata daemon",
20453
+ scope: p.scope
20454
+ }),
20455
+ signal: ac.signal
20456
+ });
20457
+ if (!res.ok) {
20458
+ const text = await res.text();
20459
+ throw new Error(`client registration failed: HTTP ${res.status} ${text.slice(0, 200)}`);
20460
+ }
20461
+ const j = await res.json();
20462
+ if (!j.client_id) throw new Error("client registration returned no client_id");
20463
+ return { clientId: j.client_id };
20464
+ } finally {
20465
+ clearTimeout(tid);
20466
+ }
20467
+ }
20159
20468
  function exchangeAuthorizationCode(fetchFn, tokenEndpoint, p) {
20160
20469
  return postToken(fetchFn, tokenEndpoint, {
20161
20470
  grant_type: "authorization_code",
@@ -20643,6 +20952,7 @@ function defaultConfig() {
20643
20952
  accessToken: null,
20644
20953
  refreshToken: null,
20645
20954
  tokenEndpoint: null,
20955
+ oauthClientId: null,
20646
20956
  userId: null,
20647
20957
  email: null,
20648
20958
  consent: { sync: false, telemetry: false, contributePackages: false },
@@ -20911,7 +21221,7 @@ function authedCloudClient(cfg, opts = {}) {
20911
21221
  ...tokenEndpoint && cfg.refreshToken ? {
20912
21222
  refreshFn: (rt) => refreshAccessToken(opts.fetchFn ?? fetch, tokenEndpoint, {
20913
21223
  refreshToken: rt,
20914
- clientId: oauthClientId()
21224
+ clientId: cfg.oauthClientId ?? oauthClientId()
20915
21225
  }),
20916
21226
  // Persist the rotated tokens so the next process starts fresh.
20917
21227
  onTokens: (t) => {
@@ -23176,6 +23486,18 @@ function triageBullet(ref) {
23176
23486
  " you? bind by its handle/id directly: (cause:#the-shown-handle \u2026) / (fix:#dprob_\u2026 \u2026)."
23177
23487
  ].join("\n");
23178
23488
  }
23489
+ function linkBullet(ref) {
23490
+ return [
23491
+ " \u2022 a problem you flagged resembles prior knowledge \u2014 LINK it to the canonical priors, not just one:",
23492
+ ` \xB7 (instance:[${ref}],[another-prior],\u2026) \u2014 the priors this problem is an instance of.`,
23493
+ " Aim for ~3 DIFFERENT relevant priors; one link is weak, three triangulate it.",
23494
+ ` \xB7 ${TAG_EXAMPLE.pattern()} \u2014 name the general shape it instantiates (e.g. (pattern: unbounded`,
23495
+ " queue growth under backpressure)) \u2014 this works with NO code anchor, and two agents naming",
23496
+ " the same pattern converge on one node. Cite a shown Pattern by handle: (pattern:[handle]).",
23497
+ ` \xB7 (aids:[${ref}],\u2026) \u2014 your FIX could also help these other, even unrelated, problems.`,
23498
+ " A hypothesis, not a claim \u2014 it's recorded as may-resolve and checked by whoever tries it."
23499
+ ].join("\n");
23500
+ }
23179
23501
  function attemptBullet() {
23180
23502
  return [
23181
23503
  " \u2022 you're attempting an approach to a flagged problem, or an attempt didn't pan out:",
@@ -23186,15 +23508,15 @@ function attemptBullet() {
23186
23508
  ].join("\n");
23187
23509
  }
23188
23510
  function buildAgentInstruction(opts = {}) {
23189
- const signals = opts.signals ?? ["prior", "problem", "fix", "constraint", "triage", "attempt"];
23511
+ const signals = opts.signals ?? ["prior", "problem", "fix", "constraint", "triage", "attempt", "link"];
23190
23512
  const ref = opts.referent ?? "its-handle";
23191
- const token = (s) => s === "problem" ? TAG_EXAMPLE.problem() : s === "constraint" ? TAG_EXAMPLE.constraint() : s === "attempt" ? TAG_EXAMPLE.tried() : TAG_EXAMPLE[s](ref);
23513
+ const token = (s) => s === "problem" ? TAG_EXAMPLE.problem() : s === "constraint" ? TAG_EXAMPLE.constraint() : s === "attempt" ? TAG_EXAMPLE.tried() : s === "link" ? TAG_EXAMPLE.pattern() : TAG_EXAMPLE[s](ref);
23192
23514
  const head2 = `We tag the priors we show you with a short handle like [${opts.handleExample ?? "chokidar-glob"}]. This is a capture protocol, not optional notes: what you DON'T tag is silently lost \u2014 the tag is the ONLY thing recorded. Whenever one of these is true, wrap it inline in your prose (no fences, no extra calls). Tag every one you state; we filter downstream, so don't self-censor or batch:`;
23193
23515
  const tail = "Mid-turn text (between tool calls) can be dropped by the harness \u2014 if a tag above appeared only mid-turn, RESTATE it in your final message of the turn; the final message always survives.";
23194
23516
  return [
23195
23517
  head2,
23196
23518
  ...signals.map(
23197
- (s) => s === "triage" ? triageBullet(ref) : s === "attempt" ? attemptBullet() : ` \u2022 ${GLOSS[s]} \u2192 ${token(s)}`
23519
+ (s) => s === "triage" ? triageBullet(ref) : s === "attempt" ? attemptBullet() : s === "link" ? linkBullet(ref) : ` \u2022 ${GLOSS[s]} \u2192 ${token(s)}`
23198
23520
  ),
23199
23521
  tail
23200
23522
  ].join("\n");
@@ -23230,7 +23552,13 @@ var init_agent_signals = __esm({
23230
23552
  // ATTEMPT arc — what's being tried and what didn't work. A failed attempt is a
23231
23553
  // witnessed NEGATIVE result: it saves the next agent the same dead end.
23232
23554
  tried: () => `(tried: the approach you're attempting)`,
23233
- failed: () => `(failed: what didn't work and the dead end it rules out)`
23555
+ failed: () => `(failed: what didn't work and the dead end it rules out)`,
23556
+ // LINK verbs (AC epic) — bind the problem in scope to CANONICAL priors and
23557
+ // abstractions. Multi-target by design: single links are weak; ~3 links to 3
23558
+ // DIFFERENT relevant priors is the target shape (see linkBullet).
23559
+ instance: (ref) => `(instance:[${ref}],[another],[a-third])`,
23560
+ pattern: () => `(pattern: name the general shape)`,
23561
+ aids: (ref) => `(aids:[${ref}])`
23234
23562
  };
23235
23563
  GLOSS = {
23236
23564
  prior: "a prior we showed you helped \u2014 or this work sits in a primed language/package",
@@ -23238,7 +23566,8 @@ var init_agent_signals = __esm({
23238
23566
  fix: "your edit fixes a problem \u2014 cite the one we showed you, or just say how you fixed one you found yourself: (fix: what you changed)",
23239
23567
  constraint: "you made a design decision because requirements conflict or something's constrained \u2014 tag the tension, ESPECIALLY when your fix makes it 'only look' contradictory (a clean solution still hides a real trap the next agent needs)",
23240
23568
  triage: "you diagnosed a bug \u2014 SPLIT the symptom (what breaks \u2192 [!\u2026]) from the cause (the mechanism you'd change \u2192 (cause:\u2026)); if the line says WHY it breaks, it's a cause, not a problem",
23241
- attempt: "you're attempting an approach, or an attempt didn't pan out \u2014 (tried: \u2026) / (failed: \u2026); a failed attempt rules out a path for the next agent"
23569
+ attempt: "you're attempting an approach, or an attempt didn't pan out \u2014 (tried: \u2026) / (failed: \u2026); a failed attempt rules out a path for the next agent",
23570
+ 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"
23242
23571
  };
23243
23572
  }
23244
23573
  });
@@ -23534,8 +23863,8 @@ var init_recheck = __esm({
23534
23863
  });
23535
23864
 
23536
23865
  // ../../packages/canonical/src/index.ts
23537
- var src_exports2 = {};
23538
- __export(src_exports2, {
23866
+ var src_exports3 = {};
23867
+ __export(src_exports3, {
23539
23868
  detectViolations: () => detectViolations,
23540
23869
  hashIdentifier: () => hashIdentifier,
23541
23870
  recheck: () => recheck,
@@ -24325,6 +24654,47 @@ function mergeProblemsByEmbedding(store, opts) {
24325
24654
  });
24326
24655
  return report;
24327
24656
  }
24657
+ function bindCanonicalNeighbors(store, opts) {
24658
+ const k = opts.k ?? 3;
24659
+ const live = (n) => n.attrs["mergedInto"] === void 0;
24660
+ const problems = store.findNodesByLabel("Problem").filter((p) => p.embedding.length > 0 && live(p));
24661
+ const patterns = store.findNodesByLabel("Pattern").filter((p) => p.embedding.length > 0);
24662
+ const candidates = [...problems, ...patterns];
24663
+ let bound = 0;
24664
+ for (const p of problems) {
24665
+ const existing = new Set(
24666
+ store.outEdges(p.id, ["MATCHES", "INSTANCE_OF"]).map((e) => e.to)
24667
+ );
24668
+ if (existing.size >= k) continue;
24669
+ const ranked = candidates.filter(
24670
+ (c) => c.id !== p.id && !existing.has(c.id) && c.embedding.length === p.embedding.length && (c.attrs["embeddingVersion"] ?? "") === (p.attrs["embeddingVersion"] ?? "")
24671
+ ).map((c) => ({ c, s: cosine(p.embedding, c.embedding) })).filter((x) => x.s >= CANONICAL_BIND_MIN && x.s < NEMORI_DEDUP_COSINE).sort((a, b) => b.s - a.s);
24672
+ const picked = [];
24673
+ for (const cand of ranked) {
24674
+ if (picked.length + existing.size >= k) break;
24675
+ if (picked.some((q) => cosine(q.c.embedding, cand.c.embedding) >= NEMORI_DEDUP_COSINE)) continue;
24676
+ picked.push(cand);
24677
+ }
24678
+ for (const { c, s } of picked) {
24679
+ const type = c.label === "Pattern" ? "INSTANCE_OF" : "MATCHES";
24680
+ store.mergeEdge({
24681
+ id: `edge_${digest({ from: p.id, type, to: c.id, k: "canonBind" })}`.slice(0, 24),
24682
+ from: p.id,
24683
+ to: c.id,
24684
+ type,
24685
+ confidence: 0.3,
24686
+ extractionSource: "daemon-extracted",
24687
+ createdAt: opts.ts,
24688
+ lastSeenAt: opts.ts,
24689
+ navSuccesses: 0,
24690
+ navFailures: 0,
24691
+ attrs: { provisional: true, machineProposed: true, cosine: Math.round(s * 100) / 100 }
24692
+ });
24693
+ bound++;
24694
+ }
24695
+ }
24696
+ return { bound, scanned: problems.length };
24697
+ }
24328
24698
  async function ingestErrorSignature(opts, sig, commandSig) {
24329
24699
  const candidateId = identityId({ kind: "RuntimeProblem", error: sig });
24330
24700
  const now = Date.now();
@@ -25043,7 +25413,7 @@ function reconcileDiagnostics(store, workspaceId2, relPath, diags, t, command) {
25043
25413
  }
25044
25414
  return { opened, resolved };
25045
25415
  }
25046
- var GENERALIZER_CURSOR, GENERALIZER_KINDS, GENERALIZER_BATCH, ANCHOR_LABELS, DIAG_SEVERITY_ERROR;
25416
+ var GENERALIZER_CURSOR, GENERALIZER_KINDS, GENERALIZER_BATCH, CANONICAL_BIND_MIN, ANCHOR_LABELS, DIAG_SEVERITY_ERROR;
25047
25417
  var init_generalizer = __esm({
25048
25418
  "../../packages/generalizer/src/generalizer.ts"() {
25049
25419
  "use strict";
@@ -25063,6 +25433,7 @@ var init_generalizer = __esm({
25063
25433
  "harness.error"
25064
25434
  ];
25065
25435
  GENERALIZER_BATCH = 500;
25436
+ CANONICAL_BIND_MIN = 0.78;
25066
25437
  ANCHOR_LABELS = ["Function", "Method", "Class"];
25067
25438
  DIAG_SEVERITY_ERROR = 1;
25068
25439
  }
@@ -25439,6 +25810,21 @@ function scoreCandidate(candidate, ctx = {}, weights) {
25439
25810
  weights
25440
25811
  );
25441
25812
  }
25813
+ function rankByRelevance(store, seedId, candidateIds, opts = {}) {
25814
+ const seed = store.getNode(seedId);
25815
+ const ctx = {
25816
+ ...seed && seed.embedding.length > 0 ? { seedEmbedding: seed.embedding, seedEmbeddingVersion: seed.attrs["embeddingVersion"] } : {},
25817
+ ...opts.hops !== void 0 ? { hops: opts.hops } : {}
25818
+ };
25819
+ const nodes = candidateIds.map((id) => store.getNode(id)).filter((n) => n != null);
25820
+ const maxPr = Math.max(1e-9, ...nodes.map((n) => n.pageRank));
25821
+ const weights = { centralityScale: maxPr, ...opts.weights };
25822
+ const now = store.currentIngestSeq();
25823
+ return nodes.map((node2) => {
25824
+ const r = scoreCandidate(node2, { ...ctx, decay: nodeFreshness(node2, now) }, weights);
25825
+ return { id: node2.id, score: r.score, components: r.components, node: node2 };
25826
+ }).sort((a, b) => b.score - a.score);
25827
+ }
25442
25828
  function localBurst(store, seedId, opts = {}) {
25443
25829
  const maxHops = opts.maxHops ?? 2;
25444
25830
  const limit = opts.limit ?? 20;
@@ -25483,6 +25869,36 @@ var init_relevance_rank = __esm({
25483
25869
  });
25484
25870
 
25485
25871
  // ../../packages/generalizer/src/index.ts
25872
+ var src_exports4 = {};
25873
+ __export(src_exports4, {
25874
+ anchorByLine: () => anchorByLine,
25875
+ anchorCandidates: () => anchorCandidates,
25876
+ anchorProblemToCode: () => anchorProblemToCode,
25877
+ annotateResolution: () => annotateResolution,
25878
+ attributeRootCause: () => attributeRootCause,
25879
+ bindCanonicalNeighbors: () => bindCanonicalNeighbors,
25880
+ closeProblem: () => closeProblem,
25881
+ codeAnchorProjection: () => codeAnchorProjection,
25882
+ commandSignature: () => commandSignature,
25883
+ embedCodeNodes: () => embedCodeNodes,
25884
+ embedSemanticNodes: () => embedSemanticNodes,
25885
+ evaluateForReview: () => evaluateForReview,
25886
+ extractDiagnostics: () => extractDiagnostics,
25887
+ extractErrorSignature: () => extractErrorSignature,
25888
+ ingestErrorSignature: () => ingestErrorSignature,
25889
+ localBurst: () => localBurst,
25890
+ mergeProblemsByEmbedding: () => mergeProblemsByEmbedding,
25891
+ nemoriDecide: () => nemoriDecide,
25892
+ promoteMotifs: () => promoteMotifs,
25893
+ rankByRelevance: () => rankByRelevance,
25894
+ rankOpenProblemNeighbors: () => rankOpenProblemNeighbors,
25895
+ reconcileDiagnostics: () => reconcileDiagnostics,
25896
+ resolveProblem: () => resolveProblem,
25897
+ runGeneralizer: () => runGeneralizer,
25898
+ runNightlyPipeline: () => runNightlyPipeline,
25899
+ scoreCandidate: () => scoreCandidate,
25900
+ selectAnchorFrame: () => selectAnchorFrame
25901
+ });
25486
25902
  var init_src10 = __esm({
25487
25903
  "../../packages/generalizer/src/index.ts"() {
25488
25904
  "use strict";
@@ -25857,7 +26273,7 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
25857
26273
  continuations: []
25858
26274
  };
25859
26275
  }
25860
- const { defaultProviders: defaultProviders2 } = await Promise.resolve().then(() => (init_src11(), src_exports3));
26276
+ const { defaultProviders: defaultProviders2 } = await Promise.resolve().then(() => (init_src11(), src_exports5));
25861
26277
  const providers = defaultProviders2();
25862
26278
  for (const p of providers) if (p.preload) await p.preload();
25863
26279
  const before = /* @__PURE__ */ new Map();
@@ -34006,8 +34422,8 @@ var init_csharp_treesitter = __esm({
34006
34422
  });
34007
34423
 
34008
34424
  // ../../packages/indexer/src/index.ts
34009
- var src_exports3 = {};
34010
- __export(src_exports3, {
34425
+ var src_exports5 = {};
34426
+ __export(src_exports5, {
34011
34427
  DRIFT_FORK_RATIO: () => DRIFT_FORK_RATIO,
34012
34428
  TreeSitterCSharpProvider: () => TreeSitterCSharpProvider,
34013
34429
  TreeSitterCppProvider: () => TreeSitterCppProvider,
@@ -39748,6 +40164,10 @@ var FIX_PREFIX = /^\s*fix:(?:#([a-z][\w-]{0,63}))?\s*/i;
39748
40164
  var CONSTRAINT_RE = /\(\s*constraint:\s*([^()\n]{8,}?)\s*\)/gi;
39749
40165
  var CAUSE_PREFIX = /^\s*cause:(?:#([a-z][\w-]{0,63}))?\s*/i;
39750
40166
  var ATTEMPT_RE = /\(\s*(tried|failed):(?:#([a-z][\w-]{0,63}))?\s*((?:[^()\n]|\([^()\n]*\)){8,}?)\s*\)/gi;
40167
+ var AIDS_PREFIX = /^\s*aids:(?:#([a-z][\w-]{0,63}))?\s*/i;
40168
+ var INSTANCE_PREFIX = /^\s*instance:\s*/i;
40169
+ var PATTERN_RE = /\(\s*pattern:\s*([^()\n]{3,}?)\s*\)/gi;
40170
+ var PATTERN_TEXT_MAX = 120;
39751
40171
  var CAUSE_TEXT_MIN = 8;
39752
40172
  var CAUSE_TEXT_MAX = 200;
39753
40173
  var FLAG_RE = /\[([!?])(?:#([a-z][\w-]{0,63})\s+)?\s*([^\]\n]{8,}?)\s*(?:@\s*([^\s\]]+?)(?::(\d+))?\s*)?\]/g;
@@ -39783,10 +40203,32 @@ function parseInlineTags(text) {
39783
40203
  let g;
39784
40204
  while ((g = CITE_GROUP_RE.exec(sentence)) !== null) {
39785
40205
  let content = g[1];
40206
+ if (/^\s*pattern:/i.test(content)) continue;
39786
40207
  const fixM = FIX_PREFIX.exec(content);
39787
40208
  const causeM = fixM ? null : CAUSE_PREFIX.exec(content);
40209
+ const aidsM = fixM || causeM ? null : AIDS_PREFIX.exec(content);
40210
+ const instM = fixM || causeM || aidsM ? null : INSTANCE_PREFIX.exec(content);
39788
40211
  const isFix = fixM !== null;
39789
40212
  const isCause = causeM !== null;
40213
+ if (aidsM || instM) {
40214
+ const body2 = content.replace(aidsM ? AIDS_PREFIX : INSTANCE_PREFIX, "");
40215
+ const handles = [];
40216
+ HANDLE_RE.lastIndex = 0;
40217
+ let hh;
40218
+ while ((hh = HANDLE_RE.exec(body2)) !== null) {
40219
+ const handle2 = hh[1] ?? hh[2];
40220
+ if (handle2 && !handles.includes(handle2)) handles.push(handle2);
40221
+ }
40222
+ if (handles.length > 0) {
40223
+ out2.push({
40224
+ kind: aidsM ? "transfer" : "instance",
40225
+ handles,
40226
+ sentence: sfield,
40227
+ ...aidsM?.[1] ? { threadId: aidsM[1] } : {}
40228
+ });
40229
+ }
40230
+ continue;
40231
+ }
39790
40232
  const verbThread = fixM?.[1] ?? causeM?.[1] ?? void 0;
39791
40233
  if (isFix) content = content.replace(FIX_PREFIX, "");
39792
40234
  else if (isCause) content = content.replace(CAUSE_PREFIX, "");
@@ -39872,6 +40314,23 @@ function parseInlineTags(text) {
39872
40314
  });
39873
40315
  }
39874
40316
  }
40317
+ PATTERN_RE.lastIndex = 0;
40318
+ let pm;
40319
+ while ((pm = PATTERN_RE.exec(sentence)) !== null) {
40320
+ const body2 = pm[1].trim();
40321
+ HANDLE_RE.lastIndex = 0;
40322
+ const ph = HANDLE_RE.exec(body2);
40323
+ const handle2 = ph ? ph[1] ?? ph[2] : void 0;
40324
+ if (handle2) {
40325
+ out2.push({ kind: "pattern", handle: handle2, sentence: sfield });
40326
+ } else {
40327
+ const raw3 = body2.replace(/\s+/g, " ").trim();
40328
+ if (raw3.length >= 3) {
40329
+ const patternText = raw3.length > PATTERN_TEXT_MAX ? `${raw3.slice(0, PATTERN_TEXT_MAX - 1).trimEnd()}\u2026` : raw3;
40330
+ out2.push({ kind: "pattern", patternText, sentence: sfield });
40331
+ }
40332
+ }
40333
+ }
39875
40334
  CONSTRAINT_RE.lastIndex = 0;
39876
40335
  let c;
39877
40336
  while ((c = CONSTRAINT_RE.exec(sentence)) !== null) {
@@ -39992,7 +40451,7 @@ function harvestInlineTags(store, text, opts) {
39992
40451
  const source = opts.sourceId ? store.getNode(opts.sourceId) : null;
39993
40452
  const mintPriors = opts.mintPriors ?? true;
39994
40453
  const touched = opts.sessionTouchedIds ?? /* @__PURE__ */ new Set();
39995
- const plan = { priorEdges: 0, problems: [], fixes: [], triages: [], attempts: [], unresolvedFixes: [] };
40454
+ const plan = { priorEdges: 0, problems: [], fixes: [], triages: [], attempts: [], unresolvedFixes: [], transfers: [], instances: [], patterns: [] };
39996
40455
  const tags = parseInlineTags(text);
39997
40456
  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);
39998
40457
  const bindSymptom = (seq, threadId) => {
@@ -40058,6 +40517,50 @@ function harvestInlineTags(store, text, opts) {
40058
40517
  const causeId = `dcause_${digest({ statement: tag.causeText })}`.slice(0, 56);
40059
40518
  plan.triages.push({ causeId, causeDescription: tag.causeText, ...bound });
40060
40519
  }
40520
+ } else if (tag.kind === "transfer") {
40521
+ const targetIds = [];
40522
+ for (const h of tag.handles ?? []) {
40523
+ const id = resolveHandle(store, h, opts.handleMap);
40524
+ if (id && !targetIds.includes(id)) targetIds.push(id);
40525
+ }
40526
+ if (targetIds.length > 0) {
40527
+ const b = bindSymptom(tag.seq, tag.threadId);
40528
+ plan.transfers.push({
40529
+ targetIds,
40530
+ ...tag.threadId ? { threadId: tag.threadId } : {},
40531
+ ...b.statement ? { boundStatement: b.statement } : {}
40532
+ });
40533
+ }
40534
+ } else if (tag.kind === "instance") {
40535
+ const targetIds = [];
40536
+ for (const h of tag.handles ?? []) {
40537
+ const id = resolveHandle(store, h, opts.handleMap);
40538
+ if (id && !targetIds.includes(id)) targetIds.push(id);
40539
+ }
40540
+ if (targetIds.length > 0) {
40541
+ const b = bindSymptom(tag.seq, tag.threadId);
40542
+ plan.instances.push({
40543
+ targetIds,
40544
+ ...b.statement ? { boundStatement: b.statement } : {},
40545
+ ...b.problemId ? { problemId: b.problemId } : {},
40546
+ ...tag.threadId ? { threadId: tag.threadId } : {},
40547
+ evidence: b.evidence
40548
+ });
40549
+ }
40550
+ } else if (tag.kind === "pattern") {
40551
+ const b = bindSymptom(tag.seq, tag.threadId);
40552
+ const bound = {
40553
+ ...b.statement ? { boundStatement: b.statement } : {},
40554
+ ...b.problemId ? { problemId: b.problemId } : {},
40555
+ ...tag.threadId ? { threadId: tag.threadId } : {},
40556
+ evidence: b.evidence
40557
+ };
40558
+ if (tag.handle) {
40559
+ const patternId = resolveHandle(store, tag.handle, opts.handleMap);
40560
+ if (patternId) plan.patterns.push({ patternId, ...bound });
40561
+ } else if (tag.patternText) {
40562
+ plan.patterns.push({ patternText: tag.patternText, ...bound });
40563
+ }
40061
40564
  } else if (tag.kind === "attempt" || tag.kind === "failure") {
40062
40565
  const b = bindSymptom(tag.seq, tag.threadId);
40063
40566
  const outcome = tag.kind === "attempt" ? "tried" : "failed";
@@ -41375,7 +41878,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
41375
41878
  }
41376
41879
 
41377
41880
  // src/engine.ts
41378
- var DAEMON_VERSION = true ? "2.0.0-dev.31" : "2.0.0-alpha.0";
41881
+ var DAEMON_VERSION = true ? "2.0.0-dev.33" : "2.0.0-alpha.0";
41379
41882
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
41380
41883
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
41381
41884
  var GIT_OP_MUTE_MS = 4e3;
@@ -41888,6 +42391,7 @@ function createWorkspaceEngine(opts) {
41888
42391
  let abstracted = 0;
41889
42392
  let triaged = 0;
41890
42393
  let priorEdges = 0;
42394
+ let linked = 0;
41891
42395
  const t = Date.now();
41892
42396
  let processedTurns = 0;
41893
42397
  const elicit = isEdgeElicitationEnabled();
@@ -42118,6 +42622,65 @@ function createWorkspaceEngine(opts) {
42118
42622
  console.warn("[errata] attempt journal failed:", err2);
42119
42623
  }
42120
42624
  }
42625
+ const bindPid = (tag) => {
42626
+ const pid = tag.problemId ?? (tag.threadId ? threads.get(tag.threadId) : void 0) ?? (tag.boundStatement ? designProblemId(tag.boundStatement) : void 0) ?? inScopeProblemId ?? sessionLastProblem.get(sessionId);
42627
+ return pid && store.getNode(pid) ? pid : void 0;
42628
+ };
42629
+ const mintCiteEdge = (from, to, type, confidence, extraAttrs) => {
42630
+ store.mergeEdge({
42631
+ id: `edge_${digest({ from, type, to })}`.slice(0, 24),
42632
+ from,
42633
+ to,
42634
+ type,
42635
+ confidence,
42636
+ extractionSource: "agent-observed",
42637
+ createdAt: t,
42638
+ lastSeenAt: t,
42639
+ navSuccesses: 0,
42640
+ navFailures: 0,
42641
+ attrs: { provisional: true, session: sessionId, ...extraAttrs }
42642
+ });
42643
+ linked++;
42644
+ };
42645
+ for (const pt of plan.patterns) {
42646
+ const pid = bindPid(pt);
42647
+ if (!pid) continue;
42648
+ let patternId = pt.patternId;
42649
+ if (patternId) {
42650
+ const node2 = store.getNode(patternId);
42651
+ if (!node2 || node2.label !== "Pattern") continue;
42652
+ } else if (pt.patternText) {
42653
+ patternId = mintPatternNode(store, pt.patternText, t);
42654
+ }
42655
+ if (!patternId || patternId === pid) continue;
42656
+ mintCiteEdge(pid, patternId, "INSTANCE_OF", pt.evidence === "witnessed" ? 0.4 : 0.3, { patternCite: true, evidence: pt.evidence });
42657
+ }
42658
+ for (const inst of plan.instances) {
42659
+ const pid = bindPid(inst);
42660
+ if (!pid) continue;
42661
+ for (const targetId of inst.targetIds) {
42662
+ if (targetId === pid) continue;
42663
+ const target = store.getNode(targetId);
42664
+ if (!target) continue;
42665
+ const fallback = typePriorEdge("Problem", target.label);
42666
+ const type = target.label === "Pattern" ? "INSTANCE_OF" : target.label === "Problem" ? "MATCHES" : fallback === "SUPERSEDES" ? "RELATES_TO" : fallback;
42667
+ mintCiteEdge(pid, targetId, type, inst.evidence === "witnessed" ? 0.4 : 0.3, { instanceCite: true, evidence: inst.evidence });
42668
+ }
42669
+ }
42670
+ for (const tf of plan.transfers) {
42671
+ const pid = bindPid(tf);
42672
+ const solId = pid ? solutionForProblem(store, pid) : void 0;
42673
+ if (!solId) {
42674
+ console.warn("[errata] aids tag dropped: no solution in scope to hypothesize from \u2014 state it beside its (fix:\u2026)");
42675
+ continue;
42676
+ }
42677
+ for (const targetId of tf.targetIds) {
42678
+ if (targetId === solId) continue;
42679
+ const target = store.getNode(targetId);
42680
+ if (!target || target.label !== "Problem") continue;
42681
+ mintCiteEdge(solId, targetId, "MAY_RESOLVE", 0.3, { transfer: true, hypothesis: true });
42682
+ }
42683
+ }
42121
42684
  } catch (err2) {
42122
42685
  console.warn("[errata] inline-tag harvest failed:", err2);
42123
42686
  }
@@ -42126,6 +42689,10 @@ function createWorkspaceEngine(opts) {
42126
42689
  console.log(`[errata] edge-elicitation: +${priorEdges} soft prior-tag edge(s)`);
42127
42690
  contextDirty = true;
42128
42691
  }
42692
+ if (linked > 0) {
42693
+ console.log(`[errata] canonical-bind: +${linked} abstraction link(s) (pattern/instance/aids)`);
42694
+ contextDirty = true;
42695
+ }
42129
42696
  if (minted > 0 || resolved > 0) {
42130
42697
  console.log(
42131
42698
  `[errata] design: +${minted} flagged, ${resolved} resolved from the conversation`
@@ -42352,6 +42919,10 @@ function createWorkspaceEngine(opts) {
42352
42919
  if (e.merged > 0) {
42353
42920
  console.log(`[errata] dedup: merged ${e.merged} paraphrased problem(s) by embedding across ${e.clusters} cluster(s)`);
42354
42921
  }
42922
+ const cb = bindCanonicalNeighbors(store, { ts: Date.now() });
42923
+ if (cb.bound > 0) {
42924
+ console.log(`[errata] canonical-bind: +${cb.bound} machine-proposed link(s) across ${cb.scanned} problem(s)`);
42925
+ }
42355
42926
  refreshContextNow();
42356
42927
  }
42357
42928
  return { embedded: sem.embedded };
@@ -42388,6 +42959,10 @@ function createWorkspaceEngine(opts) {
42388
42959
  console.log(`[errata] dedup: merged ${e.merged} paraphrased problem(s) by embedding across ${e.clusters} cluster(s)`);
42389
42960
  refreshContextNow();
42390
42961
  }
42962
+ const cb = bindCanonicalNeighbors(store, { ts: Date.now() });
42963
+ if (cb.bound > 0) {
42964
+ console.log(`[errata] canonical-bind: +${cb.bound} machine-proposed link(s) across ${cb.scanned} problem(s)`);
42965
+ }
42391
42966
  } catch (err2) {
42392
42967
  console.warn("[errata] embedding problem dedup failed:", err2);
42393
42968
  }
@@ -42494,6 +43069,7 @@ async function startDaemon(opts) {
42494
43069
  merged.accessToken = null;
42495
43070
  merged.refreshToken = null;
42496
43071
  merged.tokenEndpoint = null;
43072
+ merged.oauthClientId = null;
42497
43073
  }
42498
43074
  const cloud = authedCloudClient(merged);
42499
43075
  let webUiUrl = "";
@@ -43258,6 +43834,7 @@ async function startMultiDaemon(opts = {}) {
43258
43834
  initialCfg.accessToken = null;
43259
43835
  initialCfg.refreshToken = null;
43260
43836
  initialCfg.tokenEndpoint = null;
43837
+ initialCfg.oauthClientId = null;
43261
43838
  }
43262
43839
  const cloud = authedCloudClient(initialCfg, { timeoutMs: CLOUD_TIMEOUT_MS });
43263
43840
  const cloudNow = () => {
@@ -43269,6 +43846,7 @@ async function startMultiDaemon(opts = {}) {
43269
43846
  current.accessToken = null;
43270
43847
  current.refreshToken = null;
43271
43848
  current.tokenEndpoint = null;
43849
+ current.oauthClientId = null;
43272
43850
  }
43273
43851
  return authedCloudClient(current, { timeoutMs: CLOUD_TIMEOUT_MS });
43274
43852
  };
@@ -43881,6 +44459,7 @@ init_cloud_endpoint_policy();
43881
44459
  init_src6();
43882
44460
  init_cloud_auth();
43883
44461
  import { createServer } from "node:http";
44462
+ var DEFAULT_OAUTH_SCOPE = "openid profile graph:read graph:write mcp:tools";
43884
44463
  var strip = (u) => u.replace(/\/+$/, "");
43885
44464
  async function discoverEndpoints(cloudUrl, fetchFn = fetch) {
43886
44465
  let consoleUrl = cloudUrl;
@@ -43897,7 +44476,11 @@ async function discoverEndpoints(cloudUrl, fetchFn = fetch) {
43897
44476
  if (asm.ok) {
43898
44477
  const j = await asm.json();
43899
44478
  if (j.authorization_endpoint && j.token_endpoint) {
43900
- return { authorizationEndpoint: j.authorization_endpoint, tokenEndpoint: j.token_endpoint };
44479
+ return {
44480
+ authorizationEndpoint: j.authorization_endpoint,
44481
+ tokenEndpoint: j.token_endpoint,
44482
+ ...j.registration_endpoint ? { registrationEndpoint: j.registration_endpoint } : {}
44483
+ };
43901
44484
  }
43902
44485
  }
43903
44486
  } catch {
@@ -43924,8 +44507,8 @@ async function loginOAuthLoopback(opts) {
43924
44507
  const endpoints = await discoverEndpoints(opts.cloudUrl, fetchFn);
43925
44508
  const pkce = generatePkce();
43926
44509
  const state = randomState();
43927
- const clientId = oauthClientId();
43928
- const { code, redirectUri } = await new Promise(
44510
+ const scope = opts.scope ?? DEFAULT_OAUTH_SCOPE;
44511
+ const { code, redirectUri, clientId } = await new Promise(
43929
44512
  (resolve5, reject) => {
43930
44513
  const server = createServer((req, res) => {
43931
44514
  const u = new URL(req.url ?? "/", "http://127.0.0.1");
@@ -43949,24 +44532,40 @@ async function loginOAuthLoopback(opts) {
43949
44532
  res.writeHead(200, { "content-type": "text/html" });
43950
44533
  res.end("<html><body>inErrata: you're logged in. You can close this tab.</body></html>");
43951
44534
  server.close();
43952
- resolve5({ code: code2, redirectUri: `http://127.0.0.1:${port}/callback` });
44535
+ resolve5({ code: code2, redirectUri: `http://127.0.0.1:${port}/callback`, clientId: activeClientId });
43953
44536
  });
44537
+ let activeClientId = oauthClientId();
43954
44538
  server.on("error", reject);
43955
44539
  server.listen(0, "127.0.0.1", () => {
43956
- const addr2 = server.address();
43957
- const port = typeof addr2 === "object" && addr2 ? addr2.port : 0;
43958
- const redirectUri2 = `http://127.0.0.1:${port}/callback`;
43959
- const url2 = buildAuthorizeUrl(endpoints.authorizationEndpoint, {
43960
- clientId,
43961
- redirectUri: redirectUri2,
43962
- scope: opts.scope ?? "openid profile",
43963
- state,
43964
- challenge: pkce.challenge,
43965
- method: pkce.method
43966
- });
43967
- if (opts.open) opts.open(url2);
43968
- else console.log(`approve this login in your browser:
44540
+ void (async () => {
44541
+ try {
44542
+ const addr2 = server.address();
44543
+ const port = typeof addr2 === "object" && addr2 ? addr2.port : 0;
44544
+ const redirectUri2 = `http://127.0.0.1:${port}/callback`;
44545
+ if (endpoints.registrationEndpoint) {
44546
+ const registered = await registerOAuthClient(fetchFn, endpoints.registrationEndpoint, {
44547
+ redirectUri: redirectUri2,
44548
+ scope,
44549
+ clientName: "errata daemon"
44550
+ });
44551
+ activeClientId = registered.clientId;
44552
+ }
44553
+ const url2 = buildAuthorizeUrl(endpoints.authorizationEndpoint, {
44554
+ clientId: activeClientId,
44555
+ redirectUri: redirectUri2,
44556
+ scope,
44557
+ state,
44558
+ challenge: pkce.challenge,
44559
+ method: pkce.method
44560
+ });
44561
+ if (opts.open) opts.open(url2);
44562
+ else console.log(`approve this login in your browser:
43969
44563
  ${url2}`);
44564
+ } catch (err2) {
44565
+ server.close();
44566
+ reject(err2);
44567
+ }
44568
+ })();
43970
44569
  });
43971
44570
  if (opts.timeoutMs) {
43972
44571
  setTimeout(() => {
@@ -43982,7 +44581,7 @@ async function loginOAuthLoopback(opts) {
43982
44581
  redirectUri,
43983
44582
  clientId
43984
44583
  });
43985
- return { tokens, tokenEndpoint: endpoints.tokenEndpoint };
44584
+ return { tokens, tokenEndpoint: endpoints.tokenEndpoint, clientId };
43986
44585
  }
43987
44586
 
43988
44587
  // src/update.ts
@@ -44178,6 +44777,8 @@ async function main() {
44178
44777
  return cmdDash(rest);
44179
44778
  case "notify-test":
44180
44779
  return cmdNotifyTest();
44780
+ case "backfill-anchors":
44781
+ return cmdBackfillAnchors();
44181
44782
  case "help":
44182
44783
  case "--help":
44183
44784
  case "-h":
@@ -44215,6 +44816,9 @@ Commands:
44215
44816
  --no-embed skips the code-node embedding pass
44216
44817
  (~minutes on first run; incremental after).
44217
44818
  review Print the pending review queue
44819
+ backfill-anchors Retro-anchor resolved problems whose fix location lives only
44820
+ in prose ("addressed by an edit to \u2026") + run the canonical
44821
+ binder over the embedded backlog. Idempotent.
44218
44822
  locate <path> Print the File node + immediate symbols for a path
44219
44823
  neighbors <id> Walk the graph from a node (BFS depth 2)
44220
44824
  Flags: --depth N (1..5)
@@ -44569,6 +45173,7 @@ async function applyToken(cfg, token) {
44569
45173
  cfg.accessToken = null;
44570
45174
  cfg.refreshToken = null;
44571
45175
  cfg.tokenEndpoint = null;
45176
+ cfg.oauthClientId = null;
44572
45177
  cfg.userId = me.agentId;
44573
45178
  cfg.email = me.handle;
44574
45179
  saveConfig(cfg);
@@ -44613,6 +45218,7 @@ async function cmdLoginOAuth(cfg) {
44613
45218
  cfg.accessToken = result.tokens.accessToken;
44614
45219
  cfg.refreshToken = result.tokens.refreshToken ?? null;
44615
45220
  cfg.tokenEndpoint = result.tokenEndpoint;
45221
+ cfg.oauthClientId = result.clientId;
44616
45222
  cfg.apiKey = null;
44617
45223
  saveConfig(cfg);
44618
45224
  try {
@@ -44684,6 +45290,7 @@ async function cmdLogin() {
44684
45290
  cfg.accessToken = null;
44685
45291
  cfg.refreshToken = null;
44686
45292
  cfg.tokenEndpoint = null;
45293
+ cfg.oauthClientId = null;
44687
45294
  cfg.userId = poll.agentId ?? null;
44688
45295
  cfg.email = poll.handle ?? handle2;
44689
45296
  saveConfig(cfg);
@@ -44711,6 +45318,7 @@ async function cmdLogout() {
44711
45318
  cfg.accessToken = null;
44712
45319
  cfg.refreshToken = null;
44713
45320
  cfg.tokenEndpoint = null;
45321
+ cfg.oauthClientId = null;
44714
45322
  cfg.userId = null;
44715
45323
  cfg.email = null;
44716
45324
  saveConfig(cfg);
@@ -44763,7 +45371,7 @@ async function cmdLocate(relPath) {
44763
45371
  process.exit(2);
44764
45372
  }
44765
45373
  await ensureProfile();
44766
- const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports));
45374
+ const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
44767
45375
  const { workspacePaths: workspacePaths2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
44768
45376
  const paths = workspacePaths2(ROOT);
44769
45377
  const store = openGraphStore2({ path: paths.castalia });
@@ -44815,7 +45423,7 @@ async function cmdNeighbors(args2) {
44815
45423
  const depthIdx = args2.indexOf("--depth");
44816
45424
  const depth = depthIdx >= 0 && args2[depthIdx + 1] ? Math.max(1, Math.min(5, Number(args2[depthIdx + 1]))) : 2;
44817
45425
  await ensureProfile();
44818
- const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports));
45426
+ const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
44819
45427
  const { workspacePaths: workspacePaths2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
44820
45428
  const paths = workspacePaths2(ROOT);
44821
45429
  const store = openGraphStore2({ path: paths.castalia });
@@ -44863,7 +45471,7 @@ async function cmdNeighbors(args2) {
44863
45471
  }
44864
45472
  async function cmdTodos() {
44865
45473
  await ensureProfile();
44866
- const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports));
45474
+ const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
44867
45475
  const { workspacePaths: workspacePaths2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
44868
45476
  const paths = workspacePaths2(ROOT);
44869
45477
  const store = openGraphStore2({ path: paths.castalia });
@@ -44899,9 +45507,86 @@ async function cmdTodos() {
44899
45507
  store.close();
44900
45508
  }
44901
45509
  }
45510
+ async function cmdBackfillAnchors() {
45511
+ const profile = loadProfile(ROOT);
45512
+ await ensureProfile();
45513
+ const { anchorSolutionToDiff: anchorSolutionToDiff2, anchorProblemToDiff: anchorProblemToDiff2, deriveContextFromAnchors: deriveContextFromAnchors2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
45514
+ const { bindCanonicalNeighbors: bindCanonicalNeighbors2 } = await Promise.resolve().then(() => (init_src10(), src_exports4));
45515
+ const { digest: digest2 } = await Promise.resolve().then(() => (init_src(), src_exports));
45516
+ await withStore(async (store) => {
45517
+ const ts = Date.now();
45518
+ const wsId = profile.id;
45519
+ const PROSE = /^addressed by an edit to (.+)$/;
45520
+ let anchored = 0;
45521
+ let skipped = 0;
45522
+ for (const sol of store.findNodesByLabel("Solution")) {
45523
+ const m = PROSE.exec(sol.description.trim());
45524
+ if (!m) continue;
45525
+ if (store.outEdges(sol.id, ["ANCHORED_AT"]).length > 0) {
45526
+ skipped++;
45527
+ continue;
45528
+ }
45529
+ const target = m[1].trim();
45530
+ const problemIds = store.inEdges(sol.id, ["SOLVED_BY"]).map((e) => e.from).filter((id) => store.getNode(id)?.label === "Problem");
45531
+ const isPath = target.includes("/") || target.includes("\\");
45532
+ if (isPath) {
45533
+ anchorSolutionToDiff2(store, sol.id, [target], wsId, ts);
45534
+ for (const pid of problemIds) {
45535
+ anchorProblemToDiff2(store, pid, [target], wsId, ts);
45536
+ deriveContextFromAnchors2(store, pid, ts);
45537
+ }
45538
+ } else {
45539
+ const bare = target.includes(".") ? target.slice(target.lastIndexOf(".") + 1) : target;
45540
+ let sym = null;
45541
+ outer: for (const label of ["Function", "Method", "Class"]) {
45542
+ for (const n of store.findNodesByLabel(label)) {
45543
+ if (n.attrs["workspaceId"] && n.attrs["workspaceId"] !== wsId) continue;
45544
+ const qname = String(n.attrs["qname"] ?? "");
45545
+ if (qname === target || n.description === target) {
45546
+ sym = n;
45547
+ break outer;
45548
+ }
45549
+ if (!sym && (qname.endsWith(`.${bare}`) || n.description === bare)) sym = n;
45550
+ }
45551
+ }
45552
+ if (!sym) continue;
45553
+ for (const from of [sol.id, ...problemIds]) {
45554
+ store.mergeEdge({
45555
+ id: `edge_${digest2({ from, type: "ANCHORED_AT", to: sym.id })}`.slice(0, 24),
45556
+ from,
45557
+ to: sym.id,
45558
+ type: "ANCHORED_AT",
45559
+ confidence: 0.6,
45560
+ extractionSource: "daemon-extracted",
45561
+ createdAt: ts,
45562
+ lastSeenAt: ts,
45563
+ navSuccesses: 0,
45564
+ navFailures: 0,
45565
+ attrs: { provisional: true, backfill: true }
45566
+ });
45567
+ }
45568
+ for (const pid of problemIds) deriveContextFromAnchors2(store, pid, ts);
45569
+ }
45570
+ if (store.outEdges(sol.id, ["ANCHORED_AT"]).length > 0) {
45571
+ anchored++;
45572
+ store.updateNode(sol.id, {
45573
+ attrs: {
45574
+ ...sol.attrs,
45575
+ ...isPath ? { resolvedRelPath: target } : { resolvedSymbols: [target] }
45576
+ },
45577
+ lastUpdatedAt: ts
45578
+ });
45579
+ }
45580
+ }
45581
+ const cb = bindCanonicalNeighbors2(store, { ts });
45582
+ console.log(
45583
+ `backfill: anchored ${anchored} resolution(s) from prose (${skipped} already anchored); canonical-bind: +${cb.bound} machine link(s) across ${cb.scanned} embedded problem(s)`
45584
+ );
45585
+ });
45586
+ }
44902
45587
  async function withStore(fn) {
44903
45588
  await ensureProfile();
44904
- const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports));
45589
+ const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
44905
45590
  const { workspacePaths: workspacePaths2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
44906
45591
  const paths = workspacePaths2(ROOT);
44907
45592
  const store = openGraphStore2({ path: paths.castalia });
@@ -45276,7 +45961,7 @@ async function gatherRepo(store, ws) {
45276
45961
  }
45277
45962
  async function gatherReportData(generatedAt) {
45278
45963
  const { existsSync: existsSync20 } = await import("node:fs");
45279
- const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports));
45964
+ const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
45280
45965
  const cfg = loadConfig();
45281
45966
  const outbound = cfg.consent.sync ? "auto" : "off";
45282
45967
  const repos = [];
@@ -46007,7 +46692,7 @@ async function cmdFeedback(args2) {
46007
46692
  console.error('usage: errata feedback [up|down] "<message>"');
46008
46693
  process.exit(2);
46009
46694
  }
46010
- const { scrub: scrub2 } = await Promise.resolve().then(() => (init_src7(), src_exports2));
46695
+ const { scrub: scrub2 } = await Promise.resolve().then(() => (init_src7(), src_exports3));
46011
46696
  const scrubbed = scrub2(message).text;
46012
46697
  const c = authedCloudClient(cfg);
46013
46698
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.0-dev.31",
3
+ "version": "2.0.0-dev.33",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -25,7 +25,7 @@ function isTestRelPath(relPath) {
25
25
  function isTestScopeQname(qname) {
26
26
  return TEST_SCOPE_RE.test(qname);
27
27
  }
28
- var SEMANTIC_NODE_LABELS, CONTEXT_NODE_LABELS, CODE_NODE_LABELS, ALL_NODE_LABELS, STRUCTURAL_EDGES, CAUSAL_EDGES, RESOLUTION_EDGES, CONCEPTUAL_EDGES, EVIDENCE_EDGES, CODE_EDGES, BRIDGE_EDGES, IDENTITY_EDGES, JUSTIFICATION_EDGES, BELIEF_EDGES, ABSTRACTION_EDGES, DECOMPOSITION_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, PAGERANK_EXCLUSIONS, EDGE_WEIGHT, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, PROBLEM_RESOLUTION, DRIFT_KIND, TEST_PATH_RE, TEST_SCOPE_RE;
28
+ var SEMANTIC_NODE_LABELS, CONTEXT_NODE_LABELS, CODE_NODE_LABELS, ALL_NODE_LABELS, STRUCTURAL_EDGES, CAUSAL_EDGES, RESOLUTION_EDGES, CONCEPTUAL_EDGES, EVIDENCE_EDGES, CODE_EDGES, BRIDGE_EDGES, IDENTITY_EDGES, JUSTIFICATION_EDGES, BELIEF_EDGES, ABSTRACTION_EDGES, DECOMPOSITION_EDGES, TRANSFER_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, PAGERANK_EXCLUSIONS, EDGE_WEIGHT, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, PROBLEM_RESOLUTION, DRIFT_KIND, TEST_PATH_RE, TEST_SCOPE_RE;
29
29
  var init_castalia = __esm({
30
30
  "../../packages/shared/src/castalia.ts"() {
31
31
  "use strict";
@@ -175,6 +175,7 @@ var init_castalia = __esm({
175
175
  BELIEF_EDGES = ["CORROBORATES"];
176
176
  ABSTRACTION_EDGES = ["GENERALIZES", "DERIVED_FROM"];
177
177
  DECOMPOSITION_EDGES = ["SPLIT_INTO"];
178
+ TRANSFER_EDGES = ["MAY_RESOLVE"];
178
179
  TAXONOMY_EDGES = ["IS_A"];
179
180
  TRIAGE_EDGES = ["TRIAGED_BY", "CONFIRMS", "INDICATES", "ROUTES_TO"];
180
181
  GIT_EDGES = ["POINTS_AT", "PARENT", "AUTHORED_BY"];
@@ -189,6 +190,7 @@ var init_castalia = __esm({
189
190
  ...IDENTITY_EDGES,
190
191
  ...JUSTIFICATION_EDGES,
191
192
  ...BELIEF_EDGES,
193
+ ...TRANSFER_EDGES,
192
194
  ...ABSTRACTION_EDGES,
193
195
  ...DECOMPOSITION_EDGES,
194
196
  ...TAXONOMY_EDGES,
@@ -315,6 +317,10 @@ var init_castalia = __esm({
315
317
  INDICATES: 0.4,
316
318
  ROUTES_TO: 1,
317
319
  TRIAGED_BY: 0,
320
+ // Transfer — a witnessed could-aid hypothesis (Solution → Problem). Discounted like
321
+ // INDICATES: real signal, but a candidate must not form a hub; promotion mints the
322
+ // full-weight SOLVED_BY/MITIGATES instead of upgrading this edge.
323
+ MAY_RESOLVE: 0.3,
318
324
  // Git — topology/authorship, weightless (not domain signal-flow)
319
325
  POINTS_AT: 0,
320
326
  PARENT: 0,
@@ -24862,12 +24868,14 @@ function resolveDesignProblems(store2, t) {
24862
24868
  if (!p.id.startsWith("dprob_")) continue;
24863
24869
  if (p.attrs["resolvedAt"]) continue;
24864
24870
  let symName = "";
24871
+ let symRelPath;
24865
24872
  let edited = false;
24866
24873
  for (const e of store2.outEdges(p.id, ["ANCHORED_AT"])) {
24867
24874
  const sym = store2.getNode(e.to);
24868
24875
  if (sym && sym.lastUpdatedAt > p.createdAt) {
24869
24876
  edited = true;
24870
24877
  symName = sym.description;
24878
+ symRelPath = sym.attrs["relPath"] ?? void 0;
24871
24879
  break;
24872
24880
  }
24873
24881
  }
@@ -24877,7 +24885,11 @@ function resolveDesignProblems(store2, t) {
24877
24885
  store2.mergeNode(
24878
24886
  buildNode(solId, "Solution", `addressed by an edit to ${symName}`, t, {
24879
24887
  source: "convo",
24880
- provisional: false
24888
+ provisional: false,
24889
+ // AC-resolution-attrs: the resolving symbol/file as STRUCTURED data, not
24890
+ // just prose — the F2 join key downstream backfills and the viz read.
24891
+ resolvedSymbols: [symName],
24892
+ ...symRelPath ? { resolvedRelPath: symRelPath } : {}
24881
24893
  })
24882
24894
  );
24883
24895
  mergeEdge(store2, p.id, solId, "SOLVED_BY", t);