refactor!: ADR 0017 — retire the "species"/"reactant" vocabulary for standard Petri-net terms - #25
Open
thevolatilebit wants to merge 8 commits into
Open
refactor!: ADR 0017 — retire the "species"/"reactant" vocabulary for standard Petri-net terms#25thevolatilebit wants to merge 8 commits into
thevolatilebit wants to merge 8 commits into
Conversation
…lary Drafts the second half of the ADR 0015 naming debt. 0015 renamed the ACSets-lineage store surface but deliberately scoped `species`/`reactant` and the JSON keys out; nothing downstream needs Catalyst-compatible names anymore (ADR 0003 dropped the dep, its Phase-3 interop view was rejected), and the newer layers already speak Petri — `marking` in ADR 0007 and checkpoint.jl, `MarkingPlot` in analysis.jl, `arc` in visualize.jl — so the engine currently carries two vocabularies for one concept. Recommends the full rename (place / marking / arc) behind one-release shims, with the JSON key rename staged separately behind an open question about saved models in the wild. KEEPS `token`: it is the canonical Petri word, and the language-model confusion is a one-sentence gloss, not a rename. Records the load-bearing constraint that joins.jl:33 and equalize.jl:58 filter columns by the literal substring "spec", so the column rename must be atomic with them. The appendix carries the durable artifact: the RD→Petri term dictionary (place/colour set/arc weight/preset/firing rate/k-server/firing duration/ read arc/self-loop/continuous transition/P-invariant/QPN), which also tells a reader which literature answers a question about the engine. Draft only — no code has moved. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> (cherry picked from commit 99c202247689265ba56a05b11b7aae495b31f5cd)
…* -> place*
The nine `:S` (place) column symbols move to Petri vocabulary in one atomic
change, per ADR 0017 Tier 2:
specName -> placeName specReward -> placeReward
specModality -> placeModality specStructured -> placeStructured
specInitVal -> placeInitVal specRole -> placeRole
specCost -> placeCost specInitUncertainty -> placeInitUncertainty
specValuation -> placeValuation
The `const SCHEMA` object symbol `:S` is unchanged (`:P` is taken by the
parameter object, and `:S` reads as *places* under either vocabulary), and
the declaration ORDER of the columns is preserved, so `ALLATTRS` and every
`propertynames(net.columns)` reflection loop iterate exactly as before.
Atomic with the rename, because they are substring reflection over column
names and would otherwise silently stop matching any place column:
* `src/operators/joins.jl:33` occursin("spec", …) -> occursin("place", …)
* `src/operators/equalize.jl:58` occursin("spec", …) -> occursin("place", …)
* `src/interface/update.jl:191` Symbol(:spec, uppercasefirst(…))
-> Symbol(:place, …) (the @cost/@reward/
@valuation macros CONSTRUCT their target
column symbol from a `:spec` prefix; not
reachable by grepping for the old names)
`src/compilers.jl:188` filters on the substring "Name", which `placeName`
still satisfies — unchanged deliberately.
No wire-format change: the JSON keys in `src/serialize.jl` / `src/export.jl`
are hardcoded string literals ("name"/"init"/"cost"/… and the top-level
"species"/"reactants" arrays), never derived from a column symbol, so the
serialized bytes are identical. The key rename is ADR 0017 Tier 3 and lands
as its own final commit.
Suite: 801 pass / 0 fail / 0 broken — identical to the pre-change baseline.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…keep one-release shims The public surface adopts the Petri-net vocabulary. Six exported names move: @add_species -> @add_place (src/interface/update.jl) SetSpecies -> SetMarking (src/actions.jl) ReactantSpec -> ArcSpec (src/ReactiveDynamics.jl) reactant_specs -> arcs (src/ReactiveDynamics.jl) specname -> placename (src/ReactiveDynamics.jl) register_structured_species! -> register_token_kind! (src/interface/agents.jl) `MarkingPlot` keeps its name (already correct) and loses "species" from its docstring. Every old name survives ONE release as a shim, in a single clearly-delimited block at the end of `src/ReactiveDynamics.jl` (after the includes, because three of the new names are defined in included files) — `Base.@deprecate_binding` for the two types, `@deprecate` for the three functions, and a hand-written `@add_species` macro that depwarns and splices the call through to `@add_place`. That block is deliberately the only place in `src/` where the retired spellings survive, so the rename's grep gate can assert exactly that. Following ADR 0015, the shims are exported (source compatibility preserved); note that on Julia 1.12 `@deprecate_binding` no longer warns at the use site — it only hides the alias from `names()` — which is pre-existing behaviour shared with the ADR-0015 `ReactionNetworkSchema` shim, not something introduced here. Wire format is untouched: `stmt_to_dict(::SetMarking)` still emits `"verb" => "set_species"` and `ACTION_VERBS` still carries `:set_species`. That mismatch is staged, not an oversight — serialized keys are Tier 3 and land as their own commit so the file format can be reverted independently — and both sites now carry an explicit comment saying so. Call sites swept across src/, test/, ext/, demo/, docs/, spec/ (ADRs 0001-0016 and spec/history/ left alone: append-only). `populate_reactant_specs!` is internal and moves in Tier 5; CONTRACT's `add_species!` prose moves in Tier 4. Suite 806 pass / 0 fail / 0 broken (baseline 801/0/0). The +5 is mechanical: the `exports_resolve.jl` guard asserts one test per exported symbol, and four of the six shims are visible to `names()` (the two `@deprecate_binding` consts are flagged deprecated and hidden), plus one extra assertion in the exported-macro loop. No test added, skipped or pinned. `julia -m Runic --check .` clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…and code prose
The mechanical body of the Petri-net vocabulary rename: every Julia-level
identifier and every comment/docstring that still said "species" or "reactant"
now says "place" or "arc". No wire key, no serialized verb tag and no
diagnostic path string moves here — those are Tier 3 and land last, as their
own revertible commit.
Struct fields (renamed with no shim, the ADR 0015 precedent for fields):
ReactionNetwork.reactants -> .arcs
ArcSpec.species -> .place (the :S foreign key)
FoldedArc.species -> .place
UnfoldedArc.species -> .place
BaseStructuredToken.species-> .place (a token's current place)
PopulationEntry.species -> .place
ProgramLedger.species -> .place
NetworkGraph.species -> .places
StateDump.tokens NamedTuple key species -> place
_PROTOCOL_FIELDS :species -> :place (must track the token field)
Internal functions: get_species/set_species! -> get_place/set_place!,
populate_reactant_specs! -> populate_arcs!, extract_reactants -> extract_arcs,
recursively_find_reactants! -> recursively_find_arcs!, _static_reactants ->
_static_arcs, _reactant_atom -> _arc_atom, _reactants_to_dict -> _arcs_to_dict,
_reactant_to_dict -> _arc_to_dict, _reactant_term -> _arc_term,
_emit_macro_reactant! -> _emit_macro_arc!, FoldedReactant(s) -> FoldedArc(s),
UnfoldedReactant -> UnfoldedArc, SpeciesNode -> PlaceNode, _species_sym ->
_place_sym, _species_to_dict -> _place_to_dict, available_species ->
available_places, known_species -> known_places, highlight_species ->
highlight_places, boundary_species -> boundary_places, free_blocked_species! ->
free_blocked_places!, rhs_species/lhs_species -> rhs_places/lhs_places,
species_modalities -> place_modalities. The dead `struct Reactant`
(interface/create.jl) became `ArcTerm`, not `Arc`, because visualize.jl already
owns a live `struct Arc`.
Three of these were never exported but are reached by name anyway
(`using ReactiveDynamics: get_species` appears across the demos, and
`populate_reactant_specs!` is named in the ArcSpec docstring), so they get
one-release `@deprecate ... false` shims alongside the Tier 1 shims.
`@aka` now spells the :S object `place` (`alias_default[:S]`), and a three-line
`_AKA_LEGACY_NAMES` selector keeps `@aka net species = resource` targeting :S
for one release — without it that form would have silently produced
`alias_nothing` metadata rather than erroring.
WHAT DELIBERATELY DID NOT MOVE (all Tier 3):
* the serialized verb tag `:set_species` / `"set_species"` of `SetMarking`;
* the JSON keys `"species"` and `"reactants"`, and the `NodeRef` kind value
`:species` in REF_KINDS;
* `validate`'s diagnostic path strings (`reactants[$i].*`, `species[$i].*`);
* the `@select`/`@advance` DSL field name `:species`;
* the `token_trajectory` and `program_ledger` DataFrame column `:species`,
which is exported to CSV/Arrow;
* `export_run`'s manifest and token-record `"species"` keys.
Comments in serialize.jl/export.jl that NAME a wire array still say `species[]`
and `reactants[]` so the prose stays true to the bytes until Tier 3 flips both
together.
ONE OBSERVABLE-OUTPUT CHANGE, called out rather than hidden: a `@join`
identification block with no explicit `:alias` now generates the merged place
name `shared_place_N` instead of `shared_species_N` (operators/joins.jl). It is
a generated NAME, not a format key, so previously-serialized documents are
unaffected (place names are data, read back verbatim) and nothing in the suite,
demos or fixtures pins the old spelling. It can reorder `observables(::Ensemble‑
Problem)` for such a model, since that list is name-sorted.
demo/** and docs/literate/** are swept here too, because their code has to
compile against the renamed fields; their PROSE gets the two-register treatment
(tutorials say "resource pool") in Tier 4. spec/** prose is Tier 4.
One LATENT BUG surfaced and is fixed here: `_validate_node!`'s place-pool branch
(`kind === :species ? places : …`) is reached by every document containing a
`ref` node of kind `species`, yet NO test in the suite exercised it — the only
`ref` in the E7 fixture is a param — so a mismatched identifier there threw
`UndefVarError` on real documents while all 806 tests stayed green. Fixed, and
pinned with two new assertions in E7 that validate a place-kind ref both
resolving and dangling.
Suite: 808 pass / 0 fail / 0 broken (806 at Tier 1, +2 for that new pin).
Runic clean. Wire round-trip of demo/bd_acquisition/model.rdj.json still emits
the top-level keys
["meta","params","rd_format","reactants","species","transitions","version"].
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…rose Tier 4 of the ADR 0017 migration plan: the prose layer. The code moved in the three preceding commits; this one makes every human-readable artifact agree with it, and adds the two glossaries the ADR mandates. Spec (living normative documents; ADRs 0001-0016 are append-only and keep their original wording): - spec/CONTRACT_DRAFT.md — amended in place through §1-§15: place/marking/arc throughout, plus a new top-level **Glossary** carrying ADR 0017's term dictionary (which Petri-net family answers which question about the engine), the token-vs-language-model disambiguation, the retired-name table, and the two-register rule. Also corrects code names the rename moved: free_blocked_species! -> free_blocked_places!, extract_reactants -> extract_arcs, species_modalities -> place_modalities, add_species! -> add_place!, set_species! -> set_place!, get_species -> get_place, ArcSpec.species -> ArcSpec.place, and §7.2/J3's now-stale claim that the join reflection loop filters the substring "spec" (it filters "place"). - spec/INVENTORY.md — current-source map resynced (store field .arcs, the ArcSpec record, populate_arcs!, the ":S places" object, the "place"/"trans" reflection loops). - spec/STATUS.md, spec/DOCS_CHARTER.md, spec/PR_DRAFT.md, spec/adr/README.md, CLAUDE.md — vocabulary resynced. Docs site: - NEW docs/src/glossary.md, wired into docs/make.jl as a top-level nav page: core vocabulary, the literature-mapping table, the renamed-in-v0.3 table (every @ref target has a @docs entry), the two-register rule, and the sentence disambiguating a Petri-net token from a language-model token. - docs/src/index.md, readme.md and the reference pages adopt the register the ADR asks for: tutorial and case-study prose says "resource pool", glossed once at first use as "a place, in Petri-net terms"; the API reference and the spec say place/marking/arc. - docs/src/reference/json_schema.md gains an explicit admonition that the WIRE keys still read species[]/reactants[]/set_species, so the page does not look like an oversight before the Tier 3 commit lands. Demos: prose in demo/** resynced (the demo tours are the most-read runnable code, so the ADR calls their rename the highest-value part of Tier 4). Also folded in here, as Tier 5 stragglers the earlier word-boundary sweep could not see (they are underscore-joined or single-letter, so \bspecies\b never matched): species_ixs -> place_ixs (operators/equalize.jl), species_from/species_to -> place_from/place_to (solvers.jl @Move), plain_species -> plain_place, the `sp` locals -> `pl` across serialize.jl / visualize.jl / ledger.jl / interface/agents.jl / operators/refine.jl, and "Species record" / "Species trajectories" comment prose. NB ledger.jl's attribute_valuation! and agents.jl's add_structured_token! were left half-renamed by the Tier 5 commit (`pl = get_place(...)` then `sp === nothing`) — those would have been UndefVarErrors on an uncovered path; both are fixed here. Wire-bound strings are deliberately untouched and still read species[] / reactants[] / set_species / Ref{species} / population[].species — they move in the final Tier 3 commit. Suite: 808 pass / 0 fail / 0 broken (unchanged). Runic clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…t the draft The ADR was a draft written before any code moved, so implementing it turned up things it got wrong. Corrected in place, with the wrong figure kept visible next to the right one where a reader might have quoted it: - Evidence table: `docs/src/` was never 97 — that is the `docs/src/` + `docs/literate/` total, double-counted (31 + 66). `spec/` reads 411 on the branch base, not 438, because ADR 0016 and the deck are not on `main`. Re-measured with a command that works; the drafted 448/177/154/66 hold. - Tier 1: `@add_species` lives in `src/interface/update.jl:3,243`, not `create.jl`. `ReactantSpec` is at `:135`, `reactant_specs` at `:183`, the shim pattern at `:172,445-453`. - Tier 2: `specCost` is 21 sites, not 20 (the 206 total is right), and the draft missed `src/interface/update.jl:191`, where the column symbol is CONSTRUCTED — `Symbol(:spec, uppercasefirst(…))` from `@cost`/`@reward`/ `@valuation`. Missing it breaks those three macros with no compile error. - Tier 1b, new: the unexported names the grep gate forced (`get_species`, `set_species!`, `populate_reactant_specs!`), the six struct fields that moved with no shim, and `@aka`'s `:S => :species` legacy alias. - Tier 3, rewritten: the draft's "16 sites" undercounts the wire surface, and its own mandate to emit `arcs[$i].place` diagnostics is incoherent unless the array those paths index is renamed too. The full table now names all eleven wire-visible items, including the ones it omitted (`"reactants"`, the per-arc and population `"species"` field, `REF_KINDS`, both `src/export.jl` keys, the two result-frame columns, the `@select`/`@advance` field). - Tier 5: records the trap that cost the most here — `\bspecies\b` cannot see `species_ixs` or `free_blocked_species`, because `_` is a word character. Per the maintainer's 2026-08-22 resolution (no saved models outside this repository), Tier 3 drops the permanent read alias the draft proposed: the writer emits only new keys, the reader takes the legacy spellings for ONE release with a depwarn, and both shim sets retire together. Consequences drops the forward/backward-asymmetry worry for the same reason, and gains the one observable output change of the whole rename — an aliasless `@join` block now generates `shared_place_N`, not `shared_species_N`. The README status table gains a vocabulary-lineage note, so a reader of ADRs 0001–0015 knows to read `species` as *place*. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…trings Three leftovers the word-boundary sweep could not see. `specmap` is the rename map both composition operators build (`@join`'s `X -> parent__X`, `equalize!`'s alias collapse) — a lowercase `spec` glued to `map`, so it is invisible to `\bspecies\b` AND to the case-sensitive `spec[A-Z]` gate. It is a map of PLACE names, so: `placemap`. Local variables and one function parameter; no caller outside these two files. The AA coupling docstrings still shouted SPECIES at the reader in the two places that describe what `observables`/`getobservable` expose. A place's exported value is its marking, so that is what it now says. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… the retired ones for one release
The vocabulary rename reaches the wire format last and on its own commit, so a
document written against the previous release is a single, isolated diff to
bisect against. The writer now emits only the Petri-net spellings; the loader
still accepts every retired one for ONE release, with a deprecation warning.
Renamed on the wire (`species` → `place` throughout):
- the top-level arrays `species[]` → `places[]` and `reactants[]` → `arcs[]`
- an arc's place key `species` → `place`
- a `population[]` entry's `species` → `place`
- a `ref` node's kind value `"species"` → `"place"` (`REF_KINDS`)
- the marking-write action verb `set_species` → `set_marking`
- the export-bundle manifest key `species` → `places`, and a per-token
trajectory record's `species` → `place` (CONTRACT §14.3)
- the result-frame / ledger `DataFrame` column `:species` → `:place` (§14.1)
The read shim is three small helpers in `src/serialize.jl` — `_legacy_key`,
`_legacy_path` and `_ref_kind` — plus a legacy branch in `stmt_from_dict` and
`_LEGACY_ACTION_VERBS` in `src/actions.jl`. `validate` reports its diagnostic
paths in whichever spelling the document actually uses, so a legacy document's
diagnostics still point at real keys. `Base.depwarn` is `maxlog = 1` per call
site and a no-op unless `--depwarn=yes`, which is the same contract the Tier-1
name shims carry: one warning per session, not one per key.
Two aliases are accepted SILENTLY rather than with a warning, because both are
read inside the step loop and a `depwarn` there would fire once per token per
tick: the `@select`/`@advance` field name `:species` (`src/predicates.jl`) and
the `SetField` target in `src/solvers.jl`.
Also regenerated the one on-disk fixture (`demo/bd_acquisition/model.rdj.json`)
and reframed the former legacy-key test as an explicit deprecation test that
loads a retired-key document, loads its fully-renamed twin, and asserts the two
simulate to an identical `sol` — then that re-exporting the legacy one emits
only the new keys. That test branches on `Base.JLOptions().depwarn` so it is
correct under `--depwarn=no|yes|error`.
Suite 821 pass / 0 fail / 0 broken / 0 skipped (801 at the branch base
`c671875`; +13 here are the new deprecation testset, +7 landed with Tier 5).
Runic clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A resource pool in this engine was called a species — chemistry's word, in a tool whose own front page opens by denying it is a chemical reaction network — while the newer layers already said marking, arc and
MarkingPlot. This PR retires the inherited chemical-reaction-network vocabulary for the standard Petri-net terms. The specification isspec/adr/0017-petri-net-vocabulary.md, which is the first commit on this branch (f623856) — read it for the full argument, the options considered, and the RD→Petri term dictionary in its appendix.This is a pure rename. No semantics, no numerics, no allocator behaviour, no wire-format meaning beyond key spelling. The one observable-output change is called out under Behavioural notes below.
What changed, per tier
One commit per tier, in migration-plan order, suite green at each:
f623856adaa0ed:Sstore column symbolsspec*→place*(specName/specModality/specCost/specValuation/specInitVal/specReward/specStructured/specRole/specInitUncertainty), landed atomically with the twooccursin("spec", string(attr))reflection filters insrc/operators/joins.jlandsrc/operators/equalize.jlthat select those columns by name prefix. Splitting those apart would have silently broken@join/equalize!.ebf648cfdbe572,eb8cd05ArcSpec.species→.place,ReactionNetwork.reactants→.arcs) and code prose. No shims for struct fields, following the ADR 0015 precedent.aeb7a61spec/CONTRACT_DRAFT.md(amended in place, plus a new Glossary carrying ADR 0017's term dictionary),spec/INVENTORY.md,spec/STATUS.md,docs/src/**,docs/literate/**,demo/**. Newdocs/src/glossary.mdpage.49aa788Status:→Accepted + Implemented, and itsspec/adr/README.mdrow, in ADR 0015's header style. Corrects three things the draft got wrong (see below).43384f7SCHEMA's:Sobject symbol is unchanged (:Pis already the parameter object), and the words token and transition are unchanged — they were already canonical Petri vocabulary.Tier 1 — exported names
Every retired name resolves for one release as a
@deprecate/@deprecate_bindingshim in the single block atsrc/ReactiveDynamics.jl:488-524, following the pattern ADR 0015 established.@add_species@add_placeSetSpeciesSetMarkingReactantSpecArcSpecreactant_specsarcsspecnameplacenameregister_structured_species!register_token_kind!get_species/set_species!get_place/set_place!populate_reactant_specs!populate_arcs!MarkingPlotkeeps its name — it was already correct.Tier 3 — serialized keys
The writer emits only the new spellings; the loader accepts every retired one for one release with a deprecation warning, and
validatereports its diagnostic paths in whichever spelling the document actually uses (so a legacy document's diagnostics still point at real keys). Re-exporting migrates a document."species"array"places""reactants"array"arcs""species""place"population[]entry's"species""place""set_species""set_marking"refnode's"kind": "species""kind": "place""species""places""species""place"DataFramecolumn:species:place@select/@advancefield:species:placeThe read shim is three helpers in
src/serialize.jl(_legacy_key,_legacy_path,_ref_kind), a legacy branch instmt_from_dict, and_LEGACY_ACTION_VERBSinsrc/actions.jl.Two aliases are accepted silently rather than with a warning: the
@select/@advancefield name (src/predicates.jl) and theSetFieldtarget (src/solvers.jl). Both are read inside the step loop, where adepwarnwould fire once per token per tick.On the warning's reach:
Base.depwarnismaxlog = 1per call site and a no-op unless Julia runs with--depwarn=yes. A user therefore sees one warning per session, not one per key — the same contract the Tier-1 name shims already carry. Anyone wanting these to be hard errors can run--depwarn=error.Behavioural notes
The rename is behaviour-preserving with exactly one observable-output exception, disclosed for completeness:
@joinblock now names its generated observableshared_place_Ninstead ofshared_species_N(src/operators/joins.jl). No test, demo, or fixture pins that name, but it is a user-visible string and it can reorder the name-sortedobservableslist for a model that both uses an aliasless@joinand reads observables positionally.Nothing else changes: no allocator behaviour, no RNG stream, no numeric result. The BD acquisition demo reproduces its previous numbers.
Deliberately NOT in this PR
spec/adr/README.mdgains a Vocabulary lineage paragraph naming ADR 0017 as the boundary and pointing at the term dictionary as the translation table.spec/adr/README.mdstill lists the three CONTRACT §1.4 modality validators as@test_skipplaceholders (they landed in53d1fac), and CONTRACT §6.2/§7.5 cite a live-mutation APIadd_place!/add_transition!/add_param!that does not exist insrc/.demo/core_engine_tour/core_engine_tour.jl§3d deliberately constructs the@rate+cycletime == 0foot-gun, which53d1facturned into a construction-timeArgumentError; the script has been unrunnable past §3d since. Verified identical at this branch's base (base package, base demo file, same transitionr0, same error) — it is not caused by this PR, and fixing it would smuggle an unrelated semantic change into a rename..github/workflows/untouched.The two documentation registers
Deliberate, and please do not "fix" it in review:
Both registers describe one object; nothing in the engine distinguishes them. The new
docs/src/glossary.mdstates the rule, carries the term dictionary and the RD→Petri-literature mapping, and disambiguates token (a discrete unit of resource in a place) from the language-model sense.Verification
All output below is real, captured on
43384f7.Suite —
julia --project=. -e 'using Pkg; Pkg.test()':821 pass / 0 fail / 0 broken / 0 skipped, against 801 at the branch base
c671875. The +20 are new regression pins, not relaxations: +7 for the_validate_node!place-pool branch the rename exposed as uncovered, and +13 for the new retired-key deprecation testset. No@test_skipand no@test_brokenwere added.The deprecation read-shim is observable in that run (
Pkg.test()runs with--depwarn=yes):Formatter —
julia -m Runic --check .: no output, exit 0.Grep gate. Three families, because
_is a word character (so\bis blind toset_species) andspecmatchesspecified/inspection/thespec/directory (so the prefix gate must be case-sensitive):\b(species|reactant|reactants|reactantspec)\b,-ispec[A-Z], case-sensitive_species|species_|_reactant|reactant_,-iEvery residual hit is deliberate and enumerated — the deprecation-shim block in
src/ReactiveDynamics.jl, the Tier-3 read shim and_LEGACY_ACTION_VERBS,_AKA_LEGACY_NAMES, the retired-key deprecation test, the two "Renamed in v0.3" tables indocs/src/glossary.md, the retired-keys admonition indocs/src/reference/json_schema.md, the CONTRACT Glossary's two retired-names paragraphs, thespec/STATUS.mdandspec/adr/README.mdrows describing this rename, and the append-only ADRs 0001–0016 (excluded by construction). Gate A by file:Docs. The site builds: CI's Documentation job succeeded and deployed a preview at https://Merck.github.io/ReactiveDynamics.jl/previews/PR25/. Independently, every
@docsentry and every code-@reftarget was also cross-checked programmatically against the loaded module: 122 unique@docsentries, 0 unresolved bindings, 0 resolved-but-undocumented, 0 code-@reftargets without a@docsentry, and both new relative links (glossary.md↔reference/json_schema.md) resolve on disk. All 8docs/literate/**sources — the three tutorials, both deep dives, all three case studies — execute to completion locally as well.Demos.
agentic_pipeline,introspection_tour,refinement_tour,aa_integrationandwires_viz_tourall run clean. The BD acquisition demo runs end-to-end (reduced to 6 seeds — the 160-seed grid was skipped as agreed): the renameddemo/bd_acquisition/model.rdj.jsonfixture loads, the per-program ledger carries its:placecolumn, and the ledger reconciliation residual is-2.3e-13.core_engine_touris the one pre-existing failure documented above. All 22 scripts underdemo/anddocs/literate/parse cleanly.CI on this PR (independent of the local run above) — every required check green:
documenter/deploy)continue-on-error: trueinCI.yml); still running when this body was writtenReviewing this
Read
spec/adr/0017-petri-net-vocabulary.mdfirst (commitf623856), then the tiers in order. Tier 2 (adaa0ed) is the one commit where the diff is not self-evidently mechanical — check the two reflection filters against their renamed columns. Tier 3 (43384f7) is the compatibility surface; the deprecation test at the end oftest/semantic/serialization_ir.jlis the executable statement of what a legacy document is still promised.🤖 Generated with Claude Code