Skip to content

feat: abcd launch scaffold — the release-gate scaffolder (itd-93) - #154

Merged
REPPL merged 7 commits into
mainfrom
feat/itd-93-launch-scaffold
Jul 27, 2026
Merged

feat: abcd launch scaffold — the release-gate scaffolder (itd-93)#154
REPPL merged 7 commits into
mainfrom
feat/itd-93-launch-scaffold

Conversation

@REPPL

@REPPL REPPL commented Jul 27, 2026

Copy link
Copy Markdown
Owner

What

abcd launch scaffold — the release-gate scaffolder (itd-93 / spc-14). Writes the
changelog-driven release machinery into a managed repo that lacks it, from a single
embedded template that abcd-cli's own release workflows are regenerated from
(self-scaffold parity).

Delivery per acceptance criterion

  • AC1 — writes wired, audit-clean workflows. abcd launch scaffold writes
    release.yml, auto-release.yml, and the adr-37 runbook, wired to the repo's own
    default branch and Go version (derived from .git + go.mod, validated against an
    injection-safe allowlist), GITHUB_TOKEN-only. Bare-profile YAML verified to parse
    and to reference no secret other than GITHUB_TOKEN.
  • AC2 — first release publishes after a green rehearsal. The verify gate is armed
    against the reviewed content commit (HEAD^2^ merge path / HEAD^ direct tag);
    the abcd rendering reproduces that proven arming byte-for-byte, so the receipt-vs-tag
    self-reference cannot recur — satisfied by construction and pinned by the parity test.
  • AC3 — no semantic detector → deterministic gates alone admit. The bare profile
    omits the semantic-gate block entirely; the runbook states no detector is configured.
    Tested (TestBareRenderOmitsAbcdMachinery).
  • AC4 — re-run is a no-op; hand-edits are not clobbered. Idempotent, all-or-nothing:
    no-op on current machinery, refuse (exit 1) on a hand-edit unless --confirm. Tested.
  • AC5 — sha-keyed receipt dirs exempt from the dated-review-dir shape. The scaffolded
    runbook documents the exemption. (The executable check-reviews charter is abcd-specific
    and not scaffolded into a bare repo — a repo with no charter has no collision.)
  • AC6 — rehearsal arms the full gate and publishes nothing. The workflow_dispatch
    rehearsal simulates the two-commit roll + merge, resolves the content commit, and holds
    contents: read only — no gh release create, tag push, or attest. Tested
    (TestRehearsalPublishesNothing).

Branch A (maintainer-sanctioned 2026-07-27)

The template is the single source for release.yml/auto-release.yml; abcd-cli's live
workflows are regenerated from it. The only diff to the live release.yml is the
additive rehearsal, in three additive parts:

  1. the workflow_dispatch trigger,
  2. a guard if: github.event_name != 'workflow_dispatch' on the existing release
    (publish) job, so a rehearsal never reaches the publish path, and
  3. the new non-publishing rehearsal job.

TestSelfScaffoldParity pins render(AbcdSubstitutions) byte-for-byte to the committed
workflows; auto-release.yml is byte-identical for abcd. The existing verify/build/
publish/semantic-gate job bodies are reproduced verbatim (105 insertions, 0 deletions).
Part (2) is a job-level guard, not a step-body change; flagged here as the one judgment
call within "the additive rehearsal" for the merge review.

Decision recorded in .abcd/work/DECISIONS.md (2026-07-27).

Reviews

  • abcd:security-reviewer — APPROVE, no findings. Attacked YAML/script injection via
    the derived facts (both allowlisted to \d+\.\d+ / git-ref chars before reaching YAML,
    passed to shell via env: only), the write path (symlink/TOCTOU/traversal/clobber, all
    behind ReadGuarded + atomic rename), the token/permission model, rehearsal-publishes-
    nothing, and the live-workflow invariants — nothing survived.
  • abcd:ruthless-reviewer — one FIX-FIRST, fixed. The report marked absent-but-unwritten
    files written on the all-or-nothing abort path (report contradicted disk). Fixed:
    writes are provisional (skipped) until actually committed; TestRefusalAbortReportMatchesDisk
    added (watched fail → pass). NOTE-1 (CLI dropped the partial report on a mid-write fault)
    addressed. NOTE-2 (deriveBranch reads only loose refs; a packed-refs repo scaffolded from
    a feature branch wires that branch) left as documented safe degradation — validated and
    visible in the printed branch <name>.

Preflight

make preflight clean (build, gofmt -l . empty, vet, go test ./..., race); record-lint,
docs-lint, check-reviews, smoke all exit 0. Pre-push hook (full preflight + record-lint)
passed.

Record: itd-93 / spc-14. Maintainer merges.

REPPL added 7 commits July 27, 2026 15:41
Assisted-by: Claude:claude-opus-4-8[1m]
The scaffold package renders the changelog-driven release machinery
(release.yml, auto-release.yml, adr-37 runbook) from one embedded template,
using <% %> delimiters so GitHub Actions ${{ }} passes through literally.

AbcdSubstitutions reproduces abcd-cli's live workflows byte-for-byte
(TestSelfScaffoldParity), so the proven pattern and the shipped template are one
artifact; abcd-cli's own release.yml is regenerated from the template, adding
only the additive workflow_dispatch rehearsal (trigger + release-job guard +
non-publishing rehearsal job) — the sole sanctioned live-workflow diff (Branch A).

BareSubstitutions degrades cleanly for a managed repo with no semantic detector:
the deterministic Go gates alone, a generic build, GITHUB_TOKEN-only. Repo facts
(default branch, Go version) are derived and validated against an injection-safe
allowlist before reaching the YAML.

itd-93 / spc-14.

Assisted-by: Claude:claude-opus-4-8[1m]
abcd launch scaffold writes the release machinery into a managed repo that lacks
it, wired to the repo's own default branch and Go version. Idempotent and
fail-safe: a re-run on current machinery is a no-op (exit 0), a hand-edited file
is refused (exit 1) rather than clobbered unless --confirm, a structural fault
exits 2.

Reachable from both front doors: the CLI subcommand under launch, and the
plugin markdown surface (commands/abcd/launch.md). The brief 04-launch surface
doc, the surface baseline, and the generated CLI reference record the new
sub-verb; CHANGELOG entry added.

itd-93 / spc-14.

Assisted-by: Claude:claude-opus-4-8[1m]
…orkflow

The bare release.yml has no attest step, so its caller need not hand down
id-token/attestations. Least-privilege for the managed-repo profile; abcd's own
auto-release is unchanged (self-scaffold parity holds byte-for-byte).

itd-93 / spc-14

Assisted-by: Claude:claude-opus-4-8[1m]
On the all-or-nothing refusal-abort path the first pass marked absent files
StatusWritten before any write, so a run that refused a hand-edited sibling
reported '[written]' for a file it never wrote and that was absent on disk
(the report contradicted disk and the wrote counter). Classify now returns a
disposition, a planned write is provisional (StatusSkipped) until the second
pass actually writes it, and only a successful write flips it to StatusWritten;
on abort or a mid-write fault the unwritten files stay skipped with a reason.
The CLI now also renders the partial report on a mid-write fault before exit 2.

Adds TestRefusalAbortReportMatchesDisk (watched fail before, pass after).
Ruthless-review FIX-FIRST. itd-93 / spc-14

Assisted-by: Claude:claude-opus-4-8[1m]
…affold

# Conflicts:
#	.abcd/work/DECISIONS.md
…affold

# Conflicts:
#	.abcd/work/DECISIONS.md
@REPPL
REPPL merged commit f06de9d into main Jul 27, 2026
12 checks passed
@REPPL
REPPL deleted the feat/itd-93-launch-scaffold branch July 27, 2026 18:33
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