Skip to content

feat(ci): enforce issue traceability on the pull request - #600

Merged
ss-o merged 2 commits into
mainfrom
feature-595
Sep 2, 2026
Merged

feat(ci): enforce issue traceability on the pull request#600
ss-o merged 2 commits into
mainfrom
feature-595

Conversation

@ss-o

@ss-o ss-o commented Sep 2, 2026

Copy link
Copy Markdown
Member

Steps 1 to 3 of #595, implementing
decisions/0022-issue-traceability-on-pull-requests.md.

What lands

Validate Issue Link, a new job in commit-lint.yml. Three outcomes pass,
and the job prints which applied, so an exemption is visible in review rather
than silent:

Outcome Condition
Exempt, automation Head branch matches dependabot/, renovate/, copilot/, codex/
Exempt, labelled The pull request carries meta:no-issue
Traceable The body carries #123, owner/repo#123, or a full issue or pull-request URL

It reads only the pull_request event payload, so it needs no token and runs
with permissions: {}. Either a closing keyword or a plain reference
satisfies ADR-0022, and both land in the body, so no API call is required.

meta:no-issue added to lib/labels.yml and runbooks/labels.md. The
runbook records ADR-0022's constraint that applying it is a maintainer
decision: an agent may propose it and must not apply it on its own authority.

Automation prefixes hoisted to workflow-level env. Validate Branch Name
and Validate Issue Link must agree on them, and a second inlined copy is
exactly how two checks silently diverge. The suite now asserts there is only
one definition.

Verification

scripts/test-commit-lint-policy.sh grew from 40 to 51 checks. Two of them
matter beyond the table:

  • the exemption label the workflow honours must be a label lib/labels.yml
    actually publishes, or applying it is impossible;
  • the automation prefixes must not be inlined anywhere as well as defined in
    env.

The suite did its job twice during this change. It failed first on the
extractor when the prefixes moved, which is the shape-change guard working.
Then it caught a real defect in the new pattern: z-shell/.github#590, the
cross-repository shorthand used throughout these issues, did not match. The
pattern now accepts all three reference forms.

Three further mutations, each reverted: renaming the exemption label to one
lib/labels.yml does not declare, dropping copilot/codex from the shared
env, and loosening the reference pattern to accept #0. All three caught.

actionlint, shellcheck -s bash, trunk check, validate-agent-policy.py
and the policy test suite are clean.

Ordering, which is part of the accepted decision

This pull request is step 3: the check runs here for the first time, on a real
pull request. runbooks/branch-protection.md notes GitHub only accepts status
contexts it has already observed, so step 4 registers Validate Issue Link
in the main ruleset only after this merges.

Step 5, relaxing Validate Branch Name to a shape check here and in
z-shell/zi, comes after step 4. Relaxing earlier would open a window with
neither control active, which is the state ADR-0022 exists to close. Step 6
adds the ADR-0019 pointer and updates AGENTS.md, and lands with step 5 so the
pointer and the enforcement it describes arrive together.

Refs #595

ADR-0022 moves traceability off the branch name, where it was a proxy with
perfect precision and poor recall, and onto the pull request, where the
predicate it stands in for was checked by nothing.

Validate Issue Link passes on three outcomes and says which applied, so an
exemption is visible in review rather than silent: an automation branch, the
new meta:no-issue label, or a reference in the body. It reads only the
pull_request event payload, so it needs no token and runs with permissions: {}.

Hoist the automation prefixes to workflow-level env. Validate Branch Name and
Validate Issue Link must agree on them, and a second inlined copy is how the
two silently diverge; the suite now asserts there is only one.

Add meta:no-issue to lib/labels.yml and runbooks/labels.md. ADR-0022 makes
applying it a maintainer decision, which the runbook records.

Steps 1 and 2 of #595. The context is not registered in the ruleset until it
has been observed on a real pull request, per runbooks/branch-protection.md,
and the branch pattern does not relax until after that.

Refs #595
@ss-o
ss-o requested a review from a team as a code owner September 2, 2026 21:21
The suite anchored its extractions on single-quoted YAML scalars. Trunk's
pre-commit prettier hook rewrote the new env value to double quotes after the
local run, so the pushed commit failed CI with the shape-change error while the
pre-commit working tree had passed.

Prettier owns YAML formatting here and rewrites scalar quoting at will, so
strip one matching pair of surrounding quotes after extraction rather than
depending on which style it last chose.

Verified both ways: the suite passes with the value single-quoted and
double-quoted, and still catches the prefixes being dropped.

Refs #595
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