@inerrata-corporation/errata 2.0.2-dev.157 → 2.0.2-dev.165

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.
Files changed (2) hide show
  1. package/errata.mjs +79 -22
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -50817,14 +50817,16 @@ function generalizePrincipleForSync(principle, level = 2) {
50817
50817
  delete node2.logicalId;
50818
50818
  return node2;
50819
50819
  }
50820
- function buildPrincipleIngest(sharedStore, daemonVersion, ignorePatterns = [], level = 2) {
50820
+ function buildPrincipleIngest(sharedStore, daemonVersion, ignorePatterns = [], level = 2, opts = {}) {
50821
+ const lang = opts.primaryLanguage?.trim().toLowerCase();
50822
+ const claim = lang ? { anchorVisibility: "public", anchor: `lang:${lang}` } : {};
50821
50823
  const selected = sharedStore.findNodesByLabel("Claim").filter((n) => isSyncablePrinciple(n, ignorePatterns));
50822
50824
  for (const n of selected) {
50823
50825
  if (Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) !== ABSTRACTION_LEVEL.PRINCIPLE || n.attrs["provisional"] !== false) {
50824
50826
  throw new Error(`buildPrincipleIngest: refusing to sync non-canonical-principle ${n.id} \u2014 C7 invariant violated`);
50825
50827
  }
50826
50828
  }
50827
- const nodes = selected.map((n) => generalizePrincipleForSync(n, level));
50829
+ const nodes = selected.map((n) => ({ ...generalizePrincipleForSync(n, level), ...claim }));
50828
50830
  if (nodes.length === 0) return null;
50829
50831
  const base = {
50830
50832
  daemonVersion,
@@ -50902,13 +50904,51 @@ function generalizeRouteForSync(edge2, level) {
50902
50904
  navFailures: 0
50903
50905
  };
50904
50906
  }
50907
+ function buildBucketTokenAnchors(languages, packages = []) {
50908
+ const anchors = {};
50909
+ const langTokens = /* @__PURE__ */ new Set();
50910
+ for (const l of languages) {
50911
+ const t = canonicalizeToken(String(l));
50912
+ if (!t || t.includes(":") && !t.startsWith("lang:")) continue;
50913
+ langTokens.add(t);
50914
+ anchors[t] = t.startsWith("lang:") ? t : `lang:${t}`;
50915
+ }
50916
+ const versionless = (purl) => purl.replace(/@[^/@]+$/, "");
50917
+ const conflicted = /* @__PURE__ */ new Set();
50918
+ for (const p of packages) {
50919
+ const t = canonicalizeToken(p.name);
50920
+ if (!t || !p.purl || langTokens.has(t) || conflicted.has(t)) continue;
50921
+ const existing = anchors[t];
50922
+ if (existing === void 0) {
50923
+ anchors[t] = p.purl;
50924
+ } else if (versionless(existing) !== versionless(p.purl)) {
50925
+ delete anchors[t];
50926
+ conflicted.add(t);
50927
+ }
50928
+ }
50929
+ return anchors;
50930
+ }
50931
+ function witnessedAnchor(routes, tokenAnchors) {
50932
+ const weight = /* @__PURE__ */ new Map();
50933
+ for (const e of routes) {
50934
+ const perContext = e.attrs["perContext"] ?? {};
50935
+ for (const [bucket, c] of Object.entries(perContext)) {
50936
+ if (!bucket.startsWith("stack:") || !c || !(c.confirmed > 0)) continue;
50937
+ const anchor = tokenAnchors[bucket.slice("stack:".length)];
50938
+ if (anchor) weight.set(anchor, (weight.get(anchor) ?? 0) + c.confirmed);
50939
+ }
50940
+ }
50941
+ return [...weight.entries()].sort((a, b) => b[1] - a[1] || (a[0] < b[0] ? -1 : 1))[0]?.[0];
50942
+ }
50905
50943
  function buildTriageIngest(shared, daemonVersion, ignorePatterns = [], level = 2, opts = {}) {
50906
50944
  const lang = opts.primaryLanguage?.trim().toLowerCase();
50907
- const claim = lang ? { anchorVisibility: "public", anchor: `lang:${lang}` } : {};
50945
+ const fallbackAnchor = lang ? `lang:${lang}` : void 0;
50946
+ const tokenAnchors = opts.tokenAnchors ?? {};
50947
+ const claimOf = (anchor) => anchor ? { anchorVisibility: "public", anchor } : {};
50908
50948
  const nodes = [];
50909
50949
  const edges = [];
50910
50950
  const seenIds = /* @__PURE__ */ new Set();
50911
- const shareEndpoint = (id) => {
50951
+ const shareEndpoint = (id, anchor) => {
50912
50952
  if (seenIds.has(id)) return;
50913
50953
  const n = shared.getNode(id);
50914
50954
  if (!n) return;
@@ -50918,12 +50958,13 @@ function buildTriageIngest(shared, daemonVersion, ignorePatterns = [], level = 2
50918
50958
  description: generalize(n.description, { level }).text,
50919
50959
  embedding: [],
50920
50960
  attrs: { scope: {} },
50921
- ...claim
50961
+ ...claimOf(anchor ?? fallbackAnchor)
50922
50962
  });
50923
50963
  };
50924
50964
  for (const tri of shared.findNodesByLabel("Triage")) {
50925
50965
  const routes = shared.outEdges(tri.id, ["CONFIRMS", "INDICATES", "ROUTES_TO"]).filter((e) => isSyncableRoute(e, shared, tri, ignorePatterns));
50926
50966
  if (routes.length === 0) continue;
50967
+ const triAnchor = witnessedAnchor(routes, tokenAnchors);
50927
50968
  if (!seenIds.has(tri.id)) {
50928
50969
  seenIds.add(tri.id);
50929
50970
  const statement = String(tri.attrs["statement"] ?? "");
@@ -50935,18 +50976,18 @@ function buildTriageIngest(shared, daemonVersion, ignorePatterns = [], level = 2
50935
50976
  ...statement ? { statement: generalize(statement, { level }).text } : {},
50936
50977
  ...tri.attrs["perContextSeen"] ? { perContextSeen: tri.attrs["perContextSeen"] } : {}
50937
50978
  },
50938
- ...claim
50979
+ ...claimOf(triAnchor ?? fallbackAnchor)
50939
50980
  });
50940
50981
  }
50941
50982
  for (const tb of shared.inEdges(tri.id, ["TRIAGED_BY"])) {
50942
- shareEndpoint(tb.from);
50983
+ shareEndpoint(tb.from, triAnchor);
50943
50984
  edges.push({ ...tb, navSuccesses: 0, navFailures: 0 });
50944
50985
  }
50945
50986
  for (const e of routes) {
50946
50987
  if (!(e.type === "CONFIRMS" || e.type === "ROUTES_TO" && e.attrs["provisional"] === false)) {
50947
50988
  throw new Error(`buildTriageIngest: refusing to sync non-router route ${e.id} \u2014 C7 invariant violated`);
50948
50989
  }
50949
- shareEndpoint(e.to);
50990
+ shareEndpoint(e.to, witnessedAnchor([e], tokenAnchors));
50950
50991
  edges.push(generalizeRouteForSync(e, level));
50951
50992
  }
50952
50993
  }
@@ -51995,7 +52036,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
51995
52036
  }
51996
52037
 
51997
52038
  // src/engine.ts
51998
- var DAEMON_VERSION = true ? "2.0.2-dev.157" : "2.0.0-alpha.0";
52039
+ var DAEMON_VERSION = true ? "2.0.2-dev.165" : "2.0.0-alpha.0";
51999
52040
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
52000
52041
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
52001
52042
  var GIT_OP_MUTE_MS = 4e3;
@@ -54433,6 +54474,18 @@ async function startMultiDaemon(opts = {}) {
54433
54474
  startLoopLagMonitor();
54434
54475
  let baseUrl = "";
54435
54476
  const records = [];
54477
+ const machineDominantLanguage = () => {
54478
+ const langCounts = /* @__PURE__ */ new Map();
54479
+ for (const r of records) {
54480
+ for (const l of r.engine.profile.languages ?? []) {
54481
+ const k = String(l).trim().toLowerCase();
54482
+ if (k) langCounts.set(k, (langCounts.get(k) ?? 0) + 1);
54483
+ }
54484
+ }
54485
+ return [...langCounts.entries()].sort(
54486
+ (a, b) => b[1] - a[1] || (a[0] < b[0] ? -1 : 1)
54487
+ )[0]?.[0];
54488
+ };
54436
54489
  const updatePoller = opts.updateCheck ? startUpdatePoller({
54437
54490
  channel: loadConfig().updateChannel,
54438
54491
  onChange: (pending) => {
@@ -54995,26 +55048,30 @@ async function startMultiDaemon(opts = {}) {
54995
55048
  async syncPrinciplesPublic() {
54996
55049
  if (!loadConfig().consent.sync) return { uploaded: 0, skipped: "consent-off" };
54997
55050
  const ignore = loadClaimIgnorePatterns(globalDir());
54998
- const payload = buildPrincipleIngest(sharedStore, DAEMON_VERSION, ignore);
55051
+ const primaryLanguage = machineDominantLanguage();
55052
+ const payload = buildPrincipleIngest(sharedStore, DAEMON_VERSION, ignore, 2, {
55053
+ ...primaryLanguage ? { primaryLanguage } : {}
55054
+ });
54999
55055
  if (!payload) return { uploaded: 0 };
55000
55056
  const res = await cloudNow().ingest(payload);
55001
55057
  return { uploaded: res.accepted };
55002
55058
  },
55003
55059
  async syncTriagePublic() {
55004
- if (!loadConfig().consent.sync) return { uploaded: 0, skipped: "consent-off" };
55060
+ const cfg2 = loadConfig();
55061
+ if (!cfg2.consent.sync) return { uploaded: 0, skipped: "consent-off" };
55005
55062
  const ignore = loadClaimIgnorePatterns(globalDir());
55006
- const langCounts = /* @__PURE__ */ new Map();
55007
- for (const r of records) {
55008
- for (const l of r.engine.profile.languages ?? []) {
55009
- const k = String(l).trim().toLowerCase();
55010
- if (k) langCounts.set(k, (langCounts.get(k) ?? 0) + 1);
55011
- }
55012
- }
55013
- const primaryLanguage = [...langCounts.entries()].sort(
55014
- (a, b) => b[1] - a[1] || (a[0] < b[0] ? -1 : 1)
55015
- )[0]?.[0];
55063
+ const primaryLanguage = machineDominantLanguage();
55064
+ const languages = records.flatMap((r) => r.engine.profile.languages ?? []);
55065
+ const packages = cfg2.consent.contributePackages ? records.flatMap(
55066
+ (r) => r.engine.store.findNodesByLabel("Package").map((p) => ({
55067
+ name: String(p.attrs["name"] ?? ""),
55068
+ purl: String(p.attrs["purl"] ?? p.id)
55069
+ }))
55070
+ ) : [];
55071
+ const tokenAnchors = buildBucketTokenAnchors(languages, packages);
55016
55072
  const payload = buildTriageIngest(sharedStore, DAEMON_VERSION, ignore, 2, {
55017
- ...primaryLanguage ? { primaryLanguage } : {}
55073
+ ...primaryLanguage ? { primaryLanguage } : {},
55074
+ tokenAnchors
55018
55075
  });
55019
55076
  if (!payload) return { uploaded: 0 };
55020
55077
  const res = await cloudNow().ingest(payload);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.2-dev.157",
3
+ "version": "2.0.2-dev.165",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {