cli-aimlock 7.0.37 → 7.0.39

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.
@@ -0,0 +1,151 @@
1
+ import { refreshManagedSkillCopies } from './installer-storage.mjs'
2
+ import { execFile, spawn } from 'node:child_process'
3
+ import { promisify } from 'node:util'
4
+ import { lstat, mkdtemp, readFile, rename, rm } from 'node:fs/promises'
5
+ import { join, win32 } from 'node:path'
6
+ import { assertAccountAncestors, currentAccountHome, ensureAccountDirectory } from './broker-account-storage.mjs'
7
+ import { pathToFileURL } from 'node:url'
8
+ import { accountBrokerDirectory } from './broker-credentials.mjs'
9
+ import { createBrokerTransport } from './broker-transport.mjs'
10
+
11
+ const runFile = promisify(execFile)
12
+ export const LOOKUP_TIMEOUT_MS = 8000
13
+ const INSTALL_TIMEOUT_MS = 120_000
14
+ const RELEASE_PATTERN = /^(?:v)?(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$/
15
+ const OFFICIAL_IDENTITIES = Object.freeze({
16
+ 'cli-aimlock': 'R3mQ8kWpXn', 'cli-blueprint': 'wvz6zmRWmX', 'cli-calctool': 'KKyA6xljUX',
17
+ 'cli-swarm': 'zj7fTPVh4p', 'cli-validator': 'Xx9ZkQmW3p', 'cli-confirm-protocol': 'Cf8Pr7Tm2Q',
18
+ 'cli-archguard': 'Ag4Ch8Rd2K', 'cli-mergeguard': 'Mm7GnPqR2v',
19
+ })
20
+
21
+ function releaseVersion(value) {
22
+ if (typeof value !== 'string' || !RELEASE_PATTERN.test(value)) throw new Error('Official release version must be X.Y.Z')
23
+ return value.replace(/^v/, '')
24
+ }
25
+
26
+ export async function inspectOfficialRelease(context, dependencies = {}) {
27
+ if (OFFICIAL_IDENTITIES[context.npmName] !== context.runtimeCode || typeof context.packageRoot !== 'string'
28
+ || context.endpoint !== 'https://cli.tax/' + context.runtimeCode) {
29
+ throw new Error('Official package identity is required for the update check')
30
+ }
31
+ const environment = dependencies.environment === undefined ? process.env : dependencies.environment
32
+ const request = dependencies.request === undefined ? createBrokerTransport({ environment }) : dependencies.request
33
+ const endpoint = 'https://cli.tax/api/public/skills/' + context.runtimeCode
34
+ if (!/^[A-Za-z0-9]{10}$/.test(context.runtimeCode)) throw new Error('Official runtime code is invalid')
35
+ const response = await request(endpoint, { redirect: 'error', signal: AbortSignal.timeout(LOOKUP_TIMEOUT_MS) })
36
+ if (!response.ok) throw new Error('Official release lookup failed: HTTP ' + response.status)
37
+ const payload = await response.json()
38
+ const version = releaseVersion(payload.version)
39
+ const local = releaseVersion(context.packageVersion)
40
+ const left = version.split('.').map(Number), right = local.split('.').map(Number)
41
+ const differing = left.findIndex((value, index) => value !== right[index])
42
+ if (differing !== -1 && left[differing] < right[differing]) {
43
+ throw new Error('The local development package is newer than the published release; refusing to downgrade or overwrite workspace sources')
44
+ }
45
+ return { version, current: local === version }
46
+ }
47
+
48
+ async function validateCachedPackage(directory, context, version) {
49
+ const packageRoot = join(directory, 'node_modules', context.npmName)
50
+ await assertAccountAncestors(packageRoot)
51
+ const status = await lstat(packageRoot)
52
+ if (!status.isDirectory() || status.isSymbolicLink()) throw new Error('Cached official package must be a regular directory')
53
+ const manifest = JSON.parse(await readFile(join(packageRoot, 'package.json'), 'utf8'))
54
+ const skill = JSON.parse(await readFile(join(packageRoot, 'skill', 'skill.json'), 'utf8'))
55
+ if (manifest.name !== context.npmName || manifest.version !== version || releaseVersion(skill.version) !== version
56
+ || skill.name !== context.skillName || skill.endpoint !== context.endpoint || typeof skill.schemaVersion !== 'string') {
57
+ throw new Error('Installed official package identity does not match the published release')
58
+ }
59
+ return { ...context, packageRoot, packageVersion: version, skillVersion: skill.version,
60
+ schemaVersion: skill.schemaVersion, skillDir: join(packageRoot, 'skill') }
61
+ }
62
+
63
+ export function windowsNpmEntry(output) {
64
+ const commands = output.split(/\r?\n/).map(line => line.trim()).filter(line => /\\npm\.cmd$/i.test(line))
65
+ if (!commands.length || !win32.isAbsolute(commands[0]) || /[\u0000-\u001f]/.test(commands[0])) {
66
+ throw new Error('where.exe did not return an absolute npm.cmd location')
67
+ }
68
+ return { command: commands[0], script: win32.join(win32.dirname(commands[0]), 'node_modules', 'npm', 'bin', 'npm-cli.js') }
69
+ }
70
+
71
+ async function npmInvocation(environment) {
72
+ if (process.platform !== 'win32') return { executable: 'npm', args: [] }
73
+ const found = await runFile('where.exe', ['npm'], { env: environment, windowsHide: true, timeout: LOOKUP_TIMEOUT_MS })
74
+ const entry = windowsNpmEntry(found.stdout)
75
+ for (const path of [entry.command, entry.script]) {
76
+ await assertAccountAncestors(win32.dirname(path), 'win32')
77
+ const status = await lstat(path)
78
+ if (!status.isFile() || status.isSymbolicLink()) throw new Error('Windows npm entry must be a regular file without symlink ancestors')
79
+ }
80
+ return { executable: process.execPath, args: [entry.script] }
81
+ }
82
+
83
+ async function installPackage(directory, context, version, environment) {
84
+ if (typeof environment.PATH !== 'string' || !environment.PATH) throw new Error('Package installation PATH is required')
85
+ const childEnvironment = { PATH: environment.PATH, HOME: currentAccountHome() }
86
+ for (const name of ['HTTPS_PROXY', 'HTTP_PROXY', 'NO_PROXY', 'NODE_EXTRA_CA_CERTS', 'SystemRoot', 'COMSPEC', 'PATHEXT']) {
87
+ if (environment[name] !== undefined) childEnvironment[name] = environment[name]
88
+ }
89
+ const invocation = await npmInvocation(childEnvironment)
90
+ await new Promise((accept, reject) => {
91
+ const child = spawn(invocation.executable, [...invocation.args, 'install', '--prefix', directory,
92
+ '--ignore-scripts', '--no-audit', '--no-fund', '--package-lock=false', '--save-exact',
93
+ '--registry=https://registry.npmjs.org', context.npmName + '@' + version],
94
+ { env: childEnvironment, stdio: 'ignore', timeout: INSTALL_TIMEOUT_MS })
95
+ child.once('error', reject)
96
+ child.once('exit', (code, signal) => code === 0 ? accept()
97
+ : reject(new Error('Official package update failed: exit=' + code + ' signal=' + signal)))
98
+ })
99
+ }
100
+
101
+ export async function latestOfficialSkillContext(context, dependencies = {}) {
102
+ const release = await inspectOfficialRelease(context, dependencies)
103
+ if (release.current) return context
104
+ const environment = dependencies.environment === undefined ? process.env : dependencies.environment
105
+ const home = dependencies.homeDirectory === undefined ? currentAccountHome() : dependencies.homeDirectory
106
+ const directory = join(accountBrokerDirectory(environment, process.platform, home), 'packages')
107
+ await ensureAccountDirectory(directory, dependencies)
108
+ const target = join(directory, context.npmName + '-' + release.version)
109
+ try {
110
+ await lstat(target)
111
+ return await validateCachedPackage(target, context, release.version)
112
+ } catch (error) { if (error.code !== 'ENOENT') throw error }
113
+ const staged = await mkdtemp(join(directory, '.update-'))
114
+ try {
115
+ const install = dependencies.installPackage === undefined ? installPackage : dependencies.installPackage
116
+ await install(staged, context, release.version, environment)
117
+ await validateCachedPackage(staged, context, release.version)
118
+ try { await rename(staged, target) } catch (error) {
119
+ if (!['EEXIST', 'ENOTEMPTY'].includes(error.code)) throw error
120
+ await validateCachedPackage(target, context, release.version)
121
+ }
122
+ return await validateCachedPackage(target, context, release.version)
123
+ } finally { await rm(staged, { recursive: true, force: true }) }
124
+ }
125
+
126
+ export async function latestOfficialModule(context, filename, dependencies) {
127
+ const updated = await latestOfficialSkillContext(context, dependencies)
128
+ if (updated.packageRoot === context.packageRoot) return null
129
+ return { context: updated, module: await import(pathToFileURL(join(updated.packageRoot, filename)).href) }
130
+ }
131
+
132
+ export function withUpgradeMetadata(result, upgrade) {
133
+ if (result.upgrade === undefined) return { ...result, upgrade }
134
+ return { ...result, upgrade: { ...result.upgrade, previousVersion: upgrade.previousVersion,
135
+ runtimeUpdated: upgrade.runtimeUpdated || result.upgrade.runtimeUpdated,
136
+ reloadRequired: upgrade.reloadRequired || result.upgrade.reloadRequired,
137
+ managedCopies: [...upgrade.managedCopies, ...result.upgrade.managedCopies] } }
138
+ }
139
+
140
+ export async function prepareOfficialSkillUse(context, filename, dependencies) {
141
+ const selected = await latestOfficialSkillContext(context, dependencies)
142
+ const managedCopies = await refreshManagedSkillCopies(selected, dependencies)
143
+ const runtimeUpdated = selected.packageRoot !== context.packageRoot
144
+ const changedCopies = managedCopies.filter(item => item.status === 'updated')
145
+ const upgrade = { previousVersion: context.packageVersion, version: selected.packageVersion, runtimeUpdated,
146
+ reloadRequired: runtimeUpdated || changedCopies.length > 0, managedCopies,
147
+ documentationPaths: changedCopies.map(item => item.documentationPath) }
148
+ if (runtimeUpdated) upgrade.documentationPaths.push(join(selected.skillDir, 'SKILL.md'))
149
+ return { context: selected, upgrade,
150
+ module: runtimeUpdated ? await import(pathToFileURL(join(selected.packageRoot, filename)).href) : null }
151
+ }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "cli-aimlock": "./cli.mjs"
4
4
  },
5
5
  "dependencies": {
6
- "cli-swarm": "7.0.37"
6
+ "cli-swarm": "7.0.39"
7
7
  },
8
8
  "description": "Aimlock skill installer for CLI.Tax: lock a user request into an executable aim and route Blueprint, Swarm, and Calctool.",
9
9
  "exports": {
@@ -11,11 +11,16 @@
11
11
  "./local-runner": "./aimlock-local-runner.mjs",
12
12
  "./runtime": "./aimlock-runtime.mjs",
13
13
  "./chain-executor": "./aimlock-chain-executor.mjs",
14
- "./brain-client": "./brain-client.mjs"
14
+ "./brain-client": "./brain-client.mjs",
15
+ "./tasks": "./aimlock-tasks-cli.mjs"
15
16
  },
16
17
  "files": [
17
18
  "cli.mjs",
18
19
  "installer.mjs",
20
+ "installer-storage.mjs",
21
+ "broker-account-storage.mjs",
22
+ "broker-credentials.mjs",
23
+ "official-skill-update.mjs",
19
24
  "broker.mjs",
20
25
  "broker-failures.mjs",
21
26
  "broker-recovery.mjs",
@@ -31,6 +36,7 @@
31
36
  "aimlock-chain-human.mjs",
32
37
  "aimlock-chain-executor.mjs",
33
38
  "aimlock-chain-cli.mjs",
39
+ "aimlock-tasks-cli.mjs",
34
40
  "aimlock-chain-outcomes.mjs",
35
41
  "aimlock-context-map.mjs",
36
42
  "aimlock-coordination.mjs",
@@ -44,7 +50,8 @@
44
50
  "aimlock-runtime.mjs",
45
51
  "brain-client.mjs",
46
52
  "brain-client-files.mjs",
47
- "skill/references/chain-executor.md"
53
+ "skill/references/chain-executor.md",
54
+ "skill/references/task-routing.md"
48
55
  ],
49
56
  "license": "UNLICENSED",
50
57
  "name": "cli-aimlock",
@@ -53,5 +60,5 @@
53
60
  "url": "https://github.com/88208555/aimlock-clitax.git"
54
61
  },
55
62
  "type": "module",
56
- "version": "7.0.37"
63
+ "version": "7.0.39"
57
64
  }
package/skill/SKILL.md CHANGED
@@ -5,7 +5,7 @@ description: "Aimlock 仅用于大型、深度、跨模块、高风险、需要
5
5
 
6
6
  # Aimlock Skill
7
7
 
8
- Package version: v7.0.37
8
+ Package version: v7.0.39
9
9
 
10
10
  Endpoint: https://cli.tax/R3mQ8kWpXn
11
11
 
@@ -63,10 +63,10 @@ Only after the applicability gate activates Aimlock:
63
63
 
64
64
  1. Call local `capabilities`, then `probe`; use only its filesystem, Git-history, package-boundary, and import-graph facts for the initial mode. Exact `targetSymbols` may resolve through a fresh ContextBase map; missing, ambiguous, or stale map entries block.
65
65
  2. Call remote `capabilities`, `intake`, and `classify`. A fallback `bypass` response stops the Aimlock chain.
66
- 3. Call `scope-contract`; empty allowed paths are blocked. Initialize the mode's local read budget before exploration.
66
+ 3. Call `scope-contract`; empty allowed paths are blocked. Initialize the mode's local read budget before exploration. For expected long work, request the exact bounded renewal policy now, before deep reads; reuse the actual approval rather than asking again after each interval.
67
67
  4. Route every source read through local `budget-read`. File/token exhaustion requires `execute`, `plan`, or `blocked`, or an exact Confirm Protocol budget extension. Time may renew automatically only after the one-time task-bound approval described below.
68
68
  5. Call `skill-route`. The server queries the current published official directory and injects only matched skills.
69
- 6. For Probe or Swarm, workers inspect read-only and return modification nodes. Lock stays on the current agent.
69
+ 6. The current agent inspects and proposes modification nodes in every mode. Delegate read-only inspection only when the shared business-necessity gate passes; Probe/Swarm mode never requires creating workers.
70
70
  7. Call `propose-nodes`, `accept-nodes`, `snapshot-plan`, and `snapshot-verify` in order.
71
71
  8. Issue a local signed mutation pass after `mutate-gate` permits the verified snapshot. Route each batch write through local `guarded-write` with the same chainId and pass.
72
72
  9. If actual files or changed lines exceed the contract budget, call local `reassess`; upgrade only one level and preserve the current snapshot, changes, and evidence. Tell the user when this occurs.
@@ -87,7 +87,7 @@ Required routing facts include `mode`, `goalKind`, `risk`, `contractUnclear`, bl
87
87
  - Confirm Protocol: when a structured user decision is required, and always for high-risk work even if the caller sends a false hint.
88
88
  - ArchGuard: only for code/mixed work in a new project or under an existing architecture contract.
89
89
  - Blueprint: only for active Probe/Swarm work when `contractUnclear=true` and no blueprint exists.
90
- - Swarm: only for active Swarm mode.
90
+ - Swarm: only for active Swarm mode; use its task and coordination rules locally. A matched skill is not a requirement to spawn agents.
91
91
  - Validator: only for high-risk work or an explicit final-validation requirement.
92
92
  - MergeGuard: only for an explicit verified-merge requirement.
93
93
  - User-named extras are analysis candidates until their own `capabilities` prove a match.
@@ -129,7 +129,7 @@ Call `interrupt` before acting on an interruption:
129
129
  - forced stop → `stop`;
130
130
  - status query → `status`;
131
131
  - related addition → `fuse`;
132
- - unrelated request → `spawn`.
132
+ - unrelated request → first query existing task ownership through `tasks message-route`; reuse its owner when resolved. Unresolved work remains a recorded pending request. Legacy `spawn` is a recommendation only and must not replace the current goal or create an unauthorized conversation.
133
133
 
134
134
  For an active incomplete goal, the caller sends exactly every 90 seconds:
135
135
 
@@ -166,7 +166,7 @@ Aimlock returns the protocol; it does not start a timer.
166
166
  ## 受限调用与自动评价闭环
167
167
 
168
168
  - IDE / 智能体必须通过本包 `invoke` 或 JSON-stdin `broker` 调用,不得直接拼装技能 HTTP 请求,也不得读取 BrainClient token。
169
- - broker `CLITAX_BRAIN_CLIENT_TOKEN_FILE` 读取身份;macOS/Linux 文件必须为当前 broker 账户所有且权限 `0600`,Windows 文件必须位于受限 `%LOCALAPPDATA%\CLI.Tax\broker` 目录。
169
+ - broker 默认读取账号共享凭据文件;显式 `CLITAX_BRAIN_CLIENT_TOKEN_FILE` 使用绝对路径覆盖;macOS/Linux 文件必须为当前 broker 账户所有且权限 `0600`,Windows 文件必须位于受限 `%LOCALAPPDATA%\CLI.Tax\broker` 目录。
170
170
  - broker 只需要 Brain Client HTTPS、受限身份文件和调用方显式传入的路径,本身不需要完整磁盘访问。若要保证 IDE 无法读取身份文件,必须把 broker 放进独立低权限系统账户或沙箱服务,并只暴露受限 IPC;broker 与 IDE 同账户运行时,`0600` 不能隔离二者,禁止声称令牌已隔离。
171
171
  - broker 只用 `Authorization: BrainClient …` 发起一次 runtime 请求。HTTP 成功后必须保留响应顶层原始 `feedbackReceiptId`、`feedbackInvocationId` 和 `feedbackEvaluation.digest`,不得生成、猜测、复用或跨调用转移。
172
172
  - Brain Client 服务端必须严格绑定请求/响应的 `requestId` 和 `schemaVersion`,再根据真实状态、验证结果、服务端耗时与 findings 生成并持久化权威评分、评语和摘要。broker 不得生成分数或评语。
@@ -194,3 +194,42 @@ Aimlock returns the protocol; it does not start a timer.
194
194
  仅在 TLS 握手前确定尚未发送 HTTP 请求时,broker 才允许最多 3 次连接尝试,并受总超时约束。请求发出后发生断线或响应中断,只用 GET 查询原 requestId 的服务端回执,禁止重发 POST;未取得有效回执时保留不确定状态,不得假定成功或继续依赖步骤。
195
195
 
196
196
  `npx cli-aimlock@latest recover <operation> <requestId>` 可重新查询原调用,不会重做操作或重复计费。链恢复不会跳过人工确认,也不会自动重跑结果不确定的本地命令。代理连接需 Node.js 22.21+ 或 24.5+;不支持的运行时会明确报错。
197
+
198
+ ## 新消息归属与原任务连续性
199
+
200
+ 多任务协作时先登记任务目标、原始验收项和宿主定位;每条用户新需求在执行前使用 [task-routing.md](references/task-routing.md) 的 `task-describe → message-route → message-accept → task-resume` 协议。先查已有任务归属,再决定当前任务补充、转交、歧义暂存或显式接手。同一条消息的独立需求分别路由,不能用新消息覆盖原目标。
201
+
202
+ 转交只是消息状态,不等于原任务完成。接收方按 requestId 去重,只有持久接收回执才算接手;来源任务继续不依赖该交接的工作。退出、上下文压缩或宿主重启后,必须先读取 `task-resume` 恢复原目标、检查点、未完成项与待投递请求。
203
+
204
+ 用户明确要求在当前任务处理时,保留原目标;已由其他任务负责的范围需 `handoff-release` 完成安全交接,再重新验证 Aimlock 范围、快照与写入权限。禁止把别人的签名租约、预算或通过证据当作当前任务的新授权。归属不明只暂存新需求,不暂停原任务。
205
+
206
+ 这些操作使用同一协调根目录的持久台账。宿主必须在新消息入口调用并消费结果;技能不能拦截未接入的 IDE,也不会自动创建会话、Git 分支、常驻服务或跨机器复制私密消息。
207
+
208
+ ## 执行完整性共同规则
209
+
210
+ 1. 工程目标、已接受范围和验收项必须持久化;新增需求先路由与合并,不能覆盖原目标。子任务有明确服务目标的理由,执行仅用本链已匹配技能。每次恢复读取 task-resume,核对剩余项、pending请求和continuationNotifications。
211
+ 2. 默认由主代理完成工作,禁止为了省事创建子代理、把简单查找/改名/少量修改/单条命令/例行检查/汇总交接给多智能体,禁止为达到门槛拆分或夸大任务。启用Aimlock或Swarm模式不是创建授权,管理/运维/安全/协调是主代理职责,不额外创建常驻智能体。只有业务确需独立且实质性的交付、主代理同时有可推进的独立工作、预期收益严格高于上下文传递/协调/验收成本时才派单;复用已有合适负责人,用户禁止委派时不得创建。每次创建前记录业务理由、交付物、验收项、主代理工作、成本收益、精确路径和原负责人;只创建当前需要的最少数量,不预建空闲角色,不递归扩编或重复扫描。规模门槛200行/3文件/跨模块仅为必要条件,不能单独证明值得委派。主代理负责整合和完整验收,不把半成品当完成;预算抱怨不是停止指令。
212
+ 3. 自报、回复送达和动作完成不等于工程交付验证。reported始终待验收;Swarm接受工程任务时复用Validator校验签名、有效期、计划/产物/任务绑定。无证据、伪造runner或失败检查不得成为绿色完成。
213
+ 4. 原任务交接前保存检查点并释放旧锁;回程只发持久通知,宿主消费后重新核验基线、快照与写入权限。历史恢复结果不是新授权。技能不能自行唤醒未接入的IDE。
214
+ 5. 心跳停止仅允许自动回收尚未开工的assigned任务;claimed/running进入执行结果待核对状态,禁止盲目重复执行。已回传、已验收、失败和取消任务不会被自动重派。服务器停滞回收同时保存会员通知,对话界面定期读取展示。
215
+ 6. 预计长任务在预算初始化后、深读前提出一次精确自动续时策略;只有真实授权才自动续时。时间、文件数、token和写入权限分别计量;额度/次数耗尽、撤销和完成必须明确停止并说明下一步。读取预算不是付费充值,计时器由宿主运行。
216
+ 7. 云端沙箱开关按调用会员读取;关闭时仅允许当前受审官方源码摘要在受控worker中直接执行,并记录executionIsolation。未知或修改过的源码明确要求sandbox,不伪造隔离结果;worker直接执行不是OS沙箱。
217
+ 8. 使用技能前检查官方发布版本并自动升级可管理的安装副本与客户端;配置失败或升级失败停止并报告。通过configure的JSON标准输入导入一次账号凭据,后续项目/分支/任务共享;密钥不进入源码、URL或命令参数。显式环境覆盖必须是绝对路径。网页复制在点击时获取当前凭据,页面仅展示无密钥地址;已撤销密钥没有权限自动获取新密钥,需已认证网页重新同步一次。
218
+
219
+ English: keep simple work with the main agent. Delegate only substantial independent business deliverables when benefits exceed coordination costs; use the fewest needed agents, never create idle management agents. Enabling Aimlock does not authorize delegation. Finish all authorized work; a cost complaint is not a stop request. Preserve the original goal; verify execution evidence; resume from durable checkpoints; never replay uncertain side effects. Read-time renewal requires bounded approval. Reuse account credentials and check managed skill updates before use; revoked credentials require an authenticated refresh.
220
+
221
+ Русский: сохраняйте исходную цель, проверяйте доказательства выполнения и возобновляйте работу из сохранённой точки. Не повторяйте операции с неизвестным результатом. Продление чтения требует ограниченного разрешения; ключи учётной записи используются повторно, обновления навыков проверяются перед вызовом.
222
+
223
+ ## 账号共享凭据与自动更新
224
+
225
+ 在已登录的能力市场复制安装入口,将内容粘贴给 IDE。页面只展示原地址,剪贴板会携带当前账号凭据。IDE 将四字段凭据 JSON 经标准输入交给 `npx cli-aimlock@latest configure`;不要放到命令参数、项目文件或日志中。一次配置供同一操作系统账号的所有项目、分支和任务使用,八个技能共享同一文件。
226
+
227
+ 默认位置:macOS 为 `~/Library/Application Support/CLI.Tax/broker/credential.json`,Linux 为 `~/.local/share/CLI.Tax/broker/credential.json`,Windows 为 `%LOCALAPPDATA%\CLI.Tax\broker\credential.json`。显式 `CLITAX_BRAIN_CLIENT_TOKEN_FILE` 仍按绝对路径覆盖默认位置;迁移旧 IDE 配置时移除其过时覆盖,再使用账号共享文件。macOS/Linux 校验当前账号所有权和0600权限;Windows校验仅当前账号与SYSTEM可访问的ACL。
228
+
229
+ 每次新技能调用先查询官方发布版本,精确版本下载并校验身份后自动使用;更新已托管的当前项目与账号技能目录,失败恢复旧目录,禁止覆盖 Git 跟踪源码或未托管内容。升级返回 `upgrade.reloadRequired` 和说明路径时,IDE 应读取更新后的 SKILL.md、核对本任务合同再继续。install/check同样自动更新,不需要每次人工发升级指令。查询不确定调用的原回执不升级、不重发操作。
230
+
231
+ 升级不会清除账号凭据;各调用重新读取共享文件,因此重新同步一次密钥后所有任务使用新值。已撤销或失效的密钥不能为自己取得新权限,必须从已认证网页重新同步一次。两个不同操作系统账号不共享私密文件。
232
+
233
+ English: configure once using JSON stdin; all tasks under the same OS account reuse the credential. Each new invocation checks and updates the official package and managed documentation. Reload updated instructions when indicated. Revoked keys require a fresh authenticated copy.
234
+
235
+ Русский: настройте ключ один раз через JSON stdin для всех задач пользователя ОС. Перед новым вызовом пакет и управляемые инструкции обновляются автоматически. Отозванный ключ требует повторной синхронизации с авторизованной страницы.
@@ -0,0 +1,13 @@
1
+ # Aimlock task message entry
2
+
3
+ Use `cli-aimlock tasks capabilities <coordinationRoot>` to discover the task registration, routing, acknowledgement, handoff and resume schemas. JSON inputs use stdin. This entry calls the installed `cli-swarm/coordinator` directly and preserves its persistent ledger.
4
+
5
+ Before executing each new user requirement, restore the original task with `task-resume`, classify distinct items and call `message-route`. Reuse an existing owner when identified. Preserve uncertain requests and the current task's unfinished requirements. Do not append new user messages as replacement execution plans or overwrite chain state.
6
+
7
+ The installed Swarm reference `references/task-routing.md` defines the shared protocol, matching evidence, receipt validation and handoff lifecycle. Do not duplicate or maintain a separate routing algorithm in Aimlock.
8
+
9
+ The `cli-aimlock/tasks` export provides `handleTaskMessage(root,input,adapter,options)`. The IDE supplies an authorized destination-aware `deliver` function and `continueTask`. Each delivery must return the destination's persisted acceptance receipt. Atomic delivery claims prevent blind retries after process interruption. The helper checks authoritative message status and reports explicit failures; only a runnable source task continues. Delivery is bounded to 30 seconds unless the host sets a positive `options.deliveryTimeoutMs`. Timeouts preserve uncertain delivery without claiming it was cancelled; a runnable original task still continues.
10
+
11
+ Explicit forced assignment must preserve the current task checkpoint. Complete `handoff-release` at the previous owner's safe boundary, then obtain a fresh Aimlock contract/snapshot/pass for the receiving scope. After completion, the previous owner uses `handoff-resume` to refresh actual file fingerprints before rebuilding its own snapshot and continuing. Credentials, budgets and previous test receipts are never transferred as new authorization.
12
+
13
+ Status questions and explicit stop/cancel retain their existing host behavior. New requirements alone never cancel an unfinished goal. Each host must call this entry at its message boundary and consume pending inboxes after restart. The package cannot intercept unrelated hosts, create tasks or Git branches, install a background service, or grant access to unrelated accounts.
package/skill/skill.json CHANGED
@@ -6,5 +6,5 @@
6
6
  "name": "aimlock",
7
7
  "schemaVersion": "aimlock.skill.request/1.1",
8
8
  "type": "Skill",
9
- "version": "v7.0.37"
9
+ "version": "v7.0.39"
10
10
  }