@inerrata-corporation/errata 2.0.0-dev.76 → 2.0.0-dev.77

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 +82 -2
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -20899,6 +20899,11 @@ function toWirePayload(batch, runId) {
20899
20899
  // Origin key (= project) for the refute channel's cross-origin gate; absent
20900
20900
  // for id-less batches (principle sync) → those nodes stay fail-open.
20901
20901
  ...batch.originProject ? { originProject: batch.originProject } : {},
20902
+ // PJ-write (§5a): the AUDIENCE assertion — which project stratum this batch is
20903
+ // contributed to. Verified server-side against the projected link record; an
20904
+ // unverifiable assertion rejects the whole batch rather than downgrading it to a
20905
+ // wider audience. Absent ⇒ exactly today's wire.
20906
+ ...batch.projectId ? { projectId: batch.projectId } : {},
20902
20907
  nodes,
20903
20908
  edges,
20904
20909
  ...symbolSummaries ? { symbolSummaries } : {}
@@ -21145,6 +21150,18 @@ var init_client = __esm({
21145
21150
  async attachProject(projectId, locator) {
21146
21151
  return this.json("POST", "/api/gate/projects/attach", { projectId, locator });
21147
21152
  }
21153
+ /** Fetch the project's symbol salt (PJ-anchors · plan §6c) — the HMAC key this
21154
+ * workspace needs to derive project-canonical `sym_` anchor ids that CONVERGE
21155
+ * with every other member's.
21156
+ *
21157
+ * Members-only: the server gates it with the same fail-closed check the ingest
21158
+ * door uses (known + active + owned by the caller's org), and 403s otherwise.
21159
+ * Safe to hold locally for exactly one reason — a project member can already read
21160
+ * the project's code, so the salt lets them compute ids for symbols they can see
21161
+ * anyway. It is key material: keep it in memory, never log it. */
21162
+ async projectSymbolSalt(projectId) {
21163
+ return this.json("GET", `/v2/projects/${encodeURIComponent(projectId)}/symbol-salt`);
21164
+ }
21148
21165
  /** Create a locator-less project — `errata link --name` for repos without a
21149
21166
  * usable remote. Discovery can't find it; the caller stamps the id locally. */
21150
21167
  async createProject(name2) {
@@ -43276,7 +43293,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
43276
43293
  }
43277
43294
 
43278
43295
  // src/engine.ts
43279
- var DAEMON_VERSION = true ? "2.0.0-dev.76" : "2.0.0-alpha.0";
43296
+ var DAEMON_VERSION = true ? "2.0.0-dev.77" : "2.0.0-alpha.0";
43280
43297
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
43281
43298
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
43282
43299
  var GIT_OP_MUTE_MS = 4e3;
@@ -45005,6 +45022,7 @@ function runLockfilePass(opts) {
45005
45022
  init_src();
45006
45023
  init_src2();
45007
45024
  init_src8();
45025
+ init_src();
45008
45026
 
45009
45027
  // src/contribution-ready.ts
45010
45028
  init_src3();
@@ -45143,6 +45161,50 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
45143
45161
  contextNodes.push(shareableContext(t, wireId));
45144
45162
  }
45145
45163
  }
45164
+ const project = opts.project;
45165
+ if (project) {
45166
+ const now = Date.now();
45167
+ for (const sourceId of anchorSources) {
45168
+ const source = store.getNode(sourceId);
45169
+ if (!source) continue;
45170
+ for (const e of store.outEdges(sourceId, ["ANCHORED_AT"])) {
45171
+ const target = store.getNode(e.to);
45172
+ if (!target) continue;
45173
+ const relPath = target.attrs["relPath"];
45174
+ const qname = target.attrs["qname"];
45175
+ if (typeof relPath !== "string" || typeof qname !== "string") continue;
45176
+ if (ignored(relPath) || ignored(qname)) continue;
45177
+ const symId = projectSymbolId(project.salt, project.projectId, relPath, qname, target.label);
45178
+ if (!contextSeen.has(symId)) {
45179
+ contextSeen.add(symId);
45180
+ contextNodes.push({
45181
+ id: symId,
45182
+ label: "Symbol",
45183
+ // The id IS the description: there is nothing that can be said about an
45184
+ // opaque symbol without disclosing it, and the wire requires a non-empty
45185
+ // string. It must never carry the name or the path.
45186
+ description: symId,
45187
+ // `kind` is coarse (Function/Class/…) — shape, not identity.
45188
+ attrs: { kind: target.label },
45189
+ embedding: [],
45190
+ extractionConfidence: 1,
45191
+ extractionSource: "daemon-extracted",
45192
+ cumulativeSurprise: 0,
45193
+ peakSurprise: 0,
45194
+ cumulativeHits: 0,
45195
+ lastUpdatedAt: now,
45196
+ createdAt: now,
45197
+ memoryTier: "short-term",
45198
+ pageRank: 0,
45199
+ isLandmark: false,
45200
+ community: null,
45201
+ stability: "unstable"
45202
+ });
45203
+ }
45204
+ anchorEdges.push({ ...e, to: symId, attrs: {} });
45205
+ }
45206
+ }
45207
+ }
45146
45208
  if (nodes.length === 0 && anchorEdges.length === 0) return null;
45147
45209
  let symbolSummaries;
45148
45210
  if (opts.lexicon && opts.lexicon.size > 0 && nodes.length > 0) {
@@ -45444,6 +45506,14 @@ function createRootAdopter(deps) {
45444
45506
  }
45445
45507
 
45446
45508
  // src/multi.ts
45509
+ var projectSymbolSalts = /* @__PURE__ */ new Map();
45510
+ async function resolveProjectSymbolSalt(client, projectId) {
45511
+ const cached2 = projectSymbolSalts.get(projectId);
45512
+ if (cached2) return { projectId, salt: cached2 };
45513
+ const { salt } = await client.projectSymbolSalt(projectId);
45514
+ projectSymbolSalts.set(projectId, salt);
45515
+ return { projectId, salt };
45516
+ }
45447
45517
  function normPath(p) {
45448
45518
  return p.replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
45449
45519
  }
@@ -46052,11 +46122,21 @@ async function startMultiDaemon(opts = {}) {
46052
46122
  if (summaries.size > 0) lexicon = buildSymbolLexicon(store, summaries);
46053
46123
  } catch {
46054
46124
  }
46125
+ const projectId = r.engine.profile.projectId;
46126
+ let project;
46127
+ if (projectId) {
46128
+ try {
46129
+ project = await resolveProjectSymbolSalt(client, projectId);
46130
+ } catch {
46131
+ }
46132
+ }
46055
46133
  const instances = buildInstanceIngest(store, r.engine.profile, DAEMON_VERSION, ignore, {
46056
46134
  includePackages: cfg2.consent.contributePackages,
46057
- ...lexicon ? { lexicon } : {}
46135
+ ...lexicon ? { lexicon } : {},
46136
+ ...project ? { project } : {}
46058
46137
  });
46059
46138
  if (instances) {
46139
+ if (project) instances.projectId = project.projectId;
46060
46140
  const res = await client.ingest(instances);
46061
46141
  uploaded += res.accepted;
46062
46142
  const seq = store.currentIngestSeq();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.0-dev.76",
3
+ "version": "2.0.0-dev.77",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {