process: derived artifacts are accepted on dev once per beta (#697)

The screenshot fingerprint and golden baselines stop being a tax on every
task branch:

- Task branches no longer commit docs/images/** or golden baselines. On a
  branch the screenshot freshness stays a preflight warning; the review
  prompt, REVIEWER.md and AUTHOR.md drop check-docs as a per-task gate.
- beta-derived.yml refreshes them on dev in one bot commit before the beta
  candidate: canonical docs capture + docs:accept --reviewed, golden from
  the golden-images artifact of a completed Validate on dev +
  golden:accept --reviewed. A changed frame or scene is accepted only when
  named in the inputs; undeclared differences refuse. Baseline commits carry
  Release: and Baseline-Reviewed:; the subject is not a candidate subject.
- classify-changes: the Release: trailer on an issue/* branch no longer
  switches on the heavy set. ci:full / ci:golden do: process-track emits
  full=true, the review gate dispatches Validate with full=true and does not
  accept a light proof.

Canon: PROCESS.md §3 п.13, §5.1, §8, §11.4; CONTRIBUTING.md.

Issue: #697
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
This commit is contained in:
Claude
2026-09-28 23:38:50 +03:00
parent c716bb0f63
commit 2a62ad5b95
15 changed files with 490 additions and 63 deletions
+10 -6
View File
@@ -5,9 +5,11 @@
* node scripts/process-track.mjs resolve --labels="a,b" --base=<ref> --head=<ref>
* node scripts/process-track.mjs ship-limits --base=<ref> --head=<ref>
*
* `resolve` печатает `track=ship|show|ask` и `mutants=true|false` — то, что
* конвейер ревью читает, решая, сколько стоит заход: мутанты по диффу нужны
* только `ask` и метке `ci:mutants`. Инфраструктурная задача без трековой
* `resolve` печатает `track=ship|show|ask`, `mutants=true|false` и
* `full=true|false` — то, что конвейер ревью читает, решая, сколько стоит
* заход: мутанты по диффу нужны только `ask` и метке `ci:mutants`; полный
* набор (смоки, golden, perf) на ветке задачи — только меткам `ci:full` и
* `ci:golden` (#697). Инфраструктурная задача без трековой
* метки — `show` (§5.1); признак инфраструктуры механический, как в §1: в
* диффе ни одного файла класса A.
*
@@ -46,12 +48,14 @@ export const hasTrackLabel = (labels = []) => ['track:ship', 'track:show', 'trac
* Трек, по которому конвейер оценивает заход. Явная метка решает всё; без неё
* инфраструктурная задача (ни одного файла класса A в диффе) — `show`, прочие —
* `ask`. Мутанты по диффу — только на `ask` или по метке `ci:mutants`.
* Полный набор — по меткам `ci:full` и `ci:golden` на любом треке (#697).
*/
export function resolveTrack({ labels = [], files = [] } = {}) {
const infrastructure = files.length > 0 && files.every((file) => classify(file) !== 'A');
const track = hasTrackLabel(labels) ? trackFromLabels(labels) : (infrastructure ? 'show' : 'ask');
const mutants = track === 'ask' || labels.includes('ci:mutants');
return { track, mutants, infrastructure };
const full = labels.includes('ci:full') || labels.includes('ci:golden');
return { track, mutants, full, infrastructure };
}
const I18N = [/^src\/i18n\//, /^custom_components\/[^/]+\/translations\//];
@@ -120,8 +124,8 @@ if (isMainModule(import.meta.url)) {
if (command === 'resolve') {
const labels = value('labels').split(',').map((s) => s.trim()).filter(Boolean);
const files = range ? git(['diff', '--name-only', range]).split('\n').filter(Boolean) : [];
const { track, mutants } = resolveTrack({ labels, files });
emit([`track=${track}`, `mutants=${mutants}`]);
const { track, mutants, full } = resolveTrack({ labels, files });
emit([`track=${track}`, `mutants=${mutants}`, `full=${full}`]);
} else if (command === 'ship-limits') {
if (!range) throw new Error('--base is required');
const violations = shipLimitViolations({