ase-code-analyze
Analyze the source code for problems in either the logic and semantics and its related control flow, performance and efficiency, or security.
SKILL.mdplugin/skills/ase-code-analyze/SKILL.md
GitHub@${CLAUDE_SKILL_DIR}/../../meta/ase-control.md @${CLAUDE_SKILL_DIR}/../../meta/ase-skill.md @${CLAUDE_SKILL_DIR}/../../meta/ase-getopt.md
<purpose name="ase-code-analyze"> Analyze Source Code </purpose><expand name="getopt" arg1="ase-code-analyze" arg2="--performance|-p --security|-s --severity|-S=(LOW|MEDIUM|HIGH) --prefix|-P= --staged --unstaged"> $ARGUMENTS </expand>
<objective> *Analyze* the source code of <getopt-arguments/>, and its directly related source code, for problems - read-only, *without* applying any changes. The *analysis lens* depends on the selected options: problems in its *logic* and *semantics* and its related *control flow*, or problems in *performance* and *efficiency*, or problems in *security*. </objective> <flow>- <step id="STEP 1: Sanity Check Usage">
<if condition="<getopt-option-performance/> is equal `true` and <getopt-option-security/> is equal `true`">
Only output the following <template/> and then STOP the entire flow (do not perform any further steps):
<template> ⧉ **ASE**: ✪ skill: **ase-code-analyze**, ▶ ERROR: options `--performance` and `--security` are mutually exclusive </template> </if> </step> - <step id="STEP 2: Investigate Code Base">
<if condition="<ase-project-boxing/> is equal `black`">
The project source artifacts are classified as a black box, so the user does not want them inspected or their problems surfaced. Skip the entire investigation and analysis: do not invoke any
<template> <ase-tpl-bullet-normal/> **CODE ANALYSIS**: *suppressed* (`project.boxing` is `black`) </template> </if>Bash,Glob, orAgenttool and do not read any source, only output the following <template/> and then SKIP the remaining step STEP 3:First, use the following <template/> to give a hint on this step:
<template> <ase-tpl-bullet-secondary/> **ANALYSIS INVESTIGATION** </template>Dispatch the investigation to sub-agents via the
Agenttool so that no investigation details leak into the user-visible transcript. The sub-agents perform the silent reading and checking; only their final structured return values are consumed here.For this, first determine the analysis lens <lens/>: set <lens>performance</lens> if <getopt-option-performance/> is equal
<if condition="<getopt-option-staged/> is equal `true` or <getopt-option-unstaged/> is equal `true`">true, set <lens>security</lens> if <getopt-option-security/> is equaltrue, and set <lens>logic</lens> otherwise.Then silently restrict the analysis to the changed files of the Git working copy. Set <changes>staged and unstaged</changes> if both <getopt-option-staged/> and <getopt-option-unstaged/> are equal
<if condition="<getopt-option-staged/> is equal `true`"> `git -C "<repo-root/>" -c core.quotepath=off diff --cached --name-only --diff-filter=d` </if> <if condition="<getopt-option-unstaged/> is equal `true`"> `git -C "<repo-root/>" -c core.quotepath=off diff --name-only --diff-filter=d`true, set <changes>staged</changes> if only <getopt-option-staged/> is equaltrue, and set <changes>unstaged</changes> otherwise. Determine the repository root by running the commandgit rev-parse --show-toplevel(taken exactly as given) and capturing its output into <repo-root/>. Then determine the changed files by running the corresponding commands (taken exactly as given), each listing one path relative to <repo-root/> per line, and collect all listed paths, dropping duplicates:
</if>git -C "<repo-root/>" -c core.quotepath=off ls-files --others --exclude-standardSkip every listed path below the
.ase/directory (it carries ASE's own state) and every path which is not a source code file (e.g. a binary file), and prefix every remaining path with<repo-root/>/. If<getopt-arguments/>is not empty, keep only those files which lie within the source code referenced by it, expanding any directory or wildcard references with theGlobtool. Set <sources/> to the resulting list of individual source code files, preserving order.If <sources/> is empty, only output the following <template/> and then SKIP the rest of this STEP 2 and the remaining step STEP 3:
<template> <ase-tpl-bullet-normal/> **CODE ANALYSIS**: *no <changes/> source files to analyze* </template> </if> <else>Then silently resolve
<getopt-arguments/>to the list <sources/> of individual source code files, expanding any directory or wildcard references with theGlobtool.If <sources/> is empty (no source-reference given or none of it resolvable), only output the following <template/> and then STOP the entire flow (do not perform any further steps):
<template> ⧉ **ASE**: ✪ skill: **ase-code-analyze**, ▶ ERROR: no source files to analyze -- give a *source-reference* or use `--staged`/`--unstaged` </template> </else>Then partition <sources/>, preserving order, into at most eight batches of roughly equal size (a single file yields a single batch), and invoke the following tool once per batch, emitting all invocations in one single message so they run in parallel:
Agent( description: "Analysis Investigation (<batch-index/>/<batch-count/>)", subagent_type: "ase:ase-code-analyze", prompt: "<lens/> <batch/>", run_in_background: false )Here <batch/> is the space-separated list of the source code file paths of the corresponding batch, <batch-index/> is the 1-based index of that batch, and <batch-count/> is the total number of batches, so that each parallel invocation is distinguishable in the progress display.
Parse the result message of each
Agenttool invocation as a JSON array and concatenate all those arrays. Then deduplicate the combined list: when two problems share the samefileandline, silently drop all but the first one (sub-agents may have read overlapping related files for comprehension). Finally sort the list byfileand then numerically byline, and set <problems/> to that list.You MUST NOT output anything at all in this STEP 2 beyond the
</step>Bash,Glob, andAgenttool invocations and the templates above. - <step id="STEP 3: Show Results">
Before reporting, determine the problem id prefix <id-prefix/>: set <id-prefix><getopt-option-prefix/>-</id-prefix> if <getopt-option-prefix/> is not empty, and set <id-prefix></id-prefix> (set to empty) otherwise. Every reported problem id and every persisted key below carries this <id-prefix/>, so that analyses run under distinct prefixes occupy distinct id namespaces and hence do not overwrite each other.
Before reporting, determine the effective severity floor <floor/>: define the ordinal rank
LOW=1,MEDIUM=2,HIGH=3, start from <floor><getopt-option-severity/></floor> (defaultLOW), and - if <ase-project-boxing/> is equalgrey- raise <floor/> toMEDIUMwhenever its current rank is belowrank(MEDIUM)(grey boxing surfaces only material findings of severityMEDIUMand above).Then apply the effective severity floor <floor/>: Keep a detected problem if and only if its
severityfield isACCEPTEDorrank(severity)is greater than or equal torank(<floor/>); silently drop all other problems (they are neither reported nor persisted). With the default floorLOW, all problems are kept.ACCEPTEDproblems are never dropped.Then sort the surviving problems in <problems/> by their
severityfield from highest to lowest in the fixed orderHIGH,MEDIUM,LOW,ACCEPTED, so the reporting starts with the most severe problem. Within the same severity, keep thefile/lineorder established in STEP 2.Then renumber the surviving problems contiguously as
<id-prefix/>P<n/>with <n/> = 1, 2, ... in that sorted ordering, so<id-prefix/>P1is the most severe problem and the persistedase-issue-<id-prefix/>P<n/>keys follow the reported sequence. If all problems are dropped, skip the per-problem report but still purge any stale persisted problems with a singlease_kv_batchcall to theaseMCP server withtransactionalset totrueand acommandsparameter array holding exactly one{ command: "clear", prefix: "ase-issue-<id-prefix/>" }entry, and still emit the final hint <template/> below.In this STEP 3, for EVERY surviving problem in <problems/>, set <severity/> to its
<if condition="<getopt-option-performance/> is equal `true`"> <template>severityfield, <title/> to itstitlefield, <description/> to itsdescriptionfield, <evidence/> to itsevidencefield, and <trade-off/> to itstrade-offfield, and immediately report it with the following output <template/>, based on concise bullet points.<ase-tpl-bullet-signal/> PROBLEM (Severity: <severity/>): <id-prefix/>P<n/>: <title/>
<description/>⊙ EVIDENCE: <evidence/> ⊖ TRADEOFF: <trade-off/>
</template> </if> <if condition="<getopt-option-performance/> is NOT equal `true`"> <template><ase-tpl-bullet-signal/> PROBLEM (Severity: <severity/>): <id-prefix/>P<n/>: <title/>
<description/> </template> </if>Hints:
For the final results, do not output anything else, especially do not give any further explanations or information.
Uniquely identify the problems with
<id-prefix/>P<n/>where <n/> is 1, 2, ...Additionally, persist all reported problems in a single
ase_kv_batchcall to theaseMCP server withtransactionalset totrue. Thecommandsparameter array of this call starts with one{ command: "clear", prefix: "ase-issue-<id-prefix/>" }entry (which removes only the previously persistedase-issue-<id-prefix/>*keys, leaving any unrelated keys in the shared store intact), followed by one{ command: "set", key: "ase-issue-<id-prefix/>P<n/>", val: "<title/>: <description/>" }entry per reported problem.
Finally, give a final hint by expanding the following (which, depending on the configured <ase-guidance-level/>, may expand into nothing and hence emit no output at all):
<ase-tpl-hint level="minimal"> For deeper analysis, suggestions on solution approaches and then final problem resolution, use `/ase-task-edit <id-prefix/>P{n}`, or for a direct one-shot fix use `/ase-code-edit <id-prefix/>P{n}`, in the same or even a different session. </ase-tpl-hint>You MUST not output anything else in this STEP 3, especially not any further explanations.
</step>