Skip to content

Commit 9bb6877

Browse files
SisyphusZhengDevBot
andauthored
fix(release): self-consistent prepare plan + v0.44.0-beta.2 dev-state repair (#1288) (#1316)
* fix(release): prepare regenerates derived truth and release-state anchors (#1288) The v0.44.0-beta.2 bump commit passed the fast prepare gates but failed dev CI (run 33885147030) and promotion PR #1315 (run 33885139920) on every derived-truth gate the prepare plan did not re-run: content-graph:check (bump rewrites graph sources), release:truth:check (release-state planning anchors), docs:check-version-anchors (VERSION_PLAN STATUS-form head pair) and www:check-truth (zh roadmap CURRENT entry). The prepare/release plan now advances the release-state planning anchors (activeTarget/nextPlannedTrain; published fields stay finalize-owned), regenerates the content graph, and stages both artifacts in the bump commit. buildVersionAnchorReplacements covers the VERSION_PLAN repository/registry head pair and the next-public-prerelease anchors, and bumpProjectConstantsText advances NEXT_PUBLIC_PRERELEASE with the prerelease successor (the #813 binding #1283 fixed by hand). The roadmap version anchor now rewrites both CURRENT-stamped entries (en + zh). * fix(release): v0.44.0-beta.2 post-prepare consistency repair (#1288) Follow-up to the 10744cc bump commit, which failed dev CI (run 33885147030) and promotion PR #1315 (run 33885139920) on the derived-truth gates the prepare plan did not re-run. Applies exactly the steps the fixed prepare plan now performs, plus the human release prose the gates deliberately reserve for a human: - regenerate www/app/data/_generated-content-graph.json (bump rewrote graph sources version.ts/roadmap.tsx) - release-state.json planning anchors: activeTarget v0.44.0-beta.2, nextPlannedTrain v0.44.0-beta.3 (published fields stay on the beta.1 prepare-window lag; finalize owns them) - VERSION_PLAN.md STATUS-form head pair (Repository package line / npm registry line) advanced to v0.44.0-beta.2 with the prerelease dist-tag annotation release:truth:check requires - NEXT_PUBLIC_PRERELEASE and the next-public-prerelease doc anchors advance to v0.44.0-beta.3 (the #813 in-flight binding #1283 fixed by hand for Beta.1) - www roadmap CURRENT entries (en + zh): zh version advanced, and the Beta.2 theme/copy written (productization + governance offload, ADR-0151) — the superseded-theme gate is human by design - README/README.zh/VERSION_PLAN/STATUS/ROADMAP head-zone prose updated to the Beta.2 line Gates now green locally: content-graph:check, release:truth:check, docs:check-version-anchors, www:check-truth, www:check-current-truth, docs:truth, release:state-machine:check, release:evidence:check, api-reference:check, content:examples-check, text-integrity:check, build (incl. www:check-artifact-truth + www:check-links). --------- Co-authored-by: DevBot <devbot@openelement.dev>
1 parent 10744cc commit 9bb6877

12 files changed

Lines changed: 303 additions & 45 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ authoring syntax; Declarative Shadow DOM is the default server representation;
88
and interactive regions activate selectively.
99

1010
The published stable line remains the 0.43 series on npm `latest`.
11-
`v0.44.0-beta.1` is the first public v0.44 prerelease — Beta.1, Framework
12-
Qualification + Governance Freeze (ADR-0151) — published under dist-tag
13-
`beta`. The next stage is Beta.2 (`v0.44.0-beta.2`).
11+
`v0.44.0-beta.2` is the current public v0.44 prerelease — Beta.2,
12+
Productization + Governance Offload (ADR-0151) — published under dist-tag
13+
`beta`. The next stage is Beta.3 (`v0.44.0-beta.3`).
1414
The `1.0.0` target remains unscheduled and requires separate evidence and approval.
1515

1616
```text

README.zh.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
长期保存的应用组件模型;JSX 与 Basic Element 是作者层;Declarative Shadow
88
DOM 是默认服务端表示;交互区域按需升级。
99

10-
源码包行为 `0.44.0-beta.2``v0.44.0-beta.2`)——首个公开 v0.44 预发布线
11-
(Beta.1:框架资格验证 + 治理冻结,ADR-0151)。
10+
源码包行为 `0.44.0-beta.2``v0.44.0-beta.2`)——当前公开 v0.44 预发布线
11+
(Beta.2:产品化 + 治理减负,ADR-0151)。
1212
npm registry 行为 `v0.44.0-beta.2`——预发布版本(dist-tag `beta`);npm `latest` 仍为
1313
已发布的稳定 0.43 线。
1414

docs/current/VERSION_PLAN.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,25 @@
33
OpenElement = Web Components-native fullstack application framework.
44

55
The published stable line remains the 0.43 series on npm `latest`.
6-
`v0.44.0-beta.1` is published as the first public v0.44 prerelease (Beta.1
7-
Framework Qualification + Governance Freeze) under dist-tag `beta`. The next
8-
stage is Beta.2 (`v0.44.0-beta.2`) per ADR-0151.
6+
`v0.44.0-beta.2` is the current public v0.44 prerelease (Beta.2
7+
Productization + Governance Offload) under dist-tag `beta`, succeeding the
8+
published Beta.1. The next stage is Beta.3 (`v0.44.0-beta.3`) per ADR-0151.
99

1010
ADR-0147 defines the Alpha workspace train, which is complete through Alpha.9.
1111
ADR-0151 retopologizes the release train and supersedes the ADR-0149 five-Beta
1212
mapping; the remainder of ADR-0149 and ADR-0150 that is not about Beta topology
1313
is unaffected. ADR-0146 remains the release-role authority and activates at
1414
Beta.1.
1515

16-
- Repository package line: `v0.44.0-beta.1`
17-
- npm registry line: `v0.44.0-beta.1` (prerelease, dist-tag `beta`; npm `latest` remains the stable 0.43 line)
16+
- Repository package line: `v0.44.0-beta.2`
17+
- npm registry line: `v0.44.0-beta.2` (prerelease, dist-tag `beta`; npm `latest` remains the stable 0.43 line)
1818
- Current source package line: `v0.44.0-beta.2`
1919
- Current npm registry line: `v0.44.0-beta.2`
2020
- Latest landed train: `v0.44.0-beta.2`
2121
- Active internal target: none — internal Alpha checkpoints closed at Alpha.10 (verifier PASS, #1150); the active line is the public Beta train (ADR-0151)
2222
- Active release target: `v0.44.0-beta.2`
23-
- Next planned public train: `v0.44.0-beta.2`
24-
- Next public prerelease: `v0.44.0-beta.2`
23+
- Next planned public train: `v0.44.0-beta.3`
24+
- Next public prerelease: `v0.44.0-beta.3`
2525

2626
The coherent five-package distribution contract follows
2727
[PACKAGE_SURFACE.md](./PACKAGE_SURFACE.md) and ADR-0114. The supported server

docs/release/release-state.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"sourceVersion": "0.44.0-beta.1",
44
"publishedVersion": "0.44.0-beta.1",
55
"latestLandedTrain": "v0.44.0-beta.1",
6-
"activeTarget": "v0.44.0-beta.1",
7-
"nextPlannedTrain": "v0.44.0-beta.2",
6+
"activeTarget": "v0.44.0-beta.2",
7+
"nextPlannedTrain": "v0.44.0-beta.3",
88
"maturity": "beta"
99
}

docs/roadmap/ROADMAP.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ The npm `latest` dist-tag remains on the published stable 0.43 line.
88
Active execution target: `v0.44.0-beta.2`.
99
Latest landed train: `v0.44.0-beta.2`.
1010
Next planned train: `v0.44.0-beta.3`.
11-
Next public prerelease: `v0.44.0-beta.2`.
11+
Next public prerelease: `v0.44.0-beta.3`.
1212
Long-term stable product target: `1.0.0` (unscheduled).
1313

1414
Execution follows
1515
[PROJECT_WORKFLOW.md](../governance/PROJECT_WORKFLOW.md).
1616

17-
## Current: Beta.1 framework qualification + governance freeze
17+
## Current: Beta.2 productization + governance offload
1818

1919
The internal Alpha workspace train is complete through Alpha.10. Alpha.0 supplied
2020
the accepted compiler proof, exact-SHA CI foundation and minimum history safety;
@@ -27,8 +27,9 @@ Alpha identifiers were internal work identifiers, not package releases, and the
2727
three-role loop was off for all Alpha work.
2828

2929
Beta.1 (`v0.44.0-beta.1`) is published as the first public v0.44 prerelease
30-
under dist-tag `beta`; npm `latest` stays on the stable 0.43 line. The next
31-
stage is Beta.2 (`v0.44.0-beta.2`).
30+
under dist-tag `beta`; npm `latest` stays on the stable 0.43 line. Beta.2
31+
(`v0.44.0-beta.2`) is the active public prerelease line; the next stage is
32+
Beta.3 (`v0.44.0-beta.3`).
3233

3334
## Release train
3435

docs/status/STATUS.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ Updated: 2026-09-02
77
- Latest landed train: `v0.44.0-beta.2`
88
- Active release target: `v0.44.0-beta.2`
99
- Next planned train: `v0.44.0-beta.3`
10-
- Next public prerelease: `v0.44.0-beta.2`
10+
- Next public prerelease: `v0.44.0-beta.3`
1111
- Published stable package line: `v0.43.3` on npm `latest`
1212
- Current development mode: public Beta train — Beta.1 published as a
13-
prerelease under dist-tag `beta`; next stage Beta.2 (ADR-0151)
13+
prerelease under dist-tag `beta`; Beta.2 in flight, next stage Beta.3
14+
(ADR-0151)
1415
- Minimum branch rules: active on `dev` and `main` through ruleset `21775463`
1516
- Deferred hardening: #1192 Beta.3 with #1156 #1187 #1188 #1189
1617
- Long-term `1.0.0` target: unscheduled

tools/autoflow/__tests__/release.test.ts

Lines changed: 149 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
writeReleaseNote,
3333
} from '../release.ts';
3434
import {
35+
advancePrepareReleaseStateText,
3536
advancePublishedReleaseStateText,
3637
buildVersionAnchorReplacements,
3738
bumpProjectConstantsText,
@@ -42,6 +43,7 @@ import {
4243
ACTIVE_EXECUTION_VERSION,
4344
LATEST_LANDED_TRAIN,
4445
NEXT_EXECUTION_VERSION,
46+
NEXT_PUBLIC_PRERELEASE,
4547
PACKAGE_VERSION,
4648
PACKAGE_VERSION_TAG,
4749
PREVIOUS_PACKAGE_VERSION,
@@ -60,7 +62,7 @@ Deno.test('buildVersionAnchorReplacements: covers all live versioned files', ()
6062
// lag-state previous-tag form (#754). The interop example anchor likewise
6163
// covers the source-line and lagging npm-published forms. Stable targets add
6264
// the equivalent two forms for PUBLISHED_STABLE_VERSION.
63-
assertEquals(reps.length, 40);
65+
assertEquals(reps.length, 43);
6466

6567
const seen = new Set<string>();
6668
for (const [path, from, to] of reps) {
@@ -102,7 +104,7 @@ Deno.test('buildVersionAnchorReplacements: from side derives from the loaded sou
102104
from.includes(PACKAGE_VERSION) || from.includes(PACKAGE_VERSION_TAG) ||
103105
from.includes(PREVIOUS_PACKAGE_VERSION) || from.includes(PREVIOUS_PACKAGE_VERSION_TAG) ||
104106
from.includes(LATEST_LANDED_TRAIN) || from.includes(ACTIVE_EXECUTION_VERSION) ||
105-
from.includes(NEXT_EXECUTION_VERSION),
107+
from.includes(NEXT_EXECUTION_VERSION) || from.includes(NEXT_PUBLIC_PRERELEASE),
106108
`from must derive from the canonical release-state constants: ${from}`,
107109
);
108110
}
@@ -234,11 +236,11 @@ Deno.test('buildVersionAnchorReplacements: prerelease bumps rewrite the registry
234236
);
235237

236238
// Stable targets never touch the dist-tag annotation: a stable cut IS the
237-
// latest line, and the rule surface stays at the exact 40 entries.
239+
// latest line, and the rule surface stays at the exact 43 entries.
238240
assertFalse(
239241
buildVersionAnchorReplacements('9.9.9').some(([, f]) => f.includes('dist-tag')),
240242
);
241-
assertEquals(buildVersionAnchorReplacements('9.9.9').length, 40);
243+
assertEquals(buildVersionAnchorReplacements('9.9.9').length, 43);
242244
});
243245

244246
Deno.test('buildVersionAnchorReplacements: every target carries the previous or current line', () => {
@@ -278,6 +280,7 @@ const CONSTANTS_FIXTURE = [
278280
"export const LATEST_LANDED_TRAIN = 'v0.41.0-alpha.17';",
279281
"export const ACTIVE_EXECUTION_VERSION = 'v0.41.0-alpha.17';",
280282
"export const NEXT_EXECUTION_VERSION = 'v0.41.0-alpha.18';",
283+
"export const NEXT_PUBLIC_PRERELEASE = 'v0.41.0-alpha.18';",
281284
"export const PREVIOUS_PACKAGE_VERSION = '0.41.0-alpha.15';",
282285
'',
283286
].join('\n');
@@ -292,6 +295,10 @@ Deno.test('bumpProjectConstantsText: bump maintains previous line and active exe
292295
assert(updated.includes("ACTIVE_EXECUTION_VERSION = 'v0.41.0-alpha.17'"));
293296
assert(updated.includes("LATEST_LANDED_TRAIN = 'v0.41.0-alpha.17'"));
294297
assert(updated.includes("NEXT_EXECUTION_VERSION = 'v0.41.0-alpha.18'"));
298+
// The next public prerelease advances with the same prerelease successor;
299+
// left on the bumped line it trips the #813 in-flight binding as soon as
300+
// the publish evidence completes (#1283 fixed this by hand for Beta.1).
301+
assert(updated.includes("NEXT_PUBLIC_PRERELEASE = 'v0.41.0-alpha.18'"));
295302
});
296303

297304
Deno.test('bumpProjectConstantsText: stable bump sets the active target to the bump target', () => {
@@ -300,6 +307,9 @@ Deno.test('bumpProjectConstantsText: stable bump sets the active target to the b
300307
assert(fromPrevious.includes("PACKAGE_VERSION = '0.41.0'"));
301308
assert(fromPrevious.includes("PREVIOUS_PACKAGE_VERSION = '0.41.0-alpha.16'"));
302309
assert(fromPrevious.includes("ACTIVE_EXECUTION_VERSION = 'v0.41.0'"));
310+
// The train after a stable cut is a deliberate human decision; the bump
311+
// must not derive one.
312+
assert(fromPrevious.includes("NEXT_PUBLIC_PRERELEASE = 'v0.41.0-alpha.18'"));
303313
});
304314

305315
Deno.test('bumpProjectConstantsText: re-running a bump is a no-op and keeps the true previous line', () => {
@@ -334,6 +344,104 @@ Deno.test('advancePublishedReleaseStateText: finalize converges source and regis
334344
assertEquals(alpha.maturity, 'alpha');
335345
});
336346

347+
Deno.test('advancePrepareReleaseStateText: prepare advances the planning anchors only (#1288)', () => {
348+
const input = JSON.stringify({
349+
schemaVersion: 1,
350+
sourceVersion: '0.44.0-beta.1',
351+
publishedVersion: '0.44.0-beta.1',
352+
latestLandedTrain: 'v0.44.0-beta.1',
353+
activeTarget: 'v0.44.0-beta.1',
354+
nextPlannedTrain: 'v0.44.0-beta.2',
355+
maturity: 'beta',
356+
});
357+
const state = JSON.parse(advancePrepareReleaseStateText(input, '0.44.0-beta.2'));
358+
// check-release-truth pins the planning pair to ACTIVE/NEXT_EXECUTION_VERSION,
359+
// which the bump advances; prepare must move them with the bump.
360+
assertEquals(state.activeTarget, 'v0.44.0-beta.2');
361+
assertEquals(state.nextPlannedTrain, 'v0.44.0-beta.3');
362+
// The published-line fields stay finalize-owned
363+
// (advancePublishedReleaseStateText): prepare leaves the prepare-window lag.
364+
assertEquals(state.sourceVersion, '0.44.0-beta.1');
365+
assertEquals(state.publishedVersion, '0.44.0-beta.1');
366+
assertEquals(state.latestLandedTrain, 'v0.44.0-beta.1');
367+
assertEquals(state.maturity, 'beta');
368+
369+
// A stable target has no derivable successor train; nextPlannedTrain stays
370+
// human-owned (same rule as NEXT_EXECUTION_VERSION in bumpProjectConstantsText).
371+
const stable = JSON.parse(advancePrepareReleaseStateText(input, '0.44.0'));
372+
assertEquals(stable.activeTarget, 'v0.44.0');
373+
assertEquals(stable.nextPlannedTrain, 'v0.44.0-beta.2');
374+
});
375+
376+
Deno.test('buildVersionAnchorReplacements: VERSION_PLAN repository/registry head lines join the bump (#1288)', () => {
377+
// The v0.44.0-beta.2 prepare bumped the "Current *" pair but left the
378+
// STATUS-form pair ("Repository package line" / bare "npm registry line")
379+
// stale in VERSION_PLAN's head zone, failing docs:check-version-anchors and
380+
// the release:truth:check prerelease registry anchor (runs 33885139920 /
381+
// 33885147030).
382+
const version = '9.9.9-beta.2';
383+
const tag = `v${version}`;
384+
const reps = buildVersionAnchorReplacements(version);
385+
assert(
386+
reps.some(([p, f, t]) =>
387+
p === 'docs/current/VERSION_PLAN.md' &&
388+
f === `Repository package line: \`${PACKAGE_VERSION_TAG}\`` &&
389+
t === `Repository package line: \`${tag}\``
390+
),
391+
'missing VERSION_PLAN repository-line replacement',
392+
);
393+
for (const fromTag of [PACKAGE_VERSION_TAG, PREVIOUS_PACKAGE_VERSION_TAG]) {
394+
const from = `npm registry line: \`${fromTag}\``;
395+
const to = `npm registry line: \`${tag}\``;
396+
assert(
397+
reps.some(([p, f, t]) => p === 'docs/current/VERSION_PLAN.md' && f === from && t === to),
398+
`missing VERSION_PLAN registry replacement: ${from} -> ${to}`,
399+
);
400+
}
401+
// The generic registry rule must not eat the "Current npm registry line"
402+
// anchor first: the specific rule stays earlier in application order.
403+
const bareIndex = reps.findIndex(([p, f]) =>
404+
p === 'docs/current/VERSION_PLAN.md' && f === `npm registry line: \`${PACKAGE_VERSION_TAG}\``
405+
);
406+
const currentIndex = reps.findIndex(([p, f]) =>
407+
p === 'docs/current/VERSION_PLAN.md' &&
408+
f === `Current npm registry line: \`${PACKAGE_VERSION_TAG}\``
409+
);
410+
assert(bareIndex !== -1 && currentIndex !== -1 && currentIndex < bareIndex);
411+
});
412+
413+
Deno.test('buildVersionAnchorReplacements: prerelease bump advances the next-public-prerelease anchors (#1288)', () => {
414+
// #1283 advanced NEXT_PUBLIC_PRERELEASE by hand; left stale, the published
415+
// line is described as the next train and trips the #813 in-flight binding
416+
// once its publish evidence completes. The bump now advances it like
417+
// NEXT_EXECUTION_VERSION, and the doc anchors follow.
418+
const version = '9.9.9-beta.2';
419+
const nextTag = nextPrereleaseTag(version);
420+
const reps = buildVersionAnchorReplacements(version);
421+
const anchors: Array<[string, string]> = [
422+
['docs/current/VERSION_PLAN.md', 'Next planned public train: `'],
423+
['docs/current/VERSION_PLAN.md', 'Next public prerelease: `'],
424+
['docs/status/STATUS.md', 'Next public prerelease: `'],
425+
['docs/roadmap/ROADMAP.md', 'Next public prerelease: `'],
426+
];
427+
for (const [path, prefix] of anchors) {
428+
const from = `${prefix}${NEXT_PUBLIC_PRERELEASE}\``;
429+
const to = `${prefix}${nextTag}\``;
430+
assert(
431+
reps.some(([p, f, t]) => p === path && f === from && t === to),
432+
`missing next-public-prerelease replacement ${path}: ${from} -> ${to}`,
433+
);
434+
}
435+
// Stable cuts leave the human-owned next-prerelease anchors alone (same rule
436+
// as the next-train anchors: no derivable successor after a stable cut).
437+
assertFalse(
438+
buildVersionAnchorReplacements('9.9.9').some(([p, f]) =>
439+
(p === 'docs/current/VERSION_PLAN.md' && f.startsWith('Next planned public train:')) ||
440+
f.startsWith('Next public prerelease:')
441+
),
442+
);
443+
});
444+
337445
Deno.test('two-phase release: prepare never publishes, tags, or pushes main', () => {
338446
const steps = createPreparePlan('0.41.0-alpha.11', 'docs/current/VERSION_PLAN.md');
339447
const names = steps.map((step) => step.name);
@@ -360,6 +468,39 @@ Deno.test('R9: preparation runs the fast tier only, never the local full matrix'
360468
assertEquals(gates?.command, ['deno', 'task', 'autoflow:push']);
361469
});
362470

471+
Deno.test('prepare plan regenerates derived artifacts and release-truth anchors after the bump (#1288)', () => {
472+
// The v0.44.0-beta.2 bump commit (10744cc3) passed the fast prepare gates
473+
// but failed dev CI (run 33885147030) and the promotion PR (run 33885139920)
474+
// on every derived-truth gate the prepare did not re-run: content-graph:check
475+
// (bump rewrites graph sources version.ts/roadmap.tsx), release:truth:check
476+
// (release-state planning anchors), docs:check-version-anchors. The prepare
477+
// plan must leave the bump commit self-consistent under them.
478+
for (
479+
const plan of [
480+
createPreparePlan('0.41.0-alpha.11', 'docs/current/VERSION_PLAN.md'),
481+
createReleasePlan('0.41.0-alpha.11'),
482+
]
483+
) {
484+
const names = plan.map((step) => step.name);
485+
const anchors = names.indexOf('update current version anchors');
486+
const planning = names.indexOf('update release-state planning anchors');
487+
const graph = names.indexOf('regenerate content graph');
488+
const commit = names.indexOf('commit release bump');
489+
assert(anchors !== -1, 'plan must update the version anchors');
490+
assert(planning > anchors, 'release-state planning anchors advance with the bump');
491+
assert(graph > anchors, 'content graph regenerates after its sources are bumped');
492+
assert(
493+
planning < commit && graph < commit,
494+
'regeneration and anchors land inside the bump commit',
495+
);
496+
const graphStep = plan[graph];
497+
assertEquals(graphStep.command, ['deno', 'task', 'generate:content-graph']);
498+
const stage = plan.find((step) => step.name === 'stage release bump');
499+
assert(stage?.command?.includes('www/app/data/_generated-content-graph.json'));
500+
assert(stage?.command?.includes('docs/release/release-state.json'));
501+
}
502+
});
503+
363504
Deno.test('two-phase release: publish-existing never bumps and verifies main CI first', () => {
364505
// The publish-existing plan publishes in the Actions OIDC lane (#1187):
365506
// GITHUB_ACTIONS, not a token variable, gates the npm publish steps.
@@ -634,9 +775,10 @@ Deno.test('buildVersionAnchorReplacements: bump updates the VERSION_PLAN head li
634775
const version = '9.9.9';
635776
const reps = buildVersionAnchorReplacements(version)
636777
.filter(([path]) => path === 'docs/current/VERSION_PLAN.md');
637-
// Source line + registry line in both accepted states (#754), plus latest,
638-
// active, and next train fields.
639-
assertEquals(reps.length, 6);
778+
// Source line + registry line in both accepted states (#754), the
779+
// STATUS-form repository/registry head pair (#1288), plus latest, active,
780+
// and next train fields.
781+
assertEquals(reps.length, 9);
640782

641783
// Simulate the bump against the plan's real head shape: the two header
642784
// lines and the active release target all move to the target.

0 commit comments

Comments
 (0)