memhtml 0.2.2 → 0.2.3

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.
package/README.md CHANGED
@@ -410,7 +410,7 @@ envelope. `docs/code-mode.md` is the cookbook, with a measured helper and five r
410
410
  | MemoryAgentBench FactConsolidation single-hop (26KB to 1.1MB stores) | 92% to 97% | ~60% at 26KB only |
411
411
  | MemoryAgentBench FactConsolidation multi-hop | 37% to 49% | ≤7% all methods |
412
412
  | BEAM Contradiction Resolution (100K split, 40 probes) | 43.8% mean | 0% to 5% all systems |
413
- | LongMemEval-S (25-instance smoke) | 68% | ~55% to 65% typical agent baselines |
413
+ | LongMemEval-S (full 500, judged 2026-08-07) | 67.0% | ~55% to 65% typical agent baselines |
414
414
 
415
415
  Read the cross-judge numbers as reference points rather than as a ranking: the judges here are verbatim
416
416
  prompt ports running haiku-4.5, where the papers used gpt-4o and gpt-4.1-mini. `ROADMAP.md` carries these
@@ -422,7 +422,7 @@ numbers and the horizons they rank.
422
422
  $MEMHTML_ROOT/ # its own git repo, one global memory store
423
423
  projects/<workspace-slug>/ # a workspace IS a directory. There is no workspaces table.
424
424
  areas/<area-slug>/ # ongoing responsibilities
425
- areas/arcs/ # behavioural arcs (system-written by sleep only)
425
+ areas/arcs/ # behavioral arcs (system-written by sleep only)
426
426
  areas/inbox/ # where an unplaceable memory lands
427
427
  resources/<topic>/
428
428
  resources/people/<person>.html # the person plane
@@ -441,10 +441,12 @@ The layering is strict and TypeScript project references enforce it. `@memhtml/c
441
441
  `@memhtml/domain` import `effect` and nothing else, and a test reads `domain`'s own `dist` to confirm it
442
442
  names no database driver, no SDK, and no `node:fs`.
443
443
 
444
- None of them is published. All twelve are `private`, and `mise run package:assemble` bundles them into
445
- the single `memhtml` package that carries the two binaries so the table below is a map of the source,
446
- not a list of things to install. `RELEASING.md` covers how the artifact is built and what must stay
447
- outside the bundle.
444
+ None of them is published. Every workspace package is `private`, and `mise run package:assemble`
445
+ bundles the libraries and the binary-bearing apps into the single `memhtml` package that carries the
446
+ two binaries the docs site and the integration-test harness stay outside the bundle
447
+ (`tsdown.config.ts` names the exact set). The table below is a map of the source, not a list of
448
+ things to install. `RELEASING.md` covers how the artifact is built and what must stay outside the
449
+ bundle.
448
450
 
449
451
  | Package | What it owns |
450
452
  |---|---|
@@ -459,6 +461,8 @@ outside the bundle.
459
461
  | `@memhtml/eval` | The fixture corpus generator and the refusable discrimination gate. |
460
462
  | `@memhtml/cli` | The `memhtml` binary, the envelope contract, and the one composition root. |
461
463
  | `@memhtml/mcp` | The `memhtml-mcp` stdio server: 14 tools, 2 resources. |
464
+ | `@memhtml/consolidator` | The sandboxed eve agent that distills candidate memories from raw transcripts. |
465
+ | `@memhtml/docs` | The documentation site. |
462
466
 
463
467
  ## Development
464
468
 
@@ -35,7 +35,7 @@ import { runVerifierConfig } from "../../src/run-auth.js"
35
35
  * and eve rejects a token with no `sub` before consulting any matcher. That is what keeps a secret
36
36
  * leaked into some other eve app's environment from cross-authenticating here.
37
37
  *
38
- * ## The bind address STAYS, as defence in depth
38
+ * ## The bind address STAYS, as defense in depth
39
39
  *
40
40
  * `eve start` binds ALL INTERFACES by default (node_modules/eve/docs/reference/cli.md, `eve start
41
41
  * --host`), so `src/client.ts` still spawns with `--host 127.0.0.1` from a constant that takes no
@@ -1,3 +1,3 @@
1
- import { A as MAX_QUOTE_CHARS, C as ConsolidationResult, D as ConsolidatorUnavailable, E as ConsolidatorRunFailed, F as toJsonSchema, I as ungroundedEvidenceReason, M as credentialsMissingReason, N as hasConsolidatorCredentials, O as MAX_CLAIM_CHARS, P as isConsolidationKind, S as ConsolidationPayload, T as ConsolidatorCredentialsMissing, _ as readOnlyRootsProblem, a as RUN_SECRET_ENV, b as CandidateEvidence, c as runVerifierConfig, d as SANDBOX_MOUNTS_ENV, f as SandboxMountInvalid, g as pinCorpusSnapshot, h as mountReadOnlyRoots, i as makeConsolidator, j as MAX_TRANSCRIPTS_PER_RUN, k as MAX_GIST_CHARS, l as sameRunSecret, m as encodeSandboxMounts, n as consolidatorLive, o as mintRunSecret, p as decodeSandboxMounts, r as guestPathFor, s as runSecretFrom, t as Consolidator, u as signRunToken, v as CONSOLIDATION_KINDS, w as ConsolidatorContractViolation, x as CandidateMemory, y as CONSOLIDATION_OUTPUT_JSON_SCHEMA } from "./dist-CI2-0MRk.mjs";
1
+ import { A as MAX_QUOTE_CHARS, C as ConsolidationResult, D as ConsolidatorUnavailable, E as ConsolidatorRunFailed, F as toJsonSchema, I as ungroundedEvidenceReason, M as credentialsMissingReason, N as hasConsolidatorCredentials, O as MAX_CLAIM_CHARS, P as isConsolidationKind, S as ConsolidationPayload, T as ConsolidatorCredentialsMissing, _ as readOnlyRootsProblem, a as RUN_SECRET_ENV, b as CandidateEvidence, c as runVerifierConfig, d as SANDBOX_MOUNTS_ENV, f as SandboxMountInvalid, g as pinCorpusSnapshot, h as mountReadOnlyRoots, i as makeConsolidator, j as MAX_TRANSCRIPTS_PER_RUN, k as MAX_GIST_CHARS, l as sameRunSecret, m as encodeSandboxMounts, n as consolidatorLive, o as mintRunSecret, p as decodeSandboxMounts, r as guestPathFor, s as runSecretFrom, t as Consolidator, u as signRunToken, v as CONSOLIDATION_KINDS, w as ConsolidatorContractViolation, x as CandidateMemory, y as CONSOLIDATION_OUTPUT_JSON_SCHEMA } from "./dist-t84Q_98w.mjs";
2
2
 
3
3
  export { CONSOLIDATION_KINDS, CONSOLIDATION_OUTPUT_JSON_SCHEMA, CandidateEvidence, CandidateMemory, ConsolidationPayload, ConsolidationResult, Consolidator, ConsolidatorContractViolation, ConsolidatorCredentialsMissing, ConsolidatorRunFailed, ConsolidatorUnavailable, MAX_CLAIM_CHARS, MAX_GIST_CHARS, MAX_QUOTE_CHARS, MAX_TRANSCRIPTS_PER_RUN, RUN_SECRET_ENV, SANDBOX_MOUNTS_ENV, SandboxMountInvalid, consolidatorLive, credentialsMissingReason, decodeSandboxMounts, encodeSandboxMounts, guestPathFor, hasConsolidatorCredentials, isConsolidationKind, makeConsolidator, mintRunSecret, mountReadOnlyRoots, pinCorpusSnapshot, readOnlyRootsProblem, runSecretFrom, runVerifierConfig, sameRunSecret, signRunToken, toJsonSchema, ungroundedEvidenceReason };
@@ -1,4 +1,4 @@
1
- import { $ as MEMORY_EXTENSION, B as ModelUnavailable, Ct as slugify, H as StorageFailure, J as relClassFor, L as DirtyTree, Q as INBOX_DIR, R as InvalidMemory, St as filenameFor, U as WriteConflict, V as PathNotFound, W as EdgeRel, X as relTokenFor, Y as relForToken, Z as ARCS_DIR, _t as TaskStatus, at as memoryPathFor, bt as parseEntity, ct as placementFor, dt as MEMORY_TYPES, et as PEOPLE_DIR, ft as MemoryStatus, gt as TASK_STATUSES, ht as PERSON_ENTITY_PREFIX, it as isValidMemoryPath, lt as Confidence, mt as PARA_BUCKETS, nt as archivePathFor, ot as normalizePath, pt as MemoryType, q as isEdgeRel, rt as isArchivePath, st as paraBucketOf, ut as Importance, vt as WRITABLE_MEMORY_TYPES, wt as withCollisionOrdinal, xt as SLUG_FALLBACK, yt as isTaskStatus, z as LlmContractViolation } from "./dist-CI2-0MRk.mjs";
1
+ import { $ as MEMORY_EXTENSION, B as ModelUnavailable, Ct as slugify, H as StorageFailure, J as relClassFor, L as DirtyTree, Q as INBOX_DIR, R as InvalidMemory, St as filenameFor, U as WriteConflict, V as PathNotFound, W as EdgeRel, X as relTokenFor, Y as relForToken, Z as ARCS_DIR, _t as TaskStatus, at as memoryPathFor, bt as parseEntity, ct as placementFor, dt as MEMORY_TYPES, et as PEOPLE_DIR, ft as MemoryStatus, gt as TASK_STATUSES, ht as PERSON_ENTITY_PREFIX, it as isValidMemoryPath, lt as Confidence, mt as PARA_BUCKETS, nt as archivePathFor, ot as normalizePath, pt as MemoryType, q as isEdgeRel, rt as isArchivePath, st as paraBucketOf, ut as Importance, vt as WRITABLE_MEMORY_TYPES, wt as withCollisionOrdinal, xt as SLUG_FALLBACK, yt as isTaskStatus, z as LlmContractViolation } from "./dist-t84Q_98w.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import { Config, Context, Effect, Layer, Result, Schedule, Schema } from "effect";
4
4
  import { mkdir, mkdtemp, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
@@ -327,7 +327,7 @@ const pagerank = (nodes, edges, options = {}) => {
327
327
  * Communities by label propagation over the edge list read as undirected.
328
328
  *
329
329
  * Deterministic in place of a seed: nodes start labelled by themselves, sweeps visit them in
330
- * sorted order, and a node adopts the highest-weighted neighbouring label with the
330
+ * sorted order, and a node adopts the highest-weighted neighboring label with the
331
331
  * lexicographically smallest label breaking a tie. The returned labels are canonicalized to
332
332
  * the smallest member path of each community, so the partition itself is reproducible and not
333
333
  * only the grouping.
@@ -340,15 +340,15 @@ const labelPropagation = (nodes, edges, options = {}) => {
340
340
  const { sorted, folded } = normalize$1(nodes, edges);
341
341
  const minSize = options.minCommunitySize ?? 3;
342
342
  const maxSweeps = options.maxSweeps ?? 100;
343
- const neighbours = /* @__PURE__ */ new Map();
343
+ const neighbors = /* @__PURE__ */ new Map();
344
344
  const link = (from, to, strength) => {
345
- const bucket = neighbours.get(from);
345
+ const bucket = neighbors.get(from);
346
346
  const edge = {
347
347
  src: from,
348
348
  dst: to,
349
349
  strength
350
350
  };
351
- if (bucket === void 0) neighbours.set(from, [edge]);
351
+ if (bucket === void 0) neighbors.set(from, [edge]);
352
352
  else bucket.push(edge);
353
353
  };
354
354
  for (const edge of folded) {
@@ -360,7 +360,7 @@ const labelPropagation = (nodes, edges, options = {}) => {
360
360
  let changed = false;
361
361
  for (const node of sorted) {
362
362
  const weightByLabel = /* @__PURE__ */ new Map();
363
- for (const edge of neighbours.get(node) ?? []) {
363
+ for (const edge of neighbors.get(node) ?? []) {
364
364
  const label = labels.get(edge.dst);
365
365
  if (label === void 0) continue;
366
366
  weightByLabel.set(label, (weightByLabel.get(label) ?? 0) + edge.strength);
@@ -1874,7 +1874,7 @@ const buildProbes = (base, wanted) => {
1874
1874
  * the cosine. Measured before this was fixed: the kit-free control took FTS rank 1 and vector
1875
1875
  * rank 3 while its target sat at 4 and 10, on 22 of 36 probes. The gate was failing on
1876
1876
  * document length instead of on the fact. A control that wins by being terser proves nothing
1877
- * about discrimination, and a fold that "fixed" it would be tuned against an artefact.
1877
+ * about discrimination, and a fold that "fixed" it would be tuned against an artifact.
1878
1878
  *
1879
1879
  * With the kit copied, the pair differs by exactly the flipped token, which is the
1880
1880
  * high-cosine wrong-fact adversary design §5 asks for.
@@ -1956,7 +1956,7 @@ const ACCESSED_FRACTION = .6;
1956
1956
  * happens to be some probe's control.
1957
1957
  * 2. **The spread is QUERY-BLIND.** It is a function of the corpus seed and the path order. Nothing
1958
1958
  * here reads the probe list, so a target's history is whatever its position in the corpus earns it.
1959
- * A spread that favoured targets would make the gate pass by construction.
1959
+ * A spread that favored targets would make the gate pass by construction.
1960
1960
  *
1961
1961
  * The distribution is a long tail, `1 / (floor + jitter)`, because that is the shape retrieval traffic
1962
1962
  * has: a handful of memories are read constantly and most are read once. A uniform count would make
@@ -4303,7 +4303,7 @@ const text = (result) => result.stdout.toString("utf8");
4303
4303
  /**
4304
4304
  * The service against a repository root. Exported rather than only wrapped in a layer, because every
4305
4305
  * test in this package drives the real git binary against a temp-dir repo. A fake git
4306
- * verifies the shape of these calls and not git's own behaviour, and it is git's behaviour
4306
+ * verifies the shape of these calls and not git's own behavior, and it is git's behavior
4307
4307
  * (rename detection, index staging, merge conflict stages) that this package exists to use.
4308
4308
  */
4309
4309
  const makeGit = (root) => ({
@@ -4661,7 +4661,7 @@ const subjectFor = (pending) => pending.length === 1 && pending[0] !== void 0 ?
4661
4661
  const hasProvenance = (entry) => Object.keys(provenanceTrailers(entry.input)).length > 0;
4662
4662
  /**
4663
4663
  * The store over a git service. Exported so tests build it against a temp-dir repo with the
4664
- * real git binary. This package's job IS git's behaviour, so a fake git would verify only that
4664
+ * real git binary. This package's job IS git's behavior, so a fake git would verify only that
4665
4665
  * the right strings were assembled and would miss every state transition that matters.
4666
4666
  */
4667
4667
  const makeStore = (git, hooks = {}) => {
@@ -5999,7 +5999,7 @@ const IndexGit = Context.Service("memhtml/IndexGit");
5999
5999
  * `onExcessProperty: "error"` means a column added to the SELECT without being added here is a
6000
6000
  * decode failure, not a silently ignored field. Probed 2026-08-12 on node 24.19.0: `node:sqlite`
6001
6001
  * hands back null-prototype records and `Schema.decodeUnknownEffect` reads them correctly, so the
6002
- * driver's row objects need no normalisation at this seam.
6002
+ * driver's row objects need no normalization at this seam.
6003
6003
  */
6004
6004
  /**
6005
6005
  * Every column of `index_state`, in the order `0007_watermark.sql` declares them.
@@ -7264,7 +7264,7 @@ const assembleScope = (scope = {}) => {
7264
7264
  const types = (scope.memoryTypes ?? []).filter((type) => MEMORY_TYPES.includes(type));
7265
7265
  if (types.length > 0)
7266
7266
  /**
7267
- * A caller-named type list is honoured VERBATIM, `task` included. Filtering `task` back out of
7267
+ * A caller-named type list is honored VERBATIM, `task` included. Filtering `task` back out of
7268
7268
  * an explicit list would make the opt-in unreachable, and there would then be no way to search
7269
7269
  * tasks at all. The exclusion is a default and not a firewall. (The firewalls in this system are
7270
7270
  * `edge_class` and the trace tables, and both reject a write rather than defaulting.)
@@ -7860,7 +7860,7 @@ const modelFailure = (modelId, cause) => ModelUnavailable.make({
7860
7860
  * One InvokeModel round trip: send the body, decode the JSON payload. Both the transport
7861
7861
  * rejection and an unparseable payload land on `ModelUnavailable`, because neither one
7862
7862
  * says anything about the model's answer. They say only that no answer arrived. Reading
7863
- * the answer, and judging whether it honours its contract, is the caller's job.
7863
+ * the answer, and judging whether it honors its contract, is the caller's job.
7864
7864
  */
7865
7865
  const invokeJson = (client, modelId, body) => Effect.gen(function* () {
7866
7866
  const response = yield* Effect.tryPromise({
@@ -8928,7 +8928,7 @@ const ArcPlanEntry = Schema.Struct({
8928
8928
  * slug would be a model-chosen file path.
8929
8929
  */
8930
8930
  slug: Schema.String,
8931
- /** A concise behavioural-principal name, 3-8 words. */
8931
+ /** A concise behavioral-principal name, 3-8 words. */
8932
8932
  title: Schema.String,
8933
8933
  action: ArcAction,
8934
8934
  /** One or two sentences naming what changed or emerged. */
@@ -8973,34 +8973,34 @@ memory, so when the two claims COULD both be true — different scope, different
8973
8973
  aspect — answer neutral, not contradicts. Rate your confidence honestly and name the specific
8974
8974
  conflicting or compatible claims in the rationale.`;
8975
8975
  /** The arc-triage system prompt: plan only, no content. */
8976
- const ARC_TRIAGE_SYSTEM = `You triage behavioural arcs for an AI agent's long-term memory system. This is the planning pass:
8976
+ const ARC_TRIAGE_SYSTEM = `You triage behavioral arcs for an AI agent's long-term memory system. This is the planning pass:
8977
8977
  a second pass writes each arc's content, so your output is only the plan.
8978
8978
 
8979
8979
  - Assign every existing arc an action of update or skip. An arc omitted from the plan stays stale.
8980
- - Propose create only when a genuinely new behavioural pattern emerges that no existing arc covers.
8980
+ - Propose create only when a genuinely new behavioral pattern emerges that no existing arc covers.
8981
8981
  - Propose update only when the evidence materially changes or reinforces the arc. Each update costs
8982
8982
  a model call, so skip trivial or redundant evidence.
8983
8983
  - Keep evidenceKeys to the strongest 1-5 supporting memories per arc.
8984
- - Titles are concise behavioural-principal names of 3-8 words.
8984
+ - Titles are concise behavioral-principal names of 3-8 words.
8985
8985
  - Rationale is one or two sentences naming what changed or emerged.
8986
8986
  - Leave slug empty on a create.`;
8987
8987
  /** The arc-execute system prompt: one arc's content. */
8988
- const ARC_EXECUTE_SYSTEM = `You write one behavioural arc for an AI agent's long-term memory system. An arc is a self-contained
8989
- behavioural principal — a statement of a pattern, preference, or principle the agent developed
8988
+ const ARC_EXECUTE_SYSTEM = `You write one behavioral arc for an AI agent's long-term memory system. An arc is a self-contained
8989
+ behavioral principal — a statement of a pattern, preference, or principle the agent developed
8990
8990
  through experience. Arcs are read back in future sessions with no transcript context, so the
8991
8991
  content must stand alone.
8992
8992
 
8993
- - claim is the ONE load-bearing sentence: the principle itself, stated as behaviour to adopt.
8994
- - paragraphs holds 2-12 sentences across one to four paragraphs. Behavioural principles fit at the
8993
+ - claim is the ONE load-bearing sentence: the principle itself, stated as behavior to adopt.
8994
+ - paragraphs holds 2-12 sentences across one to four paragraphs. Behavioral principles fit at the
8995
8995
  tight end; an operational playbook may span the wider range.
8996
- - Use IF/THEN conditional phrasing for rules, framed positively around the behaviour to adopt.
8996
+ - Use IF/THEN conditional phrasing for rules, framed positively around the behavior to adopt.
8997
8997
  - When updating, incorporate both the existing content and the new evidence, preserving knowledge
8998
8998
  that still holds.
8999
- - Keep references like "the evidence" or "recent sessions" out of the text — name the behaviour.
8999
+ - Keep references like "the evidence" or "recent sessions" out of the text — name the behavior.
9000
9000
  - The content reads as a stable identity statement, not a changelog.`;
9001
9001
  /** The compress-synthesis system prompt. */
9002
9002
  const COMPRESS_SYSTEM = `You fold a group of related memories into ONE canonical memory for an AI agent's long-term memory
9003
- system. The members are near-neighbours in one community of the memory graph; the canonical replaces
9003
+ system. The members are near-neighbors in one community of the memory graph; the canonical replaces
9004
9004
  them, and each member you list in absorbedKeys is archived once the canonical is written.
9005
9005
 
9006
9006
  - claim is the ONE load-bearing sentence the group shares.
@@ -9016,13 +9016,13 @@ const dataBlock = (label, text) => wrapAsData(label, text);
9016
9016
  * The stance judge's user turn for one pair. Both texts are wrapped; neither carries a path.
9017
9017
  *
9018
9018
  * The prompt names no path, no cosine, and no prior verdict, so the model cannot infer which answer
9019
- * the caller is hoping for and cannot recognise a pair it judged last night.
9019
+ * the caller is hoping for and cannot recognize a pair it judged last night.
9020
9020
  */
9021
9021
  const stancePrompt = (textA, textB) => `${dataBlock("memory_a", textA)}\n\n${dataBlock("memory_b", textB)}\n\nDo these two memories contradict each other? Give your verdict, your confidence, and a rationale naming the specific claims that conflict or why they are compatible.`;
9022
9022
  /** The arc-triage user turn: the live arcs and the recent evidence, both wrapped. */
9023
- const arcTriagePrompt = (arcsText, evidenceText) => `${dataBlock("current_arcs", arcsText)}\n\n${dataBlock("evidence", evidenceText)}\n\nProduce a triage plan. Assign update or skip to every existing arc, and add a create entry for any genuinely new behavioural pattern the existing arcs do not cover.`;
9023
+ const arcTriagePrompt = (arcsText, evidenceText) => `${dataBlock("current_arcs", arcsText)}\n\n${dataBlock("evidence", evidenceText)}\n\nProduce a triage plan. Assign update or skip to every existing arc, and add a create entry for any genuinely new behavioral pattern the existing arcs do not cover.`;
9024
9024
  /** The arc-execute user turn for one arc. `current` is absent on a create. */
9025
- const arcExecutePrompt = (input) => (input.current === void 0 ? `${dataBlock("new_arc_title", input.title)}\n\n` : `${dataBlock("existing_arc", input.current)}\n\n`) + `${dataBlock("evidence", input.evidenceText)}\n\n${dataBlock("triage_rationale", input.rationale)}\n\n` + (input.current === void 0 ? "Synthesize a new behavioural principal from this evidence." : "Update the arc to incorporate the new evidence, preserving existing knowledge that holds.");
9025
+ const arcExecutePrompt = (input) => (input.current === void 0 ? `${dataBlock("new_arc_title", input.title)}\n\n` : `${dataBlock("existing_arc", input.current)}\n\n`) + `${dataBlock("evidence", input.evidenceText)}\n\n${dataBlock("triage_rationale", input.rationale)}\n\n` + (input.current === void 0 ? "Synthesize a new behavioral principal from this evidence." : "Update the arc to incorporate the new evidence, preserving existing knowledge that holds.");
9026
9026
  /** The compress user turn for one batch: every member's text, wrapped, under its offered key. */
9027
9027
  const compressPrompt = (members) => `${members.map((member) => dataBlock(`member_${member.key}`, member.text)).join("\n\n")}\n\nFold these memories into one canonical memory. List in absorbedKeys exactly the members whose content the canonical carries forward.`;
9028
9028
  /**
@@ -9081,11 +9081,11 @@ const activeCorpus = (db) => db.all(`SELECT path, memory_type, title, gist, body
9081
9081
  word_count, created_at, updated_at, valid_until, reprieves
9082
9082
  FROM files WHERE archived = 0 ORDER BY created_at ASC, path ASC`);
9083
9083
  /**
9084
- * Per-source top-`k` nearest neighbours above a similarity floor, over first-chunk vectors.
9084
+ * Per-source top-`k` nearest neighbors above a similarity floor, over first-chunk vectors.
9085
9085
  *
9086
9086
  * `ordinal = 0` collapses a file to its first chunk, not its best chunk. The format is one
9087
9087
  * fact per file, so almost every file is a single chunk. Taking the first keeps the pair set
9088
- * symmetric, which `min(distance)` over all chunks would not. An asymmetric neighbourhood
9088
+ * symmetric, which `min(distance)` over all chunks would not. An asymmetric neighborhood
9089
9089
  * would make `(a, b)` a candidate while `(b, a)` is not, so which of two files was read first
9090
9090
  * would decide whether they merge.
9091
9091
  *
@@ -9094,7 +9094,7 @@ const activeCorpus = (db) => db.all(`SELECT path, memory_type, title, gist, body
9094
9094
  * SQL function over two `Uint8Array` arguments (`packages/index/src/database.ts`) and not a driver
9095
9095
  * builtin with a fixed calling shape.
9096
9096
  */
9097
- const neighbourPairs = (db, options) => {
9097
+ const neighborPairs = (db, options) => {
9098
9098
  const excluded = options.excludeTypes ?? [];
9099
9099
  const typeFilter = excluded.length === 0 ? "" : ` AND f.memory_type NOT IN (${excluded.map(() => "?").join(", ")})`;
9100
9100
  return db.all(`WITH vecs AS (
@@ -9555,7 +9555,7 @@ const runRetentionPass = (db, at) => Effect.gen(function* () {
9555
9555
  * `update`/`create` entries cost a second call.
9556
9556
  *
9557
9557
  * **One commit per arc, not one for the phase.** An arc is a standalone assertion about the agent's
9558
- * own behaviour, and a reviewer reads it as one thing; a commit carrying four unrelated arcs is a
9558
+ * own behavior, and a reviewer reads it as one thing; a commit carrying four unrelated arcs is a
9559
9559
  * commit nobody reviews. It also means a model failure on the third arc leaves the first two
9560
9560
  * committed, so the per-item isolation reaches the git history and not only the counters.
9561
9561
  *
@@ -10000,7 +10000,7 @@ const confidenceDecay = (env) => Effect.gen(function* () {
10000
10000
  */
10001
10001
  /** The moderate similarity floor a pair must clear to be worth a model call. */
10002
10002
  const CONFLICT_COSINE_FLOOR = .8;
10003
- /** Nearest same-entity neighbours considered per source. */
10003
+ /** Nearest same-entity neighbors considered per source. */
10004
10004
  const CONFLICT_PER_SOURCE_K = 5;
10005
10005
  /** Pairs judged per cycle. The model-cost guard. */
10006
10006
  const CONFLICT_CANDIDATE_LIMIT = 200;
@@ -10143,7 +10143,7 @@ const dedupMerge = (env) => Effect.gen(function* () {
10143
10143
  * The `files_content_hash_active` index carves tasks out for the same reason, so structural and
10144
10144
  * semantic dedup agree about them.
10145
10145
  */
10146
- const pairs = yield* neighbourPairs(env.deps.db, {
10146
+ const pairs = yield* neighborPairs(env.deps.db, {
10147
10147
  floor: NEAR_DUPLICATE_THRESHOLD,
10148
10148
  perSourceK: 5,
10149
10149
  limit: 100 * 4,
@@ -10714,7 +10714,7 @@ const preflight = (env) => Effect.gen(function* () {
10714
10714
  */
10715
10715
  /** The similarity floor a pair must clear to become a mined `relates_to`. */
10716
10716
  const MINING_COSINE_FLOOR = .85;
10717
- /** Nearest neighbours considered per source file. */
10717
+ /** Nearest neighbors considered per source file. */
10718
10718
  const MINING_PER_SOURCE_K = 5;
10719
10719
  /** Pairs mined per cycle. The cost guard on a corpus whose pair space is quadratic. */
10720
10720
  const MINING_SAMPLE_LIMIT = 2e3;
@@ -10726,7 +10726,7 @@ const relationshipMining = (env) => Effect.gen(function* () {
10726
10726
  * count. The `edges` CHECK cannot refuse it, because `relates_to` under `memory` is a
10727
10727
  * well-formed edge whatever files sit at its ends.
10728
10728
  */
10729
- const pairs = yield* neighbourPairs(env.deps.db, {
10729
+ const pairs = yield* neighborPairs(env.deps.db, {
10730
10730
  floor: MINING_COSINE_FLOOR,
10731
10731
  perSourceK: 5,
10732
10732
  limit: MINING_SAMPLE_LIMIT,
@@ -10882,7 +10882,7 @@ const headOf = (env) => env.deps.git.revParseHead().pipe(Effect.map((sha) => sha
10882
10882
  * and re-assert the fact deliberately.
10883
10883
  *
10884
10884
  * **Arcs are exempt.** An arc is system-written and carries no meaningful TTL; expiring one on age
10885
- * would delete the agent's own behavioural identity on a schedule.
10885
+ * would delete the agent's own behavioral identity on a schedule.
10886
10886
  */
10887
10887
  const reprieve = (env) => Effect.gen(function* () {
10888
10888
  const expired = (yield* runRetentionPass(env.deps.db, env.at)).scored.filter((entry) => {
@@ -11459,7 +11459,7 @@ const traceConsolidation = (env) => Effect.gen(function* () {
11459
11459
  skipped,
11460
11460
  conflicts: conflicted
11461
11461
  };
11462
- const commitSha = yield* commitPhase(env, "trace-consolidation", `${conflict === void 0 ? "distil" : "distil (frame conflict)"} ${title}`, counts, commitContextFor(candidate, conflict));
11462
+ const commitSha = yield* commitPhase(env, "trace-consolidation", `${conflict === void 0 ? "distill" : "distill (frame conflict)"} ${title}`, counts, commitContextFor(candidate, conflict));
11463
11463
  if (commitSha !== null) lastCommit = commitSha;
11464
11464
  written += 1;
11465
11465
  }
@@ -12847,4 +12847,4 @@ const latest = (left, right) => left === null ? right : right === null ? left :
12847
12847
 
12848
12848
  //#endregion
12849
12849
  export { STATE_SIDECAR_PATH as $, makeIndexRecorder as A, makeGitPort as B, ModelClientLive as C, EMBED_DIM as D, EmbeddingsLive as E, reinforce as F, STATE_MIGRATIONS_DIR as G, DatabaseService as H, Indexer as I, expandRoot as J, STATE_SCHEMA as K, makeIndexer as L, readWatermark as M, Retrieval as N, EMBED_WATERMARK as O, makeRetrieval as P, STATE_DB_PATH as Q, readIndexState as R, ModelClient as S, Embeddings as T, makeDatabase as U, sanitizeFtsQuery as V, MIGRATIONS_DIR as W, INDEX_DB_PATH as X, makeStore as Y, SLEEP_REPORTS_DIR as Z, unlink as _, parseSidecar as a, commitSubject as at, discriminationGate as b, generateArtifacts as c, isValidDatetime as ct, danglingEdges as d, REINFORCE_SIGNALS as dt, attemptIo as et, publishRows as f, frameKeyOf as ft, meta as g, link as h, makeSleep as i, makeGit as it, persistScanned as j, IndexRecorder as k, accessRows as l, closesFence as lt, hrefFor as m, scanTraceRoot as n, readFileOrNull as nt, renderSidecar as o, checkMemory as ot, applyHeadEdits as p, Store as q, Sleep as r, Git as rt, archivedFormOf as s, setMeta as st, mergeTailExtract as t, initRepo as tt, allPaths as u, fenceOpeningOf as ut, SLEEP_PHASES as v, wrapAsData as w, runDiscrimination as x, isSleepPhase as y, IndexGit as z };
12850
- //# sourceMappingURL=dist-0IU3R2cD.mjs.map
12850
+ //# sourceMappingURL=dist-dfrcDFad.mjs.map