@entrorove/skill 0.1.43 → 0.1.48
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/CHANGELOG.md +25 -0
- package/IDE-EXECUTION.md +2 -2
- package/SKILL.md +3 -3
- package/break-glass.mjs +10 -3
- package/cli.mjs +15 -9
- package/ide-command.mjs +4 -2
- package/ide-hook.mjs +2 -2
- package/ide-session.mjs +43 -2
- package/install-cleanup.mjs +5 -3
- package/local-chain-broker.mjs +9 -8
- package/local-cli.mjs +5 -2
- package/local-final-gate16.mjs +2 -2
- package/manifest.json +1 -1
- package/package.json +1 -1
- package/release-state.json +15 -15
- package/release.mjs +6 -4
- package/releases.json +30 -0
- package/remote-client.mjs +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.48 — 2026-10-16
|
|
4
|
+
|
|
5
|
+
- 新增标准命令 `install --host codex`,仅配置 Codex 并保留 Claude 的配置与技能副本;后续自动更新沿用已配置的宿主范围。安装命令守卫和旧版清理也按目标宿主限界。
|
|
6
|
+
- Added the standard `install --host codex` command to configure Codex while preserving Claude configuration and skill copies. Later automatic updates retain the already configured host scope; installer command guards and obsolete-install cleanup honor the selected host.
|
|
7
|
+
|
|
8
|
+
## 0.1.47 — 2026-10-16
|
|
9
|
+
|
|
10
|
+
- 修复失败 flow 的取消、放弃和会话解绑;离线 unlock 仅恢复当前会话并保留任务队列。放行授权根或依赖目录内的只读 tsconfig 引用,越界错误说明原路径、解析结果和原因。升级时清理未改动的旧受管安装,保留用户编辑及其他任务;IDE 钩子仅对已绑定的会话和仓库生效。
|
|
11
|
+
- Fixed cancellation, abandonment, and session unbinding for failed flows; offline unlock restores only the current session and preserves its queue. Read-only tsconfig references inside the authorized root or dependency directories are accepted, while escape errors identify the input path, resolved path, and reason. Upgrades remove pristine obsolete managed installs while preserving user edits and unrelated tasks; IDE hooks apply only to a bound session and repository.
|
|
12
|
+
|
|
13
|
+
## 0.1.46 — 2026-10-16
|
|
14
|
+
|
|
15
|
+
- 更新了Codex 后续轮次工具门禁、IDE 执行与复用纪律文档、技能运行和受管安装、IDE 工作流程说明。
|
|
16
|
+
- Updated Codex tool guards across turns, IDE execution and reuse discipline documentation, skill runtime and managed installation, IDE workflow instructions.
|
|
17
|
+
|
|
18
|
+
## 0.1.45 — 2026-10-16
|
|
19
|
+
|
|
20
|
+
- 更新了原链同流程技能调用。
|
|
21
|
+
- Updated original-chain skill calls on the same workflow.
|
|
22
|
+
|
|
23
|
+
## 0.1.44 — 2026-10-16
|
|
24
|
+
|
|
25
|
+
- 更新了Calctool 审计测试运维真实检查与独立最终闸门、自动版本与更新日志。
|
|
26
|
+
- Updated Calctool audit, test, operations checks and independent final gate, automatic versioning and changelog.
|
|
27
|
+
|
|
3
28
|
## 0.1.43 — 2026-10-16
|
|
4
29
|
|
|
5
30
|
- 更新了Codex 后续轮次工具门禁、复用与变更一致性门禁、IDE 执行与复用纪律文档、技能运行和受管安装、旧版受管安装清理、IDE 工作流程说明、任务交付边界说明、安装包配置、自动版本与更新日志、本地三轴读取预算、本地阶段边界与可恢复停止、远端恢复客户端、账号沙箱偏好与任务入口确认、工作流本地调用契约。
|
package/IDE-EXECUTION.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
Install or update the managed copy with `npx @entrorove/skill install`. The installer keeps one global managed entrorove skill, replaces its older pristine version, removes only pristine duplicate installations, and preserves hand-edited files. An older package cannot overwrite a newer managed version.
|
|
1
|
+
Install or update the managed copy with `npx @entrorove/skill install`. In Codex, use `npx @entrorove/skill install --host codex` to configure Codex only; this leaves Claude Code hook settings and skill copies alone. The installer keeps one global managed entrorove skill, replaces its older pristine version, removes only pristine duplicate installations for the selected host, and preserves hand-edited files. An older package cannot overwrite a newer managed version.
|
|
2
2
|
|
|
3
3
|
Register or sign in by email at https://entrorove.com. Enter the account key once with `npx @entrorove/skill configure` and `{"token":"..."}` on standard input. The credential persists in the current OS user's restricted local store across skill upgrades. Before asking again, use the stored credential; a missing or invalid credential must be reported explicitly. Never place the key in arguments, URLs, project files or logs. entrorove accounts and keys are independent of other services.
|
|
4
4
|
|
|
5
|
-
If the IDE guard itself is the blocked step, run `entrorove unlock` directly from the
|
|
5
|
+
If the IDE guard itself is the blocked step, run `entrorove unlock` directly from the affected IDE terminal. The command is offline and records a 15-minute lease bound to that IDE session; it does not call a hook, read a credential, accept the agreement, inspect the protocol or authorize project writes. The host session ID must be present in the environment or supplied as `ENTROROVE_SESSION`. Under the lease, `flow-cancel` and `flow-abandon` recover the original flow; successful `flow-abandon` releases its task binding in both the flow state and the IDE session record, even without a hook callback. Queued requests remain, and other IDE sessions stay guarded.
|
|
6
6
|
|
|
7
7
|
To stop using Entrorove on this computer, run `entrorove uninstall` directly. It works offline, removes only the recorded Entrorove host hooks and pristine global skill, and leaves other host settings, credentials and task records in place. A hand-edited file is reported as preserved rather than deleted. This command does not inspect or change another project.
|
|
8
8
|
|
package/SKILL.md
CHANGED
|
@@ -5,14 +5,14 @@ description: Execute an engineering task through Entrorove, preserving its origi
|
|
|
5
5
|
|
|
6
6
|
# entrorove · 熵巡
|
|
7
7
|
|
|
8
|
-
Version: 0.1.
|
|
8
|
+
Version: 0.1.48.
|
|
9
9
|
|
|
10
10
|
Entrorove applies to the whole task once selected. Reading this document or calling an entry once does not execute the task. On every later turn, including after compaction, continue the original task and its required next operation before dependent work. Keep the original goal, scope, account, flow, cloud task and failure records. Never describe planning, a reported step or model output as verified delivery.
|
|
11
11
|
|
|
12
12
|
## Required execution
|
|
13
13
|
|
|
14
|
-
1. Install `npx --yes --prefer-online @entrorove/skill@latest install` only when the user chooses to enable this skill. The managed installer writes the skill and
|
|
15
|
-
`entrorove unlock` is the break-glass path: run the installed CLI directly in
|
|
14
|
+
1. Install `npx --yes --prefer-online @entrorove/skill@latest install --host codex` in Codex only when the user chooses to enable this skill. The managed installer writes the skill and Codex lifecycle hook configuration without changing Claude Code settings; confirm that the IDE trusts it and observe a real callback before describing enforcement as active. Do not ask the user to type a nonexistent `/hooks` command. If the host reports a blocked management call, show and allow the offline `entrorove unlock` command; it only opens the skill management plane and never grants project-write authority. New execution from a detected IDE requires the exact live host approval. An unsupported IDE adapter, missing hook callback, missing credential, or failed discovery stops execution explicitly. Do not silently use native tools instead. The guard is host-agnostic: one managed hook is installed once, and each host is described by its own adapter (config location, event names, entry shape). Codex and Claude Code are the verified adapters today; a host with no verified adapter, or a run whose host session identity is missing, is refused explicitly rather than degrading to native tools.
|
|
15
|
+
`entrorove unlock` is the break-glass path: run the installed CLI directly in the affected IDE terminal. It writes a short-lived lease for that IDE session only, without a hook callback, network request, credential read, agreement check or protocol lookup. The current session ID must be available from the host environment or `ENTROROVE_SESSION`. The lease permits `flow-cancel` and `flow-abandon` recovery, never project writes or another session's calls. A successful `flow-abandon` clears that session's old binding locally even without a hook callback and preserves its queued requests.
|
|
16
16
|
To remove this skill and its host hooks, run `entrorove uninstall` directly. It works offline and preserves unrelated host settings, credentials and task records. If a managed file was edited, it reports the preserved path instead of deleting it.
|
|
17
17
|
2. Read [IDE-EXECUTION.md](IDE-EXECUTION.md) for the exact entry, cloud callbacks, account agreement and operation contracts. Use the stored account credential; never put it in arguments, URLs, project files, output or fixtures. Entrorove is independent of other systems.
|
|
18
18
|
3. Discover `capabilities`, then invoke `start` with the actual goal, task type, risk and scope facts. An enabled account returns a cloud choice before charging a model. Show that choice visibly using the host question tool. Confirmation calls its original callback; exit adopts the local route for this task. Never treat silence as permission, invent acceptance, or create both routes. Existing explicit authorization for this task persists.
|
package/break-glass.mjs
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { promises as fs } from 'node:fs';
|
|
2
|
-
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
|
|
6
6
|
export const breakGlassSchema = 'entrorove.ide-break-glass/1.0';
|
|
7
7
|
export const breakGlassTtlMs = 15 * 60 * 1000;
|
|
8
|
+
export function breakGlassSessionDigest(sessionId) {
|
|
9
|
+
if (typeof sessionId !== 'string' || !/^[A-Za-z0-9_-]{1,200}$/u.test(sessionId)) {
|
|
10
|
+
throw new Error('Break-glass requires the current IDE session identity');
|
|
11
|
+
}
|
|
12
|
+
return createHash('sha256').update(sessionId).digest('hex');
|
|
13
|
+
}
|
|
8
14
|
|
|
9
15
|
function homeDirectory(home) {
|
|
10
16
|
if (typeof home !== 'string' || !path.isAbsolute(home)) throw new Error('Break-glass home must be absolute');
|
|
@@ -38,11 +44,12 @@ export function breakGlassPath(home = os.homedir()) {
|
|
|
38
44
|
return path.join(homeDirectory(home), 'break-glass.json');
|
|
39
45
|
}
|
|
40
46
|
|
|
41
|
-
export async function writeBreakGlass(home = os.homedir(), now = Date.now()) {
|
|
47
|
+
export async function writeBreakGlass(home = os.homedir(), now = Date.now(), sessionId) {
|
|
42
48
|
if (!Number.isFinite(now)) throw new Error('Break-glass clock is invalid');
|
|
49
|
+
const sessionDigest = breakGlassSessionDigest(sessionId);
|
|
43
50
|
const file = breakGlassPath(home), directory = path.dirname(file);
|
|
44
51
|
await ensurePrivateDirectory(directory, home);
|
|
45
|
-
const value = { schemaVersion: breakGlassSchema, mode: 'management-only', createdAt: new Date(now).toISOString(),
|
|
52
|
+
const value = { schemaVersion: breakGlassSchema, mode: 'management-only', sessionDigest, createdAt: new Date(now).toISOString(),
|
|
46
53
|
expiresAt: new Date(now + breakGlassTtlMs).toISOString() };
|
|
47
54
|
const stage = `${file}.${randomUUID()}.tmp`;
|
|
48
55
|
await fs.writeFile(stage, `${JSON.stringify(value)}\n`, { flag: 'wx', mode: 0o600 });
|
package/cli.mjs
CHANGED
|
@@ -17,9 +17,9 @@ import { buildReview, submitSkillFeedback, feedbackNoticeVersion } from './revie
|
|
|
17
17
|
import { queryCloudTask, runCloudTask as dispatchCloudTask } from './cloud-task-client.mjs';
|
|
18
18
|
import { watchCloudTask } from './cloud-watch-client.mjs';
|
|
19
19
|
import { queryAutomaticFeedback } from './automatic-feedback-client.mjs';
|
|
20
|
-
import { activeIdeAdapters, installIdeHooks, uninstallIdeHooks } from './ide-install.mjs';
|
|
20
|
+
import { activeIdeAdapters, ideAdapters, installIdeHooks, uninstallIdeHooks } from './ide-install.mjs';
|
|
21
21
|
import { cleanManagedDuplicates } from './install-cleanup.mjs';
|
|
22
|
-
import { assertIdeExecution } from './ide-session.mjs';
|
|
22
|
+
import { assertIdeExecution, ideGuardBinding, settleBreakGlassSession } from './ide-session.mjs';
|
|
23
23
|
import { writeBreakGlass } from './break-glass.mjs';
|
|
24
24
|
const markerName = '.entrorove-managed.json';
|
|
25
25
|
const installFiles = ['SKILL.md', 'CAPABILITY-MAP.md', 'AGREEMENT.md', 'manifest.json', 'IDE-EXECUTION.md', 'REUSE-DISCIPLINE.md', 'DELIVERY-BOUNDARIES.md'];
|
|
@@ -246,7 +246,9 @@ async function updateGlobalInstall(target, bundle) {
|
|
|
246
246
|
return true;
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
-
export async function install({ home = os.homedir(), cwd = process.cwd(), explicit = false } = {}) {
|
|
249
|
+
export async function install({ home = os.homedir(), cwd = process.cwd(), explicit = false, hostId } = {}) {
|
|
250
|
+
const selected = hostId === undefined ? null : ideAdapters.find(adapter => adapter.id === hostId);
|
|
251
|
+
if (hostId !== undefined && hostId !== 'codex') throw new Error('Install host must be codex');
|
|
250
252
|
const target = globalInstallPath(home);
|
|
251
253
|
if (!explicit && !(await managedState(target))) return { installed: false, updated: false };
|
|
252
254
|
const parent = path.dirname(target);
|
|
@@ -259,8 +261,10 @@ export async function install({ home = os.homedir(), cwd = process.cwd(), explic
|
|
|
259
261
|
const updated = await updateGlobalInstall(target, bundle);
|
|
260
262
|
const { removed, preserved } = await cleanManagedDuplicates({
|
|
261
263
|
target, cwd, home, isManaged: managedState, includeProject: explicit,
|
|
264
|
+
hostIds: selected ? [selected.id] : active?.map(adapter => adapter.id),
|
|
262
265
|
});
|
|
263
|
-
const ide = await installIdeHooks({ home, version: bundle.manifest.version,
|
|
266
|
+
const ide = await installIdeHooks({ home, version: bundle.manifest.version,
|
|
267
|
+
adapters: selected ? [selected] : active });
|
|
264
268
|
return { version: bundle.manifest.version, updated, removed, preserved, agreementStale: stale, ide };
|
|
265
269
|
});
|
|
266
270
|
}
|
|
@@ -388,7 +392,9 @@ async function invoke(data) {
|
|
|
388
392
|
if (data?.operation === 'cloud-task') return runCloudTask(data.input, remoteDependencies());
|
|
389
393
|
if (data?.operation === 'cloud-status') return runCloudStatus(data.input, remoteDependencies());
|
|
390
394
|
if (data?.operation === 'cloud-watch') return runCloudWatch(data.input);
|
|
391
|
-
|
|
395
|
+
const result = await invokeRemote(data, remoteDependencies());
|
|
396
|
+
await settleBreakGlassSession(['invoke'], data, result);
|
|
397
|
+
return result;
|
|
392
398
|
}
|
|
393
399
|
|
|
394
400
|
export { buildReview };
|
|
@@ -422,13 +428,13 @@ async function runAccountCommand(command, args) {
|
|
|
422
428
|
async function main() {
|
|
423
429
|
const [command, ...args] = process.argv.slice(2);
|
|
424
430
|
if (command === 'unlock' && args.length === 0) {
|
|
425
|
-
process.stdout.write(`${JSON.stringify(await writeBreakGlass())}\n`);
|
|
431
|
+
process.stdout.write(`${JSON.stringify(await writeBreakGlass(os.homedir(), Date.now(), ideGuardBinding().sessionId))}\n`);
|
|
426
432
|
} else if (command === 'uninstall' && args.length === 0) {
|
|
427
433
|
const result = await uninstall();
|
|
428
434
|
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
429
435
|
if (!result.uninstalled) process.exitCode = 2;
|
|
430
|
-
} else if (command === 'install' && args.length === 0) {
|
|
431
|
-
process.stdout.write(JSON.stringify(await install({ explicit: true })) + '\n');
|
|
436
|
+
} else if (command === 'install' && (args.length === 0 || args.length === 2 && args[0] === '--host')) {
|
|
437
|
+
process.stdout.write(JSON.stringify(await install({ explicit: true, hostId: args[1] })) + '\n');
|
|
432
438
|
} else if (command === 'configure' && args.length === 0) {
|
|
433
439
|
const data = await stdinJson();
|
|
434
440
|
if (Object.keys(data).length !== 1 || typeof data.token !== 'string') throw new Error('Expected {"token":"..."} on stdin');
|
|
@@ -473,7 +479,7 @@ async function main() {
|
|
|
473
479
|
} else if (command === 'local') {
|
|
474
480
|
await runLocal(args);
|
|
475
481
|
} else {
|
|
476
|
-
throw new Error('Usage: entrorove unlock | uninstall | install | configure | agreement | invoke | queue | native <domain> <operation> | notifications configure|status|test | scope-connect <repositoryRoot> | host-message [adapterModulePath] | cloud-task | cloud-watch | cloud-status | feedback <requestId> [generation] | status <requestId> | flows | usage [flowId] | billing | recurring list|claim|finish|runs | review | local (JSON on stdin)');
|
|
482
|
+
throw new Error('Usage: entrorove unlock | uninstall | install [--host codex] | configure | agreement | invoke | queue | native <domain> <operation> | notifications configure|status|test | scope-connect <repositoryRoot> | host-message [adapterModulePath] | cloud-task | cloud-watch | cloud-status | feedback <requestId> [generation] | status <requestId> | flows | usage [flowId] | billing | recurring list|claim|finish|runs | review | local (JSON on stdin)');
|
|
477
483
|
}
|
|
478
484
|
}
|
|
479
485
|
if (process.argv[1] && realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url))) { const { captureIdeResults } = await import('./ide-results.mjs');
|
package/ide-command.mjs
CHANGED
|
@@ -48,6 +48,7 @@ export function sdkCommand(parsed, runtime) {
|
|
|
48
48
|
if (simple.has(args[0]) && args.length === 1 && parsed.input) return { args, input: parsed.input };
|
|
49
49
|
if (['status', 'feedback'].includes(args[0]) && /^[a-f0-9]{64}$/u.test(args[1] ?? '') && [2,3].includes(args.length)) return { args };
|
|
50
50
|
if (['flows', 'install', 'billing'].includes(args[0]) && args.length === 1 && !parsed.input) return { args };
|
|
51
|
+
if (args[0] === 'install' && args.length === 3 && args[1] === '--host' && args[2] === 'codex' && !parsed.input) return { args };
|
|
51
52
|
if (args[0] === 'recurring' && ['list', 'claim'].includes(args[1] ?? '') && args.length === 2 && !parsed.input) return { args };
|
|
52
53
|
if (args[0] === 'recurring' && ['finish', 'runs'].includes(args[1] ?? '') && args.length === 3 && (!parsed.input || args[1] === 'finish')) return { args, ...(parsed.input ? { input: parsed.input } : {}) };
|
|
53
54
|
if (args[0] === 'usage' && args.length <= 2 && !parsed.input
|
|
@@ -61,8 +62,9 @@ export function installerCommand(parsed) {
|
|
|
61
62
|
if (!parsed || parsed.input || !['npx', 'npx.cmd'].includes(parsed.words[0])) return null;
|
|
62
63
|
const words = [...parsed.words]; words.shift();
|
|
63
64
|
while (['--yes', '--prefer-online', '--registry=https://registry.npmjs.org'].includes(words[0])) words.shift();
|
|
64
|
-
if (words.length
|
|
65
|
-
|
|
65
|
+
if (![2, 4].includes(words.length) || !/^@entrorove\/skill(?:@(?:latest|\d+\.\d+\.\d+))?$/u.test(words[0]) || words[1] !== 'install'
|
|
66
|
+
|| words.length === 4 && (words[2] !== '--host' || words[3] !== 'codex')) return null;
|
|
67
|
+
return `npx --yes --prefer-online --registry=https://registry.npmjs.org ${words[0]} install${words.length === 4 ? ' --host codex' : ''}`;
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
export function readCommand(parsed) {
|
package/ide-hook.mjs
CHANGED
|
@@ -101,7 +101,7 @@ function collectResult(state, values, local) {
|
|
|
101
101
|
}
|
|
102
102
|
async function beforeTool(event, state, home) {
|
|
103
103
|
if (state.phase === 'user-exited') return {};
|
|
104
|
-
const unlocked = await readBreakGlass(home);
|
|
104
|
+
const unlocked = await readBreakGlass(home, state.sessionId);
|
|
105
105
|
const command = event.tool_input?.command ?? event.tool_input?.cmd, parsed = literalCommand(command);
|
|
106
106
|
const isShell = ['Bash', 'exec_command', 'shell_command'].includes(event.tool_name);
|
|
107
107
|
const installer = isShell && installerCommand(parsed);
|
|
@@ -230,7 +230,7 @@ export async function runIdeHook(event, { home } = {}) {
|
|
|
230
230
|
if (resumed) messages.push(resumed);
|
|
231
231
|
return { ...output(name, { additionalContext: ideContext(state) }), ...(messages.length ? { systemMessage: messages.join('\n') } : {}) };
|
|
232
232
|
}
|
|
233
|
-
if (name==='Stop' && state.active && !(await readBreakGlass(home))) {
|
|
233
|
+
if (name==='Stop' && state.active && !(await readBreakGlass(home, state.sessionId))) {
|
|
234
234
|
const resumed = await advanceIdeQueue(state,home);
|
|
235
235
|
if (resumed || unclassifiedIdeRequirements(state) || unfinishedIdeQueue(state) && !['blocked','needs-input','delivered'].includes(state.phase)
|
|
236
236
|
|| !['ended','blocked','needs-input','setup','delivered'].includes(state.phase)) return {decision:'block',reason:blockedReason(state, event, `${ideContext(state)}${ideQueueContext(state)}${resumed}原任务或队列尚未取得结束回执;继续可运行工作,真实阻断必须明确报告。`)};
|
package/ide-session.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import path from 'node:path';
|
|
|
6
6
|
import { credentialDirectory, readCredential } from './local-credential.mjs';
|
|
7
7
|
import { withStateLock } from './local-state-lock.mjs';
|
|
8
8
|
import { requestTransport, parseTransportResponse } from './remote-transport.mjs';
|
|
9
|
-
import { breakGlassPath, breakGlassSchema, writeBreakGlass as writeOfflineBreakGlass } from './break-glass.mjs';
|
|
9
|
+
import { breakGlassPath, breakGlassSchema, breakGlassSessionDigest, writeBreakGlass as writeOfflineBreakGlass } from './break-glass.mjs';
|
|
10
10
|
|
|
11
11
|
export const ideDigest = value => createHash('sha256').update(typeof value === 'string' ? value : JSON.stringify(value)).digest('hex');
|
|
12
12
|
export const ideError = (code, message) => Object.assign(new Error(message), { code });
|
|
@@ -35,10 +35,12 @@ export async function writeIdeJson(file, value) {
|
|
|
35
35
|
try { await fs.rename(stage, file); } finally { await fs.rm(stage, { force: true }); }
|
|
36
36
|
}
|
|
37
37
|
export const writeBreakGlass = writeOfflineBreakGlass;
|
|
38
|
-
export async function readBreakGlass(home = os.homedir()) {
|
|
38
|
+
export async function readBreakGlass(home = os.homedir(), sessionId) {
|
|
39
|
+
if (!sessionId) return null;
|
|
39
40
|
const directory = await ideDirectory(home, true);
|
|
40
41
|
const value = await readIdeJson(breakGlassPath(home));
|
|
41
42
|
if (!value || value.schemaVersion !== breakGlassSchema || value.mode !== 'management-only'
|
|
43
|
+
|| value.sessionDigest !== breakGlassSessionDigest(sessionId)
|
|
42
44
|
|| typeof value.expiresAt !== 'string' || !Number.isFinite(Date.parse(value.expiresAt))
|
|
43
45
|
|| Date.parse(value.expiresAt) <= Date.now()) return null;
|
|
44
46
|
return value;
|
|
@@ -109,6 +111,22 @@ async function declaredHost(environment) {
|
|
|
109
111
|
export async function assertIdeExecution(args, input, { home = os.homedir(), environment = process.env } = {}) {
|
|
110
112
|
const { host, sessionId } = ideGuardBinding(environment);
|
|
111
113
|
if (!host || host === 'Entrorove CLI') return;
|
|
114
|
+
const lifecycle = args[0] === 'local' ? args[1] : args[0] === 'invoke' ? input?.operation : null;
|
|
115
|
+
if (['flow-cancel', 'flow-abandon'].includes(lifecycle) && await readBreakGlass(home, sessionId)) {
|
|
116
|
+
const flowId = args[0] === 'invoke' ? input?.input?.flowId : input?.flowId;
|
|
117
|
+
const state = await readIdeJson(path.join(await ideDirectory(home), `session-${ideDigest(sessionId)}.json`));
|
|
118
|
+
if (state?.flowId && state.flowId !== flowId) throw ideError('ENTROROVE_IDE_RECOVERY_SCOPE', 'Recovery must settle the flow bound to this IDE session');
|
|
119
|
+
if (args[0] === 'local') {
|
|
120
|
+
const root = input?.repositoryRoot ?? args[2];
|
|
121
|
+
if (state?.repositoryRoot && root && await fs.realpath(root) !== state.repositoryRoot) {
|
|
122
|
+
throw ideError('ENTROROVE_IDE_RECOVERY_SCOPE', 'Recovery cannot switch the IDE session repository');
|
|
123
|
+
}
|
|
124
|
+
if (input?.home && await fs.realpath(input.home) !== await fs.realpath(home)) {
|
|
125
|
+
throw ideError('ENTROROVE_IDE_RECOVERY_SCOPE', 'Recovery cannot switch the IDE session home');
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
112
130
|
const declared = verifiedIdeGuards[host] ? null : await declaredHost(environment);
|
|
113
131
|
if (!verifiedIdeGuards[host] && declared !== host || !sessionId) {
|
|
114
132
|
throw ideError('ENTROROVE_IDE_GUARD_UNSUPPORTED', `${host} has no verified tool guard adapter. Execution is blocked; never continue with another executor.`);
|
|
@@ -124,3 +142,26 @@ export async function assertIdeExecution(args, input, { home = os.homedir(), env
|
|
|
124
142
|
approvedResultContext = { home, sessionId: state.sessionId, repositoryRoot: state.repositoryRoot,
|
|
125
143
|
accountDigest: state.accountDigest, toolUseId: approved.toolUseId, inputDigest: expected };
|
|
126
144
|
}
|
|
145
|
+
|
|
146
|
+
export async function settleBreakGlassSession(args, input, result, { home = os.homedir(), environment = process.env } = {}) {
|
|
147
|
+
const operation = args[0] === 'local' ? args[1] : args[0] === 'invoke' ? input?.operation : null;
|
|
148
|
+
if (!['flow-cancel', 'flow-abandon'].includes(operation)) return false;
|
|
149
|
+
const value = result?.output ?? result;
|
|
150
|
+
const flowId = args[0] === 'invoke' ? input?.input?.flowId : input?.flowId;
|
|
151
|
+
if (value?.operation !== operation || value.flowId !== flowId || !['succeeded', 'reported'].includes(value.status)
|
|
152
|
+
|| operation === 'flow-abandon' && value.unbound !== true) return false;
|
|
153
|
+
const { host, sessionId } = ideGuardBinding(environment);
|
|
154
|
+
if (!host || host === 'Entrorove CLI' || !await readBreakGlass(home, sessionId)) return false;
|
|
155
|
+
const file = path.join(await ideDirectory(home), `session-${ideDigest(sessionId)}.json`);
|
|
156
|
+
const current = await readIdeJson(file);
|
|
157
|
+
if (!current) return false;
|
|
158
|
+
return ideSession({ session_id: sessionId, cwd: current.repositoryRoot }, state => {
|
|
159
|
+
if (state.flowId !== flowId) throw ideError('ENTROROVE_IDE_RECOVERY_SCOPE', 'Recovered flow no longer matches the IDE session');
|
|
160
|
+
if (operation === 'flow-abandon') {
|
|
161
|
+
for (const key of ['flowId', 'taskId', 'taskNumber', 'requestId', 'remoteRequestId', 'nextStep', 'pendingCall', 'readCalls']) delete state[key];
|
|
162
|
+
state.feedbackAcknowledged = false;
|
|
163
|
+
if (state.phase !== 'user-exited') state.phase = 'entry';
|
|
164
|
+
} else state.phase = 'ended';
|
|
165
|
+
return true;
|
|
166
|
+
}, home);
|
|
167
|
+
}
|
package/install-cleanup.mjs
CHANGED
|
@@ -39,12 +39,14 @@ async function removeDuplicate(directory, target, root, isManaged) {
|
|
|
39
39
|
return 'removed';
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
export async function cleanManagedDuplicates({ target, cwd, home, isManaged, includeProject = true }) {
|
|
42
|
+
export async function cleanManagedDuplicates({ target, cwd, home, isManaged, includeProject = true, hostIds = null }) {
|
|
43
43
|
const root = includeProject ? gitRoot(cwd) : null, homeRoot = gitRoot(home);
|
|
44
|
+
const includeClaude = hostIds === null || hostIds.includes('claude');
|
|
44
45
|
const candidates = [
|
|
45
|
-
...(root ? ['.codex/skills/entrorove', '.agents/skills/entrorove',
|
|
46
|
+
...(root ? ['.codex/skills/entrorove', '.agents/skills/entrorove',
|
|
47
|
+
...(includeClaude ? ['.claude/skills/entrorove'] : [])]
|
|
46
48
|
.map(relative => ({ directory: path.join(root, relative), label: relative, root })) : []),
|
|
47
|
-
...['.agents/skills/entrorove', '.claude/skills/entrorove']
|
|
49
|
+
...['.agents/skills/entrorove', ...(includeClaude ? ['.claude/skills/entrorove'] : [])]
|
|
48
50
|
.map(relative => ({ directory: path.join(home, relative), label: `~/${relative}`, root: homeRoot })),
|
|
49
51
|
];
|
|
50
52
|
const removed = [], preserved = [], seen = new Set([target]);
|
package/local-chain-broker.mjs
CHANGED
|
@@ -4,11 +4,6 @@ import { inspectLocalChainResult } from './local-chain-plan.mjs';
|
|
|
4
4
|
|
|
5
5
|
const STAGES = Object.freeze({ 'workflow-gate': 'aimlock', 'workflow-contract': 'aimlock',
|
|
6
6
|
'workflow-plan': 'blueprint', 'workflow-dispatch': 'swarm', 'workflow-verdict': 'validator' });
|
|
7
|
-
function nativeSchema(runtime, operation) {
|
|
8
|
-
const schemas = runtime.operationSchemas;
|
|
9
|
-
const selected = Array.isArray(schemas) ? schemas.find(value => value.operation === operation) : schemas?.[operation];
|
|
10
|
-
return selected?.inputSchema ?? selected?.input ?? selected;
|
|
11
|
-
}
|
|
12
7
|
export async function captureChainCloud(plan, client) {
|
|
13
8
|
if (!plan.skills.length) return null;
|
|
14
9
|
const output = await client.invoke('capabilities', {}), capabilities = output.capabilities;
|
|
@@ -37,10 +32,16 @@ export function checkChainSkillDispatch(original, state, resumed, input) {
|
|
|
37
32
|
}
|
|
38
33
|
const slug = STAGES[original.operation] ?? resumed.route?.slug;
|
|
39
34
|
if (slug !== original.skillId) fail('ENTROROVE_CHAIN_SKILL_BINDING', 'declared skill differs from the original native workflow stage');
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
// `continue` is a workflow operation. A native skill operation with the
|
|
36
|
+
// same name can have a different request body (for example, the workflow
|
|
37
|
+
// reads its persisted interaction while the native runtime requires one).
|
|
38
|
+
const schema = state.cloud.workflowOperations?.operationSchemas?.[original.operation];
|
|
42
39
|
if (schema) {
|
|
43
|
-
|
|
40
|
+
// Pinned native schemas include legacy `optional` annotations and nested
|
|
41
|
+
// object branches without an explicit `type`. Keep validation of the
|
|
42
|
+
// actual JSON Schema constraints while accepting those published forms.
|
|
43
|
+
const validate = new Ajv({ strict: true, strictRequired: false, strictTypes: false, allErrors: true })
|
|
44
|
+
.addKeyword({ keyword: 'optional', schemaType: 'boolean', valid: true }).compile(schema);
|
|
44
45
|
if (!validate(input)) fail('ENTROROVE_CHAIN_SKILL_INPUT', 'bound input violates its fixed original operation schema');
|
|
45
46
|
}
|
|
46
47
|
// Native operations without public nested schemas remain server-validated on
|
package/local-cli.mjs
CHANGED
|
@@ -25,7 +25,7 @@ import { ARCHGUARD_LOCAL_OPERATIONS } from './local-archguard-operations.mjs';
|
|
|
25
25
|
import { LOCAL_BUDGET_HANDOFF_OPERATIONS } from './local-budget-handoff.mjs';
|
|
26
26
|
import { LOCAL_CHAIN_OPERATIONS } from './local-chain-operations.mjs';
|
|
27
27
|
import { DISCIPLINE_LOCAL_OPERATIONS } from './local-discipline-operations.mjs';
|
|
28
|
-
import { assertIdeExecution } from './ide-session.mjs';
|
|
28
|
+
import { assertIdeExecution, settleBreakGlassSession } from './ide-session.mjs';
|
|
29
29
|
import { runManagedWorkflowLocalStep } from './workflow-local-client.mjs';
|
|
30
30
|
import { localErrorEnvelope } from './local-error.mjs';
|
|
31
31
|
|
|
@@ -101,6 +101,7 @@ export async function runLocal(args = [], dependencies) {
|
|
|
101
101
|
const validated = await checkedLocalInput(operation, input);
|
|
102
102
|
const supplied = operation === 'workflow-run-step' || Object.hasOwn(LOCAL_CHAIN_OPERATIONS, operation) ? dependencies : undefined;
|
|
103
103
|
const output = await withLocalInvocation(operation, validated, () => withBudgetReadContext(validated, () => handler(validated, supplied)));
|
|
104
|
+
await settleBreakGlassSession(['local', ...args], validated, output);
|
|
104
105
|
process.stdout.write(`${JSON.stringify(output)}\n`);
|
|
105
106
|
if (['pending', 'blocked', 'failed', 'incomplete'].includes(output?.status)) process.exitCode = 2;
|
|
106
107
|
} catch (cause) {
|
|
@@ -115,5 +116,7 @@ export async function runLocalInput(operation, input, dependencies) {
|
|
|
115
116
|
if (!handler) throw new Error(`Unsupported local operation: ${operation}`);
|
|
116
117
|
const validated = await checkedLocalInput(operation, input);
|
|
117
118
|
const supplied = operation === 'workflow-run-step' || Object.hasOwn(LOCAL_CHAIN_OPERATIONS, operation) ? dependencies : undefined;
|
|
118
|
-
|
|
119
|
+
const output = await withLocalInvocation(operation, validated, () => withBudgetReadContext(validated, () => handler(validated, supplied)));
|
|
120
|
+
await settleBreakGlassSession(['local', operation], validated, output);
|
|
121
|
+
return output;
|
|
119
122
|
}
|
package/local-final-gate16.mjs
CHANGED
|
@@ -96,8 +96,8 @@ async function performRole16(role, prepared) {
|
|
|
96
96
|
verifiedAt: status === 'verified' ? new Date(now).toISOString() : null };
|
|
97
97
|
return { execution, result, response };
|
|
98
98
|
}
|
|
99
|
-
function finished16(input, prepared, record) {
|
|
100
|
-
const
|
|
99
|
+
export function finished16(input, prepared, record, now = Date.now()) {
|
|
100
|
+
const roles = Object.fromEntries(FINAL_GATE16_ROLES.map(role => [role, record.roles[role].response]));
|
|
101
101
|
let status = FINAL_GATE16_ROLES.every(role => roles[role].status === 'verified') ? 'verified'
|
|
102
102
|
: FINAL_GATE16_ROLES.some(role => roles[role].status === 'blocked') ? 'blocked' : 'incomplete';
|
|
103
103
|
if (status === 'verified') for (const role of FINAL_GATE16_ROLES) {
|
package/manifest.json
CHANGED
package/package.json
CHANGED
package/release-state.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "entrorove.release-state/1.0",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"digest": "
|
|
3
|
+
"version": "0.1.48",
|
|
4
|
+
"digest": "6f79c0e2c12d4e8766801bf117bcf73070156ba89fb87e4b1137c9706b8f7df3",
|
|
5
5
|
"files": {
|
|
6
6
|
"ide-code-mode.mjs": "f3f53357ba09727b3b597851976a24de93287c0faca5052448277d0904bb61f7",
|
|
7
|
-
"ide-command.mjs": "
|
|
8
|
-
"ide-hook.mjs": "
|
|
7
|
+
"ide-command.mjs": "dcd4b48305cc4f106e5e4509e794e4b46ef02de29afa9cccbbc2774308c81ff3",
|
|
8
|
+
"ide-hook.mjs": "2f00e56de1e1149f117714d5dd334196f1a3f206c3bfab541393bc0f625e0108",
|
|
9
9
|
"ide-install.mjs": "10247efadcfeef5da001022d12080bd0f789e67fdf7862bcc65db73dda3bbe57",
|
|
10
|
-
"ide-session.mjs": "
|
|
11
|
-
"break-glass.mjs": "
|
|
10
|
+
"ide-session.mjs": "dc256e77b03303932d354768c0e79384340a3137e7421b4ae9c869f7e58e1a3a",
|
|
11
|
+
"break-glass.mjs": "6ec9f97c5d68bb33121b2374c06b9d4c8eb3419b52d00849fec7124bc63e4582",
|
|
12
12
|
"ide-results.mjs": "dfe0d3f773c65a9fc21056538d7005012c982ed4509bc0410d7f62813d0863fd",
|
|
13
13
|
"ide-queue.mjs": "806e716c775fd0079417027b135977c8516f47dddb0bc5ca19e32a355dab0e9e",
|
|
14
14
|
"local-discipline-actions.mjs": "2379c08d0f49c44068f8239db7e514d75885f4606b1b88a7a36e4ff19167caca",
|
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
"runtime/validator-runtime-v7.0.44.d.mts": "7797edbfe2f7de24da370204dce4dfd22822a1bd80df93514fff900b98afe36f",
|
|
30
30
|
"snapshot-retention.mjs": "4f8919fe8ec49fb4c23e080a8ad2fa3a9282bca3fffe7cf55c64e89ef316697e",
|
|
31
31
|
"snapshot-cleanup-journal.mjs": "76a9684cc95b4eb076e1298d78a9dff37948b00d9607b8f546c599072d3ed331",
|
|
32
|
-
"IDE-EXECUTION.md": "
|
|
32
|
+
"IDE-EXECUTION.md": "6c8b9abe17cc8f01aa3da2ab19ed34b2b9be3e3b38c1739fa6a7d763622c4864",
|
|
33
33
|
"REUSE-DISCIPLINE.md": "295ecd41c931b00c21d009ab65ac160f0e2ab81b4000ed498d2e8e97c2dc6c63",
|
|
34
34
|
"reuse-discipline-release.mjs": "20ded9c21bd71b8779c454f5eba4c7c0a943ef99d94117b9bbef891d2ab6e3de",
|
|
35
|
-
"local-final-gate16.mjs": "
|
|
35
|
+
"local-final-gate16.mjs": "083aec470670e6cdb7ad2ab27b7a51b53a9ec3a8b4121cb9cbfa17d9940892c2",
|
|
36
36
|
"local-final-gate16-checks.mjs": "1dd30e9666d458d8b12ca6e4975f6f0ac8450c3ea9cbecc7401ae037f66b589a",
|
|
37
37
|
"local-final-gate16-worker.mjs": "344d64b6c1c5552b96960e0d8514a876a3dbfa9762ab9eb749038e8351727121",
|
|
38
38
|
"local-final-gate16-plan.mjs": "9d34c51fa239376e552abc312409a7f3258519efe0b29d88a5054680cdda483c",
|
|
@@ -73,18 +73,18 @@
|
|
|
73
73
|
"local-autocoord17-waits.mjs": "2b0a713987822548a94e1ed3a9a891532db45383797dfc5d5bc8d1e35593cf25",
|
|
74
74
|
"local-validator-isolation17.mjs": "48e94604e28b8fddd567dfb35ff60b73fd094a5803bd49f076388b7f310f92aa",
|
|
75
75
|
"local-calctool-composition17.mjs": "ac89fcb41ab0d0d9b47c1b5696945281b0894eb064820775e36a011c76314e6a",
|
|
76
|
-
"cli.mjs": "
|
|
77
|
-
"install-cleanup.mjs": "
|
|
76
|
+
"cli.mjs": "2f1fa353a80000ed26061feeb44a6a4ad12e32a2f49c84bfbb6c54f89f519b7b",
|
|
77
|
+
"install-cleanup.mjs": "8a8e1a7dfe37427f86cd4d6e317890d0829894a9949d4216674a716b36edbc54",
|
|
78
78
|
"review-client.mjs": "3491eef68ed533174b31db3c53febb6519b8f088f71a9964644714a9a4c03c77",
|
|
79
79
|
"version.mjs": "1f392147d72c40af4b03b307ea607075fb815af5174fa07e254b95fe12dbf3e7",
|
|
80
|
-
"SKILL.md": "
|
|
80
|
+
"SKILL.md": "0d581e76d8c959ae04e091e24df5580e56d9ec9b6c1c6fa25a531a21e8b88ea4",
|
|
81
81
|
"CAPABILITY-MAP.md": "a0f0468a098725ced52a96dd8e22bfc7d1ce7681a8446ebf7dae3696c76c3385",
|
|
82
82
|
"AGREEMENT.md": "f93a68e92c457200dd024610e65f74e478b8f60860f951da818b70561f1b9bf8",
|
|
83
83
|
"DELIVERY-BOUNDARIES.md": "d1bb2895e23fc14bf1c76707bd1f6f03b39695501a78a0b7289dc37b099889dc",
|
|
84
84
|
"package.json": "8be823b5756da9b393af966a4152bee301cb49f988823aaf757e8c51bf867085",
|
|
85
85
|
"manifest.json": "ab06e307795bc9da5add926752b6c4dbdaf18625090261a035aa356a679c504f",
|
|
86
|
-
"release.mjs": "
|
|
87
|
-
"local-cli.mjs": "
|
|
86
|
+
"release.mjs": "34a3da868e8b5b586b318f2e8275f2f238d48a20afceb7d51c0f783a120f6973",
|
|
87
|
+
"local-cli.mjs": "11461e4cf4f6a8612ff275bf8296ec57ff22281156cb2c72834d3c764ba422a1",
|
|
88
88
|
"local-state-lock.mjs": "1dbf64264642a0851faf043e07ee9f66d2ad0508e9f799b0626246e42fae893e",
|
|
89
89
|
"local-execution.mjs": "46fddd78cd954fb080c660affe90cdaa716695580427336acb820089441a8025",
|
|
90
90
|
"local-integrity.mjs": "e6d6eace80c610f3c7299d4f8644b0dc023aa9e3d8d64b26535ea7fbced248f1",
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
"blueprint-criterion-wire.mjs": "fb6b7dcce0b97a699e3e8968372767a3fddd83fedc750998573f789177243072",
|
|
96
96
|
"blueprint-criterion-runner.mjs": "761c0e670b4b20c6bed53e5ca5d0178759505c3977ea2ed1b7223383c534bc4c",
|
|
97
97
|
"local-chain-bindings.mjs": "b8eff999ccd17b53c614a3c9f5376da78fcaa8632bb3e07bc1adcceda2e75f6c",
|
|
98
|
-
"local-chain-broker.mjs": "
|
|
98
|
+
"local-chain-broker.mjs": "d9a63f2c9eec561853a84ab5fdb7d6794f256582126017c54e5d21d0d370b015",
|
|
99
99
|
"local-chain-contracts.mjs": "d4d2be4e5c6980f2dda8ff598c7333a75e0bbf2f656aa7fe327af7c9fe73da07",
|
|
100
100
|
"local-chain-controller.mjs": "dd80d8001a11d8433b615a017a34c30dd130ff5cd9c5b58731314a8f93c9571b",
|
|
101
101
|
"local-chain-human.mjs": "9d5dbaef13ebbbe0cfdd1146cd9c48cefcca30f33ccc0b1566e67cbd730d3499",
|
|
@@ -152,7 +152,7 @@
|
|
|
152
152
|
"local-scope-state.mjs": "8b600a91fc0068d7a8c0bb752ddba7ed30ada93daafb118d6cba2368fd94cb27",
|
|
153
153
|
"local-scope-workspaces.mjs": "a44c34537e5ed2dcaf193a985e5bc05957989fbb160a650f9e37ba7d66eb2de8",
|
|
154
154
|
"local-task-routing.mjs": "6e2e506b2fb0e2e8d8c5147d7df32849b57a4e94a23634f01a355d45735858e4",
|
|
155
|
-
"remote-client.mjs": "
|
|
155
|
+
"remote-client.mjs": "bfb58132759a4312adc8ab33115d807c5a8d90c955aca3678e361ab9cefa84bd",
|
|
156
156
|
"cloud-task-client.mjs": "11acb1a033c94cdfbdfb177a3402ad97f6a5226f577138c8cf6395dc3ebb1a39",
|
|
157
157
|
"scope-runner-client.mjs": "646ab4f80d4a8209e922fd45f40efd968f0744d9dfc03188b222c1a2e11e83b8",
|
|
158
158
|
"native-client.mjs": "6f5575909bae9daba643287f876ffa0f9ff1c53a367b32a40145d740456d6605",
|
package/release.mjs
CHANGED
|
@@ -278,10 +278,7 @@ function releaseNote(changed) {
|
|
|
278
278
|
const distinct = distinctReleaseLabels(changed, releaseLabels())
|
|
279
279
|
return { zh: `更新了${distinct.map(label => label.zh).join('、')}。`, en: `Updated ${distinct.map(label => label.en).join(', ')}.` }
|
|
280
280
|
}
|
|
281
|
-
|
|
282
|
-
return withFinalGate16ReleaseLabels({ ...reuseDisciplineReleaseLabels, ...calctoolReleaseLabels, ...mutationReleaseLabels, ...swarmReleaseLabels, ...coordination17ReleaseLabels, ...nativeReadReleaseLabels, ...feedbackReleaseLabels, ...invocationReleaseLabels, ...chainReleaseLabels, ...taskEntryReleaseLabels,
|
|
283
|
-
'blueprint-criterion-wire.mjs': { zh: '蓝图验收标准执行授权', en: 'Blueprint criterion execution authority' },
|
|
284
|
-
'blueprint-criterion-runner.mjs': { zh: '蓝图验收标准实际执行器', en: 'Blueprint criterion process runner' },
|
|
281
|
+
const archguardReleaseLabels = {
|
|
285
282
|
'local-archguard-ast.mjs': { zh: 'Archguard 架构合同与执行守卫', en: 'Archguard architecture contract and execution guard' },
|
|
286
283
|
'local-archguard-checkpoint.mjs': { zh: 'Archguard 架构合同与执行守卫', en: 'Archguard architecture contract and execution guard' },
|
|
287
284
|
'local-archguard-components.mjs': { zh: 'Archguard 架构合同与执行守卫', en: 'Archguard architecture contract and execution guard' },
|
|
@@ -298,6 +295,11 @@ function releaseLabels() {
|
|
|
298
295
|
'local-archguard.mjs': { zh: 'Archguard 架构合同与执行守卫', en: 'Archguard architecture contract and execution guard' },
|
|
299
296
|
'archguard-runtime-build.mjs': { zh: 'Archguard 架构合同与执行守卫', en: 'Archguard architecture contract and execution guard' },
|
|
300
297
|
'runtime/archguard-runtime-v7.0.44.mjs': { zh: 'Archguard 架构合同与执行守卫', en: 'Archguard architecture contract and execution guard' },
|
|
298
|
+
}
|
|
299
|
+
function releaseLabels() {
|
|
300
|
+
return withFinalGate16ReleaseLabels({ ...reuseDisciplineReleaseLabels, ...calctoolReleaseLabels, ...mutationReleaseLabels, ...swarmReleaseLabels, ...coordination17ReleaseLabels, ...nativeReadReleaseLabels, ...feedbackReleaseLabels, ...invocationReleaseLabels, ...chainReleaseLabels, ...taskEntryReleaseLabels, ...archguardReleaseLabels,
|
|
301
|
+
'blueprint-criterion-wire.mjs': { zh: '蓝图验收标准执行授权', en: 'Blueprint criterion execution authority' },
|
|
302
|
+
'blueprint-criterion-runner.mjs': { zh: '蓝图验收标准实际执行器', en: 'Blueprint criterion process runner' },
|
|
301
303
|
'cli.mjs': { zh: '技能运行和受管安装', en: 'skill runtime and managed installation' },
|
|
302
304
|
'install-cleanup.mjs': { zh: '旧版受管安装清理', en: 'managed installation cleanup' },
|
|
303
305
|
'version.mjs': { zh: '版本安全检查', en: 'version safety checks' },
|
package/releases.json
CHANGED
|
@@ -1,4 +1,34 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.1.48",
|
|
4
|
+
"date": "2026-10-16",
|
|
5
|
+
"zh": "新增标准命令 `install --host codex`,仅配置 Codex 并保留 Claude 的配置与技能副本;后续自动更新沿用已配置的宿主范围。安装命令守卫和旧版清理也按目标宿主限界。",
|
|
6
|
+
"en": "Added the standard `install --host codex` command to configure Codex while preserving Claude configuration and skill copies. Later automatic updates retain the already configured host scope; installer command guards and obsolete-install cleanup honor the selected host."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"version": "0.1.47",
|
|
10
|
+
"date": "2026-10-16",
|
|
11
|
+
"zh": "修复失败 flow 的取消、放弃和会话解绑;离线 unlock 仅恢复当前会话并保留任务队列。放行授权根或依赖目录内的只读 tsconfig 引用,越界错误说明原路径、解析结果和原因。升级时清理未改动的旧受管安装,保留用户编辑及其他任务;IDE 钩子仅对已绑定的会话和仓库生效。",
|
|
12
|
+
"en": "Fixed cancellation, abandonment, and session unbinding for failed flows; offline unlock restores only the current session and preserves its queue. Read-only tsconfig references inside the authorized root or dependency directories are accepted, while escape errors identify the input path, resolved path, and reason. Upgrades remove pristine obsolete managed installs while preserving user edits and unrelated tasks; IDE hooks apply only to a bound session and repository."
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"version": "0.1.46",
|
|
16
|
+
"date": "2026-10-16",
|
|
17
|
+
"zh": "更新了Codex 后续轮次工具门禁、IDE 执行与复用纪律文档、技能运行和受管安装、IDE 工作流程说明。",
|
|
18
|
+
"en": "Updated Codex tool guards across turns, IDE execution and reuse discipline documentation, skill runtime and managed installation, IDE workflow instructions."
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"version": "0.1.45",
|
|
22
|
+
"date": "2026-10-16",
|
|
23
|
+
"zh": "更新了原链同流程技能调用。",
|
|
24
|
+
"en": "Updated original-chain skill calls on the same workflow."
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"version": "0.1.44",
|
|
28
|
+
"date": "2026-10-16",
|
|
29
|
+
"zh": "更新了Calctool 审计测试运维真实检查与独立最终闸门、自动版本与更新日志。",
|
|
30
|
+
"en": "Updated Calctool audit, test, operations checks and independent final gate, automatic versioning and changelog."
|
|
31
|
+
},
|
|
2
32
|
{
|
|
3
33
|
"version": "0.1.43",
|
|
4
34
|
"date": "2026-10-16",
|
package/remote-client.mjs
CHANGED
|
@@ -85,6 +85,7 @@ export async function invokeRemote(data, dependencies) {
|
|
|
85
85
|
process.stdout.write(JSON.stringify(presentInvocationNotices(result,dependencies.onIdeEvent,{home})) + '\n');
|
|
86
86
|
if (!response.ok || result.output.status === 'blocked' || result.output.status === 'failed'
|
|
87
87
|
|| result.output.status === 'incomplete') process.exitCode = 2;
|
|
88
|
+
return result;
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
export async function invokeRemoteResult(data, dependencies) {
|