fix: align with j4k-align 17.15.4 #16

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

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

The package now declares engines.node >=26.0.0 and builds against @types/node 26, and CI drops its Node 24.15.0 matrix leg. The next release no longer supports Node 24.

The managed workflows also gain a same-repo-pr job that fails fork and AGit pull requests, and the release job now waits for check-tip. The oxlint config adds the nodeTest preset.

Moves `.node-version` from Node 26.12.1 to 26.13.0, the version baked into the CI image (`node-ci:26-bookworm`), so CI stops downloading Node on every run. The package now declares `engines.node` `>=26.0.0` and builds against `@types/node` 26, and CI drops its Node 24.15.0 matrix leg. The next release no longer supports Node 24. The managed workflows also gain a `same-repo-pr` job that fails fork and AGit pull requests, and the release job now waits for `check-tip`. The oxlint config 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 8s
Checks / quality-checks (pull_request) Successful in 22s
Checks / qc-result (pull_request) Has been skipped
Dedupe check / dedupe-check (pull_request) Successful in 56s
Review / Review (pull_request_target) Successful in 14m13s
c205875ed3

Review 01M6GVZCD41HNXVHTKC2DBXA3F — head c205875ed3ce34b152a6d510e8e2d6d1b467d04b

Review — j4k-oss/conventional-commit-msg @ 47433b4d5e

Scope: diff against base tree b5c77f6c4dc5
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)

low — same-repo-pr encodes the trusted-PR rule as a hand-negated copy of the guard, then classifies the PR a third time in shell

  • claim: 01M6GWBT4CVYJ5G5FG6ZKHT3X4
  • 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: module-design · arm: default
  • verdicts: 1 valid / 0 invalid / 0 uncertain
    • pass 01M6GWEBMGS221MFKS20WHRQR5 · valid: The grounded excerpt shows that the new same-repo-pr job's if is the hand-written De Morgan negation of the commitlint guard the body quotes (head.repo.full_name == github.repository && toJSON(flow) == '0'). The body also quotes the step's third classification of the same values ([ HEAD_REPO = GITHUB_REPOSITORY ] && [ FLOW != 1 ]). That is one design decision, the trusted-PR rule, encoded several times in code this change adds. The only link between the encodings is the comment 'the guard's exact complement'. This is information leakage under the split-join-and-layers reference. The body checks the skill's limits. 'An explicit coupling' requires a pinning test, and per the claim and item 01M6GWDHPWVYR01ZG120MR9YEN's grep none exists. 'Repository conventions' cuts the other way: review.yml decides inside one unit and takes a labeled skip branch. The body also keeps the correction inside the change's scope by conceding that the cross-file copies cannot be joined with needs. The proposed pr-origin gate job is a credible one-home remedy: it states the rule positively once, sets an output, and commitlint uses needs/if on it. It relies on Forgejo skipping a job whose needs failed, which the author flags. Low fits: the duplication is within the new job and nothing has drifted yet.
  • duplicates: 01M6GWDHPWVYR01ZG120MR9YEN (aposd-plain)
  • disposition: none

The rule that decides which PRs are trusted (same head repository and flow exactly '0') is now written out four times in three workflow files. The new same-repo-pr job holds a hand-negated copy of it, and its step decodes flow values again. If the trusted-PR rule changes in one guard, for example because Forgejo renames or re-encodes flow (the case this job exists to catch), someone has to find and fix the other copies by hand. A copy that falls behind fails in one of two ways: an untrusted PR passes CI green with no checks, or a trusted PR is refused.

The copies:

  • commitlint in commit-msg.yml: if: github.event.pull_request.head.repo.full_name == github.repository && toJSON(github.event.pull_request.flow) == '0'
  • quality-checks in checks.yml and dedupe-check in dedupe-check.yml each carry the same predicate after github.event_name != 'pull_request' ||.
  • The new same-repo-pr job uses the anchored condition, written by hand as the De Morgan negation. Its comment says "This job's condition is the guard's exact complement".
  • Its step classifies the PR again to pick a message: if [ "${HEAD_REPO}" = "${GITHUB_REPOSITORY}" ] && [ "${FLOW}" != "1" ]. This copy also knows that flow 1 means AGit.

The only links between these copies are the comments the change added to checks.yml and dedupe-check.yml ("commit-msg.yml's same-repo-pr job fails them instead"). Nothing runs to check that they agree.

This is information leakage: one design decision encoded in several modules that must change together (module-design-tradeoffs, "Split, join, and layer" reference, Information leakage; APoSD 2e §5.2). The fix it names is to give the knowledge one home.

Why the skill's limits do not excuse it:

  • "An explicit coupling" requires the coupling to be pinned by a test. No test covers these conditions.
  • "Repository conventions" points the other way. review.yml's header records the repository's own approach for fork PRs: no fork if:, and the wrapper "takes a labeled skip branch internally" because a skipped job reads green. That approach decides once, inside one unit.
  • Cross-file needs: is not available, so the copies in checks.yml and dedupe-check.yml cannot be removed from this file. The within-file correction still removes the negated copy and the third classification.

Correction, inside commit-msg.yml: replace same-repo-pr with one gate job, such as pr-origin, that checks out nothing. It evaluates the trusted-PR rule once, in shell, from HEAD_REPO and FLOW. For a trusted PR it sets an output trusted=true. Otherwise it prints one of the existing two ::error:: messages and exits 1. Then give commitlint needs: pr-origin and if: needs.pr-origin.outputs.trusted == 'true' in place of its own copy of the predicate. The trusted-PR rule then has one home in this file, and it is stated positively, so it can be compared directly with the checks.yml and dedupe-check.yml guards instead of through a negation.

What I examined: the full text of commit-msg.yml, the quality-checks guard in checks.yml, the dedupe-check guard in dedupe-check.yml, the review.yml header, and a grep for same-repo-pr. These conclusions come from reading the code; I ran nothing. I did not confirm that Forgejo skips a job whose needs: job failed. GitHub-compatible runners do, and the correction relies on that.

Other claims

  • grounding-pending (0)
  • ungrounded (0)
  • rejected (2)
    • 01M6GWB7B4Y98DWS4JTH7QWSSX low — Published engines.node floor jumps from >=24.15.0 to >=26.0.0 with no code need, excluding Node 24 users of the CLI
    • 01M6GWDJ97M8X0H88WQGHGPG9A low — same-repo-pr merges the fork/AGit refusal and the Forgejo flow canary into one job, then re-derives in shell which one fired
  • duplicate-of (1)
    • 01M6GWDHPWVYR01ZG120MR9YEN medium — same-repo-pr adds a hand-inverted copy of the fork/AGit guard, and only comments tie it to the guards in other workflows → 01M6GWBT4CVYJ5G5FG6ZKHT3X4
  • unadjudicated (0)

Coverage

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

lens part arm unit status runs loss
general-bug whole default claims-emitted 1 no
writing-quality whole default no-claims 1 no
restated-sets whole default no-claims 1 no
unix-cli whole default no-claims 1 no
module-design whole default claims-emitted 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** `01M6GVZCD41HNXVHTKC2DBXA3F` — head `c205875ed3ce34b152a6d510e8e2d6d1b467d04b` # Review — j4k-oss/conventional-commit-msg @ 47433b4d5ebc Scope: diff against base tree `b5c77f6c4dc5` 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) ### low — `same-repo-pr` encodes the trusted-PR rule as a hand-negated copy of the guard, then classifies the PR a third time in shell - claim: `01M6GWBT4CVYJ5G5FG6ZKHT3X4` - 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: module-design · arm: default - verdicts: 1 valid / 0 invalid / 0 uncertain - pass `01M6GWEBMGS221MFKS20WHRQR5` · valid: The grounded excerpt shows that the new same-repo-pr job's if is the hand-written De Morgan negation of the commitlint guard the body quotes (head.repo.full_name == github.repository && toJSON(flow) == '0'). The body also quotes the step's third classification of the same values ([ HEAD_REPO = GITHUB_REPOSITORY ] && [ FLOW != 1 ]). That is one design decision, the trusted-PR rule, encoded several times in code this change adds. The only link between the encodings is the comment 'the guard's exact complement'. This is information leakage under the split-join-and-layers reference. The body checks the skill's limits. 'An explicit coupling' requires a pinning test, and per the claim and item 01M6GWDHPWVYR01ZG120MR9YEN's grep none exists. 'Repository conventions' cuts the other way: review.yml decides inside one unit and takes a labeled skip branch. The body also keeps the correction inside the change's scope by conceding that the cross-file copies cannot be joined with needs. The proposed pr-origin gate job is a credible one-home remedy: it states the rule positively once, sets an output, and commitlint uses needs/if on it. It relies on Forgejo skipping a job whose needs failed, which the author flags. Low fits: the duplication is within the new job and nothing has drifted yet. - duplicates: `01M6GWDHPWVYR01ZG120MR9YEN` (aposd-plain) - disposition: none > The rule that decides which PRs are trusted (same head repository and `flow` exactly `'0'`) is now written out four times in three workflow files. The new `same-repo-pr` job holds a hand-negated copy of it, and its step decodes `flow` values again. If the trusted-PR rule changes in one guard, for example because Forgejo renames or re-encodes `flow` (the case this job exists to catch), someone has to find and fix the other copies by hand. A copy that falls behind fails in one of two ways: an untrusted PR passes CI green with no checks, or a trusted PR is refused. > > The copies: > - `commitlint` in commit-msg.yml: `if: github.event.pull_request.head.repo.full_name == github.repository && toJSON(github.event.pull_request.flow) == '0'` > - `quality-checks` in checks.yml and `dedupe-check` in dedupe-check.yml each carry the same predicate after `github.event_name != 'pull_request' ||`. > - The new `same-repo-pr` job uses the anchored condition, written by hand as the De Morgan negation. Its comment says "This job's condition is the guard's exact complement". > - Its step classifies the PR again to pick a message: `if [ "${HEAD_REPO}" = "${GITHUB_REPOSITORY}" ] && [ "${FLOW}" != "1" ]`. This copy also knows that flow 1 means AGit. > > The only links between these copies are the comments the change added to checks.yml and dedupe-check.yml ("commit-msg.yml's same-repo-pr job fails them instead"). Nothing runs to check that they agree. > > This is information leakage: one design decision encoded in several modules that must change together (module-design-tradeoffs, "Split, join, and layer" reference, Information leakage; APoSD 2e §5.2). The fix it names is to give the knowledge one home. > > Why the skill's limits do not excuse it: > - "An explicit coupling" requires the coupling to be pinned by a test. No test covers these conditions. > - "Repository conventions" points the other way. review.yml's header records the repository's own approach for fork PRs: no fork `if:`, and the wrapper "takes a labeled skip branch internally" because a skipped job reads green. That approach decides once, inside one unit. > - Cross-file `needs:` is not available, so the copies in checks.yml and dedupe-check.yml cannot be removed from this file. The within-file correction still removes the negated copy and the third classification. > > Correction, inside commit-msg.yml: replace `same-repo-pr` with one gate job, such as `pr-origin`, that checks out nothing. It evaluates the trusted-PR rule once, in shell, from `HEAD_REPO` and `FLOW`. For a trusted PR it sets an output `trusted=true`. Otherwise it prints one of the existing two `::error::` messages and exits 1. Then give `commitlint` `needs: pr-origin` and `if: needs.pr-origin.outputs.trusted == 'true'` in place of its own copy of the predicate. The trusted-PR rule then has one home in this file, and it is stated positively, so it can be compared directly with the checks.yml and dedupe-check.yml guards instead of through a negation. > > What I examined: the full text of commit-msg.yml, the `quality-checks` guard in checks.yml, the `dedupe-check` guard in dedupe-check.yml, the review.yml header, and a grep for `same-repo-pr`. These conclusions come from reading the code; I ran nothing. I did not confirm that Forgejo skips a job whose `needs:` job failed. GitHub-compatible runners do, and the correction relies on that. ## Other claims - grounding-pending (0) - ungrounded (0) - rejected (2) - `01M6GWB7B4Y98DWS4JTH7QWSSX` low — Published `engines.node` floor jumps from >=24.15.0 to >=26.0.0 with no code need, excluding Node 24 users of the CLI - `01M6GWDJ97M8X0H88WQGHGPG9A` low — `same-repo-pr` merges the fork/AGit refusal and the Forgejo `flow` canary into one job, then re-derives in shell which one fired - duplicate-of (1) - `01M6GWDHPWVYR01ZG120MR9YEN` medium — `same-repo-pr` adds a hand-inverted copy of the fork/AGit guard, and only comments tie it to the guards in other workflows → `01M6GWBT4CVYJ5G5FG6ZKHT3X4` - unadjudicated (0) ## Coverage Coverage pass: 01M6GVZCD7VFM071X1QQQ25F5Z Accounting: complete (all slots terminal; see slot results for failures) Slot health: healthy | lens | part | arm | unit status | runs | loss | | --- | --- | --- | --- | --- | --- | | general-bug | whole | default | claims-emitted | 1 | no | | writing-quality | whole | default | no-claims | 1 | no | | restated-sets | whole | default | no-claims | 1 | no | | unix-cli | whole | default | no-claims | 1 | no | | module-design | whole | default | claims-emitted | 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'

low — same-repo-pr encodes the trusted-PR rule as a hand-negated copy of the guard, then classifies the PR a third time in shell

The rule that decides which PRs are trusted (same head repository and flow exactly '0') is now written out four times in three workflow files. The new same-repo-pr job holds a hand-negated copy of it, and its step decodes flow values again. If the trusted-PR rule changes in one guard, for example because Forgejo renames or re-encodes flow (the case this job exists to catch), someone has to find and fix the other copies by hand. A copy that falls behind fails in one of two ways: an untrusted PR passes CI green with no checks, or a trusted PR is refused.

The copies:

  • commitlint in commit-msg.yml: if: github.event.pull_request.head.repo.full_name == github.repository && toJSON(github.event.pull_request.flow) == '0'
  • quality-checks in checks.yml and dedupe-check in dedupe-check.yml each carry the same predicate after github.event_name != 'pull_request' ||.
  • The new same-repo-pr job uses the anchored condition, written by hand as the De Morgan negation. Its comment says "This job's condition is the guard's exact complement".
  • Its step classifies the PR again to pick a message: if [ "${HEAD_REPO}" = "${GITHUB_REPOSITORY}" ] && [ "${FLOW}" != "1" ]. This copy also knows that flow 1 means AGit.

The only links between these copies are the comments the change added to checks.yml and dedupe-check.yml ("commit-msg.yml's same-repo-pr job fails them instead"). Nothing runs to check that they agree.

This is information leakage: one design decision encoded in several modules that must change together (module-design-tradeoffs, "Split, join, and layer" reference, Information leakage; APoSD 2e §5.2). The fix it names is to give the knowledge one home.

Why the skill's limits do not excuse it:

  • "An explicit coupling" requires the coupling to be pinned by a test. No test covers these conditions.
  • "Repository conventions" points the other way. review.yml's header records the repository's own approach for fork PRs: no fork if:, and the wrapper "takes a labeled skip branch internally" because a skipped job reads green. That approach decides once, inside one unit.
  • Cross-file needs: is not available, so the copies in checks.yml and dedupe-check.yml cannot be removed from this file. The within-file correction still removes the negated copy and the third classification.

Correction, inside commit-msg.yml: replace same-repo-pr with one gate job, such as pr-origin, that checks out nothing. It evaluates the trusted-PR rule once, in shell, from HEAD_REPO and FLOW. For a trusted PR it sets an output trusted=true. Otherwise it prints one of the existing two ::error:: messages and exits 1. Then give commitlint needs: pr-origin and if: needs.pr-origin.outputs.trusted == 'true' in place of its own copy of the predicate. The trusted-PR rule then has one home in this file, and it is stated positively, so it can be compared directly with the checks.yml and dedupe-check.yml guards instead of through a negation.

What I examined: the full text of commit-msg.yml, the quality-checks guard in checks.yml, the dedupe-check guard in dedupe-check.yml, the review.yml header, and a grep for same-repo-pr. These conclusions come from reading the code; I ran nothing. I did not confirm that Forgejo skips a job whose needs: job failed. GitHub-compatible runners do, and the correction relies on that.

lens module-design · arm default · tally 1 valid / 0 invalid / 0 uncertain
claim 01M6GWBT4CVYJ5G5FG6ZKHT3X4 of review 01M6GVZCD41HNXVHTKC2DBXA3F

<!-- review:claim:01M6GWBT4CVYJ5G5FG6ZKHT3X4 --> **low** — `same-repo-pr` encodes the trusted-PR rule as a hand-negated copy of the guard, then classifies the PR a third time in shell > The rule that decides which PRs are trusted (same head repository and `flow` exactly `'0'`) is now written out four times in three workflow files. The new `same-repo-pr` job holds a hand-negated copy of it, and its step decodes `flow` values again. If the trusted-PR rule changes in one guard, for example because Forgejo renames or re-encodes `flow` (the case this job exists to catch), someone has to find and fix the other copies by hand. A copy that falls behind fails in one of two ways: an untrusted PR passes CI green with no checks, or a trusted PR is refused. > > The copies: > - `commitlint` in commit-msg.yml: `if: github.event.pull_request.head.repo.full_name == github.repository && toJSON(github.event.pull_request.flow) == '0'` > - `quality-checks` in checks.yml and `dedupe-check` in dedupe-check.yml each carry the same predicate after `github.event_name != 'pull_request' ||`. > - The new `same-repo-pr` job uses the anchored condition, written by hand as the De Morgan negation. Its comment says "This job's condition is the guard's exact complement". > - Its step classifies the PR again to pick a message: `if [ "${HEAD_REPO}" = "${GITHUB_REPOSITORY}" ] && [ "${FLOW}" != "1" ]`. This copy also knows that flow 1 means AGit. > > The only links between these copies are the comments the change added to checks.yml and dedupe-check.yml ("commit-msg.yml's same-repo-pr job fails them instead"). Nothing runs to check that they agree. > > This is information leakage: one design decision encoded in several modules that must change together (module-design-tradeoffs, "Split, join, and layer" reference, Information leakage; APoSD 2e §5.2). The fix it names is to give the knowledge one home. > > Why the skill's limits do not excuse it: > - "An explicit coupling" requires the coupling to be pinned by a test. No test covers these conditions. > - "Repository conventions" points the other way. review.yml's header records the repository's own approach for fork PRs: no fork `if:`, and the wrapper "takes a labeled skip branch internally" because a skipped job reads green. That approach decides once, inside one unit. > - Cross-file `needs:` is not available, so the copies in checks.yml and dedupe-check.yml cannot be removed from this file. The within-file correction still removes the negated copy and the third classification. > > Correction, inside commit-msg.yml: replace `same-repo-pr` with one gate job, such as `pr-origin`, that checks out nothing. It evaluates the trusted-PR rule once, in shell, from `HEAD_REPO` and `FLOW`. For a trusted PR it sets an output `trusted=true`. Otherwise it prints one of the existing two `::error::` messages and exits 1. Then give `commitlint` `needs: pr-origin` and `if: needs.pr-origin.outputs.trusted == 'true'` in place of its own copy of the predicate. The trusted-PR rule then has one home in this file, and it is stated positively, so it can be compared directly with the checks.yml and dedupe-check.yml guards instead of through a negation. > > What I examined: the full text of commit-msg.yml, the `quality-checks` guard in checks.yml, the `dedupe-check` guard in dedupe-check.yml, the review.yml header, and a grep for `same-repo-pr`. These conclusions come from reading the code; I ran nothing. I did not confirm that Forgejo skips a job whose `needs:` job failed. GitHub-compatible runners do, and the correction relies on that. lens `module-design` · arm `default` · tally 1 valid / 0 invalid / 0 uncertain claim `01M6GWBT4CVYJ5G5FG6ZKHT3X4` of review `01M6GVZCD41HNXVHTKC2DBXA3F`
Author
Owner

Confirmed as a maintenance risk: the trusted-PR rule now appears in commitlint, quality-checks, dedupe-check, the negated same-repo-pr condition and its step's shell classification, tied together only by comments. Today the complement is exact, so no PR is misclassified, and the job still turns a fork or AGit PR's silent green into a failure. All of these are rendered by j4k-align 17.15.4 (templates/workflows/commit-msg.yml.hbs and the checks and dedupe templates), so a hand edit here would be overwritten by the next j4k-align --fix; giving the rule one home (for example a gate job that commitlint needs) is an align template decision. This fleet rollout may not change align, so I've reported it to the user as an align follow-up rather than opening one.

<!-- gh-feedback:reply-to:228783 --> Confirmed as a maintenance risk: the trusted-PR rule now appears in `commitlint`, `quality-checks`, `dedupe-check`, the negated `same-repo-pr` condition and its step's shell classification, tied together only by comments. Today the complement is exact, so no PR is misclassified, and the job still turns a fork or AGit PR's silent green into a failure. All of these are rendered by j4k-align 17.15.4 (`templates/workflows/commit-msg.yml.hbs` and the checks and dedupe templates), so a hand edit here would be overwritten by the next `j4k-align --fix`; giving the rule one home (for example a gate job that `commitlint` `needs`) is an align template decision. This fleet rollout may not change align, so I've reported it to the user as an align follow-up rather than opening one.
jercik marked this conversation as resolved
jercik merged commit 5e2b53d765 into main 2026-11-03 14:26:57 +00:00
jercik deleted branch chore/align-17-15-4 2026-11-03 14:26:57 +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/conventional-commit-msg!16
No description provided.