@elvisw/dsh-magic-context 0.0.0-stage → 0.13.0

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 (66) hide show
  1. package/LICENSE +23 -0
  2. package/NOTICE +93 -0
  3. package/README.md +452 -2
  4. package/README.zh-CN.md +368 -0
  5. package/cordis.patch.yml +20 -0
  6. package/lib/client.js +2270 -0
  7. package/lib/core/compartments.js +424 -0
  8. package/lib/core/corpus-store.js +176 -0
  9. package/lib/core/directive-detect.js +147 -0
  10. package/lib/core/domain-reconcile.js +394 -0
  11. package/lib/core/domains.js +127 -0
  12. package/lib/core/embedding-local.js +247 -0
  13. package/lib/core/global-autostage.js +223 -0
  14. package/lib/core/global-domains.js +302 -0
  15. package/lib/core/journal.js +248 -0
  16. package/lib/core/llm-deadline.js +53 -0
  17. package/lib/core/machine-domain.js +106 -0
  18. package/lib/core/maintenance.js +380 -0
  19. package/lib/core/memory-bridge.js +818 -0
  20. package/lib/core/memory-categories.js +84 -0
  21. package/lib/core/memory-scoring.js +65 -0
  22. package/lib/core/memory-search.js +414 -0
  23. package/lib/core/memory-write.js +1176 -0
  24. package/lib/core/policy.js +111 -0
  25. package/lib/core/profile-confirmation.js +55 -0
  26. package/lib/core/profile-review.js +375 -0
  27. package/lib/core/profile-write.js +283 -0
  28. package/lib/core/reference-seeds.js +63 -0
  29. package/lib/core/route-health.js +106 -0
  30. package/lib/core/stores.js +1021 -0
  31. package/lib/core/tagger.js +7 -0
  32. package/lib/core/types.js +15 -0
  33. package/lib/core/vector-backfill.js +140 -0
  34. package/lib/core/vector-lane.js +184 -0
  35. package/lib/dsh/command-surface.js +376 -0
  36. package/lib/dsh/compaction-engine.js +231 -0
  37. package/lib/dsh/config-switches.js +56 -0
  38. package/lib/dsh/config.js +13 -0
  39. package/lib/dsh/context-pressure.js +36 -0
  40. package/lib/dsh/drop-landing.js +42 -0
  41. package/lib/dsh/emergency.js +89 -0
  42. package/lib/dsh/flush-command.js +148 -0
  43. package/lib/dsh/global-review.js +412 -0
  44. package/lib/dsh/historian.js +907 -0
  45. package/lib/dsh/live-journal.js +81 -0
  46. package/lib/dsh/maintenance-wiring.js +229 -0
  47. package/lib/dsh/management-pass.js +564 -0
  48. package/lib/dsh/memory-lane.js +535 -0
  49. package/lib/dsh/pre-step.js +675 -0
  50. package/lib/dsh/project-drift.js +116 -0
  51. package/lib/dsh/recomp.js +192 -0
  52. package/lib/dsh/reduce-guidance.js +188 -0
  53. package/lib/dsh/seams.js +588 -0
  54. package/lib/dsh/search-hint.js +186 -0
  55. package/lib/dsh/session-notice.js +100 -0
  56. package/lib/dsh/status-command.js +75 -0
  57. package/lib/dsh/telemetry.js +349 -0
  58. package/lib/dsh/tool-bridge.js +1009 -0
  59. package/lib/dsh/volatile.js +89 -0
  60. package/lib/index.js +931 -0
  61. package/package.json +108 -4
  62. package/tools/migrate-profile-package-name.mjs +317 -0
  63. package/vendor/onnx/LICENSE +27 -0
  64. package/vendor/onnx/ort-wasm-simd-threaded.mjs +59 -0
  65. package/vendor/onnx/ort-wasm-simd-threaded.wasm +0 -0
  66. package/vendor/onnx/ort.node.min.mjs +8 -0
@@ -0,0 +1,7 @@
1
+ export function tagPrefix(tagNumber) {
2
+ return `§${tagNumber}§ `;
3
+ }
4
+ /** Allocate (idempotently) a tag for one target in one session. */
5
+ export function ensureTag(stores, sessionId, target, now = Date.now()) {
6
+ return stores.allocateTag(sessionId, target, now);
7
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Neutral vocabulary shared by the DSH adapter's core logic.
3
+ *
4
+ * NOTHING in `src/core` may import from `@deepseek-ai/*`. The DSH contact
5
+ * surface lives entirely in `src/dsh/`; translation between the two
6
+ * vocabularies happens there. This is the upgrade-insulation contract:
7
+ * when DSH iterates, only `src/dsh/` changes; when Magic Context core is
8
+ * wired in (Phase 1+), it is consumed through its existing host seams and
9
+ * this package's stores, never through DSH types.
10
+ */
11
+ /** The one error-to-text spelling: every catch that logs or journals a
12
+ * failure composes its message through this, never by re-testing the shape. */
13
+ export function errText(error) {
14
+ return error instanceof Error ? error.message : String(error);
15
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * WP11 — filling the vector lane.
3
+ *
4
+ * Magic Context used to own `memory_embeddings` and refill it. That job left
5
+ * with it, and the consequence is measurable: on 2026-10-10 the live store had
6
+ * 1224 active memories, 820 embedded (67%), and the newest embedded id 210 rows
7
+ * behind the newest id — a lane degrading silently, since a missing vector only
8
+ * ever costs recall quality, never an error.
9
+ *
10
+ * This module writes the missing rows. Every rule below exists because the
11
+ * failure mode here is SILENT:
12
+ *
13
+ * - **Parity is a precondition, not a per-row check.** A vector written into a
14
+ * space this adapter cannot reproduce looks exactly like a good vector
15
+ * afterwards, and it degrades every read that touches it. So the shared-space
16
+ * gate runs first, and a closed gate aborts the WHOLE batch — never "skip the
17
+ * bad ones and write the rest".
18
+ * - **The planned space must be the proven space.** The plan re-reads the
19
+ * dominant id from the store; if that disagrees with the space parity was
20
+ * proven against, the batch is refused rather than written into whichever
21
+ * space happens to be dominant now.
22
+ * - **An empty plan does not call the embedder.** Not merely an optimisation:
23
+ * it is the negative control that proves "no candidates" means "no writes"
24
+ * rather than "the loop happened to have nothing to do".
25
+ * - **A zero or short vector is never stored.** Both would break cosine
26
+ * similarity for every query against that row, silently.
27
+ * - **One row never aborts the batch.** A row that fails to embed or store is
28
+ * counted and skipped; the rest still land, and the next tick retries the gap.
29
+ */
30
+ import { errText } from "./types.js";
31
+ /**
32
+ * A vector of all zeros is not "no information": cosine similarity against it is
33
+ * undefined (0/0), which some readers turn into NaN and others into a perfect
34
+ * match. Either way it is worse than a missing row, so it is never stored.
35
+ */
36
+ export function isUsableVector(vector, dims) {
37
+ if (vector === undefined || vector.length !== dims)
38
+ return false;
39
+ // The whole vector must be scanned: an early `return true` on the first
40
+ // non-zero entry would never reach a NaN or an Infinity further along, which
41
+ // is precisely the value that ruins every cosine comparison.
42
+ let anyNonZero = false;
43
+ for (const value of vector) {
44
+ if (!Number.isFinite(value))
45
+ return false;
46
+ if (value !== 0)
47
+ anyNonZero = true;
48
+ }
49
+ return anyNonZero;
50
+ }
51
+ export async function runVectorBackfill(deps) {
52
+ const empty = { created: 0, present: 0, skipped: 0, failed: 0, total: 0 };
53
+ // (1) Parity first, for the whole batch. The one exception is the first-writer
54
+ // bootstrap: an empty store has no space to prove parity against, so the
55
+ // embedder's space becomes the target only when the caller supplies it.
56
+ if (deps.parityModelId === null && deps.bootstrapModelId === undefined) {
57
+ deps.journal.info('vector-lane', 'backfill skipped: shared-space parity is unproven', {
58
+ outcome: 'backfill-parity-unproven',
59
+ ...empty,
60
+ });
61
+ return { ...empty, reason: 'parity-unproven' };
62
+ }
63
+ const plan = deps.plan();
64
+ if (plan === undefined)
65
+ return { ...empty, reason: 'no-plan' };
66
+ if (plan.candidates.length === 0) {
67
+ return { ...empty, total: plan.total, reason: 'no-candidates' };
68
+ }
69
+ // (2) The plan's space is re-read from the store; it must be the one we proved,
70
+ // or the bootstrap space when there was nothing to prove yet.
71
+ const targetModelId = deps.parityModelId ?? deps.bootstrapModelId;
72
+ if (targetModelId === undefined || plan.modelId !== targetModelId) {
73
+ deps.journal.warn('vector-lane', 'backfill skipped: planned space is not the parity-proven space', {
74
+ outcome: 'backfill-parity-mismatch',
75
+ planned: plan.modelId,
76
+ ...deps.parityModelId === null ? { bootstrap: targetModelId } : { proven: targetModelId },
77
+ });
78
+ return { ...empty, total: plan.total, reason: 'parity-mismatch' };
79
+ }
80
+ const bootstrap = deps.parityModelId === null;
81
+ if (bootstrap) {
82
+ deps.journal.info('vector-lane', 'backfill: creating the first embedding space', {
83
+ outcome: 'backfill-bootstrap',
84
+ modelId: targetModelId,
85
+ total: plan.total,
86
+ });
87
+ }
88
+ const batch = plan.candidates.slice(0, Math.max(1, deps.limit));
89
+ const rows = deps.contents(batch).filter(row => row.content.trim().length > 0);
90
+ if (rows.length === 0)
91
+ return { ...empty, total: plan.total, reason: 'nothing-producible' };
92
+ let vectors;
93
+ try {
94
+ vectors = await deps.embed(rows.map(row => row.content));
95
+ }
96
+ catch (error) {
97
+ deps.journal.warn('vector-lane', `backfill embed failed: ${errText(error)}`, {
98
+ outcome: 'backfill-embed-failed',
99
+ attempted: rows.length,
100
+ });
101
+ return { ...empty, total: plan.total, reason: 'embed-failed' };
102
+ }
103
+ let created = 0;
104
+ let present = 0;
105
+ let skipped = 0;
106
+ let failed = 0;
107
+ for (const [index, row] of rows.entries()) {
108
+ const vector = vectors[index];
109
+ if (!isUsableVector(vector, deps.dims)) {
110
+ skipped += 1;
111
+ continue;
112
+ }
113
+ const stored = deps.store({ memoryId: row.id, modelId: plan.modelId, vector });
114
+ if (!stored.ok) {
115
+ failed += 1;
116
+ continue;
117
+ }
118
+ if (stored.created === true)
119
+ created += 1;
120
+ else
121
+ present += 1;
122
+ }
123
+ const outcome = {
124
+ created,
125
+ present,
126
+ skipped,
127
+ failed,
128
+ total: plan.total,
129
+ };
130
+ deps.journal.info('vector-lane', `backfill: +${String(created)} vector(s) in the ${bootstrap ? 'new' : 'dominant'} space`
131
+ + `${plan.total > batch.length ? ` (${String(plan.total - batch.length)} still missing)` : ''}`, {
132
+ outcome: 'backfill',
133
+ ...outcome,
134
+ modelId: plan.modelId,
135
+ batch: batch.length,
136
+ ...outcome.skipped > 0 ? { skipped: outcome.skipped } : {},
137
+ ...outcome.failed > 0 ? { failed: outcome.failed } : {},
138
+ });
139
+ return outcome;
140
+ }
@@ -0,0 +1,184 @@
1
+ /**
2
+ * The vector lane: measuring the degradation the takeover caused, and planning
3
+ * (never performing) the backfill.
4
+ *
5
+ * Why measuring is the deliverable, not the fix
6
+ * ---------------------------------------------
7
+ * Magic Context used to own `memory_embeddings` and refill it. That job has no
8
+ * owner now, and nothing in the adapter writes embeddings, so the lane decays
9
+ * silently: recall still *works*, it just answers with fewer neighbours. On
10
+ * 2026-10-10 the damage was already measurable and unmeasured until now:
11
+ *
12
+ * active 1224 · embedded 904 (73.9%) · missing 404
13
+ * newest embedded memory id 1103, newest memory id 1326 — nothing written
14
+ * since id 1103 has an embedding, and 194 rows BELOW that frontier lost one
15
+ *
16
+ * Two embedding spaces coexist (≈744 rows in one model, ≈96 in another as of
17
+ * 2026-10-10 — re-measure rather than trusting these). Writing into the wrong
18
+ * space, or into a third, is the specific failure this module exists to prevent:
19
+ * `memory_embeddings` is keyed `(memory_id, model_id)`, so a wrong-space row is
20
+ * not an error — it is simply invisible to the readers that use the other space,
21
+ * forever.
22
+ *
23
+ * So this module only reads: it reports coverage and hands back the id list a
24
+ * backfill WOULD take. The write itself lives in `vector-backfill.ts` (WP11),
25
+ * which consumes exactly this plan. The switch (`memory.vectorBackfill`)
26
+ * defaulted to off until 2026-10-12 and is on by default since (the write path
27
+ * never embeds, so an off-by-default lane let Chinese semantic recall decay
28
+ * with every new row); the phase-D blind spot that motivated the original
29
+ * wording is closed, the parity gate is not optional.
30
+ */
31
+ import { DatabaseSync } from 'node:sqlite';
32
+ function tableExists(db, name) {
33
+ return db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(name) !== undefined;
34
+ }
35
+ function columnNames(db, table) {
36
+ return new Set(db.prepare(`PRAGMA table_info(${table})`).all().map(row => row.name));
37
+ }
38
+ /** Read the lane's state from the shared store. `undefined` when it cannot be read. */
39
+ export function measureVectorLane(corpusDbPath) {
40
+ let db;
41
+ try {
42
+ db = new DatabaseSync(corpusDbPath, { readOnly: true });
43
+ }
44
+ catch {
45
+ return undefined;
46
+ }
47
+ try {
48
+ if (!tableExists(db, 'memories') || !tableExists(db, 'memory_embeddings'))
49
+ return undefined;
50
+ const memoryColumns = columnNames(db, 'memories');
51
+ const activeFilter = memoryColumns.has('status') ? "WHERE status = 'active'" : '';
52
+ const active = Number(db.prepare(`SELECT COUNT(*) AS c FROM memories ${activeFilter}`).get().c);
53
+ const newestMemoryId = Number(db.prepare(`SELECT COALESCE(MAX(id), 0) AS m FROM memories ${activeFilter}`).get().m);
54
+ // Space shares are measured over the ACTIVE corpus: the question they answer
55
+ // is "which space do live memories actually live in", and a reader only ever
56
+ // looks at active rows.
57
+ const activeJoin = memoryColumns.has('status') ? "WHERE m.status = 'active'" : '';
58
+ const spaces = db.prepare(`SELECT e.model_id AS modelId, COUNT(*) AS rows, COUNT(DISTINCT e.memory_id) AS memories
59
+ FROM memory_embeddings e JOIN memories m ON m.id = e.memory_id ${activeJoin}
60
+ GROUP BY e.model_id ORDER BY rows DESC, modelId`).all();
61
+ const totalRows = spaces.reduce((sum, space) => sum + Number(space.rows), 0);
62
+ const embeddedIds = db.prepare(`SELECT DISTINCT e.memory_id AS id FROM memory_embeddings e JOIN memories m ON m.id = e.memory_id ${memoryColumns.has('status') ? "WHERE m.status = 'active'" : ''}`).all();
63
+ const embedded = embeddedIds.length;
64
+ const dominantModelId = spaces[0]?.modelId;
65
+ const dominantIds = dominantModelId === undefined
66
+ ? new Set()
67
+ : new Set(db.prepare(`SELECT DISTINCT e.memory_id AS id FROM memory_embeddings e JOIN memories m ON m.id = e.memory_id
68
+ WHERE e.model_id = ? ${memoryColumns.has('status') ? "AND m.status = 'active'" : ''}`).all(dominantModelId).map(row => Number(row.id)));
69
+ const allEmbeddedIds = new Set(embeddedIds.map(row => Number(row.id)));
70
+ const activeIds = db.prepare(`SELECT id FROM memories ${activeFilter}`).all()
71
+ .map(row => Number(row.id));
72
+ // The frontier is the newest ACTIVE memory that has an embedding. Taking the
73
+ // raw MAX(memory_id) instead would let an archived row's leftover embedding
74
+ // look like progress and hide the backlog behind it.
75
+ const newestEmbeddedMemoryId = embeddedIds.reduce((max, row) => Math.max(max, Number(row.id)), 0);
76
+ let unembeddedAboveFrontier = 0;
77
+ let gapsBelowFrontier = 0;
78
+ let dominantCoverageCount = 0;
79
+ for (const id of activeIds) {
80
+ if (!allEmbeddedIds.has(id)) {
81
+ if (id > newestEmbeddedMemoryId)
82
+ unembeddedAboveFrontier += 1;
83
+ else
84
+ gapsBelowFrontier += 1;
85
+ }
86
+ if (dominantIds.has(id))
87
+ dominantCoverageCount += 1;
88
+ }
89
+ const multiSpaceMemories = Number(db.prepare('SELECT COUNT(*) AS c FROM (SELECT memory_id FROM memory_embeddings GROUP BY memory_id HAVING COUNT(DISTINCT model_id) > 1)').get().c);
90
+ return {
91
+ active,
92
+ embedded,
93
+ missing: active - embedded,
94
+ coverage: active === 0 ? 0 : embedded / active,
95
+ spaces: spaces.map(space => ({
96
+ modelId: space.modelId,
97
+ rows: Number(space.rows),
98
+ memories: Number(space.memories),
99
+ share: totalRows === 0 ? 0 : Number(space.rows) / totalRows,
100
+ })),
101
+ ...dominantModelId === undefined ? {} : { dominantModelId },
102
+ frontier: { newestEmbeddedMemoryId, newestMemoryId, unembeddedAboveFrontier },
103
+ gapsBelowFrontier,
104
+ multiSpaceMemories,
105
+ dominantCoverage: active === 0 ? 0 : dominantCoverageCount / active,
106
+ };
107
+ }
108
+ catch {
109
+ return undefined;
110
+ }
111
+ finally {
112
+ db.close();
113
+ }
114
+ }
115
+ /**
116
+ * Which memories a backfill would take, and which space it may write into.
117
+ *
118
+ * A candidate is an ACTIVE memory with no embedding row under the DOMINANT
119
+ * model. That covers both "never embedded" and "embedded only in the other
120
+ * space" — the second case is how a space migration happens without creating a
121
+ * third space.
122
+ *
123
+ * `bootstrapModelId` is used only when the store has no space at all: it is the
124
+ * first-writer path for an empty corpus. It never overrides an existing
125
+ * dominant space.
126
+ *
127
+ * Writes nothing. The contract write is still ahead.
128
+ */
129
+ export function planBackfill(corpusDbPath, options = {}) {
130
+ const report = measureVectorLane(corpusDbPath);
131
+ if (report === undefined)
132
+ return undefined;
133
+ const limit = options.limit ?? 64;
134
+ const db = new DatabaseSync(corpusDbPath, { readOnly: true });
135
+ try {
136
+ const bootstrap = options.bootstrapModelId?.trim() ?? '';
137
+ // A bootstrap id may only be used when no space exists at all. Once any
138
+ // embedding row is present, the dominant space is the only legal target;
139
+ // accepting a bootstrap id here would be the third-space bug this module
140
+ // exists to prevent.
141
+ const dominant = report.dominantModelId ?? (bootstrap === '' ? undefined : bootstrap);
142
+ if (dominant === undefined) {
143
+ return { modelId: '', candidates: [], total: 0, reason: 'no embedding space exists yet — the first writer decides the space' };
144
+ }
145
+ const memoryColumns = columnNames(db, 'memories');
146
+ const activeFilter = memoryColumns.has('status') ? "AND m.status = 'active'" : '';
147
+ // Newest first (2026-10-10). The rows a session is most likely to search for
148
+ // are the ones written most recently, so the lane closes the frontier gap
149
+ // before it grinds through the older churn holes. The order is a policy:
150
+ // tests/vector-lane.spec.ts pins it, and flipping it back is the rollback.
151
+ const missing = db.prepare(`SELECT m.id AS id FROM memories m
152
+ WHERE NOT EXISTS (SELECT 1 FROM memory_embeddings e WHERE e.memory_id = m.id AND e.model_id = ?)
153
+ ${activeFilter}
154
+ ORDER BY m.id DESC`).all(dominant);
155
+ const ids = missing.map(row => Number(row.id));
156
+ return {
157
+ modelId: dominant,
158
+ candidates: ids.slice(0, limit),
159
+ total: ids.length,
160
+ ...ids.length === 0
161
+ ? {
162
+ reason: report.active === 0
163
+ ? 'no active memories to embed'
164
+ : 'every active memory already has a row in the dominant space',
165
+ }
166
+ : {},
167
+ };
168
+ }
169
+ catch {
170
+ return undefined;
171
+ }
172
+ finally {
173
+ db.close();
174
+ }
175
+ }
176
+ /** One line for a health report: the shape of the decay, not just a percentage. */
177
+ export function describeVectorLane(report) {
178
+ const spaces = report.spaces
179
+ .map(space => `${space.modelId.replace('embedding-provider:', '')} ${String(space.rows)} 行 (${(space.share * 100).toFixed(0)}%)`)
180
+ .join(' / ');
181
+ return `active ${String(report.active)} · 已嵌入 ${String(report.embedded)} (${(report.coverage * 100).toFixed(1)}%) · `
182
+ + `缺 ${String(report.missing)}(前沿之上 ${String(report.frontier.unembeddedAboveFrontier)} / 前沿之下 ${String(report.gapsBelowFrontier)})· `
183
+ + `空间:${spaces === '' ? '无' : spaces}`;
184
+ }