@sanqianx/project-knowledge 5.0.16-rc.4 → 5.0.16-rc.6
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 +13 -0
- package/_site/_test/codex-marketplace-scoped-path-test.js +186 -0
- package/_site/_test/test-server-module-isolation-test.js +37 -0
- package/_site/lib/integration-installer.js +27 -7
- package/docs/leader-glm-workbench-playbook.md +3 -1
- package/docs/release-5.0.16-acceptance.md +20 -0
- package/module-runtime-manifest.json +13 -13
- package/package.json +2 -2
- 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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [5.0.16-rc.6] - 2026-10-15
|
|
4
|
+
|
|
5
|
+
- 修复 Codex 0.137 将 scoped npm 目录中的 `@` 误作 Git ref:本地目录含 `@` 时从该目录执行 `marketplace add .`,更换和回退分别使用自己的工作目录,不复制目录、不访问 GitHub。
|
|
6
|
+
- CLI 子操作日志关联原操作 ID,允许继续处理的失败仍记录安全诊断;本地路径误判保留 `CODEX_LOCAL_SOURCE_REF`,不写入原始 CLI 输出。
|
|
7
|
+
- 保留 rc.5 的已验证四模块版本、索引与知识功能。rc.5 本机保真升级已通过:7 项目、43 历史文件、565 索引文件保留;真实记忆闭环与双 Node 浏览器门禁通过,热查询 P95 为 693ms(1000 文档合成语料)。
|
|
8
|
+
- 本机 Codex 已通过原生本地市场操作恢复,MCP 声明入口 initialize/六工具/resolve/search/get 验证通过;Hook 尚待用户审核,不计自动上下文通过。候选不更新 latest。
|
|
9
|
+
|
|
10
|
+
## [5.0.16-rc.5] - 2026-10-15
|
|
11
|
+
|
|
12
|
+
- 精确锁定 Workbench 0.13.2-rc.13:模型目录加载失败不再伪装成空目录;保留上次有效结果,提供明确错误与重试,打开菜单可恢复请求,关闭菜单后的迟到响应不会重开菜单。保存或删除供应商后不复用保存前的旧快照,普通菜单打开仍共享请求。
|
|
13
|
+
- 保留 rc.4 的引擎与向量检索修复;模型菜单错误不显示原始异常或凭据。补充连续保存的竞态回归及测试服务器模块隔离,安装版故障恢复仍须单独验收。
|
|
14
|
+
- Leader 负责关键开发和发布收尾,GLM 并行独立做故障测试与审查。候选发布到 next,不改变 latest。
|
|
15
|
+
|
|
3
16
|
## [5.0.16-rc.4] - 2026-10-14
|
|
4
17
|
|
|
5
18
|
- 引擎 0.2.7-rc.7 复用同一次检索刚读取的知识正文,保留晚到响应后的文件与范围校验;vector-hub 1.0.8-rc.8 将有界查询缓存延长到 10 分钟,并防止旧请求失败删除新缓存。源码真实向量热查询 P95 为 1069ms,不代表安装版验收通过。
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// Red-first regression (Q7): Codex CLI 0.137 rejects
|
|
3
|
+
// `plugin marketplace add <SOURCE>` with
|
|
4
|
+
// "Error: --ref is only supported for git marketplace sources"
|
|
5
|
+
// whenever the SOURCE string contains '@', which every scoped npm root
|
|
6
|
+
// (node_modules/@sanqianx/project-knowledge) does. Running the same add from
|
|
7
|
+
// the package directory's own cwd with SOURCE '.' avoids the '@' entirely.
|
|
8
|
+
// ensureCodexMarketplace() must use that form for the target add and for the
|
|
9
|
+
// rollback re-add of a previous scoped root, while non-'@' absolute paths keep
|
|
10
|
+
// the original invocation and third-party same-name sources stay untouched.
|
|
11
|
+
const assert = require('node:assert/strict');
|
|
12
|
+
const fs = require('node:fs');
|
|
13
|
+
const os = require('node:os');
|
|
14
|
+
const path = require('node:path');
|
|
15
|
+
const { IntegrationManager } = require('../lib/integration-installer');
|
|
16
|
+
|
|
17
|
+
const TEMP_BASE = fs.mkdtempSync(path.join(os.tmpdir(), 'codex-marketplace-scoped-path-'));
|
|
18
|
+
const TEST_HOME = path.join(TEMP_BASE, 'home');
|
|
19
|
+
const MARKETPLACE = 'project-knowledge';
|
|
20
|
+
const REF_ERROR = 'Error: --ref is only supported for git marketplace sources';
|
|
21
|
+
const NEW_ROOT = path.join(TEMP_BASE, 'new-root', '@sanqianx', 'project-knowledge');
|
|
22
|
+
const OLD_ROOT = path.join(TEMP_BASE, 'old-root', '@sanqianx-previous', 'project-knowledge');
|
|
23
|
+
const PLAIN_ROOT = path.join(TEMP_BASE, 'plain-root', 'project-knowledge');
|
|
24
|
+
const THIRD_PARTY_ROOT = path.join(TEMP_BASE, 'third-party', 'marketplace');
|
|
25
|
+
|
|
26
|
+
function writePackage(directory, name, version) {
|
|
27
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
28
|
+
fs.writeFileSync(path.join(directory, 'package.json'), JSON.stringify({ name, version }, null, 2));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Native-style in-memory codex CLI mirroring 0.137 marketplace semantics:
|
|
32
|
+
// a marketplace add SOURCE containing '@' is parsed as <repo>@<ref> and
|
|
33
|
+
// rejected; SOURCE '.' resolves against runnerOptions.cwd.
|
|
34
|
+
function createCodexCli() {
|
|
35
|
+
const state = { marketplaces: new Map(), calls: [], addCalls: [], removeCalls: [], failAddDirs: new Set() };
|
|
36
|
+
const runner = (command, args, runnerOptions = {}) => {
|
|
37
|
+
state.calls.push({ command, args: [...args], cwd: runnerOptions.cwd || null });
|
|
38
|
+
if (args[0] !== 'plugin' || args[1] !== 'marketplace') {
|
|
39
|
+
return { status: 1, stdout: '', stderr: `fake codex CLI: unsupported command: ${args.join(' ')}` };
|
|
40
|
+
}
|
|
41
|
+
if (args[2] === 'list') {
|
|
42
|
+
const lines = [...state.marketplaces].map(([name, source]) => `${name} ${source}`);
|
|
43
|
+
return { status: 0, stdout: lines.length ? `${lines.join('\n')}\n` : '', stderr: '' };
|
|
44
|
+
}
|
|
45
|
+
if (args[2] === 'remove') {
|
|
46
|
+
state.marketplaces.delete(args[3]);
|
|
47
|
+
state.removeCalls.push(args[3]);
|
|
48
|
+
return { status: 0, stdout: '', stderr: '' };
|
|
49
|
+
}
|
|
50
|
+
if (args[2] === 'add') {
|
|
51
|
+
const source = String(args[3]);
|
|
52
|
+
const resolved = path.resolve(String(runnerOptions.cwd || process.cwd()), source);
|
|
53
|
+
state.addCalls.push({ source, cwd: runnerOptions.cwd || null, resolved });
|
|
54
|
+
if (source.includes('@')) return { status: 1, stdout: '', stderr: REF_ERROR };
|
|
55
|
+
if (state.failAddDirs.has(resolved)) return { status: 1, stdout: '', stderr: 'forced marketplace add failure (test)' };
|
|
56
|
+
let stat = null;
|
|
57
|
+
try { stat = fs.statSync(resolved); } catch { /* missing source handled below */ }
|
|
58
|
+
if (!stat || !stat.isDirectory()) return { status: 1, stdout: '', stderr: `Error: marketplace source not found: ${source}` };
|
|
59
|
+
state.marketplaces.set(MARKETPLACE, resolved);
|
|
60
|
+
return { status: 0, stdout: '', stderr: '' };
|
|
61
|
+
}
|
|
62
|
+
return { status: 1, stdout: '', stderr: `fake codex CLI: unsupported marketplace command: ${args.join(' ')}` };
|
|
63
|
+
};
|
|
64
|
+
return { runner, state };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function createManager(cli, rootDir) {
|
|
68
|
+
return new IntegrationManager({
|
|
69
|
+
rootDir,
|
|
70
|
+
homeDir: TEST_HOME,
|
|
71
|
+
bridgeHomeDir: path.join(TEMP_BASE, 'bridge'),
|
|
72
|
+
env: {},
|
|
73
|
+
commandResolver: name => `fake-${name}`,
|
|
74
|
+
runner: cli.runner,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function registeredSource(cli) {
|
|
79
|
+
const line = [...cli.state.marketplaces].map(([name, source]) => `${name} ${source}`)
|
|
80
|
+
.find(item => item.startsWith(`${MARKETPLACE} `));
|
|
81
|
+
return line ? line.slice(MARKETPLACE.length).trim() : null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function lastAdd(cli) {
|
|
85
|
+
assert.ok(cli.state.addCalls.length, 'expected at least one marketplace add call');
|
|
86
|
+
return cli.state.addCalls[cli.state.addCalls.length - 1];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function assertDotAdd(add, expectedRoot, label) {
|
|
90
|
+
assert.equal(add.source, '.', `${label}: scoped root must be added via the "." source, not an "@"-containing path`);
|
|
91
|
+
assert.equal(path.resolve(add.cwd || ''), expectedRoot, `${label}: "." must resolve against the package directory's own cwd`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function main() {
|
|
95
|
+
writePackage(NEW_ROOT, '@sanqianx/project-knowledge', '5.0.16');
|
|
96
|
+
writePackage(OLD_ROOT, '@sanqianx/project-knowledge', '5.0.15');
|
|
97
|
+
writePackage(PLAIN_ROOT, '@sanqianx/project-knowledge', '5.0.16');
|
|
98
|
+
writePackage(THIRD_PARTY_ROOT, 'third-party-market', '1.0.0');
|
|
99
|
+
|
|
100
|
+
const results = [];
|
|
101
|
+
const scenario = (name, fn) => {
|
|
102
|
+
try { fn(); results.push({ name, ok: true }); }
|
|
103
|
+
catch (error) { results.push({ name, ok: false, error: String((error && error.message) || error) }); }
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
scenario('fresh: scoped npm root installs via "." from its own cwd', () => {
|
|
107
|
+
const cli = createCodexCli();
|
|
108
|
+
createManager(cli, NEW_ROOT).ensureCodexMarketplace();
|
|
109
|
+
assert.equal(registeredSource(cli), NEW_ROOT, 'fresh install must register the scoped npm root');
|
|
110
|
+
assertDotAdd(lastAdd(cli), NEW_ROOT, 'fresh install');
|
|
111
|
+
assert.equal(cli.state.removeCalls.length, 0, 'fresh install must not remove anything');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
scenario('switch: replacing a previous scoped root registers the new root', () => {
|
|
115
|
+
const cli = createCodexCli();
|
|
116
|
+
cli.state.marketplaces.set(MARKETPLACE, OLD_ROOT);
|
|
117
|
+
createManager(cli, NEW_ROOT).ensureCodexMarketplace();
|
|
118
|
+
assert.ok(cli.state.removeCalls.includes(MARKETPLACE), 'switch must remove the previous marketplace first');
|
|
119
|
+
assert.equal(registeredSource(cli), NEW_ROOT, 'switch must end registered on the new scoped root');
|
|
120
|
+
assertDotAdd(lastAdd(cli), NEW_ROOT, 'switch');
|
|
121
|
+
assert.ok(cli.state.addCalls.every(add => !add.source.includes('@')), 'no add may pass an "@"-containing source');
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
scenario('rollback: failed switch restores the old scoped root', () => {
|
|
125
|
+
const cli = createCodexCli();
|
|
126
|
+
cli.state.marketplaces.set(MARKETPLACE, OLD_ROOT);
|
|
127
|
+
cli.state.failAddDirs.add(NEW_ROOT);
|
|
128
|
+
assert.throws(() => createManager(cli, NEW_ROOT).ensureCodexMarketplace(), /已恢复原市场来源/);
|
|
129
|
+
assert.equal(registeredSource(cli), OLD_ROOT, 'rollback must restore the previous scoped root');
|
|
130
|
+
assertDotAdd(lastAdd(cli), OLD_ROOT, 'rollback');
|
|
131
|
+
assert.ok(cli.state.addCalls.every(add => !add.source.includes('@')), 'rollback add must also avoid "@" in the source');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
scenario('plain path: non-"@" absolute source keeps the original invocation', () => {
|
|
135
|
+
const cli = createCodexCli();
|
|
136
|
+
createManager(cli, PLAIN_ROOT).ensureCodexMarketplace();
|
|
137
|
+
assert.equal(registeredSource(cli), PLAIN_ROOT);
|
|
138
|
+
const add = lastAdd(cli);
|
|
139
|
+
assert.equal(add.source, PLAIN_ROOT, 'non-scoped absolute path must keep being passed as the add source');
|
|
140
|
+
assert.notEqual(add.source, '.', 'the "." form is reserved for "@"-containing paths');
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
scenario('third-party: same-name marketplace is never overwritten', () => {
|
|
144
|
+
const cli = createCodexCli();
|
|
145
|
+
cli.state.marketplaces.set(MARKETPLACE, THIRD_PARTY_ROOT);
|
|
146
|
+
assert.throws(() => createManager(cli, NEW_ROOT).ensureCodexMarketplace(), /未覆盖第三方来源/);
|
|
147
|
+
assert.equal(cli.state.addCalls.length, 0, 'third-party source must not be replaced');
|
|
148
|
+
assert.equal(cli.state.removeCalls.length, 0, 'third-party source must not be removed');
|
|
149
|
+
assert.equal(registeredSource(cli), THIRD_PARTY_ROOT, 'third-party registration must be untouched');
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
scenario('allowed failure keeps operation linkage and a safe diagnostic code', () => {
|
|
153
|
+
const cli = createCodexCli();
|
|
154
|
+
const logs = [];
|
|
155
|
+
const manager = createManager(cli, NEW_ROOT);
|
|
156
|
+
manager.operationId = 'op-native-source-test';
|
|
157
|
+
manager.logger = Object.fromEntries(['info', 'warn', 'error'].map(level => [level, (event, message, meta) => logs.push({ event, message, meta })]));
|
|
158
|
+
manager.execute('codex', ['plugin', 'marketplace', 'add', NEW_ROOT], { allowFailure: true });
|
|
159
|
+
const failure = logs.find(log => log.event === 'integration.command_failed');
|
|
160
|
+
assert.ok(failure, 'a tolerated CLI failure must not be logged as success');
|
|
161
|
+
assert.equal(failure.meta.operationId, 'op-native-source-test');
|
|
162
|
+
assert.equal(failure.meta.error.code, 'CODEX_LOCAL_SOURCE_REF');
|
|
163
|
+
assert.equal(failure.meta.context.status, 1);
|
|
164
|
+
assert.ok(!JSON.stringify(logs).includes(REF_ERROR), 'never save raw CLI output');
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
assert.equal(path.dirname(TEMP_BASE), path.resolve(os.tmpdir()));
|
|
168
|
+
assert.equal(fs.lstatSync(TEMP_BASE).isSymbolicLink(), false);
|
|
169
|
+
fs.rmSync(TEMP_BASE, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
170
|
+
|
|
171
|
+
const failed = results.filter(item => !item.ok);
|
|
172
|
+
for (const item of results) console.log(`${item.ok ? 'PASS' : 'FAIL'} ${item.name}${item.ok ? '' : ` :: ${item.error}`}`);
|
|
173
|
+
if (failed.length) {
|
|
174
|
+
console.error(`codex-marketplace-scoped-path-test: ${failed.length} of ${results.length} case(s) failed.`);
|
|
175
|
+
process.exitCode = 1;
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
console.log('codex-marketplace-scoped-path-test passed.');
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
main();
|
|
183
|
+
} catch (error) {
|
|
184
|
+
console.error(error);
|
|
185
|
+
process.exitCode = 1;
|
|
186
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const assert = require('node:assert/strict');
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const vm = require('node:vm');
|
|
6
|
+
|
|
7
|
+
const helper = path.join(__dirname, 'helpers/spawn-server.js');
|
|
8
|
+
const calls = [];
|
|
9
|
+
const moduleObject = { exports: {} };
|
|
10
|
+
const inherited = {
|
|
11
|
+
KB_TERMINAL_URL: 'http://127.0.0.1:5760',
|
|
12
|
+
KB_VECTORHUB_URL: 'http://127.0.0.1:8787',
|
|
13
|
+
KB_EVENTBRIDGE_URL: 'http://127.0.0.1:8790',
|
|
14
|
+
KB_KNOWLEDGE_ENGINE_URL: 'http://127.0.0.1:5790',
|
|
15
|
+
};
|
|
16
|
+
vm.runInNewContext(fs.readFileSync(helper, 'utf8'), {
|
|
17
|
+
module: moduleObject,
|
|
18
|
+
require(id) {
|
|
19
|
+
if (id === 'child_process') return { spawn: (...args) => { calls.push(args); return { pid: 1 }; } };
|
|
20
|
+
if (id === 'fs') return { mkdtempSync: prefix => prefix + 'owned' };
|
|
21
|
+
if (id === '../../lib/runtime-control' || id === '../../lib/runtime-endpoint') return {};
|
|
22
|
+
return require(id);
|
|
23
|
+
},
|
|
24
|
+
process: { execPath: process.execPath, pid: process.pid, env: inherited },
|
|
25
|
+
});
|
|
26
|
+
const spawnServer = moduleObject.exports.spawnServer;
|
|
27
|
+
spawnServer({ root: path.resolve(__dirname, '../..'), port: 0, dataDir: 'isolated-data' });
|
|
28
|
+
const defaults = calls[0][2].env;
|
|
29
|
+
for (const key of Object.keys(inherited)) assert.equal(defaults[key], 'http://127.0.0.1:0', key + ' must not consult a live user module');
|
|
30
|
+
assert.equal(defaults.KB_DATA_DIR, 'isolated-data');
|
|
31
|
+
assert.equal(defaults.KB_MODULES_AUTOSTART, '0');
|
|
32
|
+
assert.equal(defaults.KB_MODULES_REGISTER, '0');
|
|
33
|
+
assert.notEqual(defaults.AI_CODING_EVENT_BRIDGE_HOME, process.env.AI_CODING_EVENT_BRIDGE_HOME);
|
|
34
|
+
const ownUrls = Object.fromEntries(Object.keys(inherited).map(key => [key, 'http://127.0.0.1:12345']));
|
|
35
|
+
spawnServer({ root: path.resolve(__dirname, '../..'), port: 0, dataDir: 'isolated-data', extraEnv: ownUrls });
|
|
36
|
+
for (const key of Object.keys(inherited)) assert.equal(calls[1][2].env[key], ownUrls[key], 'explicit owned fixture remains supported');
|
|
37
|
+
console.log('test-server-module-isolation-test PASS');
|
|
@@ -436,7 +436,7 @@ class IntegrationManager {
|
|
|
436
436
|
|
|
437
437
|
log(level, event, message, input = {}) {
|
|
438
438
|
if (!this.logger || typeof this.logger[level] !== 'function') return;
|
|
439
|
-
Promise.resolve(this.logger[level](event, message, { component: 'integration-manager', ...input })).catch(() => {
|
|
439
|
+
Promise.resolve(this.logger[level](event, message, { component: 'integration-manager', operationId: this.operationId, ...input })).catch(() => {
|
|
440
440
|
try { process.stderr.write(`[integration-manager logger fallback] ${event}\n`); } catch {
|
|
441
441
|
// stderr is the final non-recursive observer fallback.
|
|
442
442
|
}
|
|
@@ -638,19 +638,29 @@ class IntegrationManager {
|
|
|
638
638
|
}
|
|
639
639
|
const result = this.runner(command, args, {
|
|
640
640
|
env: this.env,
|
|
641
|
-
cwd: this.rootDir,
|
|
641
|
+
cwd: options.cwd || this.rootDir,
|
|
642
642
|
timeout: options.timeout,
|
|
643
643
|
});
|
|
644
644
|
if (result.error) {
|
|
645
645
|
this.log('error', 'integration.command_failed', 'Integration CLI command failed.', { durationMs: Date.now() - startedAt, error: Object.assign(new Error('Integration CLI command failed.'), { code: result.error.code || 'INTEGRATION_COMMAND_FAILED' }), context: { client, argsHash } });
|
|
646
646
|
throw result.error;
|
|
647
647
|
}
|
|
648
|
+
const localRefFailure = client === 'codex' && String(result.stderr || '').trim() === 'Error: --ref is only supported for git marketplace sources';
|
|
648
649
|
if (result.status !== 0 && !options.allowFailure) {
|
|
649
650
|
const detail = String(result.stderr || result.stdout || '').trim();
|
|
650
|
-
this.log('error', 'integration.command_failed', 'Integration CLI command failed.', { durationMs: Date.now() - startedAt, error: Object.assign(new Error('Integration CLI command failed.'), { code: 'INTEGRATION_COMMAND_FAILED' }), context: { client, status: result.status, argsHash, outputHash: `sha256:${crypto.createHash('sha256').update(detail, 'utf8').digest('hex')}` } });
|
|
651
|
+
this.log('error', 'integration.command_failed', 'Integration CLI command failed.', { durationMs: Date.now() - startedAt, error: Object.assign(new Error('Integration CLI command failed.'), { code: localRefFailure ? 'CODEX_LOCAL_SOURCE_REF' : 'INTEGRATION_COMMAND_FAILED' }), context: { client, status: result.status, argsHash, outputHash: `sha256:${crypto.createHash('sha256').update(detail, 'utf8').digest('hex')}` } });
|
|
651
652
|
throw new Error(detail || `${CLIENT_LABELS[client]} command failed with exit code ${result.status}`);
|
|
652
653
|
}
|
|
653
|
-
|
|
654
|
+
const completed = result.status === 0;
|
|
655
|
+
const safeError = completed ? undefined : Object.assign(new Error(localRefFailure
|
|
656
|
+
? 'Codex 把本地目录中的 @ 误当作 Git ref;请使用目录内相对路径重试。'
|
|
657
|
+
: 'Integration CLI command returned a failure.'), {
|
|
658
|
+
code: localRefFailure ? 'CODEX_LOCAL_SOURCE_REF' : 'INTEGRATION_COMMAND_FAILED',
|
|
659
|
+
});
|
|
660
|
+
this.log(completed ? 'info' : 'warn', completed ? 'integration.command_completed' : 'integration.command_failed', completed ? 'Integration CLI command completed.' : 'Integration CLI command returned a failure.', {
|
|
661
|
+
durationMs: Date.now() - startedAt, error: safeError,
|
|
662
|
+
context: { client, status: result.status, argsHash },
|
|
663
|
+
});
|
|
654
664
|
return result;
|
|
655
665
|
}
|
|
656
666
|
|
|
@@ -718,6 +728,16 @@ class IntegrationManager {
|
|
|
718
728
|
this.execute('claude', ['plugin', 'marketplace', 'add', this.claudeMarketplaceSource]);
|
|
719
729
|
}
|
|
720
730
|
|
|
731
|
+
addCodexMarketplaceSource(source, options = {}) {
|
|
732
|
+
// Codex 0.137 parses @ in an absolute npm path as a Git ref. Resolve a
|
|
733
|
+
// real local directory via cwd instead; rollback must use its own cwd.
|
|
734
|
+
let local = false;
|
|
735
|
+
if (path.isAbsolute(source) && source.includes('@')) {
|
|
736
|
+
try { local = fs.statSync(source).isDirectory(); } catch {}
|
|
737
|
+
}
|
|
738
|
+
return this.execute('codex', ['plugin', 'marketplace', 'add', local ? '.' : source], local ? { ...options, cwd: source } : options);
|
|
739
|
+
}
|
|
740
|
+
|
|
721
741
|
ensureCodexMarketplace() {
|
|
722
742
|
const target = path.resolve(this.codexMarketplaceAddSource);
|
|
723
743
|
if (!this.dryRun) {
|
|
@@ -727,9 +747,9 @@ class IntegrationManager {
|
|
|
727
747
|
if (path.resolve(existing).toLowerCase() === target.toLowerCase()) return;
|
|
728
748
|
if (!this.isOwnCodexMarketplaceSource(existing)) throw new Error('同名 Codex 插件市场来源不是当前安装包,且无法确认属于本产品;未覆盖第三方来源。请检查 Codex 插件市场配置。');
|
|
729
749
|
this.execute('codex', ['plugin', 'marketplace', 'remove', MARKETPLACE_NAME]);
|
|
730
|
-
const added = this.
|
|
750
|
+
const added = this.addCodexMarketplaceSource(target, { allowFailure: true });
|
|
731
751
|
if (added.status !== 0) {
|
|
732
|
-
const restored = this.
|
|
752
|
+
const restored = this.addCodexMarketplaceSource(existing, { allowFailure: true });
|
|
733
753
|
throw new Error(restored.status === 0
|
|
734
754
|
? 'Codex 插件市场更换为当前安装包失败,已恢复原市场来源;请重试接入。'
|
|
735
755
|
: 'Codex 插件市场更换为当前安装包失败,恢复原市场来源也未成功;请手动检查 codex 插件市场。');
|
|
@@ -737,7 +757,7 @@ class IntegrationManager {
|
|
|
737
757
|
return;
|
|
738
758
|
}
|
|
739
759
|
}
|
|
740
|
-
this.
|
|
760
|
+
this.addCodexMarketplaceSource(target);
|
|
741
761
|
}
|
|
742
762
|
|
|
743
763
|
installClaude(options = {}) {
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## 角色与边界
|
|
4
4
|
|
|
5
|
-
Leader
|
|
5
|
+
Leader 负责知识检索、关键开发、接口决策、打包升级和最终交付。GLM-5.3 主要负责独立故障测试、回归和代码审查,明确独立的小改动才单独派发。允许多条 GLM 检查线并行;修改相同文件、用户配置、运行实例、npm 安装和固定端口验收必须串行。真实性能测试单独运行,避免并发负载污染结果。
|
|
6
|
+
|
|
7
|
+
先交付固定范围的可用版本,不因审查不断追加功能。每条检查线使用短任务合同与独立证据目录,发现问题交给 Leader 收敛修复;不重复跑已经绑定同一运行文件的完整源码回归。GLM token 充足不等于本机 CPU、内存、模型服务和文件锁无限,实际并发按资源与隔离条件安排。
|
|
6
8
|
|
|
7
9
|
使用真实 Workbench,不以其他模型的原生子代理冒充 GLM。完全模式不是扩大授权:禁止自行清空数据、覆盖第三方配置、修改客户端信任记录或发布软件。
|
|
8
10
|
|
|
@@ -2,8 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
## 当前结论
|
|
4
4
|
|
|
5
|
+
最新候选收敛到 `5.0.16-rc.6`,四模块仍锁定 Workbench rc.13、引擎 rc.7、vector-hub rc.8、bridge 0.7.2。修复限于 Codex 本地市场路径与关联日志;发布和安装版验收尚待执行,latest 仍为 5.0.14。
|
|
6
|
+
|
|
7
|
+
rc.5 官方安装收据 `kb-registry-product-2PqRja/registry-installation.json` 已验证。五仓库冻结回归在 Node 22/24 均通过:外壳 138、Workbench 365、vector-hub 73、bridge 30;引擎 169 通过、1 项 Windows 符号链接权限跳过。安装版正常页面、一次 503 恢复、故障和生命周期八项均通过。真实 MiniMax 记忆、流式、单/并发提交、1536 维索引及重启 10 项通过;固定留出集 Recall@5=1、MRR=0.9667,单独热查询 P95=692.9615ms。
|
|
8
|
+
|
|
9
|
+
已通过保护备份与 npm 全局升级把本机安装为 rc.5,7 个现有项目、43 个历史文件、565 个 D 盘索引文件及配置保持不变,运行字节与官方下载包一致。首次本机客户端修复的 Codex 失败操作 `op-29b0bc154aa94f43aa2dc759cf898697` 保留:隔离原生 CLI 复现绝对路径中的 `@` 被当作 ref,目录内 `add .` 成功;随后仅通过原生命令恢复本产品市场,正常修复操作 `op-d6d22efd9e534b1f9d06cd0ba06680cb` 成功。未修改信任记录。
|
|
10
|
+
|
|
11
|
+
Codex 声明入口的真实 MCP initialize/六工具/resolve/search/get 已通过;该结果不等于 Codex 原生模型任务自动收到知识。当前 Hook 为 modified,尚未运行此模型门禁。Claude、ZCode、OpenCode 接线已完成,实际原生送达、二次开发及正式包验收仍需完成。用于实际 Codex 路径回归的 GLM 测试文件经 Leader 修正为跨平台唯一临时目录,避免共享目录清理;首次红测试保留。
|
|
12
|
+
|
|
5
13
|
2026-10-14 开始执行本轮计划。状态:**实施中,未完成系统验收,不更新 latest**。
|
|
6
14
|
|
|
15
|
+
2026-10-15 收敛到候选 `5.0.16-rc.5`,精确锁定 Workbench `0.13.2-rc.13`,其余模块保留 rc.4 的已验收运行文件。Leader 负责关键开发与交付,GLM 独立并行故障测试、回归和审查;不新增产品功能。
|
|
16
|
+
|
|
17
|
+
rc.4 官方安装收据 `kb-registry-product-NPyWjR/registry-installation.json` 已通过内容与 integrity 核对,真实向量热查询 P95 为 1083.6643ms,固定留出集 Recall@5 为 1、MRR 为 0.9667。真实 MiniMax 领域/项目/全局记忆、工作台流式回答、单提交、跨项目并发与重启保真共 10 项通过;这些结果不等于本机原生客户端接入或另一台电脑私有语料验收。
|
|
18
|
+
|
|
19
|
+
rc.4 首次 Node 22 网页失败的历史原因仍无法确定,后续正常路径重复通过。另以一次 `/profiles` HTTP 503 在真实 Workbench iframe 中稳定复现了「首次失败后模型列表一直为空且不再请求」;两次失败记录保留。Workbench rc.12 已修复这一缺陷类,Leader 冻结源码回归 Node 22/24 各 362/362;新整包必须通过同一故障注入用例才能计为恢复。
|
|
20
|
+
|
|
21
|
+
用户当前仍运行 rc.1。其六条索引失败已通过公开索引阶段重试恢复,知识正文、晋升时间和分析运行 ID 不变;原 `532d` 运行在操作前已成功,未重复分析。候选安装、原生客户端、新版保真升级与正式发布门禁仍待完成。
|
|
22
|
+
|
|
23
|
+
GLM 独立审查复现 rc.12 连续保存供应商时复用保存前快照,Leader 修复为保存后等待旧读取结束、再发起可共享的新读取;普通菜单仍 single-flight。两条新竞态测试先失败后修复。菜单异步重绘清空过滤词属于已记录的低风险体验限制,未作为核心修复扩展。
|
|
24
|
+
|
|
25
|
+
rc.5 首次外壳 Node 22 回归为 134/137:工作台密集并发输出期间暂时不可达,三个隔离测试仍读取默认真实模块而超时,首次失败收据保留。测试服务器现在默认使用不可连接的本地端口 0,真实模块场景必须显式传入自有服务地址;三个失败用例定向复测通过,完整冻结回归仍须重跑。此修复不调整生产请求超时或测试断言。
|
|
26
|
+
|
|
7
27
|
运行基线:知识库 `5.0.16-rc.1`、Workbench `0.13.2-rc.10`、vendored 引擎 `0.2.7-rc.5`。发布 stable 标签仍为 `5.0.14`。
|
|
8
28
|
|
|
9
29
|
候选 `5.0.16-rc.2`(`21f67dc`)已发布 `next`,锁定 Workbench rc.11、引擎 rc.6、vector-hub rc.5。独立验收发现 vector-hub 公开 ESM 入口不能加载,因此本候选不能通过全部门禁,待修复后推进下一候选;本机仍运行 rc.1。
|
|
@@ -9,20 +9,20 @@
|
|
|
9
9
|
"plugins/project-knowledge/hooks/codex.json": "216e03c07295606ef6ebb2c4f669ad0d790b5e7c4f3f34600488033db75e4239",
|
|
10
10
|
"plugins/project-knowledge/scripts/context-hook.cjs": "da666153ad5723592cce42d25337ae649f7d93e43fab76b3c6d1263933de063f",
|
|
11
11
|
"plugins/project-knowledge/scripts/mcp-launcher.cjs": "7c68830b5c73eb53ef030756a4de33987f7eab6b1a6cc15602835aac3f954893",
|
|
12
|
-
"plugins/project-knowledge/.claude-plugin/plugin.json": "
|
|
13
|
-
"plugins/project-knowledge/.codex-plugin/plugin.json": "
|
|
14
|
-
"plugins/project-knowledge/.mcp.json": "
|
|
12
|
+
"plugins/project-knowledge/.claude-plugin/plugin.json": "3fcae0e4c576273eb1b92d6e5445a63c70e4c7a47d3f39e5c4d2cd7b9f8fa54c",
|
|
13
|
+
"plugins/project-knowledge/.codex-plugin/plugin.json": "f310840f564417ea12a1d510fce4ab672a6679aa30a0eb5b767b830cfc9995df",
|
|
14
|
+
"plugins/project-knowledge/.mcp.json": "807e061ce4bf14353ae35a95a282f01384828f36832b93c65513643b133669aa"
|
|
15
15
|
},
|
|
16
16
|
"modules": {
|
|
17
17
|
"terminal": {
|
|
18
18
|
"name": "@sanqianx/claude-ai-workbench",
|
|
19
19
|
"installName": "claude-ai-workbench",
|
|
20
|
-
"version": "0.13.2-rc.
|
|
20
|
+
"version": "0.13.2-rc.13",
|
|
21
21
|
"files": {
|
|
22
22
|
"LICENSE": "c1b9df1275e769f3dbab000d1e457a2d4b0f28eb5da6c77e48dc37eeba202ed7",
|
|
23
|
-
"README.md": "
|
|
23
|
+
"README.md": "beea9acbbcb7875406c0ce9704ade51eb546195b47ac01ce4627386b7d5f7054",
|
|
24
24
|
"apps/agent-terminal/app.css": "ede36d9fdb1f7036e3453134c0d5a86197bfc30e3ac547a24b4fc1d17847277e",
|
|
25
|
-
"apps/agent-terminal/app.js": "
|
|
25
|
+
"apps/agent-terminal/app.js": "7494d0e4f11bf84f925a7182b6f1d59e7a8676208b43ff682bfacc5d7fce2a3e",
|
|
26
26
|
"apps/agent-terminal/index.html": "cdffd5c535c81f56aba70ec5dd3bc060f59ec2abcdc8676b79c8f327126be605",
|
|
27
27
|
"apps/ai-profile-settings-host/index.html": "bc158f68954506d2b8e43c690f28dbe931eff9a02b1524855ac17e74ea4df736",
|
|
28
28
|
"apps/ai-profile-settings-host/page.css": "8b75cbf7f1ea5aaa92f2889390720ece310a8fd4b9ca38c890fa447d4323a557",
|
|
@@ -34,20 +34,20 @@
|
|
|
34
34
|
"apps/minimal-test-host/README.md": "fa73136f4ee3865c2d91eb97b2e8c03679aa4688e44c1e1c8ec6e27d604b0de5",
|
|
35
35
|
"docs/sdk/FILE_LAYOUT.md": "17882f96505c8161bfb66876684b9d2d3f50021a111b8b844502d3cb4e97870a",
|
|
36
36
|
"docs/sdk/INTEGRATION.md": "d4c0c80d2d2fc610205102d703a429bfaa20f9f3a48f1718f5bab02ee90138df",
|
|
37
|
-
"docs/sdk/openapi.yaml": "
|
|
37
|
+
"docs/sdk/openapi.yaml": "8483e3eda18fbdd6c896e7ae428d4cc7ee16ec3bc8485da1c6dfbb987e68eaed",
|
|
38
38
|
"docs/sdk/README.md": "7ab591d39c36a3b84cfdf487ff567040ec453975f3ef0fba86dc822094667b61",
|
|
39
|
-
"package.json": "
|
|
39
|
+
"package.json": "61e2770c9a00b4abe2fa56b735f9a450c5ac076daf580e125f71562c6840435b",
|
|
40
40
|
"packages/client/index.d.ts": "fb66b7b21ac936cddcb7f74543cf4f3bb7e80c169534ec249ab8ef2356224162",
|
|
41
41
|
"packages/client/index.js": "a28fa3c38c13e8448cff4d3e0ec95ec2d541d5e57de4b5564fa2a65b2ae892c9",
|
|
42
|
-
"packages/client/package.json": "
|
|
42
|
+
"packages/client/package.json": "852eea37302a4f8743a9246641fcd4bb026878323d08882ce9e528e5477bf2e2",
|
|
43
43
|
"packages/client/README.md": "342dff9b1dcbc85fccc9b980ed3e4e455aa71133af1d0805b8431ea2ac564ef8",
|
|
44
44
|
"packages/contracts/index.d.ts": "157f3cd80f4b27b53c63b2de41575d8332028be2e7491c4730e44b7302bd4dab",
|
|
45
45
|
"packages/contracts/index.js": "5eeb195d9c4cc54dab064510684ae1350d325fbaf47ff824dad4a04a5bb67d11",
|
|
46
|
-
"packages/contracts/package.json": "
|
|
46
|
+
"packages/contracts/package.json": "c9b491a2bd3a4b3c3f20fba0e42a877d75474a79777567e47934c5d6814d74e0",
|
|
47
47
|
"packages/contracts/README.md": "44d83a3cc508cec6c5c20dfa1f2c08d5ea03e3afb2853639fdc0a9cc8eb5b9c8",
|
|
48
48
|
"packages/core/index.d.ts": "c95b24a13f8aeeb128497833cf298790563baca6036ea5d29a9d8daff53199d7",
|
|
49
49
|
"packages/core/index.js": "825640d0edc7dd130f22da1f580d2cda355566a40b0b36e42e5f38909605bbfa",
|
|
50
|
-
"packages/core/package.json": "
|
|
50
|
+
"packages/core/package.json": "25efb6c60e8b2256adc2202ddae585cd3d14b56d1951b3bbdb833a23dc3220db",
|
|
51
51
|
"packages/core/README.md": "e222c546104a168f1038d95c6c4efb8e5603edd6145ab2cab79cab977fb710e5",
|
|
52
52
|
"packages/server/bin/agent-terminal-server.js": "043dff4d76e3fd213b666a55e581ed1e72f9e5b8de6cb798fbf42bd39ed26861",
|
|
53
53
|
"packages/server/bin/claude-workbench-server.js": "b03c730b6d86faf6974afea26c74109d59b1bbc1ecc656c1d6270258708694ac",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"packages/server/lib/system-doctor.js": "2b0e858d69d8fb268eaed950c9883473ee9850684b532bc2db8e14674a974919",
|
|
83
83
|
"packages/server/lib/ui-preferences-store.js": "e108cb22e7cc1f3438704913d5401e01de2c0e717eb2abd3bdc4727209393819",
|
|
84
84
|
"packages/server/lib/workbench-service.js": "19781d2a27fa849e5508a5e233b29008b3ff18e1f10344615c371e5947601437",
|
|
85
|
-
"packages/server/package.json": "
|
|
85
|
+
"packages/server/package.json": "91109d94332bab9ba058a8d2950147d42f051da42271e9396b3baba4df6ea580",
|
|
86
86
|
"packages/server/README.md": "a34cfaa4f4e859008b44e2be8e1aafb56e97fe83e6129c968a8562945fa843f3",
|
|
87
87
|
"packages/ui/ai-profile-settings.d.ts": "0551b6c6eda6d18ea89a976daddf01b2161195f4874fe2d67a57cd9ecc6ce643",
|
|
88
88
|
"packages/ui/ai-profile-settings.js": "e92bbac67a1199d473e4e44b32d1cc76c5b6c79306d4fef9d9067a1bb6ec42ca",
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"packages/ui/claude-terminal.js": "96bd217a4a7e4792ae3fbaaf46249ecee13b0f4e01fc6d25a1b8b22d8f8fe00c",
|
|
91
91
|
"packages/ui/index.d.ts": "e547ab39640fe7519fb367b78442dc8a2c51b2efd17b66f8b0a003b154b36ead",
|
|
92
92
|
"packages/ui/index.js": "f4394aabd395938f5c3fe587e430471d4033e83945a9b9c7e0149ad4040982c9",
|
|
93
|
-
"packages/ui/package.json": "
|
|
93
|
+
"packages/ui/package.json": "4ca5566453e06af0a497b7419e4c76cc7a0f55184c2c3d2f79392e5b78eee973",
|
|
94
94
|
"packages/ui/README.md": "793c4a9c286fee23f39062a1976ca3afe9d2816dcdb55e156ba940e1ef514f89",
|
|
95
95
|
"packages/ui/theme.css": "8f03a081272a7db11b196f7a70d0fafb1f8d954778f329f1ba53d110d9d5fd98",
|
|
96
96
|
"src/assets/claude-prompts.json": "cb111f2e0a45afe8a31c251a504d1ab5375966ed61291660e61fd2efd77f6d9f",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanqianx/project-knowledge",
|
|
3
|
-
"version": "5.0.16-rc.
|
|
3
|
+
"version": "5.0.16-rc.6",
|
|
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": {
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"@sanqianx/vector-hub": "1.0.8-rc.8",
|
|
87
87
|
"buffer": "^6.0.3",
|
|
88
88
|
"cheerio": "^1.2.0",
|
|
89
|
-
"claude-ai-workbench": "npm:@sanqianx/claude-ai-workbench@0.13.2-rc.
|
|
89
|
+
"claude-ai-workbench": "npm:@sanqianx/claude-ai-workbench@0.13.2-rc.13",
|
|
90
90
|
"cross-spawn": "7.0.6",
|
|
91
91
|
"dotenv": "^17.4.2",
|
|
92
92
|
"gpt-tokenizer": "^3.4.0",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
3
|
"name": "project-knowledge",
|
|
4
4
|
"hooks": "./hooks/claude.json",
|
|
5
|
-
"version": "5.0.16-rc.
|
|
5
|
+
"version": "5.0.16-rc.6",
|
|
6
6
|
"description": "Read durable project decisions and implementation history from Project Knowledge.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "SanQianX",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"const fs=require('fs'),path=require('path'),os=require('os');const PKG='@sanqianx/project-knowledge',SC='project-knowledge/integration-runtime/v1';let f='';const root=process.env.CLAUDE_PLUGIN_ROOT||process.env.PLUGIN_ROOT;if(root){f=path.join(root,'scripts','mcp-launcher.cjs');if(!fs.existsSync(f))f=''}if(!f){const dd=process.env.KB_DATA_DIR||path.join(os.homedir(),'.project-knowledge-v5');try{const bp=path.join(dd,'integration-runtime.json');const st=fs.statSync(bp);if(st.isFile()&&st.size<=32768){const b=JSON.parse(fs.readFileSync(bp,'utf8'));if(b&&b.schema===SC&&b.packageName===PKG&&typeof b.packageRoot==='string'&&path.isAbsolute(b.packageRoot)){const c=path.join(b.packageRoot,'plugins','project-knowledge','scripts','mcp-launcher.cjs');const rr=fs.realpathSync(b.packageRoot),cr=fs.realpathSync(c);const rel=path.relative(rr,cr);if(rel&&rel!=='..'&&!rel.startsWith('..'+path.sep)&&!path.isAbsolute(rel)&&fs.statSync(cr).isFile())f=cr}}}catch(e){}}if(!f){console.error('[project-knowledge-mcp] 未能通过受信任插件根或已验证的安装绑定定位启动器,已停止;不访问网络,也不加载工作目录源码。');process.exit(127)}require(f);"
|
|
9
9
|
],
|
|
10
10
|
"env": {
|
|
11
|
-
"KB_PLUGIN_VERSION": "5.0.16-rc.
|
|
11
|
+
"KB_PLUGIN_VERSION": "5.0.16-rc.6"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
}
|