@inerrata-corporation/errata 2.0.2-dev.612 → 2.0.2-dev.627

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.
@@ -16728,11 +16728,13 @@ init_src();
16728
16728
  // ../../packages/local-graph/src/design-problem.ts
16729
16729
  init_src();
16730
16730
  init_src();
16731
- init_src2();
16732
16731
 
16733
16732
  // ../../packages/local-graph/src/problem-package-link.ts
16734
16733
  init_src();
16735
16734
 
16735
+ // ../../packages/local-graph/src/design-problem.ts
16736
+ init_src2();
16737
+
16736
16738
  // ../../packages/local-graph/src/problem-dedup.ts
16737
16739
  init_src();
16738
16740
  init_src();
package/errata.mjs CHANGED
@@ -18154,207 +18154,6 @@ var init_aggregate = __esm({
18154
18154
  }
18155
18155
  });
18156
18156
 
18157
- // ../../packages/embedding/src/model.ts
18158
- import { mkdirSync as mkdirSync3, existsSync as existsSync4 } from "node:fs";
18159
- import { homedir } from "node:os";
18160
- import { dirname as dirname3, join as join3 } from "node:path";
18161
- import { createRequire } from "node:module";
18162
- function semanticFloorFor(version2) {
18163
- if (version2 === EMBEDDING_VERSION || version2 === MODEL_EMBEDDING_VERSION) return 0.25;
18164
- return 0.5;
18165
- }
18166
- function noteHashFallback() {
18167
- if (warnedHashFallback) return;
18168
- if (process.env["ERRATA_EMBED_HASH_ONLY"] === "1") return;
18169
- warnedHashFallback = true;
18170
- console.warn(
18171
- `[errata] embedding model unavailable (${lastError?.message ?? "unknown"}) \u2014 falling back to ${EMBEDDING_VERSION} hash vectors; semantic ranking runs at reduced fidelity`
18172
- );
18173
- }
18174
- function getCacheDir() {
18175
- return process.env["ERRATA_MODEL_CACHE"] ?? join3(homedir(), ".errata", "models");
18176
- }
18177
- async function loadTransformers() {
18178
- try {
18179
- return await import("@huggingface/transformers");
18180
- } catch (err2) {
18181
- void err2;
18182
- }
18183
- try {
18184
- const seaResourceBase = join3(
18185
- // execPath dir is where errata.exe lives; resources/ rides alongside.
18186
- dirname3(process.execPath),
18187
- "resources",
18188
- "_resolve.js"
18189
- );
18190
- const resourceRequire = createRequire(seaResourceBase);
18191
- return resourceRequire("@huggingface/transformers");
18192
- } catch (err2) {
18193
- lastError = err2 instanceof Error ? err2 : new Error(String(err2));
18194
- return null;
18195
- }
18196
- }
18197
- async function loadPipeline() {
18198
- const cacheDir = getCacheDir();
18199
- if (!existsSync4(cacheDir)) mkdirSync3(cacheDir, { recursive: true });
18200
- try {
18201
- const tx = await loadTransformers();
18202
- if (!tx) {
18203
- throw lastError ?? new Error("transformers package unavailable");
18204
- }
18205
- tx.env.cacheDir = cacheDir;
18206
- tx.env.useFSCache = true;
18207
- tx.env.allowLocalModels = true;
18208
- tx.env.allowRemoteModels = process.env["ERRATA_OFFLINE"] !== "1";
18209
- const pipe2 = await tx.pipeline("feature-extraction", MODEL_NAME, {
18210
- // Quantized weights cut size 4x; quality drop is negligible for
18211
- // short-text similarity. Override via env if you want full
18212
- // precision.
18213
- dtype: process.env["ERRATA_MODEL_DTYPE"] ?? "q8"
18214
- });
18215
- return pipe2;
18216
- } catch (err2) {
18217
- lastError = err2 instanceof Error ? err2 : new Error(String(err2));
18218
- return null;
18219
- }
18220
- }
18221
- async function ensureModelLoaded() {
18222
- if (!pipelinePromise) {
18223
- pipelinePromise = loadPipeline();
18224
- }
18225
- return pipelinePromise;
18226
- }
18227
- async function embedTextWithModel(text) {
18228
- const pipe2 = await ensureModelLoaded();
18229
- if (!pipe2) {
18230
- throw new Error(
18231
- `embedding model could not be loaded: ${lastError?.message ?? "unknown"}`
18232
- );
18233
- }
18234
- if (!text) return new Array(MODEL_EMBEDDING_DIM).fill(0);
18235
- const out2 = await pipe2(text, { pooling: "mean", normalize: true });
18236
- return Array.from(out2.data);
18237
- }
18238
- async function embedBatchWithModelOrHash(texts) {
18239
- if (texts.length === 0) return [];
18240
- if (process.env["ERRATA_EMBED_HASH_ONLY"] === "1") {
18241
- return texts.map((t) => {
18242
- const v = embed(t);
18243
- return { vector: v, version: EMBEDDING_VERSION, dim: v.length };
18244
- });
18245
- }
18246
- try {
18247
- const pipe2 = await ensureModelLoaded();
18248
- if (pipe2) {
18249
- const out2 = await pipe2(texts, {
18250
- pooling: "mean",
18251
- normalize: true
18252
- });
18253
- const dim = out2.dims[out2.dims.length - 1] ?? MODEL_EMBEDDING_DIM;
18254
- const total = texts.length;
18255
- const results = [];
18256
- for (let i2 = 0; i2 < total; i2++) {
18257
- const v = Array.from(out2.data.subarray(i2 * dim, (i2 + 1) * dim));
18258
- results.push({ vector: v, version: MODEL_EMBEDDING_VERSION, dim });
18259
- }
18260
- return results;
18261
- }
18262
- } catch {
18263
- }
18264
- noteHashFallback();
18265
- return texts.map((t) => {
18266
- const v = embed(t);
18267
- return { vector: v, version: EMBEDDING_VERSION, dim: v.length };
18268
- });
18269
- }
18270
- async function embedTextWithModelOrHash(text) {
18271
- if (process.env["ERRATA_EMBED_HASH_ONLY"] === "1") {
18272
- const v = embed(text);
18273
- return { vector: v, version: EMBEDDING_VERSION, dim: v.length };
18274
- }
18275
- try {
18276
- const v = await embedTextWithModel(text);
18277
- return { vector: v, version: MODEL_EMBEDDING_VERSION, dim: v.length };
18278
- } catch {
18279
- noteHashFallback();
18280
- const v = embed(text);
18281
- return { vector: v, version: EMBEDDING_VERSION, dim: v.length };
18282
- }
18283
- }
18284
- var MODEL_NAME, MODEL_EMBEDDING_DIM, MODEL_EMBEDDING_VERSION, pipelinePromise, lastError, warnedHashFallback;
18285
- var init_model = __esm({
18286
- "../../packages/embedding/src/model.ts"() {
18287
- "use strict";
18288
- init_src3();
18289
- MODEL_NAME = "Xenova/all-MiniLM-L6-v2";
18290
- MODEL_EMBEDDING_DIM = 384;
18291
- MODEL_EMBEDDING_VERSION = "minilm-l6-v2";
18292
- pipelinePromise = null;
18293
- lastError = null;
18294
- warnedHashFallback = false;
18295
- }
18296
- });
18297
-
18298
- // ../../packages/embedding/src/index.ts
18299
- function djb2(s) {
18300
- let h = 5381;
18301
- for (let i2 = 0; i2 < s.length; i2++) {
18302
- h = (h << 5) + h + s.charCodeAt(i2) >>> 0;
18303
- }
18304
- return h;
18305
- }
18306
- function djb2Signed(s) {
18307
- let h = 0;
18308
- for (let i2 = 0; i2 < s.length; i2++) {
18309
- h = h * 31 + s.charCodeAt(i2) | 0;
18310
- }
18311
- return h;
18312
- }
18313
- function tokenize2(text) {
18314
- return text.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length > 0 && t.length <= 40);
18315
- }
18316
- function* charTrigrams(text) {
18317
- const s = text.toLowerCase();
18318
- for (let i2 = 0; i2 <= s.length - 3; i2++) {
18319
- yield s.slice(i2, i2 + 3);
18320
- }
18321
- }
18322
- function embed(text) {
18323
- const vec = new Array(EMBEDDING_DIM).fill(0);
18324
- if (!text) return vec;
18325
- for (const tok of tokenize2(text)) {
18326
- const idx = djb2(tok) % EMBEDDING_DIM;
18327
- const sign = djb2Signed(tok) & 1 ? 1 : -1;
18328
- vec[idx] = vec[idx] + sign;
18329
- }
18330
- for (const tri of charTrigrams(text)) {
18331
- const idx = djb2("3:" + tri) % EMBEDDING_DIM;
18332
- const sign = djb2Signed("3:" + tri) & 1 ? 1 : -1;
18333
- vec[idx] = vec[idx] + 0.5 * sign;
18334
- }
18335
- let normSq = 0;
18336
- for (const x of vec) normSq += x * x;
18337
- if (normSq <= 0) return vec;
18338
- const inv = 1 / Math.sqrt(normSq);
18339
- for (let i2 = 0; i2 < vec.length; i2++) vec[i2] = vec[i2] * inv;
18340
- return vec;
18341
- }
18342
- function cosine(a, b) {
18343
- if (a.length !== b.length || a.length === 0) return 0;
18344
- let dot = 0;
18345
- for (let i2 = 0; i2 < a.length; i2++) dot += a[i2] * b[i2];
18346
- return dot;
18347
- }
18348
- var EMBEDDING_DIM, EMBEDDING_VERSION;
18349
- var init_src3 = __esm({
18350
- "../../packages/embedding/src/index.ts"() {
18351
- "use strict";
18352
- init_model();
18353
- EMBEDDING_DIM = 256;
18354
- EMBEDDING_VERSION = "hash-v1";
18355
- }
18356
- });
18357
-
18358
18157
  // ../../packages/local-graph/src/problem-package-link.ts
18359
18158
  function buildPackageIndex(store) {
18360
18159
  const idx = /* @__PURE__ */ new Map();
@@ -18680,6 +18479,207 @@ var init_problem_package_link = __esm({
18680
18479
  }
18681
18480
  });
18682
18481
 
18482
+ // ../../packages/embedding/src/model.ts
18483
+ import { mkdirSync as mkdirSync3, existsSync as existsSync4 } from "node:fs";
18484
+ import { homedir } from "node:os";
18485
+ import { dirname as dirname3, join as join3 } from "node:path";
18486
+ import { createRequire } from "node:module";
18487
+ function semanticFloorFor(version2) {
18488
+ if (version2 === EMBEDDING_VERSION || version2 === MODEL_EMBEDDING_VERSION) return 0.25;
18489
+ return 0.5;
18490
+ }
18491
+ function noteHashFallback() {
18492
+ if (warnedHashFallback) return;
18493
+ if (process.env["ERRATA_EMBED_HASH_ONLY"] === "1") return;
18494
+ warnedHashFallback = true;
18495
+ console.warn(
18496
+ `[errata] embedding model unavailable (${lastError?.message ?? "unknown"}) \u2014 falling back to ${EMBEDDING_VERSION} hash vectors; semantic ranking runs at reduced fidelity`
18497
+ );
18498
+ }
18499
+ function getCacheDir() {
18500
+ return process.env["ERRATA_MODEL_CACHE"] ?? join3(homedir(), ".errata", "models");
18501
+ }
18502
+ async function loadTransformers() {
18503
+ try {
18504
+ return await import("@huggingface/transformers");
18505
+ } catch (err2) {
18506
+ void err2;
18507
+ }
18508
+ try {
18509
+ const seaResourceBase = join3(
18510
+ // execPath dir is where errata.exe lives; resources/ rides alongside.
18511
+ dirname3(process.execPath),
18512
+ "resources",
18513
+ "_resolve.js"
18514
+ );
18515
+ const resourceRequire = createRequire(seaResourceBase);
18516
+ return resourceRequire("@huggingface/transformers");
18517
+ } catch (err2) {
18518
+ lastError = err2 instanceof Error ? err2 : new Error(String(err2));
18519
+ return null;
18520
+ }
18521
+ }
18522
+ async function loadPipeline() {
18523
+ const cacheDir = getCacheDir();
18524
+ if (!existsSync4(cacheDir)) mkdirSync3(cacheDir, { recursive: true });
18525
+ try {
18526
+ const tx = await loadTransformers();
18527
+ if (!tx) {
18528
+ throw lastError ?? new Error("transformers package unavailable");
18529
+ }
18530
+ tx.env.cacheDir = cacheDir;
18531
+ tx.env.useFSCache = true;
18532
+ tx.env.allowLocalModels = true;
18533
+ tx.env.allowRemoteModels = process.env["ERRATA_OFFLINE"] !== "1";
18534
+ const pipe2 = await tx.pipeline("feature-extraction", MODEL_NAME, {
18535
+ // Quantized weights cut size 4x; quality drop is negligible for
18536
+ // short-text similarity. Override via env if you want full
18537
+ // precision.
18538
+ dtype: process.env["ERRATA_MODEL_DTYPE"] ?? "q8"
18539
+ });
18540
+ return pipe2;
18541
+ } catch (err2) {
18542
+ lastError = err2 instanceof Error ? err2 : new Error(String(err2));
18543
+ return null;
18544
+ }
18545
+ }
18546
+ async function ensureModelLoaded() {
18547
+ if (!pipelinePromise) {
18548
+ pipelinePromise = loadPipeline();
18549
+ }
18550
+ return pipelinePromise;
18551
+ }
18552
+ async function embedTextWithModel(text) {
18553
+ const pipe2 = await ensureModelLoaded();
18554
+ if (!pipe2) {
18555
+ throw new Error(
18556
+ `embedding model could not be loaded: ${lastError?.message ?? "unknown"}`
18557
+ );
18558
+ }
18559
+ if (!text) return new Array(MODEL_EMBEDDING_DIM).fill(0);
18560
+ const out2 = await pipe2(text, { pooling: "mean", normalize: true });
18561
+ return Array.from(out2.data);
18562
+ }
18563
+ async function embedBatchWithModelOrHash(texts) {
18564
+ if (texts.length === 0) return [];
18565
+ if (process.env["ERRATA_EMBED_HASH_ONLY"] === "1") {
18566
+ return texts.map((t) => {
18567
+ const v = embed(t);
18568
+ return { vector: v, version: EMBEDDING_VERSION, dim: v.length };
18569
+ });
18570
+ }
18571
+ try {
18572
+ const pipe2 = await ensureModelLoaded();
18573
+ if (pipe2) {
18574
+ const out2 = await pipe2(texts, {
18575
+ pooling: "mean",
18576
+ normalize: true
18577
+ });
18578
+ const dim = out2.dims[out2.dims.length - 1] ?? MODEL_EMBEDDING_DIM;
18579
+ const total = texts.length;
18580
+ const results = [];
18581
+ for (let i2 = 0; i2 < total; i2++) {
18582
+ const v = Array.from(out2.data.subarray(i2 * dim, (i2 + 1) * dim));
18583
+ results.push({ vector: v, version: MODEL_EMBEDDING_VERSION, dim });
18584
+ }
18585
+ return results;
18586
+ }
18587
+ } catch {
18588
+ }
18589
+ noteHashFallback();
18590
+ return texts.map((t) => {
18591
+ const v = embed(t);
18592
+ return { vector: v, version: EMBEDDING_VERSION, dim: v.length };
18593
+ });
18594
+ }
18595
+ async function embedTextWithModelOrHash(text) {
18596
+ if (process.env["ERRATA_EMBED_HASH_ONLY"] === "1") {
18597
+ const v = embed(text);
18598
+ return { vector: v, version: EMBEDDING_VERSION, dim: v.length };
18599
+ }
18600
+ try {
18601
+ const v = await embedTextWithModel(text);
18602
+ return { vector: v, version: MODEL_EMBEDDING_VERSION, dim: v.length };
18603
+ } catch {
18604
+ noteHashFallback();
18605
+ const v = embed(text);
18606
+ return { vector: v, version: EMBEDDING_VERSION, dim: v.length };
18607
+ }
18608
+ }
18609
+ var MODEL_NAME, MODEL_EMBEDDING_DIM, MODEL_EMBEDDING_VERSION, pipelinePromise, lastError, warnedHashFallback;
18610
+ var init_model = __esm({
18611
+ "../../packages/embedding/src/model.ts"() {
18612
+ "use strict";
18613
+ init_src3();
18614
+ MODEL_NAME = "Xenova/all-MiniLM-L6-v2";
18615
+ MODEL_EMBEDDING_DIM = 384;
18616
+ MODEL_EMBEDDING_VERSION = "minilm-l6-v2";
18617
+ pipelinePromise = null;
18618
+ lastError = null;
18619
+ warnedHashFallback = false;
18620
+ }
18621
+ });
18622
+
18623
+ // ../../packages/embedding/src/index.ts
18624
+ function djb2(s) {
18625
+ let h = 5381;
18626
+ for (let i2 = 0; i2 < s.length; i2++) {
18627
+ h = (h << 5) + h + s.charCodeAt(i2) >>> 0;
18628
+ }
18629
+ return h;
18630
+ }
18631
+ function djb2Signed(s) {
18632
+ let h = 0;
18633
+ for (let i2 = 0; i2 < s.length; i2++) {
18634
+ h = h * 31 + s.charCodeAt(i2) | 0;
18635
+ }
18636
+ return h;
18637
+ }
18638
+ function tokenize2(text) {
18639
+ return text.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length > 0 && t.length <= 40);
18640
+ }
18641
+ function* charTrigrams(text) {
18642
+ const s = text.toLowerCase();
18643
+ for (let i2 = 0; i2 <= s.length - 3; i2++) {
18644
+ yield s.slice(i2, i2 + 3);
18645
+ }
18646
+ }
18647
+ function embed(text) {
18648
+ const vec = new Array(EMBEDDING_DIM).fill(0);
18649
+ if (!text) return vec;
18650
+ for (const tok of tokenize2(text)) {
18651
+ const idx = djb2(tok) % EMBEDDING_DIM;
18652
+ const sign = djb2Signed(tok) & 1 ? 1 : -1;
18653
+ vec[idx] = vec[idx] + sign;
18654
+ }
18655
+ for (const tri of charTrigrams(text)) {
18656
+ const idx = djb2("3:" + tri) % EMBEDDING_DIM;
18657
+ const sign = djb2Signed("3:" + tri) & 1 ? 1 : -1;
18658
+ vec[idx] = vec[idx] + 0.5 * sign;
18659
+ }
18660
+ let normSq = 0;
18661
+ for (const x of vec) normSq += x * x;
18662
+ if (normSq <= 0) return vec;
18663
+ const inv = 1 / Math.sqrt(normSq);
18664
+ for (let i2 = 0; i2 < vec.length; i2++) vec[i2] = vec[i2] * inv;
18665
+ return vec;
18666
+ }
18667
+ function cosine(a, b) {
18668
+ if (a.length !== b.length || a.length === 0) return 0;
18669
+ let dot = 0;
18670
+ for (let i2 = 0; i2 < a.length; i2++) dot += a[i2] * b[i2];
18671
+ return dot;
18672
+ }
18673
+ var EMBEDDING_DIM, EMBEDDING_VERSION;
18674
+ var init_src3 = __esm({
18675
+ "../../packages/embedding/src/index.ts"() {
18676
+ "use strict";
18677
+ init_model();
18678
+ EMBEDDING_DIM = 256;
18679
+ EMBEDDING_VERSION = "hash-v1";
18680
+ }
18681
+ });
18682
+
18683
18683
  // ../../packages/local-graph/src/problem-dedup.ts
18684
18684
  function corroborations(n) {
18685
18685
  return Number(n.attrs["corroborations"] ?? 0);
@@ -19276,7 +19276,9 @@ function anchorProblemToWorkingFile(store, problemId, relPath, workspaceId2, ts,
19276
19276
  from: problemId,
19277
19277
  to: file2.id,
19278
19278
  type: "ANCHORED_AT",
19279
- // witnessed = the agent's own declaration, F2-grade; edited = soft heuristic.
19279
+ // witnessed = the agent's own declaration, F2-grade; edited = soft heuristic;
19280
+ // hint-confirmed = a read-grade hint whose file was later edited while the
19281
+ // problem stayed open (AC-hint-upgrade) — same soft tier as edited.
19280
19282
  confidence: provenance === "witnessed" ? 0.4 : 0.3,
19281
19283
  extractionSource: "agent-observed",
19282
19284
  createdAt: ts,
@@ -19296,6 +19298,54 @@ function recordAnchorHint(store, problemId, relPath, provenance, ts) {
19296
19298
  });
19297
19299
  return true;
19298
19300
  }
19301
+ function openAnchorHint(p) {
19302
+ const h = p.attrs["anchorHint"];
19303
+ if (!h || typeof h.path !== "string" || h.upgradedAt) return null;
19304
+ return { path: h.path, ts: typeof h.ts === "number" ? h.ts : 0 };
19305
+ }
19306
+ function consumeAnchorHint(store, p, ts) {
19307
+ const hint = p.attrs["anchorHint"];
19308
+ store.updateNode(p.id, { attrs: { ...p.attrs, anchorHint: { ...hint, upgradedAt: ts } } });
19309
+ deriveContextFromAnchors(store, p.id, ts);
19310
+ }
19311
+ function upgradeAnchorHintsForFile(store, relPath, workspaceId2, ts) {
19312
+ let upgraded = 0;
19313
+ for (const p of store.findNodesByLabel("Problem")) {
19314
+ if (p.validTo != null || p.attrs["resolvedAt"]) continue;
19315
+ const hint = openAnchorHint(p);
19316
+ if (!hint || hint.path !== relPath) continue;
19317
+ if (anchorProblemToWorkingFile(store, p.id, relPath, workspaceId2, ts, "hint-confirmed")) {
19318
+ consumeAnchorHint(store, p, ts);
19319
+ upgraded++;
19320
+ }
19321
+ }
19322
+ return upgraded;
19323
+ }
19324
+ function upgradeAnchorHints(store, workspaceId2, ts) {
19325
+ let upgraded = 0;
19326
+ let standing = 0;
19327
+ const filesByPath = /* @__PURE__ */ new Map();
19328
+ for (const f of store.findNodesByLabel("File")) {
19329
+ if (f.attrs["workspaceId"] && f.attrs["workspaceId"] !== workspaceId2) continue;
19330
+ const rel = typeof f.attrs["relPath"] === "string" ? f.attrs["relPath"] : f.description;
19331
+ if (rel && !filesByPath.has(rel)) filesByPath.set(rel, f);
19332
+ }
19333
+ for (const p of store.findNodesByLabel("Problem")) {
19334
+ if (p.validTo != null || p.attrs["resolvedAt"]) continue;
19335
+ const hint = openAnchorHint(p);
19336
+ if (!hint) continue;
19337
+ standing++;
19338
+ const file2 = filesByPath.get(hint.path.trim().replace(/^\.?\//, ""));
19339
+ const changedAt = file2 ? Number(file2.attrs["contentChangedAt"] ?? 0) : 0;
19340
+ if (changedAt <= hint.ts) continue;
19341
+ if (anchorProblemToWorkingFile(store, p.id, hint.path, workspaceId2, ts, "hint-confirmed")) {
19342
+ consumeAnchorHint(store, p, ts);
19343
+ upgraded++;
19344
+ standing--;
19345
+ }
19346
+ }
19347
+ return { upgraded, standing };
19348
+ }
19299
19349
  function resolveDesignProblemByStatement(store, statement, fixNote, t) {
19300
19350
  const problemId = identityId({ kind: "DesignProblem", statement });
19301
19351
  return closeDesignProblem(store, problemId, fixNote, t);
@@ -19507,6 +19557,7 @@ var init_design_problem = __esm({
19507
19557
  "use strict";
19508
19558
  init_src();
19509
19559
  init_src();
19560
+ init_problem_package_link();
19510
19561
  init_src3();
19511
19562
  init_src2();
19512
19563
  init_problem_package_link();
@@ -22060,6 +22111,22 @@ var init_mechanism_liveness = __esm({
22060
22111
  effectCounter: "corroboratedEdges",
22061
22112
  note: "expected STARVED until VS-corroboration-rate lands \u2014 the channel is genuinely starved"
22062
22113
  },
22114
+ {
22115
+ id: "anchor-hint-upgrade",
22116
+ what: "promotes a read-grade anchor hint once its file is edited while the problem stays open",
22117
+ // The maintenance sweep is the reliable invoker (the harvest seam also
22118
+ // counts into capture's anchorHintsUpgraded, but only on edited turns).
22119
+ pass: "semantic-maintenance",
22120
+ // Conditional stamp: only flagged-during-read Problems carry a hint. 302
22121
+ // held one at mechanism birth (census 2026-08-09) — the fed floor is
22122
+ // "the field exists at all", the revisit-sweep precedent.
22123
+ fed: { labels: ["Problem"], attr: "anchorHint", minFraction: 0 },
22124
+ effectCounter: "anchorHintsUpgraded",
22125
+ // The standing hints ARE the queue — without the gauge, "found nothing"
22126
+ // and "runs forever against work it can never clear" read identically.
22127
+ backlogCounter: "anchorHintsStanding",
22128
+ note: "drains as hinted files change; contentChangedAt is forward-only so the backlog moves with real edits"
22129
+ },
22063
22130
  {
22064
22131
  id: "wm-reinforce-exposure",
22065
22132
  what: "labels each paraphrase re-derivation with the prior's exposure (shown/evicted/unshown)",
@@ -22301,6 +22368,8 @@ __export(src_exports2, {
22301
22368
  toolNodeId: () => toolNodeId,
22302
22369
  toolPriorsFor: () => toolPriorsFor,
22303
22370
  triageOf: () => triageOf,
22371
+ upgradeAnchorHints: () => upgradeAnchorHints,
22372
+ upgradeAnchorHintsForFile: () => upgradeAnchorHintsForFile,
22304
22373
  walk: () => walk,
22305
22374
  wmCalibrationCells: () => wmCalibrationCells
22306
22375
  });
@@ -48046,6 +48115,48 @@ var init_outbox = __esm({
48046
48115
  }
48047
48116
  });
48048
48117
 
48118
+ // src/message-accumulator.ts
48119
+ function createMessageAccumulator(opts = {}) {
48120
+ const ttlMs = opts.ttlMs ?? MESSAGE_BUFFER_TTL_MS;
48121
+ const buffers = /* @__PURE__ */ new Map();
48122
+ const evictStale = (nowMs) => {
48123
+ for (const [id, b] of buffers) {
48124
+ if (nowMs - b.lastAt > ttlMs) buffers.delete(id);
48125
+ }
48126
+ };
48127
+ return {
48128
+ accumulate(messageId, index, delta, isFinal, nowMs) {
48129
+ if (!messageId) return isFinal ? { text: delta } : null;
48130
+ evictStale(nowMs);
48131
+ let b = buffers.get(messageId);
48132
+ if (!b) {
48133
+ b = { chunks: /* @__PURE__ */ new Map(), lastAt: nowMs };
48134
+ buffers.set(messageId, b);
48135
+ }
48136
+ b.chunks.set(index, delta);
48137
+ if (isFinal) b.finalIndex = index;
48138
+ b.lastAt = nowMs;
48139
+ if (b.finalIndex === void 0) return null;
48140
+ for (let i2 = 0; i2 <= b.finalIndex; i2++) {
48141
+ if (!b.chunks.has(i2)) return null;
48142
+ }
48143
+ const text = [...b.chunks.entries()].sort((a, z2) => a[0] - z2[0]).map(([, d]) => d).join("");
48144
+ buffers.delete(messageId);
48145
+ return { text };
48146
+ },
48147
+ size() {
48148
+ return buffers.size;
48149
+ }
48150
+ };
48151
+ }
48152
+ var MESSAGE_BUFFER_TTL_MS;
48153
+ var init_message_accumulator = __esm({
48154
+ "src/message-accumulator.ts"() {
48155
+ "use strict";
48156
+ MESSAGE_BUFFER_TTL_MS = 5 * 60 * 1e3;
48157
+ }
48158
+ });
48159
+
48049
48160
  // src/webui.ts
48050
48161
  var webui_exports = {};
48051
48162
  __export(webui_exports, {
@@ -48056,6 +48167,9 @@ __export(webui_exports, {
48056
48167
  recallForFile: () => recallForFile,
48057
48168
  recallForTool: () => recallForTool
48058
48169
  });
48170
+ function accumulateMessageDelta(messageId, index, delta, isFinal, nowMs) {
48171
+ return messageAccumulator.accumulate(messageId, index, delta, isFinal, nowMs);
48172
+ }
48059
48173
  function fileUriToFsPath(raw2) {
48060
48174
  let p = raw2.replace(/^file:\/\//, "").replace(/\\/g, "/");
48061
48175
  if (/^\/[A-Za-z]:/.test(p)) p = p.slice(1);
@@ -48443,17 +48557,16 @@ function buildWebUi(deps) {
48443
48557
  } catch {
48444
48558
  return c.json({ error: "bad-json" }, 400);
48445
48559
  }
48446
- const text = String(body2["delta"] ?? "");
48560
+ const delta = String(body2["delta"] ?? "");
48447
48561
  const sessionId = String(body2["session_id"] ?? "");
48448
48562
  const messageId = typeof body2["message_id"] === "string" ? body2["message_id"] : void 0;
48449
- if (body2["final"] === false) return c.json({ ok: true, skipped: "partial" });
48450
- if (typeof body2["index"] === "number" && body2["index"] > 0) {
48451
- console.warn(`[errata] MessageDisplay arrived chunked (index ${body2["index"]}) \u2014 delta accumulation needed, text may be partial`);
48563
+ const index = typeof body2["index"] === "number" ? body2["index"] : 0;
48564
+ const isFinal = body2["final"] !== false;
48565
+ const whole = accumulateMessageDelta(messageId, index, delta, isFinal, Date.now());
48566
+ if (whole !== null && whole.text && sessionId && deps.onMessage) {
48567
+ deps.onMessage({ sessionId, text: whole.text, ...messageId ? { messageId } : {} });
48452
48568
  }
48453
- if (text && sessionId && deps.onMessage) {
48454
- deps.onMessage({ sessionId, text, ...messageId ? { messageId } : {} });
48455
- }
48456
- return c.json({ ok: true });
48569
+ return c.json({ ok: true, ...whole === null ? { buffered: true } : {} });
48457
48570
  });
48458
48571
  app.post("/api/session-end", async (c) => {
48459
48572
  let body2;
@@ -48666,7 +48779,7 @@ function proposalToIngest(p, profile, daemonVersion) {
48666
48779
  payloadDigest: p.id
48667
48780
  };
48668
48781
  }
48669
- var wsPackagesCache, WS_PACKAGES_TTL_MS, loggedToolSessions, META_LABELS;
48782
+ var messageAccumulator, wsPackagesCache, WS_PACKAGES_TTL_MS, loggedToolSessions, META_LABELS;
48670
48783
  var init_webui = __esm({
48671
48784
  "src/webui.ts"() {
48672
48785
  "use strict";
@@ -48678,6 +48791,8 @@ var init_webui = __esm({
48678
48791
  init_vfile();
48679
48792
  init_tool_index();
48680
48793
  init_outbox();
48794
+ init_message_accumulator();
48795
+ messageAccumulator = createMessageAccumulator();
48681
48796
  wsPackagesCache = /* @__PURE__ */ new WeakMap();
48682
48797
  WS_PACKAGES_TTL_MS = 6e4;
48683
48798
  loggedToolSessions = /* @__PURE__ */ new Set();
@@ -54685,7 +54800,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
54685
54800
  }
54686
54801
 
54687
54802
  // src/engine.ts
54688
- var DAEMON_VERSION = true ? "2.0.2-dev.612" : "2.0.0-alpha.0";
54803
+ var DAEMON_VERSION = true ? "2.0.2-dev.627" : "2.0.0-alpha.0";
54689
54804
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
54690
54805
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
54691
54806
  var GIT_OP_MUTE_MS = 4e3;
@@ -55411,6 +55526,7 @@ function createWorkspaceEngine(opts) {
55411
55526
  let corroboratedEdges = 0;
55412
55527
  let touchedFileTurns = 0;
55413
55528
  let touchedToolTurns = 0;
55529
+ let anchorHintsUpgraded = 0;
55414
55530
  let linked = 0;
55415
55531
  const t = Date.now();
55416
55532
  let processedTurns = 0;
@@ -55434,6 +55550,12 @@ function createWorkspaceEngine(opts) {
55434
55550
  if (processedTurns++ > 0) await yieldToLoop();
55435
55551
  const turnFile = turn.workingFile ? toRel(turn.workingFile) : void 0;
55436
55552
  const editedTurnFile = turn.editedFile ? toRel(turn.editedFile) : void 0;
55553
+ if (editedTurnFile) {
55554
+ try {
55555
+ anchorHintsUpgraded += upgradeAnchorHintsForFile(store, editedTurnFile, profile.id, t);
55556
+ } catch {
55557
+ }
55558
+ }
55437
55559
  if (opts.sharedStore) {
55438
55560
  try {
55439
55561
  abstracted += harvestAbstractionFences(opts.sharedStore, turn.text, t).applied;
@@ -55957,6 +56079,8 @@ function createWorkspaceEngine(opts) {
55957
56079
  // The sum, so one liveness effectCounter sees an outcome regardless of
55958
56080
  // which cell it landed in (WM-join).
55959
56081
  exposureOutcomes: exposureShown + exposureEvicted + exposureUnshown,
56082
+ // AC-hint-upgrade (harvest seam): edited-this-turn hint promotions.
56083
+ anchorHintsUpgraded,
55960
56084
  touchedFileTurns,
55961
56085
  touchedToolTurns,
55962
56086
  // Seam diagnostic: sessions holding tool-run records at harvest time.
@@ -56219,6 +56343,11 @@ function createWorkspaceEngine(opts) {
56219
56343
  semanticMaintenance() {
56220
56344
  const seqBefore = store.currentIngestSeq();
56221
56345
  const report = runSemanticMaintenance(store);
56346
+ let hintUpgrade = { upgraded: 0, standing: 0 };
56347
+ try {
56348
+ hintUpgrade = upgradeAnchorHints(store, profile.id, Date.now());
56349
+ } catch {
56350
+ }
56222
56351
  appendPassLedger(paths.configDir, "semantic-maintenance", report.durationMs, {
56223
56352
  revisitsCleared: report.revisitsCleared,
56224
56353
  revisitsStanding: report.revisitsStanding,
@@ -56229,7 +56358,9 @@ function createWorkspaceEngine(opts) {
56229
56358
  fixCandidatesStanding: report.fixCandidates.standing,
56230
56359
  designResolved: report.designResolved,
56231
56360
  claimsEvaluated: report.claimsEvaluated,
56232
- seqAdvanced: store.currentIngestSeq() - seqBefore
56361
+ seqAdvanced: store.currentIngestSeq() - seqBefore,
56362
+ anchorHintsUpgraded: hintUpgrade.upgraded,
56363
+ anchorHintsStanding: hintUpgrade.standing
56233
56364
  });
56234
56365
  if (report.revisitsCleared > 0 || report.fixCandidatesSettled > 0 || report.designResolved > 0) {
56235
56366
  refreshContextNow();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.2-dev.612",
3
+ "version": "2.0.2-dev.627",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -25273,7 +25273,6 @@ function markBoth(store2, a, b, patch, ts) {
25273
25273
  // ../../packages/local-graph/src/design-problem.ts
25274
25274
  init_src();
25275
25275
  init_src();
25276
- init_src2();
25277
25276
 
25278
25277
  // ../../packages/local-graph/src/problem-package-link.ts
25279
25278
  init_src();
@@ -25458,6 +25457,9 @@ function backfillProblemContext(store2, ts) {
25458
25457
  return report;
25459
25458
  }
25460
25459
 
25460
+ // ../../packages/local-graph/src/design-problem.ts
25461
+ init_src2();
25462
+
25461
25463
  // ../../packages/local-graph/src/problem-dedup.ts
25462
25464
  init_src();
25463
25465
  init_src();