From 522ea8e9a1ab40ef1aecbf2b72a7e84c09f7a6c5 Mon Sep 17 00:00:00 2001 From: Matthias Brusdeylins Date: Sat, 1 Aug 2026 02:54:54 +0200 Subject: [PATCH] =?UTF-8?q?feat(ase-code-analyze):=20add=20-Q=20one-shot?= =?UTF-8?q?=20analyze=20=E2=86=92=20resolve=20=E2=86=92=20implement=20?= =?UTF-8?q?=E2=86=92=20verify?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a --quick/-Q flag that turns an analysis into a fully autonomous one-shot pipeline. After reporting and persisting the surviving problems, -Q groups them into per-file clusters and dispatches one worktree-isolated `ase-code-resolve -Q` sub-agent per cluster in parallel (in the background, with a progress line per returning cluster; each worktree is seeded with the live tree's uncommitted state so its diff applies). It then reconciles the returned diffs into the working tree (plain `git apply`, `--3way` fallback, conflicting clusters re-resolved sequentially so all problems merge), removes the temporary worktrees, and finally runs the project's formatter, build, and test suite centrally on the merged result with up to two autonomous repair rounds. ACCEPTED findings (documented, reviewed trade-offs) are excluded from auto-resolution. Nothing is staged or committed -- staging remains with the user. -Q composes with --severity and requires a Git repository (otherwise clusters are resolved sequentially without worktree isolation). Adds "Bash" to allowed-tools for the reconcile and worktree cleanup, and reports a per-problem result table plus a verification outcome. Co-Authored-By: Claude Opus 4.8 (1M context) --- plugin/skills/ase-code-analyze/SKILL.md | 163 +++++++++++++++++++++++- plugin/skills/ase-code-analyze/help.md | 28 ++++ 2 files changed, 189 insertions(+), 2 deletions(-) diff --git a/plugin/skills/ase-code-analyze/SKILL.md b/plugin/skills/ase-code-analyze/SKILL.md index 32d49270..745e600d 100644 --- a/plugin/skills/ase-code-analyze/SKILL.md +++ b/plugin/skills/ase-code-analyze/SKILL.md @@ -1,6 +1,6 @@ --- name: ase-code-analyze -argument-hint: "[--help|-h] [--performance|-p] [--security|-s] [--severity|-S=(LOW|MEDIUM|HIGH)] " +argument-hint: "[--help|-h] [--performance|-p] [--security|-s] [--severity|-S=(LOW|MEDIUM|HIGH)] [--quick|-Q] " description: > Analyze the source code for problems in either the logic and semantics and its related control flow, performance and efficiency, @@ -10,6 +10,7 @@ disable-model-invocation: false effort: high allowed-tools: - "Agent" + - "Bash" - "Glob" --- @@ -23,7 +24,7 @@ Analyze Source Code + arg2="--performance|-p --security|-s --severity|-S=(LOW|MEDIUM|HIGH) --quick|-Q"> $ARGUMENTS @@ -204,6 +205,164 @@ problems in *performance* and *efficiency*, or problems in *security*. followed by one `{ command: "set", key: "ase-issue-P", val: ": <description/>" }` entry per reported problem. + <if condition="<getopt-option-quick/> is equal `true` and at least one problem survived the severity floor"> + + The `--quick`/`-Q` flag turns this analysis into a *one-shot* + `analyze → resolve → implement → verify` pipeline that resolves + the surviving problems fully autonomously, *without any user + interaction*. Problems whose `severity` is `ACCEPTED` are + *excluded* from auto-resolution: they document deliberately + accepted trade-offs, so "fixing" them would undo reviewed + decisions -- they stay reported and persisted only. Let <count/> + be the number of surviving *non-ACCEPTED* problems and + <accepted-count/> the number of surviving `ACCEPTED` problems, + and keep the surviving <problems/> entries (each with its `file`, + `title`, and `description` field) available for the sub-steps + below. If <count/> is `0`, *skip* this entire one-shot block and + continue with the final hint <template/> below. + + First, announce the one-shot phase with the following <template/>: + + <template> + <ase-tpl-bullet-secondary/> **ONE-SHOT RESOLUTION** (<count/> problem(s), <accepted-count/> ACCEPTED skipped) + </template> + + Then perform the following sub-steps and finally *STOP* the entire + flow (do *not* emit the final hint <template/> below): + + 1. *Guard and snapshot*: with the `Bash` tool, run + `git rev-parse --is-inside-work-tree` to check whether the + target is a Git working tree. If it fails (no Git repository), + worktree isolation is impossible, so *skip* sub-steps 3-6 and + instead resolve each cluster of sub-step 2 *sequentially* -- + one non-isolated `Agent` invocation at a time, in ascending + order, each with the sub-step 3 prompt but *without* the + `isolation` parameter, the seeding instruction, and the diff + return (the fixes land in the live tree directly); for each + problem, record its <outcome/> as `resolved` and its changed + files <files/> (from `git diff --name-only` taken immediately + before and after its cluster's `Agent`) -- then continue with + sub-step 7. Otherwise, capture the repository root + `git rev-parse --show-toplevel` as <live-root/> and + `git worktree list --porcelain` as <worktrees-before/> for the + cleanup in sub-step 6. + + 2. *Cluster by file*: group the <count/> problems by their `file` + field -- problems sharing the same file form *one* cluster + (resolving same-file problems in separate parallel worktrees + would guarantee merge conflicts). Order the clusters by their + lowest contained `P<n/>` and let <cluster-count/> be the number + of clusters, <cluster-index/> the 1-based cluster number, and + <cluster-problems/> the ascending, comma-separated `P<n/>` list + of a cluster. + + 3. *Resolve in parallel (background)*: for *every* cluster, invoke + the following tool once, emitting *all* invocations *in one + single message* so they run in *parallel*, each in its *own* + isolated Git worktree: + + ```text + Agent( + description: "Resolve <cluster-problems/> (<cluster-index/>/<cluster-count/>)", + subagent_type: "general-purpose", + isolation: "worktree", + run_in_background: true, + prompt: "First seed this worktree with the live working tree's uncommitted state: run `git -C \"<live-root/>\" diff HEAD | git apply --whitespace=nowarn` (skip when that diff is empty), then `git add -A && git commit -m seed` (skip the commit when nothing is staged). Then, for each of <cluster-problems/> in ascending order, call the tool Skill(skill: \"ase:ase-code-resolve\", args: \"-Q P<n/>\") to fully resolve AND implement that issue in this worktree. When finished, run `git add -A` followed by `git diff --cached`, and return ONLY that complete unified diff as your final message (an empty string if nothing changed)." + ) + ``` + + The background execution keeps the long fan-out interruptible + and observable: *each time* one of these `Agent` invocations + completes, immediately output one progress line with the + following <template/>, then keep waiting until *all* clusters + have returned. Collect each returned unified diff, keyed by its + cluster. + + <template> + <ase-tpl-bullet-secondary/> **RESOLVED** (<cluster-index/>/<cluster-count/>): <cluster-problems/> + </template> + + 4. *Reconcile sequentially -- always merge, never prompt*: with the + `Bash` tool, process the collected cluster diffs in ascending + cluster order. For each *non-empty* diff, write it to a + temporary file and apply it with `git apply --whitespace=nowarn + <patch-file/>` -- deliberately *without* `--index`: staging + remains with the user. On success, record each contained + problem's <outcome/> as `merged` and its changed files <files/> + (the `+++ b/<path>` headers of its diff). On failure, retry + with `git apply --3way --whitespace=nowarn <patch-file/>`. If + the three-way attempt also fails or leaves Git conflict markers + in any touched file, or the diff is empty, or its `Agent` + returned nothing, do *not* stop -- instead add the cluster's + problems to a *retry set* (a possibly marker-littered file is + repaired there). + + 5. *Retry conflicts sequentially*: for each `P<n/>` in the retry + set, in ascending order and strictly *one at a time*, set + <title/> and <description/> to that problem's `title` and + `description` fields (from <problems/>) and invoke a + *non-isolated* `Agent` against the now-updated live working + tree: + + ```text + Agent( + description: "Re-resolve P<n/> (sequential)", + subagent_type: "general-purpose", + run_in_background: false, + prompt: "Call the tool Skill(skill: \"ase:ase-code-resolve\", args: \"-Q <title/> — <description/>\") to fully resolve AND implement that problem directly in the current working tree. The affected files may still contain Git conflict markers from a failed three-way merge -- remove any such markers as part of the resolution." + ) + ``` + + Because each such `Agent` edits the live tree directly and + sequentially, its change always integrates cleanly, so *all* + <count/> problems end up merged. Record that problem's + <outcome/> as `re-resolved` and its changed files <files/> + (from `git diff --name-only` taken immediately before and after + that single `Agent`). + + 6. *Remove the worktrees*: with the `Bash` tool, compare the current + `git worktree list --porcelain` against <worktrees-before/>; for + *each* newly added worktree, run `git worktree remove --force + <path/>`, then run `git worktree prune` to drop any remaining + administrative references. + + 7. *Verify and repair*: the per-worktree resolutions ran in `dry` + mode (no verification), so the *merged result* MUST now be + verified centrally. Determine the project's canonical + *formatter*, *build*, and *test* commands from its build + configuration (e.g. npm `package.json` scripts, `Makefile`, + Gradle `spotlessApply`/`build`/`test`, Cargo, etc). With the + `Bash` tool run, in this order: the formatter (if any), the + build, and the test suite. If any of them fails, hand the + *complete* failure output to one *non-isolated* + `Agent(subagent_type: "general-purpose", run_in_background: + false)` with the prompt to repair exactly those failures in the + current working tree without touching unrelated user changes, + then re-run the failed commands. Perform at most *two* such + repair rounds. Set <verify/> to `green` when everything passes, + or to a short failure summary when failures remain. Do *not* + stage or commit anything -- staging remains with the user. + + 8. *Report the per-problem results*: for *every* auto-resolved + problem `P<n/>`, in ascending order, output the following + <template/>, where <marker/> is `✓` when its <outcome/> is + `merged` or `resolved` and `↻` when its <outcome/> is + `re-resolved`, and <files/> is the comma-separated list of its + changed files (or `no changes` when empty): + + <template> + <ase-tpl-bullet-signal/> **P<n/>** <marker/> *<outcome/>*: <files/> + </template> + + 9. Finally, output the following summary <template/> and then *STOP* + the entire flow (do *not* emit the final hint <template/> below): + + <template> + ⧉ **ASE**: ↪ hint: **one-shot `-Q`: auto-resolved <count/> problem(s) (<accepted-count/> ACCEPTED skipped), verification: <verify/> -- staging remains with you.** + </template> + + </if> + 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): diff --git a/plugin/skills/ase-code-analyze/help.md b/plugin/skills/ase-code-analyze/help.md index 9789317f..6fe1545a 100644 --- a/plugin/skills/ase-code-analyze/help.md +++ b/plugin/skills/ase-code-analyze/help.md @@ -10,6 +10,7 @@ [`--performance`|`-p`] [`--security`|`-s`] [`--severity`|`-S`=(`LOW`|`MEDIUM`|`HIGH`)] + [`--quick`|`-Q`] *source-reference* ## DESCRIPTION @@ -38,6 +39,26 @@ severity* order `HIGH`, `MEDIUM`, `LOW`, `ACCEPTED` - keeping the `file`/`line` order within the same severity - and are renumbered contiguously as `P<n>`, so `P1` is the most severe problem. +The `--quick`|`-Q` option turns the analysis into a fully autonomous +one-shot `analyze → resolve → implement → verify` pipeline: after +reporting, it groups the surviving problems into *per-file clusters* +(same-file problems are never resolved in parallel), dispatches one +worktree-isolated `ase-code-resolve -Q` sub-agent per cluster in +parallel (in the background, with a progress line per returning +cluster; each worktree is first *seeded* with the live tree's +uncommitted state so its diff applies cleanly), then reconciles all +resulting diffs into the working tree (plain `git apply`, `--3way` as +fallback, and a conflicting cluster is re-resolved sequentially so that +*all* problems are merged), removes the temporary worktrees again, and +finally runs the project's formatter, build, and test suite centrally +on the merged result, with up to two autonomous repair rounds for any +failures. `ACCEPTED` problems document deliberately accepted trade-offs +and are *excluded* from auto-resolution. Nothing is staged or +committed -- staging remains with the user. It composes with +`--severity` (only surviving findings are resolved) and requires a Git +repository (otherwise the clusters are resolved sequentially without +worktree isolation). + The skill investigates the code base silently, reports each detected problem as a `PROBLEM` entry with severity (`LOW`, `MEDIUM`, `HIGH`) and inline file/line references (in the performance lens, each entry @@ -83,6 +104,13 @@ Analyze a directory, reporting only `MEDIUM` and `HIGH` problems: ❯ /ase-code-analyze -S MEDIUM src/handlers/ ``` +Analyze a directory and, in one non-interactive shot, auto-resolve and +implement every `HIGH` finding: + +```text +❯ /ase-code-analyze -Q -S HIGH src/handlers/ +``` + ## SEE ALSO [`ase-code-resolve`](../ase-code-resolve/help.md), [`ase-code-refactor`](../ase-code-refactor/help.md), [`ase-code-lint`](../ase-code-lint/help.md),