dsh-lite-memory 0.3.0 → 0.15.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.
- package/README.md +73 -17
- package/TRIGGERS.md +18 -14
- package/anchor.js +518 -0
- package/bench/bench.mjs +145 -0
- package/bench/evolution.mjs +123 -0
- package/client.js +1519 -33
- package/docs/BENCH.md +74 -0
- package/docs/RELEASE-0.11.0.md +27 -0
- package/docs/RELEASE-0.11.1.md +11 -0
- package/docs/RELEASE-0.12.0.md +15 -0
- package/docs/RELEASE-0.12.1.md +17 -0
- package/docs/RELEASE-0.12.2.md +17 -0
- package/docs/RELEASE-0.13.0.md +7 -0
- package/docs/RELEASE-0.14.0.md +7 -0
- package/docs/RELEASE-0.15.0.md +8 -0
- package/index.js +2080 -76
- package/learning.js +585 -0
- package/package.json +10 -2
- package/state.js +1476 -0
- package/store.js +2967 -244
- package/test/anchor.test.mjs +436 -0
- package/test/client.test.mjs +114 -0
- package/test/contract.test.mjs +880 -0
- package/test/control.test.mjs +278 -0
- package/test/crossing.test.mjs +372 -0
- package/test/evolution-read.test.mjs +448 -0
- package/test/fixtures/legacy-v1/archive/mem_444444444444.json +18 -0
- package/test/fixtures/legacy-v1/entries/mem_111111111111.md +2 -0
- package/test/fixtures/legacy-v1/entries/mem_222222222222.md +1 -0
- package/test/fixtures/legacy-v1/entries/mem_333333333333.md +1 -0
- package/test/fixtures/legacy-v1/index.json +63 -0
- package/test/learning.test.mjs +772 -0
- package/test/lexical.test.mjs +33 -0
- package/test/recall.test.mjs +449 -0
- package/test/scenario.test.mjs +184 -0
- package/test/state.test.mjs +485 -0
- package/test/store.test.mjs +816 -115
- package/test/view.test.mjs +257 -0
- package/view.js +616 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 项目自进化实验的本地成本基准:固定 32 条实验规则、64 条回执。
|
|
3
|
+
* 只打印可复现的存储/视图成本与边界;不调用模型,不声称效果提升。
|
|
4
|
+
*
|
|
5
|
+
* node bench/evolution.mjs
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
import os from 'node:os';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
|
|
11
|
+
process.env.DSH_HOME = fs.mkdtempSync(path.join(os.tmpdir(), 'lite-memory-evolution-bench-'));
|
|
12
|
+
const store = await import('../store.js');
|
|
13
|
+
const learning = await import('../learning.js');
|
|
14
|
+
const state = await import('../state.js');
|
|
15
|
+
const view = await import('../view.js');
|
|
16
|
+
|
|
17
|
+
const cwd = fs.mkdtempSync(path.join(os.tmpdir(), 'lite-memory-evolution-project-'));
|
|
18
|
+
const scope = store.scopeOf(cwd, { projectRoot: cwd });
|
|
19
|
+
store.setEvolution(scope, true, { operationId: 'bench_on' });
|
|
20
|
+
store.setTaskDefault(scope, { taskKind: 'video', seriesId: '口播' });
|
|
21
|
+
|
|
22
|
+
const started = Date.now();
|
|
23
|
+
for (let i = 0; i < learning.LIMITS.rules; i += 1) {
|
|
24
|
+
store.saveEntry(scope, {
|
|
25
|
+
title: `口播规范 ${i}`,
|
|
26
|
+
summary: `第 ${i} 条制作习惯`,
|
|
27
|
+
when: '口播',
|
|
28
|
+
body: `第 ${i} 条:开头先给结论,正文再展开。`,
|
|
29
|
+
applicability: 'conditional',
|
|
30
|
+
conditions: [{ key: 'seriesId', value: '口播' }],
|
|
31
|
+
resolution: 'distinct',
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
state.transact(scope, { operationId: 'bench_mark' }, (draft) => {
|
|
36
|
+
const evolution = draft.experimental.projectEvolution;
|
|
37
|
+
evolution.tasks = evolution.tasks || { sessions: {}, episodes: [] };
|
|
38
|
+
evolution.learning = evolution.learning || { attempts: {}, recent: [], receipts: [] };
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
for (const [index, entry] of draft.entries.entries()) {
|
|
41
|
+
entry.origin = 'project_evolution';
|
|
42
|
+
entry.reviewState = 'active';
|
|
43
|
+
entry.revision = 2;
|
|
44
|
+
entry.current.topicKey = `口播规范-${index}`;
|
|
45
|
+
entry.maintenance = entry.maintenance || {};
|
|
46
|
+
entry.maintenance.learning = {
|
|
47
|
+
state: 'active',
|
|
48
|
+
supportedEpisodeIds: ['ep_bench'],
|
|
49
|
+
evidence: Array.from({ length: learning.LIMITS.evidence }, (_, n) => ({ sourceType: 'human_feedback', feedbackType: 'spec_change', episodeId: `ep_${n}`, at: new Date(now).toISOString() })),
|
|
50
|
+
samples: Array.from({ length: learning.LIMITS.samples }, (_, n) => ({ episodeId: `ep_${n}`, artifactVersion: `v${n}`, dimension: '开头', verified: false, at: new Date(now).toISOString() })),
|
|
51
|
+
checkpoints: Array.from({ length: learning.LIMITS.checkpoints }, (_, n) => ({ text: `检查点 ${n}`, at: new Date(now).toISOString() })),
|
|
52
|
+
specDigest: `sd_bench_${index}`,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
evolution.learning.receipts = Array.from({ length: learning.LIMITS.receipts }, (_, n) => ({
|
|
56
|
+
operationId: `bench_${n}`,
|
|
57
|
+
episodeId: `ep_bench`,
|
|
58
|
+
status: n % 5 === 0 ? 'failed' : 'applied',
|
|
59
|
+
changes: n % 5 === 0 ? 0 : 1,
|
|
60
|
+
at: new Date(now - n * 1000).toISOString(),
|
|
61
|
+
...(n % 4 === 0 ? { usage: { known: true, inputTokens: 100, outputTokens: 20 } } : {}),
|
|
62
|
+
}));
|
|
63
|
+
return { changed: true };
|
|
64
|
+
});
|
|
65
|
+
const seedMs = Date.now() - started;
|
|
66
|
+
|
|
67
|
+
const coldStart = process.hrtime.bigint();
|
|
68
|
+
const cold = store.learningSnapshot(scope);
|
|
69
|
+
const coldMs = Number(process.hrtime.bigint() - coldStart) / 1e6;
|
|
70
|
+
const samples = [];
|
|
71
|
+
for (let i = 0; i < 50; i += 1) {
|
|
72
|
+
const at = process.hrtime.bigint();
|
|
73
|
+
store.learningSnapshot(scope);
|
|
74
|
+
samples.push(Number(process.hrtime.bigint() - at) / 1e6);
|
|
75
|
+
}
|
|
76
|
+
samples.sort((a, b) => a - b);
|
|
77
|
+
const pct = (p) => Math.round(samples[Math.min(samples.length - 1, Math.ceil((p / 100) * samples.length) - 1)] * 1000) / 1000;
|
|
78
|
+
const organizerInput = learning.buildCallInput({
|
|
79
|
+
projectId: 'bench', episodeId: 'ep_bench', taskKind: 'video', seriesId: '口播', phase: 'brief',
|
|
80
|
+
feedback: { messageIds: ['m1'], text: '之前说过开头先给结论,这次怎么又没做到。', cue: { type: 'execution_miss', explicitLongTerm: false } },
|
|
81
|
+
rules: store.learningRulesForOrganizer(scope),
|
|
82
|
+
ranges: { taskKinds: ['video'], series: ['口播'] },
|
|
83
|
+
});
|
|
84
|
+
const record = cold.rules[0];
|
|
85
|
+
const context = { taskKind: 'video', seriesId: '口播' };
|
|
86
|
+
const measured = {
|
|
87
|
+
rules: cold.rules.length,
|
|
88
|
+
organizerRules: organizerInput.rules.length,
|
|
89
|
+
organizerBytes: organizerInput.bytes,
|
|
90
|
+
stateBytes: fs.statSync(state.stateFiles(scope).current).size,
|
|
91
|
+
sampleDepth: Math.max(...cold.rules.map((rule) => rule.samples.length)),
|
|
92
|
+
checkpointDepth: Math.max(...cold.rules.map((rule) => rule.checkpoints.length)),
|
|
93
|
+
evidenceDepth: Math.max(...cold.rules.map((rule) => rule.learning.evidence.length)),
|
|
94
|
+
effect: cold.effect,
|
|
95
|
+
evaluate: view.evaluate(record, context).status,
|
|
96
|
+
modelViewBytes: Buffer.byteLength(JSON.stringify(view.toModelView(record, 'read', { context }))),
|
|
97
|
+
coldMs: Math.round(coldMs * 1000) / 1000,
|
|
98
|
+
warmP50Ms: pct(50),
|
|
99
|
+
warmP95Ms: pct(95),
|
|
100
|
+
seedMs,
|
|
101
|
+
};
|
|
102
|
+
const checks = {
|
|
103
|
+
ruleCap: measured.rules === learning.LIMITS.rules,
|
|
104
|
+
sampleCap: measured.sampleDepth === learning.LIMITS.samples,
|
|
105
|
+
checkpointCap: measured.checkpointDepth === learning.LIMITS.checkpoints,
|
|
106
|
+
evidenceCap: measured.evidenceDepth === learning.LIMITS.evidence,
|
|
107
|
+
receiptWindow: measured.effect.window === learning.LIMITS.receipts,
|
|
108
|
+
effectKnownUsage: Number.isInteger(measured.effect.inputTokens),
|
|
109
|
+
stateBudget: measured.stateBytes <= 256 * 1024,
|
|
110
|
+
organizerBudget: measured.organizerBytes <= 8 * 1024,
|
|
111
|
+
};
|
|
112
|
+
if (Object.values(checks).some((ok) => !ok)) {
|
|
113
|
+
console.error(JSON.stringify({ checks, measured }, null, 2));
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
console.log(JSON.stringify({
|
|
117
|
+
kind: 'project-evolution',
|
|
118
|
+
node: process.version,
|
|
119
|
+
platform: `${process.platform}/${process.arch}`,
|
|
120
|
+
modelQuality: 'not measured',
|
|
121
|
+
measured,
|
|
122
|
+
checks,
|
|
123
|
+
}, null, 2));
|