@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.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +9 -0
- package/_site/_test/workspace-ui-contract-test.js +2 -0
- package/module-runtime-manifest.json +1 -1
- package/package.json +1 -1
- package/plugins/project-knowledge/.claude-plugin/plugin.json +1 -1
- package/plugins/project-knowledge/.codex-plugin/plugin.json +1 -1
- package/plugins/project-knowledge/.mcp.json +1 -1
- package/ui/product.js +4 -4
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": "
|
|
5
|
+
"ui/product.js": "e35c1650df239cec0a9d73197fed7ac069bb09f0c51f4752e03115784a526518",
|
|
6
6
|
"ui/product.css": "73554abf3f951ea01a2bfe2df81748b702a6ca4488eea16bfe5afe04ef1dea70"
|
|
7
7
|
},
|
|
8
8
|
"modules": {
|
package/package.json
CHANGED
|
@@ -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
|
+
"version": "5.0.5",
|
|
5
5
|
"description": "Read durable project decisions and implementation history from Project Knowledge.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "SanQianX",
|
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; }
|