process: infrastructure without a track label runs as show (#695 r1)

CODE-REVIEW-695-r1 Medium: PROCESS §5.1 says an infrastructure task (§1)
without a track label reads as track:show, but neither the pipeline guard
nor the task packet did that.

- _process.yml guard: with no track:* and no small/trivial label, the
  diff of the task branch against dev (compare API) with no class A file
  gives the show cycle limit 2. A truncated compare answer (300 files)
  proves nothing and keeps the limit 4.
- task-packet.mjs: an infrastructure packet names the track it runs on:
  «инфраструктурный · show» without a label, the owner's label otherwise.
- Mutants guard-infra-keeps-ask-limit and
  packet-infra-track-ignores-show-default.

Issue: #695
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 22:50:19 +03:00
parent 51854aea53
commit f6c76b7351
5 changed files with 81 additions and 5 deletions
+23
View File
@@ -13334,6 +13334,29 @@ const MUTANT_DEFINITIONS = [
replace: ' if True: # mutant: concurrent flushes are not serialised\n',
}],
},
// r1 #695: инфраструктура без трековой метки — трек show (§5.1).
{
id: 'guard-infra-keeps-ask-limit',
guard: 'node --test --test-name-pattern="r1 #695" test/review-doc-guard.test.mjs',
because: 'r1 #695: an infrastructure task without a track label reads as track:show (PROCESS §5.1); '
+ 'the guard must give it the show cycle limit 2, not the ask limit 4',
patches: [{
file: '.github/workflows/_process.yml',
find: ' limit=2\n echo "инфраструктурная задача без трековой метки',
replace: ' limit=4 # mutant: infra keeps the ask limit\n echo "инфраструктурная задача без трековой метки',
}],
},
{
id: 'packet-infra-track-ignores-show-default',
guard: 'node --test --test-name-pattern="r1 #695" test/task-packet.test.mjs',
because: 'r1 #695: the packet names the track an infrastructure task actually runs on — show '
+ 'without a label, the owner label otherwise',
patches: [{
file: 'scripts/task-packet.mjs',
find: " const infraTrack = hasTrackLabel(labels) ? trackFromLabels(labels) : 'show';",
replace: ' const infraTrack = trackFromLabels(labels); // mutant: unlabelled infra reads as ask',
}],
},
];
const mutationCardSource = readFileSync(join(repoRoot, 'src/houseplan-card.ts'), 'utf8');
+10 -2
View File
@@ -141,6 +141,10 @@ export function trackFromLabels(labels = []) {
return 'ask';
}
/** Есть ли у задачи трековая метка — новая или прежняя (§5.1). */
export const hasTrackLabel = (labels = []) => ['track:ship', 'track:show', 'track:ask', 'trivial', 'small']
.some((label) => labels.includes(label));
/**
* Признаки продуктового S-flow (#632). Инфраструктурная задача входит в поток
* сразу на S7 и никогда не несёт S1–S5, ТЗ и ревью ТЗ; поэтому любой из этих
@@ -177,9 +181,13 @@ export function buildPacket(inputs) {
// продуктового потока.
const infrastructure = branch?.infrastructure === true && productFlow.length === 0;
const infrastructureHint = branch == null && status == null && labels.includes('infra') && productFlow.length === 0;
// §5.1 (r1 #695): инфраструктурная задача без трековой метки идёт как
// `show`; явная метка владельца главнее. Маршрут при этом остаётся
// инфраструктурным — вход сразу на S7, без S1–S5.
const infraTrack = hasTrackLabel(labels) ? trackFromLabels(labels) : 'show';
const track = infrastructure
? 'инфраструктурный'
: infrastructureHint ? 'инфраструктурный (предварительно; подтвердить путями/diff)'
? `инфраструктурный · ${infraTrack}`
: infrastructureHint ? `инфраструктурный · ${infraTrack} (предварительно; подтвердить путями/diff)`
: trackFromLabels(labels);
const stage = status === 'S4-spec-review' || status === 'S3-spec' || status === 'S5-ready' ? 'spec' : 'code';
const verdict = lastVerdict(comments, reviewDocs, stage);