@sanqianx/project-knowledge 5.0.9-rc.6 → 5.0.9-rc.8

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.
@@ -9,7 +9,7 @@
9
9
  "plugins": [
10
10
  {
11
11
  "name": "project-knowledge",
12
- "version": "5.0.9-rc.6",
12
+ "version": "5.0.9-rc.8",
13
13
  "source": "./plugins/project-knowledge",
14
14
  "description": "Search durable project decisions and implementation history through MCP."
15
15
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.0.9-rc.8] - 2026-10-11
4
+
5
+ - Pin Workbench 0.13.2-rc.4: atomically replace all native Agent histories,
6
+ retaining the previous complete record on disk-full or locked-file errors.
7
+ CLI fallback no longer deletes durable history before a failed rename.
8
+ - Keep the original disk-full loss and separate successful background recovery
9
+ records. Candidate acceptance includes faults against downloaded module bytes.
10
+ - Pin vector-hub 1.0.8-rc.2. Managed indexes now follow the knowledge root
11
+ under `.indexes`; show the acknowledged actual directory in System Status.
12
+ Rebuild on a root/model change while retaining the old index directory;
13
+ serialize queued writes and avoid a full paid rebuild on normal restart.
14
+ - Do not promote latest until installed and existing-v5 acceptance pass.
15
+
16
+ ## [5.0.9-rc.7] - 2026-10-11
17
+
18
+ - Vendor engine 0.2.3-rc.3: recognize promoted commit identifiers inside
19
+ natural-language tasks, including short and multiple SHAs. Raw conversation
20
+ mentions cannot replace the current promoted knowledge references.
21
+ - Preserve failed installed Workbench/context checks from rc.6; latest remains
22
+ unchanged until fresh registry runtime and existing-v5 acceptance pass.
23
+
3
24
  ## [5.0.9-rc.6] - 2026-10-11
4
25
 
5
26
  - Vendor engine 0.2.3-rc.2. Unassigned projects no longer share an implicit
package/README.md CHANGED
@@ -127,6 +127,13 @@ visible as dirty state and is retried.
127
127
  vector-hub owns the derived index; the shell no longer runs a second index
128
128
  writer. Failed indexing leaves promoted Markdown intact and repairable.
129
129
 
130
+ Managed vectors follow the configured knowledge root at `<knowledge>/.indexes`.
131
+ The system drawer displays the actual directory and pending wiring separately.
132
+ Root changes leave project Markdown and old indexes untouched, drain existing
133
+ index writes, switch subsequent writes, and rebuild registered knowledge with
134
+ the configured embedding model. Credentials and small runtime metadata remain
135
+ in the product data directory; no expensive historical Agent analysis is started.
136
+
130
137
  The application does not create, edit, refresh, or delete `CLAUDE.md`.
131
138
 
132
139
  ## Requirement capture
@@ -77,6 +77,7 @@ node src/bin.js serve [--port 5790] [--host 127.0.0.1] [--data DIR]
77
77
  - 晋升与索引分别记录。索引失败保留已晋升知识并显示待修复,不重新调用模型。
78
78
  - 索引错误保留兼容的 `INDEX_FAILED` 及可选 `error.details`(类别、HTTP 状态、上游代码/脱敏原因、请求标识、耗时和尝试次数);项目和共享索引均写入 `log/v2`。响应仅解析有界 JSON,不记录原始 body 或认证头。只重试索引保留原分析运行、晋升时间和知识字节。
79
79
  - 项目、领域、智脑检索使用包含范围。未分配领域不是共享领域:领域范围只包含当前项目与智脑共享知识;显式加入同一领域后才包含其他项目。整个智脑范围仍包含全部同智脑项目。向量只提供排序,显示内容必须来自当前真实文件;索引不可用时降级为文件检索。
80
+ - 已晋升提交的 SHA 或短 SHA 在自然语言查询中仍作为标识符匹配,只返回当前文件的晋升依据;仅在原始会话中提到相同 SHA 不构成知识晋升引用。多个提交标识符可以一起查询。
80
81
  - 候选必须有已晋升文件中的引用依据,未确认候选不能进入任务。确认记录原子持久化后写共享记忆文件,派生索引异步更新,索引失败不会撤销有效记忆。
81
82
  - 旧格式不读取、不自动迁移。损坏的正式状态不覆盖、不清空。
82
83
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanqianx/ai-coding-knowledge-engine",
3
- "version": "0.2.3-rc.2",
3
+ "version": "0.2.3-rc.3",
4
4
  "description": "Knowledge engine module for project-knowledge: commit-boundary triggered knowledge analysis/generation (trigger plane) and retrieval for development assistants (retrieval plane).",
5
5
  "license": "Apache-2.0",
6
6
  "main": "src/server.js",
@@ -10,15 +10,17 @@ class EngineRetrieval extends KnowledgeRetrievalService {
10
10
  signalSet(input = {}) {
11
11
  const signals = super.signalSet(input);
12
12
  const query = signals.indexQuery.trim().toLowerCase();
13
- if (/^[a-f0-9]{7,64}$/.test(query) && this.store.listRuns().some(run => run.promotedAt && run.commitSha?.startsWith(query))) signals.commitPrefix = query;
13
+ const promoted = this.store.listRuns().filter(run => run.promotedAt && run.commitSha);
14
+ const identifiers = [...query.matchAll(/(?:^|[^a-z0-9])([a-f0-9]{7,64})(?=$|[^a-z0-9])/g)].map(match => match[1]);
15
+ signals.commitPrefixes = [...new Set(identifiers.filter(id => promoted.some(run => run.commitSha.startsWith(id))))];
14
16
  return signals;
15
17
  }
16
18
  score(candidate, signals) {
17
- if (signals.commitPrefix) {
19
+ if (signals.commitPrefixes?.length) {
18
20
  // A known commit is an identifier, not a semantic topic. Unrelated
19
21
  // vector hits must not crowd its current, provenance-checked files out.
20
22
  const source = this.store.listRuns(candidate.projectId).find(run => run.promotedAt && run.staging?.operations?.some(operation => operation.path === candidate.entryId));
21
- if (!source?.commitSha?.startsWith(signals.commitPrefix)) return { score: 0, selectionSignals: [] };
23
+ if (!signals.commitPrefixes.some(prefix => source?.commitSha?.startsWith(prefix))) return { score: 0, selectionSignals: [] };
22
24
  const result = super.score(candidate, signals);
23
25
  return { score: Math.max(1, result.score), selectionSignals: [...result.selectionSignals, 'exact-commit'] };
24
26
  }
@@ -0,0 +1,52 @@
1
+ 'use strict';
2
+ const assert = require('node:assert/strict');
3
+ const path = require('node:path');
4
+ const { StorageLayout } = require('../lib/storage-layout');
5
+ const { ModuleBridge } = require('../lib/module-bridge');
6
+ const root = path.resolve('D:/knowledge storage 中文');
7
+ const layout = new StorageLayout({ dataDir: path.resolve('D:/metadata') });
8
+ assert.equal(layout.getVectorRootPath({ knowledge: { rootPath: root } }), path.join(root, '.indexes'));
9
+ assert.equal(layout.getVectorRootPath({ knowledge: { rootPath: '' } }), path.join(layout.getDataDir(), 'vectorhub'));
10
+ const settingsStore = { read: () => ({ knowledge: { rootPath: root }, brain: { id: 'brain-default', domains: [] } }) };
11
+ const bridge = new ModuleBridge({ settingsStore, dataDir: layout.getDataDir() });
12
+ const spec = bridge._supervisedSpecs().find(spec => spec.name === 'vector-hub');
13
+ assert.equal(spec.env.VECTOR_HUB_ROOT, path.join(root, '.indexes'));
14
+ assert.equal(spec.env.VECTOR_HUB_CONFIG, path.join(layout.getDataDir(), 'vectorhub', 'config.json'));
15
+ const calls = [];
16
+ bridge._fetch = async (url, init) => { const body = JSON.parse(init.body); calls.push({ url, body }); return { ok: true, json: async () => url.includes('/api/internal/runtime-config') ? { ok: true, rootPath: path.join(root, '.indexes') } : {} }; };
17
+ bridge.syncEngineConfiguration().then(async status => {
18
+ assert.equal(calls.find(call => call.url.includes('/api/internal/runtime-config')).body.storageRoot, path.join(root, '.indexes'));
19
+ assert.equal(status.indexStorage.status, 'ready');
20
+ let currentRoot = root, release, started;
21
+ const entered = new Promise(resolve => { started = resolve; });
22
+ const held = new Promise(resolve => { release = resolve; });
23
+ const queued = new ModuleBridge({ dataDir: layout.getDataDir(), settingsStore: { read: () => ({ knowledge: { rootPath: currentRoot }, brain: { id: 'brain-default', domains: [] } }) } });
24
+ const applied = [];
25
+ queued._fetch = async (url, init) => {
26
+ const body = JSON.parse(init.body);
27
+ if (url.endsWith('/api/internal/runtime-config')) {
28
+ applied.push(body.storageRoot);
29
+ if (applied.length === 1) { started(); await held; }
30
+ return { ok: true, json: async () => ({ rootPath: body.storageRoot }) };
31
+ }
32
+ return { ok: true, json: async () => null };
33
+ };
34
+ const first = queued.syncEngineConfiguration(); await entered;
35
+ currentRoot = path.join(root, 'new root');
36
+ const second = queued.syncEngineConfiguration(); release();
37
+ await first;
38
+ const latest = await second;
39
+ assert.deepEqual(applied, [path.join(root, '.indexes'), path.join(currentRoot, '.indexes')]);
40
+ assert.equal(latest.indexStorage.actualPath, path.join(currentRoot, '.indexes'));
41
+ assert.equal(latest.indexStorage.status, 'ready');
42
+ const broken = new ModuleBridge({ dataDir: layout.getDataDir(), settingsStore: { read: () => { throw new Error('corrupt settings'); } } });
43
+ let revoked;
44
+ broken._fetch = async (url, init) => {
45
+ if (url.endsWith('/api/internal/runtime-config')) revoked = JSON.parse(init.body);
46
+ return { ok: false };
47
+ };
48
+ const unavailable = await broken.syncEngineConfiguration();
49
+ assert.deepEqual(revoked, { settings: null });
50
+ assert.equal(unavailable.indexStorage.status, 'pending');
51
+ console.log('vector-storage-root-test PASS');
52
+ }).catch(error => { console.error(error); process.exitCode = 1; });
@@ -24,6 +24,7 @@
24
24
 
25
25
  const { spawn, spawnSync } = require('child_process');
26
26
  const path = require('path');
27
+ const { StorageLayout } = require('./storage-layout');
27
28
  const fs = require('fs');
28
29
  const crypto = require('crypto');
29
30
  const { once } = require('events');
@@ -310,10 +311,19 @@ class ModuleBridge {
310
311
  } };
311
312
  }
312
313
 
313
- async syncEngineConfiguration() {
314
- if (this.syncingConfig) return this.configStatus || { scopes: false, model: false };
315
- this.syncingConfig = true;
316
- const status = { scopes: false, model: false, embedding: false };
314
+ syncEngineConfiguration() {
315
+ if (this.configSyncPromise) return this.configSyncPromise.catch(() => undefined).then(() => this.syncEngineConfiguration());
316
+ const pending = this._syncEngineConfiguration().finally(() => { if (this.configSyncPromise === pending) this.configSyncPromise = null; });
317
+ this.configSyncPromise = pending;
318
+ return pending;
319
+ }
320
+
321
+ async _syncEngineConfiguration() {
322
+ const dataDir = this.dataDir || require('./data-dir').getDataDir();
323
+ let indexPath = null;
324
+ try { indexPath = new StorageLayout({ dataDir }).getVectorRootPath(this.settingsStore?.read()); }
325
+ catch { /* Corrupt settings must not switch storage or prevent credential revocation. */ }
326
+ const status = { scopes: false, model: false, embedding: false, indexStorage: { expectedPath: indexPath, actualPath: null, status: 'pending' } };
317
327
  const headers = { 'Content-Type': 'application/json', Authorization: `Bearer ${this.runtimeToken}` };
318
328
  try {
319
329
  if (this.settingsStore) {
@@ -341,10 +351,15 @@ class ModuleBridge {
341
351
  const resolved = await this._fetch(`${this.terminalUrl}/api/claude-workbench/v1/internal/embedding-config`, { method: 'POST', headers, body: '{}' });
342
352
  if (resolved.ok) settings = await resolved.json();
343
353
  } catch { /* Revocation wins over a previously cached runtime key. */ }
344
- const applied = await this._fetch(`${this.vectorHubUrl}/api/internal/runtime-config`, { method: 'POST', headers, body: JSON.stringify({ settings }) });
354
+ const applied = await this._fetch(`${this.vectorHubUrl}/api/internal/runtime-config`, { method: 'POST', headers, body: JSON.stringify({ settings, ...(indexPath ? { storageRoot: indexPath } : {}) }) });
345
355
  status.embedding = applied.ok && !!settings;
356
+ if (applied.ok) {
357
+ const result = await applied.json();
358
+ status.indexStorage.actualPath = result.rootPath || null;
359
+ status.indexStorage.status = result.rootPath && path.resolve(result.rootPath) === indexPath ? 'ready' : 'pending';
360
+ }
346
361
  } catch { /* Public status contains no resolved configuration. */ }
347
- this.syncingConfig = false; this.configStatus = status;
362
+ this.configStatus = status;
348
363
  return status;
349
364
  }
350
365
 
@@ -559,12 +574,13 @@ class ModuleBridge {
559
574
  this.logger.warn('modules.supervisor', '@sanqianx/vector-hub runtime not installed; expecting an external service.', {});
560
575
  } else {
561
576
  const dataDir = this.dataDir || require('./data-dir').getDataDir();
562
- const root = path.join(dataDir, 'vectorhub');
577
+ const configRoot = path.join(dataDir, 'vectorhub');
578
+ const root = new StorageLayout({ dataDir }).getVectorRootPath(this.settingsStore?.read());
563
579
  specs.push({
564
580
  name: 'vector-hub',
565
581
  command: `node ${JSON.stringify(vectorHubEntry)} serve --host ${urlHost(this.vectorHubUrl)} --port ${urlPort(this.vectorHubUrl, 8787)} --root ${JSON.stringify(root)}`,
566
582
  url: this.vectorHubUrl,
567
- env: { VECTOR_HUB_ROOT: root, VECTOR_HUB_CONFIG: path.join(root, 'config.json'), VECTOR_HUB_LEGACY_CONFIG: path.join(root, 'no-legacy-config.json'), KB_VECTOR_MANAGED: '1', KB_VECTOR_RUNTIME_TOKEN: this.runtimeToken },
583
+ env: { VECTOR_HUB_ROOT: root, VECTOR_HUB_CONFIG: path.join(configRoot, 'config.json'), VECTOR_HUB_LEGACY_CONFIG: path.join(configRoot, 'no-legacy-config.json'), KB_VECTOR_MANAGED: '1', KB_VECTOR_RUNTIME_TOKEN: this.runtimeToken },
568
584
  });
569
585
  }
570
586
  }
@@ -921,7 +921,7 @@ function createRequestHandler(runtime, options = {}) {
921
921
  }
922
922
  if (method === 'GET' && pathname === '/api/brain') {
923
923
  const settings = runtime.settingsStore.read();
924
- return send(res, 200, { ok: true, brain: settings.brain, knowledgeRoot: settings.knowledge.rootPath, configuration: runtime.moduleBridge.configStatus || null });
924
+ return send(res, 200, { ok: true, brain: settings.brain, knowledgeRoot: settings.knowledge.rootPath, indexStoragePath: runtime.layout.getVectorRootPath(settings), configuration: runtime.moduleBridge.configStatus || null });
925
925
  }
926
926
  if (method === 'PATCH' && pathname === '/api/brain') {
927
927
  const body = await readJsonBody(req);
@@ -982,8 +982,8 @@ function createRequestHandler(runtime, options = {}) {
982
982
  if (body.logging) throw new DomainError('IMMUTABLE_FIELD', 'Logging storage and capture policy are not user settings.', { status: 409 });
983
983
  if (!Object.keys(patch).length) throw new DomainError('INVALID_ARGUMENT', 'Only the knowledge root is mutable on this route.');
984
984
  const settings = await runtime.settingsStore.updatePatch(patch);
985
- await runtime.moduleBridge.syncEngineConfiguration();
986
- return send(res, 200, { ok: true, settings: { ...settings, ai: publicAiProfilesConfig(settings.ai) } });
985
+ const configuration = await runtime.moduleBridge.syncEngineConfiguration();
986
+ return send(res, 200, { ok: true, settings: { ...settings, ai: publicAiProfilesConfig(settings.ai) }, configuration });
987
987
  }
988
988
 
989
989
  if (method === 'GET' && pathname === '/api/projects') return send(res, 200, { ok: true, projects: listProjectViews(runtime.registryStore, runtime.projectStore) });
@@ -49,6 +49,10 @@ class StorageLayout {
49
49
  getRegistryLockPath() { return path.join(this.dataDir, 'runtime', 'locks', 'projects.lock'); }
50
50
 
51
51
  getIndexPath() { return path.join(this.dataDir, 'index', 'knowledge.lancedb'); }
52
+ getVectorRootPath(settings) {
53
+ const root = settings?.knowledge?.rootPath;
54
+ return root ? path.join(path.resolve(root), '.indexes') : path.join(this.dataDir, 'vectorhub');
55
+ }
52
56
  getCachePath(...segments) { return path.join(this.dataDir, 'cache', ...segments); }
53
57
  getRuntimePath(...segments) { return path.join(this.dataDir, 'runtime', ...segments); }
54
58
  getRecoveryPath(...segments) { return path.join(this.dataDir, 'recovery', ...segments); }
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schema": "project-knowledge/module-content/v1",
3
3
  "productFiles": {
4
- "ui/index.html": "0cb319212230af66f3530bb1b57915894f41789f1ea1c57bb8ae54b0f01164a8",
5
- "ui/product.js": "50d26a9aa3a95889804f8ca771dada9e1ea89d6956851e58dadf119a75842b9c",
4
+ "ui/index.html": "5cc3f9519a0671e7d5b24a94987a96b7ee81d3ed3367e3c02cd70934f08e64c8",
5
+ "ui/product.js": "1081a5b01f2f46c4828b63873670360de85d78e7830eebbec1721ddb1618e8e1",
6
6
  "ui/product.css": "3f89daeb52c5f1ed8a79150c9a84200187474a013fd97c6d7c8799d850e5b0b7",
7
7
  "ui/favicon.svg": "c48be946b224112ebb0238b44263f7a61bda31e531afa895c2e9801c0ff24f32"
8
8
  },
@@ -10,10 +10,10 @@
10
10
  "terminal": {
11
11
  "name": "@sanqianx/claude-ai-workbench",
12
12
  "installName": "claude-ai-workbench",
13
- "version": "0.13.2-rc.3",
13
+ "version": "0.13.2-rc.4",
14
14
  "files": {
15
15
  "LICENSE": "c1b9df1275e769f3dbab000d1e457a2d4b0f28eb5da6c77e48dc37eeba202ed7",
16
- "README.md": "2343588083f2a0e9a6adf85524a8194f3f29a48e3a73874a9f1ccaa240d0fb11",
16
+ "README.md": "6f4176416a3cfa702d17da8987327e014fec93e34ff5bd350175c771a55c1521",
17
17
  "apps/agent-terminal/app.css": "39cc65ac65bcb390f4aa21d9b783182ca229557f6bec15090f69598120161917",
18
18
  "apps/agent-terminal/app.js": "2fedcc79f9515ebae89d1c7dc996d732aa1d0946038eaaa045438121bf27f551",
19
19
  "apps/agent-terminal/index.html": "6a52ba210696c8aed99e2786e21d2771340070d51583199dd74c8da41edf0257",
@@ -27,20 +27,20 @@
27
27
  "apps/minimal-test-host/README.md": "fa73136f4ee3865c2d91eb97b2e8c03679aa4688e44c1e1c8ec6e27d604b0de5",
28
28
  "docs/sdk/FILE_LAYOUT.md": "17882f96505c8161bfb66876684b9d2d3f50021a111b8b844502d3cb4e97870a",
29
29
  "docs/sdk/INTEGRATION.md": "d4c0c80d2d2fc610205102d703a429bfaa20f9f3a48f1718f5bab02ee90138df",
30
- "docs/sdk/openapi.yaml": "b15b526e2550379a1129d323c1bc9179bbb24ddaf00619c8af0b47c8a6aa6526",
30
+ "docs/sdk/openapi.yaml": "702a9cab4ccc38c186977c4bdcba653443311c676d6c7a70b7661647fa303470",
31
31
  "docs/sdk/README.md": "7ab591d39c36a3b84cfdf487ff567040ec453975f3ef0fba86dc822094667b61",
32
- "package.json": "0336e4cb683c6271d2a32a90c2aa084576a9371911ea9dfaeab05aa1f0f75df9",
32
+ "package.json": "87a7e1e85554e0d047eac03787c405d7017b5d83648a4968638553c136d0b7d1",
33
33
  "packages/client/index.d.ts": "fb66b7b21ac936cddcb7f74543cf4f3bb7e80c169534ec249ab8ef2356224162",
34
34
  "packages/client/index.js": "92fe5ddd32289d729f336f669e47bd9601e562f5a4309ee4fa7f7f15b567edc2",
35
- "packages/client/package.json": "eb5b5a83bded43afbcba5e2c8d6bb32566618339fd5744cf11f04954f2eb39c4",
35
+ "packages/client/package.json": "796d1fb39003b780248a962967ae4f0f84a5d834b2beedeedc10b958291c3645",
36
36
  "packages/client/README.md": "342dff9b1dcbc85fccc9b980ed3e4e455aa71133af1d0805b8431ea2ac564ef8",
37
37
  "packages/contracts/index.d.ts": "edc717067bfb864c6c95df0c408a799fbf90b7552519131e6dc35af3f9eb9006",
38
38
  "packages/contracts/index.js": "565b4a88190dbb8994cd0a9309b30b00f64305d65505fff9fa360d7ce69dfb58",
39
- "packages/contracts/package.json": "dae063757b282011db49389d237090ce847da8241fc6fa9b09999da52c0522a4",
39
+ "packages/contracts/package.json": "deaa5929f849f6f994df7fbb0243c77f896b8fc73edcc3c785206b898cfafa71",
40
40
  "packages/contracts/README.md": "44d83a3cc508cec6c5c20dfa1f2c08d5ea03e3afb2853639fdc0a9cc8eb5b9c8",
41
41
  "packages/core/index.d.ts": "c95b24a13f8aeeb128497833cf298790563baca6036ea5d29a9d8daff53199d7",
42
42
  "packages/core/index.js": "5579ceb1a63d3f962f5656c75f82cf60cd834fd270b4aa95e581bf38e4432448",
43
- "packages/core/package.json": "bf426f18d4f174a7c54deaec98c8b7d26e45b5e39f27873ff79336b5110710c6",
43
+ "packages/core/package.json": "6e579a889060bf6fad7709ea89a104fe4ac90854ea39107b649c44b3b83666bf",
44
44
  "packages/core/README.md": "e222c546104a168f1038d95c6c4efb8e5603edd6145ab2cab79cab977fb710e5",
45
45
  "packages/server/bin/agent-terminal-server.js": "043dff4d76e3fd213b666a55e581ed1e72f9e5b8de6cb798fbf42bd39ed26861",
46
46
  "packages/server/bin/claude-workbench-server.js": "b03c730b6d86faf6974afea26c74109d59b1bbc1ecc656c1d6270258708694ac",
@@ -57,15 +57,15 @@
57
57
  "packages/server/lib/context-resolver.js": "d3060bfe35fb184e521847fc0900cf6114f8ebf3120ce13ed39dfc224af54660",
58
58
  "packages/server/lib/conversation-capture.js": "9f3ee29003eaea4778dc1e4b7e23e868f2ba0268bd43db07317acba62f48a094",
59
59
  "packages/server/lib/diagnostics.js": "b45687fcc07f8baeb33ffd08efdc875494d4e3205887514fdfd7e1ce6370753b",
60
- "packages/server/lib/drivers/cli-json-runner.js": "c3febcea2df92b72125d053a4ffe6349e61caa98491acb6123ae964b6b90de8a",
61
- "packages/server/lib/drivers/codex-driver.js": "cb6f60048af534d836c7e95c494fbd16aa28ba24c5e94d76edb2eb9720f4cb54",
62
- "packages/server/lib/drivers/opencode-driver.js": "f79d1e9d036ff15ce0ac9e2872ffc9331efbd60edc9f610e7b6cb1dff39303fb",
63
- "packages/server/lib/drivers/zcode-driver.js": "13a53b58ef99cc73df421918a6399408a51f16f04e4ecaa5467f46480782e4cc",
60
+ "packages/server/lib/drivers/cli-json-runner.js": "d3ad5dc67481d69abb3593ca58e7ca703bf1c438042d634d83642803849d797f",
61
+ "packages/server/lib/drivers/codex-driver.js": "d472a6229aab8e3e5a568fa5f6c63de77afcf2b84c7a930101dd94e8b11a640e",
62
+ "packages/server/lib/drivers/opencode-driver.js": "322043d2d1912204c17b8c46f14d19bf132c096365cdacfdb98cfc0855e88c73",
63
+ "packages/server/lib/drivers/zcode-driver.js": "89c99e3f40c8064260d83153116c2c12acfec9485df2e495207ba3a64bb95764",
64
64
  "packages/server/lib/drivers/zcode-profile-runtime.js": "77c5ac83551cc424375918863d4a31039984492c3a1c987a615a072ac7cb1f14",
65
65
  "packages/server/lib/event-stream.js": "b0f20bac19933a1a428c22938ae2666a1231b74a4330619b885171662133f48b",
66
66
  "packages/server/lib/folder-picker.js": "70f55df999262b90433f2b4251aa69dd70a23b55a84756b5f1d24dbeacfbda31",
67
67
  "packages/server/lib/http-handler.js": "c0b1cc19c66beef0f0d9b8db48ede6b110bff59d410b81673bab2e81c05b01d7",
68
- "packages/server/lib/json-file.js": "c922e10116655cd519a5365aaac5468266f6d8a76e41db33eaa51f94b79dae13",
68
+ "packages/server/lib/json-file.js": "4252b57abcd0aafa45c584bac98fcbaf09174774addbb5a4798b381a7aeb35cc",
69
69
  "packages/server/lib/knowledge-context.js": "82023a94472fcb6fd6a74a53be43091473dbef11e6ac94ff9482c8a7fbc5c286",
70
70
  "packages/server/lib/model-detection.js": "fa52213200c1f1a1f00e463ada57c415bf1bd4e2aedfebd04de50750509d06cf",
71
71
  "packages/server/lib/profile-store.js": "70a9ff6aa31fe438ba8431f3e461f72e5d977f3510f2c42d39e9133e2f3491a8",
@@ -74,7 +74,7 @@
74
74
  "packages/server/lib/system-doctor.js": "2b0e858d69d8fb268eaed950c9883473ee9850684b532bc2db8e14674a974919",
75
75
  "packages/server/lib/ui-preferences-store.js": "e108cb22e7cc1f3438704913d5401e01de2c0e717eb2abd3bdc4727209393819",
76
76
  "packages/server/lib/workbench-service.js": "92b9323db8742bbdd69abd111c81cab86b225103596f6818b007fbfe2376fc6f",
77
- "packages/server/package.json": "e8e34475d6b9ced8622f17fe8742e6e5dbacc4295606a8bfc3dd0d3d8423ff5f",
77
+ "packages/server/package.json": "618af8f48eb5da8f163d061c1832973a0b1e8a733fb795ff9c00f56379a4d1b1",
78
78
  "packages/server/README.md": "a34cfaa4f4e859008b44e2be8e1aafb56e97fe83e6129c968a8562945fa843f3",
79
79
  "packages/ui/ai-profile-settings.d.ts": "0551b6c6eda6d18ea89a976daddf01b2161195f4874fe2d67a57cd9ecc6ce643",
80
80
  "packages/ui/ai-profile-settings.js": "e92bbac67a1199d473e4e44b32d1cc76c5b6c79306d4fef9d9067a1bb6ec42ca",
@@ -82,7 +82,7 @@
82
82
  "packages/ui/claude-terminal.js": "96bd217a4a7e4792ae3fbaaf46249ecee13b0f4e01fc6d25a1b8b22d8f8fe00c",
83
83
  "packages/ui/index.d.ts": "e547ab39640fe7519fb367b78442dc8a2c51b2efd17b66f8b0a003b154b36ead",
84
84
  "packages/ui/index.js": "f4394aabd395938f5c3fe587e430471d4033e83945a9b9c7e0149ad4040982c9",
85
- "packages/ui/package.json": "b51ed224564803725fcc24ed76802f561ef25caf63e6cb36823b74fced9f4cd4",
85
+ "packages/ui/package.json": "f5da277437bfb5308bb0cc8c998cc7b02cc92db7dd767a2242eedcad30200b81",
86
86
  "packages/ui/README.md": "793c4a9c286fee23f39062a1976ca3afe9d2816dcdb55e156ba940e1ef514f89",
87
87
  "packages/ui/theme.css": "8f03a081272a7db11b196f7a70d0fafb1f8d954778f329f1ba53d110d9d5fd98",
88
88
  "src/assets/claude-prompts.json": "cb111f2e0a45afe8a31c251a504d1ab5375966ed61291660e61fd2efd77f6d9f",
@@ -95,7 +95,7 @@
95
95
  "src/backend/lib/ai-vendor-presets.js": "02c6de9c2e89ad0286426e8eb4900c3c6a4960ef0e8f9d27ffb5836062abfbb2",
96
96
  "src/backend/lib/ai-workspace.js": "969917f26cd0b0a272932714819d838a2bab2a5aac5c4e946647dfa3afa479bf",
97
97
  "src/backend/lib/automation-config.js": "c23b868bbcfbcece4465c9c939faccaef582667e858f3f36fc7b6d19bcd545e6",
98
- "src/backend/lib/claude-cli-runner.js": "05cc4e57e7e52721de8d9e14eff1f37424bd094796bbbc70fcbca0a6c203d868",
98
+ "src/backend/lib/claude-cli-runner.js": "d72ab781fc9b7194fcb4ea44dd8b7d6ef3a8812924af261d37859e8e5602d379",
99
99
  "src/backend/lib/data-dir.js": "a62d96d1ab538e37690ad31fe4f51e84120b55b6bc767661ed98ad9242f879db",
100
100
  "src/backend/lib/llm-client.js": "76d1a73fbea445b5ac34c23d1a3b084e0884c5efed6f7d3b9ed76d406d2cd038",
101
101
  "src/backend/lib/model-context-windows.js": "f64f7c995143407b7390105087e3ebcd56a5a3ba2fd3019478a86f9e3c6b7896",
@@ -112,9 +112,9 @@
112
112
  "vectorHub": {
113
113
  "name": "@sanqianx/vector-hub",
114
114
  "installName": "@sanqianx/vector-hub",
115
- "version": "1.0.8-rc.1",
115
+ "version": "1.0.8-rc.2",
116
116
  "files": {
117
- "README.md": "801e0d2f258bc6d386b7ab44e1d8157c9f48d9c979b84c813773c34a9ee358c1",
117
+ "README.md": "b0d0fd647aef14c803ac4573f58bd2d425c2dc9bc736187a4684d7caba473184",
118
118
  "dist/cjs/bin.d.ts": "43e818adf60173644896298637f47b01d5819b17eda46eaa32d0c7d64724d012",
119
119
  "dist/cjs/bin.js": "8d0317ce087d22074b4ad350d63bf39cd6d218da565496621cd0daf4245cbdc4",
120
120
  "dist/cjs/bin.js.map": "818e872380d9c7ba045238ba65ce77111ba822b356be26327ed05936e5667e5e",
@@ -136,12 +136,12 @@
136
136
  "dist/cjs/server/folder-picker.d.ts": "b9c59dbc834fff668b1894f516450c2edc985c7bfac31edf9b7b4e766474b32b",
137
137
  "dist/cjs/server/folder-picker.js": "053121152a210c899e8593d60670a2a510b435c3b479300c572aa4bc8443e58e",
138
138
  "dist/cjs/server/folder-picker.js.map": "dce1ad1b03c8a6a4fba7b3cacec5b65e55c1dfd1886c5e70df384efd1a5c68a6",
139
- "dist/cjs/server/manager.d.ts": "8aeb6b7d6e5f8ef94b65d0c078a3333b39e03546b2fc3cf8c0c0e144db4cff01",
140
- "dist/cjs/server/manager.js": "1faed06b5efd6bea357ebf86e09af13791277fa07258eacc602af2945ae42845",
141
- "dist/cjs/server/manager.js.map": "0d42dc88ad03bc723971a4967fb16b4fbf734ba06845e10ff10d85cf98c7b130",
139
+ "dist/cjs/server/manager.d.ts": "d23ee9c3f9b72ff89c511f81f5cfb6e2b62d4ba4963099c3c9f5a65531216097",
140
+ "dist/cjs/server/manager.js": "aea5c81a048cf2bd7736c289dbee9cf2d0bea4caf7093a1d8f8179d6fcea48a3",
141
+ "dist/cjs/server/manager.js.map": "594ac93b2986160e47f927683f2f5feee84054dbf7255d965ada9dea561845b8",
142
142
  "dist/cjs/server/server.d.ts": "13288ace9aa6ec016a2b06dc036868324ac6c23c7e73771e95d120be778f238a",
143
- "dist/cjs/server/server.js": "8b42771d2d1c4f18f51f1d7c305edd702bf86b009ea14e5f02d133a46de3c141",
144
- "dist/cjs/server/server.js.map": "701f115fb78fcca13723568fc7514a290acff9dc3fe63c9104a35bdb7120459e",
143
+ "dist/cjs/server/server.js": "43d6e18a1a36fd1af6179ff98d356efaee1da9464c85d76e9bf057b71741534e",
144
+ "dist/cjs/server/server.js.map": "d599dbfbe0f98abaf103849eafee70b407d332ff0d767c1d95f54c80e85bf2bb",
145
145
  "dist/esm/bin.d.ts": "43e818adf60173644896298637f47b01d5819b17eda46eaa32d0c7d64724d012",
146
146
  "dist/esm/bin.js": "69f6059ce2336eb7f0d9503f86c83da787aaf74a8bfd804c694ba5b2e1728be0",
147
147
  "dist/esm/bin.js.map": "fc174c2b5c66c20ff88184ddeb00577406185945ccadb0bddbb2014909339e9e",
@@ -164,13 +164,13 @@
164
164
  "dist/esm/server/folder-picker.d.ts": "b9c59dbc834fff668b1894f516450c2edc985c7bfac31edf9b7b4e766474b32b",
165
165
  "dist/esm/server/folder-picker.js": "6c8247e431b7181c45fb169b29e5825a0b3589f44e1625b3a5a291d7b8358042",
166
166
  "dist/esm/server/folder-picker.js.map": "f70723213f032a0f10f538289a176a50fc8f02c200b0194479ffc139b5fbb13b",
167
- "dist/esm/server/manager.d.ts": "8aeb6b7d6e5f8ef94b65d0c078a3333b39e03546b2fc3cf8c0c0e144db4cff01",
168
- "dist/esm/server/manager.js": "4f9c7a4cb12c7ac6d13f43ce37a8e2984bf1b4229feddb412f08ace12ca6859b",
169
- "dist/esm/server/manager.js.map": "286cadd292ff7225a5faaa0946fb3b127e0ede488f1cae9f33aac2c7ec8f7726",
167
+ "dist/esm/server/manager.d.ts": "d23ee9c3f9b72ff89c511f81f5cfb6e2b62d4ba4963099c3c9f5a65531216097",
168
+ "dist/esm/server/manager.js": "2f1772ce5885128694e8cd9c89ca7ae74694a1f85758fc8e17b577b7ab54c2e4",
169
+ "dist/esm/server/manager.js.map": "f68a87c9763e8c4e3ddfc98e981ada4ea83922793035f19051b88dc3e7f47bc0",
170
170
  "dist/esm/server/server.d.ts": "13288ace9aa6ec016a2b06dc036868324ac6c23c7e73771e95d120be778f238a",
171
- "dist/esm/server/server.js": "357f53c83ded73318016256fbb752e78b90f3a94aecfca71607de8326cad9ebf",
172
- "dist/esm/server/server.js.map": "97d1cbd3a4fff6ab0cb7994df6c5b73daea03a0dd9c8a1841cec5bb7be82e66c",
173
- "package.json": "acb511c809a53643d2ee501a58bb08c74fc85edbac0ecbc35d8f3e7c549389d3",
171
+ "dist/esm/server/server.js": "df4caa8a596a9724c526dab5395e5018f63164ef0d10522d75ca4c44d62c1ee3",
172
+ "dist/esm/server/server.js.map": "3743325b664476176931989f2d762d53b48c5eb4bcbf3d81ab222c4231d026be",
173
+ "package.json": "812251c1b6f091da2f7ab06c93446e5f7c19bf4715074919e38e956e0eca373b",
174
174
  "ui/index.html": "7301a595d625dadcd424069e7bb978004bfb6118eddef7a223bd25449ca6e0eb",
175
175
  "ui/vendor/marked.min.js": "c68075672d976e4777390560baa112194855bd4404b13647da4855aae1f9360c"
176
176
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanqianx/project-knowledge",
3
- "version": "5.0.9-rc.6",
3
+ "version": "5.0.9-rc.8",
4
4
  "description": "Knowledge base manager with Git integration, AI-driven analysis, and bilingual (zh-CN/en-US) knowledge output",
5
5
  "main": "_site/server.js",
6
6
  "scripts": {
@@ -81,10 +81,10 @@
81
81
  "@lancedb/lancedb": "0.31.0",
82
82
  "@modelcontextprotocol/sdk": "1.29.0",
83
83
  "@sanqianx/ai-coding-event-bridge-console": "0.7.2",
84
- "@sanqianx/vector-hub": "1.0.8-rc.1",
84
+ "@sanqianx/vector-hub": "1.0.8-rc.2",
85
85
  "buffer": "^6.0.3",
86
86
  "cheerio": "^1.2.0",
87
- "claude-ai-workbench": "npm:@sanqianx/claude-ai-workbench@0.13.2-rc.3",
87
+ "claude-ai-workbench": "npm:@sanqianx/claude-ai-workbench@0.13.2-rc.4",
88
88
  "cross-spawn": "7.0.6",
89
89
  "dotenv": "^17.4.2",
90
90
  "gpt-tokenizer": "^3.4.0",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
3
3
  "name": "project-knowledge",
4
- "version": "5.0.9-rc.6",
4
+ "version": "5.0.9-rc.8",
5
5
  "description": "Read durable project decisions and implementation history from Project Knowledge.",
6
6
  "author": {
7
7
  "name": "SanQianX",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-knowledge",
3
- "version": "5.0.9-rc.6",
3
+ "version": "5.0.9-rc.8",
4
4
  "description": "Read durable project decisions and implementation history from Project Knowledge.",
5
5
  "author": {
6
6
  "name": "SanQianX",
@@ -6,7 +6,7 @@
6
6
  "args": [
7
7
  "-y",
8
8
  "--package",
9
- "@sanqianx/project-knowledge@5.0.9-rc.6",
9
+ "@sanqianx/project-knowledge@5.0.9-rc.8",
10
10
  "project-knowledge-mcp"
11
11
  ]
12
12
  }
package/ui/index.html CHANGED
@@ -40,7 +40,7 @@
40
40
  <section id="agentCaptureSection"><div class="actions"><h3>外部 Agent 采集</h3><button id="refreshAgentCapture">检查状态</button></div><p class="muted">只接入你使用的工具。采集外部开发会话,不会重新安装 Agent,也不影响已有记录。</p><div id="agentCaptureList"></div><p id="agentCaptureFeedback" class="feedback" role="status"></p></section>
41
41
  <section><h3>后台维护模型</h3><p class="muted">使用持久化默认模型,不跟随聊天中的临时切换。</p><select id="maintenanceModel" aria-label="后台维护默认模型"></select><div class="actions"><button id="saveMaintenance">保存默认模型</button><button id="configureProviders">管理模型供应商</button></div><p id="configurationStatus" class="muted"></p></section>
42
42
  <section><h3>向量检索模型</h3><p id="embeddingStatus" class="muted">正在读取配置。</p><button id="openEmbedding">配置向量模型</button><p class="muted">凭据由工作台统一保存。未配置时仍可使用文本检索。</p></section>
43
- <section><h3>智脑设置</h3><label>名称<input id="brainName" maxlength="100"></label><label>知识根目录<div class="input-with-action"><input id="knowledgeRoot"><button id="pickRoot">选择</button></div></label><p class="muted">修改根目录不会移动已有项目知识或共享知识。</p><button id="saveBrainSettings">保存设置</button></section>
43
+ <section><h3>智脑设置</h3><label>名称<input id="brainName" maxlength="100"></label><label>知识根目录<div class="input-with-action"><input id="knowledgeRoot"><button id="pickRoot">选择</button></div></label><label>向量索引目录<output id="indexStoragePath" class="detail-path"></output></label><p id="indexStorageStatus" class="muted"></p><p class="muted">索引跟随知识根目录,可重新构建;切换时原索引保留,已有项目知识与共享知识不移动。</p><button id="saveBrainSettings">保存设置</button></section>
44
44
  <section><div class="actions"><button id="openEngine">知识引擎诊断</button><button id="openLogs">系统诊断记录</button></div><p class="muted">诊断不影响正在进行的会话与维护。</p></section>
45
45
  </div>
46
46
  </aside>
package/ui/product.js CHANGED
@@ -159,6 +159,7 @@
159
159
  const [brain, projects, health] = await Promise.all([api('/api/brain'), api('/api/projects/aggregated'), api('/api/modules/health')]);
160
160
  if (epoch !== registryEpoch) return;
161
161
  state.brain = brain.brain; state.root = brain.knowledgeRoot; state.projects = projects.projects; state.health = health.modules; state.ownership = health.ownership;
162
+ state.indexStorage = { path: brain.indexStoragePath, ...brain.configuration?.indexStorage };
162
163
  if (!activeProject()) { state.projectId = state.projects[0]?.projectId || ''; state.epoch++; Object.keys(frames).forEach(frameContext); }
163
164
  renderProjectOptions(); renderSystem(); connectProgress(); await refreshSnapshot(); setView(state.view);
164
165
  } catch (error) { toast(error.message); }
@@ -170,9 +171,12 @@
170
171
  function renderSystem() {
171
172
  const down = Object.keys(modules).filter(key => !state.health[key]?.up);
172
173
  const pending = state.ownership?.owner === 'engine' && !state.ownership.ready;
174
+ const storagePending = !!state.indexStorage?.expectedPath && state.indexStorage.status !== 'ready';
175
+ renderStorageInfo();
173
176
  $('systemDot').className = `dot ${down.length || pending ? 'issue' : 'up'}`;
174
177
  $('systemTitle').textContent = pending ? '知识引擎连接待恢复' : down.length ? '部分服务需要处理' : '系统连接正常';
175
178
  $('systemDetail').textContent = pending ? `${state.ownership.message || '服务恢复后自动重试。'}${state.ownership.error ? ` · ${state.ownership.error.step} (${state.ownership.error.code})` : ''}` : down.length ? down.map(k => modules[k]).join('、') : '本机知识服务已连接';
179
+ if (storagePending && !pending && !down.length) { $('systemDot').className = 'dot issue'; $('systemTitle').textContent = '索引目录接线待恢复'; $('systemDetail').textContent = `目标目录:${state.indexStorage.expectedPath}。请在系统状态中修复接线。`; }
176
180
  $('moduleHealth').innerHTML = Object.entries(modules).map(([key, name]) => `<div class="row"><div><b>${esc(name)}</b><small>${esc(state.health[key]?.url || '')}</small></div>${badge(state.health[key]?.up ? '在线' : '离线', state.health[key]?.up ? 'up' : 'issue')}</div>`).join('');
177
181
  if (!navigator.onLine) {
178
182
  $('systemDot').className = 'dot issue'; $('systemTitle').textContent = '网页连接中断';
@@ -183,8 +187,13 @@
183
187
  async function openSystem() {
184
188
  $('systemDrawer').hidden = false; $('drawerBackdrop').hidden = false;
185
189
  $('brainName').value = state.brain.name; $('knowledgeRoot').value = state.root;
190
+ renderStorageInfo();
186
191
  await Promise.all([loadMaintenance(), loadAgentCapture()]);
187
192
  }
193
+ function renderStorageInfo() {
194
+ $('indexStoragePath').textContent = state.indexStorage?.actualPath || state.indexStorage?.path || '设置知识根目录后自动确定';
195
+ $('indexStorageStatus').textContent = state.indexStorage?.status === 'ready' ? '索引目录已生效。' : `索引接线待恢复;目标目录:${state.indexStorage?.expectedPath || state.indexStorage?.path || '尚未设置'}`;
196
+ }
188
197
  async function loadAgentCapture() {
189
198
  const epoch = ++captureEpoch;
190
199
  try {
@@ -376,7 +385,7 @@
376
385
  on('embeddingForm', 'submit', async event => { event.preventDefault(); await saveEmbedding(); });
377
386
  on('disableEmbedding', 'click', () => saveEmbedding(false));
378
387
  on('embeddingDialog', 'close', () => { $('embeddingSecret').value = ''; });
379
- on('saveBrainSettings', 'click', async () => { await api('/api/brain', { method: 'PATCH', body: { name: $('brainName').value } }); await api('/api/settings', { method: 'PATCH', body: { knowledge: { rootPath: $('knowledgeRoot').value } } }); toast('设置已保存,已有知识未移动。'); await refreshRegistry(); if (resumeImport) closeSystem(); });
388
+ on('saveBrainSettings', 'click', async () => { await api('/api/brain', { method: 'PATCH', body: { name: $('brainName').value } }); const saved = await api('/api/settings', { method: 'PATCH', body: { knowledge: { rootPath: $('knowledgeRoot').value } } }); toast(saved.configuration?.indexStorage?.status === 'ready' ? '设置已保存,索引目录已生效;已有知识未移动。' : '设置已保存,索引目录接线待恢复;已有知识保留。'); await refreshRegistry(true); if (resumeImport) closeSystem(); });
380
389
  on('setupImportRoot', 'click', async () => { $('importDialog').close(); resumeImport = true; await openSystem(); $('knowledgeRoot').focus(); });
381
390
  on('pickRoot', 'click', () => pick('knowledgeRoot')); on('pickCode', 'click', () => pick('importCode')); on('pickKnowledge', 'click', () => pick('importKnowledge'));
382
391
  on('openEngine', 'click', () => { closeSystem(); initializeFrame('engine'); $('engineDialog').showModal(); post('engine', { type: 'kb:visibility', visible: true }); });
@@ -3,11 +3,11 @@
3
3
  "modules": {
4
4
  "knowledge-engine": {
5
5
  "name": "@sanqianx/ai-coding-knowledge-engine",
6
- "version": "0.2.3-rc.2",
6
+ "version": "0.2.3-rc.3",
7
7
  "root": "_modules/knowledge-engine",
8
8
  "files": {
9
- "README.md": "371d8faaf36f2e9d4edd524ee8c17a064d3c0b819fffedc4e1449d1ac0273eae",
10
- "package.json": "74aaed9a82d59ecaa2b528ccf6164ed44c495347b35fba004c64a82edaad2fb4",
9
+ "README.md": "c367f328a0770bf0c53e80e4cfb7b3f7815589312e793755ec00b677b84e601c",
10
+ "package.json": "6f0dc1fecb5d3bd0da4c1714977cf2e5f767fb49cb54ec92caff08fff1ebec6d",
11
11
  "src/analysis-contract.js": "fee063967d32eefc955cf0729f7dc8cb31bd690b85e22471c9059494a599c77a",
12
12
  "src/analysis-output.js": "95a3c19dcc9ab85d1dba7fee5b9aec80f9c000dfba89da3fd0be25a81e2fb680",
13
13
  "src/analysis-worker.js": "a105cabe6e1573b2d986b1e7a5aaf615e2fb53524156fc8e4e2c0a71f2c97e55",
@@ -18,7 +18,7 @@
18
18
  "src/headless-analyzer.js": "cfe54b392b2aff6e2c5157481dfeb5ccebc4ce83d1d74aa44f28cf2eb923b013",
19
19
  "src/index-request.js": "78f26b872299005499fff4f2d1f9e8f986784f2ff36a5cf2be2b1e7b7c7d9378",
20
20
  "src/memories.js": "0a8667e6daba99fa5022393951a28e96cdadf98af85b6af9a6be96c7f4e896fc",
21
- "src/retrieval.js": "c70bbe85fc821f41b3de6649f77ba96288f253d18b1aa279c9395673121909ee",
21
+ "src/retrieval.js": "bbb09cefc3c6ed692a51edfeecf6ac50619b8a2afbdf2034e0fdb5e00f4cfa68",
22
22
  "src/runtime/README.md": "9be676eca76a7857b34d7357194e6f0ee733c22e61d962d53984715dbec7f673",
23
23
  "src/runtime/atomic-file.js": "9846b4b69db5ded811acf19a1181ef93615d93efaa542b858e552a7f3124ad23",
24
24
  "src/runtime/automation-config.js": "6498c5397be12b155829740595a1553d4dcd6eaa7db6ced3ef88fdc60218f00e",