mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
perf: make review scope and ceremony fit the size of the task
The owner's report: the process works but every stage takes a long time even on simple bugs. Two causes, and neither was the one that first comes to mind. The reviewer ran everything regardless. On #89 it installed Chromium, ran all 127 smoke files and a full golden capture — right for a task rated 10/10 for complexity, absurd for a bug about a room divider. Full suites are the pre-beta gate; the review now runs typecheck, unit and build always, and smokes, golden, pytest or performance only where the diff and the AC call for them. The price of narrowing it is honesty: the reviewer must list which gates it ran, which it did not, and why, so a skipped gate is a visible decision rather than a silent one. The reviewer also built its own environment out of model turns, with no npm cache and no browser cache, paid for from the same forty-five minutes. The workflow now installs dependencies and Chromium as ordinary cached steps, after switching to the task branch so the lockfile is the branch's own. Second, ceremony did not scale down. The light track makes a spec cheap; the new trivial track does without one — S2-analysis straight to S5-ready, no spec review, AC in the issue body. It is deliberately hard to qualify for: a bug on one surface, no new UX contract, no migration, no i18n, no perf or touch effect, three checkable AC at most, and expected behaviour already on record. Nothing left to decide is the criterion that holds the whole thing up, and it cannot be met by feeling sure. Code review is never skipped on either track. It is what stands in for testing here, so it is the one stage speed may not buy. Issue: #127 Issue: #128 User-Visible: no
This commit is contained in:
@@ -41,6 +41,15 @@ of a status and `rejected` on a closed issue. Exactly one `S*` label per open
|
||||
issue. [GitHub Projects (v2)](https://github.com/users/Matysh/projects/1) is a
|
||||
human-facing view synchronised from the labels, not the source of truth.
|
||||
|
||||
Two shortcuts exist for small work. `small` — the light track: the spec lives in
|
||||
the issue body and its review is a comment. `trivial` — the short track: no spec
|
||||
stage at all, `S2-analysis` straight to `S5-ready`, with the AC written into the
|
||||
issue body first. `trivial` requires a bug confined to one surface with no new UX
|
||||
contract, no migration, no i18n, no perf or touch impact, at most three checkable
|
||||
AC, **and expected behaviour already on record** — nothing left to decide. Code
|
||||
review is never skipped on either track; it is what stands in for testing.
|
||||
`PROCESS.md` §5 and §5.1 hold the criteria.
|
||||
|
||||
An issue filed by an outsider is worked exactly like one of the owner's own, once
|
||||
the owner has decided to take it. The check sits **at the entrance**, not on every
|
||||
step: while an issue carries no status label it is outside the process and the
|
||||
|
||||
@@ -67,6 +67,12 @@ const CLASS_C = [
|
||||
|
||||
const CHANGELOGS = ['docs/CHANGELOG.md', 'docs/CHANGELOG.ru.md'];
|
||||
|
||||
// Метки, при которых файла ТЗ в docs/specs/ быть не должно: на лёгком треке ТЗ
|
||||
// живёт в теле issue (§5), на коротком — там же, и ревью ТЗ вообще не проводится
|
||||
// (§5.1, issue #128). Офлайн эти случаи неотличимы от «ТЗ не написано», поэтому
|
||||
// проверка 3 краснеет только когда метки прочитаны.
|
||||
export const NO_SPEC_FILE = ['small', 'trivial'];
|
||||
|
||||
export const ALLOWED_STATUS = ['S5-ready', 'S6-in-progress', 'S7-code-review', 'S8-merged'];
|
||||
export const STRICT_STATUS = ['S5-ready', 'S6-in-progress', 'S7-code-review'];
|
||||
|
||||
@@ -235,12 +241,12 @@ export function checkSpecs(commits, specFiles, labelsOf = null) {
|
||||
if (labels === null) {
|
||||
out.push({
|
||||
level: 'warn', rule: 3, sha: c.short,
|
||||
msg: `класс A по ${t}, но ТЗ docs/specs/${nn}-*.md не найдено — допустимо только при метке small`,
|
||||
msg: `класс A по ${t}, но ТЗ docs/specs/${nn}-*.md не найдено — допустимо при метке small или trivial`,
|
||||
});
|
||||
} else if (!labels.includes('small')) {
|
||||
} else if (!labels.some((l) => NO_SPEC_FILE.includes(l))) {
|
||||
out.push({
|
||||
level: 'fail', rule: 3, sha: c.short,
|
||||
msg: `класс A по ${t}: ТЗ docs/specs/${nn}-*.md нет, и метки small на issue нет — код без ТЗ`,
|
||||
msg: `класс A по ${t}: ТЗ docs/specs/${nn}-*.md нет, и метки ${NO_SPEC_FILE.join(' / ')} на issue нет — код без ТЗ`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,8 +134,9 @@ test('a class A commit without a spec warns offline and fails with labels', () =
|
||||
assert.equal(offline[0].level, 'warn');
|
||||
assert.equal(offline[0].rule, 3);
|
||||
|
||||
// С метками: small оправдывает отсутствие файла, его отсутствие — нет.
|
||||
// С метками: small и trivial оправдывают отсутствие файла, их отсутствие — нет.
|
||||
assert.deepEqual(checkSpecs([c], [], () => ['small', 'S5-ready']), []);
|
||||
assert.deepEqual(checkSpecs([c], [], () => ['trivial', 'S5-ready']), []);
|
||||
const strict = checkSpecs([c], [], () => ['S5-ready']);
|
||||
assert.equal(strict.length, 1);
|
||||
assert.equal(strict[0].level, 'fail');
|
||||
|
||||
Reference in New Issue
Block a user