Skip to content

Commit 1986efc

Browse files
committed
chore(perf): replace blocked signoff with todo backlog flow
1 parent 10282dc commit 1986efc

5 files changed

Lines changed: 64 additions & 52 deletions

File tree

docs/diataxis/en/explanation/startup-node-update-acceleration-plan.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,4 +220,4 @@ npm run perf:startup:matrix -- --root tmp/startup-logs --single-platform-label w
220220
- Output: `tmp/startup-logs/report-startup-signoff.md`
221221
- Layered decision model:
222222
- Engineering signoff: based on Windows real logs + simulated multi-platform three-cohort gates.
223-
- Release signoff: marked as `BLOCKED` when real multi-device cohorts are missing (never falsely `PASS`).
223+
- Release signoff: marked as `TODO` when real multi-device cohorts are missing and tracked in future test backlog.

docs/diataxis/en/reference/interfaces-and-runtime.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,10 @@ This reference tracks canonical API/runtime contracts.
8282
- `npm run perf:startup:matrix:simulate -- --seed-root tmp/startup-logs --out-root tmp/startup-logs-simulated`
8383
- `npm run perf:startup:matrix -- --root tmp/startup-logs-simulated --out tmp/startup-logs-simulated/report-platform-matrix.md`
8484
- Note: `tmp/startup-logs-simulated` is synthetic data and must not be used for release-go performance decisions.
85-
- One-click no-hardware signoff (engineering gate + release gate blocking status):
85+
- One-click no-hardware signoff (engineering gate + release gate TODO tracking):
8686
- `npm run perf:startup:signoff:nohw`
8787
- This command automatically runs: Windows real-log gates + simulated multi-platform three-cohort gates, then writes a layered signoff report.
88-
- If real multi-device cohort data is missing, release signoff is marked as `BLOCKED` (not falsely `PASS`).
88+
- If real multi-device cohort data is missing, release signoff is marked as `TODO` and moved to future test backlog.
8989
- Three-cohort automatic regression and rollout gate (Phase 4):
9090
- `npm run perf:startup:cohorts:verify -- --root <cohorts-root> --cohorts small,medium,large --out <report-path> --strict`
9191
- Directory contract: `<cohorts-root>/<cohort>/<platform>/baseline|pilot`

docs/diataxis/zh/explanation/startup-node-update-acceleration-plan.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,4 +220,4 @@ npm run perf:startup:matrix -- --root tmp/startup-logs --single-platform-label w
220220
- 产物:`tmp/startup-logs/report-startup-signoff.md`
221221
- 分层结论:
222222
- 工程签收:基于 Windows 真实日志 + 模拟多端三规模门禁。
223-
- 发布签收:若缺少真实多端 cohort,状态为 `BLOCKED`(不会误判为 `PASS`
223+
- 发布签收:若缺少真实多端 cohort,状态为 `TODO`,并写入未来待办待测事项

docs/diataxis/zh/reference/interfaces-and-runtime.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,10 @@
8282
- `npm run perf:startup:matrix:simulate -- --seed-root tmp/startup-logs --out-root tmp/startup-logs-simulated`
8383
- `npm run perf:startup:matrix -- --root tmp/startup-logs-simulated --out tmp/startup-logs-simulated/report-platform-matrix.md`
8484
- 注意:`tmp/startup-logs-simulated` 为模拟数据,禁止用于 release-go 性能结论,仅用于脚本/门禁流程演练。
85-
- 无硬件一键签收(工程签收 + 发布签收阻塞提示):
85+
- 无硬件一键签收(工程签收 + 发布签收待办提示):
8686
- `npm run perf:startup:signoff:nohw`
8787
- 该命令会自动执行:Windows 真实日志门禁 + 模拟多端三规模门禁,并输出分层签收报告。
88-
- 若缺少真实多端 cohort 数据,发布签收会标记为 `BLOCKED`(而非误判为 `PASS`
88+
- 若缺少真实多端 cohort 数据,发布签收会标记为 `TODO` 并进入未来待办测试清单
8989
- 三规模自动回归与灰度门禁(Phase 4):
9090
- `npm run perf:startup:cohorts:verify -- --root <cohorts-root> --cohorts small,medium,large --out <report-path> --strict`
9191
- 目录约定:`<cohorts-root>/<cohort>/<platform>/baseline|pilot`

scripts/verify-startup-release-readiness.js

Lines changed: 58 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ function parseArgs(argv) {
137137
return args;
138138
}
139139

140-
function runNodeScript(scriptPath, scriptArgs, options = {}) {
140+
function runNodeScript(scriptPath, scriptArgs) {
141141
const result = spawnSync(process.execPath, [scriptPath, ...scriptArgs], {
142142
cwd: process.cwd(),
143143
encoding: 'utf8'
@@ -155,7 +155,7 @@ function runNodeScript(scriptPath, scriptArgs, options = {}) {
155155
status: result.status,
156156
error: result.error ? result.error.message : '',
157157
command: `${path.basename(scriptPath)} ${scriptArgs.join(' ')}`.trim(),
158-
note: options.note || ''
158+
pendingTodo: false
159159
};
160160
}
161161

@@ -181,70 +181,85 @@ function hasRealCohortData(rootDir) {
181181
if (!fs.existsSync(rootDir)) {
182182
return false;
183183
}
184-
const cohortNames = ['small', 'medium', 'large'];
185-
for (const cohort of cohortNames) {
186-
const cohortRoot = path.join(rootDir, cohort);
187-
if (!fs.existsSync(cohortRoot)) {
184+
for (const cohort of ['small', 'medium', 'large']) {
185+
if (!fs.existsSync(path.join(rootDir, cohort))) {
188186
return false;
189187
}
190188
}
191189
return true;
192190
}
193191

194-
function renderStatus(ok, blocked = false) {
195-
if (blocked) {
196-
return 'BLOCKED';
192+
function renderStatus(ok, pendingTodo = false) {
193+
if (pendingTodo) {
194+
return 'TODO';
197195
}
198196
return ok ? 'PASS' : 'FAIL';
199197
}
200198

199+
function buildFutureTodoBacklog(realCohortsRoot) {
200+
return [
201+
`Collect real macOS cohorts under ${path.join(realCohortsRoot, 'small|medium|large', 'macos', 'baseline|pilot')}.`,
202+
`Collect real Android cohorts under ${path.join(realCohortsRoot, 'small|medium|large', 'android', 'baseline|pilot')}.`,
203+
`Collect real iOS cohorts under ${path.join(realCohortsRoot, 'small|medium|large', 'ios', 'baseline|pilot')}.`,
204+
'Ensure each platform has >=10 sessions for baseline and pilot in each cohort.',
205+
'Run perf:startup:cohorts:verify on real datasets and archive report-cohorts-real.md as release evidence.'
206+
];
207+
}
208+
201209
function buildReport(summary, args) {
202210
const lines = [
203211
'# Startup Plan B Signoff Report',
204212
'',
205213
`Generated at: ${summary.generatedAt}`,
206214
'',
207-
'## 中文',
215+
'## Chinese',
208216
'',
209-
'### 分层签收结论',
210-
`- 工程签收(无多端硬件): ${renderStatus(summary.engineeringGatePass)}`,
211-
`- 发布签收(真实多端硬件): ${renderStatus(summary.releaseGatePass, summary.releaseGateBlocked)}`,
217+
'### Layered Signoff',
218+
`- Engineering signoff (no multi-device hardware): ${renderStatus(summary.engineeringGatePass)}`,
219+
`- Release signoff (real multi-device hardware): ${renderStatus(summary.releaseGatePass, summary.releaseGatePendingTodo)}`,
212220
'',
213-
'### 执行明细',
221+
'### Execution Detail',
214222
'| Step | Status | Command |',
215223
'|---|---|---|'
216224
];
217225

218226
for (const step of summary.steps) {
219-
lines.push(`| ${step.name} | ${renderStatus(step.ok, step.blocked)} | \`${step.command}\` |`);
227+
lines.push(`| ${step.name} | ${renderStatus(step.ok, step.pendingTodo)} | \`${step.command}\` |`);
220228
}
221229

222230
lines.push('');
223-
lines.push('### 说明');
224-
lines.push(`- Windows 根目录: \`${args.windowsRoot}\``);
225-
lines.push(`- 模拟多端目录: \`${args.simulatedRoot}\``);
226-
lines.push(`- 模拟三规模目录: \`${args.simulatedCohortsRoot}\``);
227-
lines.push(`- 真实三规模目录: \`${args.realCohortsRoot}\``);
228-
lines.push(`- 门禁阈值: TTI P50 >= ${args.minTtiImprove}%, TFS P50 >= ${args.minTfsImprove}%`);
229-
lines.push(`- 样本门槛: 每平台 baseline/pilot >= ${args.minSessionsPerPlatform}`);
230-
lines.push('- 说明: 无多端硬件时,发布签收会标记为 BLOCKED,不会误判为 PASS。');
231+
lines.push('### Notes');
232+
lines.push(`- Windows root: \`${args.windowsRoot}\``);
233+
lines.push(`- Simulated platform root: \`${args.simulatedRoot}\``);
234+
lines.push(`- Simulated cohorts root: \`${args.simulatedCohortsRoot}\``);
235+
lines.push(`- Real cohorts root: \`${args.realCohortsRoot}\``);
236+
lines.push(`- Gate thresholds: TTI P50 >= ${args.minTtiImprove}%, TFS P50 >= ${args.minTfsImprove}%`);
237+
lines.push(`- Session floor: baseline/pilot >= ${args.minSessionsPerPlatform}`);
238+
lines.push('- Without real multi-device data, release signoff is TODO and tracked in backlog.');
239+
lines.push('');
240+
lines.push('### Future TODO Backlog');
241+
for (const item of summary.futureTodos) {
242+
lines.push(`- [ ] ${item}`);
243+
}
231244

232245
lines.push('');
233246
lines.push('## English');
234247
lines.push('');
235-
lines.push('### Signoff Summary');
236-
lines.push(`- Engineering gate (no multi-device hardware): ${renderStatus(summary.engineeringGatePass)}`);
237-
lines.push(`- Release gate (real multi-device hardware): ${renderStatus(summary.releaseGatePass, summary.releaseGateBlocked)}`);
248+
lines.push('### Layered Signoff');
249+
lines.push(`- Engineering signoff (no multi-device hardware): ${renderStatus(summary.engineeringGatePass)}`);
250+
lines.push(`- Release signoff (real multi-device hardware): ${renderStatus(summary.releaseGatePass, summary.releaseGatePendingTodo)}`);
238251
lines.push('');
239-
lines.push('### Details');
252+
lines.push('### Execution Detail');
240253
lines.push('| Step | Status | Command |');
241254
lines.push('|---|---|---|');
242255
for (const step of summary.steps) {
243-
lines.push(`| ${step.name} | ${renderStatus(step.ok, step.blocked)} | \`${step.command}\` |`);
256+
lines.push(`| ${step.name} | ${renderStatus(step.ok, step.pendingTodo)} | \`${step.command}\` |`);
244257
}
245258
lines.push('');
246-
lines.push('### Notes');
247-
lines.push('- Release gate remains BLOCKED without real macOS/Android/iOS cohort datasets.');
259+
lines.push('### Future TODO Backlog');
260+
for (const item of summary.futureTodos) {
261+
lines.push(`- [ ] ${item}`);
262+
}
248263

249264
return lines.join('\n');
250265
}
@@ -265,7 +280,6 @@ function main() {
265280

266281
const steps = [];
267282

268-
// Step 1: Windows baseline/pilot compare gate
269283
const windowsCompareOut = path.join(windowsRoot, 'report-phase1-windows-compare.md');
270284
const stepWindowsCompare = runNodeScript(compareScript, [
271285
'--baseline', path.join(windowsRoot, 'baseline'),
@@ -274,9 +288,8 @@ function main() {
274288
'--min-tti-improve', String(args.minTtiImprove),
275289
'--min-tfs-improve', String(args.minTfsImprove)
276290
]);
277-
steps.push({ name: 'windows-compare', ...stepWindowsCompare, blocked: false });
291+
steps.push({ name: 'windows-compare', ...stepWindowsCompare });
278292

279-
// Step 2: Windows matrix strict gate
280293
const windowsMatrixOut = path.join(windowsRoot, 'report-phase1-windows-matrix.md');
281294
const stepWindowsMatrix = runNodeScript(matrixScript, [
282295
'--root', windowsRoot,
@@ -286,24 +299,22 @@ function main() {
286299
'--min-tfs-improve', String(args.minTfsImprove),
287300
'--strict'
288301
]);
289-
steps.push({ name: 'windows-matrix', ...stepWindowsMatrix, blocked: false });
302+
steps.push({ name: 'windows-matrix', ...stepWindowsMatrix });
290303

291-
// Step 3: Simulated multi-platform matrix preparation
292304
const stepSimulate = runNodeScript(simulateScript, [
293305
'--seed-root', windowsRoot,
294306
'--out-root', simulatedRoot,
295307
'--sessions-per-platform', String(args.sessionsPerPlatform),
296308
'--seed', String(args.seed)
297309
]);
298-
steps.push({ name: 'simulate-platform-logs', ...stepSimulate, blocked: false });
310+
steps.push({ name: 'simulate-platform-logs', ...stepSimulate });
299311

300-
// Step 4: Simulated cohorts gate
301312
let stepSimulatedCohorts = {
302313
ok: false,
303314
status: 1,
304315
error: '',
305316
command: `${path.basename(cohortsScript)} --root ${simulatedCohortsRoot}`,
306-
blocked: false
317+
pendingTodo: false
307318
};
308319
if (stepSimulate.ok) {
309320
ensureDir(simulatedCohortsRoot);
@@ -324,15 +335,14 @@ function main() {
324335
} else {
325336
stepSimulatedCohorts.error = 'skip due to simulation generation failure';
326337
}
327-
steps.push({ name: 'simulated-cohorts-gate', ...stepSimulatedCohorts, blocked: false });
338+
steps.push({ name: 'simulated-cohorts-gate', ...stepSimulatedCohorts });
328339

329-
// Step 5: Real cohorts gate (blocked when no hardware datasets)
330340
let stepRealCohorts = {
331341
ok: false,
332342
status: null,
333343
error: '',
334344
command: `${path.basename(cohortsScript)} --root ${realCohortsRoot}`,
335-
blocked: false
345+
pendingTodo: false
336346
};
337347
const realCohortsAvailable = hasRealCohortData(realCohortsRoot);
338348
if (realCohortsAvailable) {
@@ -351,21 +361,23 @@ function main() {
351361
status: null,
352362
error: 'no real multi-device cohort dataset found',
353363
command: `${path.basename(cohortsScript)} --root ${realCohortsRoot}`,
354-
blocked: true
364+
pendingTodo: true
355365
};
356366
}
357367
steps.push({ name: 'real-cohorts-gate', ...stepRealCohorts });
358368

359369
const engineeringGatePass = stepWindowsCompare.ok && stepWindowsMatrix.ok && stepSimulatedCohorts.ok;
360-
const releaseGateBlocked = stepRealCohorts.blocked === true;
361-
const releaseGatePass = !releaseGateBlocked && stepRealCohorts.ok;
370+
const releaseGatePendingTodo = stepRealCohorts.pendingTodo === true;
371+
const releaseGatePass = !releaseGatePendingTodo && stepRealCohorts.ok;
372+
const futureTodos = releaseGatePendingTodo ? buildFutureTodoBacklog(args.realCohortsRoot) : [];
362373

363374
const summary = {
364375
generatedAt: new Date().toISOString(),
365376
steps,
366377
engineeringGatePass,
367378
releaseGatePass,
368-
releaseGateBlocked
379+
releaseGatePendingTodo,
380+
futureTodos
369381
};
370382

371383
const report = buildReport(summary, args);
@@ -374,7 +386,7 @@ function main() {
374386
console.log(`[startup-signoff] Report written: ${outPath}`);
375387
console.log(
376388
`[startup-signoff] engineeringGate=${renderStatus(engineeringGatePass)}, ` +
377-
`releaseGate=${renderStatus(releaseGatePass, releaseGateBlocked)}`
389+
`releaseGate=${renderStatus(releaseGatePass, releaseGatePendingTodo)}`
378390
);
379391

380392
if (args.strictEngineering && !engineeringGatePass) {

0 commit comments

Comments
 (0)