Skip to content

feat(adw): the profile is the phase list, not a label on it - #3

Merged
ruslan-korneev merged 1 commit into
masterfrom
profile-honoured
Jul 27, 2026
Merged

feat(adw): the profile is the phase list, not a label on it#3
ruslan-korneev merged 1 commit into
masterfrom
profile-honoured

Conversation

@ruslan-korneev

Copy link
Copy Markdown
Owner

Stacked on #2 (which is stacked on #1). Closes RUS-190 and RUS-191 — they were filed separately, but
the phase matrix and the new profile are one edit; splitting them would have meant writing the same
table twice.

The problem

workflow-triage picked a profile and the scripts honoured it — review.sh:37 scaled the fan-out,
gate.sh:167 scaled the required lenses — but adw-run did not. Its phases were written
unconditionally, so a light run still paid for the scout agent, the full artifact set, the groom agent
passes and a stop at G2.

The two skills also disagreed in writing: triage said light → G7 only; adw-run phase 4 said
"stop for the operator" with no mention of the profile. The orchestrator wins in practice, so light
bought a cheaper groom, a cheaper review, and nothing else.

The change

adw-run carries a phase × profile table and runs one column.

Phase superlight light standard / deep
scout skip skip agent
plan ~12 lines + 1 check short but complete full
groom none 1 lens, inline one agent per lens
G2 skip skip stop
worktree + draft PR yes yes yes
RED one test, written inline optional agent, gate enforced
green + evidence required required required
review 1 reviewer 1 reviewer fan-out + wildcard (+ judge)
G7 stop stop stop

Below standard the specialist agents go away, because their value goes away: the scout protects a
context this task will not fill, and the test-author guard exists so an implementer cannot bend a test —
when you are about to write both, the honest substitute is writing the test first and not touching it
after. G2 goes away because a twelve-line plan is one the operator approves without reading, and a gate
that gets rubber-stamped devalues the one that must not.

superlight is new: no groom pass at all, one check, one reviewer. It needed no change to
gate.sh's requirements
gate.sh plan wants four headers and one numbered check, gate.sh evidence
wants one evidence file, and on a task this size three of those headers are one word long.

What never scales down: the worktree, the draft PR, gate.sh green, gate.sh evidence, one
reviewer. The workspace takes seconds and is what makes a run revertible and visible; one reviewer is
the cheapest independent look at a diff there is.

The floor, which nothing documented before: a typo, a version bump, a comment fix should not enter
the loop at all. Triage reasons about blast radius, so it honestly answers superlight for a one-liner
— that is not a licence to spend a worktree and a PR on it.

Operator override

arguments: [profile, ref]
argument-hint: "[superlight|light|standard|deep] [ticket-ref]"

/adw-run light SM-12. Claude Code's : is a plugin namespace (/my-plugin:review), not an option
separator — /adw-run:light would parse as a skill light in a plugin adw-run. Arguments are the
mechanism, and an unpassed named argument expands to an empty string, so "nobody chose" stays a normal
branch.

Script changes

  • gate.sh: superlight added to the profile alternation. Without it, **Profile:** superlight matches
    the light inside the word and the run is groomed as light. superlight also skips the GROOM_LOG.md
    requirement — no pass was meant to happen — while the blocker check still runs, because a blocker stops
    the run at every profile.
  • review.sh: superlight resolves to the light fan-out instead of dying as an unknown profile.

How to verify

bash tests/run.sh                            # 116 passed, 0 failed, 1 known gap
ADW_TEST_SHELL=/bin/bash bash tests/run.sh

Non-vacuous by mutation: dropping superlight from gate.sh's alternation fails 2 assertions, dropping
it from review.sh fails 1.

One thing worth knowing, because a comment in the first draft of this PR got it wrong: order in the
alternation is irrelevant.
ERE is leftmost-longest, so light|superlight and superlight|light both
return superlight — verified by swapping them and watching the suite stay green. What matters is that
the longer word is in the list at all.

Not verified

  • No real task has been run at superlight end to end. The profile is asserted at the two places a
    script can see it (gate.sh groom, review.sh); the rest is instructions to the orchestrator, and
    instructions are advisory by construction.
  • The floor is prose. Nothing mechanically stops a one-line change from entering the loop, and nothing
    should — the judgement is the operator's.
  • arguments:/argument-hint: frontmatter is documented Claude Code behaviour but has not been
    exercised here; /adw-run light SM-12 has not been typed against the installed skill.

workflow-triage picked a profile and the scripts honoured it — review.sh scaled the fan-out, gate.sh
scaled the required lenses — but adw-run did not. Its phases were written unconditionally, so a
`light` run still paid for the scout agent, the full artifact set, the groom agent passes and a stop
at G2. The two skills also disagreed in writing: triage said `light` → G7 only, adw-run said "stop for
the operator" with no mention of the profile. The orchestrator won, so `light` bought a cheaper groom
and a cheaper review and nothing else.

adw-run now carries a phase × profile table and runs one column. Below `standard`: no scout agent
(read the files — the agent protects a context this task will not fill), no groom agent (`light` runs
the one lens inline), no test-author agent (write the failing test yourself and do not touch it
afterwards), and no G2 — a twelve-line plan is one the operator approves without reading, and a gate
that gets rubber-stamped devalues the one that must not.

Adds `superlight` for work below `light`: no groom pass at all, one check, one reviewer. It needs no
change to gate.sh, because the gates already accept that shape — `gate.sh plan` wants four headers and
one numbered check, `gate.sh evidence` wants one evidence file, and on a task this size three of those
headers are one word long.

What never scales down, at any profile: the worktree, the draft PR, `gate.sh green`, `gate.sh
evidence`, and one reviewer. The workspace is script-driven and takes seconds; it is what makes a run
revertible and visible, and cutting it saves nothing measurable. One reviewer is the cheapest
independent look at a diff there is — without it a small run is a solo run awarding itself a green
tick.

Adds the floor, which nothing documented before: a typo, a version bump, a comment fix should not
enter the loop at all. Triage reasons about blast radius, so it will honestly answer `superlight` for
a one-liner — that is not a licence to spend a worktree and a PR on it. Below the floor the cost is
the operator's attention, not the tokens: a PR that says nothing teaches them to stop reading PRs.

Operator override: `arguments: [profile, ref]` + `argument-hint`, so `/adw-run light SM-12` names the
profile and triage is skipped. Claude Code's `:` is a plugin namespace (`/my-plugin:review`), not an
option separator — `/adw-run:light` would parse as a skill `light` in a plugin `adw-run` — so
arguments are the mechanism, and an unpassed named argument expands to an empty string, which makes
"nobody chose" a normal branch.

- scripts/gate.sh: 'superlight' added to the profile alternation. Without it "**Profile:**
  superlight" matches the `light` inside the word and the run is groomed as light. Order in the
  alternation is irrelevant — ERE is leftmost-longest, so both alternatives start at the same offset
  and the longer one wins either way; verified by swapping them and watching the tests stay green.
  superlight also skips the GROOM_LOG.md requirement, since no pass was meant to happen. The blocker
  check still runs: a blocker stops the run at every profile.
- scripts/review.sh: `superlight` resolves to the light fan-out rather than dying as unknown.
- groom-harden, slice-review, task-plan, the AGENTS.md block, the dev-prompt template and README
  updated to four profiles.

Tests: 5 new assertions. superlight passes G1 with no ledger at all, still fails on an open blocker,
and is recognised by review.sh instead of being rejected by name. Verified non-vacuous by mutation —
dropping `superlight` from gate.sh's alternation fails 2, dropping it from review.sh fails 1. Suite:
116 passed, 0 failed, 1 known gap, under bash 5.2 and 3.2.

VERSION 2.1.0 → 2.2.0.

Refs RUS-190, RUS-191
@ruslan-korneev ruslan-korneev self-assigned this Jul 27, 2026
@ruslan-korneev
ruslan-korneev changed the base branch from gates-degraded to master July 27, 2026 17:48
@ruslan-korneev
ruslan-korneev merged commit dfef74a into master Jul 27, 2026
2 checks passed
@ruslan-korneev
ruslan-korneev deleted the profile-honoured branch July 27, 2026 17:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant