背景与授权
从 #5720 拆出。维护者 2026-08-06 已在 #5720 的裁决评论中预批本项立项(原文:「附带批准:os:check 块禁 ctx: any 的门禁约束立项(落 spec scripts,可同 PR 或由承接方拆单)」),#5720 的实现 PR 选择拆单交付,故本单只做门禁,不含文档改写。
未加 pm:* 标签,交分诊路由定级。
问题
{/* os:check */}(.mdx)/ <!-- os:check -->(skills/**)是作者的声明:「这段应当能编译」。packages/spec/scripts/check-skill-examples.ts 会把每个被标记的块真的丢给 tsc --noEmit 编译 —— 但块内一旦把入参标成 any,该参数上每一次属性访问都不再被检查,门是绿的,覆盖的却是零。
#5720 是这道空门的实测标本:两段被标记的 hook 示例写着 export async function beforeUpdate(ctx: any),读的 ctx.services 在 hook 上下文里根本不存在(引擎逐键构造九键、沙箱十键均不产),照抄的 hook 会因可选链短路无条件抛 PERMISSION_DENIED、拒掉每一次写入 —— 而 check:skill-examples 一直是绿的。把同一段函数体的 any 换成如实的 HookContext 再编译,立刻两处报同一条:
error TS2339: Property 'services' does not exist on type '{ object: string; event: …; input: Record< string, unknown >; … }'
同一个 any 同时掩盖了 #5605 的 ctx.session?.positions(当时是 TS2339)和 #5720 的 ctx.services。一个标了 os:check 又把入参标 any 的示例,等于声明「这段编译得过」却什么也没证明 —— 与该脚本已有的两道反空转断言(orphan marker、零块 fail())同一族,只是缺了这一条。
建议约束
在 packages/spec/scripts/check-skill-examples.ts 的提取阶段(extractFromFile 之后、写 build dir 之前)对被标记块加一条静态检查:参数标注为 any(含 Promise< any >、Record< string, any > 之外的裸参数标注、(ctx: any) / (ctx: any, x: any) / function f(ctx: any) / 箭头函数同形)即失败,报到 页面:真实行号,并给出处方(标真实类型,或去掉 os:check 标记)。
待定的细节,建议由承接方按现状实测后定,不要预设:
验收
关联
背景与授权
从 #5720 拆出。维护者 2026-08-06 已在 #5720 的裁决评论中预批本项立项(原文:「附带批准:os:check 块禁
ctx: any的门禁约束立项(落 spec scripts,可同 PR 或由承接方拆单)」),#5720 的实现 PR 选择拆单交付,故本单只做门禁,不含文档改写。未加
pm:*标签,交分诊路由定级。问题
{/* os:check */}(.mdx)/<!-- os:check -->(skills/**)是作者的声明:「这段应当能编译」。packages/spec/scripts/check-skill-examples.ts会把每个被标记的块真的丢给tsc --noEmit编译 —— 但块内一旦把入参标成any,该参数上每一次属性访问都不再被检查,门是绿的,覆盖的却是零。#5720 是这道空门的实测标本:两段被标记的 hook 示例写着
export async function beforeUpdate(ctx: any),读的ctx.services在 hook 上下文里根本不存在(引擎逐键构造九键、沙箱十键均不产),照抄的 hook 会因可选链短路无条件抛PERMISSION_DENIED、拒掉每一次写入 —— 而check:skill-examples一直是绿的。把同一段函数体的any换成如实的HookContext再编译,立刻两处报同一条:同一个
any同时掩盖了 #5605 的ctx.session?.positions(当时是 TS2339)和 #5720 的ctx.services。一个标了 os:check 又把入参标any的示例,等于声明「这段编译得过」却什么也没证明 —— 与该脚本已有的两道反空转断言(orphan marker、零块fail())同一族,只是缺了这一条。建议约束
在
packages/spec/scripts/check-skill-examples.ts的提取阶段(extractFromFile之后、写 build dir 之前)对被标记块加一条静态检查:参数标注为any(含Promise< any >、Record< string, any >之外的裸参数标注、(ctx: any)/(ctx: any, x: any)/function f(ctx: any)/ 箭头函数同形)即失败,报到页面:真实行号,并给出处方(标真实类型,或去掉 os:check 标记)。待定的细节,建议由承接方按现状实测后定,不要预设:
as any/ 局部变量: any?([docs] runtime-services 的 hook 示例在教ctx.services—— hook 上下文从来没有这个键,照抄的 hook 会拒掉每一次写入 #5720 的实现里,ctx.api因契约声明为api: z.unknown()必须窄化,示例用的是一个具名局部类型as CrossObjectApi—— 若把as any一并禁掉,要确认现存 207 块里有多少要跟着改。)any入参;若非零,是一次改净还是先建棘轮(repo 内check:*棘轮惯例)。--self-test(红/绿双向:标了any的块必须红,改成真实类型必须绿)。验收
any⇒ 门红,报页面 + 行号 + 处方;ctx.services—— hook 上下文从来没有这个键,照抄的 hook 会拒掉每一次写入 #5720 落地后)全绿;--self-test覆盖红/绿两个方向。关联
ctx.services—— hook 上下文从来没有这个键,照抄的 hook 会拒掉每一次写入 #5720(runtime-services hook 示例教了不存在的ctx.services;docs-only 修法已单独交付)positions/preserveAudit—— 引擎在生产、消费方在读、文档在教,契约里没有(#5050 的镜像方向) #5605(HookContext.session补positions/preserveAudit声明 —— 被同一个any掩盖的另一半)