Repository navigation
chore: carry a copyright line and SPDX-License-Identifier: MIT in every source file - #1563
Merged
Merged
Conversation
WalkthroughWarning Review details and warnings were omitted to fit the comment limit. |
jmrplens
force-pushed
the
bp-file-headers
branch
from
October 27, 2026 13:04
680e30c to
3b94948
Compare
jmrplens
force-pushed
the
bp-file-headers
branch
from
October 27, 2026 14:37
3b94948 to
eaf7a51
Compare
The finding and count-table comparators of the audit report were chains of ifs, each a strict comparison of two keys already known to differ, so gremlins' boundary mutants, < turned into <=, behave exactly as the original and live. The case of the tagless switch over the test-function families tested name == "TestMain" beside a Test prefix that already implies it, which left two mutants gremlins could not see as covered. On the base seven mutants lived and two were not covered. The comparators are now cmp.Or chains of three-way comparisons, the families a table with the redundant comparison gone, and the count table is cut with min. sortFindings also becomes stable. sort.Slice could put findings that share all four keys in either order, so two runs over one tree could list them differently; slices.SortStableFunc keeps the order they were found in. The new test sorts thirty-two findings over two keys, enough that the sort package's unstable sort no longer orders by insertion, and it failed against sort.Slice and against slices.SortFunc before passing against the stable sort. The package keeps every statement covered, 626 of 626 conditions and 500 of 500 branches, and gremlins kills all 246 mutants. Refs #1269 Signed-off-by: José M. Requena Plens <mail@jmrp.io>
Every source file is to open with two lines, the copyright statement "Copyright (c) 2026 José M. Requena Plens" and "SPDX-License-Identifier: MIT", which answer the OpenSSF Best Practices criteria copyright_per_file and license_per_file. This commit adds the gate, the fix mode that writes the header, the generators' share of it and what the header would otherwise break; the header itself reaches the tree in the next commit, made by the fix mode. cmd/internal/fileheader holds the two statements and Go, the form a Go file opens with: the two lines as comments and a blank line, without which the header would be read as the package's doc comment or join a generated file's "Code generated" comment. The gate and every generator read the same constants. cmd/audit_file_headers judges the files git holds in its index and the untracked ones it would add, read with git ls-files. That list is what the repository publishes: a walk would read what .gitignore keeps out (plan/, dist/, site/node_modules), and the name rule of internal/sourcewalk would leave out .github/scripts. Of those it judges Go, shell, PowerShell, Python, Ruby, jq, JavaScript and TypeScript, CSS, Astro, Makefiles and the Dockerfile, each with the header in its comment syntax and after what has to stay above it: a shebang, an encoding declaration on line 1 or 2 for Python and Ruby, a Dockerfile's parser directives, a CSS @charset rule, and the fence of an Astro component's frontmatter, which is where its header lives so that it is not rendered into the page. A file fails when the header is not those two lines, in order, exactly there, and at every comment line whose text opens with the word Copyright or an SPDX tag other than the header: a second copy, a header below the package doc comment, or the notice of a file somebody else wrote. The word has to end there, so the doc comment of fileheader.CopyrightStatement is not a notice. Each line is read alone, so a line of a multi-line string or a heredoc that opens with a comment marker counts as a comment, which errs towards reporting. -fix writes the header into a file that only lacks it, keeping every other byte and its mode, and never rewrites a file with another notice, so a file this repository did not write is not stamped. make check-file-headers runs it and make fix-file-headers its fix mode. It is step 32 of make analyze and a step of ci.yml's generated job. cmd/gen_action_catalog_manifest, cmd/gen_action_grants and cmd/gen_brand open the Go file each writes with the header, and the three generated files are regenerated with it. cmd/gen_action_grants/table_stub.go.txt, the Go source that generator compiles in its output's place, carries it too, by hand, since the gate does not read a .txt file. cmd/godoc_tool's fix -move-package-doc writes it into the doc.go it creates. Four things the header moves are changed here, so that making the rewrite again on a later main does not lose them. scripts/setup-orbit-fixtures.sh printed its help as lines 2 to 44 of itself, which with the header would print the header and lose the last three lines of the usage comment; it now prints the comment by its text, and its help test holds the whole comment beside #1532's nested namespace test. Three quoted compiler messages name a line the header moves three down, gobco's on internal/tools/todos in the testing README and upstream-bugs.md (49:27, now 52:27) and the redeclaration panic in scripts/coverage-conditions.sh (5:6, now 8:6), and are written as the next commit leaves them. A comment of the e2e suite that named line 28 of internal/tools/catalog_filter.go names the declaration. docs/development/file-headers.md says what the header is, which files carry it and where, how a generated file gets it, what happens to a file this repository did not write and how the rewrite lands. The command reference, the static analysis reference, the repository map and the docs/development index name the command. CONTRIBUTING gains a Copyright and License Headers subsection under Code Standards and a checklist item, and the pull request template a checkbox. CLAUDE.md gains the rule and the link, the command in the tree and the package counts (311 in the module, 338 directories holding tracked Go files). AGENTS.md gains the rule among its invariants and counts 32 analyze steps. The Go instructions say a new file opens with the header, the Copilot instructions name the command, the create-mcp-tool templates open with the header, and the go-source-documentation skill and the go-source-documenter agent say it sits above a file's own comment and is not a doc comment. The tests were written first. Against stubs of every function, with the Makefile and ci.yml as they stood before, 14 of the command's 16 test functions failed; the two that passed expect an empty answer, which is the stubs'. The cases for jq failed before the kind existed, the word boundary's four cases failed under a prefix rule, and a fixture planted with a user ignore file naming *.sh lost its script until the tests' git isolation also replaced the user configuration directory. The generators' three new tests and godoc_tool's three doc.go move tests failed before each wrote the header, two more doc.go expectations in its bound tests were updated when the change made them fail, and the help test of setup-orbit-fixtures.sh failed on the fixed range. The command covers every statement, condition and branch and gremlins kills every mutant; godoc_tool, the three generators and fileheader keep every statement, condition and branch with no mutant left alive. Refs #1269 Signed-off-by: José M. Requena Plens <mail@jmrp.io>
…ry source file Every source file of the repository now opens with "Copyright (c) 2026 José M. Requena Plens" and "SPDX-License-Identifier: MIT", as comments of its language, which answers the OpenSSF Best Practices criteria copyright_per_file and license_per_file. make fix-file-headers wrote the header into the 3419 files that lacked it: 3278 Go files (testdata included), 54 Python, 36 shell, 18 MJS, 13 Astro, 9 CSS, 5 TypeScript, and the Ruby, PowerShell, JavaScript and jq files, the Makefile and the Dockerfile. A shebang, the Dockerfile's syntax directive and each Astro component's frontmatter fence stay above it, and every other byte and every file mode is kept. The three generated Go files and the action grants stub carry it already, from the previous commit. One edit is by hand. cmd/audit_test_closed_servers pins the line of every finding in its planted module, which the header moves three lines down, so the 64 positions of plantedFindings and the three literals beside them move by three; each of the new values is what the audit reports. go build, go vet, the e2e build, the whole unit suite, the harness, HTTP and stdio transport suites, golangci-lint and its formatters over the tree, every step of make analyze, the Python script tests, the bundle manifests jq derives and the site's checks, build and lint pass over the rewritten tree, and make check-file-headers reports all 3432 source files carrying the header. Refs #1269 Signed-off-by: José M. Requena Plens <mail@jmrp.io>
jmrplens
force-pushed
the
bp-file-headers
branch
from
October 27, 2026 17:05
eaf7a51 to
ca76db6
Compare
|
jmrplens
added a commit
that referenced
this pull request
Oct 28, 2026
…ndency and regenerate the testing reference (#1564) Refs #1269, #1114, #1243, #1129 This is the top of the stack that carries the OpenSSF Best Practices work of #1269 and the supply-chain layers below it (#1114, #1243, #1269's Scorecard workflow and #1129's image scan). The layers below leave the committed generated artifacts stale under the freshness deferral, and this one regenerates them once, on the tree the merge puts on `main`. It also carries the fixes the review bots' threads on the layers asked for, each in a commit of its own (Review fixes, below); it changes no handler. The whole stack sits on `main` at `8f339f4e8`, onto which I rebased it on 27 October 2026, layer by layer and in order. Every commit of it is signed and carries a `Signed-off-by` trailer: the layers written before the maintainer adopted the Developer Certificate of Origin got theirs from `git rebase --signoff`. Where a layer met `main`'s configuration stack (#1518 to #1525) or the Orbit fixtures' move (#1532) the conflicts kept both sides, and generated files took `main`'s side to be regenerated here. The supply-chain stack's own regeneration, `c-c1-regen`, conflicted with `main`'s testing reference, held nothing else, and was dropped, so `issue-1129-trivy` is now the top of that part. The header rewrite of `bp-file-headers` was made again by `make fix-file-headers` on the rebased tree rather than rebased. ## What it regenerates Only the testing reference moves, and the action record gains the one file a review fix reads. The layers and the review fixes add 271 test functions, 266 under `cmd/` and five in `test/e2e/http`, 41 test files under `cmd/` and seven packages, so `docs/development/testing/testing.md` gains them in its totals, its naming breakdown, its distribution table and the `cmd` coverage table. I refreshed the counts with `go run ./cmd/gen_testing_docs/ -skip-coverage`, which carries every recorded coverage figure forward and writes `n/a` for a package no coverage run has measured. The six new packages that have statements (`cmd/audit_dco`, `cmd/audit_file_headers`, `cmd/audit_image_vulns`, `cmd/audit_site_headers`, `cmd/fuzz_targets` and `cmd/reproduce_release`) carry the 100.0% `go test -covermode=count -cover` reports for each, and `cmd/internal/fileheader`, which holds constants alone, keeps `n/a`. A second `-skip-coverage` run keeps every figure. Every other generator of `make update-all` runs on this tree and writes nothing: the brand assets, the action grants, the token footprint, the site stats, the llms files, the per-domain tool reference in both languages, the LobeHub manifest, the model corpus ledger and results page, the action catalog manifest, the benchmark charts and the e2e coverage record page, and the table formatter after them. The request inventory, recorded again over the whole unit suite on this tree, does not move (1680 rows, 976 paths, 1090 of 1090 catalog actions owned by a package that recorded a request). `go run ./cmd/audit_supply_chain -record` reads the 32 pinned actions again from GitHub and writes only the Dockerfile of `hadolint/hadolint-action`, which the review fix for #1552 reads. The package and file counts in `CLAUDE.md` match the tree: 311 packages in the module, 338 directories holding tracked Go files, 182 under `internal/tools`, 788 non-test and 488 test Go files there. ## Checks on this head With the freshness comparisons checked (`GITLAB_MCP_TEST_SNAPSHOT_PARITY` unset): - `go test ./... -count=1`: 301 packages pass, recording the request inventory as they run, and `go run ./cmd/gen_request_inventory/ -check` passes after them (1680 rows, 976 paths). The coverage job's own command passed with a total of 100.0% of statements on the head before the review fixes, and `cmd/audit_supply_chain`, the one package whose code they change, is at 100.0% of statements, 1532 of 1532 conditions and 1118 of 1118 branches under gobco, with gremlins leaving no mutant of the five files they change lived, uncovered or timed out. - Every `make` target the generated artifacts job runs, 45 of them with `check-closed-servers`, `check-supply-chain`, `check-e2e-static` and `audit-catalog-first`, passes; `check-openplugin`, `check-server-json-packages` (the eight declared packages), `check-file-headers` (3434 source files) and `check-dco` (all 73 commits from `8f339f4e8`) pass locally, since the first two need `jq` and the network and the last two read git. - `make analyze` on the remote runner: 30 of 32 steps pass. Step 6, markdownlint, has no `npx` there, and step 32, the file headers, has no `.git`; both pass locally, markdownlint over `"**/*.{md,mdx}"`. - `make test-e2e-http` (780 tests, the 8 that need Docker for a proxy or a balancer skipped) and `make test-e2e-stdio` (277 tests) pass. - The server binary and the e2e suite's compiles of the compile job, and the type-check job's vets for windows/amd64, darwin/arm64 and linux/arm64, pass. - Locally: the repository scripts' 517 Python tests, `make check-em-dash` against `main`, `make check-plan-untracked`, `make check-mcpb`, the site's `i18n:check`, `facts:check`, `chips:check`, `llms:check`, `version:check`, `build` and `lint`, and `node scripts/check-doc-links.mjs` (350 files, 8267 anchors) pass. - Every layer's head below this one passes `go build ./...`, `go vet ./...` and `go test ./... -count=1` with the freshness comparisons deferred, as CI runs them. - `make check-pr-description` passes on this text and on every layer's. ## The release rehearsals Three layers change what `release.yml` does, and each is rehearsed from its own branch once the stack is pushed: `issue-1129-trivy` for the supply-chain layers (the PyPI publish and the image scan), `bp-release-notes` for the written summary preflight requires, and `bp-reproducible-builds` for the rebuild compared byte for byte. `gh workflow run release.yml --ref <branch>` builds, smoke-tests and dry-runs every publisher from that branch and publishes nothing. Its race gate runs the unit suite without the deferral, and the packages whose tests compare a committed artifact pass that way on each of the three branches and on `bp-image-base`. The review fix to `scripts/publish-pypi.sh`, whose `--dry-run` the rehearsal's PyPI job runs, lives on this branch, so the PyPI half of the `issue-1129-trivy` rehearsal no longer exercises the script `main` will carry, and `bp-regen` is rehearsed as well for it. ## After the first CI round The first CI round of the stack asked for fixes in ten layers, each made in the layer that owns it and folded into the commit it belongs to, or added as a commit of that layer where it is new work, and every layer above rebased on it: - SonarCloud: the duplicated literals of #1550, #1552 and #1557, the nested anonymous structs of #1553, the eight-parameter functions of #1558, the tool run by its name from PATH in #1557, #1558, #1562 and #1563 (each now resolved with `exec.LookPath`, as `cmd/gen_orbit_record` does), and the test variables of #1562. - GitGuardian on #1551: the stand-in OIDC token of the PyPI publish tests is built at run time, and no commit of that layer carries the literal. - `windows-latest` on #1555: a file in the release notes directory's place is refused on every system. - The whole-tree condition measurement of #1558, which could not measure 31 packages: `scripts/coverage-conditions.sh` stages the two external test package shapes gobco v1.3.4 cannot read, two tests read the same thing in gobco's copy as in the source, and the 31 are measured and recorded. I decided on 27 October to keep that staging, which supersedes my decision of 6 October to leave the limit to gobco, until gobco publishes a release with the fixes; upstream-bugs entries 97 and 140, the script and the testing page say it is temporary. - #1561 gained the hardened mode the maintainer decided on: `--allow-plaintext-http` defaults to `true`, and `false` refuses a plaintext listener off loopback, as register row ADM-015. This head regenerates the testing reference once more for the tests that round added. On every layer's head, `go build ./...`, `go vet ./...` and `go test ./... -count=1` pass with the freshness comparisons deferred, and every package whose code that round changed is at 100.0% of statements, with every condition and branch gobco counts there taken and no mutant lived or uncovered beyond the one constant initializer of `cmd/server/listen.go` the layer below names. ## Review fixes The review bots' threads on #1550 to #1562 found ten real gaps, and I fixed each here, at the top, in a commit of its own, so no layer below changes and only this pull request runs CI again; every thread, declined ones included, is answered with the commit or with why it does not apply. In `cmd/audit_supply_chain` (#1550, #1552, #1555): a GoReleaser template is a value only the run knows and a build's overrides and a flags string are read, an absolute `--config`, `dir` or `dist` stays absolute and is refused, a tag-named image is refused in a job whose token neither it nor its workflow declares, the images a container action's Dockerfile builds from are held to their digest, read as BuildKit binds the file's stages, parser directives and heredocs (the record gains `hadolint/hadolint-action`'s Dockerfile, whose base is pinned), a release note crediting an assistant as its author is refused, and release note headings and fences are read as GitHub renders them. `TestClient_StatelessAnswersCarryNoSession` holds the stateless initialize to a JSON-RPC result (#1550), `scripts/publish-pypi.sh` publishes exactly the six platform wheels, each a regular file (#1551), the install pages say `make check-repeatable` does not build the universal macOS binary (#1557), and the Code of Conduct offers the OpenPGP key for a report sent by email (#1560). Each testable fix came with a test that failed before it, `cmd/audit_supply_chain` stays at 100.0% of statements, and the testing reference is refreshed for the seven test functions they add. ## Dependencies This layer also moves every dependency to its newest release, with no cooldown, which fixes this PR's CI failure: golang.org/x/net v0.62.0 fixes GO-2026-6860 and GO-2026-6866 in x/net/html, and check-binary-vulns now reports no advisory on the six binaries. The other Go moves are tiktoken-go/tokenizer v0.10.0 (whose Codec interface gained two methods that the cmd/audit_tokens test doubles now implement), gqlparser v2.5.64, grpc v1.85.0, grpc-gateway v2.33.0 and their indirect dependencies. The builder image moves to the rebuilt golang:1.27.3-alpine3.24 digest. Five actions move: setup-python v7.1.0, markdownlint-cli2-action v25.0.0, login-action v4.7.0, codeql-action v4.39.1 and sonarqube-scan-action v8.4.0, with pinned-actions.json re-recorded. The release tools move to GoReleaser v2.19.0, cosign v3.1.4, oras 1.3.6 and mcp-publisher v1.8.6, the NuGet validation to the .NET 10.0.403 SDK (both dnx facts the install page relies on re-verified), and the npm validation and publishing to Node 24. The PyPI upload's lock is recompiled (platformdirs 4.13.7, pyasn1 0.6.5). The site moves to pnpm 12.16.1, Node 24.22.1 and the patch releases of astro, starlight, markdown-remark, @astrojs/check and typescript-eslint. The telemetry example moves to collector 0.164.0 and otel-lgtm 0.38.1, the balancer e2e to HAProxy 3.4, and the e2e Bitbucket fixture to 10.5, which now starts with basic authentication force-allowed: Bitbucket 10 blocks it by default, and both the fixture's setup script and GitLab's importer authenticate with it. Left out on purpose: client-go stays at v3.30.0 because it moves in its own stack (the server's major tracks it, and a bump moves the served surface and the fine-grained table); the GitLab CE/EE images stay pinned because 19.5 is still GitLab's newest release and the fine-grained table records it; Node 26 is not taken because no 26.x is LTS and it drops Corepack; TypeScript 7 is refused by the peer ranges of @astrojs/check and typescript-eslint. The release tools, the SDK and the builder image were rehearsed with `release.yml` on this branch before merging. ## Before this merges - **#1517.** It is the outside contribution open on 27 October, based on `main` at `e3e09d290`. Its 18 changed source files merge with the top of this stack without a conflict; the file it adds has no header and its six commits no sign-off, which the header and DCO layers say how to handle. Milestone: 3.4.0. --------- Signed-off-by: José M. Requena Plens <mail@jmrp.io>
jmrplens
added a commit
that referenced
this pull request
Oct 28, 2026
…ition tier stack (#1571) Refs #1280 Refs #1240 This is the top of the access level and edition tier stack. The four layers below it, the access levels of #1280 and the three layers that answer #1240, regenerate nothing under the freshness deferral, and this layer regenerates once every committed artifact they move. It adds no behavior of its own: one commit, the regeneration and the R-PATH declaration that can only land with it. The stack sits on `main` at `6c9066aef`, onto which I rebased it on 28 October 2026, layer by layer and in order. Every commit is signed and carries a `Signed-off-by` trailer. The five files the layers add carry the copyright and license header of #1563, written by `make fix-file-headers` into the commit that adds each one. `main` took row 140 of the upstream register for gobco, so the two rows the layers add are 141 and 142. The regeneration was made again on the rebased tree rather than rebased. ## The regeneration The layers changed the surface every generated artifact describes. The access level parameters publish the levels each route accepts as integer enums, the group access request approval reads the group and the requester for a Minimal access approval, and the group, member, LDAP link, group variable, issue, merge request, notification and project parameters are tier tagged or described by tier. - The tool snapshots of the individual surface and of the opaque, compact and full meta schemas, which change on the tools those parameters reach (`gitlab_access`, `gitlab_group`, `gitlab_member_role` and `gitlab_project` on the opaque meta surface; `gitlab_admin`, `gitlab_ci_variable`, `gitlab_issue` and `gitlab_user` as well on the full one). - The per-domain tool reference of the access, admin, ci-variable, group, issue, member-role, merge-request, project and user groups, in English and Spanish, the four llms files, the token footprint with the README block it writes, and the testing reference, refreshed with `-skip-coverage`. - The action request record and the fine-grained table, which gain the two optional reads of `access.approve_group` (`GET /groups/:id` and `GET /groups/:id/members/:user_id`), and the fine-grained permissions reference that prints them. - The request inventory, recorded again on the whole unit suite with the freshness checks on and merged: it gains those two reads and the `new_epic` flag a group notification settings update now sends, and nothing else moves. The site stats, the brand assets, the manifests, the model evaluation pages, the charts and the e2e coverage page regenerate unchanged, and a second run of every generator over the committed result changes nothing. ## The R-PATH declaration R-PATH reads the group the approval fetches as a `GroupDetail` the package never publishes. I declared it beside the LDAP link listing's existence probe, as a read the package makes for its own use: it is sent only when `access.approve_group` is asked for `access_level` 5 on a licensed session, reads `parent_id` alone to refuse the approval on a subgroup before it is sent, and returns nothing of the answer. The declaration lands here because only this commit's inventory holds the read, and a declaration that answers nothing fails the audit. ## How I tested it With the freshness checks on, on this head: `go test ./... -count=1` passes (301 packages), `make analyze` passes every step (markdownlint, which needs Node, and the file header check, which reads git's file list, run locally on the same tree), every check the "Generated artifacts" job of CI runs passes, among them `check-tool-reference`, `check-llms`, `check-footprint`, `check-site-stats`, `check-testing-docs`, `check-request-inventory`, `check-file-headers`, `audit-1to1-paths`, `check-action-grants`, `check-action-grants-derivation`, `audit-1to1-grants`, `check-e2e-static` and `check-tenancy`, as do `check-server-json`, `check-server-json-packages` and `check-openplugin`, `make check-dco` passes on every commit of the stack, `make test-e2e-http` (780 tests, 8 of them skipped for want of Docker on the runner) and `make test-e2e-stdio` (277 tests) pass, and the e2e packages compile. The site passes `i18n:check`, `facts:check`, `chips:check`, `llms:check`, `build` and `lint`, and `node scripts/check-doc-links.mjs` passes. Against Docker GitLab 19.5.0 both complete runs passed with the skip gate on, on this stack as it stood on `e3e09d290` before the rebase: `make test-e2e-ce` ran 1321 tests with no failure and one skip, the declared opt-in throttle probe; `make test-e2e-ee`, licensed, ran 1650 tests with no failure and no skip. The scenarios the layers added passed on all three surfaces: on CE, the Minimal access approval refused on the Free tier, a level the route does not grant refused with the request still pending, an Owner-level project access token granted to an Owner's token, and an issue created for two assignees keeping only the first; on EE, the same refusal and token, the Minimal access approval refused on a subgroup and granted on a licensed top-level group, and an instance custom role on an Owner base refused. I did not run them again after the rebase. What `main` brought in between does not reach those scenarios' requests: the header lines are comments, the plain HTTP listener check of #1561 is read only by an HTTP listener while the suite drives the binary over stdio, the Orbit fixtures moved for the GitLab.com suite, the Bitbucket fixture's image moved to 10.5 for the import coverage behind its own profile, and of the dependency updates of #1564 the binary links `golang.org/x/net`, whose IDNA package `internal/gitlab` uses, and the gRPC modules of the OTLP exporter, which runs only with telemetry turned on; the unit suite and both transport suites above run on them. ## #1517 #1517 is open, and the maintainer has asked for changes before merging it. This stack leaves to it everything it does or was asked to do: the offset paging of the merge request diffs in `mr_review.changes_get`, the page walk of the inline comment pre-check under RQB-013 with its check of the position's SHAs against the merge request's `diff_refs`, and the curated text, request declarations and test moves the review asked for; nothing here touches `mrchanges`, `mrdiscussions`, `mrdraftnotes`, `internal/toolutil/diff_position.go` or the tenancy register. Its unused `order_by`, `sort`, `pagination` and `page_token` are #1530 and the pre-check's `position_type` is #1531, both after #1517. Two hand-written files are changed by both, in different blocks, so a rebase of either is mechanical: `cmd/audit_1to1/internal/paths/sent_declarations.go`, where this stack adds the access request probe to the existence probes and its reason after the LDAP one while #1517 adds the merge request rows to the position pre-check block and their reason, and the `internal/tools/testdata/tools_meta.json` golden, where this stack changes the `gitlab_access`, `gitlab_group`, `gitlab_member_role` and `gitlab_project` entries and #1517 the `gitlab_mr_review` one. Both change generated files: `tools_individual.json`, `tools_meta_compact.json` and `tools_meta_full.json`, `docs/development/request-inventory.json`, `docs/development/action-requests.json`, `internal/tools/actiongrants/table_gen.go`, `docs/development/token-footprint.md` and `site/src/data/token-footprint.json` with the README token block, `docs/development/testing/testing.md`, `llms-full.txt`, `llms-full-individual-tools.txt` and `llms-full-meta-tools.txt`. Whichever of #1517 and this stack lands second regenerates those files on top of the other, together with the `mr-review` tool reference, which only #1517 changes and this stack regenerates unchanged. Signed-off-by: José M. Requena Plens <mail@jmrp.io>
jmrplens
added a commit
that referenced
this pull request
Oct 29, 2026
…1582) Refs #1547 This is the top of the localization stack for #1547. The five layers below it add the message catalog and `GITLAB_MCP_LANGUAGE` with English alone, teach `audit_md_escaping` the catalog and add the person-facing text gate, move every text the server shows a person directly into the catalog with English unchanged byte for byte, add the Spanish catalog, and document the setting with ADR-0027. They run their suites under `GITLAB_MCP_TEST_SNAPSHOT_PARITY=deferred`, and this one regenerates the committed artifacts once, over the whole stack. It adds no behavior of its own. The stack sits on `main` at `d6f108bcd`, onto which I rebased it on 28 October 2026, layer by layer and in order, since it had been built on `8f339f4e8` and `main` took 24 pull requests since. Every commit is signed and carries a `Signed-off-by` trailer. Every source file the layers add, the planted modules of `cmd/audit_i18n` and `cmd/audit_md_escaping` included, carries the copyright and license header of #1563, written by `make fix-file-headers` into the commit that adds it, and the lines the person-facing text gate's findings tree pins moved down three with it. The gate is now step 33 of `make analyze`, after the header gate, so the second layer renumbers every step to `/33` and moves the header gate's Makefile test to `[32/33]`. The language field and the `AllowPlaintextHTTP` field of #1561 sit side by side in the HTTP overlay and in the server's flag struct, and the package counts in `CLAUDE.md` are 312 and 339 after the first layer and 313 and 349 after the second. The regeneration was made on the rebased tree. ## The regeneration I ran every generator of `make update-all`, with the testing reference written by `go run ./cmd/gen_testing_docs/ -skip-coverage`. Every other generator found its output current: the layers move no tool, action, schema, description, resource or prompt, which is what the stack promises for anyone who leaves the setting unset, and the documentation layer already carries what the site pages and `server.json` say about the setting. The testing reference moves its package, file and test counts to the ones the stack adds. ## How I checked it On this branch, with `GITLAB_MCP_TEST_SNAPSHOT_PARITY` unset: - `go test ./... -count=1` passes over all 313 packages. - `make analyze` passes its 33 steps: 31 on a copy of the tree without `.git` or Node, and markdownlint and the copyright and license header gate in the checkout. - Every target of CI's `generated` job passes, `check-testing-docs`, `check-llms`, `check-tool-reference`, `check-site-stats`, `check-footprint`, `check-action-grants`, `check-i18n`, `check-md-escaping`, `check-gateway-chars`, `check-surface-quality`, `check-server-json` and `check-server-json-packages` among them, and so do `check-dco`, `check-em-dash` and `check-plan-untracked`. - `make test-e2e-http` (811 tests, the 8 that need Docker skipped) and `make test-e2e-stdio` (313 tests) pass. Both drive the real binary with the setting unset, `en`, `EN-GB`, `es`, `es-419` and through the flag, and ask the `interactive.issue_create` questions in English and in Spanish, with the property keys, the option values and the listings unchanged in both. - The end-to-end suite under `test/e2e/gitlab` and its harness compile under the `e2e` tag, `go vet -tags e2e` passes on them, and the harness's own tests pass. - The site's `i18n:check`, `facts:check`, `chips:check`, `llms:check`, `build` and `lint` pass, and `scripts/check-doc-links.mjs` finds every local link and anchor of 352 files. Each layer below passes on its own as well, checked out alone after the rebase: `go build ./...`, `go vet ./...` and with the `e2e` tag, the compile of `test/e2e/gitlab`, `go test ./... -count=1` under `GITLAB_MCP_TEST_SNAPSHOT_PARITY=deferred`, `make golangci-lint` over the whole module, the gates each layer's description names (`check-i18n` from the second layer up, where it exists), `check-file-headers`, `check-dco`, `check-em-dash`, markdownlint on the Markdown it changes, `check-doc-links`, and both transport modules: 790 HTTP and 288 stdio tests on the first two layers, 794 and 292 on the third, 811 and 313 on the fourth and fifth. Signed-off-by: José M. Requena Plens <mail@jmrp.io>
jmrplens
added a commit
that referenced
this pull request
Oct 29, 2026
…'s diff, publish the pagination of mr_review.changes_get, and say when a prompt read only the first page of changed files (#1584) An inline discussion or draft note on a file past the first page of a merge request's diff was refused locally as "not in the merge request diff", because the position pre-check read one page of 100 files, and `mr_review.changes_get` returned one page without saying how to continue. Nikita Turchaninov (slowaner) found and fixed both in #1517, and that work is his: the pre-check walks the diff a page at a time and stops at the file, bounded by the new register row RQB-013; it compares the merge request's `diff_refs` with the position before and after the walk; and it leaves the write to GitLab whenever its evidence is incomplete. `changes_get` publishes its pagination, and its Files line reads `N`, `N of total` or `N shown, more available`. This pull request carries #1517 to land it for 3.4.0, with him as co-author, and I'll close #1517 when it merges. His six commits carry no `Signed-off-by:` trailer, which the Developer Certificate of Origin needs on every commit since #1562, and adding one means rewriting his branch, so I squashed them into one commit of mine on today's `main`, `fix(tools): handle paginated merge request diffs`, with a `Co-authored-by:` trailer naming him, and opened it from a branch of this repository. The merge conflicted only in generated files (the README token block, the testing reference and the token footprint), and I regenerated them from the merged tree rather than taking a side. The branch is rebased on the localization stack (#1577 to #1582), where only the testing reference conflicted, regenerated the same way. #1530 and #1531 stay separate, as agreed in the review of #1517. ## What I added on top - `internal/tools/mrchanges/action_specs_test.go`, the one file the pull request adds, opens with the copyright and license header #1563 requires, written by `make fix-file-headers`. - The doc comment of `toolutil.MergeRequestDiffForPositionCheck` says again why skipping the check is safe: the write goes to the same instance with the same credential, so a 401, 403 or 404 on the listing or on the snapshot read is the refusal the write is about to get, and a transient failure, a snapshot that moved or an exhausted page budget leaves the write judged by GitLab alone. Both `validatePosition` comments that send the reader there are true again, and name the snapshot case. - The same gap in the prompts. The five prompts that read a merge request's changed files (`summarize_mr_changes`, `review_mr`, `suggest_mr_reviewers`, `mr_risk_assessment` and `mr_description_quality`) read one page of 100, as their descriptions have said since issue 1169, but counted it as the whole diff: a review or a risk assessment of a merge request changing 250 files read "Files changed: 100", with the line totals of those 100 and nothing saying the other 150 were never read. Their count now reads as `changes_get`'s does, and when the merge request changes more files a line says that every count and list covers the page alone and that `mr_review.changes_get` reads the rest from page 2 with `per_page` 100. A merge request within one page gets exactly the message it got before. `TestMRDiffPrompts_MoreFilesThanOnePage_SayWhatTheyRead` fails on the parent in every partial case, and the prompt section of the site says the same in English and Spanish. The line stays English under `GITLAB_MCP_LANGUAGE=es`, like the rest of a `prompts/get` body, since the model reads it and ADR-0027 keeps what the model reads out of the message catalog. - `suggest_mr_reviewers` reads the merge request and its changed files as `review_mr` does, but its exclusion entry named only `project.members`, so an operator who excluded `mr_review.changes_get` or `merge_request.get` was still served the changed paths through it, and with the line above it would have named the excluded action. It now names both, and `TestRegister_ExcludingAnActionRemovesThePromptServingTheSameData` fails without that. ## The other diff routes I went through every handler that reads a diff for the same gap. Whether GitLab pages a route is what the live record says it takes: only the merge request diffs, the diff versions and the commit diff declare `page` and `per_page`. | Route | Read by | Paged | Affected | | --- | --- | --- | --- | | `GET /projects/:id/merge_requests/:merge_request_iid/diffs` | `mr_review.changes_get` and the position pre-check of `mr_review.discussion_create`, `mr_review.draft_note_create` and `mr_review.draft_note_update` | Yes | Yes, fixed by slowaner's commit | | The same route | the five prompts above | Yes | Yes, fixed here: still one page, now said in the message | | `GET /projects/:id/merge_requests/:merge_request_iid/versions` | `mr_review.diff_versions_list` | Yes | No: it takes `page` and `per_page` and publishes its pagination | | `GET /projects/:id/merge_requests/:merge_request_iid/versions/:version_id` | `mr_review.diff_version_get` | No | No | | `GET /projects/:id/merge_requests/:merge_request_iid/raw_diffs` | `mr_review.raw_diffs` | No | No | | `GET /projects/:id/repository/commits/:sha/diff` | `repository.commit_diff` | Yes | No: it takes `page` and `per_page` and publishes its pagination | | `GET /projects/:id/repository/compare` | `repository.compare` and the `generate_release_notes`, `compare_branches` and `audit_commit_hygiene` prompts | No | No | | `GET /projects/:id/merge_requests/:merge_request_iid/changes` | nothing | No | No | ## How I tested it On the head, `go test ./... -count=1` passes (303 packages), recording the request inventory on the whole unit suite, and `gen_request_inventory -check` finds the committed inventory current. `golangci-lint` passes on every package the branch touches. `audit-1to1-paths`, `audit-1to1-grants`, `check-action-grants`, `check-action-grants-derivation`, `check-tenancy`, `check-surface-quality`, `check-tool-reference`, `check-meta-descriptions`, `check-action-ids`, `check-sdk-context`, `check-md-escaping`, `check-i18n`, `check-test-file-names`, `check-test-subtests`, `check-test-goroutines`, `check-godocs`, `check-llms`, `check-testing-docs`, `check-footprint`, `check-site-stats`, `check-md-tables`, `check-doc-tool-names`, `check-e2e-static`, `check-action-catalog-manifest`, `audit-catalog-first`, `check-file-headers`, `check-dco` and `check-em-dash` pass, and the three `test/e2e/gitlab` packages compile and vet under the `e2e` tag. Every generator of `make update-all` runs clean on the head, the testing reference with `-skip-coverage`, which its own commit refreshed. The site passes `i18n:check`, `facts:check`, `chips:check` and `llms:check`, and `node scripts/check-doc-links.mjs` passes. I did not run the Docker suites against a GitLab. <details> <summary>Design notes from slowaner's description</summary> The position pre-check searches for the requested old or new path one page at a time and stops at the first match. It retains no earlier pages. Discussion create and draft-note create and update share this lookup and preserve the requested body, position and SHAs. Before trusting the listing, the helper reads the merge request's `diff_refs` and compares all three SHAs with the position. It reads them again after finding the file or finishing the listing. Both snapshot reads are kept: the second detects a push during the search, so evidence from a newer diff cannot justify a local refusal. A successful lookup costs k+2 reads for a match on page k, plus the write. This remains best effort, since GitLab validates changes after the final read. A changed, missing or unreadable snapshot, a listing error, cancellation, non-advancing pagination or an exhausted page budget makes the pre-check advisory, and GitLab judges the original write. Only a complete, stable result can produce the existing file or line error. A matching file with no available patch skips line validation. The walk is bounded by RQB-013 at 100 actual list calls of 100 files. A match or completed listing on call 100 is valid; call 101 is never sent. Reaching the bound adds no caller quota and does not reject the write. GitLab documents a maximum `diff_max_files` of 3,000, normally at most 30 pages at 100 files per page; the 100-call bound also ends a malformed walk that keeps advertising another page. GitLab's own diff-size limits still apply. | Item | Answer | | --- | --- | | VAL-001 | Allow: bounds the diff pages one advisory position check may read. | | VAL-002 | `KeyRequest`; mint cost is nothing. Each invocation has its own finite walk; this is not an allowance accumulated by a caller. | | VAL-003 | Class P, as computed for a request bound by the register. No class D finding. | | VAL-004 | `RequestBound`, not a share or fairness guarantee. | | VAL-005 | No claim to protect a process-wide resource or one population from another, so no process partner applies. | | VAL-006 | At 100 list calls, a match or terminal page is accepted. If another page is needed, discard incomplete evidence and let GitLab judge the unchanged write. No table is keyed on caller input. | | VAL-007 | No new refusal, channel, code, HTTP status, `Retry-After` or retry class, on HTTP or STDIO. Existing stable-snapshot position errors remain unchanged. | | VAL-008 | Counts actual diff-list calls within this lookup only. It does not charge an admission, tenant or server quota, and charges no unjudged write. | | VAL-009 | Fixed source constant `mergeRequestDiffPositionMaxPages = 100`; 100 files per call. No new setting, flag or MCP parameter, so operator-supplied zero and malformed values do not apply. | | VAL-010 | Debug diagnostics state why the advisory check was skipped. No new refusal metric or caller/address identity label; existing project/MR context identifies the operation. | | VAL-011 | The same request bound and advisory fallback apply on STDIO. | | VAL-012 | No population-protection or fairness claim, so fairness measurement is not applicable. Boundary, early-stop and fallback behavior are covered by regression tests. | `changes_get` publishes pagination metadata in structured output and Markdown. Guidance describes offset continuation, `next_page` as `page`, with `per_page: 100`. The keyset request option #1517 first added, and its synthetic endpoint tests, were removed during its review, and the existing input fields stay as they are for #1530. </details> Co-authored-by: Nikita Turchaninov <2010628+slowaner@users.noreply.github.com>
This was referenced Oct 29, 2026
jmrplens
added a commit
that referenced
this pull request
Nov 1, 2026
…the PyPI and Homebrew packages (#1696) Closes #1591 #1563 gave every tracked source file the copyright and license header and made the Go generators and the create-mcp-tool templates write it. This closes the places it left out, which create source outside the tree `make check-file-headers` judges. Five Go templates still showed a new file opening with its package clause: the minimal `doc.go` and the `action_specs.go` of the go-safe-move-refactor skill, the `action_specs.go` of the modularize-go-package skill, and the two files of the sub-package example in `docs/development/development.md`. Each now opens with the two header lines and a blank line, which in the `doc.go` template keeps the header from being read as the package comment. The forwarding stubs of that skill's step 5 showed the file with a path comment right above `package tools` and no header, which would fail the gate and `make check-godocs`; it keeps its header now. In `development.md` the file paths moved out of the code blocks into the sentences before them. Two release scripts write source into what they publish, and neither carried the header: `scripts/build_pypi.py` writes `__init__.py` and `__main__.py` into every wheel, and `scripts/update-homebrew-tap.sh` writes the Ruby formula the tap serves. Each now opens it with a `FILE_HEADER` of its own, spelled on one line on purpose: the gate reads each line of a script alone, so a line of a triple-quoted string or a heredoc opening with the notice would count as a second copy of the script's own header. In the formula the header comes first, where the gate puts it in a Ruby file with no shebang, and the `typed` and `frozen_string_literal` magic comments follow; Ruby reads those in any comment before the first token. No gate reads either output, so a test of each script holds it to the header the script opens with below its shebang, the one the gate ties to `cmd/internal/fileheader`, and a change of holder or year moves the oracle with the tree. `test_the_package_modules_open_with_the_file_header` builds the six wheels and reads both modules of each, which must still compile. `test_the_formula_opens_with_the_file_header` renders the formula and runs its leading comments under Ruby, which freezes a literal only while the magic comment is read. Both fail on main and pass here. `docs/development/file-headers.md` names the wheel modules and the formula among the generated source, and its section on changing the holder or the year lists the copies the gate does not read. Item 13 of #1114 ports `build_pypi.py` to Go; if that lands later, the port writes the header from the `fileheader` constants. I checked it with every Python script test, shellcheck, `make check-file-headers`, `check-dco`, `check-em-dash`, `check-test-subtests`, `check-test-goroutines`, `check-godocs`, `check-action-ids`, `check-surface-quality`, markdownlint and `format_md_tables --check` on the touched pages, and `scripts/check-doc-links.mjs`. No Go package changes. --------- Signed-off-by: José M. Requena Plens <mail@jmrp.io>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Refs #1269
What this changes
Every source file of the repository now opens with two lines,
Copyright (c) 2026 José M. Requena PlensandSPDX-License-Identifier: MIT, written as comments of its language. These answer the OpenSSF Best Practices criteriacopyright_per_fileandlicense_per_file, which ask every source file to name its copyright holder and its license, the second in the SPDX form near the top of the file. Until now no source file said either.The pull request has three commits: a refactor of
cmd/godoc_toolthat its mutation gate asked for once this layer touched it; the gate with its fix mode, the generators' share of the header and what the header would otherwise break; and the rewrite of the tree made by that fix mode. The testing reference that counts the new tests is regenerated once, at the top of the stack.The gate
cmd/internal/fileheaderholds the two statements,CopyrightStatementandLicenseStatement, andGo, the form a Go file opens with: the two lines as comments and a blank line. Without the blank line the header would be read as the package's doc comment, or would join a generated file'sCode generatedcomment. The gate and every generator read the same constants, so a header a generator writes is the header the gate holds it to.cmd/audit_file_headersjudges the files git holds in its index and the untracked ones it would add, read withgit ls-files. I chose git's list over a walk of the tree because the question is which files the repository publishes. A walk would read what.gitignorekeeps out (plan/,dist/,site/node_moduleswith its thousands of files somebody else wrote) unless it named each of them again, and the name rule ofinternal/sourcewalkleaves out every dot-directory, which would leave out the scripts under.github/scripts. Files of a checkout nested in the tree are not listed, which is the answer the marker rule ofinternal/sourcewalkgives a walk. The cost is that the command runs in a checkout, not in a copy of the tree without its.git.Of those files it judges Go (testdata included), shell, PowerShell, jq, Python, Ruby, JavaScript and TypeScript in each of their extensions, CSS, Astro components, Makefiles and the Dockerfile. Markdown, MDX, JSON, YAML (the workflows included), TOML, the pinned GraphQL schema, plain text, SVG and images are documentation, data and configuration and carry no header. Each kind gets the header in its comment syntax, after what has to stay above it to keep working: a shebang, an encoding declaration on line 1 or 2 for Python and Ruby, a Dockerfile's parser directives, a CSS
@charsetrule, and the frontmatter fence of an Astro component, whose header lives in the frontmatter so that it is not rendered into the page. In a Go file the header comes before any build constraint, as in the Go project's own files.A file fails when its header is not those two lines, in order, exactly there. It also fails at every comment line whose text opens with the word
Copyrightor with an SPDX tag other than the header: a second copy of the header, a header written below the package doc comment, or the notice of a file somebody else wrote. The word has to end there, so the doc comment ofCopyrightStatementis not a notice. Each line is read alone, without the syntax of the file around it, so a line of a multi-line string or a heredoc that opens with a comment marker is read as a comment. The rule errs towards reporting, since a notice it missed would be a file somebody else wrote stamped with this one. Running it over the tree found two lines of ours: the doc comment of the constant, then namedCopyright, which is why the word has to end there and the constant is nowCopyrightStatement, and a line of the gate's own comment, which I reworded.-fixwrites the header into every file that does not open with it and carries no other notice, followed by a blank line unless the file has one there already, keeping every other byte and the file's mode. An Astro component without a frontmatter is given one around the header. A file with another notice is never rewritten. No file in the tree carries one today: the module vendors nothing and the site's dependencies stay insite/node_modules.make check-file-headersruns the gate andmake fix-file-headersits fix mode. It is step 32 ofmake analyze, and a step of thegeneratedjob ofci.yml, which runs on every pull request and every push tomain.The generators and what the header moves
cmd/gen_action_catalog_manifest,cmd/gen_action_grantsandcmd/gen_brandopen the Go file each writes with the header, and the three generated files are regenerated with it, never edited.cmd/gen_action_grants/table_stub.go.txt, the stand-in the generator compiles intable_gen.go's place, is Go source under a.txtname the gate does not read, and it carries the header by hand in the same commit.cmd/godoc_tool'sfix -move-package-docwrites the header into thedoc.goit creates.The same commit changes what the header would break or leave pointing at the wrong line, so that making the rewrite again on a later
mainloses none of it.scripts/setup-orbit-fixtures.sh --helpprinted lines 2 to 44 of the script, which with the header would have printed the header and lost the last three lines of its usage comment; it now prints the usage comment by pattern, and its help test holds the whole comment. Three quoted compiler messages name a line the header moves three down: theinternal/tools/todosfailure quoted in the testing README and inupstream-bugs.md(49:27, now52:27) and the redeclaration panic quoted inscripts/coverage-conditions.sh(5:6, now8:6), each written as the rewrite leaves it. A comment of the e2e suite that named line 28 ofinternal/tools/catalog_filter.gonames the declaration instead.Other line references in
docs/developmentto positions in this repository's own files had already drifted before this change, and I left those as they were:settings.go:35in the testing README, for one, is a comment and not theerr != nilthe README names, and moving it by three would not make it right.The godoc_tool refactor
Touching
godoc_toolmeant holding it to the mutation gate, and on the base seven of its mutants lived and two were not covered: the finding and count-table comparators, whose<mutated to<=cannot be told apart where the keys are already known to differ, and the case expression of a tagless switch over the test-function families. The first commit makes the comparatorscmp.Orchains of three-way comparisons and the families a table, and cuts the count table withmin; these order and count as before. It also changes one behavior:sortFindingsbecomes stable.sort.Slicecould put findings that share all four keys in either order, so two runs over one tree could list them differently, andslices.SortStableFunckeeps the order they were found in.The rewrite
The third commit was made by
make fix-file-headers, run afresh on this layer after the stack was rebased ontomainat8f339f4e8rather than rebased itself: 3419 files, 3278 of them Go, 54 Python, 36 shell, 18 MJS, 13 Astro, 9 CSS, 5 TypeScript, and the Ruby, PowerShell, JavaScript and jq files, the Makefile and the Dockerfile. One edit is by hand.cmd/audit_test_closed_serverspins the line of every finding in its planted module, which the header moves three lines down, so its 64 positions and the three literals beside them move by three; each new value is what the audit reports. Thatmainhad not changed the audit, so the two test files are the hand-edited ones of the first rewrite, and every other file the first rewrite stamped whose contentmainhad not changed came out of the fresh run byte for byte the same.Documentation
docs/development/file-headers.mdsays what the header is, which files carry it and where, how a generated file gets it, what happens to a file this repository did not write, how a change of holder or year is made, and how this rewrite lands. The command reference, the static analysis reference (itsmake analyzerow and the two new targets), the repository map and thedocs/developmentindex name the command.CONTRIBUTING.mdgains a Copyright and License Headers subsection under Code Standards and a checklist item, and the pull request template a checkbox.CLAUDE.mdgains the rule and the link, the command in the tree and the package counts (311 in the module, 338 directories holding tracked Go files).AGENTS.mdgains the rule among its invariants and counts 32 analyze steps. The Go instructions say a new file opens with the header before itspackageclause, the Copilot instructions name the command, thecreate-mcp-toolskill's templates open with the header, and thego-source-documentationskill and thego-source-documenteragent say the header sits above a file's own comment and is not a doc comment.Tests
I wrote the tests first. Against stubs of every function, with the
Makefileandci.ymlas they stood before, 14 of the command's 16 test functions failed; the two that passed expect an empty answer, which is the stubs'. The cases I added later failed first too: the jq cases before the kind existed; the word boundary's four cases (// CopyrightStatement is ...,// Copyright_holder ...,// Copyright2026 ...,// Copyrighted material) under the earlier prefix rule; a fixture planted beside a user ignore file naming*.sh, which lost its script until the tests' git isolation also replaced the user configuration directory; the help test ofsetup-orbit-fixtures.shagainst the fixed line range; andgodoc_tool's stable-sort test, which sorts thirty-two findings over two keys and failed againstsort.Sliceand againstslices.SortFunc. The three generators' new tests andgodoc_tool's threedoc.gomove tests failed before each wrote the header; two moredoc.goexpectations, ingodoc_tool's bound tests, I found when the change made them fail, and updated.The cases run over real repositories built in temporary directories, with git's system and user configuration and the user's ignore file kept out: a clean tree, a planted file without the header, a third-party notice, a header beside another notice, the fix mode writing and keeping an executable script's mode, the fix mode leaving a file with another notice and writing nothing over a clean tree, a file deleted from the working tree, a symbolic link, a directory that is not a repository, and a file that cannot be stated, read or rewritten. The rule's own cases cover each kind and each preamble, the header absent and out of place, and what the fix writes, each fix judged clean afterwards. Two contract tests hold the
Makefileandci.ymlto the targets and the step.On the tree itself, the gate passes over all 3432 source files, and with an untracked Go file and an untracked shell script planted without the header it fails naming both.
What only the maintainer can do
mainwill have gained source files without the header, and made again it is exactly the fix mode's output over that tree: on themainof that moment, the first two commits rebased as usual, thenmake fix-file-headersrun afresh, then the positions incmd/audit_test_closed_serversmoved again, whichgo test ./cmd/audit_test_closed_servers/names, and the testing reference regenerated. Everything else the header needs by hand travels in the second commit, so it is rebased rather than made again.mainate3e09d290. I merged each of the 18 source files it changes withgit merge-file, its base against the top of this stack, and none conflicts. The file it adds,internal/tools/mrchanges/action_specs_test.go, has no header and fails the gate until its author runsmake fix-file-headersafter rebasing.test/fixtures/orbitnow carry the header. The fixture projects on GitLab.com keep the content they were created with, sincescripts/setup-orbit-fixtures.shpushes a fixture only when it creates the project; no recorded answer depends on their line numbers.copyright_per_fileandlicense_per_filecan be answered Met once this merges, withmake check-file-headersanddocs/development/file-headers.mdas the evidence.Checks run
go test ./cmd/audit_file_headers/ -count=1 -cover: 100.0% of statements;make coverage-conditions PKG=./cmd/audit_file_headersin condition mode (94/94) and branch mode (56/56);make coverage-mutants PKG=./cmd/audit_file_headers: 65 killed, 0 lived, 0 not covered.cmd/godoc_tool: 100.0% of statements, 626/626 conditions, 500/500 branches, 246 mutants killed, 0 lived, 0 not covered, after the refactor commit and again after the gate commit.cmd/gen_brand,cmd/gen_action_catalog_manifestandcmd/gen_action_grants: 100.0% of statements, every condition and branch, and 56, 7 and 98 mutants killed with none lived or not covered.go build ./...,go vet ./...,go test -tags e2e -cover./test/e2e/gitlab/..., andgo test ./... -count=1: pass.make test-e2e-harness,make test-e2e-httpandmake test-e2e-stdio: pass.golangci-lint config verify,golangci-lint fmt --diffandgolangci-lint runover the tree with the analysis tags, and every other step ofmake analyze, the new step 32 included: pass.make check-action-catalog-manifest,make brand-checkandmake check-action-grants: the three generated files are current.make check-mcpb: pass, and the manifestmcpb/platform.jqderives for each of the three platforms is byte for byte the one it derived before the header.python3 -m unittest discover -s scripts -p "*_test.py": 509 tests pass.i18n:check,facts:check,chips:check,llms:check,version:check,buildandlint, andnode scripts/check-doc-links.mjs: pass.npx markdownlint-cli2andgo run ./cmd/format_md_tables/ --checkon the changed pages: pass.make check-testing-docs,make check-dco DCO_BASE=bp-dco,scripts/check-em-dash.sh diff bp-dcoandmake check-pr-descriptionon this text: pass.On the rebased stack
I rebased the stack onto
mainat8f339f4e8on 27 October 2026 and made the rewrite again on it, as described above. Thatmaincarries #1532, which lengthened the usage comment ofscripts/setup-orbit-fixtures.sh, printed it as lines 2 to 44 and added a test of a nested namespace, so the gate commit's change to the same lines conflicted: the merge keeps the help printed by pattern, and the help test beside #1532's. The checks above ran on this layer before that rebase. On the rebased head,go build ./...,go vet ./...andgo test ./... -count=1pass with the freshness comparisons deferred, as CI runs every layer below the top,make check-file-headerspasses over all 3432 source files, and every commit carries aSigned-off-bytrailer. The committed generated artifacts are regenerated once at the top of the stack, which runs every gate over the combined tree.After the first CI round
SonarCloud found
listFilesrunninggitby its name (S4036). It now resolves git withexec.LookPathand runs the absolute path, ascmd/gen_orbit_recordandcmd/gen_model_resultsalready do, and a PATH holding no git is reported as the lookup's failure, which a new test holds; the change is folded into the gate's commit.cmd/audit_file_headersstays at 100.0% of statements, 96 of 96 conditions and 58 of 58 branches, golangci-lint is clean, and gremlins kills the three mutants offiles.gowith none lived or uncovered. The layers below changed in this round without adding a source file, so the rewrite commit is the fix mode's output it was, rebased; the gate commit also moves the linescripts/coverage-conditions.shnow quotes frominternal/tools/todos,action_specs_test.go:49:27, to52:27, as it moves the same quotation elsewhere.make check-file-headerspasses over the same 3432 files.