For AI agents: the complete documentation index is available at https://scriptedalchemy.github.io/agent-bundle/zh/llms.txt, the full documentation bundle is available at https://scriptedalchemy.github.io/agent-bundle/zh/llms-full.txt, and this page is available as Markdown at https://scriptedalchemy.github.io/agent-bundle/zh/guide/concepts/architecture.md.
跳至主要内容
  • 简体中文
  • 编译器架构

    agent-bundle 把一个项目编译为宿主原生的插件。本页描述的是编译器在今天的代码中的实际工作 方式:后续阶段读取的三层数据、生产与消费每一层的模块,以及这些阶段留下的产物清单。它是 #592 的文档切片:第 2 步的三层,以及第 3 步落地的 v2 权威清单(PR #604)。

    除非明确写出包名,下文的路径都相对于 packages/agent-bundle/src/。类型名就是编译器导出的 那些,目前还不存在 ApplicationIR、ProjectionIR 或 ArtifactIR 类型。

    本页描述的输出布局是复合插件根目录:产物输出处只有一个目录,由 targets 选择其中出现 哪些宿主投影 (#555 Wave 1, PR #578)。不存在 artifact/<host>/ 分区,也不存在 plugin target。

    三层

    src/ conventions + agent-bundle.config.ts
            │
            ▼
    config/discover.ts
      + routes/graph.ts  (compileRouteGraph)
            │
            ▼
    DiscoveredProject
      (skills, commands, rules, state, routeGraph, …)
            │
            ▼
    config/normalize.ts  →  NormalizedPlugin     ← Application layer
            │
            ▼
    adapters/*.ts  plan()
      + adapters/capabilities/*.json
            │
            ▼
    TargetArtifactPlan  (one per selected host)
            │
            ▼
    build/compose.ts  (composeProjections)       ← Projection layer
            │
            ▼
    CompositePlan  (entries, hookEntries, identity)
            │
            ▼
    build/build.ts + build/emit.ts + build/compile-stages.ts
            │
            ▼
    composite plugin root
      + agent-bundle.manifest.json
      + agent-bundle.compile-evidence.json
            │
            ▼
    build/compiler.ts + build/external-policy.ts / AB6005
      + build/validate-artifact*.ts / AB6005 (residual), AB6039
      / prepack AB7014, AB7015                   ← Artifact layer

    想了解这些箭头起点处的文件系统约定,请读项目结构;想了解 箭头终点处的字节,请读 Target 与产物。

    应用层

    发现在每次构建中运行一次,随后规范化冻结出一个与宿主无关的模型。今天这项工作由两个结构 分担;它们还不是同一个 IR。

    发现产出什么

    config/discover.ts 遍历项目并返回一个 DiscoveredProject:

    集合来源解析器
    skillssrc/skills/<name>/SKILL.md 或渲染式 Skill 模块,或显式的 skills globconfig/skill.ts
    commandssrc/commands/*.mdconfig/command.ts
    rulessrc/rules/*.mdcconfig/rule.ts
    statesrc/state.ts(以 state: false 退出)config/state-extract.ts
    assets / payloadsassets/,或配置中的 assets / payloadconfig/discover.ts
    routeGraph约定的可执行模块routes/graph.ts

    routes/graph.ts 中的 compileRouteGraph 是可执行路由的编译器。它只 glob 下列根目录 (不含其他):

    src/layout.{ts,tsx}
    src/mcp/*/layout.{ts,tsx}
    src/mcp/*/{tools,resources,prompts,apps}/*.{ts,tsx}
    src/events/*/*.{ts,tsx}
    src/events/stop.{ts,tsx}
    src/providers/*.{ts,tsx}
    src/cli/**/*.{ts,tsx}
    src/scripts/**/*.{ts,tsx,jsx}

    冻结后的结果是一个 CompiledRouteGraph(routes/types.ts):

    • servers[],CompiledServerSurface(generated / custom / command / remote / conflict),每个都持有 kind 为 tool、resource、prompt 或 app 的 CompiledAgentRoute 行。
    • cli?,CompiledCliSurface(generated / conventional / conflict),带有 CompiledCliCommand 行,其 argv 语法来自字面量 config.inputJsonSchema 或 JSON 输入。
    • events[],kind 为 event-route 的 CompiledAgentRoute 行。
    • scripts[],kind 为 script。
    • providers[],CompiledProvider(不是路由 kind;它们包裹执行)。
    • layouts?,CompiledLayout(root 或 server 作用域)。事件路由与浏览器 App 永不被包裹。
    • contracts?,路由本地的 config.inputJsonSchema 元数据,id 为 contract:<module>#inputJsonSchema。
    • digest,根据项目相对身份和声明元数据计算的 sha256。
    • diagnostics,路由图错误(AB48xx 与 AB494x)。

    每个 CompiledAgentRoute 携带 id、kind、source、约定式的 provenance、一份静态 提取的 config(或 emptyRouteConfig)、可选的有界 inputSchema、可选的 contract (共享的 RouteContract id),以及,对 MCP 路由而言,serverId。事件路由还携带 event(来自 routes/public.ts 的 CanonicalAgentEvent)。

    Skill、命令、规则、配置中声明的钩子、手写的 MCP 入口以及宿主原生的钩子文档不在这张 图里。它们留在与之并列的 DiscoveredProject / NormalizedPlugin 上。

    规范化向前传递什么

    config/normalize.ts 消费 DiscoveredProject 与已加载的配置,发出一个 NormalizedPlugin (core/types.ts)。它就是之后每个规划器读取的对象。它并不保留 CompiledRouteGraph;PreparedProject(dev/project-service.ts)把 model 与 routeGraph 作为并列字段携带。插件对象持有:

    • 身份(metadata)与所选的 targets(NormalizedTarget[],排序去重后的名称);
    • skills、commands、rules、hooks、nativeHooks、mcpServers、mcpApps、 scripts、assets、payloads;
    • 从路由图复制过来的 providers 与 layouts;
    • runtime.node(生成式可执行文件的下限);
    • 可选的 state、notices、packageBuild、marketplace 与宿主扩展。

    配置声明的钩子与 src/events/** 路由都落在 NormalizedPlugin.hooks 中。事件路由分支会 设置 eventRoute 以及形如 hook:event-route:tool-before 的 id(规范事件名里的 / 换成 -);配置分支则不会。宿主原生的 钩子文档(Claude 的 hooks/hooks.json 源等)是第三个集合 nativeHooks。

    config/validate.ts 针对同一个已发现的项目运行。它不会重新发现文件;它只判定发现阶段 已经找到的内容。

    下一层接收什么

    适配器与 build/compose.ts 接收完整的 NormalizedPlugin。它们不会再次调用 compileRouteGraph。共享的编译阶段(build/entries.ts、build/cli-bins.ts、 build/mcp-apps.ts)也读取这个模型:生成式 MCP 入口、路由式 CLI bin、脚本与 App 都从它 规划一次,然后归属到复合身份上。

    投影层

    投影是同一个 NormalizedPlugin 在某个宿主上的表示。配置键仍然是 targets。复合根目录 落地之后,这个键选择的是哪些投影会被规划进那唯一的输出目录,它并不命名产物、运行时、 分发形式或应用。

    target 从哪里进入

    1. agent-bundle.config.ts 的 targets,或 CLI 的 --target。两者都省略时, adapters/registry.ts 只接纳默认宿主 portable。
    2. config/normalize.ts 把所选名称存到 NormalizedPlugin.targets 上。
    3. build/compose.ts 的 planComposite 调用 sortedProjections(model.targets.map((t) => t.name)),并且只对这些名称运行 registry.get(name).plan(model)。
    4. plugin 不是 target。targets: ['plugin'] 与 --target plugin 都是 AB4100。
    5. inspect --target 是 api.ts 的 inspect() 上的显示过滤器:它只在打印的 plans 中保留该名称(未知名称是 AB7004)。它不会改变 selectedTargets 或复合 身份。inspect --bundler 仍然组合完整的所选集合。

    adapters/composite-layout.ts 拥有选择相关的辅助函数:sortedProjections、 projectionIdentity(排序后的名称以 + 连接,例如 claude+codex)与 hookWrapperPath。

    命令、规则、钩子或脚本上声明级的 targets 仍然表示“这个组件到达这些宿主”。当该集合 与所选集合有交集时,组件就会被包含。命令或规则若只限定在所选宿主的子集上,却位于另一个所选 宿主会按约定发现的目录中,则是 AB4105。Skill 总是发往每一个所选宿主 (skill.targets 就是所选集合);会改变字节的按宿主 Skill frontmatter 扩展是 AB4103。

    谁来规划投影

    每个内置适配器都实现 TargetAdapter.plan(model),并返回一个 TargetArtifactPlan (adapters/types.ts):entries(write 或 copy)、可选的 hookEntries,以及 diagnostics。

    宿主规划器能力表
    ampadapters/amp.ts 中的 ampAdapter.planadapters/capabilities/amp-0.0.0-20260907001852-gf348fed.json
    claudeadapters/claude.ts 中的 planClaudeArtifactsadapters/capabilities/claude-2.1.260.json
    codexadapters/codex.ts 中的 planCodexArtifactsadapters/capabilities/codex-0.147.0.json
    cursoradapters/cursor.ts 中的 planCursorArtifactsadapters/capabilities/cursor-2026-08-28.json
    portableadapters/portable.ts 中的 portableAdapter.planadapters/capabilities/portable-1.0.0.json

    这些能力 JSON 文件是注册表与生成的宿主参考页面所读取的宿主 证据:观察到的版本、清单路径、安装表面、路径 token、MCP 传输方式与组件支持。适配器据此 查询宿主能表达什么;compose.ts 在判定 AB4105 时查询 registry.hostsComponent 与 registry.artifactLayout,在对整个所选集合求通知投递声明的交集时查询 registry.noticeDelivery。共享的 MCP 入口与每个宿主的钩子包装器都由该交集接线,因此它们 声明的是同一组路由。

    TargetRegistry(adapters/registry.ts)是注册适配器的唯一位置。createDefaultRegistry 先把 portable 注册为默认值,然后注册 codex、claude、cursor 与 amp。注册顺序不是 目标优先级:planComposite 在规划前先对所选集合排序(sortedProjections),复合身份就是 排序后的名称连接。不存在 plugin 适配器。

    amp 是唯一一个插件形态为生成目录、而非一组声明式文档的内置宿主。它的规划在 .amp/plugins/{plugin}/ 下写出一个 index.js PluginAPI 工厂,由该 API 注册 Skill 与事件 回调;其 MCP 配置是 Skill 作用域的:一个规范服务器需要恰好一个 Amp Skill,而由编译器拥有的 本地服务器会被拒绝,因为固定的契约没有记录可用于启动它的插件根 token。逐表面的证据仍在生成的 宿主参考页面;面向作者的选择地图是 目标与能力地图。

    compose 交给产物组装什么

    composeProjections(build/compose.ts)合并所选的计划:

    • 同一路径上字节相同的条目只保留一份。同一路径上字节不同则是 AB4103(投影按宿主名顺序 比较,路径按路径顺序比较)。
    • install/surface.ts 的 installSurfaceEntries 作为一个合成的所有者被合并进来(任何 内置宿主都有 INSTALL.md;选中 cursor 或 portable 时有 install.mjs)。
    • 钩子条目是拼接的;它们不按路径合并。到达多个所选宿主的钩子会为每个宿主编译一个包装器 (hooks/<name>.<host>.mjs);只到达单个宿主的钩子保留 hooks/<name>.mjs (hookWrapperPath)。
    • Codex 与 Cursor 的钩子/MCP 文档与各自的清单并列(.codex-plugin/hooks.json、 .cursor-plugin/mcp.json……)。当另一个所选宿主有到达约定 hooks/hooks.json / .mcp.json / mcp.json 路径的钩子或 MCP 服务器时,这些投影会发出一份空的屏蔽文档, 使目录发现无法加载该文件。

    构建阶段拿到的 CompositePlan 携带 entries、hookEntries、selected、identity、 projections(每个所选宿主一份已规划的投影)、cliBin(当任一所选宿主接纳路由式 CLI 时为 true)以及 noticeDelivery。AB4106 更早在模型上判定,位于 config/validate.ts:把高级注册表上的适配器与任何其他 target 混在一起的选择不能共享 一个根目录。

    编译后的 MCP 入口、脚本、路由式 CLI bin 与 MCP App 不会按宿主重新规划。 build/build.ts 以 target: composite.identity 把它们编译一次,并写到根目录。

    产物层

    产物组装消费 CompositePlan 与已编译的表面,并在 artifactRoot 写出一棵目录树(CLI 默认为 artifact/;output.distPath 或 --output 可以移动它)。

    写入器

    写入器模块写出什么
    计划条目build/emit.ts 的 emitPlanEntries宿主文档、Skill、命令、规则、资源、INSTALL.md / install.mjs
    脚本、钩子、MCP 入口、CLI binbuild/rslib.ts 的 compileRslibSurfaces,经由 build/entries.ts、build/cli-bins.tsscripts/*.mjs、hooks/*.mjs、mcp/mcp-<server>-<hash>.mjs、bin/<plugin>.mjs(外加 -flight.mjs worker)
    MCP Appbuild/mcp-apps.ts 的 compileMcpAppsmcp-apps/<name>.html(同时内联进生成的服务器)
    编译证据build/compile-evidence.ts 的 createCompileEvidenceRecordagent-bundle.compile-evidence.json(每个已编译文件一条 assets[])
    清单build/build.ts 的 manifestFor + build/emit.ts 的 writeManifestagent-bundle.manifest.json
    发布build/emit.ts 的 publishArtifact把暂存目录原子重命名到 outputRoot

    build/compile-stages.ts 安排工作顺序:先是 MCP App(MCP 入口会嵌入它们的 HTML),然后是 node 表面。

    校验器

    检查模块代码
    规范清单解析 + 文件摘要匹配build/validate-artifact.tsAB60xx 系列;解析错误由 parseArtifactManifest 抛出
    宿主包、包构建 dist 与 MCP App 视图的编译只保留获准的 externalbuild/compiler.ts、build/external-policy.tsAB6005
    编译证据记录对照清单 bundle 文件build/compile-evidence.ts 的 compileEvidenceDiagnosticsAB6039
    编译器看不见的已输出模块:任何位置的表达式 import()、编译产物中构建被要求忽略的字面量导入(rspackIgnore/webpackIgnore),以及框架未编译或 tools 逃生舱可能改写的 JavaScript 的导入与语法build/validate-artifact-modules.tsAB6005(残余形态)
    Skill / 钩子 / MCP 文档与所选宿主匹配build/validate-artifact-skills.ts、build/validate-artifact-hooks.ts(executables.hooks[],AB6018)、build/validate-artifact-mcp.ts按表面划分的 AB60xx
    产物对输出根目录的所有权build/validate-artifact.tsAB6014
    打包的 tarball 包含清单中的每个文件,且没有未使用的安装依赖build/pack-inventory.tsAB7010、AB7014、AB7015

    AB6005 读取每次宿主包、包构建 dist 与 MCP App 视图编译的证据。Rspack 保持的每个 ExternalModule 都必须是 Node 内建模块、pnpapi 或已输出的同级文件;其他 external 都会失败。 这就是 build/compiler.ts 与 build/external-policy.ts 强制的自包含规则;生成式插件编译器配置 同样实施该规则(build/rslib.ts 的 composeEntryLibConfig:autoExternal: false、 bundle: true、没有面向作者的 externals)。

    AB7014 / AB7015 是 prepack 门禁:package.json 中的安装期依赖必须出现在打包后的 预构建 runtimeDependencies、打包后声明文件引用或消费者安装脚本中 (AB7014),并且消费者的 npm 必须能够抓取它(AB7015)。内联进 bundle 的包不算已使用; 编译证据会记录诊断中点名的 dist bundle。

    复合根目录

    以 targets: ['amp', 'claude', 'codex', 'cursor', 'portable'] 构建时,host-test 示例的根目录为:

    artifact/
    ├── .amp/plugins/<name>/{index.js,skills/,hooks/}
    ├── .agents/plugins/marketplace.json
    ├── .claude-plugin/{plugin.json,marketplace.json}
    ├── .codex-plugin/{plugin.json,hooks.json,mcp.json}
    ├── .cursor-plugin/{plugin.json,marketplace.json,hooks.json,mcp.json}
    ├── .mcp.json
    ├── plugin.json, mcp.json
    ├── hooks/hooks.json
    ├── hooks/<hook>.mjs
    ├── hooks/<hook>.{claude,codex,cursor}.mjs
    ├── hooks/hooks-flight.mjs
    ├── mcp/mcp-<server>-<hash>.mjs (+ -flight)
    ├── bin/<plugin>.mjs, bin/<plugin>-flight.mjs
    ├── skills/, scripts/, commands/, rules/, assets/, mcp-apps/
    ├── INSTALL.md, install.mjs
    ├── agent-bundle.manifest.json
    └── agent-bundle.compile-evidence.json

    Target 与产物是输出契约:哪个宿主读取哪份文档、 钩子包装器的命名规则,以及 AB4103 / AB4105 / AB4106。本页不重复那张表。

    执行内核与 Agent Document

    上面的编译器流水线止于磁盘上的文件。请求时是另一套独立的栈。已经存在的请求内核是 runAgentRequest(packages/rsc-runtime/src/agent-request.ts,以 @agent-bundle/runtime 导入)。生成式 MCP 路由、事件路由与渲染式 CLI 命令会调用它。 配置声明的钩子绕过它:生成的包装器解码宿主信封并直接调用作者的函数,没有 provider、布局或 Agent Document。原生钩子文档是适配器校验并合并的宿主 JSON;它们不是 编译出来的包装器,也不进入内核。

    表面入口请求路径
    生成式 MCP stdiomcp-entry.ts(仅生命周期:stdout 守卫、信号、关闭),然后是来自 build/entry-shell.ts 的生成入口mcp-server-runtime.ts 注册路由、运行 runAgentRequest、通过预热的 Flight worker 渲染,并用 attachMcpStructuredContent 对 tool 结果做降级
    事件路由同一个生成的 MCP 服务器(events/ipc.ts 中的 createEventRuntimeServer)events/project.ts 把宿主信封规范化,并经 runAgentRequest 投影文档(projectEventDocument)
    配置声明的钩子由 adapters/hook-contract.ts 生成的 hooks/<name>.mjs包装器中的宿主原生编解码器;不调用 runAgentRequest
    原生钩子文档适配器声明的宿主 JSON(nativeHooks)校验后合并进宿主钩子文档;没有包装器,也不进内核
    路由式 CLIcli-entry.ts 的 runGeneratedCliEntry来自路由图的命令树;渲染式 .tsx 命令使用 runAgentRequest。CLI 文档类型位于 cli-entry.ts,并不导入 @agent-bundle/runtime
    浏览器 App宿主 ui/* 桥接(Workbench 的 McpAppFrameRelay、serve-app 的 HOST_SCRIPT)App 是工具结果之上的一个视图,而不是第二张路由图

    mcp-entry.ts 是 stdio 进程外壳。它不构造请求上下文。构造请求上下文的是 mcp-server-runtime.ts:身份、lineage、provider、runAgentRequest、布局(针对文档路由) 以及 MCP 投影。

    Agent Document 是渲染式路由的规范响应。其类型位于 packages/rsc-runtime/src/agent-document.ts,以 @agent-bundle/runtime 导入:

    • version(当前为 1)
    • status:success | represented-error | failed
    • root:由 Agent.* 节点组成的树(result、text、markdown、context、json、 progress、image、audio、resource、error)
    • 可选的 value(可 JSON 序列化的结构化结果)

    MCP 的 tool 路由把这份文档降级为 CallToolResult 内容加 structuredContent。resource 与 prompt 路由则返回经校验的协议结果(来自 document.value)。CLI 的人类可读/JSON 模式 通过 CLI 输出契约渲染同一份文档。Workbench 通过 packages/workbench/src/runtime/agent-document-client.ts 检视它。原始的 CallToolResult 是互操作边界,而不是编写模型。

    上下文值是 Observed<T>(@agent-bundle/runtime):state 为 available (带有 source:native | receipt | derived)或 unavailable(带有 reason)。内核不会凭空发明宿主未提供的宿主或会话身份。

    agent-bundle.manifest.json 的现状

    写入器是 build/build.ts 的 manifestFor。它组装出一个 ArtifactManifest (build/manifest.ts;TypeDoc: ArtifactManifest), 来源是 manifestProjections、manifestBins / manifestHooks / manifestMcpServers / manifestScripts、manifestDistribution,以及 build/manifest-routes.ts 的 artifactRoutesFor。writeManifest 再用 assembleArtifactManifest 将其序列化:规范的 stableJson 加一个末尾换行。 parseArtifactManifest 拒绝任何其他字节序列、重复键、未知键、缺失键、未排序 的数组,以及指向清单自身的文件条目。manifestVersion 为 5。公开读取方是 build/manifest-file.ts 的 readArtifactManifest:ok、missing(仅 ENOENT)或 invalid。

    该 schema 在 TypeScript 中封闭(build/manifest.ts 中的 requireExactKeys)并且作为 JSON Schema 随包发布 (packages/agent-bundle/schemas/agent-bundle.manifest.schema.json), 由 build/manifest-schema.ts 经 api.ts / index.ts 导出为 artifactManifestSchema 与 validateArtifactManifestSchema。解析器仍是 更严格的权威:它还检查交叉引用、规范字节与排序。adapters/schemas/** 下的宿主 plugin.json / hooks.json / mcp.json schema 与 schemas/** 下的 Agent Skills frontmatter 是另一份契约;网站的 宿主参考 / 事件参考页面由 adapters/capabilities/*.json 与 docs/diagnostics.md 生成,而不是由 这份清单生成。

    每个分节与字段见 产物清单。本页只保留大纲。

    写入器发出的分节

    文档分为两部分,各有自己的版本号。公开契约(manifestVersion: 6) 是消费者读取的部分。编译器记录(compiler,recordVersion: 1)是 这次运行的操作性账目,生产者、项目摘要、来源、适配器修订、固定的 schema、验证结果,它的变化不会推动 manifestVersion;消费者读取方 永远不需要它。

    分节记录什么
    manifestVersion5
    application与宿主无关的身份:id、name、version,可选的 description
    files[]除清单自身外的每个发出文件(path、bytes、sha256、kind,可选的 mode)
    runtime来自 NormalizedPlugin.runtime 的 { node }
    projections[]每个所选宿主一行。host 是所选名称;builtInHost 是随包适配器身份(高级注册表适配器则缺省);documents(plugin?、marketplace?、mcp?、hooks?、entry?)指向派生出的宿主文档;以及可选的 marketplace.name。由 targets[] 更名而来。
    routes编译后的路由图:servers[]、events[]、scripts[]、cli?、providers[]、layouts[]、contracts[]、digest
    executables根目录能启动的进程:bins[]、hooks[](kind 为 config | event-route)、mcpServers[](entry、apps[])、scripts[]
    distributionchannels(始终有 local;已打包时有 npm)以及可选的 install 指针
    compilerrecordVersion: 1;producer({ name: 'agent-bundle', version });project(configPath、configDigest、modelDigest、revision、sourceInputs[],可选的 packageName / packageVersion);provenance[](每个 files[] 行一条 { path, sourceInputs[] });adapters[](每个投影一条 { host, adapterRevision, observedVersion, schemas[] });agentSkills(specification、sourceRevision、schemaSha256);validation({ source, artifact, projections[] },每个 status 都是 'passed')

    谁读取各个字段

    生产环境的读取方调用 readArtifactManifest 或 parseArtifactManifest。 测试不在此列,已安装宿主的证明套件除外。

    读取方使用的字段用途
    build/validate-artifact.ts全部重新解析磁盘上的字节,匹配 files[] 的摘要与 mode,对照注册表检查 projections[] 与 compiler.adapters[](适配器修订、观测版本与 builtInHost 身份,AB6010),固定 compiler.agentSkills 与 runtime.node。没有单独的一致性检查:宿主文档与清单在同一次构建中由同一份编译计划写出,且每个文档都是带摘要的 files[] 行
    build/compiler.ts、build/external-policy.ts宿主包、包构建 dist 与 MCP App 视图的 CompileResult.externalsAB6005 编译证据自包含检查
    build/compile-evidence.tsfiles[](bundle 行)AB6039:把持久化的编译证据记录对照文件表复核,且不解析 JavaScript
    build/validate-artifact-modules.tsfiles[](.js/.mjs 行)加包构建 dist;编译证据记录证明的 bundle 行只做词法分析,其字面量导入对照记录在案的外部依赖核对AB6005 残余遍历:表达式 import()、被忽略(rspackIgnore)的字面量导入、未编译或被逃生舱改写的模块
    build/validate-artifact-skills.tsprojections[](manifestTargets)加目录树Skill 文档对照所选宿主
    build/validate-artifact-hooks.tsexecutables.hooks[]、projections[]AB6018:钩子行对照宿主钩子文档
    build/validate-artifact-mcp.tsprojections[]、MCP 文件MCP 文档对照所选宿主
    build/pack-inventory.tsfiles[]、projections[]、application.version、compiler.project.packageVersion打包的 tarball 必须包含清单中的每个文件(AB7010);摘要漂移;发布版本对齐;AB7014 / AB7015
    eval/artifact.tsfiles[]、projections[]、runtimeevalTargetDigests:对整张文件表为每个 projections[].host 计算一个摘要(相同字节,不同身份)
    dev/artifacts/artifact-inspection-service.tsfiles[]、compiler.project、compiler.provenance[]、application、distribution、projections[]、routes、executablesWorkbench 产物检视器:从 files[] 重建一棵树,按投影各标注一次;应用树经由 dev/artifacts/application-explorer.ts(ArtifactInspection.application),一个薄投影,而不是清单的原始形状
    dev/artifacts/artifact-executables.tsexecutables.scripts[]按宿主划分的脚本行(取代 artifact-script-catalog.ts)
    services/hook-service.tsexecutables.hooks[]hooks list / simulate
    dev/playground/hook-playground-service.tsexecutables.hooks[](经由 hook-service)Workbench 钩子演练场
    install/identity.ts 的 readBundleIdentityapplication、projections[]install、uninstall 与 doctor:身份来自 application;投影按 builtInHost === host 选取(不是所选的 host 名);插件文档来自必须存在的 documents.plugin;市场名称来自 marketplace.name(claude / codex)。缺任一则是 AB7001。从不探测 <from>/<host>。
    serve-app、mcp list / invoke / runexecutables.mcpServers[]、projections[]build/manifest-projection.ts 解析服务器;当只有一个具备 MCP 能力的投影托管该服务器时,--target 可省略
    inspect --jsonoutput.manifestinspectManifestOutput:已构建清单存在时给出投影与可执行文件摘要
    test/installed.tsprojections[]、executables.hooks[]已安装宿主的证明按 builtInHost 选取随包适配器
    index.ts重新导出这些类型、parse / serialize / assemble / read 以及 schema公开 API

    不存在 portable 的 install / doctor 宿主 (BundleIdentityHost 是 amp | claude | codex | cursor)。 doctor 覆盖 claude、codex 与 cursor;Amp 没有生命周期探测 (DoctorHost 将其排除)。

    第 3 步落地了什么

    #592 的第 3 步 让这个文件成为编译后的应用索引(manifestVersion 2)。原先差距列表中的 这些编号项现在都在清单里,只有 (5) 除外:

    1. 路由图。 routes 记录服务器、工具、资源、提示、App、CLI 命令、 事件路由、provider、布局、契约与 digest。
    2. MCP / CLI / App 清点。 executables.mcpServers[] 记录每台服务器 (entry、apps[]);executables.bins[] 记录路由式 CLI。
    3. 钩子语义。 executables.hooks[].kind 为 config 或 event-route。作者写进宿主钩子文档的原生命令不是行。 agent-bundle.hooks.json 已删除。
    4. Install / doctor 身份。 readBundleIdentity 读取 application 以及 builtInHost 匹配该宿主的投影。
    5. 能力视图。 有意不记录。通知投递交集在构建时由 build/compose.ts 的 compositeNoticeDelivery 推导;inspect 的 omittedFeatures 仍来自模型。把该交集写进清单是后续的 #592 工作。
    6. 作为一等行的可执行文件。 executables.bins[]、hooks[]、 mcpServers[] 与 scripts[]。
    7. 分发元数据。 distribution.channels 以及可选的 distribution.install。

    字段契约见 产物清单。

    代码今天在哪里分叉

    #592 点名了本页不得掩盖的那些分裂。这里只列路径,不给修复。

    发现不是一张图。 compileRouteGraph 覆盖可执行路由。Skill、命令、规则、配置钩子、 原生钩子与手写的 MCP 入口是 DiscoveredProject / NormalizedPlugin 上彼此平行的集合。 之后需要“每一个表面”的消费者仍要遍历多个字段。

    五个规划器,一次合并。 planClaudeArtifacts、planCodexArtifacts、 planCursorArtifacts、portableAdapter.plan 与 ampAdapter.plan 各自遍历整个模型并输出 宿主文档。 compose.ts 合并的是字节;它并没有用单个 project(application, capabilities) 函数取代 这些规划器。

    事件执行。 约定式 src/events/** 支持普通 .ts 处理器、渲染 .tsx 处理器和显式延迟加载的 .view.tsx 模块。宿主原生文档仍是适配器输入。Provider 通过请求上下文延迟解析。

    MCP 与 CLI。 同级 <tool>.cli.ts 投影工具,不创建第二个操作。 flag 元数据来自字面量 config.inputJsonSchema;编译后的可执行文件加载运行时 schema。 检查阶段不解释 schema 导入或别名链。

    浏览器桥接曾被分叉。 现在只有一个宿主侧中继,位于 web-host/browser/frame-relay.ts(McpAppFrameRelay),由 Workbench、serve-app、开发态 /web/<server>/<app> 与产物的 <plugin> web 页面共同挂载 (#564 已落地);App 使用 agent-bundle/app 的类型化客户端(#594 已落地)。

    与清单并存的文件系统探测。 install、uninstall 与 doctor 通过 install/identity.ts 的 readBundleIdentity 读取身份(application、 projections[].builtInHost、documents.plugin、市场名称)。它们不会探测 <from>/<host> 或宿主的 plugin.json 来寻找根目录。Eval 仍对整张文件表按 每个 projections[].host 各哈希一遍(evalTargetDigests),而不是记录一份 按投影划分的文件视图。Workbench 检视器从 files[] 重建一棵树,按 projections[] 各标注一次,并从 executables 读取可执行文件,而不是从路径 前缀推导。

    共享表面中残留的按 target 逻辑。 共享的 MCP / CLI / App 编译使用 composite.identity,但钩子包装器仍然固化一个 target。 dev/artifacts/artifact-executables.ts 把 executables.scripts[] 展开为 每个列出该脚本的宿主一行。artifact-inspection-service.ts 为每个 projections[] 宿主把同一棵树各标注一次。通知投递是所有所选宿主的交集 (compose.ts 的 compositeNoticeDelivery),应用到每一个共享的 MCP 入口上,并且不写进清单。

    能力选择保持窄范围。 事件路由可以声明 requires: ['events.toolBefore.deny'] 这样的能力行;编译器根据固定的能力表选择支持它的宿主。其他组件仍使用 targets;当事件路由的行为 确实依赖特定宿主时,targets 也仍是它的逃生口。

    路线图

    #592 是总纲。本页记录三层 (第 2 步)与 v2 清单(第 3 步)。它之下的实现切片各有自己的 issue:

    Issue切片
    #555复合插件根目录;targets 作为投影选择(Wave 1 已作为 PR #578 落地)
    #593把本地 schema 导入解析进同一份路由契约(已落地)
    #596一个操作,地道的 MCP + CLI 投影
    #595事件路由内核上的预检 / 惰性 provider
    #594生成的类型化 App 客户端 + 共享桥接
    #564基于同一桥接的生产 web 表面

    第 3 步以版本 2 落地了权威的 agent-bundle.manifest.json;后续的可执行、分发与路由契约字段 把当前契约推进到 manifestVersion 6。 字段契约见 产物清单。#592 会一直保持打开,直到该 issue 上剩余的验收标准落地。

    下一步