fix(gate): the plan-code guard catches bare sprint and phase codes, and the purge takes the P ones

The sprint alternative matched only `(S6)` or `S3e2`, so the commonest purged form (`# S6:`,
`S3's`, `"""S6 —`, `S1 justified`) and every phase code (`P1`) would come back unflagged; the phase
codes had in fact survived the purge in 16 lines (Plex client sections, the upload's header shape),
now reworded around them.

One pattern now covers epic, roadmap, sprint and phase codes; the named exceptions are TV episode
notation, a fixture's season or episode title (`title="S1"`) and ruff's `E4/E7/E9`, and a ruff rule
like `S110` does not match. The case test lists the purged forms and no longer claims every form.
audit_metrics copies the definition (ASCII, as JavaScript's \b is) and reports it as
plan_code_lines / plan_code_files.
This commit is contained in:
2026-10-05 00:50:36 +02:00
parent 5257d57196
commit 5ca2a0e6ee
10 changed files with 47 additions and 40 deletions
+2 -2
View File
@@ -79,7 +79,7 @@ beforeEach(() => {
vi.stubGlobal("XMLHttpRequest", FakeXHR as unknown as typeof XMLHttpRequest);
});
// The upload body is a Blob and only a Blob: `FormData` was accepted until P1 and is gone, because
// The upload body is a Blob and only a Blob: `FormData` was accepted once and is gone, because
// a multipart part is a DECLARED body that FastAPI spools before the route's auth dependency runs —
// and nothing on the backend can parse one any more (`python-multipart` was dropped with it).
const body = () => new Blob(["x"]);
@@ -432,7 +432,7 @@ describe("the debug session a tab records into", () => {
});
});
// P1 — the upload's wire shape is a security boundary, not a detail. A multipart part is a DECLARED
// The upload's wire shape is a security boundary, not a detail. A multipart part is a DECLARED
// body, which the server reads and spools BEFORE its auth dependency runs; the raw body is what lets
// `current_user` resolve first. A revert to FormData here would silently re-open that, and the
// backend's own test only sees the shape the client actually sends.
+1 -1
View File
@@ -391,7 +391,7 @@ export async function req<T = unknown>(
// `HttpError` throw — so callers handle failures exactly as they do a `req` call.
//
// `body` is a `Blob`/`File` — the bytes themselves, and nothing else. `FormData` was the other
// accepted shape until P1 and is deliberately gone: a multipart part is a DECLARED body, which
// accepted shape once and is deliberately gone: a multipart part is a DECLARED body, which
// FastAPI spools to disk before the route's auth dependency runs, and the backend dropped
// `python-multipart` altogether, so there is no longer anything on the other end that could parse
// one. `cfg.headers` is how a caller sends the metadata that used to ride as sibling form fields.