Follow-up from the review of #106, which wired inbound @adr markers into check and the Action. Shipped in v0.5.0.
The gap
The marker path bounds two dimensions and not the third. Files are capped at MARKER_SCAN_FILE_CAP = 3000 and each header window at MARKER_HEADER_WINDOW_BYTES = 8192, but markers-per-file is unbounded, and resolveSourceMarkers emits one finding per distinct (path, line, ref).
Measured against e92fe40:
- A comma-packed
// @adr 1000,1001,… line terminating inside the window yields 1,618 markers from 8,098 bytes.
- The Action evaluates up to 2,999 changed files (it refuses only
>= 3000), so the ceiling is roughly 4.85M finding objects — about 2.1 GB peak RSS and 2.8 s in sortFindings.
- All of it is authored by the pull request, reachable from a fork on a read-only
GITHUB_TOKEN.
Why this is not blocking
On ubuntu-latest it is a survivable transient. It cannot corrupt output and cannot fail the check: marker findings are warn/info, they are excluded from the rendered comment, and CheckOutcome.ok reads only error findings on changed ADR records.
The concern is a memory-constrained self-hosted runner, where an OOM surfaces through main().catch(…) into core.setFailed — pull-request-authored content failing a check run, which ADR-0021 and ADR-0022 both promise cannot happen.
Shape of a fix
marker-scan-capped already establishes the pattern: cap, then collapse the overflow into a single warn naming what was dropped. The open question is the number, which is a policy call rather than an implementation detail.
Worth recording alongside it: a single line longer than the window yields zero markers, because completeLinePrefix (packages/core/src/markers/scan.ts) drops the severed line. The amplification needs many terminated lines, or one ending just inside the window — which is why the naive "one enormous line" attack produces nothing.
Under ADR-0016, the cap test must be observed failing against an uncapped tree before it counts as coverage.
Follow-up from the review of #106, which wired inbound
@adrmarkers intocheckand the Action. Shipped in v0.5.0.The gap
The marker path bounds two dimensions and not the third. Files are capped at
MARKER_SCAN_FILE_CAP = 3000and each header window atMARKER_HEADER_WINDOW_BYTES = 8192, but markers-per-file is unbounded, andresolveSourceMarkersemits one finding per distinct(path, line, ref).Measured against
e92fe40:// @adr 1000,1001,…line terminating inside the window yields 1,618 markers from 8,098 bytes.>= 3000), so the ceiling is roughly 4.85M finding objects — about 2.1 GB peak RSS and 2.8 s insortFindings.GITHUB_TOKEN.Why this is not blocking
On
ubuntu-latestit is a survivable transient. It cannot corrupt output and cannot fail the check: marker findings arewarn/info, they are excluded from the rendered comment, andCheckOutcome.okreads onlyerrorfindings on changed ADR records.The concern is a memory-constrained self-hosted runner, where an OOM surfaces through
main().catch(…)intocore.setFailed— pull-request-authored content failing a check run, which ADR-0021 and ADR-0022 both promise cannot happen.Shape of a fix
marker-scan-cappedalready establishes the pattern: cap, then collapse the overflow into a singlewarnnaming what was dropped. The open question is the number, which is a policy call rather than an implementation detail.Worth recording alongside it: a single line longer than the window yields zero markers, because
completeLinePrefix(packages/core/src/markers/scan.ts) drops the severed line. The amplification needs many terminated lines, or one ending just inside the window — which is why the naive "one enormous line" attack produces nothing.Under ADR-0016, the cap test must be observed failing against an uncapped tree before it counts as coverage.