From 6643b152cada9a0978893074916a7107ddd89c43 Mon Sep 17 00:00:00 2001 From: garrytan Date: Wed, 28 Oct 2026 19:46:40 +0000 Subject: [PATCH] docs(pregate): state exactly which allow_paths file names are refused Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --- CHANGELOG.md | 2 +- docs/pregate.md | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1615bc83..af81a6063 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ **A sealed policy can now refuse `sealed//tasks.json` while allowing the `MANIFEST.json` beside it, and can catch `HELDOUT/` with a `heldout` glob.** The sealed guard only had deny globs and one-commit waivers, so the gstack-evals layout, which keeps a public manifest of hashes and counts next to its sealed tasks, needed a fresh `.gstack/sealed-allow.tsv` line for every manifest commit (gstack-evals wiki/board/2026-10-28-gsta-9-sealed-manifest-glob-gap.md). Their first draft also wrote `sealed/**`, which never matched their nested `tasks//sealed/` directories, and garrytan/gstack-evals#3 (dc54796) hand-listed `Sealed/`, `HELDOUT/` and other case variants. ### Added -- **`sealed.allow_paths`** (`lib/sealed-guard.ts`): globs that exempt publishable files from `sealed.path` and `sealed.transcript`, applied after the deny globs and before sha waivers. They are read from the destination base branch only, so a push cannot widen its own exceptions; a pushed copy is still validated and refuses when malformed. Text rules still read an exempt file, so a manifest that quotes a sealed answer still refuses. An entry with a wildcard file name (`**`, `sealed/*`, `**/*.json`) is refused. Each exempt path prints `exempt commit (sealed.allow_paths )` on every push. +- **`sealed.allow_paths`** (`lib/sealed-guard.ts`): globs that exempt publishable files from `sealed.path` and `sealed.transcript`, applied after the deny globs and before sha waivers. They are read from the destination base branch only, so a push cannot widen its own exceptions; a pushed copy is still validated and refuses when malformed. Text rules still read an exempt file, so a manifest that quotes a sealed answer still refuses. An entry whose file name contains `**` or is only wildcards before its extension (`**`, `sealed/*`, `**/*.json`) is refused. Each exempt path prints `exempt commit (sealed.allow_paths )` on every push. - **`sealed.case_insensitive: true`**: `paths` and `transcripts` match regardless of case, so `**/heldout/**` also refuses `HELDOUT/` and `HeldOut/`. The value is the base branch's OR the pushed one, because it only tightens. `allow_paths` never fold case. Separator and spelling variants such as `hold-out/` still need their own globs. ### Changed diff --git a/docs/pregate.md b/docs/pregate.md index 337cbe623..82d3d5eb7 100644 --- a/docs/pregate.md +++ b/docs/pregate.md @@ -805,8 +805,10 @@ gstack-pregate sealed [--range ] [--remote origin] [--base ] [--js `sealed.transcript`, applied after the deny globs and before waivers. They are read from the destination base branch only: an exception a push adds takes effect once it lands on the base branch, so a branch can never widen - its own. They never fold case, and an entry with a wildcard file name - (`**`, `sealed/*`, `**/*.json`, `sealed/**.json`) is refused: name the file. An exempt file is checked by the + its own. They never fold case. An entry whose file name contains `**`, or + is only wildcards before its extension (`**`, `sealed/*`, `**/*.json`, + `sealed/**.json`), is refused; a partial wildcard such as `MANIFEST*.json` + is accepted and matches every file it spells, so name the file. An exempt file is checked by the text rules only, so configure `answer_markers` when you exempt files next to sealed data. Each exempt path is listed on every push (`exempt commit (sealed.allow_paths )`) and counted as