Skip to content

Commit 3a185d7

Browse files
author
DevBot
committed
fix(release): converge v0.43.1 published truth
1 parent 9bd5261 commit 3a185d7

12 files changed

Lines changed: 164 additions & 36 deletions

File tree

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,15 @@ and the
7575
built on the
7676
[ADR-0129](./docs/adr/ADR-0129-response-header-channel.md) response-header
7777
channel. Delivered scope is the 0.43 line together with Universal WC SSR;
78-
production-runtime recovery and cache semantics remain 0.44 work.
78+
framework-owned production-runtime recovery and cache semantics remain
79+
unfrozen and unscheduled under ADR-0140.
7980

8081
## Current release state
8182

82-
The five-package convergence is published as stable `0.43.0` (Universal WC
83-
SSR under ADR-0135, on top of the ADR-0122 application loop and untouched
84-
ADR-0119 static freeze). npm beta.1 through beta.3 remain withdrawn partial artifacts and
83+
The five-package convergence is published as stable `0.43.1`: the cumulative
84+
maintenance baseline for Universal WC SSR under ADR-0135, on top of the
85+
ADR-0122 application loop and untouched ADR-0119 static freeze. npm beta.1
86+
through beta.3 remain withdrawn partial artifacts and
8587
are not compatibility baselines. The third audit sweep completed in alpha.19 (see
8688
[ADR-0118](./docs/adr/ADR-0118-third-audit-round-alpha19-cleanup-sweep.md)),
8789
and the #390 pilot was retired by maintainer decision after zero recruitment
@@ -99,8 +101,9 @@ cache/ISR, streaming SSR, performance SLOs, the third-party WC SSR corpus
99101
promise is static-first applications with fullstack output paths—not broad
100102
fullstack parity.
101103

102-
The `1.0.0` path is a stable five-package product after the application loop, WC SSR,
103-
production runtime and external-adoption evidence are complete.
104+
The `1.0.0` path remains unscheduled. It requires a maintainer-approved ADR,
105+
real-product compatibility evidence and external adoption before the
106+
five-package surface can receive a long-term compatibility commitment.
104107

105108
## Start
106109

README.zh.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,14 @@ Cloudflare 是被组合的服务提供方,不是框架内建功能。
6060
(绿色运行
6161
[31925944647](https://github.com/open-element/openelement/actions/runs/31925944647)),
6262
构建于 [ADR-0129](./docs/adr/ADR-0129-response-header-channel.md)
63-
响应头通道之上。交付范围是 0.43 线与 Universal WC SSR;生产运行时恢复与
64-
缓存语义仍是 0.44 的工作
63+
响应头通道之上。交付范围是 0.43 线与 Universal WC SSR;框架自有生产运行时
64+
恢复与缓存语义在 ADR-0140 下仍未冻结,也没有已排期的后续 minor
6565

6666
## 当前发布状态
6767

68-
五包收敛已作为 stable `0.41.0` 发布。npm beta.1 至 beta.3 仍是已撤回的
69-
不完整历史产物,不构成兼容基线。第三轮审计清扫于 alpha.19 完成(ADR-0118),
68+
五包收敛已作为 stable `0.43.1` 发布:它是 ADR-0135 Universal WC SSR 之上的
69+
累计维护基线,并进入 ADR-0140 规定的 0.43.x patch-only 维护模式。npm beta.1
70+
至 beta.3 仍是已撤回的不完整历史产物,不构成兼容基线。第三轮审计清扫于 alpha.19 完成(ADR-0118),
7071
#390 试点在零招募后由 maintainer 决策退役(ADR-0119)。
7172

7273
`0.42 = WC 轻量全栈(WC light fullstack)``0.42.0` 稳定线交付 request-time

docs/release/release-state.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"schemaVersion": 1,
3-
"sourceVersion": "0.43.0",
4-
"publishedVersion": "0.43.0",
5-
"latestLandedTrain": "v0.43.0",
3+
"sourceVersion": "0.43.1",
4+
"publishedVersion": "0.43.1",
5+
"latestLandedTrain": "v0.43.1",
66
"activeTarget": "v0.43.1",
77
"nextPlannedTrain": "not scheduled (maintenance mode)",
88
"maturity": "stable"

docs/roadmap/ROADMAP.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Execution and release state follow the
1313
> ADR-0135; the #1002 production closure is complete.\
1414
> Planned line: `0.43.1` cumulative maintenance baseline; no later minor is
1515
> scheduled. `0.43.0` (Universal WC SSR) shipped 2026-08-20 under ADR-0135.\
16-
> Maturity stage: stable (0.43.0 — the 0.41.x interface freeze under
16+
> Maturity stage: stable (0.43.1 cumulative maintenance baseline — the 0.41.x interface freeze under
1717
> ADR-0119, the request-time loop freeze under ADR-0122, and the Universal
1818
> WC admission freeze under ADR-0135); the
1919
> abandoned beta naming is retired.
@@ -134,11 +134,10 @@ making the standard Custom Element contract span both layers. See the official
134134

135135
## Current release state
136136

137-
`0.43.0` is both the current source package line and the published npm
138-
line (2026-08-20, dist-tag `latest`), promoted from the `0.43.0-alpha.2`
139-
train (published 2026-08-15, dist-tag `alpha`) without further changes.
140-
No later minor is scheduled; `0.43.x` enters maintenance mode after the
141-
`v0.43.1` cumulative baseline. These are
137+
`0.43.1` is both the current source package line and the published npm
138+
line (2026-08-24, dist-tag `latest`). It follows the `0.43.0` Universal WC
139+
SSR stable line and its `0.43.0-alpha.2` train. No later minor is scheduled;
140+
`0.43.x` is now in maintenance mode after the `v0.43.1` cumulative baseline. These are
142141
separate facts by design: landed work is not described as published until the
143142
registry and immutable release evidence prove it.
144143
npm beta.1 through beta.3 are immutable partial artifacts and remain withdrawn

docs/status/STATUS.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
## Current position
1414

1515
OpenElement is a Web Components-native application framework, stable at
16-
`0.43.0` under ADR-0135: the 0.41.x static freeze (ADR-0119 — `defineElement`,
16+
`0.43.1` as the cumulative maintenance baseline over ADR-0135: the 0.41.x static freeze (ADR-0119 — `defineElement`,
1717
`definePage`, `buildApp`, the five-package graph, the supported subpaths and
1818
the static/SPA semantics of `defineApp`) and the request-time Application Loop
1919
freeze (ADR-0122 — loader/action signatures, the
@@ -27,8 +27,8 @@ unfrozen and are not scheduled. `v0.43.1` is a cumulative maintenance baseline:
2727
Wave A requalified the 33 earlier closures, Wave B remediated six confirmed
2828
findings, and Wave C returned `GO` on the schema/runtime candidate after
2929
exact-SHA CI, authorized 23-migration Supabase application, post-apply
30-
catalog/RLS qualification, and Advisor review. v0.43.1 is now in the governed
31-
release workflow. Alpha.19 completed the third audit cleanup sweep (ADR-0118)
30+
catalog/RLS qualification, and Advisor review. v0.43.1 is published and the
31+
0.43.x line is now in ADR-0140 maintenance mode. Alpha.19 completed the third audit cleanup sweep (ADR-0118)
3232
and the #390 pilot requirement was retired by maintainer decision after zero
3333
recruitment. The `0.41.1` patch carries the third-party audit's fixable
3434
tooling and hygiene set with no frozen-surface change. On the 0.42 alpha

examples/supabase-cloudflare-starter/deno.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "0.43.0",
2+
"version": "0.43.1",
33
"tasks": {
44
"build": "deno run --config ../../deno.json --allow-read --allow-write --allow-net --allow-env --allow-ffi --allow-sys --allow-run ../../packages/adapter-vite/src/cli/build.ts",
55
"nitro:build": "OPEN_ELEMENT_NITRO_PRESET=cloudflare_module deno run --config ../../deno.json --node-modules-dir=auto -A npm:nitro@3.0.0 build && rm -rf .output-workers/public/server",

tools/autoflow/__tests__/release.test.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
writeReleaseNote,
3333
} from '../release.ts';
3434
import {
35+
advancePublishedReleaseStateText,
3536
buildVersionAnchorReplacements,
3637
bumpProjectConstantsText,
3738
nextPrereleaseTag,
@@ -248,6 +249,29 @@ Deno.test('bumpProjectConstantsText: re-running a bump is a no-op and keeps the
248249
assert(once.includes("PREVIOUS_PACKAGE_VERSION = '0.41.0-alpha.16'"));
249250
});
250251

252+
Deno.test('advancePublishedReleaseStateText: finalize converges source and registry truth', () => {
253+
const input = JSON.stringify({
254+
schemaVersion: 1,
255+
sourceVersion: '0.43.1',
256+
publishedVersion: '0.43.0',
257+
latestLandedTrain: 'v0.43.0',
258+
activeTarget: 'v0.43.1',
259+
nextPlannedTrain: 'not scheduled (maintenance mode)',
260+
maturity: 'stable',
261+
});
262+
const stable = JSON.parse(advancePublishedReleaseStateText(input, '0.43.1'));
263+
assertEquals(stable.sourceVersion, '0.43.1');
264+
assertEquals(stable.publishedVersion, '0.43.1');
265+
assertEquals(stable.latestLandedTrain, 'v0.43.1');
266+
assertEquals(stable.activeTarget, 'v0.43.1');
267+
assertEquals(stable.nextPlannedTrain, 'not scheduled (maintenance mode)');
268+
assertEquals(stable.maturity, 'stable');
269+
270+
const alpha = JSON.parse(advancePublishedReleaseStateText(input, '0.44.0-alpha.1'));
271+
assertEquals(alpha.publishedVersion, '0.44.0-alpha.1');
272+
assertEquals(alpha.maturity, 'alpha');
273+
});
274+
251275
Deno.test('two-phase release: prepare never publishes, tags, or pushes main', () => {
252276
const steps = createPreparePlan('0.41.0-alpha.11', 'docs/current/VERSION_PLAN.md');
253277
const names = steps.map((step) => step.name);
@@ -260,6 +284,7 @@ Deno.test('two-phase release: prepare never publishes, tags, or pushes main', ()
260284
assertFalse(commands.some((command) => command.includes('git push')));
261285
const stage = steps.find((step) => step.name === 'stage release bump');
262286
assert(stage?.command?.includes('packages/create/src/version.ts'));
287+
assert(stage?.command?.includes('examples/supabase-cloudflare-starter/deno.json'));
263288
});
264289

265290
Deno.test('two-phase release: publish-existing never bumps and verifies main CI first', () => {
@@ -811,7 +836,26 @@ async function initReleaseRepo(): Promise<{ root: string; work: string }> {
811836
await git(work, ['config', 'user.name', 'Release Test']);
812837
await git(work, ['checkout', '-b', 'main']);
813838
await Deno.writeTextFile(`${work}/seed.txt`, 'seed\n');
814-
await git(work, ['add', 'seed.txt']);
839+
await Deno.mkdir(`${work}/docs/release`, { recursive: true });
840+
await Deno.writeTextFile(
841+
`${work}/docs/release/release-state.json`,
842+
`${
843+
JSON.stringify(
844+
{
845+
schemaVersion: 1,
846+
sourceVersion: '9.9.9',
847+
publishedVersion: '9.9.8',
848+
latestLandedTrain: 'v9.9.8',
849+
activeTarget: 'v9.9.9',
850+
nextPlannedTrain: 'not scheduled',
851+
maturity: 'stable',
852+
},
853+
null,
854+
2,
855+
)
856+
}\n`,
857+
);
858+
await git(work, ['add', 'seed.txt', 'docs/release/release-state.json']);
815859
await git(work, ['commit', '-m', 'seed']);
816860
await git(work, ['checkout', '-b', 'dev']);
817861
await git(work, ['remote', 'add', 'origin', origin]);
@@ -896,6 +940,12 @@ Deno.test('local release finalize: evidence and closure land on main, dev is syn
896940
await git(work, ['show', 'main:docs/release/autoflow3/v9.9.9.json']),
897941
) as { status: string };
898942
assertEquals(mainEvidence.status, 'completed');
943+
const releaseState = JSON.parse(
944+
await git(work, ['show', 'main:docs/release/release-state.json']),
945+
) as { sourceVersion: string; publishedVersion: string; latestLandedTrain: string };
946+
assertEquals(releaseState.sourceVersion, '9.9.9');
947+
assertEquals(releaseState.publishedVersion, '9.9.9');
948+
assertEquals(releaseState.latestLandedTrain, 'v9.9.9');
899949
// The release note on main carries the Durable closure section.
900950
const note = await git(work, ['show', 'main:docs/release/v9.9.9.md']);
901951
assert(note.includes('## Durable closure'));

tools/autoflow/release.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
releaseTag,
3939
updateCurrentVersionAnchors,
4040
updateProjectConstants,
41+
updatePublishedReleaseState,
4142
} from './version-anchors.ts';
4243

4344
// Re-exported for cli.ts (releaseTag) and tools/check-docs-truth.ts
@@ -341,6 +342,7 @@ export function createReleasePlan(
341342
'packages/*/deno.json',
342343
'packages/create/src/version.ts',
343344
'packages/ui/src/generated-manifest.json',
345+
'examples/supabase-cloudflare-starter/deno.json',
344346
'tools/project-constants.ts',
345347
'README.md',
346348
'README.zh.md',
@@ -1092,6 +1094,7 @@ async function commitFinalEvidenceAndClosure(
10921094
branch: string,
10931095
): Promise<void> {
10941096
await writeAndStageReleaseEvidence(evidence);
1097+
await updatePublishedReleaseState(evidence.targetVersion);
10951098
const tag = releaseTag(evidence.targetVersion);
10961099
const env = (name: string) => Deno.env.get(name);
10971100
const record: ReleaseClosureRecord = {
@@ -1111,6 +1114,7 @@ async function commitFinalEvidenceAndClosure(
11111114
'add',
11121115
closureFile(evidence.targetVersion),
11131116
releaseNoteFile(evidence.targetVersion),
1117+
'docs/release/release-state.json',
11141118
]);
11151119
if (await hasStagedChanges()) {
11161120
await runCaptured([

tools/autoflow/version-anchors.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,48 @@ export function releaseTag(version: string): string {
2020
return `v${version}`;
2121
}
2222

23+
export interface PublishedReleaseState {
24+
schemaVersion: number;
25+
sourceVersion: string;
26+
publishedVersion: string;
27+
latestLandedTrain: string;
28+
activeTarget: string;
29+
nextPlannedTrain: string;
30+
maturity: 'alpha' | 'beta' | 'stable';
31+
}
32+
33+
/**
34+
* Advance the durable source/registry truth only after publication completes.
35+
* Prepare intentionally leaves publishedVersion on the prior line; finalize is
36+
* the first point where npm, the immutable tag and the GitHub release are all
37+
* proven, so it owns this transition.
38+
*/
39+
export function advancePublishedReleaseStateText(text: string, version: string): string {
40+
const state = JSON.parse(text) as PublishedReleaseState;
41+
const prerelease = version.match(/-(alpha|beta)(?:\.|$)/u)?.[1];
42+
return `${
43+
JSON.stringify(
44+
{
45+
...state,
46+
schemaVersion: 1,
47+
sourceVersion: version,
48+
publishedVersion: version,
49+
latestLandedTrain: releaseTag(version),
50+
activeTarget: releaseTag(version),
51+
maturity: prerelease === 'alpha' || prerelease === 'beta' ? prerelease : 'stable',
52+
} satisfies PublishedReleaseState,
53+
null,
54+
2,
55+
)
56+
}\n`;
57+
}
58+
59+
export async function updatePublishedReleaseState(version: string): Promise<void> {
60+
const path = 'docs/release/release-state.json';
61+
const text = await Deno.readTextFile(path);
62+
await Deno.writeTextFile(path, advancePublishedReleaseStateText(text, version));
63+
}
64+
2365
export function nextPrereleaseTag(version: string): string {
2466
const match = version.match(/^(\d+\.\d+\.\d+)-([a-zA-Z]+)\.(\d+)$/u);
2567
if (!match) return releaseTag(version);

tools/bump-version.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
*/
2121

2222
const PACKAGES_DIR = 'packages';
23+
const VERSIONED_APP_DENOS = [
24+
'examples/supabase-cloudflare-starter/deno.json',
25+
] as const;
2326

2427
interface PackageJson {
2528
name?: string;
@@ -133,6 +136,10 @@ function updateVersion(
133136
const name = data.name ?? path;
134137
const oldVersion = data.version ?? 'unknown';
135138

139+
if (data.version === toVersion) {
140+
return { updated: false, name, oldVersion };
141+
}
142+
136143
if (data.version && data.version === fromVersion) {
137144
if (!dryRun) {
138145
const text = Deno.readTextFileSync(path);
@@ -219,6 +226,9 @@ function main(): void {
219226

220227
// Find all package deno.json files
221228
const packageDenos = findPackageDenos(root);
229+
const versionedAppDenos = VERSIONED_APP_DENOS.map((path) => `${root}/${path}`);
230+
const versionedAppSet = new Set(versionedAppDenos);
231+
const versionedDenos = [...packageDenos, ...versionedAppDenos];
222232
console.log(`Found ${packageDenos.length} package(s) in ${PACKAGES_DIR}/`);
223233

224234
// Determine "from" version
@@ -231,21 +241,28 @@ function main(): void {
231241
}
232242

233243
if (resolvedFrom === toVersion) {
234-
console.log(`Already at version ${toVersion}. Nothing to do.`);
235-
return;
244+
console.log(`Package line already at ${toVersion}; checking every governed manifest.`);
245+
} else {
246+
validateVersionStep(resolvedFrom, toVersion);
236247
}
237248

238-
validateVersionStep(resolvedFrom, toVersion);
239-
240249
console.log(`Bumping: ${resolvedFrom}${toVersion}${dryRun ? ' (dry-run)' : ''}`);
241250
console.log('');
242251

243252
// Update package versions
244253
let updatedCount = 0;
245254
const mismatched: string[] = [];
246255

247-
for (const path of packageDenos) {
248-
const result = updateVersion(path, resolvedFrom, toVersion, dryRun);
256+
for (const path of versionedDenos) {
257+
const existing = readJson(path).version;
258+
// Versioned application manifests are convergence anchors, not publishable
259+
// packages. Heal them on an idempotent resume even when the package line
260+
// was already bumped before this manifest joined the governed set.
261+
const manifestFrom = versionedAppSet.has(path) && existing ? existing : resolvedFrom;
262+
if (versionedAppSet.has(path) && existing && existing !== toVersion) {
263+
validateVersionStep(existing, toVersion);
264+
}
265+
const result = updateVersion(path, manifestFrom, toVersion, dryRun);
249266
if (result.updated) {
250267
updatedCount++;
251268
console.log(` ✅ ${result.name}: ${result.oldVersion}${toVersion}`);
@@ -258,7 +275,7 @@ function main(): void {
258275
}
259276

260277
console.log('');
261-
console.log(`Updated ${updatedCount}/${packageDenos.length} packages.`);
278+
console.log(`Updated ${updatedCount}/${versionedDenos.length} versioned manifests.`);
262279

263280
// Update cross-package imports in each package's deno.json. (Root deno.json
264281
// is deliberately not touched: check-package-graph bans @openelement/*
@@ -289,7 +306,7 @@ function main(): void {
289306
console.log('Validating alignment...');
290307

291308
let allAligned = true;
292-
for (const path of packageDenos) {
309+
for (const path of versionedDenos) {
293310
const data = readJson(path);
294311
if (data.version !== toVersion) {
295312
allAligned = false;
@@ -298,7 +315,7 @@ function main(): void {
298315
}
299316

300317
if (allAligned) {
301-
console.log(` ✅ All ${packageDenos.length} packages aligned to ${toVersion}`);
318+
console.log(` ✅ All ${versionedDenos.length} versioned manifests aligned to ${toVersion}`);
302319
} else {
303320
console.log(' ❌ Version alignment check FAILED');
304321
if (!dryRun) Deno.exit(1);

0 commit comments

Comments
 (0)