docs: recommend the @v1 release tag for reusable-workflow consumers #12
Reference in New Issue
Block a user
Delete Branch "docs/recommend-v1"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Makes the public contract match how the fleet now pins. The example stub + README pointed at
@main/@<sha>; update to recommend@v1— gadfly's curated release tag, re-moved on deliberate releases so central swarm tuning propagates without per-consumer re-pinning. A full@<sha>is still offered for an immutable pin;@mainis discouraged (moves on every push).examples/reusable.yml:uses: …@main→@v1+ updated pin comments.README.md: pin guidance now covers the reusable workflow ref (@v1/@<sha>), not just the image:vNtag.Docs-only. Advisory-only invariant unchanged.
🤖 Generated with Claude Code
🪰 Gadfly — live review status
6/6 reviewers finished · updated 2026-06-28 04:14:05Z
claude-code/opus· claude-code — ✅ doneclaude-code/opus:max· claude-code — ✅ doneclaude-code/sonnet· claude-code — ✅ donedeepseek-v4-pro:cloud· ollama-cloud — ✅ doneglm-5.2:cloud· ollama-cloud — ✅ doneminimax-m3:cloud· ollama-cloud — ✅ doneLive status board. Findings are posted in each model's own comment. Advisory only — does not block merge.
🪰 Gadfly review —
deepseek-v4-pro:cloud(ollama-cloud)Verdict: Minor issues — 5 reviewers: security, correctness, maintainability, performance, error-handling
🔒 Security — No material issues found
Verdict: No material issues found
This is a docs-only change that steers consumers from
@main(moves on every push — highest supply-chain risk) toward either@v1(curated release tag, moves only on deliberate releases) or@<sha>(immutable). From a security perspective, this is a net improvement: it reduces the window during which a compromised push tomainwould silently propagate into every consumer's workflow with their forwarded secrets.@v1auto-updates on releases (convenience, central tuning propagates) vs.@<sha>(immutable, no surprise changes). Both are strictly better than@main, which the diff now explicitly discourages.One minor observation (not a security issue, but noted for completeness): the reusable workflow's own doc comment at
.gitea/workflows/review-reusable.yml:28still says "Consumers should likewise pinuses: ...@<sha>(not @main)" without mentioning@v1. That file wasn't in this diff, so it's outside scope, but it's now slightly out of step with the new guidance.🎯 Correctness — Minor issues
Now I have all the information I need. Let me evaluate each finding:
Finding 1 (
@v1tag may not exist): The draft reviewer explicitly labels this as "Unverified" and acknowledges it's a shallow clone where the tag could exist on the remote. I confirmed there is no localv1tag. Since the reviewer themselves cannot confirm it, and I also cannot positively confirm it (the tag's absence in a shallow clone of a feature branch proves nothing), this finding must be dropped per the instructions: "DROP the finding if you cannot confirm it."Finding 2 (docstring drift): I confirmed that
.gitea/workflows/review-reusable.ymlwas not modified in this diff. Its header comment at line 9 still documents the consumer call as@<sha>only, and lines 28-29 still say "Consumers should likewise pinuses: ...@<sha>(not @main)." Meanwhile, the PR updatesexamples/reusable.ymlandREADME.mdto recommend@v1. This is a real inconsistency — the reusable workflow's own docstring contradicts the new guidance. Kept.Verdict: Minor issues
.gitea/workflows/review-reusable.yml:9still documents the consumer call as@<sha>only:uses: ...@<sha>(not @main)." This file is not in the diff, but it's the canonical documentation inside the workflow being referenced. Now the example stub says@v1while the reusable workflow's own docstring says@<sha>with no mention of@v1. A consumer who opens the reusable workflow to understand their pin options will see only the@<sha>recommendation — contradicting the new guidance. Not a runtime bug, but a correctness-of-documentation inconsistency that undermines the PR's purpose.🧹 Code cleanliness & maintainability — Minor issues
Verdict: Minor issues
.gitea/workflows/review-reusable.yml:9,28-29— stale pin guidance in the reusable workflow's own header comment. The PR updates consumer-facing docs (examples/reusable.yml,README.md) to recommend@v1as the primary ref, but the reusable workflow's own docstring still saysuses: ...@<sha>(line 9) and "Consumers should likewise pinuses: ...@<sha>(not @main)" (lines 28-29) with no mention of@v1. A maintainer reading this file gets different guidance than a consumer reading the examples. Over time these two sources of truth will drift further. (Verified by reading the file at lines 1-30.)Fix: Update lines 9 and 28-29 to match the new guidance — e.g.,
@v1(or@<sha>) and mention the curated-tag approach, so the reusable workflow's own documentation stays in sync with the consumer-facing examples.⚡ Performance — No material issues found
Verdict: No material issues found
This is a docs-only change — it updates comments in
examples/reusable.ymland guidance inREADME.mdto recommend@v1(a curated release tag) over@mainfor the reusable workflow ref. There is no code, no logic, no runtime path, and therefore nothing to evaluate through the performance lens. The change has zero impact on allocations, queries, loops, blocking calls, or any other performance characteristic.🧯 Error handling & edge cases — No material issues found
Verdict: No material issues found
This is a docs-only change — it updates comments in
examples/reusable.ymland prose inREADME.md. There are no code paths, no new functions, no error returns, no panics, and no data handling introduced. The error-handling & edge-cases lens (ignored errors, missing cleanup/rollback, panics on bad input, nil/empty/zero/negative/overflow/off-by-one) has nothing to evaluate here.The one thing that brushes against "edge case" territory — whether the
@v1tag actually exists on the repo right now (if it doesn't, consumers following the new guidance would get an immediate workflow-resolution failure) — is a deployment-coordination concern, not an error-handling defect in the diff. I can't verify tag existence with the available file-reading tools, but even if the tag were missing, that's a release-process gap, not something the diff's code/configuration mishandles.Automated adversarial review by Gadfly. Advisory only — does not block merge. · ⏱️ reviewed in 2m 13s
🪰 Gadfly review —
glm-5.2:cloud(ollama-cloud)Verdict: Minor issues — 5 reviewers: security, correctness, maintainability, performance, error-handling
🔒 Security — No material issues found
VERDICT: No material issues found
Reviewed through the security lens. This is a docs-only change adjusting pin guidance for the reusable-workflow
uses:ref.examples/reusable.yml:54now pins@v1instead of@main, and the comment block (:17-20,:52-53) accurately explains the security trade-off:@v1is a curated tag moved only on deliberate releases (so central tuning propagates),@<sha>is offered for an immutable pin, and@mainis explicitly discouraged because it moves on every push and "would change what runs with your forwarded secrets." The least-privilege secrets-forwarding guidance (:14-16,:58-62) and the comment-trigger actor gate (:49-51,github.actor == 'your-username') are untouched and remain sound.README.md:315-318mirrors the same guidance consistently. No secret leakage, injection, authn/authz, or unsafe-input handling is introduced — the only tainted surface (forwarded secrets to a third-party workflow) is already addressed by the explicitsecrets:block advice, which this PR preserves.The change is a net security improvement (moving the recommended example off the highest-churn mutable ref while still documenting the immutable option). Nothing in my lane to flag.
🎯 Correctness — Minor issues
The finding is confirmed. Lines 9 and 28-29 of
.gitea/workflows/review-reusable.ymlstill recommend@<sha>with no mention of@v1, directly contradicting the updated README andexamples/reusable.ymlguidance.VERDICT: Minor issues
.gitea/workflows/review-reusable.yml:9and:28-29— The PR rewrites the pin guidance inREADME.mdandexamples/reusable.ymlto recommend@v1as the primary ref (with@<sha>as the immutable alternative, avoid@main), but the reusable workflow's own header comments — consumer-facing documentation embedded in the file consumers actually point at — were not updated. Line 9's example still shows...review-reusable.yml@<sha>with no mention of@v1, and lines 28–29 explicitly state "Consumers should likewise pinuses: ...@<sha>(not @main)", framing@<sha>as the recommendation. This now directly contradicts the new README/example guidance (@v1first,@<sha>as the immutable alternative). A consumer reading the workflow file they're subscribing to gets the old, conflicting advice. Suggested fix: update those two comment spots to match the new@v1-first /@<sha>-immutable / avoid-@mainordering. (Note: thev1git tag's existence could not be confirmed with read-only tools; worth verifying it exists before/with merge so the example's@v1ref resolves.)🧹 Code cleanliness & maintainability — No material issues found
No material issues found.
The diff is docs/comment-only and cleanly updates the pin guidance to
@v1consistently across both files. The example file (examples/reusable.yml) and README prose both use the same framing (@v1curated release tag → auto-updating stability;@<sha>→ immutable pin; avoid@main), so the duplicated messaging stays consistent rather than drifting. No dead code, naming, or structural concerns introduced.⚡ Performance — No material issues found
No material issues found.
This is a docs-only change (comments in
examples/reusable.ymland prose inREADME.md) updating recommended pin references (@main→@v1). It touches no runtime code, queries, loops, allocations, or hot paths — there is nothing to evaluate through the performance lens.🧯 Error handling & edge cases — No material issues found
No material issues found
This is a docs-only change: it rewrites comments in
examples/reusable.yml(lines 17-20, 52-54) and prose inREADME.md(lines 315-318) to recommend@v1over@main. No executable code, logic, error-handling, input parsing, or control flow is touched.Through the error-handling / edge-case lens specifically:
uses:ref (@main→@v1), which is a ref string, not logic. A missing/non-existent@v1tag would surface as a Gitea Actions checkout/reusable-resolution failure at job start (same failure mode as any bad ref), not a swallowed error or panic in this repo's code.Nothing in my lane to flag.
Automated adversarial review by Gadfly. Advisory only — does not block merge. · ⏱️ reviewed in 1m 10s
🪰 Gadfly review —
claude-code/sonnet(claude-code)Verdict: Blocking issues found — 5 reviewers: security, correctness, maintainability, performance, error-handling
🔒 Security — Minor issues
The finding is confirmed. Lines 28-29 of
review-reusable.ymlstill saypin uses: ...@<sha> (not @main), which directly contradicts the new guidance inexamples/reusable.ymlthat recommends@v1as the primary recommendation. The second finding (mutable tag trust model) is a design-level observation about the PR's documented intent — the PR description acknowledges the tradeoff — and there is no code to confirm or deny it against; it's a documentation quality concern the draft labels as intentional.Minor issues
review-reusable.ymlstill contradicts the new guidance (review-reusable.yml:28-29):The reusable workflow's own header comment still says:
The updated example stub now defaults to
@v1(mutable tag), but this authoritative comment in the reusable workflow was not updated. A security-aware consumer readingreview-reusable.ymldirectly will get the opposite recommendation from what the example stub models — the two pieces of guidance now contradict each other.Suggested fix: Update
review-reusable.ymllines 28–29 to align with the new guidance (e.g., mention@v1as the recommended starting point and@<sha>for an immutable pin).🎯 Correctness — Blocking issues found
The git repository has no tags at all —
git tag -lreturns empty, andpacked-refscontains only the remote branch ref. The build-image workflow (lines 73–74) confirms it publishes Docker image tags in response to a pushedv*git tag, but it does not create the git tag itself. The diff inexamples/reusable.yml:54changes@mainto@v1, andREADME.mdinstructs consumers to pinreview-reusable.yml@v1. The finding is confirmed.Blocking issues found
@v1tag does not exist —examples/reusable.yml:54/README.md:315No
v1git tag has been pushed to this repository (git tag -lreturns empty;.git/packed-refscontains only the remote branch ref fordocs/recommend-v1). The diff changesuses: …@maintouses: steve/gadfly/.gitea/workflows/review-reusable.yml@v1and updates the README to tell consumers to pinreview-reusable.yml@v1, but in Gitea Actions the@refin auses:directive resolves to a live git ref. A consumer who follows this guidance right now will get a workflow resolution failure — the ref simply doesn't exist.The build-image workflow (
.gitea/workflows/build-image.yml:21,73-74) publishes Docker image tags when av*git tag is pushed; it does not create the git tag itself. Git tags must be pushed separately viagit tag v1 && git push origin v1.Fix: Push a
v1git tag to the repository (or the release cut that creates it) before — or atomically with — merging this PR. Without that tag, any consumer following the updated docs or example stub will have a broken workflow.🧹 Code cleanliness & maintainability — Minor issues
Verdict: Minor issues
README:315 — terminology mismatch. The PR introduces the term "full-stub consumers" in the Release section (line 315), but the README's own intro (lines 40–44) refers to the same
adversarial-review.ymlpath as "the full self-containedadversarial-review.yml". A reader scanning only the Release section encounters "full-stub consumers" without a prior definition tying it toadversarial-review.yml; the intro's "full self-contained" phrasing is the more anchored reference. Fix: match the intro's wording — e.g."Pin full-self-contained-stub consumers…"or append(\adversarial-review.yml`)` inline. Verified against README lines 39–46 and 313–318.Slightly inconsistent phrasing for the same concept across files.
@v1is described three ways:examples/reusable.ymlline 18: "a curated pointer moved on deliberate releases"examples/reusable.ymlline 52: "curated release tag (auto-updates on releases)""Tag" vs "pointer," "moved on releases" vs "moved on deliberate releases" vs "auto-updates on releases" — not a runtime issue, but when the wording drifts across three spots for the same concept, the next editor won't know which phrasing is authoritative and will need to update all three again. Picking one phrasing and using it consistently reduces future churn. Verified by reading both files.
Neither finding is blocking. The docs are broadly coherent and the actual
@v1pin onexamples/reusable.yml:54is correctly placed.⚡ Performance — No material issues found
No material issues found.
This is a docs-only change (README prose and a comment +
uses:ref in an example YAML). There is no executable code, no queries, no allocations, no loops, and no hot paths touched. Nothing to evaluate through a performance lens.🧯 Error handling & edge cases — No material issues found
No material issues found
This is a pure documentation change — updated prose in
README.mdand revised comments plus a singleuses:ref string inexamples/reusable.yml. There are no code paths, error returns, input handling, or runtime logic of any kind introduced or modified. My lens (error handling & edge cases) has nothing to evaluate here.Automated adversarial review by Gadfly. Advisory only — does not block merge. · ⏱️ reviewed in 3m 30s
🪰 Gadfly review —
claude-code/opus:max(claude-code)Verdict: Minor issues — 5 reviewers: security, correctness, maintainability, performance, error-handling
🔒 Security — No material issues found
VERDICT: No material issues found
This is a docs-only change to supply-chain pinning guidance, which is squarely in scope for the security lens — so I checked it on the merits rather than waving it through.
examples/reusable.yml:54and the surrounding comment (:17-20,:52-53), plusREADME.md:315-318— the change swaps the recommended reusable-workflow ref from@mainto@v1. Verified by reading both files at the PR state. Security-relevant facts:uses:ref is a genuine supply-chain control.@v1is a mutable tag ("re-moved on deliberate releases"), meaning a moved/compromisedv1would execute new code against forwarded secrets.@main, which mutates on every push (strictly larger attack surface).@v1moves only on deliberate releases.@<sha>pin for consumers who want it, and explicitly discourages@main. This mirrors standard practice (actions/checkout@v4).secrets:forwarding oversecrets: inherit) is preserved (:14-16,:55-62).No injection, secret leakage, authz, or untrusted-data handling is introduced or weakened. Nothing material in my lane.
One note, not a finding: a careless copy-paste consumer gets a mutable pin by default — but that's already mitigated by the explicit inline comment recommending
@<sha>, and it's a security upgrade over the previous@maindefault.🎯 Correctness — No material issues found
I've verified the change against the actual repo. My investigation is complete.
VERDICT: No material issues found
This is a docs-only change. Through the Correctness lens, the factual claims hold up against how the system actually works, and the two edited files are internally consistent.
What I verified:
@v1claim is consistent with the release model. README:317 andexamples/reusable.yml:52describe@v1as a curated tag "moved on releases" so swarm tuning propagates. I confirmed the mechanism:review-reusable.yml:93hardcodes the image at:sha-c342bdband its header (:26-27) says that sha is "bumped per Gadfly release." So re-pointing thev1git tag to a newer commit does propagate a newer pinned image — the auto-update story is coherent, not contradictory. A force-movedv*tag also re-triggersbuild-image.yml(:19-21), republishing:v1/:latest, so the image and workflow-ref stories line up.:vNimage vs@v1workflow-ref guidance is accurate.build-image.yml:73-74publishes:${GITHUB_REF_NAME}(+:latest) on av*tag push, matching README:315's:vNadvice.examples/, and CLAUDE.md: every consumer-facing ref now recommends@v1/@<sha>and discourages@main; README:41 uses a neutral@…placeholder. No leftover@mainrecommendation that would contradict the new guidance.steve/gadfly/.gitea/workflows/review-reusable.ymlmatches the registry pathgitea.stevedudenhoeffer.com/steve/gadfly; only the ref suffix changed.One caveat I could not verify (flagging, not asserting as a bug):
v1tag.git tag -lreturns nothing at this checkout, and I was denied network access togit ls-remote, so I cannot confirm av1tag actually exists on the remote yet. If the release process cuts only semver tags (e.g.v1.0.0) and never pushes/moves a barev1, then a consumer copy-pastingexamples/reusable.yml:54(...review-reusable.yml@v1) would hit a workflow-resolution failure, and:v1image pins would also break. This is a release-process/sequencing concern external to the diff text — worth a one-line confirmation from the author that thev1tag is (or will be) published before/with these docs, but it is not a logic defect in the change itself.Outside my lens: none worth raising.
🧹 Code cleanliness & maintainability — Minor issues
Both findings verify against the code.
review-reusable.yml:9still shows…@<sha>and:28still sayspinuses: ...@(not @main)with no mention of@v1, whileREADME.md:317-318andexamples/reusable.ymlnow lead with@v1. Andgit tag -lis empty — nov1tag exists.VERDICT: Minor issues
Finding — stale duplicate of the pin guidance left un-updated (
@<sha>/@main, no@v1).gitea/workflows/review-reusable.yml:9and:28The "how to pin the reusable" advice exists in three consumer-facing places. This PR updated two of them (
README.md:315-318,examples/reusable.yml:17-19,52-54) to recommend@v1, but the third copy — the worked consumer-stub example and pin note in the reusable workflow's own header — still reads:uses: steve/gadfly/.gitea/workflows/review-reusable.yml@<sha>Consumers should likewise pinuses: ...@(not @main)…So the contract now gives inconsistent guidance depending on which file a consumer opens: README/example say "use
@v1, sha is the immutable alternative," whilereview-reusable.yml's header still presents@<sha>as the recommendation and never mentions@v1. CLAUDE.md's maintenance rule ("the example workflows are the contract users rely on — stale docs are a bug") applies directly here.review-reusable.yml:9to…@v1and reword:28to mirror the new phrasing ("pin@v1for auto-updating stability, or@<sha>for an immutable pin; avoid@main"). Keeps the three copies in sync.Note the duplication itself is the root maintainability smell — the same paragraph is now hand-maintained in three spots and has already drifted once. Not worth refactoring docs into a single source here, but the fix above should bring all three back into agreement in this same change.
Outside my lens (flagging because it's potentially blocking):
git tag -lreturns no tags — there is currently nov1tag (or any tag) in the repo. If the curated@v1ref isn't actually created/moved as part of this release, every doc now points consumers at a ref that won't resolve. That's a correctness/release-process concern for another reviewer, not a cleanliness one.Nothing else in my lens: the wording changes in the two edited files are clear, consistent with each other, and follow the surrounding comment style.
⚡ Performance — No material issues found
VERDICT: No material issues found
This is a documentation-only change —
README.mdpin guidance andexamples/reusable.ymlcomments/ref, swapping@main→@v1. There is no code, query, loop, allocation, or hot path touched, so there is nothing for the performance lens to evaluate.uses:workflow ref, which affects which image/workflow consumers pin to, not execution efficiency. Verified by reading the full diff — both hunks are comment text and prose.Nothing in my lane to flag here.
🧯 Error handling & edge cases — No material issues found
VERDICT: No material issues found
This is a docs-only change — prose in
README.mdand YAML comments plus a singleuses:ref string (@main→@v1) inexamples/reusable.yml. There is no executable code, no control flow, and therefore no error paths, cleanup/rollback, boundary conditions, nil/empty handling, or overflow surface for my lens to evaluate.I confirmed from the diff that the only non-comment change is the workflow ref tag in the
uses:line; everything else is comment/prose. Nothing in the error-handling & edge-case lens is materially wrong here.review-reusable.yml@v1. Whether that tag actually exists in the gadfly repo is a real correctness concern (a dangling ref would break every consumer's workflow resolution), but that belongs to the correctness lens, not mine.Automated adversarial review by Gadfly. Advisory only — does not block merge. · ⏱️ reviewed in 2m 20s
🪰 Gadfly review —
claude-code/opus(claude-code)Verdict: Minor issues — 5 reviewers: security, correctness, maintainability, performance, error-handling
🔒 Security — No material issues found
VERDICT: No material issues found
I reviewed this through the security (supply-chain) lens, since the only thing a docs-only change to a pin recommendation can affect is what code runs with a consumer's forwarded secrets. I read both edited files in full (
examples/reusable.yml:14-54,README.md:313-318) to confirm the diff matches the checked-out state.What I checked and why it's not a finding:
Recommending a movable
@v1ref over an immutable@<sha>(examples/reusable.yml:52-54,README.md:316-318). This is the one real security-relevant trade-off:@v1is re-pointed on releases, so whoever controls the gadfly repo can change the code that executes with the consumer's forwarded provider keys /GITEA_TOKEN— exactly the risk the old@<sha>-immutable wording warned about. However, the new text discloses this accurately rather than hiding it: it explains@v1"moves on releases / deliberate releases," still documents@<sha>as the immutable option, and explicitly discourages the worst case@main("moves on every push and would change what runs with your forwarded secrets"). This mirrors the project's already-accepted posture for the image:vNtag (also movable). It's an informed, disclosed product trade-off, not an insecure default introduced silently.Least-privilege secret guidance preserved (
examples/reusable.yml:14-20, 55-62). The edit left the "forward ONLY what the reviewer needs / prefer explicit oversecrets: inherit" guidance and the commented-out optional secrets intact. No widening of secret exposure.No injection, authz, SSRF, deserialization, validation, or credential-leak surface is touched — this is comment/prose only and the binary, scripts, and workflows are unchanged.
🎯 Correctness — Minor issues
I've verified both findings. The
v1tag does exist on the remote (refs/tags/v1→22aff85), so Finding 1 is contradicted by the actual repo state and must be dropped. Finding 2's factual basis is confirmed —review-reusable.ymllines 9 and 28–29 still reference only@<sha>and don't mention@v1— though its "contradiction" framing is overstated (the header recommends@<sha>, which the new guidance still endorses, and warns against@main, which it also still endorses).VERDICT: Minor issues
This is a docs-only change. The factual claims hold up against the code; one surviving consistency gap remains.
Findings (Correctness lens)
.gitea/workflows/review-reusable.yml:28-29(and the example at:9) still tell consumers only to pin@<sha>, never mentioning the newly-recommended@v1. The PR updatedREADME.mdandexamples/reusable.ymlto recommendreview-reusable.yml@v1(curated release tag) as the primary option for reusable-workflow consumers, but the reusable workflow's own subscription instructions — a place a consumer reads to learn how to pin — still say only "Consumers should likewise pinuses: ...@<sha>(not @main)". This isn't a hard contradiction (@<sha>remains a valid form in the new guidance, and both discourage@main), but it's a missed spot: the now-preferred@v1option isn't surfaced where consumers look. A one-block update there to mention@v1would keep the guidance consistent. Confirmed by reading the file; minor docs-consistency item.🧹 Code cleanliness & maintainability — Minor issues
I verified both findings against the actual repo.
Finding 1 (review-reusable.yml:9, :28): Confirmed. Line 9 still shows
...review-reusable.yml@<sha>as the canonical usage example, and line 28 still reads "Consumers should likewise pinuses: ...@<sha>(not @main)". Neither mentions@v1, while this PR makes@v1the primary recommendation inREADME.mdandexamples/reusable.yml. The inconsistency across the three copies of consumer-facing pin guidance is real.Finding 2 (
@v1may not resolve): Cannot positively confirm.git tag -lreturns no tags in this checkout, but the draft itself flags this as unverified and "likely just unfetched tags," and absence of tags locally does not provev1is unpublished. Dropping per the gate rule (keep only what I can confirm).VERDICT: Minor issues
.gitea/workflows/review-reusable.yml:9and:28— Stale/inconsistent pin guidance left behind. This PR updates the@v1recommendation inREADME.mdandexamples/reusable.yml, but the reusable workflow's own header doc comments still say to pin@<sha>and "(not @main)" with no mention of@v1. Line 9's canonical usage example shows...review-reusable.yml@<sha>, and line 28 says "Consumers should likewise pinuses: ...@<sha>(not @main)". After this change the public pin guidance now disagrees across three copies of the same advice. CLAUDE.md treats consumer-facing docs as "the contract users rely on — stale docs are a bug," so this is a real (if minor) maintainability gap. Fix: update lines 9 and 28 to match the new@v1-primary /@<sha>-immutable / avoid-@mainframing (or replace the duplicated prose with a single pointer to the README section so it can't drift again).The two files actually touched (
README.md,examples/reusable.yml) are internally consistent and read cleanly; the wording change is well-scoped and low-churn.⚡ Performance — No material issues found
VERDICT: No material issues found
This PR changes only
README.md(pin-guidance prose) andexamples/reusable.yml(comments + theuses:ref@main→@v1). There is no executable code, no data path, no loops, queries, or allocations in the diff — nothing for a performance lens to evaluate.examples/reusable.yml:55/README.md:315: the only functional change is the workflow ref consumers pin to; it has zero runtime-performance dimension (it selects which version of the reusable workflow is fetched, not how much work it does).Nothing in my lens is materially wrong.
🧯 Error handling & edge cases — No material issues found
The change touches only
README.mdandexamples/reusable.yml, and within those only prose and YAML comments — no executable code, no scripts, noentrypoint.sh/Go logic. There are no error paths, no inputs being parsed, no cleanup/rollback, and no edge cases introduced by this diff.VERDICT: No material issues found
This is a docs-only PR (README pin guidance + example stub comments/
uses:ref). Through the error-handling & edge-cases lens there is nothing to scrutinize — no swallowed errors, no nil/empty/zero/overflow/boundary surfaces, no unhappy paths added. Verified by reading the full diff: the only functional line changed is theuses:workflow ref inexamples/reusable.yml:54(@main→@v1), which is consumer-side YAML, not a code path Gadfly executes.Outside my lens: the PR leans on a
@v1tag existing and being maintained as a "re-moved on releases" pointer; I could not confirm anyv*tag exists in this repo (git tag -lreturned empty) — but tag/release accuracy is a correctness/docs-validity concern for another lens, not error handling.Automated adversarial review by Gadfly. Advisory only — does not block merge. · ⏱️ reviewed in 3m 4s
🪰 Gadfly review —
minimax-m3:cloud(ollama-cloud)Verdict: Blocking issues found — 5 reviewers: security, correctness, maintainability, performance, error-handling
🔒 Security — No material issues found
Looking at this change through the 🔒 Security lens specifically.
The change is documentation-only — it updates pinning guidance from
@main/@<sha>to@v1/@<sha>for reusable-workflow consumers. Security-relevant aspects to check:Secret forwarding surface — the comment correctly still warns about
secrets: inherithanding over every repo secret; explicit forwarding is still recommended. The new guidance doesn't relax this.Tag mutability (
@v1vs@mainvs@<sha>) — this is genuinely the security-relevant tradeoff, and the new comment explicitly:@main(moves on every push — could change what runs against forwarded secrets without consumer action).@v1as a curated tag "moved on deliberate releases" — less mutable than@main(only moves on tagged releases), but still mutable.@<sha>as the immutable option.From a security perspective,
@v1is strictly better than@main(smaller attack window — attacker needs to land av*tag push, not anymainpush) but strictly worse than@<sha>(which the comment also offers). The text is honest about this: "curated pointer moved on deliberate releases" vs "immutable pin." No claim that@v1equals@<sha>.Permissions block —
permissions:stays at the existing least-privilege (contents: read,issues: write,pull-requests: write); unchanged.Comment-author gate —
issue_commentstill gated toyour-username; unchanged.No new injected input, no new deserialization, no new SSRF surface — purely a comment/ref change.
One minor observation: the new
@v1recommendation nudges consumers toward a mutable tag. A security-strict reviewer might prefer the PR to lead with@<sha>and mention@v1as a convenience option, since silent movement of what runs against forwarded secrets is the exact threat the original@main-warning called out — and@v1reintroduces a (smaller) version of it. But the comment does flag this honestly ("curated … moved on deliberate releases"), and@<sha>is still offered side-by-side. This is a recommendation/tone call, not a gap; I'll note it but not block on it.No material security issues. The diff actually improves the security posture of the recommended default (smaller mutation window than
@main) while preserving the immutable@<sha>escape hatch and the explicit-secrets warning.VERDICT: No material issues found
permissions:block,secrets:explicit-forwarding guidance, and the actor gate onissue_commentare all unchanged.@v1over@main) reduces — not increases — the window in which an upstream push can silently change what runs against the consumer's forwarded secrets, while still documenting@<sha>as the immutable option. Verified by readingexamples/reusable.yml:14–20,52–54andREADME.md:313–318.🎯 Correctness — Blocking issues found
VERDICT: Blocking issues found
examples/reusable.yml:54/README.md:317— the advertised@v1mechanism does not exist in this repo. The PR's whole pitch is that@v1is "gadfly's curated release tag, re-moved on deliberate releases so central swarm tuning propagates without per-consumer re-pinning." But the only release automation in the repo is.gitea/workflows/build-image.yml, which publishes container image tags (:v1,:latest,:sha-<short>) togitea.stevedudenhoeffer.com/steve/gadfly— it never touches a git ref. Grep across the repo for any release script, tag-moving workflow, orgit push --force ... v1step returns nothing (scripts/has onlyrun.sh,status-board.sh,system-prompt.txt;.gitea/workflows/has onlybuild-image.yml,review-reusable.yml,adversarial-review.yml). So a consumer who follows the new advice and pinsuses: steve/gadfly/.gitea/workflows/review-reusable.yml@v1will get aworkflow_callresolve failure unless a human manuallygit tag v1 <sha> && git push --force origin v1for every release. Until the PR also adds the release-time automation (or at least an explicitscripts/release.sh+ a release workflow that force-moves the gitv1tag onv*tag pushes), the new recommendation is a footgun: the defaultexamples/reusable.ymlwill not run out of the box. Fix: add the missing automation in the same change (e.g. ascripts/release.shinvoked by arelease.ymlworkflow onpush: tags: ['v*']that force-moves the gitv1ref to the new commit, mirroring howbuild-image.ymlre-tags:latest), or hold this docs change until that exists..gitea/workflows/review-reusable.yml:9and:28— internal doc is now stale and contradicts the new recommendation. The reusable workflow's own header still tells consumers to pinuses: ...@<sha>(line 9:uses: steve/gadfly/.gitea/workflows/review-reusable.yml@<sha>) and the closing paragraph (line 28) still says "Consumers should likewise pinuses: ...@<sha>(not @main)" — without mentioning the@v1option the freshly-updated README/reusable.yml now steer consumers toward. CLAUDE.md's own maintenance rule is "the README andexamples/… MUST be reflected … in the same change — stale docs are a bug." Three-doc rule, not two. Verified by reading.gitea/workflows/review-reusable.yml:1-30and grepping the repo for@<sha>/@v1/@main(hits inREADME.md,examples/reusable.yml, and.gitea/workflows/review-reusable.ymlonly). Fix: update the two@<sha>mentions in this file's header comment to the same@v1(with@<sha>offered as the alternative) so all consumer-facing docs agree.🧹 Code cleanliness & maintainability — Minor issues
VERDICT: Minor issues
README.md:315— "full-stub consumers" is a newly coined compound that's never defined and only used once.examples/reusable.yml:1calls its stub "SLIM consumer stub" and.gitea/workflows/review-reusable.yml:23points consumers at "the full stub in adversarial-review.yml", so the established vocabulary is "slim" vs. "full". Hyphenating to "full-stub" reads as a new term and mildly obscures which of the two stubs is meant for the:vNadvice. Suggest restructuring the sentence (e.g. "Pin the full stub to a:vNimage tag for stability…") rather than introducing "full-stub".Terminology drift between the two surfaces:
README.md:317calls@v1"a curated tag moved on releases";examples/reusable.yml:18calls it "a curated pointer moved on deliberate releases". Same concept, different label. Pick one — "tag" is more conventional and is also literally what it is (a git tag).Cross-file doc inconsistency:
.gitea/workflows/review-reusable.yml:9(embedded consumer example) still showsuses: steve/gadfly/.gitea/workflows/review-reusable.yml@<sha>, and line 28 still tells consumers to pin@<sha>and explicitly warns against@main, with no mention of@v1. So the README andexamples/reusable.ymlnow promote@v1as the primary pin with@<sha>as the immutable option, but the reusable's own header example promotes@<sha>and says nothing about@v1— the opposite recommendation. The PR updates one consumer-facing surface but not the matching embedded example inside the reusable itself. Suggest: at least add@v1as the primary recommendation in the embedded stub example (line 9) and update the prose on line 28 to match the new guidance.Pre-existing comment duplication, not introduced but not addressed:
examples/reusable.ymlnow repeats the same@v1/@<sha>/@mainguidance in two places — the header block at lines 17–20 and the inlineuses:comment at lines 52–53 — with slightly different wording. The duplication pattern existed before this PR (it duplicated@<sha>/not-@main), so it isn't a regression, but since the PR touches both comments anyway it would have been a low-churn moment to consolidate to a single canonical wording (probably the inline one, since it sits next to the actualuses:field). Not a blocker.The headline change itself (
@main→@v1with@<sha>preserved as the immutable option) is clean and matches the PR's stated intent. Nothing else in the diff strikes as unclean — no dead code, no leaky abstractions, no naming surprises, no structural churn.⚡ Performance — No material issues found
VERDICT: No material issues found
This PR is documentation-only: README.md guidance prose plus a workflow
uses:ref change (@main→@v1) inexamples/reusable.yml. Verified both touched regions:README.md:313-318— added the reusable-workflow pinning paragraph alongside the existing image-tag guidance.examples/reusable.yml:52-54—uses:ref updated, comment rewritten.Nothing in this diff touches runtime code paths, allocations, queries, loops, or any hot path. There is no efficiency-relevant change to evaluate through the Performance lens.
🧯 Error handling & edge cases — No material issues found
VERDICT: No material issues found
This PR is docs/comments-only — it changes two blocks of prose (
examples/reusable.yml:14-20,examples/reusable.yml:52-53) and one paragraph (README.md:315-318). No code paths, no error paths, no nil checks, no cleanup, no boundary conditions, no I/O — nothing in the error-handling & edge-cases lens is touched.I verified by reading
examples/reusable.yml:1-70andREADME.md:300-330:uses:line atexamples/reusable.yml:54is now…@v1; the surroundingsecrets:/with:/concurrency:blocks are unchanged.@main", "curated pointer moved on deliberate releases"); any preconditions about the@v1tag actually existing belong to the release process, which is out of scope for this diff and out of my lane.Automated adversarial review by Gadfly. Advisory only — does not block merge. · ⏱️ reviewed in 1m 22s