Skip to content

The tap.python plan, revised for its audit and review — and the record brought up to 1.0.2 - #41

Merged
tap merged 2 commits into
mainfrom
v1/record-after-1.0.2
Oct 9, 2026
Merged

tap merged 2 commits into
mainfrom
v1/record-after-1.0.2

Conversation

@tap

@tap tap commented Oct 9, 2026 •

Copy link
Copy Markdown
Owner

What this changes

Docs only, four commits:

  1. The record brought up to 1.0.2. CLAUDE.md's rule about the reserved-name guard describes 1.0.2, not 1.0.1, and docs/AUDIT-TAP-PYTHON-PLAN.md gains a dated addendum on what the two releases since the audit changed in its findings.
  2. docs/TAP-PYTHON-PLAN.md revised for every audit finding, with the production plan's Phase 9 and sequencing following. The plan ends with a revision record naming what each finding changed.
  3. After the maintainer's review: documentation in Max's own system (9.4), a book (9.7), and the test coverage gaps closed in 9.1, 9.3 and 9.5.
  4. The three open decisions, decided by the maintainer: the release that carries tap.python is 2.0.0 (the list[…] parameter is a contract change, the CHANGELOG's rule applied as written); a str return outputs as the spike finds composes best; the vignette is the short form, written separately.

Why

The audit found two blockers in the plan as first written. The revision settles them:

  • One binary, two Max classes (D11). Two externals would each compile in their own copy of the header-only core and start the interpreter; the second aborts Max (reproduced with two shared objects in one process), and 1.0.1's Windows failure showed a function's address is not its identity across a DLL boundary. The maintainer chose one binary on 2026-10-09.
  • The second class is a plain SDK class, not a min class. min keeps one file-scope this_class per translation unit (c74_min_api.h:325) and returns early from a second wrap_as_max_external(). A second min class in another translation unit would work only by accident of internal linkage, and break the one-definition rule the moment a test instantiated its templates elsewhere. A plain class is what the shared glue already speaks, and it is what the audit's outlet finding needed anyway. Max finds it through the package's init/ objectfile mapping, with a stub external as the fallback; the spike settles which. Its reference page is written by hand, since there is no min generator for it.
  • A spike in Max, on a Mac and on Windows, before any code the rest depends on (9.0). Three releases in a row shipped what only a host platform could show, and the third was Windows-only. The spike's questions are listed in the plan.

The major and minor findings are folded in as the revision record says: raw outlets created dumpout-first with the dumpout in the obex; a recursive per-object lock across output and port changes; a class-level anything forwarder that fixes the dispatch order itself; Scheduler in Audio Interrupt detected and stated as a limit; announce-once per object kind; the tuple rule gated on bind_audio; the list[…] parameter recorded as a change with the old behavior pinned first.

The review added what the plan lacked. Documentation was reference pages and help files only; 9.4 now has a vignette, three tutorials with patchers, an Extras overview named as the landing patcher, help tabs for both objects, and CI checks for what is written by hand, with 9.0 finding where Max reads the files from. 9.7 is the family's mdBook after 2.0.0, with example code and performance tables pulled from what ships. Test coverage had four gaps: no sanitizer rows for the Max glue, where the new lock lives; a performance sentence with no measurement; no soak for the new object; and the hand-made pages, help patchers and init/ file unchecked. All four are in the plan now, plus the output table as a data-driven test over its edges, core tests for the new examples, and an injected audio-thread predicate so the Scheduler-in-Audio-Interrupt notice is testable without Max. Windows stays by hand and is written down as a limit.

Verification

Prose only. Every claim about min and the SDK was checked against the headers in the submodule (this_class, wrap_as_max_external, deduce_maxclassname, doc_update, object_obex_store, outlet_insert_after, systhread_isaudiothread) and the mock kernel's stubs; the claims about the releases against the commits on main; the claims about Max's package folders against Cycling '74's current package documentation. The plan's section links and its references to the audit's finding ids were checked by script. What only Max can settle is listed under 9.0, not asserted.

Notes for the reviewer

  • Contract change. The list[…] parameter changes what a tap.python~ method with such a hint receives (the empty symbol today). Nothing in this PR changes code; the plan records that the release carrying it is 2.0.0.
  • Nothing in the plan is built. 9.0 is the first PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WnyasLjC6poziMpwguw4in

tap and others added 2 commits October 9, 2026 00:34
… to the audit

CLAUDE.md still described 1.0.1's guard (a comparison with &method_false), which 1.0.2 replaced
with asking Max what it answers for a name no class can have. The rule now says why — a function
pointer Max returns is never compared with the address of an imported function, which across a
DLL boundary is the module's own thunk — and what 1.0.1 found in Max: what the object itself
registers, attributes included, answers its name and must be left out of the guard. And the
lesson of three releases: Max glue is verified on both platforms before a tag.

The audit of the tap.python plan gains a dated addendum: the verdict and findings stand; B1 is
reinforced by the thunk finding; B2's prerequisite (8.8) is met and the spike needs Windows too;
M3's guard half is likely resolved by 1.0.2's design, its dispatch-order half still open, with
8.8's evidence that an added attribute is found by object_getmethod(); a new rule for the plan's
guard; and the references the two releases made stale.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WnyasLjC6poziMpwguw4in
…ss, a spike first

D11, decided 2026-10-09: one binary registers both Max classes, since two externals would each
start the interpreter and the second aborts Max (audit B1, reproduced); and the second class is a
plain SDK class rather than a min class, since min keeps one file-scope this_class per translation
unit and returns early from a second wrap_as_max_external(). Max finds the object through the
package's init/ objectfile mapping, with a stub external as the fallback; the spike settles which.

Every other finding is folded in: a 9.0 spike in Max on both platforms before 9.1 (B2); raw
outlets created dumpout-first, the dumpout in the obex, outlet_insert_after on reload (M1); a
recursive per-object lock across output and port changes, with a race test (M2); a class-level
anything forwarder that fixes the dispatch order itself, and the guard as 1.0.2 has it (M3);
Scheduler in Audio Interrupt detected, named and stated as a limit (M4); announce-once per
(file, kind) (M5); the tuple rule gated on bind_audio, an unsaid-length tuple output as a list,
and the list[...] parameter recorded as a change with the old behavior pinned first (M6); and the
minor items, with the str return left to the spike. The production plan's Phase 9 and its
sequencing line follow; the plan ends with a revision record naming what each finding changed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WnyasLjC6poziMpwguw4in
@tap tap changed the title Bring the record up to 1.0.2: CLAUDE.md's guard rule, and an addendum to the audit The tap.python plan, revised for its audit — and the record brought up to 1.0.2 Oct 9, 2026
@tap
tap merged commit 4501d8f into main Oct 9, 2026
18 checks passed
@tap tap changed the title The tap.python plan, revised for its audit — and the record brought up to 1.0.2 The tap.python plan, revised for its audit and review — and the record brought up to 1.0.2 Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant