@inerrata-corporation/errata 2.0.0-dev.69 → 2.0.0-dev.71

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, TRANSFER_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, SOLUTION_STRUCTURE_EDGES, SUSPICION_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";
@@ -172,6 +172,8 @@ var init_castalia = __esm({
172
172
  ABSTRACTION_EDGES = ["GENERALIZES", "DERIVED_FROM"];
173
173
  DECOMPOSITION_EDGES = ["SPLIT_INTO"];
174
174
  TRANSFER_EDGES = ["MAY_RESOLVE"];
175
+ SOLUTION_STRUCTURE_EDGES = ["BUILDS_ON", "SUPERSEDES", "ALTERNATIVE_TO"];
176
+ SUSPICION_EDGES = ["SUSPECTED_LINK"];
175
177
  TAXONOMY_EDGES = ["IS_A"];
176
178
  TRIAGE_EDGES = ["TRIAGED_BY", "CONFIRMS", "INDICATES", "ROUTES_TO"];
177
179
  GIT_EDGES = ["POINTS_AT", "PARENT", "AUTHORED_BY"];
@@ -179,6 +181,8 @@ var init_castalia = __esm({
179
181
  ...STRUCTURAL_EDGES,
180
182
  ...CAUSAL_EDGES,
181
183
  ...RESOLUTION_EDGES,
184
+ ...SOLUTION_STRUCTURE_EDGES,
185
+ ...SUSPICION_EDGES,
182
186
  ...CONCEPTUAL_EDGES,
183
187
  ...EVIDENCE_EDGES,
184
188
  ...CODE_EDGES,
@@ -288,6 +292,15 @@ var init_castalia = __esm({
288
292
  // INDICATES: real signal, but a candidate must not form a hub; promotion mints the
289
293
  // full-weight SOLVED_BY/MITIGATES instead of upgrading this edge.
290
294
  MAY_RESOLVE: 0.3,
295
+ // Solution-structure (SS-structure) — witnessed inter-solution relationships.
296
+ // BUILDS_ON flows (extension → base) so a foundational solution accrues centrality,
297
+ // discounted like MAY_RESOLVE so one witness isn't a hub; SUPERSEDES/ALTERNATIVE_TO
298
+ // are weightless gradients (PageRank-excluded below).
299
+ BUILDS_ON: 0.4,
300
+ SUPERSEDES: 0,
301
+ ALTERNATIVE_TO: 0,
302
+ // Suspicion — a hypothesis, weightless + PageRank-excluded (never flows rank / EIG).
303
+ SUSPECTED_LINK: 0,
291
304
  // Git — topology/authorship, weightless (not domain signal-flow)
292
305
  POINTS_AT: 0,
293
306
  PARENT: 0,
package/errata.mjs CHANGED
@@ -64,7 +64,7 @@ function toCloudAttrs(attrs) {
64
64
  }
65
65
  return rest2;
66
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, EDGE_CONDUCTANCE_OVERRIDES, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, TRUTH_KIND, ABSTRACTION_LEVEL, PROBLEM_RESOLUTION, DRIFT_KIND, TEST_PATH_RE, TEST_SCOPE_RE;
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, SOLUTION_STRUCTURE_EDGES, SUSPICION_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, PAGERANK_EXCLUSIONS, EDGE_WEIGHT, EDGE_CONDUCTANCE_OVERRIDES, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, TRUTH_KIND, ABSTRACTION_LEVEL, PROBLEM_RESOLUTION, DRIFT_KIND, TEST_PATH_RE, TEST_SCOPE_RE;
68
68
  var init_castalia = __esm({
69
69
  "../../packages/shared/src/castalia.ts"() {
70
70
  "use strict";
@@ -222,6 +222,8 @@ var init_castalia = __esm({
222
222
  ABSTRACTION_EDGES = ["GENERALIZES", "DERIVED_FROM"];
223
223
  DECOMPOSITION_EDGES = ["SPLIT_INTO"];
224
224
  TRANSFER_EDGES = ["MAY_RESOLVE"];
225
+ SOLUTION_STRUCTURE_EDGES = ["BUILDS_ON", "SUPERSEDES", "ALTERNATIVE_TO"];
226
+ SUSPICION_EDGES = ["SUSPECTED_LINK"];
225
227
  TAXONOMY_EDGES = ["IS_A"];
226
228
  TRIAGE_EDGES = ["TRIAGED_BY", "CONFIRMS", "INDICATES", "ROUTES_TO"];
227
229
  GIT_EDGES = ["POINTS_AT", "PARENT", "AUTHORED_BY"];
@@ -229,6 +231,8 @@ var init_castalia = __esm({
229
231
  ...STRUCTURAL_EDGES,
230
232
  ...CAUSAL_EDGES,
231
233
  ...RESOLUTION_EDGES,
234
+ ...SOLUTION_STRUCTURE_EDGES,
235
+ ...SUSPICION_EDGES,
232
236
  ...CONCEPTUAL_EDGES,
233
237
  ...EVIDENCE_EDGES,
234
238
  ...CODE_EDGES,
@@ -273,8 +277,15 @@ var init_castalia = __esm({
273
277
  // git topology, not signal-flow
274
278
  "AUTHORED_BY",
275
279
  // git authorship, not signal-flow
276
- "CONTRIBUTED"
280
+ "CONTRIBUTED",
277
281
  // agent attribution (Agent → knowledge), not signal-flow
282
+ "SUPERSEDES",
283
+ // "prefer newer" gradient between solutions, not signal-flow
284
+ "ALTERNATIVE_TO",
285
+ // symmetric peer marker — weight would let alternatives inflate each other
286
+ // NB: BUILDS_ON is NOT excluded — it flows extension→base so foundational solutions rank up.
287
+ "SUSPECTED_LINK"
288
+ // Somnus hypothesis (PLAN_SOMNUS_V2 §4) — never flows rank; navigation-invisible.
278
289
  ]);
279
290
  EDGE_WEIGHT = {
280
291
  // Causal — high signal
@@ -371,6 +382,15 @@ var init_castalia = __esm({
371
382
  // INDICATES: real signal, but a candidate must not form a hub; promotion mints the
372
383
  // full-weight SOLVED_BY/MITIGATES instead of upgrading this edge.
373
384
  MAY_RESOLVE: 0.3,
385
+ // Solution-structure (SS-structure) — witnessed inter-solution relationships.
386
+ // BUILDS_ON flows (extension → base) so a foundational solution accrues centrality,
387
+ // discounted like MAY_RESOLVE so one witness isn't a hub; SUPERSEDES/ALTERNATIVE_TO
388
+ // are weightless gradients (PageRank-excluded below).
389
+ BUILDS_ON: 0.4,
390
+ SUPERSEDES: 0,
391
+ ALTERNATIVE_TO: 0,
392
+ // Suspicion — a hypothesis, weightless + PageRank-excluded (never flows rank / EIG).
393
+ SUSPECTED_LINK: 0,
374
394
  // Git — topology/authorship, weightless (not domain signal-flow)
375
395
  POINTS_AT: 0,
376
396
  PARENT: 0,
@@ -15628,7 +15648,9 @@ __export(src_exports, {
15628
15648
  RESOLUTION_EDGES: () => RESOLUTION_EDGES,
15629
15649
  RouteContextCountWireSchema: () => RouteContextCountWireSchema,
15630
15650
  SEMANTIC_NODE_LABELS: () => SEMANTIC_NODE_LABELS,
15651
+ SOLUTION_STRUCTURE_EDGES: () => SOLUTION_STRUCTURE_EDGES,
15631
15652
  STRUCTURAL_EDGES: () => STRUCTURAL_EDGES,
15653
+ SUSPICION_EDGES: () => SUSPICION_EDGES,
15632
15654
  SYMBOL_SUMMARY_KINDS: () => SYMBOL_SUMMARY_KINDS,
15633
15655
  SymbolSummarySidecarSchema: () => SymbolSummarySidecarSchema,
15634
15656
  TAXONOMY_EDGES: () => TAXONOMY_EDGES,
@@ -17857,15 +17879,21 @@ function priorsForFile(store, relPath) {
17857
17879
  related.set(n.id, n);
17858
17880
  }
17859
17881
  }
17882
+ const solutionsByProblem = /* @__PURE__ */ new Map();
17860
17883
  for (const p of openProblems) {
17861
17884
  for (const e of store.outEdges(p.id, ["SOLVED_BY", "CAUSED_BY", "INSTANCE_OF"])) {
17862
17885
  const n = store.getNode(e.to);
17863
17886
  if (n && CITABLE_PRIOR_LABELS.has(n.label)) related.set(n.id, n);
17887
+ if (n && n.label === "Solution" && e.type === "SOLVED_BY") {
17888
+ const list = solutionsByProblem.get(p.id) ?? [];
17889
+ if (!list.some((s) => s.id === n.id)) list.push(n);
17890
+ solutionsByProblem.set(p.id, list);
17891
+ }
17864
17892
  }
17865
17893
  }
17866
17894
  if (openProblems.length === 0 && related.size === 0) return null;
17867
17895
  openProblems.sort((a, b) => (b.lastUpdatedAt ?? 0) - (a.lastUpdatedAt ?? 0));
17868
- return { file: file2, openProblems, related: [...related.values()] };
17896
+ return { file: file2, openProblems, related: [...related.values()], solutionsByProblem };
17869
17897
  }
17870
17898
  function anchorProblemToDiff(store, problemId, changedPaths, workspaceId2, t, opts = {}) {
17871
17899
  return anchorNodeToDiff(store, problemId, "Problem", changedPaths, workspaceId2, t, opts);
@@ -20212,7 +20240,13 @@ function sliceForFile(store, relPath) {
20212
20240
  const fp = priorsForFile(store, relPath);
20213
20241
  const priors = fp ? {
20214
20242
  openProblems: fp.openProblems.slice(0, 3).map((p) => ({ id: p.id, description: p.description })),
20215
- related: fp.related.slice(0, 4).map((n) => ({ id: n.id, label: n.label, description: n.description }))
20243
+ related: fp.related.slice(0, 4).map((n) => ({ id: n.id, label: n.label, description: n.description })),
20244
+ solutionsByProblem: Object.fromEntries(
20245
+ fp.openProblems.slice(0, 3).map((p) => [
20246
+ p.id,
20247
+ (fp.solutionsByProblem.get(p.id) ?? []).slice(0, 4).map((s) => ({ id: s.id, description: s.description }))
20248
+ ])
20249
+ )
20216
20250
  } : void 0;
20217
20251
  return {
20218
20252
  relPath,
@@ -20378,6 +20412,12 @@ function renderSnapshot(s) {
20378
20412
  );
20379
20413
  for (const p of w.priors.openProblems) {
20380
20414
  lines.push(` - ${p.description} \u2192 \`(fix:[${p.id}])\` \xB7 \`([${p.id}])\``);
20415
+ const sols = w.priors.solutionsByProblem[p.id] ?? [];
20416
+ for (const s2 of sols) {
20417
+ lines.push(
20418
+ ` - already solved by: ${s2.description} \u2014 if your fix builds on / supersedes / is an alternative to this, say so: \`(builds-on:[${s2.id}])\` \xB7 \`(supersedes:[${s2.id}])\` \xB7 \`(alternative:[${s2.id}])\``
20419
+ );
20420
+ }
20381
20421
  }
20382
20422
  }
20383
20423
  if (w.priors?.related.length) {
@@ -24141,7 +24181,11 @@ function linkBullet(ref) {
24141
24181
  " queue growth under backpressure)) \u2014 this works with NO code anchor, and two agents naming",
24142
24182
  " the same pattern converge on one node. Cite a shown Pattern by handle: (pattern:[handle]).",
24143
24183
  ` \xB7 (aids:[${ref}],\u2026) \u2014 your FIX could also help these other, even unrelated, problems.`,
24144
- " A hypothesis, not a claim \u2014 it's recorded as may-resolve and checked by whoever tries it."
24184
+ " A hypothesis, not a claim \u2014 it's recorded as may-resolve and checked by whoever tries it.",
24185
+ ` \xB7 when your fix relates to a PRIOR solution you were primed with (a problem's`,
24186
+ ` "already solved by" line): (builds-on:[${ref}]) if you layer on it \xB7 (supersedes:[${ref}])`,
24187
+ " if you replace it \xB7 (alternative:[h]) if it's a different approach \u2014 pick one. This is the",
24188
+ " only way N solutions on one problem stop being a flat bag."
24145
24189
  ].join("\n");
24146
24190
  }
24147
24191
  function attemptBullet() {
@@ -41136,6 +41180,9 @@ var CAUSE_PREFIX = /^\s*cause:(?:#([a-z][\w-]{0,63}))?\s*/i;
41136
41180
  var CAUSE_ARROW = /\s+(?:<-|←)\s+/;
41137
41181
  var ATTEMPT_RE = /\(\s*(tried|failed):(?:#([a-z][\w-]{0,63}))?\s*((?:[^()\n]|\([^()\n]*\)){8,}?)\s*\)/gi;
41138
41182
  var AIDS_PREFIX = /^\s*aids:(?:#([a-z][\w-]{0,63}))?\s*/i;
41183
+ var BUILDS_ON_PREFIX = /^\s*builds-on:(?:#([a-z][\w-]{0,63}))?\s*/i;
41184
+ var SUPERSEDES_PREFIX = /^\s*supersedes:(?:#([a-z][\w-]{0,63}))?\s*/i;
41185
+ var ALTERNATIVE_PREFIX = /^\s*alternative:(?:#([a-z][\w-]{0,63}))?\s*/i;
41139
41186
  var INSTANCE_PREFIX = /^\s*instance:\s*/i;
41140
41187
  var PATTERN_RE = /\(\s*pattern:\s*([^()\n]{3,}?)\s*\)/gi;
41141
41188
  var PATTERN_TEXT_MAX = 120;
@@ -41179,10 +41226,13 @@ function parseInlineTags(text) {
41179
41226
  const causeM = fixM ? null : CAUSE_PREFIX.exec(content);
41180
41227
  const aidsM = fixM || causeM ? null : AIDS_PREFIX.exec(content);
41181
41228
  const instM = fixM || causeM || aidsM ? null : INSTANCE_PREFIX.exec(content);
41229
+ const ssM = fixM || causeM || aidsM || instM ? null : BUILDS_ON_PREFIX.exec(content) && { re: BUILDS_ON_PREFIX, kind: "builds-on" } || SUPERSEDES_PREFIX.exec(content) && { re: SUPERSEDES_PREFIX, kind: "supersedes" } || ALTERNATIVE_PREFIX.exec(content) && { re: ALTERNATIVE_PREFIX, kind: "alternative" };
41182
41230
  const isFix = fixM !== null;
41183
41231
  const isCause = causeM !== null;
41184
- if (aidsM || instM) {
41185
- const body2 = content.replace(aidsM ? AIDS_PREFIX : INSTANCE_PREFIX, "");
41232
+ if (aidsM || instM || ssM) {
41233
+ const re = aidsM ? AIDS_PREFIX : instM ? INSTANCE_PREFIX : ssM.re;
41234
+ const threadMatch = ssM ? ssM.re.exec(content) : null;
41235
+ const body2 = content.replace(re, "");
41186
41236
  const handles = [];
41187
41237
  HANDLE_RE.lastIndex = 0;
41188
41238
  let hh;
@@ -41191,11 +41241,13 @@ function parseInlineTags(text) {
41191
41241
  if (handle2 && !handles.includes(handle2)) handles.push(handle2);
41192
41242
  }
41193
41243
  if (handles.length > 0) {
41244
+ const kind = aidsM ? "transfer" : instM ? "instance" : ssM.kind;
41245
+ const threadId = aidsM?.[1] ?? threadMatch?.[1] ?? void 0;
41194
41246
  out2.push({
41195
- kind: aidsM ? "transfer" : "instance",
41247
+ kind,
41196
41248
  handles,
41197
41249
  sentence: sfield,
41198
- ...aidsM?.[1] ? { threadId: aidsM[1] } : {}
41250
+ ...threadId ? { threadId } : {}
41199
41251
  });
41200
41252
  }
41201
41253
  continue;
@@ -41445,7 +41497,7 @@ function harvestInlineTags(store, text, opts) {
41445
41497
  const source = opts.sourceId ? store.getNode(opts.sourceId) : null;
41446
41498
  const mintPriors = opts.mintPriors ?? true;
41447
41499
  const touched = opts.sessionTouchedIds ?? /* @__PURE__ */ new Set();
41448
- const plan = { priorEdges: 0, problems: [], fixes: [], triages: [], attempts: [], unresolvedFixes: [], transfers: [], instances: [], patterns: [], refutes: [], corroborations: [] };
41500
+ const plan = { priorEdges: 0, problems: [], fixes: [], triages: [], attempts: [], unresolvedFixes: [], transfers: [], solutionLinks: [], instances: [], patterns: [], refutes: [], corroborations: [] };
41449
41501
  const tags = parseInlineTags(text);
41450
41502
  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);
41451
41503
  const bindSymptom = (seq, threadId) => {
@@ -41530,6 +41582,22 @@ function harvestInlineTags(store, text, opts) {
41530
41582
  ...b.statement ? { boundStatement: b.statement } : {}
41531
41583
  });
41532
41584
  }
41585
+ } else if (tag.kind === "builds-on" || tag.kind === "supersedes" || tag.kind === "alternative") {
41586
+ const targetIds = [];
41587
+ for (const h of tag.handles ?? []) {
41588
+ const id = resolveHandle(store, h, opts.handleMap);
41589
+ if (id && !targetIds.includes(id)) targetIds.push(id);
41590
+ }
41591
+ if (targetIds.length > 0) {
41592
+ const b = bindSymptom(tag.seq, tag.threadId);
41593
+ const relation = tag.kind === "builds-on" ? "BUILDS_ON" : tag.kind === "supersedes" ? "SUPERSEDES" : "ALTERNATIVE_TO";
41594
+ plan.solutionLinks.push({
41595
+ relation,
41596
+ targetIds,
41597
+ ...tag.threadId ? { threadId: tag.threadId } : {},
41598
+ ...b.statement ? { boundStatement: b.statement } : {}
41599
+ });
41600
+ }
41533
41601
  } else if (tag.kind === "instance") {
41534
41602
  const targetIds = [];
41535
41603
  for (const h of tag.handles ?? []) {
@@ -42976,7 +43044,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
42976
43044
  }
42977
43045
 
42978
43046
  // src/engine.ts
42979
- var DAEMON_VERSION = true ? "2.0.0-dev.69" : "2.0.0-alpha.0";
43047
+ var DAEMON_VERSION = true ? "2.0.0-dev.71" : "2.0.0-alpha.0";
42980
43048
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
42981
43049
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
42982
43050
  var GIT_OP_MUTE_MS = 4e3;
@@ -43791,6 +43859,20 @@ function createWorkspaceEngine(opts) {
43791
43859
  mintCiteEdge(solId, targetId, "MAY_RESOLVE", 0.3, { transfer: true, hypothesis: true });
43792
43860
  }
43793
43861
  }
43862
+ for (const sl of plan.solutionLinks) {
43863
+ const pid = bindPid(sl);
43864
+ const solId = pid ? solutionForProblem(store, pid) : void 0;
43865
+ if (!solId) {
43866
+ console.warn(`[errata] ${sl.relation} tag dropped: no solution in scope \u2014 state it beside its (fix:\u2026)`);
43867
+ continue;
43868
+ }
43869
+ for (const targetId of sl.targetIds) {
43870
+ if (targetId === solId) continue;
43871
+ const target = store.getNode(targetId);
43872
+ if (!target || target.label !== "Solution") continue;
43873
+ mintCiteEdge(solId, targetId, sl.relation, 0.4, { solutionStructure: true, hypothesis: true });
43874
+ }
43875
+ }
43794
43876
  if (plan.refutes.length > 0 && typeof cloud.reportContradictions === "function") {
43795
43877
  void cloud.reportContradictions({ daemonVersion: DAEMON_VERSION, projectId: profile.id, items: plan.refutes }).then((r) => {
43796
43878
  if (r?.recorded) console.log(`[errata] refute: ${r.recorded} contradiction(s) recorded`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.0-dev.69",
3
+ "version": "2.0.0-dev.71",
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, 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;
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, SOLUTION_STRUCTURE_EDGES, SUSPICION_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";
@@ -183,6 +183,8 @@ var init_castalia = __esm({
183
183
  ABSTRACTION_EDGES = ["GENERALIZES", "DERIVED_FROM"];
184
184
  DECOMPOSITION_EDGES = ["SPLIT_INTO"];
185
185
  TRANSFER_EDGES = ["MAY_RESOLVE"];
186
+ SOLUTION_STRUCTURE_EDGES = ["BUILDS_ON", "SUPERSEDES", "ALTERNATIVE_TO"];
187
+ SUSPICION_EDGES = ["SUSPECTED_LINK"];
186
188
  TAXONOMY_EDGES = ["IS_A"];
187
189
  TRIAGE_EDGES = ["TRIAGED_BY", "CONFIRMS", "INDICATES", "ROUTES_TO"];
188
190
  GIT_EDGES = ["POINTS_AT", "PARENT", "AUTHORED_BY"];
@@ -190,6 +192,8 @@ var init_castalia = __esm({
190
192
  ...STRUCTURAL_EDGES,
191
193
  ...CAUSAL_EDGES,
192
194
  ...RESOLUTION_EDGES,
195
+ ...SOLUTION_STRUCTURE_EDGES,
196
+ ...SUSPICION_EDGES,
193
197
  ...CONCEPTUAL_EDGES,
194
198
  ...EVIDENCE_EDGES,
195
199
  ...CODE_EDGES,
@@ -234,8 +238,15 @@ var init_castalia = __esm({
234
238
  // git topology, not signal-flow
235
239
  "AUTHORED_BY",
236
240
  // git authorship, not signal-flow
237
- "CONTRIBUTED"
241
+ "CONTRIBUTED",
238
242
  // agent attribution (Agent → knowledge), not signal-flow
243
+ "SUPERSEDES",
244
+ // "prefer newer" gradient between solutions, not signal-flow
245
+ "ALTERNATIVE_TO",
246
+ // symmetric peer marker — weight would let alternatives inflate each other
247
+ // NB: BUILDS_ON is NOT excluded — it flows extension→base so foundational solutions rank up.
248
+ "SUSPECTED_LINK"
249
+ // Somnus hypothesis (PLAN_SOMNUS_V2 §4) — never flows rank; navigation-invisible.
239
250
  ]);
240
251
  EDGE_WEIGHT = {
241
252
  // Causal — high signal
@@ -332,6 +343,15 @@ var init_castalia = __esm({
332
343
  // INDICATES: real signal, but a candidate must not form a hub; promotion mints the
333
344
  // full-weight SOLVED_BY/MITIGATES instead of upgrading this edge.
334
345
  MAY_RESOLVE: 0.3,
346
+ // Solution-structure (SS-structure) — witnessed inter-solution relationships.
347
+ // BUILDS_ON flows (extension → base) so a foundational solution accrues centrality,
348
+ // discounted like MAY_RESOLVE so one witness isn't a hub; SUPERSEDES/ALTERNATIVE_TO
349
+ // are weightless gradients (PageRank-excluded below).
350
+ BUILDS_ON: 0.4,
351
+ SUPERSEDES: 0,
352
+ ALTERNATIVE_TO: 0,
353
+ // Suspicion — a hypothesis, weightless + PageRank-excluded (never flows rank / EIG).
354
+ SUSPECTED_LINK: 0,
335
355
  // Git — topology/authorship, weightless (not domain signal-flow)
336
356
  POINTS_AT: 0,
337
357
  PARENT: 0,
@@ -24960,15 +24980,21 @@ function priorsForFile(store2, relPath) {
24960
24980
  related.set(n.id, n);
24961
24981
  }
24962
24982
  }
24983
+ const solutionsByProblem = /* @__PURE__ */ new Map();
24963
24984
  for (const p of openProblems) {
24964
24985
  for (const e of store2.outEdges(p.id, ["SOLVED_BY", "CAUSED_BY", "INSTANCE_OF"])) {
24965
24986
  const n = store2.getNode(e.to);
24966
24987
  if (n && CITABLE_PRIOR_LABELS.has(n.label)) related.set(n.id, n);
24988
+ if (n && n.label === "Solution" && e.type === "SOLVED_BY") {
24989
+ const list = solutionsByProblem.get(p.id) ?? [];
24990
+ if (!list.some((s) => s.id === n.id)) list.push(n);
24991
+ solutionsByProblem.set(p.id, list);
24992
+ }
24967
24993
  }
24968
24994
  }
24969
24995
  if (openProblems.length === 0 && related.size === 0) return null;
24970
24996
  openProblems.sort((a, b) => (b.lastUpdatedAt ?? 0) - (a.lastUpdatedAt ?? 0));
24971
- return { file: file2, openProblems, related: [...related.values()] };
24997
+ return { file: file2, openProblems, related: [...related.values()], solutionsByProblem };
24972
24998
  }
24973
24999
  function resolveDesignProblems(store2, t) {
24974
25000
  let resolved = 0;
@@ -25819,7 +25845,13 @@ function sliceForFile(store2, relPath) {
25819
25845
  const fp = priorsForFile(store2, relPath);
25820
25846
  const priors = fp ? {
25821
25847
  openProblems: fp.openProblems.slice(0, 3).map((p) => ({ id: p.id, description: p.description })),
25822
- related: fp.related.slice(0, 4).map((n) => ({ id: n.id, label: n.label, description: n.description }))
25848
+ related: fp.related.slice(0, 4).map((n) => ({ id: n.id, label: n.label, description: n.description })),
25849
+ solutionsByProblem: Object.fromEntries(
25850
+ fp.openProblems.slice(0, 3).map((p) => [
25851
+ p.id,
25852
+ (fp.solutionsByProblem.get(p.id) ?? []).slice(0, 4).map((s) => ({ id: s.id, description: s.description }))
25853
+ ])
25854
+ )
25823
25855
  } : void 0;
25824
25856
  return {
25825
25857
  relPath,