dx-apexguru-scan
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseApexGuru Performance Scan Skill
ApexGuru 性能扫描技能
CRITICAL: Mandatory Script Usage
重要提示:必须使用指定脚本
Every step — token resolution, zipping, API calls, and report decoding — MUST go
through the bundled scripts in . No exceptions.
<skill_dir>/scripts/每一个步骤——令牌解析、打包ZIP、API调用和报告解码——必须通过目录下的捆绑脚本执行,无例外。
<skill_dir>/scripts/WRONG — never do this:
错误示例——切勿这样做:
bash
undefinedbash
undefinedWRONG: hand-rolled curl to the API
错误:手动编写curl调用API
curl -X POST https://api.salesforce.com/... -F file=@x.zip
curl -X POST https://api.salesforce.com/... -F file=@x.zip
WRONG: inline base64 + jq to read the report
错误:直接使用base64 + jq读取报告
cat raw.json | jq -r .report | base64 -d | jq '.[]'
cat raw.json | jq -r .report | base64 -d | jq '.[]'
WRONG: reading the raw result file directly (report is a large base64 blob)
错误:直接读取原始结果文件(报告是大型Base64 blob)
Read tool → apexguru-raw-*.json
Read tool → apexguru-raw-*.json
WRONG: inline node/python to parse violations
错误:直接用node/python解析违规内容
node -e "const r = require('./raw.json'); ..."
undefinednode -e "const r = require('./raw.json'); ..."
undefinedRIGHT — always do this:
正确示例——务必这样做:
bash
undefinedbash
undefinedPREFERRED — one command runs all three steps (package → submit+poll →
推荐:一条命令完成所有三个步骤(打包→提交+轮询→解码+展示),最终在标准输出中打印可直接展示的报告。
decode+present) and prints the ready-to-show report as its final stdout.
初始扫描请使用该命令:它不会中途中断。
Use this for every initial scan: it cannot be left half-finished.
—
bash "<skill_dir>/scripts/scan.sh" "<project-root>"
bash "<skill_dir>/scripts/scan.sh" "<project-root>"
Optionally persist the presented markdown to a file as well:
可选:同时将生成的Markdown报告保存到文件中:
bash "<skill_dir>/scripts/scan.sh" "<project-root>" --out ./apexguru-report.md
The three underlying scripts still exist and `scan.sh` calls them in order.
Invoke them individually only for **drill-downs on an already-scanned result**
(Step 5), or when you deliberately need to inspect an intermediate artifact:
```bashbash "<skill_dir>/scripts/scan.sh" "<project-root>" --out ./apexguru-report.md
三个底层脚本仍然存在,`scan.sh`会按顺序调用它们。仅在以下场景单独调用它们:**对已扫描结果进行深入分析**(步骤5),或者需要检查中间产物时:
```bashEquivalent manual chain (scan.sh runs exactly these, in this order):
等效的手动执行流程(scan.sh完全按此顺序运行):
bash "<skill_dir>/scripts/build-zip.sh" "<project-root>" "./apexguru-<TS>.zip"
bash "<skill_dir>/scripts/run-scan.sh" "./apexguru-<TS>.zip" "./apexguru-raw-<TS>.json"
node "<skill_dir>/scripts/decode-report.js" "./apexguru-raw-<TS>.json" --present
bash "<skill_dir>/scripts/build-zip.sh" "<project-root>" "./apexguru-<TS>.zip"
bash "<skill_dir>/scripts/run-scan.sh" "./apexguru-<TS>.zip" "./apexguru-raw-<TS>.json"
node "<skill_dir>/scripts/decode-report.js" "./apexguru-raw-<TS>.json" --present
Drill into a subset WITHOUT re-scanning (reuse the raw file scan.sh left, or
不重新扫描的情况下深入分析子集(复用scan.sh生成的原始文件,或给scan.sh添加--raw参数将其保存到指定路径):
pass --raw to scan.sh to keep it at a known path):
—
node "<skill_dir>/scripts/decode-report.js" "./apexguru-raw-<TS>.json" --rule SOQL_IN_LOOP --full
node "<skill_dir>/scripts/decode-report.js" "./apexguru-raw-<TS>.json" --group file --top 5
`<skill_dir>` is the absolute path to the directory containing this SKILL.md.
**Never** use `./scripts/` — that resolves against the user's CWD, not the skill dir.
Any filter/rank/group question ("which file has the most issues?", "show only
SOQL-in-loop", "break down by severity") is answered by re-running
`decode-report.js` with flags against the **same raw result file** — never re-scan,
never parse the JSON by hand.
---node "<skill_dir>/scripts/decode-report.js" "./apexguru-raw-<TS>.json" --rule SOQL_IN_LOOP --full
node "<skill_dir>/scripts/decode-report.js" "./apexguru-raw-<TS>.json" --group file --top 5
`<skill_dir>`是包含此SKILL.md文件的绝对路径。**切勿**使用`./scripts/`——它会解析为用户的当前工作目录,而非技能目录。
任何过滤/排序/分组请求(如“哪个文件的问题最多?”、“仅显示循环中的SOQL”、“按严重程度分类”)都应通过对**同一原始结果文件**重新运行带参数的`decode-report.js`来处理——切勿重新扫描,切勿手动解析JSON。
---CRITICAL: Present --present
output verbatim — never condense it
--present重要提示:原样展示--present
的输出——切勿精简
--presentdecode-report.js --present--presentThe attribution is already in that stdout — the summary line is the exact
output that states the mode (e.g. "ApexGuru (static analysis) is active. To
unlock runtime intelligence…"). Do NOT prepend or append your own attribution sentence
(no "Attribution: analysisMode: static…", no naming the org, no restating
"static-only findings"). The script's line is the complete, approved wording;
adding your own makes the output non-deterministic and off-message.
decode-report.js --present--present归属信息已包含在该标准输出中——汇总行明确标注了模式(例如“ApexGuru (static analysis) is active. To unlock runtime intelligence…”)。请勿添加自己的归属语句(不要写“归属:analysisMode: static…”,不要提及组织名称,不要重复“仅静态分析结果”)。脚本生成的行是完整且经过批准的表述;添加自定义内容会导致输出非确定性且偏离规范。
WRONG — never do this:
错误示例——切勿这样做:
text
Top Issues (worst first)text
Top Issues (worst first)Severity Rule Method Line
Severity Rule Method Line
1 Major UsingTheTestMethodKeyword legacy... 136
...
Key Antipatterns Detected:
- SOQL/DML in loops (3 violations)
*(a hand-built summary that drops every message/code/fix — even for
violations that had one)*
```text
Attribution: analysisMode: static — source-only analysis. The scanned org
(ag-skills-org) is not onboarded to ApexGuru's full runtime metrics, so
these are static-only findings.(an agent-authored attribution line prepended to the report — the script's
own summary line already states the mode; this duplicate is non-deterministic
and names an org the script never had access to)
1 Major UsingTheTestMethodKeyword legacy... 136
...
Key Antipatterns Detected:
- SOQL/DML in loops (3 violations)
*(手动构建的汇总,丢弃了所有消息/代码/修复方案——即使违规项包含这些内容)*
```text
归属:analysisMode: static — 仅基于源代码的分析。扫描的组织(ag-skills-org)未接入ApexGuru的完整运行时指标,因此这些是仅静态分析的结果。(由助手添加的归属语句,放在报告前——脚本自身的汇总行已标注模式;此重复内容非确定性且提及了脚本无法访问的组织名称)
RIGHT — always do this:
正确示例——务必这样做:
Paste the full stdout from — every
card and the closing table — unedited, in one response.
decode-report.js --present### Issue N## Summary粘贴的完整标准输出——包括所有卡片和结尾的表格——未经编辑,一次性返回给用户。
decode-report.js --present### Issue N## SummaryOverview
概述
ApexGuru detects performance antipatterns in Apex (SOQL/DML in loops,
, SOQL without /, unused SOQL fields).
This skill drives the ApexGuru SFAP Scan API: it packages the user's Apex
(every / under the project root, any layout) into a zip, submits
it, polls until the scan finishes, decodes the base64-encoded report, and
presents violations grouped by rule with severity, , and suggested
fixes.
Schema.getGlobalDescribe()WHERELIMIT.cls.triggerfile:lineAttribution is mandatory. The API returns :
analysisMode- → source-only analysis → label results "Static only".
static - → enriched with runtime metrics from an org onboarded to ApexGuru → label results "Production insights".
full
decode-report.js --presentfullstaticIn scope: zipping a project's Apex, submitting/polling the scan, decoding + presenting
violations, filtering/grouping existing results, troubleshooting API errors.
Out of scope: general static analysis / security / lint (→ ,
which lists ApexGuru as an engine), applying fixes to code, onboarding an org to
ApexGuru, minting SFAP tokens.
dx-code-analyzer-runApexGuru检测Apex代码中的性能反模式(循环中的SOQL/DML、、无/的SOQL、未使用的SOQL字段)。该技能调用ApexGuru SFAP Scan API:将用户的Apex代码(项目根目录下所有/文件,任意目录结构)打包为ZIP,提交扫描请求,轮询直至扫描完成,解码Base64编码的报告,并按规则分组展示违规情况,包括严重程度、以及建议修复方案。
Schema.getGlobalDescribe()WHERELIMIT.cls.triggerfile:line归属信息是必填项。API会返回:
analysisMode- → 仅基于源代码的分析 → 将结果标注为**“仅静态分析”**。
static - → 结合已接入ApexGuru的组织的运行时指标 → 将结果标注为**“生产环境洞察”**。
full
decode-report.js --presentfullstatic适用范围:打包项目的Apex代码、提交并轮询扫描、解码并展示违规情况、过滤/分组现有结果、排查API错误。
不适用范围:通用静态分析/安全检查/代码规范检查(→ 使用,其中ApexGuru作为引擎之一)、直接修复代码、将组织接入ApexGuru、生成SFAP令牌。
dx-code-analyzer-runPrerequisites
前置条件
- An authenticated CLI org (
sf).sf org login web ...derives the SFAP JWT from it viaresolve-token.sh— this is the normal IDE-session path. Alternatively, set<instanceUrl>/ide/auth/APEXGURU_SFAP_TOKENto supply a JWT directly (CI/headless). The org is derived from the token'sAPEXGURU_SFAP_TOKEN_FILEclaim — no org id is passed. Passtnkto pick a specific org. See--org <alias>. If no token can be resolved, the script returns a clear error with a hint.<skill_dir>/references/authentication.md - ,
sf,bash,curl,zip,jqon PATH (standard on macOS/Linux dev boxes).node - A folder containing Apex — an sfdx project, a subtree, or any folder with
force-app//.clsfiles..triggercollects all Apex beneath it regardless of layout; the API walks the whole archive.build-zip.sh
- 已认证的CLI组织(
sf)。sf org login web ...通过resolve-token.sh从该组织获取SFAP JWT——这是IDE会话的常规路径。或者,直接设置<instanceUrl>/ide/auth/APEXGURU_SFAP_TOKEN环境变量提供JWT(适用于CI/无头环境)。组织信息从令牌的APEXGURU_SFAP_TOKEN_FILE声明中获取——无需传递组织ID。添加tnk参数可指定特定组织。详情请见--org <alias>。如果无法解析令牌,脚本会返回清晰的错误提示。<skill_dir>/references/authentication.md - **、
sf、bash、curl、zip、jq**已添加到PATH中(macOS/Linux开发环境默认已包含)。node - 包含Apex代码的文件夹——可以是sfdx项目、子目录,或任何包含
force-app//.cls文件的文件夹。.trigger会收集该文件夹下所有Apex代码,无论目录结构如何;API会遍历整个压缩包。build-zip.sh
Workflow
工作流程
Step 1: Identify the project root
步骤1:确定项目根目录
The project root is any folder that contains Apex somewhere beneath it
(usually an sfdx project root next to , but a
subtree or a loose folder of files works too). If the user gave a path,
use it; otherwise use the current working directory. collects
every / under it (any layout) and fails clearly if none exists.
sfdx-project.jsonforce-app/.clsbuild-zip.sh.cls.trigger项目根目录是任何在其下包含Apex代码的文件夹(通常是所在的sfdx项目根目录,但子目录或零散的文件文件夹也可以)。如果用户提供了路径,则使用该路径;否则使用当前工作目录。会收集该目录下所有/文件(任意目录结构),如果未找到则会明确报错。
sfdx-project.jsonforce-app/.clsbuild-zip.sh.cls.triggerStep 2: Package the project
步骤2:打包项目
bash
TS=$(date +%Y%m%d-%H%M%S)
bash "<skill_dir>/scripts/build-zip.sh" "<project-root>" "./apexguru-${TS}.zip"Output JSON gives , , , , . The script enforces
the 200MB compressed limit and fails fast if exceeded. On error (/
fields), relay the hint and stop.
zipbyteshumanSizeapexFileCountscanRooterrorhintbash
TS=$(date +%Y%m%d-%H%M%S)
bash "<skill_dir>/scripts/build-zip.sh" "<project-root>" "./apexguru-${TS}.zip"输出JSON包含、、、、字段。脚本会强制执行压缩后200MB的限制,如果超出则立即报错。如果返回错误(包含/字段),请传达提示信息并停止操作。
zipbyteshumanSizeapexFileCountscanRooterrorhintStep 3: Submit and poll
步骤3:提交并轮询扫描
bash
bash "<skill_dir>/scripts/run-scan.sh" "./apexguru-${TS}.zip" "./apexguru-raw-${TS}.json"- Add if the user wants a quicker/cheaper run (skips LLM-heavy fix generation).
--fast - The endpoint follows the token's environment — the base URL is derived
from the token's claim: a prod org hits
tnk, and an internal stage/dev org hitsapi.salesforce.com/stage.. Customers authenticate a prod org, so they always hit prod; no extra flags or config.dev.api.salesforce.com - picks which authenticated
--org <alias>org the JWT is derived from (omit to use the CLI's default org).sf - Progress () streams to stderr; the script polls ~every 15s. Default ceiling is 10 min (
QUEUED → RUNNING → SUCCEEDED,--max-pollsto adjust).--interval - On success, stdout is a one-line JSON summary and the full raw body is written to
. On failure, stdout is
apexguru-raw-${TS}.json— relay the hint. For status-code specifics see{error, httpStatus, status, hint}.<skill_dir>/references/error-handling.md - Foreground only. Do not background this; polling output must be observed.
- A SUCCEEDED scan is not the finish line. The raw result is a base64 blob, not a user-facing answer. Do not stop or report "done" after the scan succeeds — you MUST continue to Step 4 to decode and present the report. Ending the turn at Step 3 leaves the user with nothing readable.
bash
bash "<skill_dir>/scripts/run-scan.sh" "./apexguru-${TS}.zip" "./apexguru-raw-${TS}.json"- 如果用户希望更快/更轻量的扫描(跳过LLM生成修复方案的步骤),添加参数。
--fast - 端点地址由令牌的环境决定——基础URL从令牌的声明中获取:生产组织访问
tnk,内部测试/开发组织访问api.salesforce.com/stage.。客户认证生产组织,因此始终访问生产环境;无需额外参数或配置。dev.api.salesforce.com - 参数指定从哪个已认证的
--org <alias>组织获取JWT(省略则使用CLI的默认组织)。sf - 扫描进度()会输出到标准错误流;脚本大约每15秒轮询一次。默认超时时间为10分钟(可通过
QUEUED → RUNNING → SUCCEEDED、--max-polls参数调整)。--interval - 成功时,标准输出为单行JSON汇总,完整的原始响应会写入文件。失败时,标准输出为
apexguru-raw-${TS}.json——请传达提示信息。状态码详情请见{error, httpStatus, status, hint}。<skill_dir>/references/error-handling.md - 仅在前台运行。请勿后台运行;必须观察轮询输出。
- 扫描成功并不代表完成。原始结果是Base64 blob,并非面向用户的可读内容。扫描成功后请勿停止操作或报告“完成”——必须继续执行步骤4来解码并展示报告。在步骤3结束会导致用户无法获取可读结果。
Step 4: Decode and present
步骤4:解码并展示
bash
node "<skill_dir>/scripts/decode-report.js" "./apexguru-raw-${TS}.json" --present--present--fullanalysisMode: full### Issue N--top## SummaryExpensiveMethodsfullFor Step 5 drill-downs (filtering/grouping an existing result), the bare
(non-) JSON form is fine — see the reading rules below, which apply
whenever you run the script without .
--present--presentDO NOT: invent script code, use bare paths, decode base64
inline, the field, or Read the raw file directly.
./scripts/...jqreportbash
node "<skill_dir>/scripts/decode-report.js" "./apexguru-raw-${TS}.json" --present--present--fullanalysisMode: full### Issue N--top## SummaryExpensiveMethodsfull对于步骤5的深入分析(过滤/分组现有结果),可以使用不带参数的纯JSON输出——请遵循以下读取规则,适用于所有不带参数的脚本运行场景。
--present--present请勿:自行编写脚本代码、使用相对路径、直接解码Base64、使用处理字段、直接读取原始文件。
./scripts/...jqreportInstructions for reading bare (non---present
) decode-report.js
output
--presentdecode-report.js读取不带--present
参数的decode-report.js
输出的说明
--presentdecode-report.jsThe command prints one JSON object to stdout. Read it field by field before
presenting anything — do not eyeball a partial view as complete:
- Check first, before anything else. If
truncated,truewas capped to the topgroups(default 10) rules, each group's--topwas capped to 3 items, andsamplewas capped totopViolationsitems. Never present a--topresult as the full picture. Re-run the same command withtruncated:trueappended and use that output instead. Only skip this if the user explicitly asked for a quick/partial look.--full - State attribution from /
analysisMode—attribution/"Static only" orstatic/"Production insights". This is mandatory on every response, per "Attribution is mandatory" above.full - is the raw API's internal rule-code tally (e.g.
serverViolationBreakdown,SOQL_IN_LOOP_1HOP) — it's a sanity-check total (sums toGGD), not a display name. Never show these codes to the user; use the human-readableviolationCountnames instead (e.g.groups[].key,SoqlInALoopOneHop).SchemaGetGlobalDescribeNotEfficient - (top-level) is the severity distribution across ALL violations — use it for the summary table. Each
severityCountsentry has its owngroups[]scoped to just that rule.severityCounts - Build the "Violations by Rule" table from , one row per entry:
groups→ Rule,key→ Count,count→ Severity, and oneseverityCounts(orsample[0]whenitems[0]) → Example (--full).file:line - Build the "Top Issues" table from — already sorted worst-severity-first. Use
topViolations,rule,severity, and the first entry offile:line(if non-empty) as Suggested Fix. Iffixesis empty, omit that column's value rather than inventing a fix.fixes - When the user asks to explain a specific violation ("what does this
mean", "why is this flagged"), surface that violation's (plain- language why) and
message(Help Doc URL) verbatim — both exist on every violation object but are intentionally left out of the summary tables in step 5/6 to keep those scannable. Fall back toresources[0]only ifreferences/violation-catalog.mdis empty.message - being
fixesis expected, not an error — the API's[]field (fix code) isn't populated for every rule (notablysuggestions, a CPU ranking with no single-line fix); don't say "no fix available", just omit the column.ExpensiveMethods - With , each group also carries an
--fullarray (every violation for that rule, not just the 3-itemitems) — usesampleinstead ofitemswhen the user wants the complete list for one rule ("show me all the SOQL unused-fields ones").sample
命令会向标准输出打印一个JSON对象。在展示任何内容前,请逐字段读取——不要只看部分内容就认为是完整结果:
- 首先检查字段。如果为
truncated,则true仅包含前groups个规则(默认10个),每个组的--top仅包含3个条目,sample也仅包含前topViolations个条目。切勿将--top的结果作为完整内容展示。请重新运行相同命令并添加truncated:true参数,使用新的输出。仅当用户明确要求快速/部分查看时可跳过此步骤。--full - 从/
analysisMode字段获取归属信息——attribution/“仅静态分析”或static/“生产环境洞察”。根据前文“归属信息是必填项”的要求,每次响应都必须包含此信息。full - ****是API内部的规则代码统计(例如
serverViolationBreakdown、SOQL_IN_LOOP_1HOP)——这是用于校验的总数(总和等于GGD),并非展示名称。切勿向用户展示这些代码;请使用易读的violationCount名称(例如groups[].key、SoqlInALoopOneHop)。SchemaGetGlobalDescribeNotEfficient - **顶层的**是所有违规项的严重程度分布——用于汇总表格。每个
severityCounts条目包含自己的groups[],仅针对该规则。severityCounts - 从构建“按规则分类的违规项”表格,每个条目对应一行:
groups→ 规则名称,key→ 数量,count→ 严重程度,severityCounts(或sample[0]参数下的--full) → 示例(items[0])。file:line - 从构建“顶级问题”表格——已按严重程度从高到低排序。使用
topViolations、rule、severity,以及file:line的第一个条目(如果非空)作为建议修复方案。如果fixes为空,则省略该列的值,不要自行编造修复方案。fixes - 当用户要求解释特定违规项(如“这是什么意思”、“为什么会被标记”),请原样展示该违规项的(通俗易懂的原因)和
message(帮助文档URL)——每个违规项对象都包含这两个字段,但为了让汇总表格更简洁,步骤5/6中未包含它们。仅当resources[0]为空时,才参考message。references/violation-catalog.md - 为
fixes是正常情况,并非错误——API的[]字段(修复代码)并非对所有规则都填充(尤其是suggestions,这是CPU排名,没有单行修复方案);不要说“无可用修复方案”,只需省略该列即可。ExpensiveMethods - 使用参数时,每个组还包含
--full数组(该规则的所有违规项,而非仅3个条目的items)——当用户需要某个规则的完整列表时(如“显示所有未使用SOQL字段的违规项”),请使用sample而非items。sample
Presentation template (fallback — only when NOT using --present
)
--present展示模板(备用——仅当无法使用--present
时)
--present--present--presentFilling the title placeholder: derive
the label from the field (not alone) — it already
encodes the three states:
<Static only | Production insights>attributionanalysisMode- "Production insights" (with runtime metrics) — enriched with production runtime metrics.
analysisMode: full - "Static only" + (no runtime metrics) — org is onboarded, but there's no runtime data for this code yet; generate a runtime report in Scale Center.
analysisMode: full - "Static only" + — source-only. Onboard the org to ApexGuru for production insights.
analysisMode: static
The fenced block below is the literal rendered output — substitute the real
values and print it; do not emit any of the guidance above:
text
undefined--present--present--present填充标题占位符:从字段获取标签(而非仅)——它已包含三种状态:
<仅静态分析 | 生产环境洞察>attributionanalysisMode- “生产环境洞察”(且包含运行时指标)——结合了生产环境运行时指标。
analysisMode: full - “仅静态分析” + (无运行时指标)——组织已接入ApexGuru,但该代码暂无运行时数据;请在Scale Center生成运行时报告。
analysisMode: full - “仅静态分析” + ——仅基于源代码。请将组织接入ApexGuru以获取生产环境洞察。
analysisMode: static
以下是字面渲染的输出——替换真实值后打印;不要输出上述指导内容:
text
undefinedApexGuru Scan Complete — <Static only | Production insights>
ApexGuru扫描完成 — <仅静态分析 | 生产环境洞察>
Found X performance violations across Y files.
| Severity | Count |
|---|---|
| Critical (1) | X |
| High (2) | X |
| Moderate (3) | X |
共发现X个性能违规项,分布在Y个文件中。
| 严重程度 | 数量 |
|---|---|
| Critical (1) | X |
| High (2) | X |
| Moderate (3) | X |
Violations by Rule
按规则分类的违规项
| Rule | Count | Severity | Example |
|---|---|---|---|
| SOQL_IN_LOOP | 15 | High (2) | AccountService.cls:42 |
| DML_IN_LOOP | 8 | Critical (1) | AccountService.cls:60 |
| GGD | 2 | Moderate (3) | Utils.cls:12 |
| 规则 | 数量 | 严重程度 | 示例 |
|---|---|---|---|
| SOQL_IN_LOOP | 15 | High (2) | AccountService.cls:42 |
| DML_IN_LOOP | 8 | Critical (1) | AccountService.cls:60 |
| GGD | 2 | Moderate (3) | Utils.cls:12 |
Top Issues
顶级问题
| # | Rule | Sev | File:Line | Suggested Fix |
|---|---|---|---|---|
| 1 | DML_IN_LOOP | 1 | AccountService.cls:60 | Collect records; DML once after the loop |
| ... up to 10 |
Raw result:
./apexguru-raw-<TS>.json
Scale to result size: **0** → "no performance antipatterns found"; **1–10** → one
table; **11+** → severity counts + by-rule table + top 10. End with the raw result
path. Do **not** append your own follow-up offer (no "I can drill in without
re-scanning…", no "filter by rule / group by file / explain a violation" menu) —
`--present` already prints the script's "show all" footer; that is the complete,
approved closing line and adding your own makes the output non-deterministic.
Rule-catalog details: `<skill_dir>/references/violation-catalog.md`.| # | 规则 | 严重程度 | 文件:行号 | 建议修复方案 |
|---|---|---|---|---|
| 1 | DML_IN_LOOP | 1 | AccountService.cls:60 | 收集记录;循环结束后执行一次DML |
| ... 最多显示10个 |
原始结果文件:
./apexguru-raw-<TS>.json
根据结果规模调整展示方式:**0个违规项** → “未发现性能反模式”;**1–10个** → 一个表格;**11个及以上** → 严重程度统计+按规则分类表格+前10个顶级问题。结尾附上原始结果文件路径。**请勿**添加自定义的后续提示(不要写“我可以不重新扫描进行深入分析…”,不要提供“按规则过滤/按文件分组/解释违规项”菜单)——`--present`已打印脚本的“显示全部”页脚;这是完整且经过批准的结束语,添加自定义内容会导致输出非确定性。规则详情请见:`<skill_dir>/references/violation-catalog.md`。Step 5: Drill into results (no re-scan)
步骤5:深入分析结果(无需重新扫描)
Re-run against the same raw file with flags:
decode-report.js| User says | Flags |
|---|---|
| "show only SOQL-in-loop" | |
| "just the critical ones" | |
| "what's in AccountService.cls?" | |
| "group by file" / "which file is worst?" | |
| "break down by severity" | |
| "show me everything" | |
对同一原始文件重新运行带参数的:
decode-report.js| 用户指令 | 参数 |
|---|---|
| “仅显示循环中的SOQL” | |
| “仅显示严重级别为Critical的项” | |
| “AccountService.cls中有什么问题?” | |
| “按文件分组” / “哪个文件问题最严重?” | |
| “按严重程度分类” | |
| “显示所有内容” | |
Constraints & Gotchas
约束与注意事项
| Item | Why / Fix |
|---|---|
Run scripts with absolute | |
| Any project layout is fine | The API walks the whole archive for Apex; |
Never decode | It is a large base64 blob — always use |
Use | Implies |
| Never re-scan to filter | Step 5 re-decodes the existing raw file instantly |
| Attribution is pre-rendered | |
| Org not onboarded to ApexGuru — tell the user, don't treat as an error |
| 401 / 403 / 404 / 400 | Token / org-ownership / scanId / zip issues — see references/error-handling.md |
| Foreground only, ~15s polls | Backgrounding loses progress; scans can take minutes |
| Token is a secret | |
| Not a security/lint scanner | For PMD/ESLint/security, use |
| 事项 | 原因/修复方案 |
|---|---|
使用绝对路径 | |
| 支持任意项目目录结构 | API会遍历整个压缩包查找Apex代码; |
切勿直接解码 | 它是大型Base64 blob——请始终使用 |
初始解码使用 | 隐含 |
| 过滤时切勿重新扫描 | 步骤5重新解码现有原始文件可瞬间完成 |
| 归属信息已预渲染 | |
期望 | 组织未接入ApexGuru——告知用户,不要视为错误 |
| 401 / 403 / 404 / 400错误 | 令牌/组织所有权/扫描ID/ZIP文件问题——请见references/error-handling.md |
| 仅在前台运行,约15秒轮询一次 | 后台运行会丢失进度;扫描可能需要数分钟 |
| 令牌是敏感信息 | |
| 并非安全/代码规范扫描工具 | 如需PMD/ESLint/安全检查,请使用 |
Reference & Script Index
参考资料与脚本索引
Scripts (execute via / with the absolute prefix, never Read):
bashnode<skill_dir>/| File | When to use |
|---|---|
| Resolve SFAP JWT + base URL (called by run-scan.sh) |
| Local (no-network) JWT pre-flight: env/scope/expiry (called by resolve-token.sh) |
| Step 2 — collect the project's Apex into a size-checked zip |
| Step 3 — submit + poll to completion |
| Steps 4–5 — decode base64 report, group/filter violations |
References (read on demand):
| File | When to read |
|---|---|
| Where the SFAP JWT comes from; env-var/file setup |
| Endpoint contracts, request/response shapes, limits |
| ApexGuru rule meanings and typical fixes |
| 400/401/403/404, FAILED, timeout, static-vs-full diagnosis |
examples/脚本(使用/执行,必须添加绝对路径前缀,切勿直接读取):
bashnode<skill_dir>/| 文件 | 使用场景 |
|---|---|
| 解析SFAP JWT + 基础URL(由run-scan.sh调用) |
| 本地(无网络)JWT预检查:环境/权限/有效期(由resolve-token.sh调用) |
| 步骤2——将项目的Apex代码收集到经过大小检查的ZIP文件中 |
| 步骤3——提交扫描请求并轮询直至完成 |
| 步骤4–5——解码Base64报告,分组/过滤违规项 |
参考资料(按需阅读):
| 文件 | 阅读场景 |
|---|---|
| SFAP JWT的来源;环境变量/文件配置 |
| 端点契约、请求/响应格式、限制 |
| ApexGuru规则的含义和典型修复方案 |
| 400/401/403/404错误、扫描失败、超时、静态/全模式诊断 |
examples/