Skip to content

Commit 3427d38

Browse files
authored
Merge pull request #320 from metaobjectsdev/chore/changelog-0.24.0
docs(changelog): the next cut is 0.24.0, and it absorbs the unreleased 0.23.3
2 parents 5a1250e + cb40ee0 commit 3427d38

1 file changed

Lines changed: 60 additions & 10 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
77

88
## [Unreleased]
99

10+
## [0.24.0] — npm `0.24.0` · PyPI `0.24.0` · NuGet `0.24.0` · Maven `7.24.0`
11+
12+
A coordinated **MINOR** across all four registries. It is a MINOR rather than a PATCH
13+
because two of its changes are DEFAULT FLIPS, not corrections of previously-wrong
14+
behaviour: the Java Maven plugin now fails a build that a silently-empty model used to
15+
let pass, and Java and Python now follow symlinked directories where they previously did
16+
not. Pre-1.0, `^0.23.x` resolves `<0.24.0`, so a MINOR is adopted deliberately while a
17+
PATCH would be taken automatically on a routine update — the same call, for the same
18+
reason, as `0.21.0`.
19+
1020
### Added — `sources` is read by all four CLI surfaces, plus `meta init --config-only`
1121

1222
`.metaobjects/config.json`'s `sources` key stops being a Node-only concern. Adopter
@@ -51,8 +61,21 @@ guide: [`docs/features/metadata-sources.md`](docs/features/metadata-sources.md).
5161
including when a declared `sources` path is itself a symlink, or a symlink
5262
sits partway through a walked tree. TypeScript and C# already did; Java and
5363
Python now match (a symlinked `sources` path previously resolved to zero
54-
files in Java, silently, exit 0). A symlink cycle is a loud error rather
55-
than a hang. Gated by two new `symlinks`-bearing corpus cases.
64+
files in Java, silently, exit 0). A symlink CYCLE is a loud error in every
65+
port. Gated by three new `symlinks`-bearing corpus cases.
66+
67+
That last sentence was written before it was true, and the gap is worth
68+
recording because "a loud error rather than a hang" understated what C# did.
69+
`Directory.EnumerateFiles(dir, "*", AllDirectories)` follows symlinks but has
70+
no loop guard, and its `EnumerationOptions` default of `IgnoreInaccessible`
71+
SWALLOWS the kernel's own ELOOP refusal — so a self-referential directory
72+
symlink neither hung nor threw. It **completed normally, returning ~40 copies
73+
of one real file** at ever-deeper phantom paths, and because source
74+
de-duplication keys on the LEXICAL path every phantom was admitted as its own
75+
source, loading the same metadata once per level. C# now walks with a
76+
per-branch real-ancestor guard and raises on revisit, matching the three ports
77+
that already did. The claim is now carried by a corpus case
78+
(`a-symlink-cycle-is-an-error`) rather than by prose.
5679
- **Behavior change (Java/Maven only): a `<loader>` naming neither
5780
`<sourceDir>` nor `<sources>`, with no `.metaobjects/config.json` `sources`
5881
and no default `metaobjects/` directory, now FAILS the build**
@@ -209,6 +232,23 @@ asserts its target equals the configured registry, checks it against a deny-list
209232
public registries, **parses `bun publish --dry-run`** rather than trusting bun, and runs with
210233
`HOME` redirected so a fall-back has no credential to use.
211234

235+
### Fixed — `meta init --print-only` wrote the files it was previewing
236+
237+
`--print-only` is documented as "print what would be written, don't write". It honoured
238+
that on the full scaffold, and — since the fix that moved `--config-only` below the
239+
guard — on `--config-only`. The two agent-context paths, **`--docs-only` and
240+
`--refresh-docs`**, return from `init()` ABOVE that guard and were missed, so both
241+
documented dry runs scaffolded for real: the docs, every stack-scoped skill reference,
242+
the manifest, and, with `--wire-root`, a newly created root `CLAUDE.md`.
243+
244+
The guard now sits at the I/O rather than at the report. `writeAgentContext` already
245+
computes the complete plan before performing a single write, so a dry run reports
246+
exactly the set a real run would touch, with no second hardcoded list to drift out of
247+
step. Reporting is future-tense under a dry run: the old code announced `wired
248+
@.metaobjects/AGENTS.md into CLAUDE.md` and `refreshed version written to <path>.new`
249+
for edits it had not made — a side effect on a file you own, which you could go looking
250+
for and never find.
251+
212252
### Fixed — `scripts/release.mjs` preflighted only one package
213253

214254
The target-version check ran `npm view @metaobjectsdev/cli@<version>` and nothing else, so a
@@ -266,11 +306,19 @@ the same migrations. Three changes are visible even to that project. Adopter gui
266306
naming the target it cannot find, never a half-resolved model — and the
267307
replacement is an explicit `{ "path": "../shared-model/metaobjects" }` source,
268308
which works in any layout and needs no topological ordering.
269-
- **`.metaobjects/config.json` rejects unknown keys.** `ConfigSchema` is `.strict()`
270-
at every level, so a key that was previously stripped in silence is now a load
271-
error naming the key. Silently dropping a key means the setting you wrote does not
272-
exist: `{ "migrate": { "scopee": [...] } }` used to mean *unscoped*, governing
273-
every table in a database you were trying to share.
309+
- **`.metaobjects/config.json` rejects unknown keys — in the Node CLI only, and that
310+
asymmetry is deliberate.** `ConfigSchema` is `.strict()` at every level, so a key
311+
that was previously stripped in silence is now a load error naming the key. Silently
312+
dropping a key means the setting you wrote does not exist: `{ "migrate": { "scopee":
313+
[...] } }` used to mean *unscoped*, governing every table in a database you were
314+
trying to share. The C#, Python and Java CLIs read the neutral subset and IGNORE an
315+
unknown key, so the same config loads there and fails here. That is intended and now
316+
ruled: this file is TypeScript's, and TypeScript is the only port that models its
317+
whole vocabulary — so it is the only one that CAN tell a typo from a key a sibling
318+
owns. A partial reader could imitate strictness only by carrying TypeScript's key
319+
list in lockstep, at which point a port one release behind would reject a config a
320+
newer `meta` had just written. Consequence to plan for: a config written by a NEWER
321+
`meta` hard-fails an OLDER one, which is what `schema_version` is for.
274322
- **`ExpectedView.fqn` is required.** On the public `@metaobjectsdev/codegen-ts`
275323
export, the declaring object's fully-qualified name is no longer optional —
276324
`migrate.scope` decides ownership on that name, and a view arriving without one
@@ -302,10 +350,12 @@ the same migrations. Three changes are visible even to that project. Adopter gui
302350
it a config: `meta init` writes one, and a `"sources": []` config is enough to
303351
claim the directory and take the default.
304352

305-
## [0.23.3] — npm `0.23.3` · PyPI `0.23.3` · NuGet `0.23.3` · Maven `7.23.3`
353+
### Fixed — `meta gen` silently destroyed hand edits (was drafted as `0.23.3`)
306354

307-
A coordinated **PATCH** across all four registries, and every one of them carries a real
308-
changed product file — the same defect had to be fixed four times, once per write path.
355+
Drafted as a standalone `0.23.3` PATCH and never released — no registry ever carried
356+
`0.23.3`. It ships here instead, because the `sources` work above forces this cut to a
357+
MINOR and a release cannot be two versions at once. Every registry carries a real changed
358+
product file for it: the same defect had to be fixed four times, once per write path.
309359

310360
**`meta gen` was silently destroying hand edits, and the case it happened in was the
311361
normal one.** A generated file that existed, differed from fresh output, and had no

0 commit comments

Comments
 (0)