@sanqianx/project-knowledge 5.0.3 → 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 +17 -0
- package/_modules/knowledge-engine/package.json +1 -1
- package/_modules/knowledge-engine/src/retrieval.js +17 -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/vendor-manifest.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
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
|
+
|
|
12
|
+
## [5.0.4] - 2026-10-10
|
|
13
|
+
|
|
14
|
+
- Vendor engine 0.2.2: treat a known full/prefix commit SHA as a provenance
|
|
15
|
+
identifier. Unrelated high-scoring vector chunks cannot crowd out the matching
|
|
16
|
+
current knowledge. Preserve ordinary semantic ranking and current-file truth;
|
|
17
|
+
overwritten documents are not attributed to their earlier commit.
|
|
18
|
+
- Includes the empty-knowledge and Claude discovery/diagnostic fixes from 5.0.3.
|
|
19
|
+
|
|
3
20
|
## [5.0.3] - 2026-10-10
|
|
4
21
|
|
|
5
22
|
- Pin Workbench 0.13.1: reject stale Claude executable overrides without hiding
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanqianx/ai-coding-knowledge-engine",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
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",
|
|
@@ -7,6 +7,23 @@ const { DomainError } = require('./runtime/contracts');
|
|
|
7
7
|
|
|
8
8
|
class EngineRetrieval extends KnowledgeRetrievalService {
|
|
9
9
|
constructor(options) { super(options); this.store = options.store; this.memories = options.memories; this.vectorUrl = options.vectorUrl || 'http://127.0.0.1:8787'; }
|
|
10
|
+
signalSet(input = {}) {
|
|
11
|
+
const signals = super.signalSet(input);
|
|
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;
|
|
14
|
+
return signals;
|
|
15
|
+
}
|
|
16
|
+
score(candidate, signals) {
|
|
17
|
+
if (signals.commitPrefix) {
|
|
18
|
+
// A known commit is an identifier, not a semantic topic. Unrelated
|
|
19
|
+
// vector hits must not crowd its current, provenance-checked files out.
|
|
20
|
+
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: [] };
|
|
22
|
+
const result = super.score(candidate, signals);
|
|
23
|
+
return { score: Math.max(1, result.score), selectionSignals: [...result.selectionSignals, 'exact-commit'] };
|
|
24
|
+
}
|
|
25
|
+
return super.score(candidate, signals);
|
|
26
|
+
}
|
|
10
27
|
resolve(input = {}) {
|
|
11
28
|
let project = this.store.getProject(input.projectId || input.projectSlug || input.project);
|
|
12
29
|
if (!project && (input.repoPath || input.path)) project = this.store.listProjects().find(p => this.layout.pathsEqual(p.repoPath, input.repoPath || input.path));
|
|
@@ -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; }
|
package/vendor-manifest.json
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
"modules": {
|
|
4
4
|
"knowledge-engine": {
|
|
5
5
|
"name": "@sanqianx/ai-coding-knowledge-engine",
|
|
6
|
-
"version": "0.2.
|
|
6
|
+
"version": "0.2.2",
|
|
7
7
|
"root": "_modules/knowledge-engine",
|
|
8
8
|
"files": {
|
|
9
9
|
"README.md": "236dafd8092e13ab731d4a14548e04c4ad3126bdfa63c706a6afe6f9b1dc535d",
|
|
10
|
-
"package.json": "
|
|
10
|
+
"package.json": "4fe13c333017a073431c4b730c000a30d2be81012dbb8881dcae3167e3c38643",
|
|
11
11
|
"src/analysis-contract.js": "fee063967d32eefc955cf0729f7dc8cb31bd690b85e22471c9059494a599c77a",
|
|
12
12
|
"src/analysis-output.js": "95a3c19dcc9ab85d1dba7fee5b9aec80f9c000dfba89da3fd0be25a81e2fb680",
|
|
13
13
|
"src/analysis-worker.js": "a105cabe6e1573b2d986b1e7a5aaf615e2fb53524156fc8e4e2c0a71f2c97e55",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"src/diagnostics.js": "1ad8b21e0f26d7c18861d51c711a6d36e5070658205cab19727494279f0801e4",
|
|
18
18
|
"src/headless-analyzer.js": "cfe54b392b2aff6e2c5157481dfeb5ccebc4ce83d1d74aa44f28cf2eb923b013",
|
|
19
19
|
"src/memories.js": "0a8667e6daba99fa5022393951a28e96cdadf98af85b6af9a6be96c7f4e896fc",
|
|
20
|
-
"src/retrieval.js": "
|
|
20
|
+
"src/retrieval.js": "b3ae3f701a007e3d3ff98811bb80db3505e2fcc87f94aaa9e36057edc7eb71c2",
|
|
21
21
|
"src/runtime/README.md": "9be676eca76a7857b34d7357194e6f0ee733c22e61d962d53984715dbec7f673",
|
|
22
22
|
"src/runtime/atomic-file.js": "9846b4b69db5ded811acf19a1181ef93615d93efaa542b858e552a7f3124ad23",
|
|
23
23
|
"src/runtime/automation-config.js": "6498c5397be12b155829740595a1553d4dcd6eaa7db6ced3ef88fdc60218f00e",
|