dx-org-analyze
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTool Restrictions
工具限制
Use ONLY the Bash tool to execute all CLI commands and Python scripts. Always include for commands. Do NOT use tools.
sf--jsonsfmcp__salesforce_dx__*Output artifacts for eval/testing: When an output directory is available, write results there. After executing the skill: (1) if the user specified an output path, write there immediately; (2) otherwise run to detect the eval directory; (3) write the full JSON result to and the markdown report to .
[ -d force-app/main/adk-eval-output/ ] && echo 'force-app/main/adk-eval-output'<output-dir>/dx-org-analyze-result.json<output-dir>/dx-org-analyze-result.md仅使用 Bash 工具来执行所有 CLI 命令和 Python 脚本。 命令始终包含 。不要使用 工具。
sfsf--jsonmcp__salesforce_dx__*用于评估/测试的输出产物: 当有输出目录时,将结果写入该目录。执行技能后:(1)如果用户指定了输出路径,立即写入;(2)否则运行 检测评估目录;(3)将完整 JSON 结果写入 ,并将 Markdown 报告写入 。
[ -d force-app/main/adk-eval-output/ ] && echo 'force-app/main/adk-eval-output'<output-dir>/dx-org-analyze-result.json<output-dir>/dx-org-analyze-result.mdData Access Hierarchy
数据访问层级
When querying org data, always follow this priority order:
- SF CLI commands — Preferred. Use ,
sf org list metadata-types,sf org list metadata,sf org display,sf data query, etc.sf limits api display - Direct REST/Tooling API calls — Last resort, only when SF CLI cannot provide the data.
Never bypass this hierarchy. If an SF CLI command exists for the operation, use it even if a direct API call would be simpler.
查询组织数据时,始终遵循以下优先级:
- SF CLI 命令 — 首选。使用 、
sf org list metadata-types、sf org list metadata、sf org display、sf data query等。sf limits api display - 直接 REST/Tooling API 调用 — 最后手段,仅当 SF CLI 无法提供数据时。
切勿绕过此层级。如果存在适用于该操作的 SF CLI 命令,即使直接 API 调用更简单,也应使用它。
Authentication Rules
认证规则
- All authentication MUST go through SF CLI (,
sf org login web,sf org login jwt).sf org login access-token - Never accept raw credentials (username + password), session IDs, or access tokens directly from the user.
- The collection script obtains its access token exclusively via .
sf org display --json
- 所有认证必须通过 SF CLI(、
sf org login web、sf org login jwt)。sf org login access-token - 切勿直接接受用户的原始凭据(用户名 + 密码)、会话 ID 或访问令牌。
- 收集脚本仅通过 获取其访问令牌。
sf org display --json
Workflow
工作流程
Step 0: List Authenticated Orgs
步骤 0:列出已认证的 Org
Run this command to discover all authenticated orgs:
bash
sf org list --json --skip-connection-statusParse the JSON output. Collect orgs from all buckets (, , , , ). Present authenticated orgs in a readable table:
devHubsnonScratchOrgsscratchOrgssandboxesother| # | Alias | Username | Instance URL | Org ID | Type |
|---|
If fewer than 2 orgs are authenticated but at least 1 is available, offer the single-org introspect mode (see Introspect Workflow below). If no orgs are authenticated, STOP and advise:
You need at least 1 authenticated org. Runto authenticate.sf org login web --alias <name>
If the user explicitly requests a single-org introspection or inventory, use the Introspect Workflow regardless of how many orgs are available.
运行此命令以发现所有已认证的 org:
bash
sf org list --json --skip-connection-status解析 JSON 输出。从所有桶(、、、、)中收集 org。以可读表格形式展示已认证的 org:
devHubsnonScratchOrgsscratchOrgssandboxesother| # | 别名 | 用户名 | 实例 URL | Org ID | 类型 |
|---|
如果已认证的 org 少于 2 个但至少有 1 个可用,提供单组织内省模式(参见下方内省工作流程)。如果没有已认证的 org,则停止并建议:
您至少需要 1 个已认证的 org。运行进行认证。sf org login web --alias <name>
如果用户明确请求单组织内省或清单,无论有多少个可用 org,均使用内省工作流程。
Step 1: User Selects Two Orgs
步骤 1:用户选择两个 Org
Ask the user to select two orgs from the list. Both must be explicitly named — do NOT allow implicit/default orgs.
Select two orgs to compare. Which is the source (reference/expected state)? Which is the target (to compare against)?
Accept: alias, username, or number from the list. Resolve each selection to a concrete username. If an org lacks an alias, prompt the user to assign one. Confirm:
Comparing:
- Source:
(<alias>)<username>- Target:
(<alias>)<username>
要求用户从列表中选择两个 org。两者都必须明确命名——不允许隐式/默认 org。
选择两个 org 进行比较。哪个是源(参考/预期状态)?哪个是目标(待比较对象)?
接受:别名、用户名或列表中的编号。将每个选择解析为具体的用户名。如果 org 缺少别名,提示用户分配一个。确认:
比较:
- 源:
(<alias>)<username>- 目标:
(<alias>)<username>
Step 2: Validate Connectivity
步骤 2:验证连接
For each org, confirm reachability with a lightweight query that does not expose secrets:
bash
sf data query --target-org <alias-or-username> --query "SELECT Id FROM Organization LIMIT 1" --jsonIf the query succeeds (exit 0 and a record is returned), the org is connected. If it fails with or auth errors:
INVALID_SESSION_IDbash
sf org login web --alias <alias>对于每个 org,使用不会泄露机密的轻量查询确认可达性:
bash
sf data query --target-org <alias-or-username> --query "SELECT Id FROM Organization LIMIT 1" --json如果查询成功(退出码 0 且返回一条记录),则 org 已连接。如果失败并出现 或认证错误:
INVALID_SESSION_IDbash
sf org login web --alias <alias>Step 3: Collect Data (per org)
步骤 3:收集数据(每个 org)
Generate a unique run ID and run the collection script for each org:
bash
RUN_ID=$(date +%Y%m%d-%H%M%S)
python3 ./scripts/collect_org_data.py \
--org-alias "$SOURCE_ORG" \
--output /tmp/dx-org-comparison-${RUN_ID}-source
python3 ./scripts/collect_org_data.py \
--org-alias "$TARGET_ORG" \
--output /tmp/dx-org-comparison-${RUN_ID}-targetExit codes: = success, = fatal error (report stderr to user), = session expired (re-authenticate Step 2 and retry).
012For details on what the collection script gathers, see .
references/collection-details.md生成唯一的运行 ID 并为每个 org 运行收集脚本:
bash
RUN_ID=$(date +%Y%m%d-%H%M%S)
python3 ./scripts/collect_org_data.py \
--org-alias "$SOURCE_ORG" \
--output /tmp/dx-org-comparison-${RUN_ID}-source
python3 ./scripts/collect_org_data.py \
--org-alias "$TARGET_ORG" \
--output /tmp/dx-org-comparison-${RUN_ID}-target退出码: = 成功, = 致命错误(向用户报告 stderr), = 会话过期(重新认证步骤 2 并重试)。
012有关收集脚本收集内容的详细信息,请参阅 。
references/collection-details.mdStep 4: Compute Diff and Report
步骤 4:计算差异和报告
bash
python3 ./scripts/compute_diff.py \
--org-a /tmp/dx-org-comparison-${RUN_ID}-source \
--org-b /tmp/dx-org-comparison-${RUN_ID}-target \
--output /tmp/dx-org-comparison-${RUN_ID} \
--format both \
--org-a-label "Source" \
--org-b-label "Target"Use if the user wants shared components listed in detail.
--show-sharedbash
python3 ./scripts/compute_diff.py \
--org-a /tmp/dx-org-comparison-${RUN_ID}-source \
--org-b /tmp/dx-org-comparison-${RUN_ID}-target \
--output /tmp/dx-org-comparison-${RUN_ID} \
--format both \
--org-a-label "Source" \
--org-b-label "Target"如果用户希望详细列出共享组件,请使用 。
--show-sharedStep 5: Present Results
步骤 5:呈现结果
Read and present to the user. If the user asks follow-up questions, use for data lookups. Then resolve the output directory and copy both files there:
/tmp/dx-org-comparison-${RUN_ID}.md/tmp/dx-org-comparison-${RUN_ID}.jsonbash
OUTPUT_DIR=""
if [ -n "$USER_OUTPUT_PATH" ]; then
OUTPUT_DIR="$USER_OUTPUT_PATH"
elif [ -d "force-app/main/adk-eval-output" ]; then
OUTPUT_DIR="force-app/main/adk-eval-output"
fi
if [ -n "$OUTPUT_DIR" ]; then
cp /tmp/dx-org-comparison-${RUN_ID}.json "$OUTPUT_DIR/dx-org-analyze-result.json"
cp /tmp/dx-org-comparison-${RUN_ID}.md "$OUTPUT_DIR/dx-org-analyze-result.md"
fi读取 并呈现给用户。如果用户提出后续问题,请使用 进行数据查询。然后解析输出目录并将两个文件复制到那里:
/tmp/dx-org-comparison-${RUN_ID}.md/tmp/dx-org-comparison-${RUN_ID}.jsonbash
OUTPUT_DIR=""
if [ -n "$USER_OUTPUT_PATH" ]; then
OUTPUT_DIR="$USER_OUTPUT_PATH"
elif [ -d "force-app/main/adk-eval-output" ]; then
OUTPUT_DIR="force-app/main/adk-eval-output"
fi
if [ -n "$OUTPUT_DIR" ]; then
cp /tmp/dx-org-comparison-${RUN_ID}.json "$OUTPUT_DIR/dx-org-analyze-result.json"
cp /tmp/dx-org-comparison-${RUN_ID}.md "$OUTPUT_DIR/dx-org-analyze-result.md"
fiIntrospect Workflow (Single-Org Mode)
内省工作流程(单组织模式)
Use this workflow when the user wants to inspect a single org's configuration, or when only one org is authenticated.
当用户想要检查单个 org 的配置,或仅有一个 org 已认证时,使用此工作流程。
Introspect Step 1: Validate Connectivity
内省步骤 1:验证连接
bash
sf data query --target-org <alias-or-username> --query "SELECT Id FROM Organization LIMIT 1" --jsonbash
sf data query --target-org <alias-or-username> --query "SELECT Id FROM Organization LIMIT 1" --jsonIntrospect Step 2: Collect Data
内省步骤 2:收集数据
bash
RUN_ID=$(date +%Y%m%d-%H%M%S)
python3 ./scripts/collect_org_data.py \
--org-alias "$ORG" \
--output /tmp/dx-org-analysis-${RUN_ID}bash
RUN_ID=$(date +%Y%m%d-%H%M%S)
python3 ./scripts/collect_org_data.py \
--org-alias "$ORG" \
--output /tmp/dx-org-analysis-${RUN_ID}Introspect Step 3: Generate Report
内省步骤 3:生成报告
bash
python3 ./scripts/introspect_org.py \
--org /tmp/dx-org-analysis-${RUN_ID} \
--output /tmp/dx-org-analysis-${RUN_ID} \
--format both \
--label "OrgName"bash
python3 ./scripts/introspect_org.py \
--org /tmp/dx-org-analysis-${RUN_ID} \
--output /tmp/dx-org-analysis-${RUN_ID} \
--format both \
--label "OrgName"Introspect Step 4: Present Results
内省步骤 4:呈现结果
Read and present to the user. The report covers: metadata inventory, org settings, org limits, installed packages, licenses, system permissions, and deep data records. Then resolve the output directory and copy both files there:
/tmp/dx-org-analysis-${RUN_ID}.mdbash
OUTPUT_DIR=""
if [ -n "$USER_OUTPUT_PATH" ]; then
OUTPUT_DIR="$USER_OUTPUT_PATH"
elif [ -d "force-app/main/adk-eval-output" ]; then
OUTPUT_DIR="force-app/main/adk-eval-output"
fi
if [ -n "$OUTPUT_DIR" ]; then
cp /tmp/dx-org-analysis-${RUN_ID}.json "$OUTPUT_DIR/dx-org-analyze-result.json"
cp /tmp/dx-org-analysis-${RUN_ID}.md "$OUTPUT_DIR/dx-org-analyze-result.md"
fi读取 并呈现给用户。报告涵盖:元数据清单、组织设置、组织限制、已安装包、许可、系统权限和深度数据记录。然后解析输出目录并将两个文件复制到那里:
/tmp/dx-org-analysis-${RUN_ID}.mdbash
OUTPUT_DIR=""
if [ -n "$USER_OUTPUT_PATH" ]; then
OUTPUT_DIR="$USER_OUTPUT_PATH"
elif [ -d "force-app/main/adk-eval-output" ]; then
OUTPUT_DIR="force-app/main/adk-eval-output"
fi
if [ -n "$OUTPUT_DIR" ]; then
cp /tmp/dx-org-analysis-${RUN_ID}.json "$OUTPUT_DIR/dx-org-analyze-result.json"
cp /tmp/dx-org-analysis-${RUN_ID}.md "$OUTPUT_DIR/dx-org-analyze-result.md"
fiReport Structure
报告结构
The generated report includes:
- Drift Score — Weighted overall score (60% metadata, 30% permissions, 10% profiles) with severity level (LOW/MODERATE/HIGH/CRITICAL)
- Summary Statistics — Counts per metadata type with Identical/Different columns from deep data
- Metadata Components by Type — Only-in-Source, only-in-Target, shared per type
- Profiles — Shared, source-only, target-only
- Installed Packages — Version comparison, only-in-Source, only-in-Target
- Package Components — Namespaced components grouped by namespace
- Org Permissions — Boolean enabled/disabled diffs by category, plus value diffs
- System Permissions — PermissionsXxx fields on PermissionSet, per-set diffs
- Org Values & Limits — Grouped by Identity, Storage, API, Feature Limits
- Licenses — User, Permission Set, Package license quantity diffs
- Deep Data — Content-level diffs for Apex, Flows, Validation Rules, Custom Fields, etc.
生成的报告包括:
- 漂移评分 — 加权总分(60% 元数据、30% 权限、10% 配置文件),带严重级别(低/中/高/严重)
- 摘要统计 — 每种元数据类型的计数,包含来自深度数据的相同/不同列
- 按类型划分的元数据组件 — 仅源有、仅目标有、按类型共享
- 配置文件 — 共享、仅源、仅目标
- 已安装包 — 版本比较、仅源、仅目标
- 包组件 — 按命名空间分组的命名空间组件
- 组织权限 — 按类别划分的布尔启用/禁用差异,以及值差异
- 系统权限 — PermissionSet 上的 PermissionsXxx 字段,按集合差异
- 组织值和限制 — 按身份、存储、API、功能限制分组
- 许可 — 用户、权限集、包许可数量差异
- 深度数据 — Apex、Flow、验证规则、自定义字段等的内容级差异
Rules / Constraints
规则 / 约束
| Constraint | Rationale |
|---|---|
Always use | Structured output for reliable parsing |
| Resolve orgs to usernames, not aliases | Aliases can be ambiguous; usernames are unique |
| Skip expired and disconnected orgs | Cannot query metadata from inaccessible orgs |
| Read-only — never deploy or modify | This skill compares only, never mutates either org |
| SF CLI auth only | All authentication through SF CLI credential store |
| Both orgs must be explicit | Never compare unnamed or implicit/default orgs |
| 约束 | 理由 |
|---|---|
始终对 sf 命令使用 | 结构化输出,便于可靠解析 |
| 将 org 解析为用户名,而非别名 | 别名可能有歧义;用户名是唯一的 |
| 跳过过期和断开的 org | 无法从未知 org 查询元数据 |
| 只读——绝不部署或修改 | 此技能仅比较,绝不更改任一 org |
| 仅 SF CLI 认证 | 所有认证都通过 SF CLI 凭据存储 |
| 两个 org 必须明确 | 绝不比较未命名或隐式/默认 org |
Troubleshooting
故障排除
| Issue | Resolution |
|---|---|
| "No org found for <alias>" | Org not authenticated — run |
| Fewer than 2 authenticated orgs | Authenticate additional orgs before comparing |
| "INVALID_SESSION_ID" or auth errors | Session expired — re-run |
| Collection script exits with code 2 | Session expired — re-authenticate and retry |
| API limit errors during metadata listing | Use |
| Edition differences (DE vs EE) | Many differences are edition-inherent, not configuration drift |
| Large orgs timeout on deep data | Use |
| 问题 | 解决方法 |
|---|---|
"未找到 org | org 未认证——运行 |
| 已认证 org 少于 2 个 | 在比较之前认证更多 org |
| "INVALID_SESSION_ID" 或认证错误 | 会话过期——重新运行 |
| 收集脚本退出代码 2 | 会话过期——重新认证并重试 |
| 元数据列表期间出现 API 限制错误 | 使用 |
| 版本差异(DE 与 EE) | 许多差异是版本固有的,而非配置漂移 |
| 大型 org 在深度数据上超时 | 使用 |
Cross-Skill Integration
跨技能集成
| Need | Delegate to |
|---|---|
| Retrieve specific metadata from an org | |
| Deploy metadata to an org | |
| Create a scratch org for comparison | |
| Switch default org after comparison | |
| 需求 | 委托给 |
|---|---|
| 从 org 检索特定元数据 | |
| 将元数据部署到 org | |
| 创建用于比较的 scratch org | |
| 比较后切换默认 org | |
Reference File Index
参考文件索引
| File | When to read |
|---|---|
| For details on what the collection script gathers and how |
| For drift score formula and report section details |
| Data collection script (per org) |
| Diff computation and report generation script |
| Single-org introspection report script |
| 文件 | 何时阅读 |
|---|---|
| 了解收集脚本收集什么以及如何收集 |
| 了解漂移评分公式和报告部分细节 |
| 数据收集脚本(每个 org) |
| 差异计算和报告生成脚本 |
| 单组织内省报告脚本 |