Repository navigation
Vocabulary proposal: rename ported_elsewhere → ported_differently #21
Description
Activity
- added a commit that references this issue
on Sep 7, 2026 stevevanhooser commented
on Sep 7, 2026 ContributorAuthorMore actionsDID-python's side is done — landed in VH-Lab/DID-python#67, commit
f372533. All 7 CI checks green. Recording it here so the three repos can be kept in step; NDI-python and NDR-python still carryported_elsewhere.Scope was one entry
The issue estimated DID-python as "TBD". The answer is 1 live entry, not because the repo is small but because it only grew a
statusfield earlier the same day, in the first commit of that same PR. The rename was applied before it merged, soported_elsewherenever reachesmainthere.The one entry is
sqldb, and it argues the issue's case rather than complicating it: MATLAB has an intermediate abstract classdid.implementations.sqldbbetweendatabaseandsqlitedb. Python has no such layer at all — the behaviour is folded intoDatabaseandSQLiteDB. Nothing moved anywhere, so "elsewhere" would send a reader hunting a relocated file that does not exist. That is the same shape as six of NDR-python's nine.All four places from the cost estimate moved in one commit: the entry,
STATUSES, the normative table inPORTING_INSTRUCTIONS.md, andREPLACED_STATUSES.One decision to mirror (or to reject) in the other two
Item 4 asked for
ported_elsewhereinREPLACED_STATUSESso it gets a targeted error. DID-python's carries five names, not one:Retired Message says to write ported_elsewhereported_differentlynot_yet_portedporting_deferrednot_applicablematlab_only/porting_deferred/retired— pick the one you meanimplemented(no status — ported is the default) does_not_existretiredThe last four were retired in NDI-python and were never written in DID-python. They are rejected there anyway, by name, for the reason this issue exists: the vocabulary is shared, the three repos drifted apart once already, and someone arriving from another one should be told the current name rather than merely told no.
not_applicablewas DID-python's own key name until this week, and gets no single replacement because it had none.Whether NDI-python and NDR-python want the same five is a judgement call, not something the issue settled — flagging it so all three end up alike rather than each picking its own set.
Concretely actionable for the NDR side
AGENTS.mdstep 2 still instructs contributors to writestatus: not_yet_portedornot_applicable— both retired in NDI-python. That is upstream of this rename and worth fixing in the same pass, otherwise the repo's own instructions will keep producing values its checker rejects.Guard against the half-finished rename
The issue notes that a partial rename is strictly worse than either name. DID-python binds both tables to the constants they document — the vocabulary table to
STATUSES, and a new "Retired status names" table toREPLACED_STATUSES— and asserts no name is both current and retired. Mutation-tested: reverting the entry, and editing either table without the matching constant, each fail loudly. Equivalent in spirit toTestTheVocabularyIsTheDocumentedOne::test_spec_and_enforcement_agree.
Generated by Claude Code
stevevanhooser commented
on Sep 7, 2026 ContributorAuthorMore actionsStatus: decided, and NDR-python's side is done. The other two repos are still in progress.
Recording this before #22 merges, because merging will auto-close this issue and the closure would otherwise read as "the cross-repo vocabulary question is settled" when only one of the three repos has actually landed.
Repo Entries Status NDR-python 9 ✅ done — #22, all 7 checks green, awaiting merge NDI-python ~98 🔄 in progress DID-python TBD 🔄 in progress Option 1 from the decision list was taken: rename everywhere. NDR-python's change is 6 files — the 9
status:values, thestatus_vocabularykey in the spec (§ 6, with the definition rewritten to lead with manner and to say outright thatpython_pathanswers where), andALLOWED_STATUSES/STATUSES_REQUIRING_PYTHON_PATHin the guard test.ported_elsewherewas retired, not merely deleted — it is inREPLACED_STATUSESand in the spec's retired-values block, so the old spelling fails with a message naming its replacement:use ported_differently -- the label names the manner, not the location, since python_path already answers whereThat matters while the three repos are out of step: an entry pasted from a pre-rename branch, or from a sibling repo that has not landed its rename yet, gets a pointer instead of a bare "not in the vocabulary".
What is still outstanding after this closes
- NDI-python and DID-python have not landed. A partial rename across the three is worse than either name. Merge order does not matter; a repo left behind does.
- NDI-python never received this proposal as an issue of its own. It is the vocabulary's home repo, but it is outside the scope of the session that filed this, so this issue was raised here instead. If the rename needs a record there, it needs a human to carry it across.
- If NDI-python decides against the rename, revert NDR-python's Bridge contract: status vocabulary + file-scoped drift rule (NDI-python#211) #22 rather than leaving the repos diverged.
None of the three blocks merging #22 — they are the reason this closure should not be read as the whole question being answered.
Generated by Claude Code
stevevanhooser commented
on Sep 7, 2026 ContributorAuthorMore actionsCorrection to my previous comment — one of its two "actionable for the NDR side" points was wrong, and I'd rather retract it than leave stale advice for whoever picks this up.
I wrote that
AGENTS.mdstep 2 "still instructs contributors to writestatus: not_yet_portedornot_applicable". That was read from a checkout taken before #19 merged. On currentmain, step 2 names no values at all:If it won't be ported 1:1, still add an entry with a
statusand adecision_logexplaining whySo there is nothing to fix, and no contradiction between NDR-python's instructions and its checker. #19 also already added
REPLACED_STATUSEStotests/test_matlab_bridge_conventions.py— the same mechanism I described as worth adding. Both points were already done before I wrote them.The rest of that comment stands: DID-python's side is landed in DID-python#67, and its scope was one entry.
Two things that survive the correction
1. Naming no values in
AGENTS.mdis the better pattern, and it makes the pending rename cheaper here. Instructions that name specific status values have to be updated in lockstep with the vocabulary, or the repo ends up documenting a value its own CI rejects. NDR-python's step 2 is now immune to that by construction — theported_elsewhere→ported_differentlyrename touches no instruction text at all. Worth preserving when #19's successor lands.2. NDR-python retires
ported; DID-python did not, and now does.REPLACED_STATUSEShere maps"ported"to "no status at all (a plain port is the default)". DID-python already refused an explicitstatus: ported— the value is deliberately absent from its vocabulary tuple — but via the generic "unknown status" branch, which lists the four valid values and leaves the reader to work out that what they wrote is the default and belongs nowhere.Fixed in DID-python#67 (
f244f2f), matching NDR-python's wording. Noting it because it is the one place the two sets differed, and because the reasoning is easy to lose: there is no replacement name forported, and that is the point. The default is spelled by the absence of a status plus apython_path. If it were sometimes written out, a missing status would stop meaning "ported" and start meaning "ported, or nobody filled this in" — which is the ambiguity the field was introduced to remove. So the error says to write nothing rather than naming a substitute.That leaves DID-python and NDR-python with the same five retired names. NDI-python is the one to check — if #210 does not retire
portedtoo, the three will differ on exactly this.
Generated by Claude Code
- added a commit that references this issue
on Sep 7, 2026 stevevanhooser commented
on Sep 7, 2026 ContributorAuthorMore actionsAmendment: write
regular_portexplicitly instead of leaving a plain port blankRequested by @stevevanhooser and now implemented in #22 (commit
bb54b63), alongside theported_differentlyrename.The change. A 1:1 port is written
status: regular_portrather than carrying nostatusat all. The original design made the ordinary case implicit on the grounds that there should be exactly one way to say it — but that optimised for the wrong reader. These YAML files are read by people far more often than by the test suite, and an absent field does not announce what it means: someone looking at an entry with nostatuscannot tell "this is a normal port" from "nobody filled this in". One line removes the guess.The vocabulary is now five values, with
regular_portlisted first since it is the common case:status count in NDR-python regular_port105 ported_differently9 matlab_only4 porting_deferred2 retired0 All 120 entries now carry a status; none is left to inference.
status: regular_portsits directly undermatlab_path, so a reader sees the MATLAB file and then immediately what became of it.Rules that changed as a consequence
- The old rule inverted.
test_a_plain_port_is_not_spelled_outforbade saying the ordinary thing.test_every_entry_states_its_statusnow requires it — an entry with amatlab_pathand nostatusfails. portedandimplementedwere retired as "omitstatusinstead". They now map toregular_port, and the spec records that an absent status no longer means "regular port" — it means the entry is incomplete.regular_portrequires apython_path, same asported_differently: a port that names no module is not a recorded port.
The one thing worth flagging for NDI-python and DID-python
Every status-carrying entry previously owed a
decision_log. Writingregular_portonto 105 entries would therefore have demanded 105 boilerplate justifications — and NDI-python has ~98 more.So
regular_portis exempt from thedecision_logrequirement: mirroring MATLAB is what the port does by default, there is no decision to record, and forcing one would only devalue the logs that carry real reasoning. Every other status still owes a reason, which is the case that check exists for.If NDI-python and DID-python adopt this amendment, they will hit the same wall — worth handling deliberately rather than discovering it as ~98 red tests. In NDR-python the exemption set is defined once, beside the check that enforces it, and a test pins it to what the spec tells a reader, so it cannot quietly widen to a status that does owe an explanation.
Verification
172 bridge tests pass against a full NDR-matlab clone; 561 passed / 15 skipped / 24 xfailed on the default suite; black and ruff clean. Fault-injected six ways: an omitted status fails; a
regular_portwith nopython_pathfails;portedis redirected toregular_port; a divergent status with nodecision_logstill fails; widening the exemption in code fails against the spec; renaming the spec key alone still fails.One defect in the change was caught by that injection and fixed before pushing — the "says where" failure message hardcoded
ported_differentlyand would have misreported aregular_portoffender. It now names each entry's actual status.
Generated by Claude Code
- The old rule inverted.
Cross-repo proposal. The bridge
statusvocabulary is shared by NDI-python, NDR-python and DID-python, and was settled in NDI-python (#208, #209, #210). Filing here because that is where I have write access; this needs to be carried to NDI-python as the vocabulary's home repo before it can be acted on.Timing: worth deciding before NDI-python #210 merges — that PR carries ~98 entries using the current name.
The proposal
Rename
ported_elsewheretoported_differently. No change to its meaning, to its requiredpython_path, or to the other three values (porting_deferred,matlab_only,retired).The argument for
"Elsewhere" names a place — but
python_pathalready answers where. "Differently" names the manner, which is the part a reader cannot recover from any other field on the entry.Checked against real data: of NDR-python's nine
ported_elsewhereentries (merged in #19), only three are actually "elsewhere".+ced/+sonpipe/runcmd.m_invoke.py+sonpipe/private/invoke_binary.m_invoke.py+sonpipe/private/invoke_text.m_invoke.py+omezarr/private/decompressBlosc.mnumcodecs.Bloscdoes it+omezarr/private/decompressZstd.mnumcodecs.Zstddoes it+omezarr/private/parseDType.m+omezarr/private/readChunk.mzarr.open()assembles chunks+omezarr/private/readZArrayMeta.mzarr.Array+ndr/+reader/imagestack.mSix of nine involve nothing moving anywhere. Python simply does the job a different way, usually because a dependency does it. Calling that "ported elsewhere" sends a reader looking for a relocated file that does not exist.
The suggested full phrasing was "ported_differently (for a reason)". The second half is already enforced — every entry carrying a
statusmust have adecision_log.The argument against
ported_elsewhereis already merged in NDI-python #208/#209 and in flight in #210 (~98 entries); DID-python's parallel PR uses it; NDR-python has 9 live entries.Cost, if adopted
Mechanically small and safe per repo:
status:values on affected entries;status_vocabularykey indocs/developer_notes/ndr_matlab_python_bridge.yaml(§ 6);ALLOWED_STATUSESconstant intests/test_matlab_bridge_conventions.py;ported_elsewheretoREPLACED_STATUSESso it gets a targeted error rather than a bare "not in the vocabulary".TestTheVocabularyIsTheDocumentedOne::test_spec_and_enforcement_agreefails loudly if only some of those are done, so a half-finished rename cannot merge here. NDI-python #210 has the equivalent check.Rough sizes: NDI-python ~98 entries, NDR-python 9, DID-python TBD.
Decision needed
@stevevanhooser — one decision for all three repos, not per-repo:
ported_elsewhere— read "elsewhere" loosely as "not under the mirrored name" and let thedecision_logsay how.NDR-python will follow whatever is decided. If the answer is (1) or (3), our side is a ~15-line change and I can do it on request.