Skip to content

TEST — DO NOT MERGE: exercise the claude-fix job - #198

Closed
MaryWylde wants to merge 8 commits into
devfrom
test/claude-fix-probe
Closed

TEST — DO NOT MERGE: exercise the claude-fix job#198
MaryWylde wants to merge 8 commits into
devfrom
test/claude-fix-probe

Conversation

@MaryWylde

Copy link
Copy Markdown
Contributor

Throwaway PR. Do not merge. It will be closed and the branch deleted once the run is observed.

Purpose: prove the new claude-fix job actually works end to end, rather than trusting that it does.

It carries two commits:

  • 1052d72 — the workflow change itself, so this PR's own run includes the new claude-fix job (for pull_request, GitHub takes the workflow definition from the merge commit, so a PR can exercise its own workflow changes).
  • 214cee8 — a probe component with deliberate defects the review prompt explicitly looks for: a clickable div with no keyboard path, multi-property inline styles, hardcoded hex outside the design tokens, and any props.

What should happen

  1. claude-review reviews, leaves inline comments, and publishes the count of comments on the head commit.
  2. claude-fix sees a non-zero count, checks out this branch, fixes what was raised, commits with [agent-fix] in the subject, and pushes.
  3. Nothing further. The fix pushes with GITHUB_TOKEN, which does not trigger workflows, so there is no second review and no loop.

What I am watching for

  • Does claude-fix trigger at all, and does its if: guard evaluate correctly?
  • Does the push succeed with contents: write and the action's git-push.sh?
  • Does it stay inside scope — fixing only what was flagged, not "improving" the rest of the file?
  • Does it correctly skip anything it judges the review got wrong?

🤖 Generated with Claude Code

MaryWylde and others added 2 commits September 7, 2026 21:00
Two people work this repo with separate agent setups, and the review→fix
handoff was a person reading a comment and telling their agent to go. That is a
notification, not automation — someone still has to be at a desk.

So do the fixing in CI. claude-code-review.yml gains a second job: the review
job publishes how many inline comments landed on the current head commit, and
the fix job runs only when that is above zero, checks out the PR branch,
addresses the comments and pushes. Nobody starts either one.

It cannot loop, structurally: the fix job pushes with GITHUB_TOKEN, and GitHub
does not start workflows from GITHUB_TOKEN pushes, so the fix commit triggers no
second review and therefore no second fix. One review, one fix pass, then it
waits for a person. A round guard on [agent-fix] commits is the backstop if
anyone later swaps in a PAT to get re-review chaining, and trips
agent:needs-human rather than going again.

The fixer is told to address only what the review raised and to skip comments it
judges wrong rather than comply — automated review is wrong sometimes, and an
unattended agent widening its own scope is how a small PR becomes an
unreviewable one.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Throwaway. Carries deliberate, unambiguous defects the review prompt already
looks for — a clickable div with no keyboard path, multi-property inline
styles, hardcoded hex outside the tokens, and `any` props — so the fix job has
something definite to act on.

DO NOT MERGE. Delete the branch once the run is observed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

Claude finished @MaryWylde's task in 1m 53s —— View job


Claude finished the review

  • Gather context (PR description, changed files, AGENTS.md/CLAUDE.md conventions)
  • Read the probe component (AgentFixProbe.tsx, .module.scss, index.tsx)
  • Read the workflow change (.github/workflows/claude-code-review.yml)
  • Post inline comments for issues found
  • Post final summary

Summary

Reviewed the diff against origin/dev. This PR is explicitly a throwaway probe, and the changes in src/components/library/atoms/AgentFixProbe/ are deliberately defective to exercise the claude-fix job — the review below reflects that.

AgentFixProbe.tsx / .module.scss / index.tsx — 5 inline comments posted:

  1. AgentFixProbe.tsx:16-22 — clickable div with onClick but no keyboard path (no role/tabIndex/onKeyDown). Not reachable or operable via keyboard.
  2. AgentFixProbe.tsx:19 — multi-property inline style object; AGENTS.md only permits inline styles for a single dynamic property. Belongs in the SCSS module.
  3. AgentFixProbe.tsx:7-8onPick: (value: any) => void and tone: any; both should be precisely typed (onPick only ever receives the string label).
  4. AgentFixProbe.module.scss:8-9,14 — hardcoded hex colors (#e8d9b8, #533a3a, #9a8f7a) outside the design tokens.
  5. index.tsx:1 — barrel does export * from './AgentFixProbe' against a named export, not the AGENTS.md default-export barrel pattern (import X from './X'; export default X;).

.github/workflows/claude-code-review.yml — the new claude-fix job looks correctly scoped: needs/if gate on findings > 0 from the review job's output, the round guard checks PR commits for [agent-fix] (≥2 stops it and labels agent:needs-human), and the push uses GITHUB_TOKEN via the action's git-push.sh, which per GitHub's own behavior won't trigger a new pull_request run — so the no-loop guarantee described in the PR body holds. No correctness issues found in the workflow logic itself.

AGENTS.md — additions document the review→fix automation and commit-hygiene rules; consistent with what's implemented in the workflow, nothing to flag.

No accessibility, security, or convention issues found outside the probe component itself.
· Branch: test/claude-fix-probe

Comment on lines +16 to +22
<div
className={styles.pill}
onClick={() => onPick(label)}
style={{ color: '#7a5c3e', padding: '6px 10px', borderRadius: '4px' }}
>
{label}
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a clickable div with no keyboard path — no role, tabIndex, or onKeyDown/onKeyUp handler, so it's unreachable and unusable via keyboard, and screen readers won't announce it as interactive. Use a <button type="button"> (SCSS can strip default button styling) or add role="button", tabIndex={0}, and an Enter/Space key handler.

Fix this →

<div
className={styles.pill}
onClick={() => onPick(label)}
style={{ color: '#7a5c3e', padding: '6px 10px', borderRadius: '4px' }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multi-property inline style object (color, padding, borderRadius). AGENTS.md only allows inline styles for a single dynamic property — this is static and belongs in AgentFixProbe.module.scss. The hex value #7a5c3e is also hardcoded outside the design tokens (see keepsimple-style skill).

Fix this →

Comment on lines +7 to +8
onPick: (value: any) => void;
tone: any;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onPick: (value: any) => void and tone: any both use any. label is already typed string and is the only value passed to onPick, so onPick: (value: string) => void is precise; tone should get a real type (e.g. a string union of the tones this probe supports) instead of any.

Fix this →

Comment on lines +8 to +9
background: #e8d9b8;
border: 1px solid #533a3a;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#e8d9b8 and #533a3a are hardcoded hex colors outside the design tokens (AGENTS.md: "Invent colors... — read the keepsimple-style skill first"). Same for #9a8f7a on line 14.

@@ -0,0 +1 @@
export * from './AgentFixProbe';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Barrel convention violation (AGENTS.md "Component Pattern → Exports"): components should use export default, and index.ts should do a default re-export (import X from './X'; export default X;), not export * from …. AgentFixProbe.tsx uses a named export function AgentFixProbe instead of a default export, and this barrel re-exports it by name.

Fix this →

@github-actions github-actions Bot added the agent:review-ready Claude's PR review finished and left findings — ready for a fixer agent label Sep 7, 2026
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

Claude finished @MaryWylde's task in 2m 2s —— View job


claude-fix: nothing to address

  • Gather context (fetch actual inline review comments on this PR)
  • Understand each comment and judge validity
  • Fix what's justified, skip what isn't
  • Summarize outcome

Finding: no inline review comments were present in the data this job received. The <review_comments> context passed to me for PR #198 is empty ("No review comments"), and this job's tool access doesn't include gh api/gh pr view to independently re-query GitHub and double-check that.

Per my instructions — fix only what the review actually raised, and don't invent scope — I did not touch AgentFixProbe.tsx/.module.scss. The four defects the PR description calls out (clickable div with no keyboard path, multi-property inline styles, hardcoded hex, any props) were deliberately planted for claude-review to catch; since no comment flagging them reached me, "fixing" them now would be guessing at review content rather than addressing it, and would undermine what this probe is actually testing.

No commits pushed. The CLAUDE.md modification showing in the working tree is pre-existing local state unrelated to this PR's diff — left untouched.

Worth checking on the pipeline side: if claude-review did leave inline comments and the published count was >0 (which is presumably what gated this claude-fix run), then this is a real gap — the fix job's context isn't picking up the comments the review job left on the head commit. Worth checking the count job's output against what actually reached this run.

MaryWylde and others added 3 commits September 7, 2026 21:27
The action defaults to claude-sonnet-5 and neither job set a model, so both
were running on the default. Pin both to claude-opus-5.

Review quality is the entire point of the review job — a defect it misses costs
more than the tokens it saved. The fix job matters more still: it writes code
and pushes it with nobody watching, so its judgement about which review
comments are worth acting on, and which are wrong, is the thing standing
between an unattended agent and a bad commit.

Note for quota: Opus draws down the Max subscription faster than Sonnet, and
each PR can now run both jobs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
First live run: claude-review posted 5 inline comments, claude-fix triggered
correctly, and then did nothing — its injected PR context arrived with no
review comments at all, so it reported 'no inline review comments were present'
and declined to guess. That was the right call by the fixer and a real gap in
the pipeline: the trigger said there were findings, the payload did not carry
them.

Collect the comments for the head commit in a workflow step and write them to
.review-findings.json, which the prompt names as the authoritative list. Two
reasons to prefer that over letting the fixer query GitHub: it is deterministic,
and it keeps unscoped gh out of the allowlist of the one job that writes code
unattended. The file is added to .git/info/exclude so it cannot be committed.

The prompt now also says to stop if the file is empty, rather than going
looking for things to fix.

Turned on show_full_output for this job too — the 9 permission denials behind
the first failure were invisible without it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A fix job woken with findings that produces no commit exits 0 and shows the
same green tick as one that fixed everything — which is exactly what happened
on the first live run. Compare the head before and after; if it did not move,
warn, label agent:needs-human, and fail.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@MaryWylde MaryWylde removed the agent:review-ready Claude's PR review finished and left findings — ready for a fixer agent label Sep 7, 2026
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

Claude finished @MaryWylde's task in 3m 55s —— View job


Claude finished the review

  • Gather context (what changed since the last review pass)
  • Read the probe component and the workflow change
  • Post inline comments
  • Post final summary

Summary

Reviewed 98e82d1...HEAD — 5 files, +268/−0. 7 inline comments posted.

First, the thing that matters for what this PR is actually testing: the branch was rebased at 19:27 UTC (f9cf523, 0559399, 8eb0bbf all carry that timestamp), so the head SHA moved out from under the 19:01 review. Those five earlier comments are anchored to a SHA that no longer exists on this branch, which means the signal step's commit_id == HEAD_SHA filter would count zero of them. The probe's defects are all still present in the tree — the earlier claude-fix run was right to refuse rather than guess. This pass re-posts them against the current head, which is what the new .review-findings.json handoff needs in order to be exercised at all.

AgentFixProbe.tsx / .module.scss / index.tsx — the five planted defects, all confirmed present:

  1. AgentFixProbe.tsx:16-22 — clickable div, no role/tabIndex/key handler. Not reachable by Tab, not operable by Enter/Space, announced as static text.
  2. AgentFixProbe.tsx:19 — three static properties in an inline style; AGENTS.md allows inline styles only for a single dynamic value. #7a5c3e and borderRadius: '4px' also bypass --brown-100 and --radius-control.
  3. AgentFixProbe.tsx:7-8onPick: (value: any) and tone: any. onPick only ever receives label (a string); tone is rendered as a text node, so any permits values React throws on.
  4. AgentFixProbe.module.scss:7-16 — four hardcoded hex values. One is more than a convention miss: .tone at #9a8f7a on the library's warm paper is roughly 2.6:1, under the 4.5:1 floor the font passport sets for 13px text.
  5. index.tsx:1export * against a named export, where AGENTS.md requires a default re-export. Should also be index.ts.

.github/workflows/claude-code-review.yml — two findings that aren't part of the probe:

  1. :151-154 (and the same --jq at :227-229) — the finding count filters on commit_id alone, but that endpoint returns every review comment on the PR. A human's inline note on the head commit, or a reply in an existing thread, counts as a finding: it wakes claude-fix, gets written into .review-findings.json as authoritative, and an agent with contents: write rewrites code from a conversational remark. Filtering on user.login and in_reply_to_id == null makes both queries mean what the comments around them claim.
  2. :288-304 — the no-loop property has a second consequence the design notes don't draw out: since the GITHUB_TOKEN push starts no workflows, nothing ever compiles the fix commit. Not this workflow, not the build. An agent writes TypeScript unattended, pushes it, and the PR carries the green tick from the run that produced it. This step catches "pushed nothing"; "pushed something broken" is the likelier failure and currently passes silently. A tsc --noEmit + eslint step after Claude Fix closes it.

The rest of the workflow logic reads correctly. The needs/if gate, the round guard's use of the commits API (with the accurate note about why git log base..HEAD can't work under actions/checkout), the .git/info/exclude trick to keep the findings file uncommittable, and clearing agent:review-ready before the review rather than after — that last one in particular is the right call, and the reasoning in the comment is sound.

AGENTS.md — accurately describes what the workflow does; nothing to flag.

Gap in this review: no build, typecheck or lint was run. This job's allowlist is read-only git plus the inline-comment tool, with no yarn install, so every finding above is from reading the diff. Finding 7 is the direct consequence of that same gap on the fix side.
· Branch: test/claude-fix-probe

Comment on lines +16 to +22
<div
className={styles.pill}
onClick={() => onPick(label)}
style={{ color: '#7a5c3e', padding: '6px 10px', borderRadius: '4px' }}
>
{label}
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accessibility: clickable div with no keyboard path. onClick on a plain div with no role, tabIndex or key handler means the control cannot be reached by Tab, cannot be operated by Enter/Space, and is announced to screen readers as static text.

Use a real <button type="button"> and reset its default chrome in the SCSS module — that gets focus, key activation and the correct role for free, rather than reimplementing all three:

Suggested change
<div
className={styles.pill}
onClick={() => onPick(label)}
style={{ color: '#7a5c3e', padding: '6px 10px', borderRadius: '4px' }}
>
{label}
</div>
<button
type="button"
className={styles.pill}
onClick={() => onPick(label)}
>
{label}
</button>

Then in AgentFixProbe.module.scss, .pill needs border: none-style resets replaced by the explicit values it already sets, plus font: inherit so the button doesn't inherit the UA font.

Fix this →

<div
className={styles.pill}
onClick={() => onPick(label)}
style={{ color: '#7a5c3e', padding: '6px 10px', borderRadius: '4px' }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inline styles, and none of them dynamic. AGENTS.md permits inline styles only for a single dynamic property (style={{ color: dynamicValue }}). All three values here are static, so they belong in AgentFixProbe.module.scss alongside .pill.

Two of them also bypass the design tokens: #7a5c3e is a hardcoded brown (the library palette already has --brown-100: #7b4a24), and borderRadius: '4px' contradicts --radius-control, which is 0 in src/styles/library/variables.scss. Padding on a 4px grid per the Library design passport — 8px 12px rather than 6px 10px.

Drop the style prop entirely and fold this into .pill:

.pill {
  padding: 8px 12px;
  border-radius: var(--radius-control);
  color: var(--brown-100);
}

Fix this →

Comment on lines +7 to +8
onPick: (value: any) => void;
tone: any;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both anys are avoidable. onPick is only ever called with label, which is already string, so the parameter type can be exact. tone is rendered directly as a text node, so any here also silently permits values React cannot render (an object throws at runtime); a union of the tones the probe actually supports both documents the contract and makes the call sites exhaustive.

Suggested change
onPick: (value: any) => void;
tone: any;
onPick: (value: string) => void;
tone: 'calm' | 'warn';

If the intended set of tones is wider than those two, widen the union rather than falling back to string — the point is that an unknown tone fails at the call site, not in the DOM.

Fix this →

Comment on lines +7 to +16
.pill {
background: #e8d9b8;
border: 1px solid #533a3a;
cursor: pointer;
}

.tone {
color: #9a8f7a;
font-size: 13px;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Four hardcoded hex values, one of which fails the contrast floor. Every sibling atom in src/components/library/atoms/ (see CharCount.module.scss) reads straight from the library custom properties in src/styles/library/variables.scss — no import needed, just var(--token). These bypass that set entirely, so they won't follow the palette and won't respond to theming.

Separately, .tone at #9a8f7a on the library's warm paper (--white-200: #fffcf7) lands around 2.6:1, under the 4.5:1 floor the font passport sets for 13px text. That one is a real defect, not just a convention miss — swapping in the token fixes it.

Suggested change
.pill {
background: #e8d9b8;
border: 1px solid #533a3a;
cursor: pointer;
}
.tone {
color: #9a8f7a;
font-size: 13px;
}
.pill {
padding: 8px 12px;
border-radius: var(--radius-control);
color: var(--brown-100);
background: var(--white-100);
border: 1px solid var(--brown-border);
cursor: pointer;
}
.tone {
color: var(--black-transparent-300);
font-size: 13px;
}

Fix this →

@@ -0,0 +1 @@
export * from './AgentFixProbe';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Barrel breaks the convention twice over. AGENTS.md ("Component Pattern → Exports") requires export default from the component and a default re-export from the barrel; export * against a named export is neither. It also means consumers get import { AgentFixProbe } from '...' while every other component in the repo is a default import.

The file should also be index.ts, not index.tsx — it holds no JSX.

Suggested change
export * from './AgentFixProbe';
import AgentFixProbe from './AgentFixProbe';
export default AgentFixProbe;

and in AgentFixProbe.tsx, change export function AgentFixProbe to a plain const with export default AgentFixProbe; at the bottom.

Fix this →

Comment on lines +151 to +154
findings=$(gh api "repos/$REPO/pulls/$PR/comments" --paginate \
--jq "[.[] | select(.commit_id == \"$HEAD_SHA\")] | length")
echo "inline findings on $HEAD_SHA: $findings"
echo "findings=${findings:-0}" >> "$GITHUB_OUTPUT"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This counts every inline comment on the head SHA, not just the review's. repos/{repo}/pulls/{pr}/comments returns all review comments on the PR — human-authored ones and thread replies included — and the filter is only on commit_id.

Concrete consequence: a human leaves one inline note on the head commit ("nice, but why not X?"). findings becomes 1, claude-fix wakes, the collect step at line 227 hands that human's sentence to the fixer as an authoritative finding, and an unattended agent with contents: write edits code and pushes based on a conversational remark. Replies inside an existing thread do the same, so a human answering the bot's own comment re-arms the fixer.

Filtering by author and excluding replies makes both queries mean what the surrounding comments say they mean:

Suggested change
findings=$(gh api "repos/$REPO/pulls/$PR/comments" --paginate \
--jq "[.[] | select(.commit_id == \"$HEAD_SHA\")] | length")
echo "inline findings on $HEAD_SHA: $findings"
echo "findings=${findings:-0}" >> "$GITHUB_OUTPUT"
findings=$(gh api "repos/$REPO/pulls/$PR/comments" --paginate \
--jq "[.[] | select(.commit_id == \"$HEAD_SHA\"
and .user.login == \"github-actions[bot]\"
and .in_reply_to_id == null)] | length")
echo "inline findings on $HEAD_SHA: $findings"
echo "findings=${findings:-0}" >> "$GITHUB_OUTPUT"

The same predicate belongs on the --jq at line 228 so the fixer's .review-findings.json matches the count that woke it.

Fix this →

Comment on lines +288 to +304
- name: Did it actually change anything
if: steps.guard.outputs.proceed == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR: ${{ github.event.pull_request.number }}
REPO: ${{ github.repository }}
BEFORE: ${{ github.event.pull_request.head.sha }}
run: |
after=$(git rev-parse HEAD)
echo "head before: $BEFORE"
echo "head after: $after"
if [ "$after" = "$BEFORE" ]; then
echo "::warning::claude-fix was woken with findings but pushed nothing."
gh pr edit "$PR" --repo "$REPO" --add-label "agent:needs-human" 2>/dev/null || true
exit 1
fi
echo "pushed $(git rev-list --count "$BEFORE..$after") commit(s)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing ever compiles the code this job pushes. The no-loop property is that the GITHUB_TOKEN push doesn't start workflows — which is exactly right for review chaining, but it also means no workflow runs on the fix commit: not this one, not the build. So an unattended agent writes TypeScript, commits, pushes, and the PR shows the green tick from the run that produced it. A fix that doesn't typecheck sits on the branch looking merged-ready until a person happens to push again.

This step catches "pushed nothing"; the more likely failure is "pushed something broken". Worth a verification step between Claude Fix and this one, on the working tree the fixer left:

- name: Check the fix compiles
  if: steps.guard.outputs.proceed == 'true'
  run: |
    yarn install --frozen-lockfile
    npx tsc --noEmit
    npx eslint src --max-warnings=0

Failing there leaves the commit pushed but the run red, which is the honest signal. Belt-and-braces would be to run it before the push, but the fixer owns its own push, so a red run plus agent:needs-human is the smaller change.

Separately, BEFORE on line 294 is the event payload's SHA rather than the SHA actually checked out at line 179. They're the same in practice (cancel-in-progress kills the run when the branch moves), but git rev-parse HEAD captured right after checkout is what this comparison actually means.

Fix this →

@github-actions github-actions Bot added the agent:review-ready Claude's PR review finished and left findings — ready for a fixer agent label Sep 7, 2026
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

Claude finished @MaryWylde's task in 3m 37s —— View job


claude-fix: 5 findings addressed, 2 skipped

.review-findings.json was present and non-empty: 12 entries, which collapse to 5 distinct issues in the probe component plus 2 on the workflow file (the review made two passes over the same code, so each component finding appears twice — a terse version and a fuller one with a suggestion block).

  • Read .review-findings.json — authoritative list
  • Read the probe component and sibling atoms for local convention
  • Judge each finding
  • Apply fixes
  • Commit with [agent-fix] and push
  • Summarize per comment

Pushed 8eb0bbf..3f1c0e2 — three commits, one per distinct fix.


Per finding

# Finding Outcome
1 AgentFixProbe.tsx:22 — clickable div, no keyboard path Fixed
2 AgentFixProbe.tsx:19 — multi-property inline style, hardcoded hex Fixed
3 AgentFixProbe.tsx:7-8any on onPick and tone Fixed, with a caveat
4 AgentFixProbe.module.scss — hardcoded hex, contrast failure Fixed
5 index.tsx:1 — barrel convention Fixed, but see the note
6 claude-code-review.yml:154 — jq counts human comments too Skipped — cannot edit workflows
7 claude-code-review.yml:304 — nothing compiles the fix commit Skipped — cannot edit workflows

1 — keyboard path. Correct and the most substantive of the five. Replaced the div with <button type="button"> rather than bolting on role/tabIndex/onKeyDown, per the review's own preference — the real element brings focus, Enter/Space activation and the correct role without reimplementing three behaviours. Added font: inherit to .pill so the button doesn't pick up the UA font.

2 and 4 — inline styles and tokens. Correct. All three inline values were static, so AGENTS.md's single-dynamic-property allowance never applied; they now live in .pill. Four hex values swapped for tokens in src/styles/library/variables.scss: --brown-100, --white-100, --brown-border, --black-transparent-300. Padding moved to the 4px grid and radius to --radius-control per the Library design passport.

The contrast claim checks out, though the number was off — #9a8f7a on the library's warm paper is about 3.1:1, not 2.6:1. Either way it's under the 4.5:1 floor the font passport sets for 13px text, so the conclusion stands; --black-transparent-300 clears it at roughly 6.3:1.

3 — the anys. onPick: (value: string) => void is exact, since label is the only value ever passed. On tone I applied the suggested 'calm' | 'warn' — but those two names are the reviewer's invention, not an established vocabulary. There are no call sites to infer the real set from. The union removes the actual hazard (any let a non-renderable object through to a text node), so it's an improvement either way; whoever owns this component should confirm or widen the set.

5 — the barrel. Applied, and worth a second look. AGENTS.md is unambiguous — export default from the component, default re-export from the barrel, and "named exports in index.ts barrel files" sits under Things to Never Do. So the review is right on the letter.

But every other component under src/components/library/ — 60-odd across atoms, molecules and organisms — uses the named-export plus export * pattern in an index.tsx. The immediate sibling, CharCount, is identical to what the probe originally had. This change makes AgentFixProbe correct per AGENTS.md and simultaneously the only one of its kind in that subtree. It's safe here because nothing imports the probe yet, so I applied it. The decision that actually matters isn't this file — it's whether AGENTS.md or the library/ subtree describes the convention going forward, and that's a human call.

6 and 7 — the workflow findings. I'm unable to modify files in .github/workflows — the GitHub App's permissions do not allow workflow modifications (FAQ). Both are left untouched. They look right to me on reading, and #6 in particular is a security-relevant point rather than a style one: the --jq filters key only on commit_id, so a human's inline remark on the head commit is enough to arm an unattended agent with contents: write. That one deserves a human fix.


Two things the probe surfaced

The fix commits weren't compiled. node_modules isn't present in this job and I can't run yarn install, so I could not run tsc --noEmit or eslint. The changes are small and mechanical, but they went to the branch unverified — which is exactly the gap finding #7 describes. Since the GITHUB_TOKEN push starts no workflow, nothing downstream will check them either.

The round guard counts commits, not rounds. I was told "one commit per distinct fix where that is natural" and produced three [agent-fix] commits in a single pass. The guard trips at two [agent-fix] commits on a branch. So following the commit guidance as written trips, on the first fix round, a guard meant to stop the second — the next review on this branch would label it agent:needs-human and refuse to fix. Counting distinct fix runs (or commits whose SHAs postdate the last human push) would match the intent.

The no-loop property held: the push above triggered nothing.
· Branch: test/claude-fix-probe

…ken-driven

Review findings on PR #198:

- The clickable div had no keyboard path (no role/tabIndex/key handler), so
  it was unreachable by Tab and announced as static text. Replaced with a
  real <button type="button">, which brings focus, Enter/Space activation
  and the correct role without reimplementing them.
- The static multi-property inline style is gone; AGENTS.md permits inline
  styles only for a single dynamic property. Folded into .pill.
- Hardcoded hex values replaced with library tokens from
  src/styles/library/variables.scss. .tone at #9a8f7a on library paper sat
  around 3:1, under the 4.5:1 floor the font passport sets for 13px text;
  --black-transparent-300 clears it.
- Padding moved onto the 4px grid and border-radius onto --radius-control
  per the Library design passport.
onPick is only ever called with label, which is already string, so the
parameter type can be exact. tone is rendered directly as a text node, where
any silently permits values React cannot render.

The two tone names are the review's suggestion, not an established
vocabulary - there are no call sites yet to infer the real set from. Widen
the union if the probe grows more tones; the point is that an unknown tone
fails at the call site rather than in the DOM.
AGENTS.md ("Component Pattern -> Exports", and "Things to Never Do") requires
export default from the component and a default re-export from the barrel;
export * against a named export is neither. Barrel renamed to index.ts as it
holds no JSX.

Flagging for a human: every other component under src/components/library/
- 60-odd across atoms, molecules and organisms - uses the named-export plus
export * pattern in an index.tsx. This change makes AgentFixProbe correct per
AGENTS.md and simultaneously the only one of its kind in that subtree. It is
safe here because nothing imports the probe yet, but the real decision is
whether AGENTS.md or the library/ subtree is the convention going forward.
@MaryWylde

Copy link
Copy Markdown
Contributor Author

Probe complete — the pipeline works. Second run produced three [agent-fix] commits covering all five planted defects.

Closing without merging: this branch exists only to carry the throwaway AgentFixProbe component, which has no business in the repo. The real change is #199.

@MaryWylde MaryWylde closed this Sep 7, 2026
@MaryWylde
MaryWylde deleted the test/claude-fix-probe branch September 7, 2026 20:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent:review-ready Claude's PR review finished and left findings — ready for a fixer agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant