experience-cms-content-type-generate

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

experience-cms-content-type-generate

experience-cms-content-type-generate

What This Skill Does

本技能功能

  • DISCOVER — checks local
    <sfdx-source>/contentTypes/
    and queries
    metadata-grounding
    for existing OOTB/custom ContentTypeBundles.
  • RECONCILE — on existing pick/provided FQN, retrieves from org (custom only) and reconciles against local. Returns
    {fqn, schema}
    matching the org.
  • CREATE — generates a validator-correct ContentTypeBundle (
    schema.json
    ,
    .contentTypeBundle-meta.xml
    ).
  • VALIDATE
    sf project deploy start --dry-run
    against the CLI default (or picked) org.
  • AUTO-FIX — fixes schema issues, re-validates (max 3 attempts).
  • DEPLOY — asks yes/no, deploys on yes.
Create-only for new types, reconcile-only for existing. Does not modify, rename, or delete existing bundles beyond replacing a local copy with the org copy on user consent; does not author content records. If the message asks to add/rename/remove a field on an existing type (verbs
add
/
append
/
remove
/
drop
/
rename
/
change
/
modify
/
update
targeting an FQN or named type), print ONE line before 1a:
This skill is create-only for new types and reconcile-only for existing. To modify "<fqn|name>", edit its schema.json and redeploy, or use the CMS UI.
— then continue discovery so the user lands on the type's summary (7.5). Do NOT silently proceed as if the modification happened.
  • DISCOVER — 检查本地
    <sfdx-source>/contentTypes/
    目录,并通过
    metadata-grounding
    查询现有OOTB(开箱即用)/自定义ContentTypeBundle。
  • RECONCILE — 针对已选择/提供的FQN(完全限定名称),从组织中检索(仅自定义类型)并与本地版本协调,返回与组织匹配的
    {fqn, schema}
  • CREATE — 生成符合验证器要求的ContentTypeBundle(包含
    schema.json
    .contentTypeBundle-meta.xml
    文件)。
  • VALIDATE — 通过CLI默认(或指定)组织执行
    sf project deploy start --dry-run
    预部署验证。
  • AUTO-FIX — 修复架构问题,重新验证(最多3次尝试)。
  • DEPLOY — 询问用户是否部署,确认后执行部署。
仅针对新类型执行创建操作,针对现有类型仅执行协调操作。除了在用户同意的情况下用组织版本替换本地副本外,不修改、重命名或删除现有包;不创作内容记录。如果用户请求是对现有类型添加/重命名/删除字段(使用
add
/
append
/
remove
/
drop
/
rename
/
change
/
modify
/
update
等动词,目标为FQN或命名类型),在步骤1a前打印一行提示:
本技能仅用于创建新类型和协调现有类型。若要修改“<fqn|name>”,请编辑其schema.json并重新部署,或使用CMS UI。
— 之后继续执行发现流程,以便用户查看该类型的摘要(步骤7.5)。请勿静默执行修改操作。

Invocation contract

调用约定

Invoked directly by the user or delegated to by another skill (e.g.
experience-cms-content-generate
). Two halves: input params the caller supplies, and a return outcome emitted at every terminal state.
由用户直接调用,或由其他技能(如
experience-cms-content-generate
)委托调用。包含两部分:调用方提供的输入参数,以及每个终端状态输出的返回结果

Input params (all optional)

输入参数(均为可选)

ParamTypeEffect
fqn
string (
namespace__DeveloperName
)
Skip discovery entirely. Jump straight to step 1e (retrieve-and-reconcile) using this FQN.
intent
and the 1d pick prompt are bypassed. Use when the caller already knows exactly which type to resolve.
intent
stringThe user's original message. Drives discovery keywords in step 1c and the "matching …" wording in 1d. Default when the skill is triggered by a natural-language user prompt.
suppressCreateContentPrompt
boolean, default
false
Suppresses the trailing "Would you like to create content using this type now?" question at step 8. Callers that already drive their own content-creation flow MUST pass
true
. Direct user invocation leaves it
false
so the user gets the natural next-step offer.
spaceId
stringWorkspace scope for the step 1c workspace-content-types check (
get_content_types_for_workspace
). Pass when the caller already resolved a content space. Mutually exclusive with
baseType
— see below.
folderId
stringFolder scope for the same check, as an alternative to
spaceId
. Mutually exclusive with
baseType
— see below.
baseType
string, default
"CONTENT"
baseType
argument to
get_content_types_for_workspace
. Mutually exclusive with
spaceId
/
folderId
— see below.
Workspace scope resolution — mutual exclusivity contract.
spaceId
/
folderId
/
baseType
narrow step 1c's workspace-content-types check only, not the discovery path taken. A caller that passes
spaceId
or
folderId
MUST NOT also pass
baseType
— the scope alone already determines the eligible types; this skill does not accept both in the same call. Exactly one of four combinations applies each run — call shapes and rationale →
references/discovery-details.md#1c continued
:
  1. spaceId
    only →
    get_content_types_for_workspace({ spaceId })
    .
  2. folderId
    only →
    get_content_types_for_workspace({ folderId })
    .
  3. baseType
    only →
    get_content_types_for_workspace({ baseType })
    .
  4. None of the three →
    get_content_types_for_workspace({ baseType: "CONTENT" })
    (default).
Common invocation shapes:
  • Direct user
    intent
    ,
    suppressCreateContentPrompt
    false
    . Full discovery + retrieve-and-reconcile + trailing prompt. No
    spaceId
    /
    folderId
    /
    baseType
    — falls to combination 4 above.
  • Delegated
    { intent | fqn, suppressCreateContentPrompt: true }
    . Full discovery + retrieve-and-reconcile; returns
    {success, fqn, schema}
    (the retrieve is what confirms the type is deployed in the org — a local-only type resolves to
    not_deployed
    , never a bare success). Trailing prompt suppressed.
  • Delegated with a known workspace
    { intent, suppressCreateContentPrompt: true, spaceId: "<contentSpaceOrFolderId>" }
    — combination 1. Pass this once the caller has already resolved a workspace (e.g.
    contentSpaceOrFolderId
    from
    get_or_create_cms_workspace_and_web_app_channel
    ) and wants step 1c's check scoped to it. Do NOT also pass
    baseType
    on this call. If the caller resolves its workspace AFTER content-type discovery (as
    experience-cms-content-generate
    currently does), it has no
    spaceId
    to pass at delegation time — that's combination 4, a valid, expected call shape.
参数类型作用
fqn
字符串(格式为
namespace__DeveloperName
跳过发现流程,直接使用该FQN进入步骤1e(检索并协调)。绕过
intent
和步骤1d的选择提示。适用于调用方已明确知晓要解析的类型的场景。
intent
字符串用户的原始请求消息。驱动步骤1c中的发现关键词,以及步骤1d中的“匹配……”表述。当技能由自然语言用户提示触发时使用默认值。
suppressCreateContentPrompt
布尔值,默认
false
抑制步骤8末尾的“是否要立即使用此类型创建内容?”提示。已自行驱动内容创建流程的调用方必须传入
true
。用户直接调用时保持
false
,以便为用户提供自然的后续操作选项。
spaceId
字符串步骤1c中工作区内容类型检查(
get_content_types_for_workspace
)的工作区范围。当调用方已解析内容空间时传入。
baseType
互斥
— 见下文说明。
folderId
字符串作为
spaceId
的替代,用于步骤1c中相同检查的文件夹范围。
baseType
互斥
— 见下文说明。
baseType
字符串,默认
"CONTENT"
get_content_types_for_workspace
baseType
参数。
spaceId
/
folderId
互斥
— 见下文说明。
工作区范围解析 — 互斥约定
spaceId
/
folderId
/
baseType
仅缩小步骤1c中工作区内容类型检查的范围,不影响发现路径。传入
spaceId
folderId
的调用方不得同时传入
baseType
— 仅范围本身即可确定符合条件的类型;本技能不接受同一调用中同时传入两者。每次运行仅适用以下四种组合之一,调用形式及原理详见
references/discovery-details.md#1c continued
  1. 仅传入
    spaceId
    → 执行
    get_content_types_for_workspace({ spaceId })
  2. 仅传入
    folderId
    → 执行
    get_content_types_for_workspace({ folderId })
  3. 仅传入
    baseType
    → 执行
    get_content_types_for_workspace({ baseType })
  4. 未传入三者中的任何一个 → 执行
    get_content_types_for_workspace({ baseType: "CONTENT" })
    (默认行为)。
常见调用形式:
  • 用户直接调用 → 传入
    intent
    suppressCreateContentPrompt
    设为
    false
    。执行完整发现流程+检索协调+末尾提示。不传入
    spaceId
    /
    folderId
    /
    baseType
    → 适用上述组合4。
  • 委托调用 → 传入
    { intent | fqn, suppressCreateContentPrompt: true }
    。执行完整发现流程+检索协调;返回
    {success, fqn, schema}
    (检索操作用于确认类型已部署到组织中 — 仅本地存在的类型会解析为
    not_deployed
    ,不会直接返回成功)。抑制末尾提示。
  • 已知工作区的委托调用 → 传入
    { intent, suppressCreateContentPrompt: true, spaceId: "<contentSpaceOrFolderId>" }
    — 适用组合1。当调用方已解析工作区(如从
    get_or_create_cms_workspace_and_web_app_channel
    获取
    contentSpaceOrFolderId
    ),且希望步骤1c的检查限定在该工作区时使用此调用。请勿同时传入
    baseType
    。如果调用方在内容类型发现后才解析工作区(如当前
    experience-cms-content-generate
    的逻辑),则委托时无法传入
    spaceId
    — 适用组合4,这是合法且预期的调用形式。

Return outcome

返回结果

Every terminal state emits a structured outcome. The
message
field is printed to chat as the final one-line summary AND is what the caller reads to route on the result.
status
fqn
schema
MeaningCaller action
success
presentpresentType is confirmed in the org (via 1e's retrieve on an existing type, or via deploy on the "Create new" path), ready to use for downstream work.Proceed (e.g. author content records).
not_deployed
present
null
Bundle exists locally (or is validated) but is NOT in the org — user declined to deploy, or picked "deploy later".Do NOT proceed with content creation. Surface the message: "Content type
<fqn>
isn't deployed to
<org>
. Deploy it and re-run."
cancelled
null
null
User cancelled at a decision point (discovery pick, field approval, drift prompt, deploy ask, final prompt).Exit silently. Do not loop back into this skill.
error
null
null
Unrecoverable failure — missing
sfdx-project.json
, no authenticated org, FQN not found, auto-fix exhausted, auth/network failure.
Surface the
message
to the user and exit.
Terminal chat-line templates — one per status, printed final and mirrored into the outcome:
  • success
    Content type "<fqn>" is ready in <org>.
    (post-deploy:
    Deployed "<fqn>" to <org>. Component IDs: <ids>.
    )
  • not_deployed
    Content type "<fqn>" exists locally but is not deployed to <org>. Deploy it before creating content.
    (or 7b's "deploy later" one-liner)
  • cancelled
    Cancelled. No files written.
  • error
    <specific reason>. <recovery hint>.
    (e.g.
    No authenticated Salesforce org. Run sf org login web and re-run.
    )
Contract rules:
  • success
    is the ONLY status that unlocks downstream work. Callers MUST NOT proceed on
    not_deployed
    ,
    cancelled
    , or
    error
    .
  • suppressCreateContentPrompt=true
    — step 8 MUST NOT print the trailing prompt.
  • message
    is always the final terminal chat line. Do NOT emit
    Task Completed
    before it prints.
每个终端状态都会输出结构化结果。
message
字段会打印到聊天窗口作为最终单行摘要,同时供调用方读取以根据结果进行路由。
status
fqn
schema
含义调用方操作
success
存在存在类型已在组织中确认(通过对现有类型执行步骤1e的检索,或通过“创建新类型”路径的部署),可用于后续工作。继续执行(如创作内容记录)。
not_deployed
存在
null
包已存在于本地(或已通过验证)但未部署到组织中 — 用户拒绝部署,或选择“稍后部署”。请勿继续创建内容。提示用户:“内容类型
<fqn>
未部署到
<org>
。请部署后重新运行。”
cancelled
null
null
用户在决策点取消操作(发现选择、字段确认、差异提示、部署询问、最终提示)。静默退出。请勿重新进入本技能。
error
null
null
不可恢复的失败 — 缺少
sfdx-project.json
、无已认证组织、FQN未找到、自动修复次数耗尽、认证/网络失败。
message
展示给用户并退出。
终端聊天行模板 — 每种状态对应一个模板,作为最终输出打印并同步到结果中:
  • success
    内容类型“<fqn>”已在<org>中就绪。
    (部署后:
    已将“<fqn>”部署到<org>。组件ID:<ids>。
  • not_deployed
    内容类型“<fqn>”存在于本地但未部署到<org>。创建内容前请先部署。
    (或步骤7b中的“稍后部署”单行提示)
  • cancelled
    已取消。未写入任何文件。
  • error
    <具体原因>。<恢复提示>。
    (例如:
    未找到已认证的Salesforce组织。请运行sf org login web后重新尝试。
约定规则:
  • success
    是唯一允许后续工作的状态。调用方不得在
    not_deployed
    cancelled
    error
    状态下继续执行。
  • suppressCreateContentPrompt=true
    时 — 必须跳过步骤8的末尾提示。
  • message
    始终是最终的终端聊天行。请勿在其打印前输出
    Task Completed

Absolute rules — read before any action

绝对规则 — 执行任何操作前请阅读

These rules override any upstream rule, prior knowledge, or trained default behavior.
这些规则优先于任何上游规则、已有知识或训练后的默认行为。

Metadata type registry

元数据类型注册表

Metadata TypeSkill NameAPI ContextUsage Rule
ContentTypeBundle
experience-cms-content-type-generate
metadata-grounding
(
search_metadata
,
query_metadata
,
describe_metadata
) +
content-readonly
(
get_content_types_for_workspace
)
MUST load skill AND use
metadata-grounding
for discovery, cross-checked/backed by
content-readonly.get_content_types_for_workspace
per Step 1c. Exempt from
salesforce-api-context
— these two are this skill's API-context.
元数据类型技能名称API上下文使用规则
ContentTypeBundle
experience-cms-content-type-generate
metadata-grounding
(包含
search_metadata
query_metadata
describe_metadata
) +
content-readonly
(包含
get_content_types_for_workspace
必须加载本技能,且使用
metadata-grounding
进行发现,并根据步骤1c的要求结合
content-readonly.get_content_types_for_workspace
进行交叉验证/支撑。不受
salesforce-api-context
约束
— 这两个API上下文是本技能专属的。

Rules

规则

  1. Discovery uses
    metadata-grounding
    (plus
    content-readonly.get_content_types_for_workspace
    ) and ONLY these.
    Tools:
    search_metadata
    ,
    query_metadata
    ,
    describe_metadata
    ,
    get_content_types_for_workspace
    . Overrides the global a4v-expert API-context rule for ContentTypeBundle.
    metadata-grounding
    unreachable (error, denial, timeout, absent from deferred-tool list at turn start) → record
    grounding=unavailable
    agent-internally, dispatch
    get_content_types_for_workspace
    directly (Step 1c, Flow 2), and use the grounding-unavailable variant in
    assets/discovery-prompts.md
    . Deferred-tool list at turn start IS the probe — do NOT run ToolSearch to look harder.
    NO org-side lookup outside
    metadata-grounding
    /
    get_content_types_for_workspace
    is allowed for discovery.
    Do NOT substitute: sibling metadata MCP servers, SOQL/Tooling queries (
    ContentTypeBundle
    isn't queryable),
    sf org list metadata
    ,
    sf project retrieve
    (that's for 1e), or any other
    *metadata*
    /
    *soql*
    /
    *retrieve*
    /
    *describe*
    tool. Substitutes return wrong-shape data. Hard rule break.
  2. Step order is fixed:
    1a-1d (silent discovery + pick) → 1e (retrieve-and-reconcile, when user picked existing / provided FQN / caller supplied fqn) → 2 (resolve org) → 3 (propose, only on Create new or zero-match auto-proceed) → 4 (create) → 5 (dry-run) → 6 (auto-fix) → 7 (deploy ask) → 7.5 (schema summary) → 8 (trailing prompt)
    . Step 1e returns
    {fqn, schema}
    and skips to 7.5; 2–7 do NOT run on that path. 7.5 runs whenever
    {fqn, schema}
    was resolved. Step 8 is gated by
    suppressCreateContentPrompt
    . Under direct invocation with zero matches, 1d auto-proceeds to 2 → 3.
  3. Steps 5 and 7 are mandatory on every "Create new" path. Pre-step-5 exits: (a)
    Use existing
    /
    Provide an FQN
    / caller-supplied
    fqn
    → route through 1e which returns
    {fqn, schema}
    with no files written; (b)
    Cancel
    at any pick. Do NOT emit
    Task Completed
    between steps 4 and 7's resolution. 1e's drift "Deploy local to org" branch also routes through 5 and 7.
  4. Task Completed
    is the LAST action
    — skill is over once emitted. Deploy JSON's
    deployUrl
    is for reference, not an action prompt. Forbidden after:
    open <deployUrl>
    ,
    xdg-open
    ,
    sf org open
    ,
    sf project deploy report
    , browser tabs, URL echo, "next step" prose.
  5. Step 1e retrieve is destructive for
    schema.json
    ; drift MUST prompt the user.
    sf project retrieve start --metadata ContentTypeBundle:<Name>
    overwrites local
    schema.json
    . Snapshot it into
    localSchemaBefore
    BEFORE every 1e retrieve (never meta.xml). Drift = parsed-JSON compare of
    localSchemaBefore
    vs. post-retrieve
    schema.json
    , left side ALWAYS
    localSchemaBefore
    — never diff the post-retrieve file against itself. On drift, the drift prompt is MANDATORY (chat diff, then
    ask_user_tool
    :
    Deploy local to org
    /
    Overwrite local with org
    /
    Cancel
    ) — never reconcile silently.
    Cancel
    and
    Deploy local to org
    MUST restore
    schema.json
    from
    localSchemaBefore
    before emitting the outcome. Full snapshot/restore procedure + drift prompt template →
    references/retrieve-and-reconcile.md
    .
  6. Step 1d — show top 5 in a table, then ask. Row count =
    min(combined.length, 5)
    , always — combined is local matches + every grounding row, deduped (Location
    local, org
    ), never dropped as "irrelevant." Row-1 sort: OOTB first (
    sfdc_cms__*
    or grounding
    isOOTB
    ), custom (
    c__*
    ) follows in grounding rank. Row 1's FQN names the
    Use existing:
    option. 1+ rows → table (
    FQN | Description | Location
    ) then
    ask_user_tool
    :
    Use existing: <row-1 FQN>
    /
    Provide an FQN
    /
    Create new: <newName>
    /
    Cancel
    (
    <newName>
    avoids colliding with any FQN in
    combined
    ). Empty combined → NO TABLE, just
    ask_user_tool
    :
    Create new: <contentTypeName>
    /
    Cancel
    (+
    Provide an FQN
    when delegated/
    fqn
    -supplied). Never mix "no matches" wording with a table; no preamble; no
    #
    /
    Name
    /
    Label
    columns; never claim a type is "not in the org" — only 1e's retrieve is authoritative. Full prompt templates →
    assets/discovery-prompts.md
    .
Full agent checklist and tripwire list →
references/agent-checklist.md
.
  1. 发现流程仅使用
    metadata-grounding
    (结合
    content-readonly.get_content_types_for_workspace
    。工具包括:
    search_metadata
    query_metadata
    describe_metadata
    get_content_types_for_workspace
    。覆盖ContentTypeBundle的全局a4v-expert API上下文规则。若
    metadata-grounding
    不可用(错误、拒绝、超时、回合开始时不在延迟工具列表中)→ 在代理内部记录
    grounding=unavailable
    ,直接调度
    get_content_types_for_workspace
    (步骤1c,流程2),并使用
    assets/discovery-prompts.md
    中的grounding不可用变体提示。回合开始时的延迟工具列表即为探测依据 — 请勿运行ToolSearch进一步查找。
    发现流程中禁止使用
    metadata-grounding
    /
    get_content_types_for_workspace
    以外的组织端查找方式
    。请勿替代为:同级元数据MCP服务器、SOQL/Tooling查询(
    ContentTypeBundle
    不可查询)、
    sf org list metadata
    sf project retrieve
    (这用于步骤1e)或任何其他
    *metadata*
    /
    *soql*
    /
    *retrieve*
    /
    *describe*
    工具。替代工具会返回格式错误的数据,属于严重违规。
  2. 步骤顺序固定
    1a-1d(静默发现+选择)→ 1e(检索并协调,当用户选择现有类型/提供FQN/调用方传入fqn时)→ 2(解析组织)→ 3(提议,仅在创建新类型或无匹配自动继续时执行)→ 4(创建文件)→ 5(预部署验证)→ 6(自动修复)→ 7(部署询问)→ 7.5(架构摘要)→ 8(末尾提示)
    。步骤1e返回
    {fqn, schema}
    并跳转到7.5;该路径下不执行步骤2–7。只要
    {fqn, schema}
    已解析,就会执行步骤7.5。步骤8受
    suppressCreateContentPrompt
    控制。用户直接调用且无匹配结果时,步骤1d会自动进入步骤2→3。
  3. 步骤5和7在所有“创建新类型”路径中为必填项。步骤5前退出的情况:(a)
    使用现有类型
    /
    提供FQN
    /调用方传入
    fqn
    → 路由到步骤1e,返回
    {fqn, schema}
    且不写入任何文件;(b) 在任何选择环节
    取消
    。请勿在步骤4和步骤7的决议之间输出
    Task Completed
    。步骤1e的差异提示“将本地版本部署到组织”分支也会路由到步骤5和7。
  4. Task Completed
    是最后一个操作
    — 输出后技能执行完毕。部署JSON中的
    deployUrl
    仅作参考,不是操作提示。禁止在以下操作后输出:
    open <deployUrl>
    xdg-open
    sf org open
    sf project deploy report
    、打开浏览器标签页、输出URL、“下一步”说明文字。
  5. 步骤1e的检索操作会覆盖
    schema.json
    ;存在差异时必须提示用户
    sf project retrieve start --metadata ContentTypeBundle:<Name>
    会覆盖本地
    schema.json
    。每次执行步骤1e检索前,必须将本地版本快照到
    localSchemaBefore
    (仅快照schema.json,不包括meta.xml)。差异 = 将
    localSchemaBefore
    与检索后的
    schema.json
    进行JSON解析后比较,始终以
    localSchemaBefore
    为左侧基准 — 请勿将检索后的文件与自身进行比较。存在差异时,必须显示差异提示(聊天窗口展示差异,然后通过
    ask_user_tool
    提供选项:
    将本地版本部署到组织
    /
    用组织版本覆盖本地
    /
    取消
    )— 请勿静默协调。
    取消
    将本地版本部署到组织
    选项必须在输出结果前从
    localSchemaBefore
    恢复
    schema.json
    。完整的快照/恢复流程及差异提示模板详见
    references/retrieve-and-reconcile.md
  6. 步骤1d — 展示前5个匹配结果的表格,然后询问用户。行数 =
    min(combined.length, 5)
    ,始终如此 — combined是本地匹配结果+所有grounding结果,去重后(位置标注
    local, org
    ),绝不丢弃“不相关”结果。排序规则:首先是OOTB类型(
    sfdc_cms__*
    或grounding中的
    isOOTB
    为true),然后是自定义类型(
    c__*
    )按grounding排名排序。第一行的FQN对应
    使用现有类型:
    选项。若有1个及以上结果 → 展示表格(
    FQN | 描述 | 位置
    ),然后通过
    ask_user_tool
    提供选项:
    使用现有类型: <第一行FQN>
    /
    提供FQN
    /
    创建新类型: <newName>
    /
    取消
    <newName>
    避免与
    combined
    中的任何FQN冲突)。若combined为空 → 不展示表格,仅通过
    ask_user_tool
    提供选项:
    创建新类型: <contentTypeName>
    /
    取消
    (当委托调用/传入
    fqn
    时,额外添加
    提供FQN
    选项)。请勿将“无匹配”表述与表格混合;无需前置说明;不要添加
    #
    /
    名称
    /
    标签
    列;绝不声称某个类型“不在组织中” — 只有步骤1e的检索结果才是权威的。完整提示模板详见
    assets/discovery-prompts.md
完整代理检查清单和触发条件列表详见
references/agent-checklist.md

File paths (strict)

文件路径(严格要求)

  • Bundle directory:
    <sfdx-source>/contentTypes/<ContentTypeName>/
    — NOT
    contentTypeBundles/<ContentTypeName>/
    .
  • Two files only:
    schema.json
    and
    <ContentTypeName>.contentTypeBundle-meta.xml
    .
  • 包目录:
    <sfdx-source>/contentTypes/<ContentTypeName>/
    — 禁止使用
    contentTypeBundles/<ContentTypeName>/
  • 仅包含两个文件:
    schema.json
    <ContentTypeName>.contentTypeBundle-meta.xml

Output discipline

输出规范

The user reads the chat. Most of this skill's machinery is for you, not them.
Do not print: status lines, task-progress checklists, planning prose (
I will now…
,
Per the skill's…
), anti-pattern reasoning, exemption explanations, "operation was denied; proceeded using…" notes, or suggestions that the user run validation/deploy themselves.
Do print, and only these: the 1d discovery summary, 1e drift prompt, 3b proposed-fields table +
ask_user_tool
, 2-line "files created" confirmation in step 4, 1-line validation result in step 5, 7a deploy ask, 7b/7e 1-line summary, 7.5 schema summary table (whenever
{fqn, schema}
resolved), and step 8 prompt (when
suppressCreateContentPrompt
is
false
/unset).
Do NOT emit
Task Completed
, "Done", "All set"
until step 7 has resolved, 7.5's summary has printed, and step 8's gate has been evaluated. Premature completion silently kills the summary + deploy ask.
用户会阅读聊天窗口内容。本技能的大部分内部逻辑仅用于代理自身,无需展示给用户。
禁止打印:状态行、任务进度清单、规划性文字(
我现在将……
根据技能的……
)、反模式推理、豁免说明、“操作被拒绝;已使用……继续”注释,或建议用户自行运行验证/部署命令的内容。
允许打印,且仅打印以下内容:步骤1d的发现摘要、步骤1e的差异提示、步骤3b的提议字段表格+
ask_user_tool
、步骤4中两行的“文件已创建”确认、步骤5中一行的验证结果、步骤7a的部署询问、步骤7b/7e的单行摘要、步骤7.5的架构摘要表格(只要
{fqn, schema}
已解析),以及步骤8的提示(当
suppressCreateContentPrompt
false
/未设置时)。
请勿提前输出
Task Completed
、“完成”、“全部就绪”
— 必须在步骤7决议完成、步骤7.5的摘要打印完毕、步骤8的控制逻辑评估完成后才能输出。提前输出会导致摘要和部署询问被静默终止。

Agent checklist and tripwires

代理检查清单和触发条件

The full mandatory progress checklist and the tripwire list are in
references/agent-checklist.md
. Copy the checklist agent-internally and tick each box only after the action is genuinely done. Do not print it to chat.
完整的必填进度检查清单和触发条件列表位于
references/agent-checklist.md
。代理内部复制该清单,仅在操作真实完成后勾选对应项。请勿打印到聊天窗口。

Workflow (CREATE)

工作流(创建流程)

1. Discover existing types (silent — no user prompts in this step)

1. 发现现有类型(静默 — 本步骤无用户提示)

1a. Resolve project context (agent-internal)
Read
sfdx-project.json
. Take
packageDirectories[0].path
and append
/main/default
<sfdx-source>
. Bundles live at
<sfdx-source>/contentTypes/
. If
sfdx-project.json
is missing, emit
error
outcome per § Invocation contract with message
This is not an SFDX project — open the project root and re-run.
, print the message, and stop.
Explicit-FQN fast-path (direct user). Caller did NOT supply
fqn
but the message literally contains a
namespace__DeveloperName
token (e.g.
sfdc_cms__news
,
c__PressRelease
) → capture it as
fqn
and route directly to step 1e, skipping 1b/1c/1d. Mirror of the delegated
{fqn}
shape.
Residual-intent capture (agent-internal). Scan the message for a second clause joined by
and also
/
and then
/
then
, or a second imperative verb targeting a content record (e.g.
create <type> and also create a <thing> about X
). If present, stash as
residualIntent
— step 8's Yes branch forwards it as
intent
. Do NOT print or act on it before step 8.
1b. Local discovery (silent)
Use a directory-listing capability (
list_files
/
Glob
on
<sfdx-source>/contentTypes/*/schema.json
/ IDE
list_directory
), NOT a content-search/grep tool — content-search misses folder-name-only matches. For each subfolder, read
schema.json
(
title
+
description
). Match by intent semantically: reason about content domains, not literal strings — a folder named
MarketPlace
IS a match for a marketplace request even with no literal property match. Return every semantically-matching local bundle into
combined
(step 1d's sort + 5-row cap handle the rest). Zero matches → return zero (auto-proceed on direct invocation).
Rationale, anti-patterns, tool-selection details →
references/discovery-details.md#1b
.
1c. Org discovery (silent — dispatch
metadata-grounding.search_metadata
, backed by
content-readonly.get_content_types_for_workspace
)
Dispatch gate: 1c is a tool call, not a thought. Do NOT skip because 1b found a local match — the org may still have a same-named bundle ("Name already exists" originates here). Unconditional; only real outage exempts a given tool. Never ask "should I search?".
The
search_metadata
query
parameter carries content-domain nouns only
— 3-5 English words describing what the content is ABOUT (news, article, product, press release). NOT an FQN, namespace hint, or copy of the message.
metadataType: "ContentTypeBundle"
already signals the kind. Never dispatch a query containing
sfdc_cms
,
c__
,
__
,
content type
,
bundle
,
metadata
, or
cms
— rebuild if it does. Full ruleset + concrete call-shape table (also referenced from
experience-cms-content-generate
as drift safety-net) →
references/discovery-query-rules.md
.
Server target:
metadata-grounding
(RULE 1).
limit=5
, sorted OOTB-first.
Do NOT dispatch
query_metadata
in 1c.
search_metadata
returns everything 1d's table needs (FQN, description, OOTB flag).
query_metadata
is load-bearing only for the OOTB-schema fetch in 1e — dispatch on-demand, for the ONE picked FQN. Per-row fan-out is N wasted round-trips.
Workspace content-types check — dispatched every run, alongside or instead of grounding. Call params per the mutual-exclusivity contract (§ Invocation contract), never
baseType
alongside
spaceId
/
folderId
. Flow 1 (grounding available) — also dispatch
get_content_types_for_workspace
; org candidate set = intersection of both FQN sets (empty is valid, do not widen/retry). Flow 2 (grounding unavailable) — dispatch it directly as the sole org signal, apply step 1b's semantic matching to its rows, record
groundingFallback=workspaceTypes
for 1d's TRUTH GATE. Neither tool substitutes for 1e's retrieve. Call shapes, unavailability handling, rationale →
references/discovery-details.md#1c continued
.
1d. Always present discovery findings — including "no matches"
Discovery is the first chat-visible signal. Always tell the user what was checked and found. Every case (A/B/C) surfaces a pick list via
ask_user_tool
and WAITS for the user's reply next turn.
TRUTH GATE — 1d wording must match what actually happened in 1c. Never claim a check that didn't run this turn; never disclose a skip that didn't happen either. Three cases:
  • search_metadata
    dispatched (Flow 1, regardless of
    get_content_types_for_workspace
    outcome) → org was checked via grounding. No disclosure needed.
  • search_metadata
    unavailable but
    get_content_types_for_workspace
    dispatched (Flow 2 /
    groundingFallback=workspaceTypes
    ) → org WAS checked, just not via grounding. Append
    (checked supported content types for this workspace — metadata-grounding unavailable)
    per
    assets/discovery-prompts.md
    .
  • Both unavailable → org genuinely not checked. Append
    (org check skipped — grounding unavailable)
    per
    assets/discovery-prompts.md
    .
See
references/discovery-details.md#1d
.
Provide an FQN
gating — compute
showFqnOption
.
Show when EITHER: (1) any results exist (local OR grounding ≥1) — user may want a match that isn't row 1; rows 2–5 and beyond-cap results surface in the FQN option parenthetical; OR (2) invocation is delegated (
suppressCreateContentPrompt === true
OR caller supplied
fqn
) — always available in the delegated no-matches variant.
Otherwise (direct invocation AND zero matches) →
showFqnOption = false
; skip the pick prompt, print an info line, auto-proceed to step 2. Offering FQN input when the direct user asked to create fresh and nothing matched switches their goal.
Intent-sanity gate on direct-invocation zero-matches. Before auto-proceeding, extract at least one recognizable content-domain noun from the message (real word, named entity, or compound domain vocabulary — not gibberish, not filler-only after stripping mechanic nouns like
content type
/
bundle
/
CMS
/
schema
/
metadata
). ≥1 recognizable noun → proceed to step 2 → 3, with the step 3 proposed name built ONLY from those tokens. Gibberish/filler-only → do NOT auto-proceed; ask
Your request "<original message>" doesn't name a content domain. What kind of content type would you like to create (e.g. news, blog, press release, product)?
with
Cancel
+ free-text; free-text restarts 1b,
Cancel
cancelled
. Same gate applies when 1c's rebuilt query would be empty — do NOT dispatch a blank
search_metadata
. STRICTLY DO NOT fabricate a name from tokens absent from the message. Full rule + examples →
references/discovery-details.md#1d
.
Prompt templates (has-matches, zero-matches direct auto-proceed, zero-matches delegated, "Provide an FQN" follow-up) →
assets/discovery-prompts.md
. Copy verbatim.
1d output shape — TWO separate outputs, never merged (the #1 reported UX defect):
  1. Chat markdown FIRST — the
    Top <N> matching content types:
    header + the
    FQN | Description | Location
    table (Output 1 in
    assets/discovery-prompts.md
    ). Plain chat text, NOT the tool.
  2. THEN
    ask_user_tool
    whose
    question
    is EXACTLY
    Found matches. Pick one:
    (verbatim, one short sentence) with the 4 FIXED options:
    Use existing: <row-1 FQN>
    /
    Provide an FQN
    /
    Create new: <newName>
    /
    Cancel
    .
STRICTLY DO NOT: write any preamble/prose sentence before or instead of the table; put the table, its columns, or the
(checked supported… / org check skipped…)
suffix INSIDE the
question
field (it renders as one flat line with no markdown — the reported broken wall of text); paraphrase or "make more helpful" the
question
(it is verbatim
Found matches. Pick one:
); add a
Use existing:
option per row (options are FIXED at 4 — extra rows are reached via
Provide an FQN
). Everything structured goes in the chat markdown of Output 1; the
question
field stays a single plain sentence. →
assets/discovery-prompts.md
, copy verbatim.
Routing after the user replies:
User pickNext action
Use existing: <Name>
Go to step 1e with
fqn = <namespace>__<Name>
(default namespace
c
for local matches whose folder isn't namespaced).
Provide an FQN
(only present when
showFqnOption = true
)
Ask the follow-up in
assets/discovery-prompts.md
. On reply → step 1e with that FQN.
Create new: <contentTypeName>
Continue to step 2 → step 3.
Cancel
Emit
cancelled
outcome per § Invocation contract, print
Cancelled. No files written.
, then
Task Completed
.
STRICTLY DO NOT print the pick list and announce "proceeding to create a new one" in the same message. The user picks, not you.
1a. 解析项目上下文(代理内部操作)
读取
sfdx-project.json
。取
packageDirectories[0].path
并追加
/main/default
<sfdx-source>
。包存储在
<sfdx-source>/contentTypes/
目录下。若
sfdx-project.json
缺失,根据§调用约定输出
error
结果,提示信息为
这不是一个SFDX项目 — 请打开项目根目录后重新运行。
,打印该提示并终止。
显式FQN快速路径(用户直接调用)。调用方未传入
fqn
但消息中明确包含
namespace__DeveloperName
格式的令牌(如
sfdc_cms__news
c__PressRelease
)→ 将其捕获为
fqn
并直接路由到步骤1e,跳过步骤1b/1c/1d。与委托调用的
{fqn}
形式一致。
残留意图捕获(代理内部操作)。扫描消息中由
and also
/
and then
/
then
连接的第二个分句,或针对内容记录的第二个祈使动词(如
创建<类型>并同时创建关于X的<内容>
)。若存在,将其存储为
residualIntent
— 步骤8的“是”分支会将其作为
intent
转发。请勿在步骤8前打印或执行该意图。
1b. 本地发现(静默)
使用目录列表功能(
list_files
/ 对
<sfdx-source>/contentTypes/*/schema.json
执行
Glob
/ IDE的
list_directory
),而非内容搜索/grep工具 — 内容搜索会遗漏仅文件夹名称匹配的结果。对于每个子文件夹,读取
schema.json
(获取
title
+
description
)。按意图语义匹配:根据内容领域进行推理,而非字面字符串 — 名为
MarketPlace
的文件夹即使没有字面属性匹配,也属于市场相关请求的匹配结果。将所有语义匹配的本地包返回至
combined
(步骤1d的排序和5行限制会处理其余结果)。无匹配结果 → 返回空列表(用户直接调用时自动继续)。
原理、反模式、工具选择细节详见
references/discovery-details.md#1b
1c. 组织端发现(静默 — 调度
metadata-grounding.search_metadata
,结合
content-readonly.get_content_types_for_workspace
调度规则:1c是工具调用,不是思考过程。请勿因步骤1b找到本地匹配结果而跳过本步骤 — 组织中可能存在同名包(“名称已存在”错误源于此)。必须无条件执行;仅当工具真正中断时才可豁免。绝不询问“是否要搜索?”。
search_metadata
query
参数仅包含内容领域名词
— 3-5个描述内容主题的英文单词(如news、article、product、press release)。不得是FQN、命名空间提示或消息副本。
metadataType: "ContentTypeBundle"
已明确表示类型。绝不调度包含
sfdc_cms
c__
__
content type
bundle
metadata
cms
的查询 — 若包含则重新构建。完整规则集+具体调用形式表(同时作为
experience-cms-content-generate
的差异安全网被引用)详见
references/discovery-query-rules.md
服务器目标:
metadata-grounding
(规则1)。
limit=5
,按OOTB优先排序。
步骤1c中禁止调度
query_metadata
search_metadata
返回步骤1d表格所需的全部信息(FQN、描述、OOTB标记)。
query_metadata
仅在步骤1e中获取OOTB架构时才是必要的 — 按需调度,仅针对选中的FQN。逐行调度会造成N次不必要的往返请求。
工作区内容类型检查 — 每次运行都调度,作为grounding的补充或替代。调用参数遵循互斥约定(§调用约定),绝不将
baseType
spaceId
/
folderId
同时传入。流程1(grounding可用) — 同时调度
get_content_types_for_workspace
;组织候选集 = 两个FQN集合的交集(空集合法,无需扩大范围/重试)。流程2(grounding不可用) — 直接调度该工具作为唯一的组织端信号,对其结果应用步骤1b的语义匹配规则,在代理内部记录
groundingFallback=workspaceTypes
用于步骤1d的真实性校验。这两个工具都无法替代步骤1e的检索操作。调用形式、不可用处理、原理详见
references/discovery-details.md#1c continued
1d. 始终展示发现结果 — 包括“无匹配”情况
发现流程是第一个对用户可见的信号。必须始终告知用户检查了哪些内容以及发现了什么。所有情况(A/B/C)都通过
ask_user_tool
展示选择列表,并等待用户在下一回合回复。
真实性校验 — 步骤1d的表述必须与步骤1c的实际操作一致。绝不声称本回合未执行的检查;也绝不披露未发生的跳过操作。分为三种情况:
  • 已调度
    search_metadata
    (流程1,无论
    get_content_types_for_workspace
    结果如何)→ 通过grounding检查了组织端。无需额外说明。
  • search_metadata
    不可用但已调度
    get_content_types_for_workspace
    (流程2 /
    groundingFallback=workspaceTypes
    )→ 已检查组织端,只是未通过grounding。根据
    assets/discovery-prompts.md
    追加
    (已检查此工作区支持的内容类型 — metadata-grounding不可用)
  • 两者均不可用 → 未检查组织端。根据
    assets/discovery-prompts.md
    追加
    (已跳过组织端检查 — grounding不可用)
详见
references/discovery-details.md#1d
提供FQN
选项的显示控制 — 计算
showFqnOption
。当满足以下任一条件时显示:(1) 存在任何结果(本地或grounding结果≥1)— 用户可能需要非第一行的匹配结果;第2–5行及超出限制的结果会在
提供FQN
选项的括号中展示;或(2) 为委托调用(
suppressCreateContentPrompt === true
或调用方传入
fqn
)— 在委托调用无匹配结果的变体中始终显示。
否则(用户直接调用且无匹配结果)→
showFqnOption = false
;跳过选择提示,打印一行信息,自动进入步骤2。当用户直接请求创建全新类型且无匹配结果时,提供FQN输入选项会偏离用户目标。
用户直接调用无匹配结果时的意图合理性校验。自动继续前,从消息中提取至少一个可识别的内容领域名词(真实单词、命名实体或复合领域词汇 — 不是无意义字符,也不是去除
content type
/
bundle
/
CMS
/
schema
/
metadata
等机械名词后的纯填充词)。若提取到≥1个可识别名词 → 进入步骤2→3,步骤3的提议名称仅由这些令牌构建。若为无意义字符/纯填充词 → 请勿自动继续;询问用户
你的请求“<原始消息>”未指定内容领域。你想要创建哪种内容类型(例如:新闻、博客、新闻稿、产品)?
,提供
取消
+自由文本输入选项;自由文本输入会重新启动步骤1b,
取消
→ 输出
cancelled
结果。当步骤1c的重构查询为空时,同样适用该校验规则 — 绝不调度空白的
search_metadata
。严格禁止从消息中不存在的令牌生成名称。完整规则+示例详见
references/discovery-details.md#1d
提示模板(有匹配结果、无匹配结果用户直接调用自动继续、无匹配结果委托调用、“提供FQN”后续提示)详见
assets/discovery-prompts.md
。请严格复制原文。
步骤1d输出格式 — 两个独立输出,绝不合并(这是排名第一的UX缺陷):
  1. 首先输出聊天markdown
    Top <N> matching content types:
    标题 +
    FQN | 描述 | 位置
    表格(
    assets/discovery-prompts.md
    中的Output 1)。为纯聊天文本,不是工具输出。
  2. 然后输出
    ask_user_tool
    ,其
    question
    字段必须严格为
    Found matches. Pick one:
    (逐字复制,简短句子),包含4个固定选项:
    Use existing: <row-1 FQN>
    /
    Provide an FQN
    /
    Create new: <newName>
    /
    Cancel
严格禁止:在表格之前或替代表格写入任何前置说明/描述性句子;将表格、列或
(已检查支持的… / 已跳过组织端检查…)
后缀放入
question
字段(会渲染为无格式的单行文本 — 这是已报告的格式混乱问题);改写或“优化”
question
字段(必须严格为
Found matches. Pick one:
);为每行添加一个
Use existing:
选项(选项固定为4个 — 额外行通过
Provide an FQN
选项访问)。所有结构化内容放入Output 1的聊天markdown中;
question
字段保持为单个纯文本句子。详见
assets/discovery-prompts.md
,请严格复制原文。
用户回复后的路由:
用户选择后续操作
Use existing: <Name>
进入步骤1e
fqn = <namespace>__<Name>
(本地匹配结果的文件夹无命名空间时,默认命名空间为
c
)。
Provide an FQN
(仅当
showFqnOption = true
时显示)
根据
assets/discovery-prompts.md
询问后续问题。用户回复后 → 步骤1e,使用该FQN。
Create new: <contentTypeName>
继续进入步骤2 → 步骤3。
Cancel
根据§调用约定输出
cancelled
结果,打印
已取消。未写入任何文件。
,然后输出
Task Completed
严格禁止在同一消息中打印选择列表并宣布“将继续创建新类型”。由用户选择,而非代理自行决定。

1e. Retrieve and reconcile

1e. 检索并协调

Reached when 1d resolves to a match / provided FQN, OR when the caller invoked with
{fqn}
. Goal: return
{fqn, schema}
matching the org.
Namespace gate:
  • Custom FQN (
    c__*
    , non-platform namespace) → run
    sf project retrieve start --metadata ContentTypeBundle:<DeveloperName> --target-org <alias> --json
    . Always retrieve for custom.
  • OOTB FQN (
    sfdc_cms__*
    ) → skip
    sf project retrieve start
    (returns nothing usable). This branch needs a live
    metadata-grounding
    schema, regardless of which flow surfaced the FQN
    get_content_types_for_workspace
    (Flow 2) never returns a schema, only
    {fqn, name, description}
    . If 1c already recorded
    grounding=unavailable
    , do NOT attempt
    query_metadata
    — go straight to the error below. Otherwise dispatch
    query_metadata({ metadataType: "ContentTypeBundle", id: "<grounding row id from 1c>" })
    NOW for the picked FQN only, and resolve the schema from its response (fall back to
    describe_metadata
    if it returns no schema payload). If that response is error/empty/non-schema, surface
    Can't resolve OOTB FQN "<fqn>" without a real schema from metadata-grounding. Retry when grounding is back, or provide a custom FQN.
    and exit with
    error
    . Never fabricate OOTB schemas from training data — "sfdc_cms__news typically has title/body/summary…" IS the bug thought that poisons 3–7. Fail closed. Full rule →
    references/retrieve-and-reconcile.md
    § Namespace gate.
Reconciliation — compare retrieved schema against
<sfdx-source>/contentTypes/<DeveloperName>/schema.json
. Full matrix + drift template + routing →
references/retrieve-and-reconcile.md
.
Routing outcomes:
  • Not in local, retrieved → write local, return
    {fqn, schema=retrieved}
    .
  • In both, match → return
    {fqn, schema=local}
    .
  • In both, differ → drift prompt (
    Deploy local to org
    → step 5/7;
    Overwrite local with org
    → replace files, return;
    Cancel
    → exit).
  • In local only → print step 7.5 summary first (user sees what they'd deploy), then offer deploy (5/7) or cancel.
  • In neither → re-dispatch 1d pick with
    Try a different FQN
    option.
On success, return
{fqn, schema}
and continue to 7.5 → 8.
No proposal-of-fields, no re-validation — reconciled schema is source of truth. Create-only for new; reconcile-only for existing.
"Create new" in 1d is the ONLY path that proceeds to step 2.
当步骤1d解析为匹配结果/用户提供的FQN,或调用方以
{fqn}
形式调用时进入本步骤。目标:返回与组织端匹配的
{fqn, schema}
命名空间校验:
  • 自定义FQN
    c__*
    ,非平台命名空间)→ 执行
    sf project retrieve start --metadata ContentTypeBundle:<DeveloperName> --target-org <alias> --json
    。自定义类型必须始终执行检索。
  • OOTB FQN
    sfdc_cms__*
    )→ 跳过
    sf project retrieve start
    (返回的内容无法使用)。无论通过哪种流程得到该FQN,此分支都需要实时的
    metadata-grounding
    架构
    get_content_types_for_workspace
    (流程2)从不返回架构,仅返回
    {fqn, name, description}
    。若步骤1c已记录
    grounding=unavailable
    ,请勿尝试
    query_metadata
    — 直接进入下方错误流程。否则,立即为选中的FQN调度
    query_metadata({ metadataType: "ContentTypeBundle", id: "<步骤1c中grounding行的id>" })
    ,并从响应中解析架构(若未返回架构负载,回退到
    describe_metadata
    )。若响应为错误/空/非架构内容,提示用户
    无法从metadata-grounding获取真实架构,无法解析OOTB FQN "<fqn>"。请在grounding恢复后重试,或提供自定义FQN。
    并以
    error
    结果终止。绝不从训练数据生成OOTB架构 — “sfdc_cms__news通常包含title/body/summary……”是导致步骤3–7出错的错误思路。失败时直接终止。完整规则详见
    references/retrieve-and-reconcile.md
    §命名空间校验。
协调操作 — 将检索到的架构与
<sfdx-source>/contentTypes/<DeveloperName>/schema.json
进行比较。完整矩阵+差异模板+路由规则详见
references/retrieve-and-reconcile.md
路由结果:
  • 本地不存在,已检索到 → 写入本地,返回
    {fqn, schema=retrieved}
  • 本地和组织端均存在,且匹配 → 返回
    {fqn, schema=local}
  • 本地和组织端均存在,但不匹配 → 显示差异提示(
    将本地版本部署到组织
    →步骤5/7;
    用组织版本覆盖本地
    →替换文件并返回;
    取消
    →终止)。
  • 仅本地存在 → 先打印步骤7.5的摘要(让用户了解将要部署的内容),然后提供部署(步骤5/7)或取消选项。
  • 两者均不存在 → 重新调度步骤1d的选择列表,添加
    尝试其他FQN
    选项。
成功后,返回
{fqn, schema}
并继续进入步骤7.5 → 8
。无需提议字段,无需重新验证 — 协调后的架构为可信源。仅为新类型执行创建操作;仅为现有类型执行协调操作。
步骤1d中的“创建新类型”是唯一进入步骤2的路径。

2. Resolve target org

2. 解析目标组织

Prefer the SF CLI default (alias from
sf config set target-org=<alias>
or
defaultUsername
in
sfdx-project.json
). Resolve to
<orgAlias>
and pass as
--target-org <orgAlias>
on every
sf
call. When a default is set, this step is silent.
No default — fallback: run
sf org list --json
(silent):
  • Zero authenticated orgs → emit
    error
    with message
    No authenticated Salesforce org found. Run sf org login web and re-run.
    , print, stop.
  • Exactly one → use silently as
    <orgAlias>
    . Do not modify
    sf config
    .
  • Two or more → dispatch
    ask_user_tool
    with question
    No default Salesforce org is set. Pick the org to use for this run:
    and one option per org labelled
    <alias> (<username>) [<devhub|sandbox|scratch|prod>]
    , plus
    Cancel
    . On pick, use as
    <orgAlias>
    for this run only (do NOT run
    sf config set target-org=…
    ).
    Cancel
    → emit
    cancelled
    , print
    Cancelled. No files written.
    ,
    Task Completed
    .
The picked alias applies to every subsequent
sf
call this run (1e retrieve, 5 dry-run, 7 deploy).
优先使用SF CLI默认组织(来自
sf config set target-org=<alias>
sfdx-project.json
中的
defaultUsername
)。解析为
<orgAlias>
,并在每次
sf
调用中作为
--target-org <orgAlias>
传入。当已设置默认组织时,本步骤静默执行。
无默认组织 — 回退方案: 执行
sf org list --json
(静默):
  • 无已认证组织 → 输出
    error
    结果,提示信息为
    未找到已认证的Salesforce组织。请运行sf org login web后重新尝试。
    ,打印该提示并终止。
  • 仅一个已认证组织 → 静默使用该组织作为
    <orgAlias>
    。请勿修改
    sf config
  • 两个及以上已认证组织 → 调度
    ask_user_tool
    ,问题为
    未设置默认Salesforce组织。请选择本次运行使用的组织:
    ,每个组织对应一个选项,格式为
    <alias> (<username>) [<devhub|sandbox|scratch|prod>]
    ,同时提供
    取消
    选项。用户选择后,仅在本次运行中使用该
    <orgAlias>
    (请勿执行
    sf config set target-org=…
    )。
    取消
    → 输出
    cancelled
    结果,打印
    已取消。未写入任何文件。
    ,然后输出
    Task Completed
选中的别名适用于本次运行中所有后续
sf
调用(步骤1e的检索、步骤5的预部署验证、步骤7的部署)。

3. Propose fields and get user approval

3. 提议字段并获取用户确认

Preconditions: 1c dispatched
search_metadata
(or recorded
grounding=unavailable
), and 1d resolved to
Create new: <contentTypeName>
in the previous turn. Other 1d picks route elsewhere:
Use existing
/
Provide an FQN
→ 1e;
Cancel
→ emit
cancelled
.
If you just printed a pick list via
ask_user_tool
and the user hasn't replied, stop — your turn is over.
3a. Determine field properties (agent-internal). Set
apiName
(camelCase),
title
(human-readable),
lightning:type
,
required
. Default-minimal: no
lightning:textIndexed
,
lightning:localizable
, length/range bounds,
enum
,
const
,
placeholderText
unless the user asked.
Content-type name must be derivable from the user's message.
<contentTypeName>
and its
title
must be built from tokens actually present (PascalCase/word-order shaping OK —
laptop review
LaptopReview
). STRICTLY DO NOT invent from thin air, from an unrelated open tab, or from prior-session context. If 1d's sanity gate passed but the noun set is thin (one word), use that word — do not embellish. Proposing a name with tokens absent from the message IS the hallucination anti-pattern; stop and restart 1d's gate.
Initialize
userEditedFields = false
agent-internally. Governs step 6's branching. Flipped to
true
only when the user types free-text edits in the 3b loop (see
references/edit-fields-loop.md
).
Edit fields
Approve as shown
without typing any edit leaves it
false
— proposal accepted unchanged.
3b. Present proposed fields — markdown table FIRST as chat-visible text, THEN
ask_user_tool
in the same turn.
Do NOT collapse the table into the tool prompt — the UI strips formatting and the user cannot approve informed.
Message 1 (chat-visible plain text):
text
Proposed fields for `<contentTypeName>` at `<sfdx-source>/contentTypes/<contentTypeName>/`:

| # | API name | Type | Required | Constraints | Title |
|---|---|---|---|---|---|
| 1 | `title` | `lightning__textType` | yes | maxLength: 200 | Title |
| 2 | `body`  | `lightning__richTextType` | yes | — | Body |
Constraints format follows 7.5 (see
references/schema-summary-format.md
): comma-separated
key: value
pairs for any per-field constraint asked or proposed —
maxLength
,
minLength
,
minimum
,
maximum
,
enum
,
const
,
lightning:localizable
,
lightning:allowedUrlSchemes
, etc. Use
when a field has no constraints beyond
required
.
Message 2 (same turn): dispatch
ask_user_tool
with question
Approve these fields, edit them, or cancel?
and options
Approve
,
Edit fields
,
Cancel
.
  • Approve
    → step 4.
  • Edit fields
    → follow the loop below. Loop until approved.
  • Cancel
    → emit
    cancelled
    , print
    Cancelled. No files written.
    ,
    Task Completed
    .
Edit-fields loop — each round reprints the current table (chat-visible), then dispatches
ask_user_tool
with
Approve as shown
/
Cancel
options and accepts free-text edit instructions. Free-text tool result IS the edit instructions — parse and apply, then loop; do NOT stop. Full template + anti-stop guidance →
references/edit-fields-loop.md
.
前置条件:步骤1c已调度
search_metadata
(或已记录
grounding=unavailable
),且步骤1d在上一回合解析为
Create new: <contentTypeName>
。步骤1d的其他选择会路由到其他路径:
使用现有类型
/
提供FQN
→步骤1e;
取消
→输出
cancelled
结果。
若你刚通过
ask_user_tool
打印了选择列表但用户尚未回复,请停止操作 — 你的回合已结束。
3a. 确定字段属性(代理内部操作)。设置
apiName
(驼峰式)、
title
(人类可读)、
lightning:type
required
。默认最小配置:除非用户要求,否则不设置
lightning:textIndexed
lightning:localizable
、长度/范围限制、
enum
const
placeholderText
内容类型名称必须可从用户消息推导
<contentTypeName>
及其
title
必须由消息中实际存在的令牌构建(允许使用大驼峰式/调整词序 — 如
laptop review
LaptopReview
)。严格禁止凭空生成,或从无关的打开标签页、会话上下文生成。若步骤1d的合理性校验通过但名词集合较少(仅一个单词),则使用该单词 — 请勿添加额外内容。提议包含消息中不存在的令牌的名称属于幻觉反模式;请停止操作并重新执行步骤1d的校验。
在代理内部初始化
userEditedFields = false
。该变量控制步骤6的分支逻辑。仅当用户在步骤3b的循环中输入自由文本编辑内容时,才将其设为
true
(详见
references/edit-fields-loop.md
)。选择
编辑字段
按当前展示确认
但未输入任何编辑内容时,保持
false
— 表示接受提议的原始内容。
3b. 展示提议字段 — 先输出markdown表格作为可见聊天文本,再在同一回合输出
ask_user_tool
。请勿将表格合并到工具提示中 — UI会去除格式,导致用户无法做出知情确认。
消息1(可见聊天文本):
text
为`<contentTypeName>`提议的字段,存储路径为`<sfdx-source>/contentTypes/<contentTypeName>/`:

| # | API名称 | 类型 | 必填 | 约束 | 标题 |
|---|---|---|---|---|---|
| 1 | `title` | `lightning__textType` | 是 | maxLength: 200 | 标题 |
| 2 | `body`  | `lightning__richTextType` | 是 | — | 正文 |
约束格式遵循步骤7.5的规则(详见
references/schema-summary-format.md
):以逗号分隔的
key: value
对,表示用户要求或提议的每个字段约束 — 如
maxLength
minLength
minimum
maximum
enum
const
lightning:localizable
lightning:allowedUrlSchemes
等。当字段除
required
外无其他约束时,使用
表示。
消息2(同一回合):调度
ask_user_tool
,问题为
是否确认这些字段,编辑它们,或取消?
,选项为
确认
编辑字段
取消
  • 确认
    → 进入步骤4。
  • 编辑字段
    → 遵循下方循环逻辑。循环直到用户确认。
  • 取消
    → 输出
    cancelled
    结果,打印
    已取消。未写入任何文件。
    ,然后输出
    Task Completed
字段编辑循环 — 每一轮都重新打印当前表格(可见聊天文本),然后调度
ask_user_tool
提供
按当前展示确认
/
取消
选项,并接受自由文本编辑指令。自由文本工具结果即为编辑指令 — 解析并应用后继续循环;请勿停止。完整模板+禁止停止的指导说明详见
references/edit-fields-loop.md

4. Create files (silent — confirm in two lines max)

4. 创建文件(静默 — 最多用两行确认)

Precondition: step 3b returned the user's
Approve
in the immediately preceding turn. No file write before approval.
Create
<sfdx-source>/contentTypes/<contentTypeName>/
. Use the already-loaded
assets/schema-example.json
(per § Schema rules — do NOT re-fetch a sibling
schema.json
). Generate
schema.json
for the approved fields and
<contentTypeName>.contentTypeBundle-meta.xml
with exactly these four lines, swapping only
<masterLabel>
:
xml
<?xml version="1.0" encoding="UTF-8"?>
<ContentTypeBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <masterLabel><contentTypeName></masterLabel>
</ContentTypeBundle>
Do NOT add
<displayName>
,
<description>
,
<contentTypeFields>
,
<fieldType>
, or any legacy SOAP element — those fail the validator. Per-field forbidden keys (
type
,
format
,
default
, empty
lightning:uiOptions
) →
references/schema-rules.md
.
After writing, print exactly two lines:
text
Created <sfdx-source>/contentTypes/<contentTypeName>/schema.json
Created <sfdx-source>/contentTypes/<contentTypeName>/<contentTypeName>.contentTypeBundle-meta.xml
Then proceed to step 5. Before dispatching 5a, run the pre-deploy schema checklist in
references/pre-deploy-checklist.md
(agent-internal, do not print). Fix in place and re-check.
前置条件:步骤3b在上一回合返回用户的
确认
操作。确认前请勿写入任何文件。
创建目录
<sfdx-source>/contentTypes/<contentTypeName>/
。使用已加载的
assets/schema-example.json
(根据§架构规则 — 请勿重新获取同级的
schema.json
)。为确认的字段生成
schema.json
,并生成
<contentTypeName>.contentTypeBundle-meta.xml
,该文件仅包含以下四行,仅替换
<masterLabel>
xml
<?xml version="1.0" encoding="UTF-8"?>
<ContentTypeBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <masterLabel><contentTypeName></masterLabel>
</ContentTypeBundle>
请勿添加
<displayName>
<description>
<contentTypeFields>
<fieldType>
或任何遗留SOAP元素 — 这些会导致验证失败。每个字段禁止使用的键(如
type
format
default
、空
lightning:uiOptions
)详见
references/schema-rules.md
写入文件后,打印以下两行:
text
已创建 <sfdx-source>/contentTypes/<contentTypeName>/schema.json
已创建 <sfdx-source>/contentTypes/<contentTypeName>/<contentTypeName>.contentTypeBundle-meta.xml
然后进入步骤5。调度步骤5a前,执行
references/pre-deploy-checklist.md
中的预部署架构检查清单(代理内部操作,请勿打印)。就地修复问题并重新检查。

5. Validate (mandatory)

5. 验证(必填)

Step 5 is unconditional. Skip only if step 1d ended with
Use existing
.
grounding=unavailable
does not skip step 5 (different auth path). Do not suggest the dry-run as a command for the user to run — you run it.
5a. Run (no preamble in chat):
bash
sf project deploy start --source-dir <sfdx-source>/contentTypes/<contentTypeName> --target-org <orgAlias> --dry-run --json
5b. Result handling:
  • result.status === "Succeeded"
    → print one line:
    Validated against <org>: Succeeded (dry-run — nothing deployed yet).
    This is NOT a terminal state — your next action is step 7a's
    ask_user_tool
    .
  • result.status === "Failed"
    with
    componentFailures
    → step 6 (auto-fix).
  • result.status === "Failed"
    with zero
    componentFailures
    → CLI/auth issue. Show the raw response, ask the user to verify
    sf org list
    , source path, and
    sfdx-project.json
    . Do not count as one of the 3 attempts.
步骤5为无条件执行。仅当步骤1d以
使用现有类型
结束时才可跳过。
grounding=unavailable
不跳过步骤5(认证路径不同)。请勿建议用户自行运行预部署命令 — 由代理执行。
5a. 执行命令(聊天窗口无前置说明):
bash
sf project deploy start --source-dir <sfdx-source>/contentTypes/<contentTypeName> --target-org <orgAlias> --dry-run --json
5b. 结果处理:
  • result.status === "Succeeded"
    → 打印一行:
    已针对<org>验证:成功(预部署 — 尚未部署任何内容)。
    这不是终端状态 — 下一步操作是步骤7a的
    ask_user_tool
  • result.status === "Failed"
    且包含
    componentFailures
    → 进入步骤6(自动修复)。
  • result.status === "Failed"
    且无
    componentFailures
    → CLI/认证问题。展示原始响应,询问用户确认
    sf org list
    、源路径和
    sfdx-project.json
    。不计入3次尝试次数。

6. Fix validator failures — silent auto-fix or ask-first, based on
userEditedFields

6. 修复验证失败 — 根据
userEditedFields
执行静默自动修复或先询问用户

Branches on
userEditedFields
(set in 3a). The split reflects who authored the broken schema:
  • false
    → user accepted the agent's proposal unchanged. Validator failure is the agent's mistake. Silent auto-fix.
  • true
    → user typed edits in 3b. Failure may reflect intent (e.g.
    enum
    on integer,
    default
    on text) only the user can resolve. Show planned fixes, ask first.
Both branches share the sweep-the-whole-schema principle and the 3-attempt cap on agent-driven fixes. Each attempt fixes every problem the validator could possibly flag across the whole schema, not one field at a time — validators only report 1–2 errors per pass; don't fall into one-field-per-attempt. Error-to-fix mapping (incl. safe vs. intent-changing
Kind
) →
references/deployment-errors.md
.
6a. Silent auto-fix (
userEditedFields === false
)
  1. Read every
    componentFailures[].problem
    .
  2. Sweep
    properties
    for the same class of issue. E.g. one
    placeholderText missing
    → audit all
    lightning:uiOptions
    ; one
    format
    rejected → strip
    type
    /
    format
    /
    default
    from every field; one disallowed type-specific key → audit every field of that
    lightning:type
    .
  3. Re-write once, re-run step 5 once. Counts as one of 3 attempts.
If still failing after 3 attempts: surface the last error and route to 6b's
Let me edit
follow-up. On abandon / exit without successful validation, emit
error
with the last validator error as
message
, stop.
6b. Ask-before-fix (
userEditedFields === true
) — show planned fixes
The user authored something the validator rejected. Do NOT silently rewrite their intent.
Message 1 (chat-visible plain text, NOT in
ask_user_tool
) — enumerate every
componentFailures[].problem
, look up fixes in
references/deployment-errors.md
:
text
Validation failed on your edited schema. Planned fixes:

  ✗ <field>: <one-line error description>
      Planned: <fix> (<impact>)
  ✗ <field2>: …
      Planned: …
Include EVERY error this pass, grouped by field. When a fix drops/changes a user-authored constraint (
enum
,
const
,
lightning:localizable
, numeric bound, type swap), the parenthetical MUST state the concrete consequence — "loses numeric ordering", "no longer restricted to enum values", "text won't localize" — not "changes the type." Kind=safe fixes (
default
strip,
type
/
format
strip,
allowedUrlSchemes: ["https"]
) get the literal
safe: validator hygiene, no intent change
.
Message 2 (same turn) — dispatch
ask_user_tool
with question
How would you like to proceed?
and options
Apply these fixes and continue
/
Let me edit — I'll fix it, then re-validate
/
Cancel
.
Route:
  • Apply these fixes and continue
    → apply exactly the fixes shown, re-write once, re-run 5 once. Counts as one of 3 attempts. Success → 7a. Fail → loop back to top of 6b with the new errors (
    userEditedFields
    stays
    true
    ).
  • Let me edit
    → print file paths from step 4's two-line confirmation and validator errors verbatim, dispatch
    ask_user_tool
    with question
    Reply when you're done editing.
    and options
    Re-validate
    /
    Cancel
    .
    Re-validate
    → re-run step 5 (user-driven cycles do NOT count against 3 attempts).
    Cancel
    → emit
    cancelled
    , print
    Cancelled. Your edits remain at <sfdx-source>/contentTypes/<contentTypeName>/
    ,
    Task Completed
    . Do NOT delete the files.
  • Cancel
    → emit
    cancelled
    , print
    Cancelled. No files written.
    ,
    Task Completed
    .
If the 3-attempt cap on
Apply these fixes
is exhausted: surface the last error and route to the
Let me edit
follow-up (do NOT re-offer
Apply these fixes
). On subsequent
Cancel
, emit
error
with the last validator error as
message
, stop.
根据
userEditedFields
(步骤3a中设置)进行分支。该区分反映了谁创建了有问题的架构:
  • false
    → 用户未修改代理的提议内容。验证失败是代理的错误。执行静默自动修复
  • true
    → 用户在步骤3b中输入了编辑内容。失败可能反映了用户的意图(如对整数字段设置
    enum
    、对文本字段设置
    default
    ),只有用户才能解决。展示计划修复内容,先询问用户
两个分支都遵循全架构扫描原则,且代理驱动的修复最多尝试3次。每次尝试修复验证器可能标记的所有问题,而非逐个字段修复 — 验证器每次仅报告1–2个错误;请勿陷入逐个字段尝试的误区。错误到修复的映射(包括安全修复与改变意图的修复类型)详见
references/deployment-errors.md
6a. 静默自动修复(
userEditedFields === false
  1. 读取每个
    componentFailures[].problem
  2. 扫描
    properties
    查找同类问题。例如:一个
    placeholderText missing
    错误 → 检查所有
    lightning:uiOptions
    ;一个
    format
    被拒绝 → 从所有字段中移除
    type
    /
    format
    /
    default
    ;一个不允许的类型特定键 → 检查所有该
    lightning:type
    的字段。
  3. 一次性重写文件,重新执行步骤5一次。计入3次尝试次数。
若3次尝试后仍失败:展示最后一次错误并路由到步骤6b的
让我编辑
后续流程。若放弃/未成功验证就退出,输出
error
结果,
message
为最后一次验证错误,然后终止。
6b. 先询问再修复(
userEditedFields === true
)— 展示计划修复内容
用户创建的内容被验证器拒绝。请勿静默改写用户的意图。
消息1(可见聊天文本,请勿放入
ask_user_tool
) — 列出每个
componentFailures[].problem
,在
references/deployment-errors.md
中查找修复方案:
text
你的编辑后的架构验证失败。计划修复内容:

  ✗ <字段>: <单行错误描述>
      计划修复:<修复内容>(<影响>)
  ✗ <字段2>: …
      计划修复:…
列出本次验证的所有错误,按字段分组。当修复会删除/修改用户创建的约束(如
enum
const
lightning:localizable
、数值限制、类型转换)时,括号中必须明确说明具体后果 — 如“失去数值排序功能”、“不再限制为枚举值”、“文本无法本地化”,而非“修改类型”。安全类型的修复(如移除
default
、移除
type
/
format
、设置
allowedUrlSchemes: ["https"]
)标注为
安全:验证器合规处理,不改变意图
消息2(同一回合) — 调度
ask_user_tool
,问题为
你希望如何继续?
,选项为
应用这些修复并继续
/
让我编辑 — 我会修复,然后重新验证
/
取消
路由:
  • 应用这些修复并继续
    → 严格应用展示的修复内容,一次性重写文件,重新执行步骤5一次。计入3次尝试次数。成功 → 进入步骤7a。失败 → 回到步骤6b顶部,展示新错误(
    userEditedFields
    保持
    true
    )。
  • 让我编辑
    → 打印步骤4中两行确认的文件路径和验证错误原文,调度
    ask_user_tool
    ,问题为
    编辑完成后回复。
    ,选项为
    重新验证
    /
    取消
    重新验证
    → 重新执行步骤5(用户驱动的循环不计入3次尝试次数)。
    取消
    → 输出
    cancelled
    结果,打印
    已取消。你的编辑内容保留在<sfdx-source>/contentTypes/<contentTypeName>/
    ,然后输出
    Task Completed
    。请勿删除文件。
  • 取消
    → 输出
    cancelled
    结果,打印
    已取消。未写入任何文件。
    ,然后输出
    Task Completed
应用这些修复
的3次尝试次数耗尽:展示最后一次错误并路由到
让我编辑
后续流程(请勿再次提供
应用这些修复
选项)。若用户后续选择
取消
,输出
error
结果,
message
为最后一次验证错误,然后终止。

7. Deploy (yes/no — wait for the next user turn)

7. 部署(是/否 — 等待用户下一回合回复)

Step 5's success unlocks step 7; it does not replace it. Ask the user via
ask_user_tool
before any deploy or terminal marker.
7a. Dispatch
ask_user_tool
:
  • Question:
    Validation succeeded. Deploy "<contentTypeName>" to <org> now?
  • Options:
    Yes - deploy now
    /
    No - I'll deploy later
7b. User says no: emit
not_deployed
outcome and stop. Print one line —
text
Validated. Nothing deployed. To deploy later: sf project deploy start --source-dir <sfdx-source>/contentTypes/<contentTypeName> --target-org <orgAlias>
Return outcome:
{ status: "not_deployed", fqn: "<namespace>__<contentTypeName>", schema: null, message: "<the line above>" }
. Do NOT run step 7.5 or step 8 — the type isn't in the org.
7c. User says yes: run
bash
sf project deploy start --source-dir <sfdx-source>/contentTypes/<contentTypeName> --target-org <orgAlias> --json
7d. Deploy errors:
  • With
    componentFailures
    (rare — occurs after manual edits between validate and deploy, or transient org-side state change): route to step 6's branch matching the current
    userEditedFields
    flag. Because reaching 7d always follows at least one user-visible turn (step 7a's
    Yes - deploy now
    ), the flag is authoritative for who last authored the file. On successful re-validation, re-ask step 7a's deploy prompt. On unrecoverable failure (auto-fix exhausted then cancelled, or user cancelled in 6b), emit
    error
    outcome per § Invocation contract with the last validator error as the
    message
    , then stop.
  • With zero
    componentFailures
    (auth/network): emit
    error
    outcome per § Invocation contract with the raw response summary as the
    message
    , then stop.
7e. Success: print one line —
Deployed <contentTypeName> to <org>. Component IDs: <ids>.
This is a
success
terminal state — the outcome to emit at task end is
{ status: "success", fqn: "<namespace>__<contentTypeName>", schema: <the just-deployed schema>, message: "<the line above>" }
. Continue to step 7.5. Do not run any other command between here and step 7.5 (see Rule 4).
步骤5成功后解锁步骤7;步骤5无法替代步骤7。执行任何部署或终端标记前,通过
ask_user_tool
询问用户。
7a. 调度
ask_user_tool
:
  • 问题:
    验证成功。是否立即将“<contentTypeName>”部署到<org>?
  • 选项:
    是 — 立即部署
    /
    否 — 稍后部署
7b. 用户选择否:输出
not_deployed
结果并终止。打印一行 —
text
已验证。未部署任何内容。稍后部署请执行:sf project deploy start --source-dir <sfdx-source>/contentTypes/<contentTypeName> --target-org <orgAlias>
返回结果:
{ status: "not_deployed", fqn: "<namespace>__<contentTypeName>", schema: null, message: "<上述行内容>" }
。请勿执行步骤7.5或步骤8 — 该类型尚未部署到组织中。
7c. 用户选择是:执行命令
bash
sf project deploy start --source-dir <sfdx-source>/contentTypes/<contentTypeName> --target-org <orgAlias> --json
7d. 部署错误:
  • 包含
    componentFailures
    (罕见 — 发生在验证和部署之间用户手动编辑内容,或组织端状态临时变化):根据当前
    userEditedFields
    标记路由到步骤6的对应分支。因为进入步骤7d前必然经过至少一次用户可见的回合(步骤7a的
    是 — 立即部署
    ),该标记可权威说明谁最后编辑了文件。重新验证成功后,重新询问步骤7a的部署提示。若无法恢复(自动修复次数耗尽后取消,或用户在步骤6b中取消),根据§调用约定输出
    error
    结果,
    message
    为最后一次验证错误,然后终止。
  • componentFailures
    (认证/网络问题):根据§调用约定输出
    error
    结果,
    message
    为原始响应摘要,然后终止。
7e. 部署成功:打印一行 —
已将<contentTypeName>部署到<org>。组件ID:<ids>。
这是
success
终端状态 — 任务结束时输出的结果为
{ status: "success", fqn: "<namespace>__<contentTypeName>", schema: <刚部署的架构>, message: "<上述行内容>" }
。继续进入步骤7.5。请勿在此时到步骤7.5之间执行任何其他命令(见规则4)。

7.5. Schema summary (on every resolved-schema path)

7.5. 架构摘要(所有已解析架构的路径均执行)

Runs whenever
{fqn, schema}
has resolved, regardless of source or of
suppressCreateContentPrompt
— informational, not a turn. Run ONCE per run — track
summaryPrinted
agent-internally; 1e's "local only" branch prints it before deploy-or-cancel, so a subsequent 7e must not re-trigger it.
Run when: 1e returned
{fqn, schema}
with non-null schema; 7e succeeded; 1e's drift-prompt "Deploy local to org" reached 7e; or 1e's "local only" branch before deploy-or-cancel. Apply the
summaryPrinted
gate.
Do NOT run when: user picked
Cancel
, 7b (deploy-later), any error path with no resolved schema, or
summaryPrinted === true
.
Print as chat text (NOT in
ask_user_tool
):
text
Content type "<fqn>" is ready. Schema:

| # | API name | Type | Required | Constraints | Title |
|---|---|---|---|---|---|
| 1 | `title` | `lightning__textType` | yes | maxLength: 200 | Title |
| 2 | `body`  | `lightning__richTextType` | yes | — | Body |
Column definitions, constraint rules, sort/truncation (20-property cap), do-not-print list →
references/schema-summary-format.md
.
Continue immediately to step 8 (no separate turn, no intermediate prompt).
只要
{fqn, schema}
已解析,无论来源如何或
suppressCreateContentPrompt
设置如何,都会执行本步骤 — 仅作信息展示,不占用回合。每次运行仅执行一次 — 在代理内部跟踪
summaryPrinted
;步骤1e的“仅本地存在”分支会在部署或取消前打印摘要,因此后续步骤7e不得重新触发。
在以下情况执行:步骤1e返回
{fqn, schema}
且schema非空;步骤7e部署成功;步骤1e的差异提示“将本地版本部署到组织”进入步骤7e;或步骤1e的“仅本地存在”分支在部署或取消前。受
summaryPrinted
控制。
在以下情况不执行:用户选择
取消
、步骤7b(稍后部署)、任何无已解析架构的错误路径,或
summaryPrinted === true
打印为聊天文本(请勿放入
ask_user_tool
):
text
内容类型“<fqn>”已就绪。架构如下:

| # | API名称 | 类型 | 必填 | 约束 | 标题 |
|---|---|---|---|---|---|
| 1 | `title` | `lightning__textType` | 是 | maxLength: 200 | 标题 |
| 2 | `body`  | `lightning__richTextType` | 是 | — | 正文 |
列定义、约束规则、排序/截断规则(最多20个属性)、禁止打印列表详见
references/schema-summary-format.md
立即继续进入步骤8(无需单独回合,无需中间提示)。

8. Trailing "create content?" prompt (gated by
suppressCreateContentPrompt
)

8. 末尾“创建内容?”提示(受
suppressCreateContentPrompt
控制)

Reached only from
success
— step 8 controls only whether an extra prompt is shown after it. Gate:
suppressCreateContentPrompt === true
→ skip entirely, emit
success
+
Task Completed
(the prompt would duplicate a turn the caller already drives). Otherwise run when success came via: 1e returned
{fqn, schema}
, 7e succeeded, or 1e drift-prompt "Deploy local to org" reached 7e. Do NOT run on
Cancel
(
cancelled
), 7b (
not_deployed
), or any error path (
error
).
Dispatch
ask_user_tool
with question
Would you like to create content using "<fqn>" now?
and options
Yes — create content now
/
No — I'm done
.
  • Yes
    → hand off to
    experience-cms-content-generate
    with
    { fqn, schema, suppressCreateContentPrompt: true }
    ; also pass
    intent: <residualIntent>
    when 1a captured one (e.g.
    create a news type and also create an article about our Q4 launch
    → forward
    create an article about our Q4 launch
    ). Omit
    intent
    when no residual. Don't loop back. Emit
    success
    +
    Task Completed
    .
  • No
    → print
    Done. FQN: <fqn>.
    , emit
    success
    ,
    Task Completed
    .
Do not run any command after step 8 resolves (Rule 4).
仅从
success
状态进入本步骤 — 步骤8仅控制是否在成功后展示额外提示。控制规则:
suppressCreateContentPrompt === true
→ 完全跳过,输出
success
+
Task Completed
(该提示会与调用方已驱动的回合重复)。否则,在以下成功场景执行:步骤1e返回
{fqn, schema}
、步骤7e部署成功、或步骤1e的差异提示“将本地版本部署到组织”进入步骤7e。请勿在
取消
cancelled
)、步骤7b(
not_deployed
)或任何错误路径(
error
)执行。
调度
ask_user_tool
,问题为
是否要立即使用“<fqn>”创建内容?
,选项为
是 — 立即创建内容
/
否 — 已完成
  • → 将控制权移交
    experience-cms-content-generate
    ,传入
    { fqn, schema, suppressCreateContentPrompt: true }
    ;若步骤1a捕获到
    residualIntent
    ,同时传入
    intent: <residualIntent>
    (如
    创建新闻类型并同时创建关于Q4发布的文章
    → 转发
    创建关于Q4发布的文章
    )。无残留意图时省略
    intent
    。请勿返回本技能。输出
    success
    +
    Task Completed
  • → 打印
    已完成。FQN:<fqn>。
    ,输出
    success
    ,然后输出
    Task Completed
步骤8决议后请勿执行任何命令(规则4)。

Schema rules (validator truth)

架构规则(验证器标准)

CMS deploy validator is source of truth. Full ruleset →
references/schema-rules.md
(root, per-field keys,
lightning:uiOptions
sharp edge, per-type accepted keys, quirks). Load before step 4 and step 6.
Also load
assets/schema-example.json
before step 4
— canonical shape reference, every supported
lightning:type
in default-minimal form. Do NOT use a sibling
schema.json
as reference just because step 1b/1e primed it in context — siblings carry user-specific constraints (
maxLength
,
lightning:localizable
, indexing) that would leak in without justification.
Non-negotiables: root has
unevaluatedProperties: false
(root only), no
$schema
; per-field only
title
/
description
/
lightning:type
/
lightning:uiOptions
+ the type's accepted keys; never
type
/
format
/
default
/ empty
lightning:uiOptions
; only
sfdc_cms:metadataContent
mixin.
CMS部署验证器为权威标准。完整规则集详见**
references/schema-rules.md
**(根节点、每个字段的键、
lightning:uiOptions
注意事项、每种类型允许的键、特殊情况)。执行步骤4和步骤6前加载该文件。
执行步骤4前还需加载
assets/schema-example.json
— 这是规范格式参考,包含所有支持的
lightning:type
的默认最小配置。请勿使用步骤1b/1e中加载的同级
schema.json
作为参考 — 同级文件包含用户特定的约束(如
maxLength
lightning:localizable
、索引设置),会无理由地引入到新架构中。
不可协商的规则:根节点包含
unevaluatedProperties: false
(仅根节点),无
$schema
;每个字段仅包含
title
/
description
/
lightning:type
/
lightning:uiOptions
+ 该类型允许的键;绝不使用
type
/
format
/
default
/空
lightning:uiOptions
;仅使用
sfdc_cms:metadataContent
混合类型。

Anti-patterns

反模式

Full anti-pattern table (violation / rationalization / correct action) →
references/anti-patterns.md
. If you catch yourself thinking one of the "bug thoughts" listed there, STOP — that thought is the bug.
完整反模式表(违规行为/合理化解释/正确操作)详见
references/anti-patterns.md
。若你发现自己产生表中列出的“错误思路”,请立即停止 — 该思路本身就是问题。

Notes

注意事项

  • Folder name,
    <masterLabel>
    , and the bundle's
    title
    should be consistent (PascalCase folder, human-readable label and title).
  • Avoid
    lightning__fileType
    and
    lightning__contentReferenceType
    — currently unsupported.
  • Eval datasets live in
    packages/adk-eval/eval/domains/experience-cms-content-type-generate/
    , not in
    tests/evals/
    .
  • 文件夹名称、
    <masterLabel>
    和包的
    title
    应保持一致(文件夹使用大驼峰式,标签和标题为人类可读格式)。
  • 避免使用
    lightning__fileType
    lightning__contentReferenceType
    — 目前不支持。
  • 评估数据集位于
    packages/adk-eval/eval/domains/experience-cms-content-type-generate/
    ,而非
    tests/evals/

Reference file index

参考文件索引

  • references/agent-checklist.md
    — mandatory progress checklist and tripwires.
  • references/schema-rules.md
    — validator ruleset (bundle root + per-field +
    lightning:uiOptions
    + per-type accepted keys + validator quirks).
  • references/pre-deploy-checklist.md
    — agent-internal schema sanity check before step 5.
  • references/deployment-errors.md
    — validator error → fix mapping (step 6).
  • references/anti-patterns.md
    — bug-thought catalogue.
  • references/discovery-details.md
    — rationale for 1b/1c/1d rules.
  • references/discovery-query-rules.md
    — single source of truth for how the
    search_metadata
    query is constructed. Referenced from step 1c here AND from the parent skill
    experience-cms-content-generate
    (as a drift-safety net).
  • references/retrieve-and-reconcile.md
    — step 1e reconciliation table and drift routing.
  • references/edit-fields-loop.md
    — step 3b edit-loop template and routing table.
  • references/schema-summary-format.md
    — step 7.5 column/sort/truncation rules.
  • assets/discovery-prompts.md
    — step 1d pick-list template + zero-matches variants.
  • assets/schema-example.json
    — reference schema covering every supported
    lightning:type
    .
  • references/agent-checklist.md
    — 必填进度检查清单和触发条件。
  • references/schema-rules.md
    — 验证器规则集(包根节点+每个字段+
    lightning:uiOptions
    +每种类型允许的键+验证器特殊情况)。
  • references/pre-deploy-checklist.md
    — 执行步骤5前代理内部的架构合理性检查清单。
  • references/deployment-errors.md
    — 验证器错误→修复映射(步骤6)。
  • references/anti-patterns.md
    — 错误思路汇总。
  • references/discovery-details.md
    — 步骤1b/1c/1d规则的原理。
  • references/discovery-query-rules.md
    search_metadata
    查询构建的唯一权威标准。本步骤1c和父技能
    experience-cms-content-generate
    (作为差异安全网)均引用该文件。
  • references/retrieve-and-reconcile.md
    — 步骤1e的协调表和差异路由规则。
  • references/edit-fields-loop.md
    — 步骤3b编辑循环模板和路由表。
  • references/schema-summary-format.md
    — 步骤7.5的列/排序/截断规则。
  • assets/discovery-prompts.md
    — 步骤1d选择列表模板+无匹配结果变体。
  • assets/schema-example.json
    — 包含所有支持的
    lightning:type
    的参考架构。