fix: align with j4k-align 17.15.4 #17

Merged
jercik merged 1 commit from chore/align-17-15-4 into main 2026-11-03 14:30:49 +00:00
Owner

Moves .node-version to 26.13.0, the Node baked into the node-ci:26-bookworm CI image, so CI stops downloading Node from GitHub on every run.

The published package now requires Node 26: engines.node rises from >=24.15.0 to >=26.0.0, @types/node moves to ^26.0.0, and CI drops the Node 24 matrix leg. Every consumer is in the j4k fleet and moves to Node 26.13.0 in the same rollout.

The managed workflows are re-rendered from align 17.15.4: the fork and AGit guard moves from a checks canary to a same-repo-pr job in commit-msg, and release waits for the tip check. oxlint.config.ts adds the nodeTest preset.

Moves `.node-version` to 26.13.0, the Node baked into the `node-ci:26-bookworm` CI image, so CI stops downloading Node from GitHub on every run. The published package now requires Node 26: `engines.node` rises from `>=24.15.0` to `>=26.0.0`, `@types/node` moves to `^26.0.0`, and CI drops the Node 24 matrix leg. Every consumer is in the j4k fleet and moves to Node 26.13.0 in the same rollout. The managed workflows are re-rendered from align 17.15.4: the fork and AGit guard moves from a `checks` canary to a `same-repo-pr` job in `commit-msg`, and release waits for the tip check. `oxlint.config.ts` adds the `nodeTest` preset.
fix: align with j4k-align 17.15.4
All checks were successful
Checks / reuse (pull_request) Has been skipped
commit-msg / same-repo-pr (pull_request) Has been skipped
commit-msg / commitlint (pull_request) Successful in 5s
Dedupe check / dedupe-check (pull_request) Successful in 13s
Checks / quality-checks (pull_request) Successful in 22s
Checks / qc-result (pull_request) Has been skipped
Review / Review (pull_request_target) Successful in 14m14s
58356452d7

Review 01M6GW5VXA3A066ZAF4N072XWP — head 58356452d74a13d9860c0148ec82d31c46c3f798

Review — j4k-oss/askpplx @ ad8b94c112

Scope: diff against base tree cca3c2f9a39a
Review finished: 6 succeeded, 0 failed, 4 skipped by dispatch
Triage: settled
Facts: current review-wide projection

Computed under:

{
  "abandonment": "abandonment-v1",
  "anchor_recipe": 1,
  "batch_policy": "batch-v1",
  "coverage": "coverage-v3",
  "dispatch_policy": "dispatch-v2",
  "grounder_version": 1,
  "grounding_read_rule": "grounding-read-v1",
  "promotion_policy": "promotion-v1",
  "report": "report-v5",
  "tally": "tally-v1",
  "triage_settle": "triage-settle-v2"
}

Findings (1)

medium — Fork/AGit admission is a hand-copied negation of a guard repeated in three workflows, hosted in the commit-message workflow

  • claim: 01M6GWHKAVRQK2M0KXB52RYRXS
  • anchor: .forgejo/workflows/commit-msg.yml (snippet)
    if: github.event.pull_request.head.repo.full_name != github.repository || toJSON(github.event.pull_request.flow) != '0'
  • lens: aposd-plain · arm: default
  • verdicts: 1 valid / 0 invalid / 0 uncertain
    • pass 01M6GWJHP70VC03BXEPX7K58FT · valid: Grounded: the anchor exactly matches the same-repo-pr condition in commit-msg.yml, the negation of the fork/AGit guard. Reviewer-supplied and internally consistent: the positive guard is copied into commitlint, quality-checks and dedupe-check; checks.yml and dedupe-check.yml point in comments at 'commit-msg.yml's same-repo-pr job'; and the canary moved here from checks.yml. The Special-General Mixture red flag holds. A rule about which PR origins may run CI, covering every workflow, sits inside the commit-message workflow, so a refused fork PR fails as 'commit-msg / same-repo-pr', a name that says nothing about the actual reason. No source in the batch gives a reason for that placement. The information-leakage part is overstated. The claim itself says each job needs its own if: guard. Its proposed pr-origin.yml would still hold a hand-typed complement that can drift from three guards in other files. So the coupling it describes stays the same under the fix, and the remaining defect is where the check lives and what it is called. Moving it would also need the repository's required-check settings changed, which the reviewer could not see; that is a gap in the remedy, not a refutation. There is no present mismatch and no repeated cost in current code, so I would rate this low, not medium.
  • disposition: none

The decision of which pull requests may run CI is now spread across four job conditions in three files, and the enforcing check lives in an unrelated workflow. When someone edits one guard (for example to admit a new flow value, or adds a guarded job to a new workflow file), nothing ties same-repo-pr to the change. A drifted complement either lets a skipped-and-green PR through again or fails legitimate PRs. A contributor whose fork PR is refused sees the failure as commit-msg / same-repo-pr, which says nothing about commit messages.

The guard head.repo.full_name == github.repository && toJSON(github.event.pull_request.flow) == '0' is written out separately in commitlint (commit-msg.yml), quality-checks (checks.yml) and dedupe-check (dedupe-check.yml). The new same-repo-pr job states its condition is "the guard's exact complement" and re-types the negation by hand. Its shell body then re-derives the AGit/flow distinction ([ "${FLOW}" != "1" ]) for its error text. checks.yml and dedupe-check.yml now carry comments pointing at "commit-msg.yml's same-repo-pr job". That is a cross-file dependency held only in prose. Before this change the equivalent canary (pr-flow-canary) sat in checks.yml beside the guarded job it protected.

In APOSD terms this is information leakage: one design decision, "which PR origins are trusted", appears in several modules. It is also a special-general mixture, because a repository-wide admission rule lives inside a commit-message checker. One correction is to give the admission rule its own small workflow, for example pr-origin.yml with a single job, so the policy has a single home with an accurate check name. The guarded jobs' comments would then point at that one place. Alternatively, keep it in the workflow whose guard it mirrors. The guard expression itself has to be repeated, because each job needs its own if:. Even so, the complement and its explanation should have one owner that is not named after an unrelated concern.

I read the commit-msg.yml, checks.yml, dedupe-check.yml and release.yml workflows in full in the subject tree, plus the diff hunks that remove pr-flow-canary and add same-repo-pr. review.yml uses pull_request_target with no fork guard, so it is not part of the set. I checked statically that the three guards and the complement currently agree for pull_request events. The defect is the maintenance coupling, not a present mismatch. Repository settings that would show how required checks are named or configured are outside the tree, so I could not verify them.

Other claims

  • grounding-pending (0)
  • ungrounded (0)
  • rejected (0)
  • duplicate-of (0)
  • unadjudicated (0)

Coverage

Coverage pass: 01M6GW5VXCVCC8NFYKWFV5ZAYH
Accounting: complete (all slots terminal; see slot results for failures)
Slot health: healthy

lens part arm unit status runs loss
general-bug whole default no-claims 1 no
writing-quality workflows default no-claims 1 no
restated-sets whole default no-claims 1 no
unix-cli workflows default no-claims 1 no
module-design whole default no-claims 1 no
aposd-plain whole default claims-emitted 1 no
  • test-trimming — skipped-by-dispatch: no tests changed
  • project-docs — skipped-by-dispatch: no project documentation changed
  • use-effect — skipped-by-dispatch: no React code changed
  • react — skipped-by-dispatch: no React code changed
<!-- review:summary --> **Review** `01M6GW5VXA3A066ZAF4N072XWP` — head `58356452d74a13d9860c0148ec82d31c46c3f798` # Review — j4k-oss/askpplx @ ad8b94c112f5 Scope: diff against base tree `cca3c2f9a39a` Review finished: 6 succeeded, 0 failed, 4 skipped by dispatch Triage: settled Facts: current review-wide projection Computed under: ```json { "abandonment": "abandonment-v1", "anchor_recipe": 1, "batch_policy": "batch-v1", "coverage": "coverage-v3", "dispatch_policy": "dispatch-v2", "grounder_version": 1, "grounding_read_rule": "grounding-read-v1", "promotion_policy": "promotion-v1", "report": "report-v5", "tally": "tally-v1", "triage_settle": "triage-settle-v2" } ``` ## Findings (1) ### medium — Fork/AGit admission is a hand-copied negation of a guard repeated in three workflows, hosted in the commit-message workflow - claim: `01M6GWHKAVRQK2M0KXB52RYRXS` - anchor: `.forgejo/workflows/commit-msg.yml` (snippet) ``` if: github.event.pull_request.head.repo.full_name != github.repository || toJSON(github.event.pull_request.flow) != '0' ``` - lens: aposd-plain · arm: default - verdicts: 1 valid / 0 invalid / 0 uncertain - pass `01M6GWJHP70VC03BXEPX7K58FT` · valid: Grounded: the anchor exactly matches the same-repo-pr condition in commit-msg.yml, the negation of the fork/AGit guard. Reviewer-supplied and internally consistent: the positive guard is copied into commitlint, quality-checks and dedupe-check; checks.yml and dedupe-check.yml point in comments at 'commit-msg.yml's same-repo-pr job'; and the canary moved here from checks.yml. The Special-General Mixture red flag holds. A rule about which PR origins may run CI, covering every workflow, sits inside the commit-message workflow, so a refused fork PR fails as 'commit-msg / same-repo-pr', a name that says nothing about the actual reason. No source in the batch gives a reason for that placement. The information-leakage part is overstated. The claim itself says each job needs its own if: guard. Its proposed pr-origin.yml would still hold a hand-typed complement that can drift from three guards in other files. So the coupling it describes stays the same under the fix, and the remaining defect is where the check lives and what it is called. Moving it would also need the repository's required-check settings changed, which the reviewer could not see; that is a gap in the remedy, not a refutation. There is no present mismatch and no repeated cost in current code, so I would rate this low, not medium. - disposition: none > The decision of which pull requests may run CI is now spread across four job conditions in three files, and the enforcing check lives in an unrelated workflow. When someone edits one guard (for example to admit a new `flow` value, or adds a guarded job to a new workflow file), nothing ties `same-repo-pr` to the change. A drifted complement either lets a skipped-and-green PR through again or fails legitimate PRs. A contributor whose fork PR is refused sees the failure as `commit-msg / same-repo-pr`, which says nothing about commit messages. > > The guard `head.repo.full_name == github.repository && toJSON(github.event.pull_request.flow) == '0'` is written out separately in `commitlint` (commit-msg.yml), `quality-checks` (checks.yml) and `dedupe-check` (dedupe-check.yml). The new `same-repo-pr` job states its condition is "the guard's exact complement" and re-types the negation by hand. Its shell body then re-derives the AGit/flow distinction (`[ "${FLOW}" != "1" ]`) for its error text. checks.yml and dedupe-check.yml now carry comments pointing at "commit-msg.yml's same-repo-pr job". That is a cross-file dependency held only in prose. Before this change the equivalent canary (`pr-flow-canary`) sat in checks.yml beside the guarded job it protected. > > In APOSD terms this is information leakage: one design decision, "which PR origins are trusted", appears in several modules. It is also a special-general mixture, because a repository-wide admission rule lives inside a commit-message checker. One correction is to give the admission rule its own small workflow, for example `pr-origin.yml` with a single job, so the policy has a single home with an accurate check name. The guarded jobs' comments would then point at that one place. Alternatively, keep it in the workflow whose guard it mirrors. The guard expression itself has to be repeated, because each job needs its own `if:`. Even so, the complement and its explanation should have one owner that is not named after an unrelated concern. > > I read the commit-msg.yml, checks.yml, dedupe-check.yml and release.yml workflows in full in the subject tree, plus the diff hunks that remove `pr-flow-canary` and add `same-repo-pr`. review.yml uses `pull_request_target` with no fork guard, so it is not part of the set. I checked statically that the three guards and the complement currently agree for `pull_request` events. The defect is the maintenance coupling, not a present mismatch. Repository settings that would show how required checks are named or configured are outside the tree, so I could not verify them. ## Other claims - grounding-pending (0) - ungrounded (0) - rejected (0) - duplicate-of (0) - unadjudicated (0) ## Coverage Coverage pass: 01M6GW5VXCVCC8NFYKWFV5ZAYH Accounting: complete (all slots terminal; see slot results for failures) Slot health: healthy | lens | part | arm | unit status | runs | loss | | --- | --- | --- | --- | --- | --- | | general-bug | whole | default | no-claims | 1 | no | | writing-quality | workflows | default | no-claims | 1 | no | | restated-sets | whole | default | no-claims | 1 | no | | unix-cli | workflows | default | no-claims | 1 | no | | module-design | whole | default | no-claims | 1 | no | | aposd-plain | whole | default | claims-emitted | 1 | no | - test-trimming — skipped-by-dispatch: no tests changed - project-docs — skipped-by-dispatch: no project documentation changed - use-effect — skipped-by-dispatch: no React code changed - react — skipped-by-dispatch: no React code changed
@ -130,0 +132,4 @@
# the guard's exact complement: it fails those PRs and runs none of their code.
# It also fails every PR if Forgejo stops sending a usable `flow`.
same-repo-pr:
if: github.event.pull_request.head.repo.full_name != github.repository || toJSON(github.event.pull_request.flow) != '0'

medium — Fork/AGit admission is a hand-copied negation of a guard repeated in three workflows, hosted in the commit-message workflow

The decision of which pull requests may run CI is now spread across four job conditions in three files, and the enforcing check lives in an unrelated workflow. When someone edits one guard (for example to admit a new flow value, or adds a guarded job to a new workflow file), nothing ties same-repo-pr to the change. A drifted complement either lets a skipped-and-green PR through again or fails legitimate PRs. A contributor whose fork PR is refused sees the failure as commit-msg / same-repo-pr, which says nothing about commit messages.

The guard head.repo.full_name == github.repository && toJSON(github.event.pull_request.flow) == '0' is written out separately in commitlint (commit-msg.yml), quality-checks (checks.yml) and dedupe-check (dedupe-check.yml). The new same-repo-pr job states its condition is "the guard's exact complement" and re-types the negation by hand. Its shell body then re-derives the AGit/flow distinction ([ "${FLOW}" != "1" ]) for its error text. checks.yml and dedupe-check.yml now carry comments pointing at "commit-msg.yml's same-repo-pr job". That is a cross-file dependency held only in prose. Before this change the equivalent canary (pr-flow-canary) sat in checks.yml beside the guarded job it protected.

In APOSD terms this is information leakage: one design decision, "which PR origins are trusted", appears in several modules. It is also a special-general mixture, because a repository-wide admission rule lives inside a commit-message checker. One correction is to give the admission rule its own small workflow, for example pr-origin.yml with a single job, so the policy has a single home with an accurate check name. The guarded jobs' comments would then point at that one place. Alternatively, keep it in the workflow whose guard it mirrors. The guard expression itself has to be repeated, because each job needs its own if:. Even so, the complement and its explanation should have one owner that is not named after an unrelated concern.

I read the commit-msg.yml, checks.yml, dedupe-check.yml and release.yml workflows in full in the subject tree, plus the diff hunks that remove pr-flow-canary and add same-repo-pr. review.yml uses pull_request_target with no fork guard, so it is not part of the set. I checked statically that the three guards and the complement currently agree for pull_request events. The defect is the maintenance coupling, not a present mismatch. Repository settings that would show how required checks are named or configured are outside the tree, so I could not verify them.

lens aposd-plain · arm default · tally 1 valid / 0 invalid / 0 uncertain
claim 01M6GWHKAVRQK2M0KXB52RYRXS of review 01M6GW5VXA3A066ZAF4N072XWP

<!-- review:claim:01M6GWHKAVRQK2M0KXB52RYRXS --> **medium** — Fork/AGit admission is a hand-copied negation of a guard repeated in three workflows, hosted in the commit-message workflow > The decision of which pull requests may run CI is now spread across four job conditions in three files, and the enforcing check lives in an unrelated workflow. When someone edits one guard (for example to admit a new `flow` value, or adds a guarded job to a new workflow file), nothing ties `same-repo-pr` to the change. A drifted complement either lets a skipped-and-green PR through again or fails legitimate PRs. A contributor whose fork PR is refused sees the failure as `commit-msg / same-repo-pr`, which says nothing about commit messages. > > The guard `head.repo.full_name == github.repository && toJSON(github.event.pull_request.flow) == '0'` is written out separately in `commitlint` (commit-msg.yml), `quality-checks` (checks.yml) and `dedupe-check` (dedupe-check.yml). The new `same-repo-pr` job states its condition is "the guard's exact complement" and re-types the negation by hand. Its shell body then re-derives the AGit/flow distinction (`[ "${FLOW}" != "1" ]`) for its error text. checks.yml and dedupe-check.yml now carry comments pointing at "commit-msg.yml's same-repo-pr job". That is a cross-file dependency held only in prose. Before this change the equivalent canary (`pr-flow-canary`) sat in checks.yml beside the guarded job it protected. > > In APOSD terms this is information leakage: one design decision, "which PR origins are trusted", appears in several modules. It is also a special-general mixture, because a repository-wide admission rule lives inside a commit-message checker. One correction is to give the admission rule its own small workflow, for example `pr-origin.yml` with a single job, so the policy has a single home with an accurate check name. The guarded jobs' comments would then point at that one place. Alternatively, keep it in the workflow whose guard it mirrors. The guard expression itself has to be repeated, because each job needs its own `if:`. Even so, the complement and its explanation should have one owner that is not named after an unrelated concern. > > I read the commit-msg.yml, checks.yml, dedupe-check.yml and release.yml workflows in full in the subject tree, plus the diff hunks that remove `pr-flow-canary` and add `same-repo-pr`. review.yml uses `pull_request_target` with no fork guard, so it is not part of the set. I checked statically that the three guards and the complement currently agree for `pull_request` events. The defect is the maintenance coupling, not a present mismatch. Repository settings that would show how required checks are named or configured are outside the tree, so I could not verify them. lens `aposd-plain` · arm `default` · tally 1 valid / 0 invalid / 0 uncertain claim `01M6GWHKAVRQK2M0KXB52RYRXS` of review `01M6GW5VXA3A066ZAF4N072XWP`
Author
Owner

The coupling is real: the guard and its complement live in separate jobs, and today they agree only because they're kept in step. They aren't hand-written in this repository, though. align renders all of them from templates/workflows/{commit-msg,checks,dedupe-check}.yml.hbs, and it moved the canary into commit-msg on purpose in j4k/align#1011, where its branch-protection policy (src/checks/branch-protections/policy.ts) requires the same-repo-pr status. A local edit here would be overwritten on the next align run and would break that policy. So the question of where the admission rule should live belongs to align's standard. I've reported it there for a follow-up. It doesn't block this PR, which only re-renders the managed files.

<!-- gh-feedback:reply-to:228842 --> The coupling is real: the guard and its complement live in separate jobs, and today they agree only because they're kept in step. They aren't hand-written in this repository, though. align renders all of them from `templates/workflows/{commit-msg,checks,dedupe-check}.yml.hbs`, and it moved the canary into `commit-msg` on purpose in j4k/align#1011, where its branch-protection policy (`src/checks/branch-protections/policy.ts`) requires the `same-repo-pr` status. A local edit here would be overwritten on the next align run and would break that policy. So the question of where the admission rule should live belongs to align's standard. I've reported it there for a follow-up. It doesn't block this PR, which only re-renders the managed files.
jercik marked this conversation as resolved
jercik merged commit 6fec7ac27e into main 2026-11-03 14:30:49 +00:00
jercik deleted branch chore/align-17-15-4 2026-11-03 14:30:49 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
j4k-oss/askpplx!17
No description provided.