Skip to content

Latest commit

 

History

History
121 lines (95 loc) · 6.05 KB

v0.3.0-notes.md

File metadata and controls

121 lines (95 loc) · 6.05 KB

One Runtime

Foreman v0.3.0

Status: released. The four exit predicates were measured on the commit recorded in the table below; this commit adds documentation only and carries its own green gates-linux.

v0.3.0 is one sentence: the Node migration is finished — one runtime, one language.

Product

Foreman's own Python is gone. git ls-files '*.py' returns seven files: four vendored scrapling templates, one vendored scrapling test, one vendored superpowers token-usage utility, and one archived schema checker under openspec/changes/archive/. None of them is Foreman's.

Three subsystems moved to Node.js 24 and TypeScript in this release.

The session store. skills/foreman/scripts/fm-session.py was 1090 lines across four tables — facts, measurements, obligations, sessions. It is now packages/orchestration/src/fm-session-main.ts, bundled behind a thin adapter. tests/session.bats drives the CLI through FM_SESSION_CMD and passes 29/29 against the bundle. Point that variable at a command that does not exist and all 29 fail, which is how we know the suite is exercising the bundle and not something else.

The Tier 2 evaluator. tests/tier2_compare.py computed percentiles and bootstrap confidence intervals. The port reproduces Python's output byte for byte, which required porting MT19937 including its SHA-512 string seeding, and Python 3.12's compensated (Neumaier) float summation — naive addition deviates at the sixteenth decimal, which is enough to move a confidence bound.

Three docs/research/ utilities are retired rather than ported.

The six verified defects

§W2 of the design doc listed six defects found by review agents that ran the code. All six are fixed in this release.

Defect Landed by
Unguarded recursion in canonical-json.ts threw a raw RangeError a744e9f
POSIX backslash path-confusion, three sites 4c12622
argvWithoutDetach corrupted re-exec argv a744e9f
decodeUtf8Fatal stripped a BOM, so digest and text disagreed a744e9f
Unthrottled spawn fallback discarded the measured vendor caps a744e9f
Six set*RaceHook functions reached the published surface d74600e

The path-confusion one is worth its own paragraph, because it is the defect this release nearly shipped. On POSIX a backslash is a legal filename character, so a normalizer that strips a trailing separator turned /tmp/x\ into /tmp/x — a caller could present a path that compares equal to one directory and denotes another, inside credential-authority comparison. It existed in three copies. Two of them were reported fixed earlier in the release run and were not; measurement on the release candidate found all three still present.

The fix deletes the strip rather than gating it on Windows. resolve() already removes a trailing separator for the platform's own path flavour and preserves roots, so the strip was dead code for legitimate input, and its only live effects were bugs: the POSIX corruption above, and on Windows turning the root C:\ into C:, which isAbsolute rejects as drive-relative. The originally planned platform gate would have preserved the second one.

Exit predicates

Four predicates on one unchanged pushed commit. The table in ROADMAP.md carries the measured verdicts and the commit they were taken against.

Predicate 2 was rewritten during the release. It previously also required a green gates-windows that ran the Bats suite. That suite was then measured on Windows for the first time at pass=444 fail=270 skip=26 and does not fit the 60-minute job cap, so Windows is excluded by decision rather than by omission — and the exclusion is enforced by a test: re-adding a gating trigger to the Windows workflow fails hosted-node24-ci.test.ts. Both polarities were demonstrated before that change landed.

What this release does not do

Windows is not a gating platform and the Bats suite has never passed there. The absent flock alone accounts for 134 of the 270 failures. Recorded as BW-004.

Sprints 8 through 13 and 16, Sprint 6's project registry, and the knowledge and graph plane move to v0.4.0. Their change packages are unmodified; only their release assignment moved.

brokenwindows.md carries the open register. It grew during this release rather than shrinking, which is the intended behaviour of a log for breakage that is known, undecided and unassigned.

Notes on the work

Two Tier 2 ports were rejected before the third succeeded. The first passed all 27 tests in its oracle and was still not equivalent: whole-valued floats lost their decimals and a bootstrap confidence interval landed 16% from Python's on identical input. The second shipped a string sentinel into output. Neither was caught, because that suite asserts exit codes and shapes and no statistical value.

The fix was not a better implementer. It was tests/tier2-golden.bats, which freezes Python's exact output and diffs against it. The third port was mechanical once the oracle could see what mattered.

The same shape appeared twice more. In the session port, three project tests and two white-box Python tests retired with their subject, and their properties — worktree store sharing, single-snapshot sidecar reads, and row-check-after-write-lock — were replaced rather than dropped, because a cold review refused to let concurrency invariants retire uncovered. And in the path-confusion fix, a cross-vendor audit found that the new tests used a bare return on Windows, which node:test reports as a pass with zero assertions, and that the black-box test asserted only that a scan had not refused rather than which directory it had walked. Both were reworked before the merge; the stronger test plants a secret in the sibling directory the old normalizer collapsed onto, so a clean result can only mean the scan bound to the tree it was handed.

The recurring lesson of this release is that the oracle is usually the defect. Five separate "it passed" reports in the release run were false, and every one of them was caught by a check that could discriminate — never by a more careful reading of the report.