Goal, as stated: bring the project to a checkpoint where what it says about the environments it runs in matches what it needs — shedding the untrue past, and not going one step further than that.
Everything below is measured on this checkout on 2026-09-05 (Node 14.21.3, 20.9.0,
22.20.0 and 24.18.0 on Windows 11), with git log -S for the dates of each claim.
Companion to ANALYSIS-2026-08.md, which has the architecture and boot-cost material.
The checkpoint itself was carried out on 2026-09-07 on branch honest_checkpoint; §6
records what was done, including where doing it corrected this plan, §7 the release round
across the sibling packages, and §8 what it left.
The repo never claims ES3. The claim on the record is README.md:77, "Amber
officially only runs in ES5-compliant environments" (2018-08), backed by a
polyfill-and-shim culture: es6-promise wired into five places and bundled into
cli/dist/amber-cli.js, a globalThis preamble in three places, and "node": ">=4.0.0"
in all four package.jsons (2017–2018). The "ES3" feel comes from the syntax stance —
kernel and compiler output are deliberately ES5-only — not from any written claim.
What the code needs, with the date each requirement quietly arrived:
| requirement | edition | where | since |
|---|---|---|---|
Object.setPrototypeOf |
ES2015 | kernel-language.js:253, kernel-runtime.js:193, Kernel-Classes.st:155 |
2019-06-03 (e7c2cda1, acknowledged: "Last release compatible with IE9 and IE10") |
Promise incl. Promise.all / Promise.race |
ES2015 | boot.js:50, helpers.js, kernel-runtime.js:211, Kernel-Promises.st, $pkg.isReady prologues |
long-standing; polyfilled by convention |
Number.isFinite / Number.isNaN |
ES2015 | Kernel-Objects.st:1213, :1222 |
2020-04-19 (45b172b8), never acknowledged — this alone falsifies the ES5 sentence for a polyfilled ES5 host |
globalThis |
ES2020 | boot.js:47, helpers.js:36, kernel-checks.js:39-45 |
2021-02-23 (017e724d, 0.30.0: "so breaking"), then shimmed back |
Syntax, by contrast, is genuinely ES5 everywhere: hand-written kernel, pegjs 0.10 parser,
compiler output (the jshint "syntax errors" on compiled files are jshint's own bug, §5).
So the honest floor is decided by one thing: whether globalThis is required natively
(ES2020) or may be supplied by the host (ES2015 + a one-line shim). Recommendation: ES2020
(§3). Either way, the ES5 sentence, node >= 4, Bower, and es6-promise go.
Two gates are currently dishonest too, and a checkpoint that leaves them is not one:
the lint task has not been green since the pragma-style codegen (1,096 findings; last
lint-config commit is from 2013), and the test suite is red on Windows (763 run, 1
failure on every Node version, a 10 ms margin against a 15.6 ms timer tick). The third
gate, CI, is alive and truthful — build #217 green on master — but it last ran on
2022-03-25 against a floating node:lts, so the Node version it vouches for is 16, not
anything package.json says (§5.3).
Each row: where it is, what it asserts, when it was written, why it is untrue now, and the minimal correction. "A" / "B" refer to the two floors in §3 where they differ.
| # | where | says | since | truth | correction |
|---|---|---|---|---|---|
| 1 | README.md:77 |
"officially only runs in ES5-compliant environments" | 2018-08-18 55ebd379 |
false since 2019-06 (setPrototypeOf, IE ≤ 10 gone), doubly since 2020-04 (Number.isFinite), triply since 2021-02 (globalThis) |
replace with the §3 floor statement |
| 2 | README.md:73-75 |
"older environments … install additional polyfills (Promise polyfill is included by default)" |
2018-08-18 | describes a bundling that A removes; even under B the sentence is wrong, since Number.isFinite is not polyfilled by anything shipped |
delete; under B, say "supply globalThis" instead |
| 3 | README.md:4 |
Drone build badge at ci.lolg.it |
— | truthful: the server is live and the last master build (#217, 2022-03-25) passed — on whatever node:lts was then (16) |
keep; pin the CI matrix to the declared floor (§5.3) |
| 4 | package.json, lang/, sdk/, cli/; grunt-init-project/template.js:137 (node_version, inherited by every scaffolded project) |
"node": ">=4.0.0" |
2017-10-07 a5724dc6 (root), 2018-08-13 ff472fc7 (siblings) |
Node 4 has no globalThis (shim-dependent), EOL 2018-04, and nothing below 14 has been run here |
A: >=12 (first native globalThis; verified here on 14–24). B: >=6 |
| 5 | sdk/package.json engines |
"@ambers/lang": ">0.22.6" |
— | not an engine; engines is for runtimes |
move to peerDependencies or drop |
| 6 | CONTRIBUTING.md:4 |
"at least npm@5 (bundled with node 8)" | — | true but obsolete floor; contradicts >=4 |
state the same floor as #4 |
| 7 | CONTRIBUTING.md:85 |
Bower listed as a required dev dependency | — | debowerized 2018-08 ("debowerizing" in 55ebd379); nothing uses Bower |
delete the bullet |
| 8 | CHANGELOG |
IE7/8/9/10 support history, Bower releases | 2011–2019 | history — true statements about the past | leave untouched; add the new floor as a release note (§6 step 12) |
| # | where | what | A | B |
|---|---|---|---|---|
| 9 | index.html:26 |
var globalThis = typeof globalThis === "undefined" ? window : globalThis \|\| window; (2021-02) |
delete | keep, comment as the documented host duty |
| 10 | grunt-init-project/root/index.html:27 |
same preamble in every scaffolded project | delete | keep |
| 11 | sdk/lib/helpers.js:3 |
Node wrapper preamble … ? global : globalThis \|\| global (2021-02 c8375ea4), reproduced as line 2 of cli/dist/amber-cli.js and every amberc-built Node bundle |
delete, rebuild cli/dist |
keep |
| 12 | package.json:35 |
es6-promise devDependency (added 2013-12-26) |
delete | delete |
| 13 | index.html:36-37 |
require(["amber/es6-promise"]) … promiseLib.polyfill() |
delete | delete |
| 14 | Gruntfile.js:20-27, 90, 116 |
polyfillThenPromiseApp wrapped into the CLI and test-runner bundles |
delete; the app entry becomes a plain require(["__app__"]) |
same |
| 15 | es6-promise.amd.json (root) → generated config.js path amber/es6-promise |
AMD path for the polyfill | delete file; grunt devel regenerates config.js without it |
same |
| 16 | grunt-init-project/template.js:124 |
"es6-promise": "^4.2.6" added to every new project |
delete | same |
| 17 | grunt-init-project/root/Gruntfile.js:84, 92, 109 |
es6-promise/auto path + two mkDefine(["require","es6-promise/auto"] …) entries |
delete | same |
| 18 | grunt-init-project/root/uninstall.html:14-15 |
"you can choose to polyfill less or not at all …" | delete the bullet | same |
| 19 | cli/dist/amber-cli.js |
bundles the whole of es6-promise (see its header) and the preamble |
not touched: it is the published artifact, rebuilt only by the release ritual's Recompile (while version set to X) — every rebuild since 0.22.5 — and deliberately stale in between; the next release drops both by itself |
same |
| 20 | bower.json; bower_components/ in .gitignore and in the cli/, lang/, sdk/ ignore files; stale comments in setversion.sh:16 and release-worker.sh:25 |
Bower packaging, last touched 2018-08-13; setversion.sh only ever updated package.json |
delete all | same |
| 21 | lang/base/kernel-checks.js:32-37 |
commented-out new Function("return this") probes — the pre-globalThis global detection, dead since 2021 |
delete (part of §4) | same |
Checked so that the checkpoint does not "correct" them:
$ctx1.sendIdx["class"] bracket notation — required anyway for keyword selectors
(sendIdx["nextPutAll:"]); not reserved-word avoidance.[expr, $ctx1.sendIdx[…]=1][0] — selects the first value while evaluating the second;
the comma operator would yield the second. Codegen convenience, not ES3.throw $early=[…], var/function everywhere — valid ES5 and a legitimate choice
of output level. Choosing ES5 output is not a claim about the runtime.Kernel-Infrastructure.st:875 reservedWords — already the ES2015 list (let static
await enum …); honest as is.Kernel-Collections.st:61 "in ES5 its toString() value counts" — a true remark about
property keys.Platform-Node.st:12 globals ^ global — Node-specific, global still exists; harmless.
Could become globalThis for consistency with 0.30.0's "stop using global", optional.Conclusion for the syntax question: there is nothing ES3-motivated left to remove. The stance lives in the lint level and the stated floor, not in code shapes. The honest move is to state the floor and set the lint level to it — permitting ES2015+ syntax in the kernel from now on — while leaving existing code exactly as it is (AGENTS.md: no piecemeal modernization).
lang/base (hand-written, excl. generated parser): ES5 only — var, function,
strict mode; zero let/const/=>/class/template literals.lang/base/parser.js: "Generated by PEG.js 0.10.0" — ES5.lang/src/*.js (compiler output): ES5 only — verified across all 26 files; the only
ES2015 tokens are inside source: strings and the reservedWords literal. Grep hits
that looked like leaks (=> in Kernel-Collections.st:1699, .fill( in
NodeTestRunner.js, async in SUnit.st) are a regex character class, the
$ctx.fill context method, and prose respectively.sdk/, cli/: ES5 syntax; Node core use is fs, path, child_process,
requirejs and Promise — nothing that sets a Node floor above what lang sets.Exactly four, listed in §0. Support matrix (from the September research in
ANALYSIS-2026-08.md §5.2 and MDN compat data):
| API | Chrome | Firefox | Safari | Edge | Node |
|---|---|---|---|---|---|
Object.setPrototypeOf |
34 | 31 | 9 | 12 (IE 11 too) | 0.12 |
Promise (+all/race) |
32 | 29 | 8 | 12 | 0.12 |
Number.isFinite / isNaN |
19 | 16 | 9 | 12 | 0.10 |
globalThis |
71 | 65 | 12.1 | 79 | 12 |
Every row but the last is satisfied by any 2015-era engine (IE 11 fails only on
Number.isFinite/isNaN — which is precisely what the README's "ES5 + Promise polyfill"
recipe cannot know). globalThis is the sole 2019-era requirement.
.drone.yml, Drone at ci.lolg.it, live): node:lts floating tag, Linux. Last
run #217 on 2022-03-25 for the current master head (81713dec), green; node:lts
then meant Node 16. Nothing has been pushed since, so nothing newer has been verified.ANALYSIS-2026-08.md §5.2.@ambers/lang requires an ES2020-capable JavaScript engine:
globalThis,Promise,Object.setPrototypeOf,Number.isFinite/isNaNnatively. Browsers: Chrome/Edge 79+ (Chrome 71+), Firefox 65+, Safari 12.1+. Node 12+; verified on 14–24 as of this checkpoint. No polyfills or preambles are shipped or needed.
Why A:
globalThis.
Stop using global, so breaking, but just fix preamble of index.html." The preambles
were a courtesy to engines that were already EOL (Node ≤ 10 by 2021-04; IE 11 by
2022-06; pre-2019 browsers). Five years on, the courtesy has become the lie.kernel-checks.js becomes literally true. It already asserts globalThis and
native Promise; today those assertions pass only because the shim runs first.node:lts image is years past ES2020.globalThisRequires an ES2015 engine plus a
globalThisbinding; hosts older than ES2020 must define it before loading (the CLI wrapper and project template do). Node 6+.
Honest too, and one line cheaper per entry point. It buys support for Node 6–10 and 2016–2018 browsers that nobody runs or tests. Choose B only if there is a known deployment on such an engine; otherwise it is documentation of a promise nobody will keep.
class, arrows, const..js except by recompilation where a .st changes.What the checkpoint does permit going forward: ES2015+ syntax in hand-written kernel code, gated by AGENTS.md's rule that a syntax raise is its own concern, never smuggled in with a fix. The lint level is set to say so (§5.1).
kernel-checks.js — safer and intent-revealingToday the file is thirteen anonymous assert(function(){…}) calls. On failure it throws
the source text of the probe — the reader gets Assertion failed: function () { return
typeof globalThis !== "undefined"; } and has to infer the missing feature and the
edition it belongs to. The probes mix three different kinds of guarantee, and two of the
things the kernel relies on are not probed at all.
| probe(s) | guards | kind |
|---|---|---|
Object.create(null) has no hasOwnProperty; its prototype is null; Object.create(p) inherits |
method dictionaries and selector sets are Object.create(null) maps (kernel-fundamentals.js) |
ES5 semantics |
Object.setPrototypeOf returns the object and re-links |
trait composition and detached-root re-parenting (kernel-language.js, kernel-runtime.js) |
ES2015 API |
typeof globalThis, globalThis.Object === Object, Object.create(globalThis).Object === Object |
the globals object is Object.create(globalThis) (boot.js:47) |
ES2020 API + Amber's globals trick |
fn.apply(void 0) is undefined, apply(null) is null, apply(3) is 3, … |
strict-mode this is passed unboxed — every send to a Number/String/Boolean receiver depends on this being the primitive |
ES5 strict semantics (the most Amber-specific probe in the file, and unlabelled) |
| assignment to a frozen object does not add the property | MethodContext.prototype.locals = Object.freeze({}) fallback |
ES5 semantics |
typeof Promise, .resolve, .reject, .then |
Promise is a detached root and the boot protocol |
ES2015 API |
| (missing) | Number.isFinite / Number.isNaN — used by Kernel-Objects.st since 2020 |
ES2015 API |
| (missing) | Promise.all / Promise.race — used by Kernel-Promises.st |
ES2015 API |
| (dead) | commented-out new Function("return this") probes |
pre-2021 global detection |
lang/base/kernel-checks.jsGroup probes by the guarantee they represent, name each, collect all failures, and
throw once with a message a stranger can act on. Keep this one file in ES5 syntax
forever — it is the thing that must run on a too-old engine in order to say so.
What landed is the sketch below plus two details: a probe that throws carries the
exception text into the message, and the unboxed-this probe carries a scoped
validthis directive for jshint.
define(function () {
"use strict";
var FLOOR = "ES2020";
var missing = [];
function need (edition, feature, probe) {
var ok;
try { ok = probe(); } catch (e) { ok = false; }
if (!ok) missing.push(feature + " (" + edition + ")");
}
// --- APIs the kernel calls directly ---------------------------------
need("ES2020", "globalThis", function () {
return typeof globalThis === "object" && globalThis.Object === Object;
});
need("ES2015", "Promise", function () {
return typeof Promise === "function" && typeof Promise.resolve === "function" &&
typeof Promise.all === "function" && typeof Promise.race === "function";
});
need("ES2015", "Object.setPrototypeOf", function () {
var p = {x: 4, y: 5}, q = {x: 6};
return Object.setPrototypeOf(q, p) === q && q.x === 6 && q.y === 5;
});
need("ES2015", "Number.isFinite / Number.isNaN", function () {
return Number.isFinite(1) && !Number.isFinite("1") && Number.isNaN(NaN);
});
// --- semantics Amber's object model is built on ----------------------
// Method dictionaries and selector sets are Object.create(null) maps.
need("ES5", "prototype-less objects", function () {
var o = Object.create(null);
return !("hasOwnProperty" in o) && Object.getPrototypeOf(o) === null;
});
// The globals object is Object.create(globalThis); lookups must fall through.
need("ES2020", "inheriting from globalThis", function () {
return Object.create(globalThis).Object === Object;
});
// A send to 3 or "foo" must reach the method with `this` as the primitive itself;
// sloppy-mode boxing would break every Number/String/Boolean receiver.
need("ES5 strict mode", "unboxed primitive `this`", function () {
function me () { return this; }
return me.apply(void 0) === void 0 && me.apply(null) === null &&
me.apply(3) === 3 && me.apply("foo") === "foo" && me.apply(true) === true;
});
// MethodContext falls back to a frozen empty `locals`; writes must not leak into it.
need("ES5", "Object.freeze is honoured", function () {
var o = Object.freeze({});
try { o.foo = "bar"; } catch (e) {}
return !("foo" in o);
});
if (missing.length) {
throw new Error("Amber needs an " + FLOOR + "-capable JavaScript engine; " +
"this one lacks: " + missing.join(", "));
}
});
Net effect: the same guarantees plus the two missing ones, no dead code, the floor named
once as data, and a failure message that says what to upgrade. Under Floor B, the
globalThis probes stay but FLOOR reads "ES2015 with a globalThis binding" — the file
is where the decision is recorded either way.
grunt jshint (jshint 2.9.6 via grunt-contrib-jshint ^1.1.0, no configuration at all
— the last commit touching lint setup is 0fff71b9 from 2013-03-16) reports 1,096
findings in 38 files:
lang/base (hand-written): 6 — three W093 "return assignment", two W033, one
W032. Two of those are in the untracked kernel-interpreter.js. Style only.lang/src (compiled): ~1,090 — 539 missing semicolons, 224 "misleading line
break" (the pragma-comment idiom), 86 expression statements, 71 "better in dot
notation" (sendIdx["class"]), 55 unreachable code (return self; after throw
$early), and 61 E-class errors that are jshint's own bug: in esversion: 5 mode
its throw parser rejects throw $early=[…]; with esversion: 6 every file parses
clean. Node 14–24 parse and run all of it.The task lints generated output against rules written for hand-written code, with a tool level below what the tool itself can parse.
Done in the checkpoint: grunt-contrib-jshint ^3.2.0 (jshint 2.13.6, the first that
knows esversion: 11); a root .jshintrc — esversion 11, node, eqnull, sub
(bracket notation for AMD-shaped keys) — replacing the eqnull directives repeated at
the top of each kernel file; lang/base/.jshintrc extending it with -W093, so
return x = y is tolerated where it already exists and flagged anywhere new; the
targets narrowed to the hand-written files (kernel, sdk/index.js,
sdk/lib/{amberc,helpers,without-imports}.js, sdk/tasks/*.js,
cli/dist/amberc-cli.js, cli/test/*.js, Gruntfile.js,
grunt-init-project/template.js); and the findings jshint was right about fixed — four semicolons, a callback called through
&&, an eval and a loop closure marked deliberate. Result: all 21 files lint free.
763 tests run, 1 failures, 0 errors on Node 14.21.3, 20.9.0, 22.20.0 and 24.18.0 alike;
the failure is always SUnitPromiseTest >> testTimeouts (SUnit-Tests.st:343, added
2020-10-03 704dd5af). Run in isolation on Node 20 it passes; in isolation on Node 24
one extra "SUnit grace time exhausted" appears (fakeMultipleTimeoutPassing timing out),
so the expected-failures set no longer matches. The fake tests use 10 ms delays against
20 ms timeouts; measured here, setTimeout(10) fires after 14.5–24.9 ms (median 15.5)
— the Windows 15.6 ms timer tick. The test is deterministic on Linux (1 ms timers, which
is what CI ran) and unwinnable on Windows under suite load.
Done in the checkpoint, and not by a uniform factor — a first attempt at ×10 produced
2000 ms grace times that risk colliding with defaults. The rule applied: where two
timers race, the shorter goes to 50 ms and the longer 100 ms behind it (20/30 →
50/150; nested 150; 50 → 50; 150 and 150; 50 → 150; 50); a grace time racing an
immediate action goes to 100; the sub-suite meta-tests from 200 to 500; timers racing
nothing keep their values. Green on Node 14, 20, 22 and 24; the suite runs in
4.3–5.1 s. NodeTestRunner printing only the test name — and not the assertion text —
remains a smaller gap, untouched (§8).
ci.lolg.it (Drone, self-hosted as lolgit.herby.sk) is live: the badge reports
success, and the API shows build #217 green for the master push "Working on 0.30.4"
on 2022-03-25 — the current master head. (An earlier fetch from this session's tooling
got ECONNREFUSED; that was the tool's network path, not the server.)
The honesty gap is subtler than a dead badge: .drone.yml runs on node:lts, a floating
tag, so the green means "passed on Node 16 in March 2022" and says nothing about the
>= 4 in package.json or about today's LTS.
Done in the checkpoint, on the lang pipeline: the test step also leaves the built
runner behind, and a test-on-floor step on node:12 executes it. Building on the
floor was not an option — grunt ^1.0.3 resolves to 1.6, which needs Node 16 — so the
toolchain runs on LTS and Amber is exercised on the floor, the same split as the local
verification. engines is thereby a tested claim from the first push. The badge stays.
honest_checkpoint, 2026-09-07)One concern per commit, in this order. Where carrying a step out corrected the plan, the correction is noted rather than hidden.
Widen timing margins in SUnit tests. + Recompile. — §5.2.Working on 0.31.0 — not in the plan. A higher floor and dropped polyfills is
a breaking change, and in this repo a breaking change opens with the release
ritual's own commit shape bumping the worked-on version (lang/package.json,
Kernel-Infrastructure.st version, its recompiled .js) to the next minor, so
that everything after it — and the API-CHANGES.txt entry — sits under the version
that ships it. The SUnit fix above stays on the 0.30.4 side.State the ES2020 engine floor in kernel-checks. — §4.Remove the es6-promise polyfill. / Stop scaffolding the es6-promise polyfill. —
#12–#18, split by release unit.Drop the globalThis preamble from the development page. / Stop scaffolding the
globalThis preamble. / sdk: Drop the globalThis preamble from the Node wrapper. —
#9–#11.cli/dist/amber-cli.js. Not done — see #19, the bundle is a
release artifact. Building it to verify was still worth it: the result boots through
the new checks on Node 14 and 24 and passes the CLI e2e test; it was discarded.Declare Node 12 as the floor. — #4, the four package.jsons and the scaffold's
node_version. sdk: Move the @ambers/lang requirement out of engines. — #5, into an
"amber": {"lang": ">0.22.6"} field npm ignores, and amberc now prints the lang
version it compiles with next to that range on every run. A peer dependency was
considered and rejected: npm refuses prerelease versions such as 0.30.4-pre against
>0.22.6, which would break this repo's own npm install ../lang.State the environment floor in README and CONTRIBUTING. — #1, #2, #6.Remove the Bower leftovers. — #20, eight files.Satisfy jshint in the hand-written code. / Lint only hand-written code, at the
ES2020 level. — §5.1.CI: Run the suite on the declared Node floor as well. — §5.3, lang pipeline only.Note the ES2020 floor in API-CHANGES.txt. — under 0.31.0:. The CHANGELOG entry
followed in item 19.AGENTS.md: What the checkpoint settled. — the floor, the CI facts, and the two
conventions learned along the way (the bundle is rebuilt at release only; a breaking
change opens with Working on X).cli: Fix amberc -p. — found by the lint pass and deliberately kept out of it:
optionsArray.shift.split(','), shift never called, so every -p threw. One
character, and an e2e test that compiles a fixture with Amber reachable only through
-p mappings.cli: Find Amber where amberc is installed. — the second amberc bug, found while
writing that test: the default amber_dir was node_modules/amber, the package name
from before the 2018 move to @ambers, so amberc without -d had thrown ever
since. Now the resolved @ambers/lang, hoisting-proof; e2e test with neither -d
nor -p.@ambers/sdk: Bump version to 0.13.0. — its Node wrapper changed (step 5); a minor,
like every package in the release round (§7).Scaffold the versions that share the ES2020 floor. / scaffolding: Bump version to
0.31.0. — new projects depend on the first floor-stating releases of everything;
the scaffold tracks lang's line, as 0.28, 0.29 and 0.30 did.cli: Require the packages that share the ES2020 floor. / cli: Bump to 0.108.0. —
lang, sdk and scaffold at their new minors; a minor of its own because its bundle
lost the Node < 12 preamble.CHANGELOG: The ES2020 floor. — the upcoming-release entry under ?? Sep 2026 -
Release 0.31.0, the way 017e724d wrote 0.30.0's alongside its breaking change. An
earlier draft of this document held the entry back on a "CHANGELOG is written at
release only" rule; the history does not support that rule, and AGENTS.md now says
what the history shows.Gates at the end: grunt jshint green on all hand-written files; 763 tests run,
0 failures on Node 14, 20, 22 and 24; the CLI e2e suite at 3 passing; CI alive, with
the floor step waiting for the first push. Nothing changed a line of Smalltalk semantics
or compiled output beyond the timing constants in one test class and the version string.
The seven sibling packages carried the same wiring as amber's own dev files — an
es6-promise.amd.json declaring the polyfill's AMD path (the source of every
amber/es6-promise and helios/es6-promise/auto entry a regenerated config.js ever
showed, since the AMD config builder walks everything it can reach), the same Gruntfile
wrapper loading it ahead of the app, the dependency, and engines >= 4; Helios also had
a polyfills module its popup page went through, plus global and globalThis
preambles. No code in any of them required the module.
Each sibling got the same sequence on a drop_es6_promise branch, in its own convention
(no -pre; the release commit's subject is the version): Remove the es6-promise
polyfill. (Helios: then Drop the global and globalThis preambles from the popup
page.) → Declare Node 12 as the floor. → Require the siblings that share the ES2020
floor. (every @ambers/* range, dependencies and devDependencies, moved to the target's
new minor, each entry keeping its operator; open-ended > became >=) → the version
commit. Dropping a shipped polyfill and raising the floor is breaking, hence a minor
everywhere. The runtime dependency graph gives the publish order:
| step | package | version | requires (runtime) |
|---|---|---|---|
| 1 | @ambers/lang |
0.31.0 | — |
| 2 | @ambers/sdk |
0.13.0 | — (tooling; the siblings' devDependencies say ^0.13.0) |
| 3 | domite |
0.10.0 | lang |
| 3 | contrib-jquery |
0.8.0 | lang |
| 4 | contrib-web |
0.9.0 | contrib-jquery, lang |
| 5 | helios |
0.14.0 | contrib-web, lang |
| 5 | contrib-legacy |
0.11.0 | contrib-web, lang |
| 5 | silk |
0.7.0 | domite, lang |
| 6 | prof-stef |
0.4.0 | contrib-legacy, contrib-web, lang |
| 7 | @ambers/grunt-init-amber-project |
0.31.0 | scaffolds all of the above |
| 8 | @ambers/cli |
0.108.0 | scaffold, sdk, lang |
Release notes: none of the seven has ever had a CHANGELOG file. In 125 release commits the one breaking release that was noted, contrib-jquery's 0.7.0, put the note in the commit body ("Moving jQuery to >= 2 may be a breaking change."), so each version commit above carries its note the same way: the engine floor, the packages that share it, and the polyfill no longer shipped (Helios: the preambles too).
Known and accepted: the devDependencies form cycles (contrib-jquery's dev setup wants
helios and contrib-legacy, which depend on contrib-web, which depends on contrib-jquery),
so a fresh npm install of a sibling's development setup only resolves once the whole
round is published. Left as they were: sdk's "amber": {"lang": ">0.22.6"} note, a
compatibility claim rather than a floor, and @ambers/ide-starter-modal, which declared
nothing.
What the siblings' Node test tasks can and cannot verify, stated as found: grunt test
is red in six of the seven exactly as it is on their master — document is not
defined in contrib-legacy, helios and prof-stef (DOM-touching code bundled into the Node
runner), every test erroring in domite (20) and silk (45) (DOM tests without a DOM), and
Cannot read properties of undefined (reading 'localMethods') in contrib-web; contrib-
jquery has no test packages. None of it changed with the branches; the runners build
through the new wrapper in all seven, which is what could be checked.
amber-compat-*: mark deprecated on npm; nothing in the round depends on them.localMethods failure is the one that is not simply
"DOM in Node"..gitattributes: with core.autocrlf=true every commit warns "LF will be replaced
by CRLF" and each recompile shows phantom modifications; * text=auto eol=lf would
end both.NodeTestRunner prints only a failing test's name, not the assertion text.Platform-Node.st:12 still answers global; globalThis would match 0.30.0's
intent. Optional.