Skip to content

ci: run one-function-per-file at upstream's default - #1103

Merged
thekevinbot merged 1 commit into
mainfrom
claude/1020-ofpf-default-q7v3
Sep 5, 2026
Merged

thekevinbot merged 1 commit into
mainfrom
claude/1020-ofpf-default-q7v3

Conversation

@thekevinbot

Copy link
Copy Markdown
Collaborator

Fixes #1020.

The last rung. Every scanned root is already clean at max_lines = 1, so the
committed ceiling holds nothing back and the key comes out. Upstream's default
for python and typescript is 1, spelled out in the CLI's own help:

Optional: if the file — or its [<language>].one_function_per_file table — is
absent, the default threshold of one line applies and nothing is exempt

Deleting the key therefore makes the gate stricter, not looser. Nothing is
added to replace it — the rule stays in the gate list of every lane that names
one, and stays in the reusable workflow's default set for the two SDK lanes.

Census — all five roots, threshold 1

Measured on main at 3a1e427 in a throwaway clone under /tmp. Each root's
config was copied out and max_lines set to 1 in the copy; no config in
the repo was edited to take the measurement.

Root Language Config Violations
internals/checks/src python internals/checks/testing-conventions.toml 0
packages/ts/src typescript packages/ts/testing-conventions.toml 0
packages/python/dirsql python packages/python/testing-conventions.toml 0
plugins/dirsql-plugin-embeddings/src python plugins/dirsql-plugin-embeddings/testing-conventions.toml 0
internals/distcheck/src python root testing-conventions.toml (that job passes no config:) 0

Tool version. Measured with testing-conventions@latest, which resolved to
0.0.115 — npm latest moved from 0.0.111 mid-campaign, and CI is unpinned,
so latest is what CI will run. Re-measured under 0.0.111 as well: identical
verdicts, exit 0 on all five. Nothing is pinned or floored anywhere as a result.

Positive controls, because exit 0 alone cannot tell "clean" from "scanned
nothing."
A module with two multi-line module-scope functions was planted
inside a copy of each of the five real trees and the same command re-run.
All five failed, each naming the planted beta:

zz_control.py:6: one-function-per-file — `beta` runs 2 lines, and `alpha`
already holds this file; move it to its own module

Only the control was named — the rest of each tree stayed clean, so the zeros
above are real scans of real files.

What is deleted, and what is not

one_function_per_file was the sole key in each [python] / [typescript]
table, so the bare header goes with it. Six tables across five files:

File Table Was
testing-conventions.toml [python] 12
testing-conventions.toml [typescript] 12
packages/ts/testing-conventions.toml [typescript] 12
packages/python/testing-conventions.toml [python] 12
internals/checks/testing-conventions.toml [python] 12
plugins/dirsql-plugin-embeddings/testing-conventions.toml [python] 10

Untouched: [python.coverage], [typescript.coverage], [rust] /
[rust.coverage], [e2e], and both [[python.exempt]] entries. Those are
separate TOML tables and need no bare parent header. Root [rust] stays as is —
upstream ships no default for this rule on Rust, which is deliberately out of
scope for the ratchet.

Verified, not assumed. Two things were checked rather than reasoned about:

  1. The coverage floor is still read with the header gone. Ran unit coverage
    against a copy of the post-deletion internals/checks config with the floor
    raised to an impossible 101:
    error: coverage check failed — coverage 100.00% is below the required 101%.
    The table is read; only the one-function-per-file threshold changed.
  2. Every post-deletion config still parses and still enforces 1. Each of the
    five edited configs re-runs the census at exit 0, and the two positive
    controls still fail against them — the same verdicts as the explicit
    max_lines = 1.

Verification

  • just preflight: 0 failing pair(s), 3 skipped — 40 (root, gate) pairs across 8 scan roots, including one-function-per-file on all five roots with the deleted-key configs. The three skips are packaging, which needs a built artifact.
  • Manual run of the gate on all five roots with the committed configs (the
    deleted-key form), plus the ten control runs above.

E2E Verification

N/A - config-only. No source file changes, so no receipt is owed: e2e verify
runs --scope packages/python/dirsql --extra-scope packages/rust/src --extra-scope packages/python/src (and the ts equivalent), and a
packages/<pkg>/testing-conventions.toml edit falls in none of them. Confirmed
green by just preflight, which runs e2e-verify for all four attesting
packages against --base origin/main.

Changelog / Migrations

  • Not required. changelog_gate scopes to packages/ and plugins/, and
    is_exempt waives a package-root testing-conventions.toml by exact
    re.fullmatch(rf"{p}/testing-conventions\.toml", path) — still present on
    main. The root and internals/ files are outside its roots entirely. A
    skip-changelog: line rides the commit as a backstop.
  • No migration fragment: no public API, no runtime behavior change.
  • No PARITY.md change: no SDK surface is touched.

Release impact

None. Every package's release globs carve the file out explicitly
(packages/ts/!(testing-conventions.toml)), which is what #944 exists to
guarantee, so merging this publishes nothing.

Campaign close-out

The ratchet is finished: every scanned root reports zero violations at
`max_lines = 1`, so the committed ceiling has nothing left to hold back.
Deleting the key hands the rule to upstream's default of one line, which is
stricter than any number this repo has carried.

`one_function_per_file` was the sole key in each `[python]` / `[typescript]`
table, so the bare headers go with it. `[python.coverage]`, `[typescript.coverage]`
and `[[python.exempt]]` are separate tables and are unaffected -- verified by
running `unit coverage` against a copy of the internals/checks config with the
key gone and the floor raised to 101, which fails on the floor it still reads.

Rust stays out: upstream ships no default for the rule there, and opting it in
is a design call rather than a step on this ratchet.

skip-changelog: config-only; `changelog_gate` exempts a package-root
testing-conventions.toml by exact match, and the release globs carve it out of
every published artifact.
@thekevinbot
thekevinbot merged commit b2e3e29 into main Sep 5, 2026
85 checks passed
@thekevinbot
thekevinbot deleted the claude/1020-ofpf-default-q7v3 branch September 5, 2026 12:06
@thekevinbot

Copy link
Copy Markdown
Collaborator Author

Post-merge note on the tool version, for the record: npm latest moved again between the local census and this PR's CI run. Locally latest resolved to 0.0.115 (and 0.0.111 was re-run for comparison — identical verdicts); the CI static-check jobs resolved 0.0.116. All three agree, and the typescript-sdk / Static checks log shows the gate running against --config packages/ts/testing-conventions.toml packages/ts/src — the deleted-key form — with no violations. Nothing is pinned or floored as a result.

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.

ci: ratchet one-function-per-file from max_lines = 100 toward the default of 1

1 participant