@sanqianx/project-knowledge 5.0.4 → 5.0.5

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.4",
12
+ "version": "5.0.5",
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,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.0.5] - 2026-10-10
4
+
5
+ - Invalidate in-flight registry snapshots after domain creation, project import,
6
+ ownership changes and wiring repair. A read begun before the write cannot
7
+ hide the newly registered data until the next polling cycle.
8
+ - Includes all knowledge-maintenance, Claude discovery and local diagnostic
9
+ fixes from 5.0.3, plus exact commit retrieval from 5.0.4. No schema migration
10
+ or automatic replay of failed model tasks.
11
+
3
12
  ## [5.0.4] - 2026-10-10
4
13
 
5
14
  - Vendor engine 0.2.2: treat a known full/prefix commit SHA as a provenance
@@ -18,6 +18,8 @@ assert.equal((script.match(/\.src = /g) || []).length, 1, 'frames initialize onc
18
18
  for (const contract of ['kb:theme', 'kb:select-project', 'kb:scope', 'kb:knowledge', 'kb:ready']) assert.ok(script.includes(contract));
19
19
  assert.ok(script.includes('event.origin !== location.origin') && script.includes('contentWindow === event.source'), 'module messages must be from the expected frame and origin');
20
20
  assert.ok(script.includes('state.epoch++') && script.includes('referenceEpoch') && script.includes('logEpoch'), 'late project/reference/log feedback must be isolated');
21
+ assert.match(script, /on\('domainForm'[\s\S]*?await refreshRegistry\(true\)/, 'domain writes must invalidate pre-mutation reads');
22
+ assert.match(script, /registered = true;[\s\S]*?await refreshRegistry\(true\)/, 'import must not reuse a pre-import snapshot');
21
23
  assert.ok(script.includes('esc(r.title)') && script.includes('esc(m.text)') && script.includes('esc(project.name)'));
22
24
  assert.ok(script.includes('text.textContent = record.message') && script.includes("'logs/appended'"), 'diagnostics stay inert and stream live');
23
25
  assert.ok(script.includes('URL.revokeObjectURL(url)') && script.includes('logStream?.close()'));
@@ -2,7 +2,7 @@
2
2
  "schema": "project-knowledge/module-content/v1",
3
3
  "productFiles": {
4
4
  "ui/index.html": "e7291caab778eba3c5499d8286804ad1f4ef31c87a957f69c8fb77befc01321b",
5
- "ui/product.js": "1a6ddedd97b00c3f798c13a0a55b0f63790e701483492bc97d28cae4034efaf8",
5
+ "ui/product.js": "e35c1650df239cec0a9d73197fed7ac069bb09f0c51f4752e03115784a526518",
6
6
  "ui/product.css": "73554abf3f951ea01a2bfe2df81748b702a6ca4488eea16bfe5afe04ef1dea70"
7
7
  },
8
8
  "modules": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanqianx/project-knowledge",
3
- "version": "5.0.4",
3
+ "version": "5.0.5",
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": {
@@ -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.4",
4
+ "version": "5.0.5",
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.4",
3
+ "version": "5.0.5",
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.4",
9
+ "@sanqianx/project-knowledge@5.0.5",
10
10
  "project-knowledge-mcp"
11
11
  ]
12
12
  }
package/ui/product.js CHANGED
@@ -291,7 +291,7 @@
291
291
  const result = await api(`/api/projects/${encodeURIComponent(project.projectId)}/module-register`, { method: 'POST', body: {} });
292
292
  const pending = Object.entries(result.modules).filter(([, v]) => !v.ok).map(([key]) => modules[key]);
293
293
  $('wiringFeedback').textContent = pending.length ? `项目已登记,待恢复:${pending.join('、')}` : '四个模块已连接。';
294
- toast($('wiringFeedback').textContent); await refreshRegistry(); Object.keys(frames).forEach(frameContext);
294
+ toast($('wiringFeedback').textContent); await refreshRegistry(true); Object.keys(frames).forEach(frameContext);
295
295
  }
296
296
  async function pick(target) {
297
297
  const result = await api('/api/terminal/system/pick-folder');
@@ -350,7 +350,7 @@
350
350
  };
351
351
  execute().catch(error => toast(error.message));
352
352
  });
353
- document.addEventListener('change', e => { if (e.target.id === 'projectDomain') api(`/api/projects/${encodeURIComponent(state.projectId)}`, { method: 'PATCH', body: { domainId: e.target.value || null } }).then(refreshRegistry).catch(error => toast(error.message)); });
353
+ document.addEventListener('change', e => { if (e.target.id === 'projectDomain') api(`/api/projects/${encodeURIComponent(state.projectId)}`, { method: 'PATCH', body: { domainId: e.target.value || null } }).then(() => refreshRegistry(true)).catch(error => toast(error.message)); });
354
354
  window.addEventListener('message', event => {
355
355
  if (event.origin !== location.origin || !event.data || typeof event.data !== 'object') return;
356
356
  const key = Object.keys(frames).find(k => $(frames[k].id).contentWindow === event.source); if (!key) return;
@@ -393,7 +393,7 @@
393
393
  on('loadLogs', 'click', loadLogs);
394
394
  on('exportLogs', 'click', async () => { const params = new URLSearchParams({ q: $('logsSearch').value.trim() }); if ($('logsScope').value === 'project' && state.projectId) params.set('projectId', state.projectId); const response = await fetch(`/api/logs/export?${params}`); if (!response.ok) throw new Error('诊断导出失败。'); const blob = await response.blob(); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = 'knowledge-diagnostics.jsonl'; link.click(); setTimeout(() => URL.revokeObjectURL(url), 1000); });
395
395
  on('createDomain', 'click', () => { $('domainForm').reset(); $('domainDialog').showModal(); });
396
- on('domainForm', 'submit', async e => { e.preventDefault(); await api('/api/domains', { method: 'POST', body: Object.fromEntries(new FormData(e.target)) }); $('domainDialog').close(); await refreshRegistry(); });
396
+ on('domainForm', 'submit', async e => { e.preventDefault(); await api('/api/domains', { method: 'POST', body: Object.fromEntries(new FormData(e.target)) }); $('domainDialog').close(); await refreshRegistry(true); });
397
397
  on('memoryForm', 'submit', async e => { e.preventDefault(); await api(`/api/engine/memories/${encodeURIComponent(editingMemoryId)}`, { method: 'PATCH', body: { text: $('memoryText').value } }); $('memoryDialog').close(); await refreshSnapshot(); });
398
398
  on('unbindForm', 'submit', async e => {
399
399
  e.preventDefault(); if (!unbindProjectId || unbinding) return;
@@ -423,7 +423,7 @@
423
423
  e.preventDefault(); if (!state.preflight?.ready || state.preflight.plannedGitInit && !$('importForm').elements.confirmGitInit.checked || state.preflight.checks.hook?.replacementProjectId && !$('importForm').elements.confirmReplaceHook.checked) return;
424
424
  $('confirmImport').disabled = true; $('confirmImport').textContent = '正在登记…';
425
425
  let failed = false, registered = false;
426
- try { const result = await api('/api/projects/import', { method: 'POST', body: importInput() }); registered = true; state.projectId = result.projectId; state.epoch++; $('importDialog').close(); await refreshRegistry(); Object.keys(frames).forEach(frameContext); setView('projects'); toast(Object.values(result.modules).every(m => m.ok) ? '项目已导入,四个模块已连接。' : '项目已导入,部分接线待恢复。'); }
426
+ try { const result = await api('/api/projects/import', { method: 'POST', body: importInput() }); registered = true; state.projectId = result.projectId; state.epoch++; $('importDialog').close(); await refreshRegistry(true); Object.keys(frames).forEach(frameContext); setView('projects'); toast(Object.values(result.modules).every(m => m.ok) ? '项目已导入,四个模块已连接。' : '项目已导入,部分接线待恢复。'); }
427
427
  catch (error) {
428
428
  failed = true;
429
429
  if (registered) { toast(`项目已登记,但页面状态刷新失败:${error.message}`); return; }