@entrorove/skill 0.1.43 → 0.1.47
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 +20 -0
- package/IDE-EXECUTION.md +1 -1
- package/SKILL.md +2 -2
- package/break-glass.mjs +10 -3
- package/cli.mjs +5 -3
- package/ide-hook.mjs +2 -2
- package/ide-session.mjs +43 -2
- 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 +13 -13
- package/release.mjs +6 -4
- package/releases.json +24 -0
- package/remote-client.mjs +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.47 — 2026-10-16
|
|
4
|
+
|
|
5
|
+
- 更新了Codex 后续轮次工具门禁、IDE 执行与复用纪律文档、技能运行和受管安装、IDE 工作流程说明、本地执行命令、远端恢复客户端。
|
|
6
|
+
- Updated Codex tool guards across turns, IDE execution and reuse discipline documentation, skill runtime and managed installation, IDE workflow instructions, local execution command, remote recovery client.
|
|
7
|
+
|
|
8
|
+
## 0.1.46 — 2026-10-16
|
|
9
|
+
|
|
10
|
+
- 更新了Codex 后续轮次工具门禁、IDE 执行与复用纪律文档、技能运行和受管安装、IDE 工作流程说明。
|
|
11
|
+
- Updated Codex tool guards across turns, IDE execution and reuse discipline documentation, skill runtime and managed installation, IDE workflow instructions.
|
|
12
|
+
|
|
13
|
+
## 0.1.45 — 2026-10-16
|
|
14
|
+
|
|
15
|
+
- 更新了原链同流程技能调用。
|
|
16
|
+
- Updated original-chain skill calls on the same workflow.
|
|
17
|
+
|
|
18
|
+
## 0.1.44 — 2026-10-16
|
|
19
|
+
|
|
20
|
+
- 更新了Calctool 审计测试运维真实检查与独立最终闸门、自动版本与更新日志。
|
|
21
|
+
- Updated Calctool audit, test, operations checks and independent final gate, automatic versioning and changelog.
|
|
22
|
+
|
|
3
23
|
## 0.1.43 — 2026-10-16
|
|
4
24
|
|
|
5
25
|
- 更新了Codex 后续轮次工具门禁、复用与变更一致性门禁、IDE 执行与复用纪律文档、技能运行和受管安装、旧版受管安装清理、IDE 工作流程说明、任务交付边界说明、安装包配置、自动版本与更新日志、本地三轴读取预算、本地阶段边界与可恢复停止、远端恢复客户端、账号沙箱偏好与任务入口确认、工作流本地调用契约。
|
package/IDE-EXECUTION.md
CHANGED
|
@@ -2,7 +2,7 @@ Install or update the managed copy with `npx @entrorove/skill install`. The inst
|
|
|
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.47.
|
|
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
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 IDE lifecycle hook configuration; 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
|
|
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
|
@@ -19,7 +19,7 @@ import { watchCloudTask } from './cloud-watch-client.mjs';
|
|
|
19
19
|
import { queryAutomaticFeedback } from './automatic-feedback-client.mjs';
|
|
20
20
|
import { activeIdeAdapters, 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'];
|
|
@@ -388,7 +388,9 @@ async function invoke(data) {
|
|
|
388
388
|
if (data?.operation === 'cloud-task') return runCloudTask(data.input, remoteDependencies());
|
|
389
389
|
if (data?.operation === 'cloud-status') return runCloudStatus(data.input, remoteDependencies());
|
|
390
390
|
if (data?.operation === 'cloud-watch') return runCloudWatch(data.input);
|
|
391
|
-
|
|
391
|
+
const result = await invokeRemote(data, remoteDependencies());
|
|
392
|
+
await settleBreakGlassSession(['invoke'], data, result);
|
|
393
|
+
return result;
|
|
392
394
|
}
|
|
393
395
|
|
|
394
396
|
export { buildReview };
|
|
@@ -422,7 +424,7 @@ async function runAccountCommand(command, args) {
|
|
|
422
424
|
async function main() {
|
|
423
425
|
const [command, ...args] = process.argv.slice(2);
|
|
424
426
|
if (command === 'unlock' && args.length === 0) {
|
|
425
|
-
process.stdout.write(`${JSON.stringify(await writeBreakGlass())}\n`);
|
|
427
|
+
process.stdout.write(`${JSON.stringify(await writeBreakGlass(os.homedir(), Date.now(), ideGuardBinding().sessionId))}\n`);
|
|
426
428
|
} else if (command === 'uninstall' && args.length === 0) {
|
|
427
429
|
const result = await uninstall();
|
|
428
430
|
process.stdout.write(`${JSON.stringify(result)}\n`);
|
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/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.47",
|
|
4
|
+
"digest": "479d681e00143de8b7ac8191a245dd1240918b9ff5c0fcca2145b0a73a184452",
|
|
5
5
|
"files": {
|
|
6
6
|
"ide-code-mode.mjs": "f3f53357ba09727b3b597851976a24de93287c0faca5052448277d0904bb61f7",
|
|
7
7
|
"ide-command.mjs": "158d8f26c1dc28a04284e429150a2060d7278661f656a75e7e9f7600f536b7bf",
|
|
8
|
-
"ide-hook.mjs": "
|
|
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": "fc40040262f07d6bcc64fe157e200bfb85e6ea1845109e4624e7903745877891",
|
|
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": "
|
|
76
|
+
"cli.mjs": "0119f5c5647c41ba5a4b709664b529be76f1a9b698ab9574ba38e6683eff9717",
|
|
77
77
|
"install-cleanup.mjs": "72bb6bd55382449a986828cd1ae3e98e5fd0bf373f89bbdcc039023ae72a2337",
|
|
78
78
|
"review-client.mjs": "3491eef68ed533174b31db3c53febb6519b8f088f71a9964644714a9a4c03c77",
|
|
79
79
|
"version.mjs": "1f392147d72c40af4b03b307ea607075fb815af5174fa07e254b95fe12dbf3e7",
|
|
80
|
-
"SKILL.md": "
|
|
80
|
+
"SKILL.md": "6d55d552c31ee30795aec5e29b5f3eb0a007b8da9a81431901fae4b20b3f4be5",
|
|
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,28 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.1.47",
|
|
4
|
+
"date": "2026-10-16",
|
|
5
|
+
"zh": "更新了Codex 后续轮次工具门禁、IDE 执行与复用纪律文档、技能运行和受管安装、IDE 工作流程说明、本地执行命令、远端恢复客户端。",
|
|
6
|
+
"en": "Updated Codex tool guards across turns, IDE execution and reuse discipline documentation, skill runtime and managed installation, IDE workflow instructions, local execution command, remote recovery client."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"version": "0.1.46",
|
|
10
|
+
"date": "2026-10-16",
|
|
11
|
+
"zh": "更新了Codex 后续轮次工具门禁、IDE 执行与复用纪律文档、技能运行和受管安装、IDE 工作流程说明。",
|
|
12
|
+
"en": "Updated Codex tool guards across turns, IDE execution and reuse discipline documentation, skill runtime and managed installation, IDE workflow instructions."
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"version": "0.1.45",
|
|
16
|
+
"date": "2026-10-16",
|
|
17
|
+
"zh": "更新了原链同流程技能调用。",
|
|
18
|
+
"en": "Updated original-chain skill calls on the same workflow."
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"version": "0.1.44",
|
|
22
|
+
"date": "2026-10-16",
|
|
23
|
+
"zh": "更新了Calctool 审计测试运维真实检查与独立最终闸门、自动版本与更新日志。",
|
|
24
|
+
"en": "Updated Calctool audit, test, operations checks and independent final gate, automatic versioning and changelog."
|
|
25
|
+
},
|
|
2
26
|
{
|
|
3
27
|
"version": "0.1.43",
|
|
4
28
|
"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) {
|