Skip to content

1.0.1: attributes and messages work in Max again (plus the package icon and the tap.python design) - #37

Merged
tap merged 5 commits into
mainfrom
ccr-7cc21291-ck3wuh
Oct 3, 2026
Merged

tap merged 5 commits into
mainfrom
ccr-7cc21291-ck3wuh

Conversation

@tap

@tap tap commented Oct 2, 2026 •

Copy link
Copy Markdown
Owner

What this changes

This PR fixes 1.0.0's tap.python~ in Max, where a class's attributes and messages did not work at all. It also:

  • Replaces the package icon with the Tap family's PythonTap icon.
  • Adds the tap.python design and plan, with an adversarial audit of it, as docs only.

Why

Plan 8.2's guard reserves a Python method or field name if the Max object already answers it. It asked object_getmethod() and treated any non-null result as "answered". But for a name the object does not have, Max returns method_false(), a function, as ext_obex.h documents. So in Max every field and method of every class was "reserved by the host", and the console said so for each. Audio still worked because process() is bound before the guard. The mock kernel answers null, so the unit tests passed.

The fix is found_method(), which treats null and method_false() alike as "not found".

Verification

  • The glue test now asks Max's question the way Max answers it. Its kernel returns method_false() for an unknown name, and a real method for the names min registers plus one name the test's class defines on purpose. With 1.0.0's null test restored, the suite fails across the board with the same console lines seen in Max. With the fix, it passes. clang-format and clang-tidy are clean.
  • The first CI run failed on Windows only, in the test itself (abad3a2). The fake "found" method and the fake method_false() both returned 0. MSVC's Release link folds identical functions (/OPT:ICF), so on Windows they shared one address, and the one name that relies on the fake was exposed. Locally, lld --icf=all folds the same pair (one address in nm). The fake now has a body of its own. The scenario also checks first that the kernel's two answers differ, so a folding linker fails it by name. The fix in the object is unchanged.
  • Not run: Max. On a Mac, the check that confirms the fix is:
    cmake --build build && python3 runtime-tests/run.py --only attributes-and-messages -v
    Tagging v1.0.1 should wait for the full runtime suite and the 8.8 items.

Notes for the reviewer

  • Contract change. None. The fix restores what the ReadMe already promises. CHANGELOG.md has a 1.0.1 entry.
  • Package icon (8407f93). icon.png was min's template gear. It is now PythonTap-ground.svg from Add family icons and palette under brand/ TapHouse#9 (a545539, still open), rendered at 500×500 with cairosvg as that PR's make_icons.py does. The brand guide names the ground version for package icons.
  • Design docs. docs/TAP-PYTHON-PLAN.md and Phase 9 of the production plan, plus docs/AUDIT-TAP-PYTHON-PLAN.md. The audit finds two blockers, so the plan is not ready to build; the plan text is unchanged pending review. Both docs stay out of the shipped package. This part can be split into its own PR if you would rather merge the fix alone.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WnyasLjC6poziMpwguw4in

tap and others added 5 commits October 2, 2026 19:48
docs/TAP-PYTHON-PLAN.md: the decisions (D7-D11), the class contract — what a
method returns is what the object outputs, its return hint the outlet count —
the thread model, what changes in the core, the shared glue, the package, and
the plan as Phase 9 of the production plan, which now points to it. The new
plan is kept out of the shipped package like the others, and CLAUDE.md names
it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WnyasLjC6poziMpwguw4in
Plan 8.2's guard asked object_getmethod() whether the Max object already
answers a Python method's or field's name and took anything but null for
yes. For a name the object does not have, Max returns method_false(), a
function, as the SDK documents, so in Max every field and method of every
class was "reserved by the host" and the object had no attributes and no
messages; only audio still worked. The mock kernel answers null, which is
why the unit tests passed.

found_method() now treats null and method_false() alike as not found. The
glue test's kernel answers as Max does (method_false() for an unknown name,
a method for the names min registers and for one the test's class defines on
purpose), and the reserved-name scenario checks a field and that name: it
fails with the null test and passes with the fix. CHANGELOG 1.0.1, the plan's
record under 8.2, and CLAUDE.md's rule about reading a Max call's return
contract.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WnyasLjC6poziMpwguw4in
docs/AUDIT-TAP-PYTHON-PLAN.md: two blockers, six major and nine minor
findings, each checked against the source. The blockers: two externals each
compile in their own copy of the header-only core, and the second one's
initialize() aborts the process (reproduced with two shared objects in one
process); and the plan verifies Max-only behavior last, as 1.0.0 did. The
plan itself is unchanged, pending review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WnyasLjC6poziMpwguw4in
…_false

The test kernel's fake object_getmethod() answered a registered name with a
lambda returning 0 and an unknown name with method_false(), also returning 0.
MSVC's Release link folds identical functions (/OPT:ICF, on by default), so on
Windows both had one address, found_method() read every name as unanswered,
and maxtest_host_answers was exposed as a message: the one failing check.
lld --icf=all folds the same pair here (one address in nm); GCC settled the
comparison at compile time, which is why Linux and macOS passed.

The fake now answers with answered_method(), whose body is its own, and the
scenario first requires that the kernel's two answers differ, so a folding
linker fails it by name. The fix to the object itself is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WnyasLjC6poziMpwguw4in
icon.png was min's template icon. It is now PythonTap-ground.svg from
TapHouse's brand/ (tap/TapHouse#9, a545539, still open), rendered at 500x500
with cairosvg as brand/make_icons.py renders its PNGs: the ground version is
the one the brand guide names for package icons.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WnyasLjC6poziMpwguw4in
@tap tap changed the title 1.0.1: attributes and messages work in Max again (and the tap.python design) 1.0.1: attributes and messages work in Max again (plus the package icon and the tap.python design) Oct 3, 2026
@tap
tap merged commit 9cd4a92 into main Oct 3, 2026
18 checks passed
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