This is the record of an abcd-managed repository

abcdBetav0.16.2 · 2026-11-06

Development record

Every dependabot PR that bumps a pinned action in .github/workflows/release.yml or auto-release.yml fails TestSelfScaffoldParity and can never go green on its own. Observed on PR #211 (actions/attest 4.2.0 -> 4.2.2): 'release.yml: abcd rendering is not byte-identical to the committed workflow', failing check on BOTH platforms while gitleaks, record-lint, smoke and zizmor all pass. Root cause: the committed workflow is a GENERATED artefact. internal/core/launch/scaffold/templates/release.yml.tmpl:270 and .github/workflows/release.yml:248 both pin actions/attest@f7c74d28b9d84cb8768d0b8ca14a4bac6ef463e6 (v4.2.0), and TestSelfScaffoldParity asserts the two are byte-identical so that abcd's own release dogfoods the machinery a managed repo receives. Dependabot edits only the derived file, so parity breaks by construction on every such bump — this is recurring and structural, not a one-off. The obvious fix (bring the scaffold template into dependabot's scope) is NOT AVAILABLE: the github-actions ecosystem discovers only .github/workflows/*.yml and composite action.yml manifests under the configured directory, and no package-ecosystem scans an arbitrary .tmpl under internal/. .github/dependabot.yml today declares gomod and github-actions, both at directory /. Note also the wrong-direction trap: auto-rendering the scaffold on a dependabot PR would REVERT the bump, since render flows template -> workflow. Options, none adopted: (a) make the parity failure self-explaining — the message says 'not byte-identical' and prints the first diff but never names the template path or says 'an action bump must be applied to the template too', which is the cheapest change and matches the loud-staging principle; (b) propagate the bump backwards — a job on dependabot PRs that applies the changed pin to the template and commits to the bot branch, which is the durable fix but is custom automation writing to a bot branch; (c) drop these two workflows from dependabot's scope and manage their pins by hand from the template, trading automation for consistency. Secondary risk worth weighing: a permanently-red dependabot PR trains the maintainer to discount red CI on exactly the PRs where CI most needs to be trusted.

issueopenmajoriss-209

Every dependabot PR that bumps a pinned action in .github/workflows/release.yml or auto-release.yml fails TestSelfScaffoldParity and can never go green on its own. Observed on PR #211 (actions/attest 4.2.0 -> 4.2.2): 'release.yml: abcd rendering is not byte-identical to the committed workflow', failing check on BOTH platforms while gitleaks, record-lint, smoke and zizmor all pass. Root cause: the committed workflow is a GENERATED artefact. internal/core/launch/scaffold/templates/release.yml.tmpl:270 and .github/workflows/release.yml:248 both pin actions/attest@f7c74d28b9d84cb8768d0b8ca14a4bac6ef463e6 (v4.2.0), and TestSelfScaffoldParity asserts the two are byte-identical so that abcd's own release dogfoods the machinery a managed repo receives. Dependabot edits only the derived file, so parity breaks by construction on every such bump — this is recurring and structural, not a one-off. The obvious fix (bring the scaffold template into dependabot's scope) is NOT AVAILABLE: the github-actions ecosystem discovers only .github/workflows/*.yml and composite action.yml manifests under the configured directory, and no package-ecosystem scans an arbitrary .tmpl under internal/. .github/dependabot.yml today declares gomod and github-actions, both at directory /. Note also the wrong-direction trap: auto-rendering the scaffold on a dependabot PR would REVERT the bump, since render flows template -> workflow. Options, none adopted: (a) make the parity failure self-explaining — the message says 'not byte-identical' and prints the first diff but never names the template path or says 'an action bump must be applied to the template too', which is the cheapest change and matches the loud-staging principle; (b) propagate the bump backwards — a job on dependabot PRs that applies the changed pin to the template and commits to the bot branch, which is the durable fix but is custom automation writing to a bot branch; (c) drop these two workflows from dependabot's scope and manage their pins by hand from the template, trading automation for consistency. Secondary risk worth weighing: a permanently-red dependabot PR trains the maintainer to discount red CI on exactly the PRs where CI most needs to be trusted.

Half fixed 2026-08-11; the automation is a recorded DEAD END, do not re-attempt as described. The manual half shipped: make scaffold-sync propagates the workflow pins into the templates, TestSyncRepoPinsIsCleanToday fails preflight when a bump landed on a workflow alone and names the fixing command, and option (a) from the original entry is moot because the sync tool subsumes it. What remains open is option (b), the zero-touch propagation onto the dependabot branch.

A workflow_run implementation was built and REJECTED in review on 2026-08-11, for two reasons worth recording so the next attempt does not rediscover them. First, it cannot work at all: a push made with GITHUB_TOKEN raises no events, so the sync commit moves the PR head to a SHA that never gets a CI run — the PR goes from red to permanently pending, a weaker signal than the failure it set out to fix. This repo already documents the mechanism at .github/workflows/auto-release.yml ("A GITHUB_TOKEN-pushed tag raises no tag-push event, which is why the release below invokes release.yml explicitly rather than relying on the tag"). Second, the design was unsound: actions/checkout with ref: <head_branch> makes the BRANCH's tree the workspace, so a subsequent go run ./cmd/scaffold-sync executes branch-supplied code under the contents: write token that persist-credentials: true leaves in .git/config. workflow_run buys a trusted workflow DEFINITION, not a trusted WORKSPACE — the standard pitfall. Independent review also found the trigger fails zizmor --persona regular with dangerous-triggers (unverified locally; no docker daemon), and that committing as github-actions[bot] collides with the no-branch-commit tripwire in release.yml, which fails a release run when a bot commit lands on the default branch mid-job.

Any future attempt therefore needs, at minimum: a push credential that is NOT GITHUB_TOKEN (a GitHub App token preferred over a PAT — short-lived and scoped, and its pushes do raise events); a structure where the untrusted tree is never executed under the write token (compute the patch in a read-only job with persist-credentials: false, apply and push from a trusted one checked out at github.sha); a commit identity that is not github-actions[bot]; and a concurrency group keyed on workflow_run.event as well as the branch, since ci produces both a push-derived and a pull_request-derived run per dependabot branch and the useless one can otherwise cancel the working one.

Deferral 2026-09-30

Deferred past v0.11.1: The product thinker's ruling M3 of 2026-09-23: automate it, planned next cycle as its own intent with a security review. That intent is filed as the draft itd-2609301020001595 (a pinned-action bump syncs its scaffold template and lands re-authored), and this record now waits on that draft's planning interview. The credential sign-off M3 owed is given: ruling H2 (a GitHub App the person creates and installs pushes; the person is the landed commit's author) and ruling CG1 (the App token is minted in shell, openssl JWT and curl exchange, revoked on exit, no new action). The manual half ships (make scaffold-sync and TestSyncRepoPinsIsCleanToday), so a pin bump on a workflow alone reds preflight and names the fix; until the draft ships, a dependabot pull request bumping a pinned action is landed by a human.

Remedy grounds (2026-09-29)

  • The credential shape was the open question and H2 answers it for dependency updates; the record's own rejected workflow_run attempt supplies the rest (never execute the bot tree under a write token). Renovate's regex custom manager can update pins in arbitrary files such as a .tmpl in the same PR: https://docs.renovatebot.com/modules/manager/regex/ (consulted 2026-09-29).
  • Rejected for now: switching to Renovate, the simpler structural fix but a new tool and app needing the person's sign-off; worth putting to the person with the intent.

Deferral lapsed 2026-10-23

The deferral past v0.11.1 lapsed long ago and is withdrawn, on the old-majors triage of 2026-10-23. It stays open until itd-2609301020001595 ships. The reason it carried stays in the body above.

Frontmatter

idiss-209
typeissue
lifecycleopen
severitymajor

References1

mentions4