Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions docs/BACKLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,37 @@ cited report. Several of those reports — the `docs/reviews/` and `docs/securit
maintainer-internal and will not resolve here; [`SECURITY-DOCS-POLICY.md`](SECURITY-DOCS-POLICY.md)
states the rule that decides what is withheld and what you can request.

### Ledger erratum (2026-07-30) — read this before citing or allocating a number

**`#242`–`#246` as written in the ADRs are not indices into this file.**
[ADR 0115](adr/0115-asvs-l3-drive-to-pass-secure-by-default-flips-and-residual-closure.md) partitioned
the ASVS L3 drive-to-Pass programme across five work packages and writes them `BACKLOG #242`–`#246`;
ADRs 0004, 0014, 0018, 0019, 0068, 0077, 0080 and 0105 cite the same numbers as `WP #243`–`WP #246`.
Those items were filed in the maintainer-internal ledger that **this file is a published baseline of**,
and the published baseline stops at **#231** — as the #185 banner and the `#313` reference further down
already say. They were never published here, and they are not back-filled: their per-cell scope is
defined only in the `docs/security/` remediation plan, which
[`SECURITY-DOCS-POLICY.md`](SECURITY-DOCS-POLICY.md) withholds. Read those citations the way the
`docs/reviews/` and `docs/security/` paths above are read — **provenance into the internal ledger, not a
pointer into this file.** The same applies to every ASVS-programme number above #231; that programme
continued well past #246. Whether any of it is republished here is an owner decision.

**Consequently the numbers in this file above #231 are a second, independent sequence**, and items
#232–#239 and #248–#251 do not correspond to the internal items sharing those numbers. This is recorded,
not repaired: renumbering would rewrite ratified ADRs, and republishing would cross the policy above.

**#240–#247 are permanent holes — do not file there.** They were allocated on 2026-07-30 by repeated
runs for the same four titles; only the last run's numbers (#248–#251) were filed. #240–#243 are held by
a worktree that no longer exists, and `alloc.ps1` has no release verb by design ("holes are free,
collisions are not"), so those claims stand permanently and the ledger gate will refuse a commit that
files there. **#315** is a deliberate probe allocation used to verify the floor fix below; it is also a
hole. Always allocate with `scripts/coord/alloc.ps1`; never pick a number by reading this file.

The root cause is fixed: the backlog floor in `alloc.ps1` now sweeps **every** local and remote ref, as
its own header comment always promised and as the ADR path already did. Before the fix it read only
`origin/main` + `HEAD`, so numbers living on refs this branch does not carry were invisible and were
handed out as free — which is exactly how #240–#247 were issued over cited numbers.

---

## Shipped — v0.1.0 (enterprise / HA milestone)
Expand Down
35 changes: 27 additions & 8 deletions scripts/coord/alloc.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,34 @@ function Get-Floor {
}
}
} else {
# BACKLOG.md is one big file: read it from origin/main and from this worktree's HEAD + index.
$texts = @(
(& git show "origin/main:docs/BACKLOG.md" 2>$null) -join "`n"
(& git show "HEAD:docs/BACKLOG.md" 2>$null) -join "`n"
)
# BACKLOG.md is ONE BIG FILE, so the floor needs its CONTENT, not a filename listing -- but it
# still needs EVERY ref, exactly like the adr branch above and exactly as this function's own
# header comment promises. Reading only origin/main + HEAD is what re-issued #240-#247 on
# 2026-07-30 over numbers ADR 0115 and seven amended ADRs already cite: the items holding
# those numbers live on refs the published branch does not carry, so they were invisible here
# and the allocator handed the numbers out as free. A number that exists on ANY ref is taken.
#
# Batched deliberately: ~550 refs share ~190 distinct BACKLOG.md blobs, and a `git show` per
# ref costs ~34s on Windows (one process each). Two `git cat-file` processes do it in ~3s.
$refs = @("origin/main", "HEAD") + @(& git for-each-ref --format='%(refname)' refs/heads refs/remotes)
$specs = ($refs | Select-Object -Unique | ForEach-Object { "${_}:docs/BACKLOG.md" })

$oids = [System.Collections.Generic.HashSet[string]]::new()
foreach ($line in ($specs -join "`n" | & git cat-file --batch-check='%(objectname) %(objecttype)' 2>$null)) {
$p = "$line".Split(' ')
if ($p.Count -ge 2 -and $p[1] -eq 'blob') { [void]$oids.Add($p[0]) }
}

$rx = [regex]'^#{2,3} (\d+)\.'
if ($oids.Count -gt 0) {
foreach ($line in (($oids -join "`n") | & git cat-file --batch 2>$null)) {
$m = $rx.Match("$line")
if ($m.Success) { $seen.Add([int]$m.Groups[1].Value) }
}
}
$wip = Join-Path $repo "docs/BACKLOG.md"
if (Test-Path $wip) { $texts += (Get-Content $wip -Raw) }
foreach ($t in $texts) {
foreach ($m in [regex]::Matches($t, '(?m)^#{2,3} (\d+)\.')) { $seen.Add([int]$m.Groups[1].Value) }
if (Test-Path $wip) {
foreach ($m in $rx.Matches((Get-Content $wip -Raw))) { $seen.Add([int]$m.Groups[1].Value) }
}
}

Expand Down
Loading