Artifact af2f3fac4b3c13533cac0696fb8d8c914e7991ff31719df282b55e5f2fd84c8c:
- File revival/doc/roadmap.md — part of check-in [3419a76d11] at 2026-08-02 01:36:48 on branch andrew-6.4 — docs: M4 batch map built from real Phase 1 census — 1778 errors/83 dirs, 24 batches/7 waves; supersedes the 'no batch map needed' plan (user: wdc size: 162544)
AUIS Revival Roadmap
Current as of 2026-07-11. See porting-changelog.md for the detailed
history behind each completed item.
Current action plan
Objective: messages demo a.k.a.amsdemo
- ~~Prerequisite: cui~~ — done 2026-07-07, was a missing RESOLVER_LIB link flag, not sgtty
- ~~gendemo~~ — done 2026-07-07: cwd bug (needs to run from
src/ams/demo/) plus acui reconsegfault (modern-flex init-flag polarity bug, new bug class, seeporting-assessment.md§13); both fixed, demo folder populates and reconstructs cleanly - ~~Then find the bugs in the demos~~ — done 2026-07-11. Chased through three
stacked bugs to find the real one:
- Caption display:
tm_year(years since 1900) printed via%02dinstead of%02doftm_year % 100— harmless before 2000, wrong ("7-Jul-126") oncetm_yearexceeds 99. Fixed inbldcapt.c/shrkdate.c. - Message ordering:
recon.c's sort-by-time comparator had no tiebreak for messages sharing the same one-second-resolutionAMS_DATE; fixed with anAMS_IDfallback (kept as a general hardening, checked in separately from the caption fix). - Parser bug in
parsedate()— FIXED. Root cause: mkparser/cparser.c fixed-width-table assumption affecting all bison-generated grammars tree-wide. Full analysis: porting-assessment.md §15. Result:gendemopopulates with correct captions and Part 1…23 ordering. - Inter-line spaceing in folders and message header panes is double wide.
- Caption display:
Objective: AMS over IMAP/SMTP (kicked off 2026-07-16)
Teach the AMS clients to use IMAP as a mail store and SMTP as a sender,
Fastmail as the test platform. Plan of record:
revival/doc/ams-IMAP-project.md; the MS_* server-client interface it
builds on is documented in revival/doc/ams-server-client-interface.md
(converted from ServerCalls.d via ez2md). Architecture decision: local
.MS_MsgDir store stays as the cache (Thunderbird model), sync agent
mirrors IMAP; AMDS delivery remains excluded.
- ~~Milestone 1: SMTP send~~ — done 2026-07-17.
tlscon/netrc/smtpsubmodules inoverhead/mail/lib,dropoff()gated on thesmtphostpreference, legacy sendmail pipe as fallback. End-to-end acceptance passes (revival/tools/smtp-send-test: scripted cui → SMTP → Fastmail, real send confirmed). Implementation delegated to a Sonnet instance againstrevival/doc/claude-history/smtp-send-prompt.md(three stages, two review gates). The acceptance push flushed out and fixed three latent legacy bugs: cui NULL address-validation crashes (7 sites), the fdplumb.h open-rename variadic-ABI corruption (seerevival.md, "Old bugs never found"), and client-side dest-host DNS validation (now defaults off whensmtphostis set;validatedesthostspreference overrides). - ~~Milestone 2: IMAP spike~~ — done 2026-07-17. Full
CAPABILITY/LOGIN/LIST/EXAMINE/SEARCH/FETCH sequence (read-only,
including a real 9.6KB body literal) ran against live Fastmail;
decision: hand-roll the IMAP client (§8 of the plan doc now
records the reasoning). Key transport finding: tlscon's fixed 4KB
line buffer + missing resync primitive wedge the connection on
large single-line responses (
UID SEARCH ALLon a 3,939-message mailbox) — growable buffer + reconnect design is milestone 3's first task, and sync will target Fastmail'sESEARCH/CONDSTOREinstead of naive SEARCH-ALL. Spike driver:src/overhead/mail/lib/imapspike.c;tlscon_ReadBytesadded (additive; both SMTP regression suites re-passed). - Milestone 3a — done 2026-07-18: tlscon hardened
(
tlscon_ReadLineAlloc, growable line reads — the spike'sUID SEARCH ALLwedge case now survives) andimap_prot.[ch]landed: the tree's first born-ANSI module (full-prototype header, scanf banned in favor of strtoul/strcasecmp), ESEARCH-aware, streaming body fetch, reconnect-with-UIDVALIDITY-check contract.revival/tests/imap-protocol-tests9/9 live against Fastmail; both SMTP suites still green. Spec:revival/doc/claude-history/imap-protocol-prompt.md. - Milestone 3b — done 2026-07-18:
imapsync(src/ams/msclients/imapsync/) mirrors IMAP one-way into a local mspath root (~/.IMAP/fastmail/.MESSAGES/...) through the store's own code via one additive MS entry point (MS_AppendFileToFolderWithId, caller-supplied id/date). Ids are deterministic f(UIDVALIDITY,UID) in base32hex — mixed-case base64 collided on APFS's case-insensitive filenames (two live pairs hit, e.g....GvA/...Gva). Flags mapping viaMS_AlterSnapshot, CONDSTORE/HIGHESTMODSEQ refresh skip,-full-checkexpunge marking, skip-and-retry on empty body fetches (a live Fastmail expunge-during-FETCH race).revival/tests/imap-sync-tests6 cases live incl. scripted cui browse; real-mailbox browse inmessagesconfirmed by hand. Spec:revival/doc/claude-history/imap-sync-prompt.md.- Latent hazard noted for the wider tree: the store's own
ams_genid()ids are mixed-case base64 too, so every natively created message file carries the same (much rarer) case-collision risk on case-insensitive filesystems. Not fixed; revisit if a native-store collision is ever observed. - Close-out regression run surfaced two more real bugs, both fixed
2026-07-18: (1)
WritePureFile(ams/libs/ms/rawdb.c) unlinked its target on open failure — underO_CREAT|O_EXCLanEEXISTcollision therefore deleted the existing message's body file (35-year-old data-loss bug; see revival.md old-bugs); (2) RFC 3501UID n:*always includes the highest existing uid, so an idempotent re-run could re-present the top already-mirrored message as a candidate — imapsync now filters candidates at/below its watermark and pre-checks the deterministic+<id>body file before appending (robust even when the store's Message-ID-based duplicate check can't catch a re-append). - M3c observations from first real browse: mirrored folders need Message Folders → Expose All to appear (subscription defaults — M3c work item); metamail launch is reported for MIME messages but displays nothing (pre-existing platform gap, metamail not functional here — HTML mail display now has its own objective, see "Objective: HTML mail rendering" below; root cause now identified, see that section); first full mirror is slow-ish (~3,800 messages; per-run incremental cost is near-zero thereafter).
- NEW BUG 2026-07-19: messages crashes on exit —
EXC_BAD_ACCESSinMS_SetAssociatedTime(amsn.do), called fromcaptions__MakeCachedUpdates←ams__CommitStateduring the quit keystroke'skeystate__DoProc. Faulting address0x16c34214fits entirely in 32 bits on a platform where heap/ stack pointers don't — the classic LP64 pointer-truncation signature (see porting-assessment §12); crash is atldr w8, [x21, #0x14], i.e. dereferencing a bad struct pointer. ROOT-CAUSED same day (second capture showed the sign-extended twin0xffffffffb6c34214, and the user isolated the trigger: only after clicking into the mirrored INBOX's captions): LP64 Variant 1, missing prototype.FindInDirCache(definedmsdir.c:680, returnsstruct MS_Directory *) is declared in no header;setasct.c:48calls it undeclared → implicit-int return truncates the pointer to 32 bits, then the cast re-extends (bit 31 decides zero- vs sign-extension — both observed addresses). The elegant part: the cache-miss sentinel(struct MS_Directory *) -1survives truncation intact, so the!= -1guard works and nothing crashes until the directory is actually IN the cache (i.e., you visited the folder) and a real pointer gets mangled — exactly the observed "clicking into INBOX lights the fuse." Long-latent (1991), not a regression; local folders were exposed too but the garbage deref only faults when the truncated address is unmapped. Fix: one-lineextern struct MS_Directory *FindInDirCache();in setasct.c (sole external caller), compile-verified, in tree pending runtime confirmation + commit. The build's-Wno-implicit-function-declarationis why this class is silent — standing argument for the M2 prototype sweep. - Startup noise logged 2026-07-19, unassessed:
Fontconfig warning: using without calling FcInit()and twoNot a JPEG filelines (libjpeg probing a non-JPEG — source not identified). - First real-send observations (2026-07-18, sending from
messages): - From-address is
wdc@Mac-mini.lan— RESOLVED 2026-07-18.MS_SubmitMessage(ams/libs/ms/submsg.c) deletes any user-supplied From and stampsMe@MyMailDomain;MyMailDomainis the cell name =ThisDomain, an AndrewSetup key (overhead/util/lib/svcconf.c), falling back to the hostname when no AndrewSetup exists — hence the.lanFrom and Fastmail's "551 5.7.1 Not authorised" on external relay. Fix (no sudo needed): the AndrewSetup search path ends at${ANDREWDIR}/etc/AndrewSetup(site.h points ANDREWDIR at the build tree), sobuild/etc/AndrewSetupcontainingThisDomain: fastmail.comcorrects every AMS client at once. Verified live: cui send now arrives asFrom: William Cattey <wdc@fastmail.com>. Belongs in the quickstart doc (M3c deliverable). - FIXED 2026-07-18: formatted send was default.
Root cause: MS_GetConfigurationParameters LP64 int*/long* mismatch in out-parameters
(see porting-assessment.md §12, "By-pointer case"). Plain bodies now auto-strip,
formatted bodies offer choice per
mailsendingformat. <critical:fdplumb>"File descriptor replaced!" and transient preferences blackout. Gate 1 CLOSED 2026-07-19 by Fable static analysis (seerevival/doc/claude-history/fdplumb-REPORT.md). Key finding: preferences fopen is raw libc (not dbg_fopen), so fdplumb is exonerated for the blackout. Fixes committed: profile.c now retries transient load failures, prints errno, and dbg_dup2/setprof.c crash paths fixed. Remaining: profile.c runtime monitoring of the new errno log (low priority).- FIXED 2026-07-18: RCPT TO built from a display-form address.
dropoff() callers pass full RFC 822 addresses; in particular the
kept-blind-copy fallback (submsg.c) appends
MyPrettyAddress(William Cattey <wdc@fastmail.com>) verbatim to the envelope vector when direct insertion of the blind copy fails. smtpsub.c then wrapped it in a second bracket pair —RCPT TO:<William Cattey <wdc@fastmail.com>>. Fastmail answers 250 at RCPT time and fails the whole transaction after DATA with501 5.1.3 Bad recipient address syntax, so every recipient is reported bad — which is exactly how it presented in the GUI. Caught by the user reading anAMS_SMTP_TRACE=1transcript. Fix:smtp_addrspec()in smtpsub.c reduces each tolist entry to a bare addr-spec (ParseAddressList, strip comments and display phrase, unparse unfolded) at the protocol boundary, healing all callers. Reproduced and verified withsmtptest.testand a display-form recipient: 501 before, queued after. Follow-up still open: why the blind copy's direct insertion fails in this setup ("Sending your BCC through the mail after error in direct insertion") — with the envelope fixed, keep-blind now mails you the copy instead of failing the whole send, but the direct-file path should work.
- Latent hazard noted for the wider tree: the store's own
- Milestones 3c–5 (next: 3c, messages-GUI acceptance incl. folder
visibility): writeback via change journal (4) — spec written
2026-07-19:
revival/doc/claude-history/imap-writeback-prompt.md(now inclaude-history/, retired 2026-07-23 with M4) (gated, Sonnet-executable: per-folder.MS_Journalcapture at the four MS mutation points, replay-then-mirror server-wins ordering, drop-and-refetch identity for appends, purge safety valve, all destructive tests confined to a dedicatedRevival/WritebackTestmailbox); XOAUTH2 (5). - Delegated work queue (written 2026-07-19, for Sonnet-class
sessions during the budget crunch). Standing briefing:
revival/doc/sonnet-playbook.md(launch instructions at the top; one task per fresh session; STOP-gated; no fossil commits — each session ends with a<task>-session.diff+<task>-REPORT.mdin the tree root for review). Task prompts, in suggested order of attack (safest first):- ~~
strlit-sweep-prompt.md~~ (now inclaude-history/) — done 2026-07-23. Root cause wasn't a file-by-file mutation bug after all:config/darwin/system.mcrhad simply never set-fwritable-strings, and Apple clang (unlike real gcc since 4.0) still implements it — one-line fix plus a full rebuild, verified live. A-Wwrite-stringsscan afterward quantified the scope (26,628 literal→char*sites, almost all inert boilerplate or never-mutated static tables) and a full source cleanup was considered and rejected as disproportionate. The three confirmed reachable-by-literal call sites got belt-and-suspenders fixes anyway. Seeporting-assessment.mdissue #1 andclaude-history/strlit-REPORT.md. - ~~
m2-census-prompt.md~~ (now inclaude-history/m2/) — done 2026-07-24. Classified all 67int*/long*and 18char**→char*instances into 13 shared root shapes and fixed three findings: thechar**cluster's real bug was threeCUI_*methods inams.chtypedchar *when theircuilib.cimplementations takechar **(clang's own "remove &" fix-it would have broken all 18 correct callers); a live, reachable bug via the stretch-goal sweep —MS_ParseDatewriting a class-typedlong *into a realint *implementation, hit bycaptions__MarkRangeOfMessages's uninitializedlonglocals; andfontdesc_StringBoundingBox's.chsignature, the odd one out among its long*-typed siblings. All three verified via full rebuild and a human smoke test, committed as three separate checkins. The other 45int*/long*instances (caller declaresint, callee wantslong *— stack-overrun direction) are cataloged but not yet fixed. Seeclaude-history/m2/m2-census-REPORT.md. bcc-direct-insertion-prompt.md— root-cause the blind-copy direct-insertion failure (investigation-gated).- ~~
folder-visibility-prompt.md~~ (now inclaude-history/) — done 2026-07-22. Root cause was not subscriptions but a site-config global,AMS_OnlyMail(defaults to1withoutRUN_AMDS_ENV), which restricted the default "Expose New" view to$HOME/.MESSAGESregardless of subscription status. The Gate-1 report's own proposal (imapsync auto-subscribe at creation) was tested live and falsified before this was found — seerevival/doc/claude-history/folder-visibility-REPORT.md's "Correction" section. Fixed viaAMS_OnlyMail: Noinbuild/etc/AndrewSetup(newrevival/tools/write-andrewsetupregenerates it aftermake Clean); mirrored folders now need that setting plus Ask/Show-All subscription (not plain Subscribe) to appear by default. Documented inquickstart.mdandmail-quickstart.md. - ~~
fdplumb-prompt.md~~ (now inclaude-history/) — Gate 1 CLOSED 2026-07-19 by a Fable session (static analysis; seerevival/doc/claude-history/fdplumb-REPORT.mdand M3c item 3 above). Fixes committed. Only the low-priority runtime half remains (wait for the new profile warning line to fire); do not re-queue as written — the prompt's dbg_fopen premise was disproven. - ~~
imap-writeback-prompt.md~~ (now inclaude-history/) — milestone 4 writeback. DONE 2026-07-23, all three gates closed and committed (fb4876aGate 1 code,83dc58c/6879cdfGate 2,df2a94c/164f736Gate 3 — seerevival/doc/claude-history/imap-writeback-REPORT.mdfor the full history andams-IMAP-project.md§7 for the design summary). AMS-over-IMAP is feature-complete: capture, suppression, flags/purge/append replay, crash-safe resume, all confined toRevival/WritebackTestin test. One real incident happened and was fully resolved mid-arc — a Gate 1 test suite that was safe when written became unsafe once Gate 2's replay went live and permanently deleted one real ~2009 message from the live account; fixed same day, not recoverable, user chose not to pursue further recovery. Remaining: a messages-GUI hand test (two-line instruction in the Gate 3 report) is wdc's to run, not automated. - ~~
mime-display-prompt.md~~ (now inclaude-history/) — done 2026-07-21. MIME body display inmessages: newmimepartmodule (src/ams/libs/hdrs/mimepart.h+src/ams/libs/shr/mimepart.c), wired intotext822.c: multipart/alternative prefers text/plain, html-only mail gets the interim tag-strip shim, multipart/mixed lists non-text parts as[attachment: ...]lines, UTF-8text/plainfinally renders instead of falling to a dead metamail button. Three gates, all closed — seerevival/doc/claude-history/mime-display-REPORT.md. By-hand acceptance against wdc's real mailbox (Gate 3) found and fixed two more pre-existing, unrelated bugs that were blocking this from working at all:GetHeader's header/body-boundary check was CRLF-blind (an entire CRLF-encoded body was being swallowed into the "minor headers" display — explains the wall-of-headers/tiny-font/undecoded-=20/stray-bold symptoms wdc first saw, all at once), andtext822.do's Imakefile link line silently omittedlibmsshr.a(-undefined dynamic_lookupmasks missing libs at build time; the first real call to a new library symbol crashed at runtime — fixed, verified withnm -m). One follow-on left open: amultipart/mixedattachment renders as a bare?instead of the expected[attachment: ...]line — root cause not yet found, queued asmime-attachment-icon-prompt.md(item 8 below). mime-attachment-icon-prompt.md— root-cause the bare-?attachment-rendering bug above (added 2026-07-21).
- ~~
Objective: HTML mail rendering (added 2026-07-19; queued behind milestones 4–5)
Essentially all real-world mail arrives as HTML (usually
multipart/alternative with a text/html part). metamail is not
functional on this platform (launches, displays nothing — see the
M3c observations above, and the root-cause finding below), and even
fixed it would remain an external button-press viewer. For
messages to be genuinely useful as a daily reader, text/html
bodies must render inline in the message pane via the
htmlview/html inset machinery. Sequencing: start after writeback (4)
and XOAUTH2 (5) close out the store work.
Current state of the pieces:
- htmlview no longer crashes (overlapping-strcpy family, fixed 2026-07-10) but renders essentially nothing from real-world HTML — and that symptom has never been root-caused; it may be a few gating bugs (DOCTYPE? charset meta? entity handling?) rather than wholesale parser obsolescence. See Insets to Repair → htmlview.
- messages' foreign-type display path shells out to metamail
(
atkams/messages/lib/mailobj.c); AMS has a header parser (hdrparse) but no MIME body parser (ams-IMAP-project.md§4). - metamail root cause identified 2026-07-24 (found during M2
rollout point 4b's runtime check,
claude-history/ m2/m2-metamail-REPORT.md): a plaintext/plainbody run directly (printf ... | metamail) already crashes with a Bus error before any display happens. Underlldb, the actual first-hit signal isSIGTTOU(terminal job-control — a background process group attempting a terminal-controlioctl), stopped insideExecuteMailcapEntry'sioctl()call (metamail.c), reached viaHandleMessage→TryMailcapEntry→ExecuteMailcapEntry— the code that forks an external viewer for a mailcap entry and hands it terminal control. This is 1980s/90s BSD job-control code (companion to thegtty/sttylegacy-syscall macros elsewhere in the same file,sgtty.h/sys/ioctl_compat.h) that doesn't survive contact with modern macOS process-group/terminal semantics — a different failure category entirely from "displays nothing," and unrelated to M2's implicit-declaration fixes (confirmed:ioctlwas already correctly declared before that session touched the file, and M2's fixes are additive declarations only, no logic changes). Root cause identified, not yet fixed — whoever picks up metamail's "separate side quest" (H3 below) should start from this finding rather than the mailcap-execution code in general.
MIME body plumbing moved out of this objective 2026-07-19, done
2026-07-21 — was the mime-display task in the delegated work
queue above, spec now retired to
revival/doc/claude-history/mime-display-prompt.md, report at
revival/doc/claude-history/mime-display-REPORT.md. Delivered: the
quick win (prefer text/plain from multipart/alternative — most mail
now readable with zero htmlview work), CTE decoding, UTF-8→Latin-1
conversion, and an interim tag-strip shim for html-only mail —
confirmed working against a real mailbox message (Gate 3 by-hand
acceptance). What remains here is the real HTML rendering:
- H1 — htmlview triage: build a fixture corpus from real Fastmail messages and establish what the ~1994 parser actually does with each — root-cause the "renders nothing" symptom before designing any rewrite.
- H2 — good-enough rendering: readable text with paragraphs, links, emphasis, lists; unknown tags skipped cleanly, script/style content dropped, UTF-8 and common entities handled. Explicitly NOT: CSS, tables-as-layout fidelity, remote images.
- H3 — inline integration: route text/html parts to an inline htmlview inset in the message pane, replacing both the metamail button and mime-display's interim tag-strip shim for this type; metamail stays the fallback for other foreign types (its macOS build remains a separate side quest).
Objective: Reliable operation
- Let's get all the function prototypes live with ANSI — plan of record now at Medium-term → ANSI C conversion (M1–M4)
Little Annoyances to clean up
Keymap:
- The arrow keys don't work yet
- We don't have a "Meta" key active yet
make Clean transiently deletes src/atk/adew/Arb:
- adew's
clean::rule does$(RM) arb, which on macOS's case-insensitive filesystem deletes the version-controlledArbdirectory entry's fileArb(observed 2026-07-10 during the batch-11 gate; dependInstall regenerates it and fossil is clean again post-gate, so it's self-healing in a full gate but would leave the tree dirty after a baremake Clean). Pre-existing; fix is renaming one of the two or making the rule case-exact.
messages: X_OpenFont BadValue (observed 2026-07-23, not yet investigated)
messagesprintedX error 2-BadValue ... Will ignore operation 45:0 on resource ID a005b3(and a005b4, one right after) to the terminal during otherwise-normal use (browsing folders after the M4 hand test). Request code 45 isX_OpenFont; the catch-all handler (XErrorsToConsole,atk/basics/x/xim.c:696) logs and ignores any X error rather than crashing, so this is non-fatal but real — two font loads failed. Plausible candidate for another LP64-class bug (a corrupted value reaching the OpenFont request) given this tree's track record, and/or related to the knownMK_CONSOLEfont gap — not yet distinguished. Not root-caused; needs a dedicated session (breakpoint the font-open path, identify which font name/size triggered it) before it goes inporting-assessment.md.
ez: horizontal text-block drag locks at position 0 after first drag (observed 2026-07-25, not yet investigated)
- Selecting and dragging a block of text: vertical dragging works
correctly, but after the first horizontal drag the displayed
horizontal position reads 0 and stays locked there — further
horizontal drags have no visible effect (vertical dragging continues
to work). Found during M2 rollout point 4h's (
contrib/zip/lib) runtime check, unrelated to that session's own declaration-only fix — no M2 session has touched any mouse-drag or cursor-position code. Not yet root-caused; "locks at exactly 0" is suggestively similar in shape to this project's other LP64 sign/width-corruption bugs (a coordinate corrupted to zero rather than merely wrong), but that's a hypothesis, not a finding — needs its own dedicated investigation session. See memoryproject_text_drag_horizontal_lock.
filetype.c DeleteEntry:
filetype__DeleteEntry(atk/basics/common/filetype.c:216,218, observed 2026-07-09, logged before the basics/common -pi rollout — pre-existing, not a regression): passes&defaultMapping.newAttributes(astruct attributes **) toFreeAttributes(), which walks it as a list node — UB/bogus frees if that path ever runs. The enclosingif (strcmp(extension, "*"))also looks inverted (wipes the default mapping when the extension is NOT"*"). Compiler flags it via -Wincompatible-pointer-types.
Applications to Repair
Applications that currently crash instead of running. All are
pre-existing failures surfaced by first-ever runtime tests during the
M1 rollout — none are -pi regressions.
Overlapping-strcpy crash family — FIXED 2026-07-10, runtime-confirmed
A tree-wide audit (grep for the same-variable idiom strcpy(x, x+n)
plus manual read-through of every call site that derives its second
argument from a pointer computed off the first, e.g. via
index()/strchr()/rindex() in the enclosing function) found
15 overlapping-strcpy call sites across 9 files — the 3 already
logged here (bush, org, htmlview) plus 6 more never surfaced by a
runtime test. All are the same idiom: an in-place left-shift
(strcpy(dst, dst+n) or two differently-named pointers that alias
the same buffer) to delete characters from a string. Apple's
fortified libc's strcpy aborts (EXC_BREAKPOINT →
__strcpy_chk → __chk_fail_overlap) whenever src/dst ranges
overlap, even though the classic forward byte-copy this idiom relies
on is safe precisely for this direction (dst < src) and has clearly
worked for ~35 years on non-fortified libcs. Fix is mechanical and
semantics-preserving everywhere: strcpy(dst, src) → memmove(dst,
src, strlen(src)+1) — memmove is defined for overlapping ranges and
produces byte-identical output to what the (unfortified) strcpy
already produced. All 9 files compile clean (zero error: lines)
after the fix, checked individually per file, except the two
noted as dead-tree below. Full gate (make Clean && make
dependInstall) run 2026-07-10: zero real error: lines tree-wide
(one hit, the known -Wdeprecated-non-prototype false positive);
bush.do, org.do, htmlview.do, strtbl.do, label.do, and
gentlex all reinstalled with fresh timestamps.
- bush.c:269 (
bush__InitTree) — root cause confirmed: not the originally-guessedstrcpy(p, p+n)shape.GivenDirNameisself->given_dir_name;bush__Createcallsbush_InitTree(self, GivenDirName), soroot_pathandGivenDirNameare the same pointer insideInitTree— thestrcpy(GivenDirName, root_path)at line 269 is a full self-copy, which fortify treats as total overlap. Runtime-confirmed 2026-07-10: bush launches (was: instant crash on every launch). New pre-existing bug noticed during this check, NOT related to the strcpy fix (bush.c's rendering code was untouched): bush is confused about foreground/background colors, and leaf nodes draw completely wrong. Needs its own dedicated debugging session — logged here so it isn't mistaken for a side effect of this fix. - org.c:396 (
Strip(), called fromRead_Bodyat line 192) — root cause corrected from what was logged here previously. The earlier note namedstrcpy(fName, tmpnam(seed))(org.c:231) as the site; re-derivation found that call copies between two independent stack buffers (not overlapping) and doesn't match the crash's actual call path as convincingly asStrip()'sstrcpy(string, ptr)whereptr = string + (leading whitespace count)— an exact instance of the same aliasing idiom as every other confirmed site, sitting directly inRead_Body's control flow, and triggered by any node name with leading whitespace (routine in org's indented tree format). Fixed at line 396. Runtime-confirmed 2026-07-10: all 3 example.orgfiles load and work 100% (was: crash on load). Separately noted, not fixed:org.c:231'sstrcpy(fName, tmpnam(seed))is still a real bug —seedis sprintf'd as if it were a naming template, buttmpnam()'s buffer-argument form just overwrites it, so the sprintf'd content is silently discarded. Not an overlap (doesn't crash), but wasted work and a misleading read. Left alone pending a deliberate decision on temp-file strategy (tempnam()/mkstemp()) — out of scope for a mechanical overlap fix. - html.c (
html__ReadSubString/entity parser) — all 4 sites fixed: line 992 (posStart/posEnd+1alias the samebuf) and the threestrcpy(buf, buf+pos)sites (now ~1414, 1424, 1462). Runtime-confirmed 2026-07-10: htmlview launches without crashing (was: instant crash on any HTML content). New pre-existing issue noticed during this check, NOT related to the strcpy fix: no HTML file on hand actually rendered visible text — real-world HTML has likely diverged too far from what this ~1994 parser understands. Separate task, needs its own fixture/triage (does it choke on DOCTYPE/charset, on modern tag soup, or something else); logged here so it isn't mistaken for a regression. - atk/supportviews/strtbl.c (3 sites) and label.c (3 sites)
— identical escape-stripping idiom (
while (t = index(t, '\\')) strcpy(t, t+1);for\,{,}) instringtbl__AddStringandlabel__SetText. Never hit a coredump — found only by the tree-wide grep, and no fixture exists to exercise a label/string- table entry containing\,{, or}. Accepted gate-only (compiles clean, installed, mechanically identical to the 3 runtime-confirmed sites above) — same precedent asptext/ltext/circlepi/mit-utilin point-10 batch 11. - atk/syntax/tlex/readtlx.c:260 — quote-stripping in the tlex
grammar reader (
seqline handling).atk/syntax/tlexis a build-time code generator (not a runtime app); found only by grep. Runtime check: rebuild whatever.tlxgrammar exercises a quotedseqargument. - contrib/calc/calcv.c:502 — leading-zero digit strip in the
calculator inset. Verified 2026-07-11:
contrib/calcis now in the active build (MK_CALC, see "calc inset" under Completed) and this fix compiles clean. - contrib/mit/fxlib/server/commands.c:230 — same idiom (
.@realm stripping in the MITfxcourse server). Still outside the active build: fails to compile for an unrelated reason, a missing generatedfxserver_err.hfrom a Kerberos code-gen step that's never been run in this checkout. Fixed by the same mechanical edit for correctness/consistency, but compile-unverified — no way to build the file right now. Verify wheneverfxlib/serveris ever brought into the active tree (same precedent aswpedita.chin point-10 batch 11).
typescript — crashes on launch (PTY failure + missing NULL check)
- First-ever launch of the
typescriptapp (2026-07-10, point-10 batch-6 runtime checks; not a -pi regression: atk/typescript was zero-fallout, no.ch/.cfile in the directory was touched). PrintsCan't connect subchannel(fromGetPtyandNamefailing — suspect PTY allocation doesn't work the way this code expects under the current terminal/sandbox), thenEXC_BAD_ACCESSinsidetypescript__Createat thetypescript_SetDataObject(self, ...)call:self = typescript_New()came back NULL becauseInitializeObjectreturned FALSE (the pty failure above), andCreatenever checks for that before dispatching throughself. Two bugs really — the underlying PTY/subchannel failure (macOS PTY compat, not LP64), and the missing NULL check that turns any such failure into a crash instead of a clean error return.
Insets to Repair
Insets with known breakage, or not buildable/enabled at all. Each is its own task; none block M1.
calc — FULLY WORKING — all rendering bugs fixed, confirmed 2026-07-12
Brought into the active build 2026-07-11 (see Completed → contrib/calc
inset). First real interactive exercise (2026-07-11/12) found one real
crash (fixed) and three real Xft rendering bugs, all now fixed. Full
trail, reproduction steps, and what was tried/disproven along the way:
revival/doc/claude-history/calc-text-rendering-investigation.md. Summary:
- Fixed, confirmed:
calc.c WriterNULL-pointer crash on every document checkpoint (sprintf'sintreturn cast tochar *). - Fixed, confirmed via lldb trace:
xgraphic.c GetXftForeColorused the staleforegroundpixeleven ingraphic_WHITE(erase) mode, since Xft never consults the core-X GC's color swap — erase-by-redraw was drawing in black, not white. - Root-caused and fixed 2026-07-12: the ghost was AA
erase-by-overdraw residue in
xgraphic_DrawChars's Xft path — "erasing" a string by redrawing the same glyphs in background color only exactly restores pixels where a glyph's alpha is 1; anti-aliased edge pixels stay partially gray forever, accumulating with each draw/erase cycle. Fixed by filling the glyph's advance-cell rectangle with the background color (XftDrawRect) instead of redrawing glyph shapes, whenevertransferMode == graphic_WHITE. User-confirmed: no more gray residue behind the final answer. - Fixed and confirmed 2026-07-12: a bug surfaced by the ghost fix
above — during incremental multi-keystroke redraws, the display showed
only a suffix of the correct string (typing
123+4=showed1,2,23,3+,23+4instead of1,12,123,123+,123+4), and a window focus-loss/regain always corrected it. Root-caused via a liveXGetImageframebuffer readback added toxgraphic_DrawChars: the server-side drawable consistently had the correct pixels even at moments the screen showed them missing, proving this wasn't a drawing defect but a rootless-XQuartz recomposite lag — Xft/Render-extension draws don't reliably reach the visible native window surface without an external nudge. Fixed with a self-XCopyArea"kick" through the core X11 path (known to repaint reliably) after each Xft draw, forcing the compositor to pick up the already-correct pixels. This also fixed an independently-discovered, broader symptom: text near a calc inset staying invisible until unrelated nearby redraw activity revealed it — same root cause, not calc-specific. Full writeup:porting-changelog.md's 2026-07-12 entry. - Intentional design: the "=" button remains highlighted after being pressed, staying highlighted until a different button is pressed — a common calculator UI pattern for showing the last-pressed button.
- Tried and reverted: a hypothesis that
xgraphic_DrawChars's alignment math should use the Xft-resolved font's metrics instead of the core "dummy" font's metrics (since Xft's fontconfig substitute for a custom Andy font could plausibly have different ascent/descent). Implemented, tested live, found to make zero observable difference anywhere (not just calc) — reverted back to original core-only metrics, then re-confirmed inert via a side-by-side Frame-animation comparison in both states. Not the cause of anything seen this session, in either direction.
zip — builds and loads now; solid-black render bug at -O, RESOLVED 2026-07-11
- Progress 2026-07-11:
MK_ZIPdefined inconfig/site.h, Makefiles regenerated downcontrib/zip/{lib,symbols,samples,utility}.contrib/zip/lib's ~21.chfiles were 100% untyped 1990s K&R style (never touched by the M1 rollout since the directory was inert) — typing them against real implementations took ~479 compile errors down to 0 (Sonnet-delegated mechanical pass + 6 real.c-side bug fixes: missing K&R param declarations inzipdf00.c/zipdi00.c/zipve02.c, a pointer-through-long-rock laundering cast inzipedit.c, a transposed-argument live bug inzipve00.c'sDrawStringcall, and 13 files'Build_Objectstubpeerparams retyped fromlong/inttozip_type_figure). All installed and indexed (build/dlib/atk/index), fonts installed,zipviewclass loads — the "not supported" placeholder is gone for good. Full details, including a Makefileinstall.time/$?staleness gotcha that silently skips reinstalling files after a-kbuild error, in memoryproject_zip_inset_status. - Also fixed 2026-07-11, general core-ATK bug, not zip-specific:
atk/basics/x/xgraphic.c's Xft (anti-aliased text) drawing path never applied the pane-level GC clip to itsXftDraw— zoomed-in text in any Xft-rendered, clip-relying view could bleed outside its own bounds. Fixed with a newxgraphic_GetClipBoundingRecthelper mirroringxgraphic_LocalSetClippingRect's clip computation; required relinkinglibbasics.a/runapp(statically linked). Runtime-confirmed: zip zoom no longer escapes its box. - RESOLVED 2026-07-11. Solid-black rectangle at
-O(correct at-O0). Root cause: classpp typed-dispatch signedness mismatch —zip.chdeclaredreturns charbut implementation isunsigned char. Full analysis: porting-assessment.md §16. Fix: one-line.chtype correction + classpp regeneration. Tree-wide scan of 566.chfiles found no other instances. Confirmed working end-to-end at normal default optimization. Tested againstCattey.turninandcontrib/zip/samples/dragon.zip. - Confirmed 2026-07-11 (found while gating an unrelated
MK_CALCchange), RESOLVED 2026-08-01 (M3 Wave 7 batch C2):contrib/zip/utility/ltapp.c:115,123—lt_Set_Debug(self->lt, debug)/ltv_Set_Debug(self->ltview, debug)pass aboolean(int)debugthrough an untypedSet_Debugclass method whose.ch-declared parameter isvoid *— same untyped-K&R-.chgap as the rest ofcontrib/zip/libbefore its M1-style typing pass, not a regression from anything touched this session. Blocked a full top-to-bottommake dependInstallgate (SUBDIRSorder putszipaftercalcincontrib/Imakefile). Fixed by M3 C2's.ch-typing treatment (Set_Debug( boolean debug );acrosslt/ltv/sched/schedv) — the same treatmentcontrib/zip/libalready got. Confirmed gone from both the subtree and tree-wide gates; seeclaude-history/m3/m3-rollout-runbook.md's C2 findings entry.
zip / calc / raster — insets fail to load when embedded inside a mixed-content document — RESOLVED 2026-07-26 (calc/zip/raster all runtime-confirmed)
- Found during M2 rollout point 4h's (
contrib/zip/lib) runtime check: a standalone zip-only document round-trips correctly (save/reload confirmed working), but the same zip inset content embedded inside a larger document — surrounded by ordinary text and other inset types — fails to render at all, "as if there is no zip inset present"; a subsequent save of that document loses the inset entirely.calcshows the identical symptom in the same test document;annotation,eq, andtableinsets in the same document render correctly (htmlrenders too, with its own already-known incorrect behavior). Test file: wdc's/tmp/t2.ez, later reproduced minimally withrevival/simple_calc.ez. - Confirmed not a regression from any M2 work (unchanged from the
original triage — the M2 diffs to the relevant files were additive-
only or a single unrelated
#includeline). Pre-existing, original- 1988-import code, not caused by the ANSI C conversion work — traced viafossil annotateto the initial-import commit, predating any modernization work. - Root-caused 2026-07-26, via lldb. The earlier "resync-on-failed-
Read" hypothesis (below, for the record) was directly disproven:
calc__Readwas breakpointed and confirmed to return0(dataobject_NOREADERROR) cleanly — no resync fires, the read genuinely succeeds. The real bug is on the write side:calc's sharedapt__WriteObjecthelper (atk/apt/apt/apt.c:524) wrote alongunique id into its own\begindata/\enddatatags using%dinstead of%ld— on this LP64 platform that silently truncates the id to its low 32 bits. The separately-written\view{calcv,id,...}reference tag (atk/text/text.c:1332) computes the same id correctly with%ld. Result: the two tags disagree (verified numerically — the view's id and the truncated id are bit-identical except for the truncated id missing the top 32 bits), so on reloaddictionary_LookUp(keyed by the correct id from the view tag) never finds the object registered under its truncated begindata id — a completely silent miss (atk/text/text.c:705-709, barereturn 0, no stderr at all, which is why nothing printed during the original triage).ziphas an independent instance of the identical mistake in its ownzip__Write(contrib/zip/lib/zip.c:307,324) — not shared code withapt.c, the same K&R idiom copy-pasted into a second file. Full writeup:porting-assessment.md§20, memoryproject_lp64_printf_id_truncation(supersedes memoryproject_embedded_inset_load_failure, which has the full investigation trail). - Fixed and runtime-confirmed 2026-07-26 for both
calcandzip:apt.candzip.cfixed (%d→%ld), rebuilt, installed (apt.do/zip.do); wdc confirmed both survive insert → save → reload embedded in a mixed document. rasterhas the identical bug, independently found via a tree- wide sweep for the same mistake (raster__Write,atk/raster/cmd/raster.c— its own independent Write function, not shared withapt.corzip.ceither): almost certainly the same vanish-on-embed/lost-on-save symptom would reproduce for an embedded raster/image inset, but this was never previously reported or tested — it was found by code inspection, not a runtime symptom. Fixed and rebuilt (raster.doinstalled). Runtime-confirmed 2026-07-26: wdc tested an embedded raster insert → save → reload in a mixed document — works correctly.- The tree-wide sweep also fixed ~30 other files carrying the same
copy-pasted mistake (most never previously reported broken, since
nobody had tested embedding those inset types the way this
investigation tested calc/zip) — see
porting-assessment.md§20 for the full inventory. Notablyeq's instance (eqvcmds.c) is in its Cut/Copy-to-cutbuffer path, not its ordinary save (which was already correct) — wdc confirmed eq Cut/Copy still works correctly after the fix.
<details> <summary>Original working hypothesis (2026-07-25, disproven — kept for the record)</summary>
simpletext__HandleBegindata (smpltext.c:901) already has the
2026-07-05 figure-fix's resync-on-failed-read fallback (falls back
to a raw "unknown" object and prints a warning to stderr if
dataobject_Read returns anything other than dataobject_NOREADERROR)
— that fallback is what should fire here if zip's/calc's Read
fails partway through when called via this embedding path
specifically, as opposed to when either class is the top-level/root
object of its own file. Directly disproven via lldb 2026-07-26:
calc__Read returns 0 (success) cleanly; the resync path never
fires. The real cause is the write-side %d/%ld truncation above.
</details>
ness — bison grammar extension blocker
atk/ness/objects/ness.grauses a multi-character string token extension specific to the Andrew bison fork. Ness scripting is unavailable until this is resolved. Options: implement the extension in a bison%skeletonor rewrite the affected grammar rules.atk/ness/{objects,type}are inert (not in the default build). Related loose end:celv's only callers live inness/objects, andnevent.cwas edited in point-10 batch 1 — compile-unverified until ness builds.
htmlview — crashed reading any HTML file (ReadSubString overlapping strcpy) — FIXED 2026-07-10, runtime-confirmed
- First-ever real engagement of htmlview (2026-07-10, point-10
batch-11 runtime checks; needs a
~/.ezinitto map.htmlat all, per the help instructions — without it ez reads HTML as plain text, which is why this never surfaced before). See "Overlapping-strcpy crash family" under Applications to Repair for the fix (all 4 sites inhtml.cnow usememmove, compiles clean, installed via the full gate). Runtime-confirmed 2026-07-10: htmlview launches without crashing (was: instant crash). A.ezinitin the home directory does NOT affect regular non-HTML ez startup (verified). New follow-on, separate from this fix: no HTML fixture on hand actually rendered visible text — likely real-world HTML has diverged too far from this ~1994 parser (see the html.c bullet under "Overlapping-strcpy crash family" above). 2026-07-19: this follow-on is now milestone H1 of "Objective: HTML mail rendering" (Current action plan) — triage/root-cause happens there, driven by a real-mail fixture corpus.
layout — excess whitespace — RESOLVED (transient, not reproduced 2026-07-24)
- Observed 2026-07-10 during point-10 batch-5 runtime checks: the
complex layout inset near the end of
Sherman.Allocappeared to render with excess whitespace margin around its contents. Presumed pre-existing, not a regression — zero files in atk/layout were touched in that batch. No longer reproduces (confirmed 2026-07-24). Likely a transient rendering artifact that cleared as other Xft/display work was completed, or a session-state issue. No explicit fix needed.
figure — menu commands ignored until inset regains input focus — RESOLVED (LP64 #3 fix, 2026-07-04)
- Observed 2026-07-09 in
95Summer.ez: figure inset menus posted but menu commands were ignored until the inset regained input focus. Fixed 2026-07-04 as part of the LP64 bug #3 audit:figv.c'sChangeZoomProcwas passing bare-1literal through untyped dispatch for zoom direction; on arm64, this zero-extended to0xFFFFFFFF, corrupting the menu command dispatch. Fixed with(long)-1cast (figv.c:129-130). No longer reproduces (confirmed 2026-07-24).
figure — figotext label rendering garbled — RESOLVED 2026-07-24
- Figure-inset text labels (
figotextobjects — box labels, captions) rendered corrupted/garbled instead of the real string, observed inPAPERS/conf/1993/InglettandNEWSLETTERS/EZ/95Summer.ez. Found during M2 rollout point 3a's runtime check; confirmed pre-existing and unrelated to that batch's fix via a controlled revert test (claude-history/m2/m2-batch3a-REPORT.md§11). Root cause found and fixed same day:atk/basics/common/ fontdesc.c'sfontdesc__StringBoundingBoxcomputed its string width viafontdesc_StringSize(font, graphic, string, (long *) &w, (long *) &junk), butw/junkwere declared plainint(4 bytes); the real implementation (xfontdesc__StringSize,atk/basics/x/ xfontd.c) writes through both out-params as genuinelong *(8 bytes), so every call overflowed 4 bytes past each stack slot — a live memory-corruption bug on every label recompute. Confirmed viafossil artifactagainst the original 2026-06-24 trunk import: the cast is verbatim 1990s CMU source, not something this port introduced — on the 32-bit hosts this code was written for,intandlongwere the same width, so the cast was a no-op; LP64 is what turns it into a real overflow. It evaded the M2 census's own compiler-warning-based audit specifically because the explicit cast suppresses-Wincompatible-pointer-types; seeporting-assessment.md§12's "New sub-variant (2026-07-24)" for the full writeup and a tree-wide census of this masking pattern (21 hits, only this one real). Fixed by wideningw/junktolongand dropping the now- unneeded casts. Rebuilt (atk/basics/common,libbasics.arelink,runapprelink) and confirmed live:95Summer.ezrenders correctly;Inglettrenders correctly except for the two items below (both pre-existing, both narrower in scope than this fix).
figure — italic text: non-monotonic sizing, distinct from the fix above (found 2026-07-24, open)
- While confirming the fix above against
Inglett, two remaining, narrower problems surfaced, both isolated to italic text (fontstyle:2) specifically — every plain/boldfigotextin the document now renders correctly:- A modest (~3-5%) width overflow on the two italic runs in the
document (
andy-16pt "The quick brown" lead-in and theandysans-10pt-italic "The quick brown..." label), enough to visibly overlap adjacent content but not a dramatic mismatch — likely just the ordinary cost of substitutingtimes/helveticafor the (uninstalled at these sizes)andy/andysansfont family, not a code bug. Quantified via a standalone core-vs-Xft width comparison tool; see below. - Real, unexplained bug: hand-testing in the figure toolset
(Figure → Toolset → ungroup → select text → font-size picker)
found that italic text size scaling is not monotonic —
10pt italic renders bigger than 12pt, and bigger than 20pt.
Plain and bold text both scale monotonically as expected; only
italic is affected. Root cause not yet found: the toolset's
size-selection code (
fontselv.c'sSetSizeProc/InsertSize) was checked and is not the cause (each menu entry resolves via a stable string-table handle, not by position); a faithful simulation of the core font-resolution engine (xfontdesc_LoadXFont'sClosestFonts/XExplodeFontNamefallback chain,atk/basics/x/xfontd.c) for one italic pair (10pt vs 12pt) came out monotonic and correct, so the inversion is not yet localized. Needs its own investigation session — not chased further here at wdc's request. Diagnostic tools used for both items above (not checked in, scratch-only):fontwidth_test.c(coreXTextWidthvs XftXftTextExtents8for the same resolved font) andfontpick_test.c(portsGetNthDash/XExplodeFontName/ClosestFontsverbatim to show which installed bitmap a given nominal size/style resolves to).
- A modest (~3-5%) width overflow on the two italic runs in the
document (
eq — integral symbol missing (suspect font pipeline, not eq)
- Integral symbol missing in eq insets (observed 2026-07-08 in
Sherman.Alloc, pre-existing — not a -pi regression). Suspects: symba PCF generation, or thexset fp+font-path setup. Other symbol glyphs render fine.
raster — convertraster RF read-back hang
convertraster intype=RFhangs reading back the.rasfile the same binary just wrote (observed 2026-07-09, logged before the atk/raster/lib -pi rollout — pre-existing, not a regression). Writer output also looks LP64-suspicious: header fields appear 8 bytes wide. Lead found 2026-07-12 (M2 point 0 triage, see Medium-term → ANSI C conversion):oldRF__WriteImage(oldrf.c:221) passes along buf[]topixelimage_GetRow, whose real signature wantsshort *dest— a 4x size mismatch,-Wincompatible-pointer-typesflags it directly. Not yet traced throughGetRow's bit-packing far enough to confirm/fix; likely root cause or a major contributor. Other codecs fine: raster identity rewrite, PostScript, MacPaint, Xbitmap write and Xbitmap→raster round-trip (byte-identical to identity output) all pass; baseline captured in~/src/AUIS/test-baselines/raster-pi/. The raster inset itself is proven working; this is the converter CLI only.
~~clock — face never draws~~ — working again, likely font/session state, not code (2026-07-12)
- Clock inset was observed instantiating with its face/hands never
rendering (2026-07-12, in
build/testing.ez). Manually bisected across the entire M1 rollout plus all recent zip/calc/Xft work — 9 checkpoints from6338ade7de(2026-07-07, before M1 point 1) through HEAD, each a full from-scratchmake Clean && make Worldrebuild — blank at every single one, including the oldest. No commit in that range explains it, so it was logged as a confirmed pre-existing, not-yet-root-caused bug. - Reopened same day: inserting a brand-new clock inset via ez's
<ESC><TAB>clock("insert inset by name") command rendered correctly, in the same session, same build. The old inset (parsed from serialized datastream text in the test file) and the new one (created fresh through ez's own inset-creation code path) are not the same code path, and only the old one was ever observed broken. - Concrete mechanism found:
clockview__InitializeObject(contrib/time/clockv.c:288-289) doesif (!(self->cursor = cursor_Create(self))) return(FALSE);followed bycursor_SetStandard(self->cursor, Cursor_Gunsight).xcursor__SetStandard(atk/basics/x/xcursor.c:97-107) hardcodesfontdesc_Create("icon", 0, 12)(font familyicon12) to build the cursor's fill pattern. If that font resolution fails for any reason,cursor_Createreturns null,InitializeObjectreturnsFALSEimmediately, and the clockview never finishes initializing — matching the observed symptom exactly (nothing draws at all, not just labels: hands are drawn later inRedraw, which never runs on an object that failed to initialize). - Not fully closed:
icon12itself was already confirmed present infonts.dirand resolvable viaxlsfontsbefore any of the 2026-07-12con10/con12console-font work (see "MK_CONSOLEbeing off..." below), so this isn't the same root cause as that issue. Current best explanation is a transient X-server font-cache/session state problem specific to whateverezprocess the old, broken clock instance lived in — not a permanent gap and not a code defect — but this hasn't been isolated further (e.g. by testing whether the old serialized datastream clock also now renders correctly in a freshezlaunch, which would confirm it's session-state and not something specific to the by-name insertion path).
image — JPEG/GIF import renders as a solid black box, TIFF import renders as a solid white box; raster renders correctly (found 2026-07-26, open)
- Found during M3 batch O2's (
overhead/image/jpeg,overhead/image/ tiff) runtime check: inserting an Image inset inezand importing a.jpg/.jpegor.giffile renders a solid black box; importing a.tif/.tifffile renders a solid white box. Importing an ATK native raster (.ras) file renders correctly. This is the generalimage/igraphicinset family (atk/image,atk/basics/common), not specific to any one format's decoder — GIF and raster both go through code untouched by O2 and show the same broken/working split as JPEG and TIFF respectively, so the pattern cuts across the O2 diff rather than following it. - Confirmed NOT a regression from M3 O2: bisected live (2026-07-26)
by stashing the batch's entire diff, rebuilding
libjpeg.a/libtiff.aand relinkingjpeg.do/tif.dofrom pristine, unmodified K&R source, and re-testing the identical JPEG/TIFF files — same black-box/white-box symptom on the pristine build. This inset family had never been exercised before in this revival (first-ever runtime test, same situation M1/M2 kept finding elsewhere in the tree); the bug is pre-existing, not introduced by the ANSI conversion. O2's own diff is gate-green (gated twice, deterministic) and unrelated to this finding — committed alongside this entry. - Working hypothesis, not yet investigated: wdc's own suspicion,
based on the black-vs-white split cutting cleanly across which
format renders solid black (JPEG, GIF) vs. solid white (TIFF) vs.
correctly (raster) — "something funky going on with drawables," and
possibly the same class of bug as the zip inset's solid-black
render bug (
porting-assessment.md§16, a classpp typed-dispatch signedness mismatch between a.ch's declaredreturns char/shortand the real implementation's signedness — RESOLVED 2026-07-11, see "zip" above). Not confirmed; needs its own dedicated debug session before being written up as root-caused.nm -gconsumer detail and exact runtime-check commands are inclaude-history/m3-o2-imagecodecs-REPORT.md. - Re-tested 2026-07-26 after M3 batch B1 (
atk/basics/common, which ownsgif.c/image.c, unlike O2's jpeg/tiff codec libraries): importing a different GIF file (foo.gif) now renders a solid white box, not black; re-importing the same JPEG test file (testorig.jpg) still renders solid black, unchanged. Not attributed to B1:gif.c's B1 diff was reviewed function-by-function and is pure K&R→ANSI signature syntax with zero semantic change (no type, body, or logic differences);jpeg.cwasn't touched by B1 at all (it's O2's file, a different directory) and shows no symptom change either, consistent. A separate, concurrent session also landed 11 commits touchingimage.c/image.ch(an LP64%d→%lddatastream-write fix,image__SendBeginData/SendEndData) between B1's start and this re-test; confirmed viafossil diffthat this fix is about the save/write datastream path only, not thegif__Loadimport/decode path, and gif's own file has no overlap with that commit set at all. Most likely explanation: the new test file simply exercises the still-unconfirmed underlying bug differently (consistent with "something funky going on with drawables" depending on file-specific state) rather than a code change on either side — but this is inference, not a confirmed root cause, same as the entry above. Still needs its own dedicated debug session.
Questions
- How do I get a right click with my magic pad?
- How do I get drag scroll working without having to click and drag the elevator?
Major milestones
2026-07-17: First SMTP mail sent by AMS — AMS/IMAP-project milestone 1 complete: scripted cui composes and submits through the real
dropoff()path over TLS to Fastmail, authenticated, end-to-end. Roughly 35 years after AMDS last moved a message by copying files through a distributed filesystem, the Andrew Message System speaks a mail protocol the rest of the world still speaks.2026-07-10: M1 complete — classpp emits fully typed dispatch casts by default across the whole active tree (11 rollout points, ~50 directories, ~35 years of
.chsignature drift found and fixed; five live LP64/caller bugs caught by the typed casts along the way: suite unsigned rocks, htmlview DisplayString transposition, clockv NewString, lexan ParseNumber int*/long*, noteview/stroffetv ICONSTYLE string literal). The compiler now type-checks every method call site tree-wide. Next: M2 prototype sweep.2026-07-05:
messagesapplication running with local mail store — "mail (Private BB; 0 new of 0)" confirmed in the folder panel. All three prerequisite streams closed simultaneously: AMS local backend alive, atkams/ interface working, ATK insets (lset, value, pushbutton/link) sufficient for the messages UI to render.
Completed
ez2mdconverter (revival/tools/ez2md): converts.ezfiles to Markdown; handles styles, footnotes, page breaks, nested insets, and raster images (decoded to inline PNG); tested against 51 archive documents- Full build: 278
.dofiles, 0 errors,make dependInstallexit 0 ezlaunches, renders documents, scrollbar/menus/keyboard input all workhelpapplication: multiple frames, topic navigation working- Dialog boxes: visible, correctly positioned, text readable
- Raster insets: rendering correctly
- Table insets: cell text visible (LP64
update.cfix) - Eq insets: complex equations render correctly
- Fad insets: fully working (LP64 fix + Xft XOR ghost fix + 30ms timing floor)
- Fnote insets: marker glyph centered correctly (Xft metrics fix, 2026-07-04); proven working — footnote marker and popup text display correctly in
Cattey.Writing helpapp: fully functional — Programs list panel scroll fixed (LP64 fix, 2026-07-04); regression tests below- Bp (page break) insets: proven working — visible as page-break rule in
Cattey.Writing - Srctext insets: proven working — indentation and syntax coloring render correctly (LP64 audit)
- Figure insets: proven working —
95Summer.ez's figure renders correctly end to end (see Chronological log 2026-07-04). Two independent bugs stacked on top of each other: (1) parser-desync — official CMUpatch.633(figattr tolerates unknown attributes from later format versions) plus newsmpltext.chardening (failed inset reads fall back to a rawunknownobject instead of corrupting the rest of the parse); (2) LP64 —figure__Read's$originline was parsed withsscanf(buf, "$origin %d %d", &val1, &val2)intolong val1, val2, the same %d-into-long pattern as the other LP64 audits, leaving stack garbage in the upper 32 bits oforiginx. That corruptedoriginxflows straight intofigview'spanx(SetDataObjectdoespanx = originx), pushing the entire figure's rendering ~4 billion pixels off-screen — content was being drawn, just nowhere near the visible clip region. Confirmed live vialldb: foundoriginx == 0x100000000in the runningfigview's memory. Fixed bothfigure__Readand the analogousfigure__ReadPartial. Sherman.Allocintegration test: text, eq, fad, cel/arbiter spreadsheet all render; zip unsupported (expected). Calc is a separate contrib inset, not part of this document — seecontrib/calcunder Completed.- Xft phase 1: body text rendering via client-side Xft (anti-aliased)
- Andy symbol fonts (
symba*.pcf) built and installed inbuild/X11fonts/ overhead/malloc/malloc.ciaddarenaarena-size pointer-arithmetic bug fixed (patches/contrib/malloc.ci.auis6.3.diff, 2026-07-04) — source-correctness only, see Historical patches audit below for why it has no runtime effect heremessagesapplication: running (2026-07-05) — local mail store (Private BB) visible in folder panel; three-pane layout, menus, and help text all rendering; AMS local backend + atkams/ interface + ATK insets all workingchartapplication: launched and runtime-verified interactively (2026-07-10, point-10 batch 5) — startup, chart creation, format switching, palette labels; exercises theSetChartAttribute/SetItemAttributerewritehtmlviewDisplayString transposition fixed (2026-07-09) — threemessage_DisplayStringcalls had priority/string transposed since the 1990s; those HTML-editing status messages display for the first timemkparser/cparser.cfixed-width table bug (2026-07-11) — the shared parser engine used by all five AUIS grammars (prsdate,eliy,eqparse,num,parsey) assumed every bison table was ashort; modern bison narrows some to 1 byte per grammar, corrupting every lookup into a narrowed table. Root-caused viaamsdemo's caption dates/ordering; fixed generically in the shared engine, not per-grammar. Seeporting-assessment.md§15 — a close cousin of the LP64 bug family (§12): different mechanism (generator-chosen storage width vs. ABI sign/zero-extension), same shape (1990s code assumed a fixed width; a modernized tool in the chain silently chose otherwise decades later).contrib/calcinset — brought into the active build 2026-07-11:#define MK_CALCinconfig/site.h, Makefiles regenerated downcontrib/calc(make Makefilesfromcontrib/). Unlikezip,calc.ch/calcv.chwere already fully ANSI-typed (not 1990s K&R) — no classpp typing pass needed.calcv.chad 11 K&R functions forward-referenced (called before theirstaticdefinition) via a stale non-staticforward declaration, which clang now rejects as a linkage conflict (static declaration ... follows non-static declaration); fixed by replacing the one non-static forward decl with properstaticANSI prototypes for all 11 internal helpers. Also fixed: threegraphic_BLACK(0xFF int constant) arguments passed directly tovoid *Tileparameters inFill_Area, needing the same(struct graphic *)cast already used atchart/charthst.c:238for the identical idiom; and 5 sites (calc.c:155,calcv.c:526,548,557,558) usingsscanf(...,"%F", &x)wherexisdouble—%F/%fonly fill 4 bytes, silently leaving the upper 4 bytes of eachdoubleas stack garbage, the same wrong-width-scanf shape as the documented LP64 Variant 4 class (just float/double instead of int/long) — fixed to%lf. The already-presentcalcv.c:502overlapping-strcpy fix (see Overlapping-strcpy crash family above) compiles clean now that the directory builds.calc.do/calcv.dobuild warning-clean of errors and install (make installincontrib/calc); full top-levelmake dependInstallgate confirmscontrib/calcitself builds clean, though the gate doesn't reach pastcontrib/zip/utility(pre-existing, unrelated break — see Insets to Repair → zip). Fully working — runtime rendering confirmed 2026-07-12; all identified bugs fixed (see Insets to Repair → calc for details).
LP64 bug classes identified and swept:
- Variant 1: Missing prototypes / pointer return truncation (23 sites)
- Variant 2: >8-arg untyped dispatch stack spill (classpp fix)
- Variant 3: int constant zero-extended through untyped dispatch
(observable_OBJECTDESTROYED, value_OBJECTDESTROYED,
class_VERSIONNOTKNOWN)
- Variant 4: %d with long * in scanf family (full tree audit done; one straggler found later and fixed — figure.c's $origin parsing, see Completed and Chronological log 2026-07-04)
- Variant 5: long/int mismatch in display positioning through untyped
dispatch (lpair, panel, dialog, table, fad, srctext, eq, metax, toez,
typescript margins; style__ReadAttr operand; figure_NULLREF sentinel; full audit committed)
Related but not itself LP64 (2026-07-22): a K&R-style empty-parens
extern declaration of a new variadic function crashes on arm64 —
the ABI passes variadic args on the stack and fixed args in registers,
so an under-declared call site emits the wrong calling convention
regardless of word width; symptom is a crash inside vsnprintf/
vfprintf, not a truncated value. Found building the IMAP writeback
change journal (MSJournal_Record, ams/libs/ms/msjournal.c); fixed
with a full ...-prototyped extern at every call site. Same root
pathology as the LP64 family (K&R declarations under-specifying type
info for a modern ABI) but a different mechanism — grouped here for
visibility, not counted as Variant 6. Full writeup:
porting-assessment.md §18; also in sonnet-playbook.md's bug-class
list (item 6) since that's what delegated sessions read first.
Variant 3 follow-up audit (2026-07-04) — bare -1 literals at call sites,
not just #defined sentinels:
Found via help's list-panel scroll bug: textv.c:455,
self->frameDot = text_CreateMark((struct text *) dataObject, -1, 0).
text_CreateMark dispatches through the untyped (struct mark *(*)())
class-method macro, so the bare int literal -1 isn't sign-extended to
the long pos field on LP64 — frameDot->pos ends up as garbage (observed:
4294967295, 4294967335, 8589934591 in lldb — all the "low 32 bits look
like -1, upper 32 bits are register garbage" signature). DoUpdate's
mark_GetPos(self->frameDot) != -1 check then spuriously fires on every
first redraw. Fixed: (long)-1 cast at the call site.
This is the same root mechanism as Variant 3 (observable_OBJECTDESTROYED
etc.) but the -1 is a bare call-site literal rather than a named
#defined sentinel, so grepping for the constant's name doesn't find it —
it only shows up by grepping call sites directly. A full sweep (see
methodology below) turned up 6 more confirmed instances, all fixed with
the same (long)-1 cast, all compile-clean and rebuilt/reinstalled:
src/atk/text/content.c:649,src/atk/textaux/contentv.c:134,186—content_Enumerate/content_Denumerate'sopos/pos(long) is checked< 0as an "enumerate everything" sentinel insrc/atk/text/content.c(content__Enumerate/content__Denumerate); the corrupted value would read as a huge positive number instead, silently skipping the enumerate-all path.src/atk/figure/figv.c:129-130—ChangeZoomProc'srock(long) is checkedrock<0/rock>0to decide zoom in vs. zoom out; the "Zoom Out" menu item andEsc-zkeybinding both passed a bare-1throughmenulist_AddToML/keymap_BindToKey(both untyped dispatch). If corrupted, Zoom Out would zoom in instead.src/atk/raster/cmd/rasterv.c:1634-1635—ModifyCommand'srock(long) is checkedrock == -1(exact equality) for "invert selection"; the "Negative" menu item andEsc-nkeybinding both passed a bare-1through the same two untyped-dispatch macros. If corrupted, Negative would silently do nothing (falls through all the==branches).
Audit methodology (repeatable for future sweeps): ```sh
class-dispatch-style calls (lower_Upper(...)) with a bare -1 argument
| grep -rEn 'b[a-z][a-zA-Z0-9]_[A-Z][a-zA-Z0-9]*([^;()](, | () *-1 *(, | ))[^;]*)' |
| src/ --include=*.c | grep -v "(long)-1|(long) -1|== *-1|!= *-1" |
This narrowed ~925 raw `-1`-near-parens hits down to 22 candidates. Each
candidate needs manual triage: (1) find the macro's dispatch — untyped
`(TYPE (*)())` cast is the risky pattern, a plain field-assignment macro
(e.g. `mark_SetPos`, `rectangle_SetRectSize`) or a normal prototyped C
function is safe; (2) find the receiver and check whether it actually
*consumes* the value in a way sensitive to its exact bit pattern (a sign
check `< 0`/`== -1`, or arithmetic) vs. ignoring the parameter entirely
(several `view_FullUpdate(...,-1,-1)` width/height args in `figv.c` and
`rastvaux*.c` are ignored by both `figview__FullUpdate` and
`rasterview__FullUpdate`, which recompute geometry from the view instead —
confirmed harmless despite passing through the same untyped mechanism).
**Deferred / not yet triaged** (lower priority, left as future audit
targets, not confirmed either way):
- `src/atk/basics/common/rect.c` / `figv.c:905` — `rectangle_InsetRect`
is a plain function but its header prototype
(`rect.h:73: void rectangle_InsetRect(/*LHS, DeltaX, DeltaY*/);`) has no
parameter types, so call sites don't widen `-1` to the real `long
DeltaX, DeltaY`. Unlike the confirmed bugs above, the receiver does
arithmetic (`+=`/`-=`) rather than a sign check, so a corrupted value
would grossly mis-size a rectangle rather than silently no-op. (Not the
cause of the `95Summer.ez` "messy screen" case — that turned out to be
a figure-attribute version mismatch, see Completed; this remains an
untriaged latent risk.)
- `environ_GetProfileInt(...,-1)` (messages/atkams, several sites) and
`cwp_Search(...,-1,...)` (ams/delivery) — likely safe (looks like a
plain `int`-returning function, not virtual dispatch) but unverified;
deprioritized since `messages`/AMS revival is long-term, not part of
the active inset sweep.
- `tlex_RecentPosition(...,-1 or -2,...)` (ness) — moot until the `ness`
bison grammar extension blocker is resolved; the code doesn't run yet.
---
## Historical patches audit (`patches/`) — complete, 2026-07-04
CMU's official 6.3.x point-release patches plus community/site contrib
patches from the 1990s live in `patches/official/` and `patches/contrib/`
(the same set is duplicated verbatim under `andrew-6.4/patches/`,
`trunk/patches/`, and the top-level `AUIS/patches/` — they're identical,
no need to check more than one copy). This was triggered by finding that
CMU had already patched the exact figure-attribute-version bug hit while
fixing `95Summer.ez` (see Completed, above) — worth checking here *before*
deep-diving into a new bug, since CMU or a site admin may have already
found and fixed it decades ago. Every file every patch touches was
diffed against current source (not just the patch descriptions) to
determine actual relevance.
**Applied:**
- `official/patch.633` — "make figure accept figures created with later
versions, including C++ 7.2+." Makes `figattr__Read` tolerate unknown
attribute names instead of returning `dataobject_BADFORMAT`. Applied
2026-07-04 as part of the `95Summer.ez` figure fix (see Completed).
- `contrib/malloc.ci.auis6.3.diff` — `overhead/malloc/malloc.ci`
`addarena`: `A.arenaend - A.arenastart` is `struct freehdr *`
subtraction, which the C standard defines in units of
`sizeof(struct freehdr)`, not bytes — undercounts the arena-growth
heuristic by ~20-24x. Fixed by casting both to `char *` before
subtracting. **No observable runtime effect**: `ANDREW_MALLOC_ENV` is
`#undef`'d in `config/site.h` and there is no `malloc.o`/`libmalloc.a`
anywhere in `build/` — this codebase runs on system `malloc` via libc,
Andrew's custom allocator is dead code here. Fixed anyway for source
correctness (submitted originally by the current user, `wdc@mit.edu`,
in 1995) in case `ANDREW_MALLOC_ENV` is ever revisited. `malloc.ci` is
`#include`d into `malloc.c`/`pmalloc.c`, which currently fail to
compile for unrelated pre-existing reasons (`AbortFullMessage`
static/non-static prototype conflict) — out of scope, this directory
isn't part of the active build either way.
**Investigated, found already fixed in our 6.3.1 baseline** (no action
needed — but worth knowing these bug patterns were already closed before
this project started, so don't waste time rediscovering them):
- `official/patch.631`, `atk/figure/figospli.c` hunk — guards
`ctemp[last+1].t4 /= ctemp[last+1].t2` division (spline math for
polyline figures) with `if (last >= 0)` to avoid an uninitialized-value
divide on degenerate (too-few-point) curves. Already present at both
call sites (lines ~148, ~210).
- `official/patch.631`, `atk/textobjects/unknown.c` (the exact file our
new `smpltext.c` hardening depends on) — all 3 hunks already applied:
`self->odata==NULL` typo (comparison instead of assignment, would have
left a dangling pointer after `text_Destroy`) is correctly `=`; `static
int tungetc` is correctly `static void`; `unknown__Read` already
`return`s `ret` at the end.
- `official/patch.631`, `atk/support/hash.c` hunk — use-after-free fix
(`return egg->value` after `free(egg)`) already applied; value is
copied to a local before the free.
- `official/patch.631`, `atk/text/tabs.c` hunk — `PrevTab >= 0` bounds
check already extended to `PrevTab >= 0 && PrevTab < self->number`.
**Not applicable:**
- `official/patch.631`, `atk/basics/common/im.c` hunk — `#ifdef
hpux`-only, doesn't affect Darwin.
- `official/patch.632` — AMS `parseadd.c` fix, `official/patch.634` —
AMS/`eatmail` coredump fix. Both out of scope; AMS/Messages revival is
long-term (see Medium-term below), not part of the active inset sweep.
- `contrib/symlink.patch` — makes a shared-lib install symlink relative
instead of absolute in `overhead/class/lib/Imakefile`. Confirmed dead
code path for us: it's inside `#else /* LIBDL_ENV */`, and Darwin's
config never defines `LIBDL_ENV` — we build a static `libclass.a`, not
the shared `libclass.so` this patch targets.
- All SGI/NetBSD/Solaris/HP-UX/RS6000 platform ports (`SGI-port.6.3.3.*`,
`NetBSD*.README`/`.diffs`, `Solaris*.diffs`/`.README`,
`patch.631-hp-only`, `dvi2disp.patch`, `mit.patch`) — assembler flags,
`stty`/`gtty` variants, `mode_t` sizing for Irix, `sys_errlist` typing,
etc. for platforms unrelated to macOS/arm64.
---
## Subsystem dependency lattice
Indentation shows inheritance / dependency. `[PROVEN]` means confirmed
working through runtime testing. Unlabelled leaves are untested.
overhead/class [PROVEN — loader, everything depends on this]
atk/basics [PROVEN — view, graphic, scroll, lpair, panel, sbuttonv, xgraphic, xfontd, xim]
dataobject [PROVEN] view [PROVEN] | | +-- bp / bpv [PROVEN] +-- scroll / sbuttonv [PROVEN] +-- raster [PROVEN] +-- lpair [PROVEN] +-- text ---- textview [PROVEN] | +-- fnote [PROVEN — Cattey.Writing: footnote marker + popup] | +-- textref / texttag [PROVEN — ex14/ex14.doc cross-ref page numbers] | +-- rofftext (extends text) | +-- srctext [PROVEN — indentation + syntax coloring confirmed] | +-- eq -- eqview [PROVEN — complex equation rendered from ia-archive/dec.91] +-- table [PROVEN — cell text visible after LP64 fix] +-- fad -- fadview [PROVEN] +-- pushbutton -- pushbuttonview | +-- link -- linkview (hyplink) +-- lookz -- lookzview +-- value -- valueview | +-- sliderv | | +-- bargraphV | +-- buttonV | +-- controlV, enterintV, enterstrV, fourwayV | +-- stringV -- clklistV +-- apt -- aptv | +-- org -- orgv (outliner) | +-- chart (charts) +-- cel (ADEW spreadsheet cell; needs value+text) | +-- arbiter (ADEW application builder) +-- lset (scrollable list view) +-- figure -- figview [PROVEN — 95Summer.ez renders correctly] +-- figobj hierarchy (figorect, figoplin, figoell, figogrp, figotext...)
application [PROVEN via ez, help] +-- ez [PROVEN] +-- help [PROVEN — multiple frames, topic nav, frame size correct] +-- fad [PROVEN] +-- typescript / pipescript (terminal emulator) +-- bush (shell) +-- org (orga) (outliner as standalone app) +-- chart (chartapp) +-- launchapp
contrib +-- writestamp [PROVEN] +-- calc [builds and installs clean, 2026-07-11 — runtime untested] ```
Note: help does not use lset — confirmed by source audit. lset is
unproven and requires its own test.
Inset testing sequence
Ordered by dependency depth; each step proves a layer the next relies on.
[PROVEN] items are already confirmed; start from the first unconfirmed entry.
| # | Inset / App | Test document | What it proves | Search string |
|---|---|---|---|---|
| 1 | fnote | [PROVEN] PAPERS/atk/Cattey.Writing |
inline text-in-text insets | look for superscript footnote markers in body text; click to expand |
| 2 | textref / texttag | [PROVEN] src/atk/examples/ex14/ex14.doc + ex15/ex15.doc |
cross-ref insets; page-number references that update dynamically | in ex14: search "Program Listing for Example 14 at the end of this section on p." — the number after "p." is a live textref pointing to the texttag at the listing |
| 3 | eq | ia-archive/dec.91 |
[PROVEN] equation editor; text marks confirmed | look for rendered equations with fractions and subscripts |
| 4 | table | ia-archive/aug.90 |
[PROVEN] cell text visible | spreadsheet cells with numbers and formulas |
| 5 | value (slider/button) | ia-archive/sep.90 or ia-archive/jan.90 |
value views; valueview dispatch chain | slider or button widgets embedded in text |
| 6 | lset | ia-archive/nov.91 or ia-archive/jan.90 |
scrollable list widget | scrollable selection list inset |
| 7 | pushbutton / link | PAPERS/conf/1995/widgets.ez |
hyplink chain: pushbutton→link→linkview | clickable button insets |
| 8 | fad | src/atk/adew/Title.doc |
[PROVEN] LP64 fix complete | animated/fading text title inset |
| 9 | org | src/atk/org/example1.org |
outliner; proves apt→aptv base | outline nodes with expand/collapse |
| 10 | rofftext | bin/rofftext -d <manpage> |
roff formatter on top of text | formatted man page output |
| 11 | chart | build/doc/atk/classes.org or synthesize |
proves apt branch independently of org | bar or line chart inset |
| 12 | cel / adew | src/atk/adew/vallist |
[PROVEN via Sherman.Alloc] ADEW stack: value+text+cel+arbiter renders | spreadsheet cells with live calculation |
| 13 | typescript | bin/typescript -d |
terminal emulator; crashes "Can't connect subchannel" — likely macOS PTY compat issue, not LP64 | terminal window inset |
| 14 | bush | bin/bush -d |
shell application | interactive shell |
| 15 | figure | NEWSLETTERS/EZ/95Summer.ez |
[PROVEN] two stacked bugs fixed: parser desync (patch.633 + smpltext.c) and LP64 $origin scanf corruption (figure.c); renders correctly end to end |
drawing/diagram insets in newsletter |
| 16 | Sherman.Alloc | PAPERS/atk/Sherman.Alloc |
[PROVEN] text+eq+fad+cel/arbiter all render; zip unsupported (expected) | multi-inset compound document |
| 18 | calc | Esc-Tab, type calc, Enter in any ez doc (see contrib/calc/calc.help) |
[PROVEN] fully working 2026-07-12; rendering bugs fixed (AA erase, recomposite lag), all tests pass | calculator button-grid inset |
| 17 | Cattey.Writing | PAPERS/atk/Cattey.Writing |
[PROVEN] writestamp, fnote, raster, |
No good test document exists for: lookz, launchapp, prefed
— these need synthetic test files or targeted app launches.
srctext is now [PROVEN].
Known non-starters: ness (bison extension blocker, still inert)
— detailed under Insets to Repair. zip now builds and loads
(see Insets to Repair → zip) though zip/utility is still broken.
clock/timeoday (contrib, lower priority, still inert). calc now
builds (see row 18 above; row kept lower-priority pending runtime test).
Heisenbugs (intermittent, not currently reproducible)
Display mess
Observed: On rare occasions, text will draw into the menu area. But I can't reproduce it reliably.
^V scroll hang on fresh window (spoon host)
Observed: on host spoon, repeatedly: opening help or ez and
pressing ^V to scroll the default window caused the process to die
(confirmed dead in debugger) while the X window persisted until XQuartz
was restarted. help would still believe a server process was available.
Triggered even on the default help window with no special document.
Stopped reproducing spontaneously once debugging attempts began.
Not reproduced on: Mac-mini. Not triggered by VS Code terminal (was running from native Terminal.app).
Possible cause (superseded, see below): the checkpoint timer UAF
(observable_OBJECTDESTROYED zero-extension bug, fixed 2026-06-30) was a
plausible match — scrolling a fresh window can trigger a checkpoint, and
the UAF produced a crash rather than a hang.
Xlib display-lock self-deadlock — deferred (reproduced 2026-07-04, root cause identified)
Reproduced by accident during the figure-inset LP64 audit: scrolling in
both ez (viewing NEWSLETTERS/EZ/95Summer.ez) and, independently, a
help window hung the same session. Not a crash this time — attaching
lldb to the stuck help process (no relaunch, no interrupt needed — it
was already wedged) showed:
frame #0: libsystem_kernel.dylib`__psynch_mutexwait
frame #1: libsystem_pthread.dylib`_pthread_mutex_firstfit_lock_wait
frame #2: libsystem_pthread.dylib`_pthread_mutex_firstfit_lock_slow
frame #3: libX11.6.dylib`_XLockDisplay
frame #4: libX11.6.dylib`XkbGetUpdatedMap
frame #5: libX11.6.dylib`XkbKeysymToModifiers
frame #6: libX11.6.dylib`XRefreshKeyboardMapping
frame #7: runapp`HandleWindowEvent
frame #8: runapp`xim__HandleFiles
frame #9: runapp`im__Interact
frame #10: runapp`im__KeyboardProcessor
frame #11: runapp`application__Run
frame #12: helpa.do`helpapp__Run
frame #13: runapp`main
Only one thread exists in the process, and it's blocked forever trying
to acquire Xlib's own display-connection mutex (_XLockDisplay) — a
self-deadlock, not a cross-thread one. HandleWindowEvent is responding
to an X MappingNotify (keyboard mapping changed) by calling
XRefreshKeyboardMapping, which tries to lock the display — but something
earlier in the same call chain already holds that lock (almost
certainly Xlib's own event-dispatch machinery calling back into
xim__HandleFiles/HandleWindowEvent while still holding it internally),
and the lock isn't held recursively. This matches the "intermittent,
input-related, seems tied to fresh windows" character of the original
report far better than the checkpoint-timer theory, and is not fixed
by any patch committed so far — this is a live, distinct bug.
Trigger appears to be keyboard-mapping churn (MappingNotify), not
scrolling logic itself — consistent with why ^V specifically was the
original trigger (a modifier-involving key combo) and why it's
intermittent (depends on X server-side keymap-change timing, not app
state).
Not yet investigated: which AUIS/Xlib call site re-enters
_XLockDisplay while already holding it; whether this is triggerable
deliberately (vs. needing to wait for an incidental MappingNotify);
whether it's an AUIS-side bug (calling into Xlib from inside a callback
that already holds the lock) or an XQuartz/libX11 packaging issue specific
to this environment. Needs a dedicated debugging session — see
revival/doc/runtime-debugging-guide.md for the general lldb debugging
process/cookbook developed for this project.
Regression test checklists
help application
Run: DISPLAY=:0; build/bin/runapp helpa -d
- Startup: window opens showing "A Guided Tour of Andrew" in the main panel
- Overviews pane: right panel top section shows entries (Andrew Tour, Multimedia, Mail, Programming); text is readable
- Programs pane: right panel bottom section shows programs list starting from the top of the list (first entry visible, scrollbar at top) — regression for LP64 frameDot bug
- Overviews link: click "Andrew Tour" in Overviews → main panel changes to that document
- Programs link: click any entry in Programs → main panel changes to that help topic
- In-text links: click a cross-reference link in the main panel text → navigates to linked topic
- Expand/Shrink Programs pane: use Panels menu → "Expand Programs" / "Shrink Programs" → pane resizes correctly
- Show History: use Panels menu → "Show History" → history pane appears listing previously visited topics
- History links: click an entry in the History pane → main panel navigates to that topic
ez application (menus)
Run: DISPLAY=:0; build/bin/ez build/testing.ez
Before testing, check ~/.ezinit. If it exists, it must start
with include /Users/wdc/src/AUIS/andrew-6.4/build/lib/global.ezinit
or every global menu/keybinding — including "Media" — silently
disappears. This is original 1988 atk/basics/common/init.c cascade
design (addmenu/addkey docstring at line 76), not a bug: app.c
loads ~/.ezinit first, and if it loads successfully, returns
immediately without ever reaching global.ezinit (where the
addmenu lines for Media live — see atk/ez/ezinit). A personal
init file replaces the global one unless it explicitly includes it.
This looks exactly like a code regression in menu construction and
cost a full manual bisection (6338ade7de through HEAD, 9 checkpoints,
each a clean from-scratch rebuild, all showing Media present) before
being traced to a stray one-line ~/.ezinit (added earlier for
htmlview testing, forgotten about) on 2026-07-12.
- Media menu present: textview "Insert"-area menu bar has a "Media" submenu (Equation, Header/Footer, PostScript, Raster, Spreadsheet, Animation, Hyperlink, Layout, Ness, Note, Writestamp, By name...)
- Clock inset: insert fresh via
<ESC><TAB>clockand confirm it renders — see Insets to Repair → clock (unrelated to the Media issue above; a parsed clock from serialized datastream text has been seen failing to render even when a freshly-inserted one works, root cause not fully isolated)
Active (instances running)
- Xft phase 2: menu rendering — deprioritized; menus are working acceptably with the current rendering path
Near-term
~~LP64 positioning sweep~~ — complete
All five LP64 variant classes identified, swept, and committed. Sherman.Alloc
and 95Summer.ez used as integration tests; both render correctly.
~~Messages application prerequisites~~ — DONE (2026-07-05)
Goal: get messages running with a local mail store. Three streams of work:
Stream 1 — remaining ATK inset prerequisites (unproven):
These insets appear in the messages UI and/or in rendered mail:
- lset (scrollable list) — mail folder/message list display; test with ia-archive/nov.91 or jan.90
- value / valueview (slider, button) — UI controls; test with ia-archive/sep.90 or jan.90
- pushbutton / link / linkview — hyplink navigation; test with PAPERS/conf/1995/widgets.ez
Stream 2 — AMS local mail store: found, 2026-07-04. The build already separates the message store/UI from the AMDS delivery daemon via independent Imake flags:
| Flag | Gates | Needed for local-store messages? |
|---|---|---|
AMS_ENV |
whether ams//atkams/ build at all (Imakefile:37-39), plus overhead/mail (libmail.a, libcparser.a) |
yes — currently #undef'd in config/site.h, overriding allsys.h's default of 1 |
AMS_DELIVERY_ENV |
ams/delivery/ (sendmail/vicemail/queuem/trymail) and ams/utils/ (nntp/muserver/purge/reauth/undigest) — the actual AMDS transport |
no — leave off |
SNAP_ENV |
networked "remote message server" variant (ams/ms, libcuis.a) vs. the local nosnap path (libcuin.a) |
no — leave off, local path is the default |
WHITEPAGES_ENV |
overhead/wpi/wputil; auto-forced only by AFS_ENV or AMS_DELIVERY_ENV |
no — stays off since neither of those is on |
With only AMS_ENV on, atkams/messages/lib's Imakefile builds amsn.do
against NLIBS (libcui.a, libcuin.a, libmssrv.a, libeli.a,
librxp.a) — the local, non-networked message store — and never touches
delivery or white-pages code.
The local-mailbox backend the user remembers is real and already in the
source: ams/libs/ms/newmail.c's ProcessNewMail(..., PROCESSNEW_MBOX, ...)
imports from a plain mailbox file returned by GetPersonalMailbox() in
ams/libs/ms/findmbox.c — a standard Unix mbox (~/mailbox, or the
mailboxdir profile override), with no AFS/AMDS/white-pages involved. This
is almost certainly the exact seam the user's fetchmail fork fed into at
MIT Athena. AFS_ENV/WHITEPAGES_ENV references in ams/libs/ms/mswp.c,
init.c, and atkams/messages/lib/{ams,stubs}.c are all #ifdef-optional
(mswp.c:980 even has an explicit #ifndef WHITEPAGES_ENV fallback path),
confirming this is a first-class supported configuration, not a hack.
Next action: ~~flip #undef AMS_ENV → #define AMS_ENV 1 in
config/site.h~~ — done, 2026-07-05. AMS_ENV/CONTRIB_ENV are on in
config/site.h. All newly-exposed subtrees (atkams/messages/lib,
overhead/mail, overhead/eli, ams/libs/cui, ams/libs/ms,
contrib/srctext/eatmail/time) fixed and verified compiling/linking
clean per-directory. User's first full top-level make dependInstall
(no -k) surfaced exactly 2 more link-time errors (nns's getla()
needing getloadavg() instead of dead /dev/kmem+nlist(), and a
missing ${RESOLVER_LIB} on nns's link line) — both fixed same-day,
full details in porting-changelog.md's 2026-07-05 entry. ams/msclients/vui
and contrib/tm — curses terminal clients on the removed BSD sgtty API —
remain conditionalized out of the build (MK_VUI/MK_TM) rather than fixed;
not needed for the GUI messages path. Rationale in porting-assessment.md
§7a. ams/msclients/cui was originally grouped with them but didn't actually
share that dependency — see the 2026-07-07 fix below.
First runtime test of messages (2026-07-05) segfaulted: EXC_BAD_ACCESS
in _platform_strlen via mailconf.c's CkAMSCellConfig (AndrewDir/
LocalDir called with no prototype in scope — same LP64 #1 pattern fixed
at 23 sites on 2026-06-30, recurring because overhead/mail was never
built/audited before AMS_ENV went on). Fixed mailconf.c plus a sweep
of 5 more active files with the same bare-call pattern (ams/libs/ms/init.c,
hdlnew.c; atkams/messages/lib/stubs.c; overhead/mail/metamail/metamail/{metamail,mailto}.c;
overhead/eli/lib/prims1.c); all rebuilt clean. Full details in
porting-changelog.md. Separately, contrib/bdffont turned out to be
unbuildable (missing bdfparse.act, no generator, no fossil history) and
was conditionalized out (MK_BDFFONT); see porting-assessment.md §7b.
✓ MILESTONE (2026-07-05): messages is running. "mail (Private BB; 0 new
of 0)" confirmed in the folder panel. Three-pane layout, menu bar, and help
text all rendering correctly.
Follow-up (2026-07-05): same-tip rebuild on host spoon segfaulted immediately.
Real SIGSEGV (confirmed via lldb, not a codesigning/kernel-kill artifact),
in CUI_GetHeaders's header-scanning loop. Two long/int mismatches in
CUI_GetHeaders's startbyte/nbytes/status params, both invisible at
compile time (no prototype in scope at the mismatched boundaries) — same
LP64 Variant 5 family as lpair__Init/style__SetNewIndentation, but this
time crossing a plain unprototyped C call, not just the void (*)() vtable
macros. ms/libs/ms/headers.c's MS_HeadersSince (int/int *) was the
outlier; cuilib.c's CUI_GetHeaders and the dormant SNAP variant
(cuisnap.c) already agreed on long/long *. Fixed end-to-end
(headers.c, ams.ch/amsn.ch/amss.ch, ams.c/amsn.c/amss.c,
capaux.c, foldaux.c, dormant ams/ms/ms.c); rebuilt clean. Full detail
in porting-assessment.md §12 and porting-changelog.md. Next up:
retest on spoon.
Stream 3 — atkams/ interface audit: resolved by the Stream 2 survey.
ams/Imakefile and atkams/messages/lib/Imakefile show the boundary is
exactly the Imake flags above — messages links against the local
libmssrv.a/libcuin.a regardless of whether AMDS is present. No IMAP
adapter is needed for the local-store path; that fallback remains available
later if the mbox approach hits a wall.
Contrib objects: CONTRIB_ENV on brings in calc demos gestures wpedit
time eatmail mit srctext (see contrib/Imakefile); tm and bdffont
deferred (§ above). Still TBD whether any of these besides srctext
(already a proven inset, see Completed) matter for the messages path
specifically.
gendemo — done; demo folder populates and reconstructs cleanly
✓ (2026-07-07) cui builds/links/installs — the blocker was a missing
${RESOLVER_LIB} link flag on its Imakefile (same bug class as nns's
2026-07-05 fix), not the BSD sgtty API as originally assumed. cui doesn't
use curses at all, and its one sgtty reference was already dead code
(POSIX_ENV is unconditionally on for darwin). Full detail in
porting-changelog.md's 2026-07-07 entry.
✓ (2026-07-07) gendemo itself has two independent bugs, both fixed:
- It reads its 23 demo posts (
d1/d1.heads...d23/d23.heads) relative to the current directory, not$ANDREWDIR— those files live only insrc/ams/demo/and are never installed. Mustcd src/ams/demobefore invoking it (ANDREWDIRis only used to findcui/arpadate). - With cwd fixed,
cui's finalreconstep segfaulted on the very first address caption it tried to build. Root cause: a new bug class — flex regeneratesoverhead/mail/lib/parsel.cat build time (no fossil history), and modern flex inverted the meaning of an internal init flag that a hand-writtenpareset_lexer()was poking directly instead of using flex's real public API. Fixed (yyrestart(yyin)); swept the whole tree and found/fixed one sibling instance (overhead/eli/lib/elil.flex, the ELI/FLAMES filter-language lexer — pre-emptive, no confirmed crash yet). Full writeup inporting-assessment.md§13, session detail inporting-changelog.md's 2026-07-07 entry. Verified:reconcompletes ("Reconstructed folder ~/.MESSAGES/amsdemo with twenty-three entries") repeatably, no crash.
Next up — two threads:
- ~~New, unrelated intermittent crash found while re-verifying
recon~~ — root-caused and fixed 2026-07-11. Thememmoveheap overrun and unkillable-UE-state hang (escalated 2026-07-09) were both symptoms of the same bug:mkparser/cparser.c— the shared, hand-written parser engine used by every AUIS grammar, not justprsdate— assumes every LALR table is ashort, but modern bison narrows several tables to 1-byte types when a grammar's value range allows it. Reading a 1-byte array through a(short *)cast merges pairs of entries into garbage, which manifested asparsedateheader()failing on every input (not just certain years), sometimes cleanly (fast syntax error), sometimes by a runaway state-machine loop that grew the parser stack without bound (thememmoveoverrun) badly enough to occasionally take unbounded time (theUEhang). Full root-cause writeup:porting-assessment.md§15. Since the crash is gone,gendemo's auto-invocation fromsrc/ams/demo/Imakefile'sinstall.time::target (disabled 2026-07-09,#if 0/#endif) can likely be re-enabled — not done as part of this fix; left as a follow-up decision since it changesdependInstall's default behavior. - Once
reconis fully stable, verifymessagescan actually browse and read the populatedamsdemofolder end-to-end (captions, dates, bodies). Partially done 2026-07-11: captions and Part 1…23 ordering verified correct interactively. Body content for each message not separately re-verified this session.
IMAP / AMS backend investigation (week of 2026-07-14)
With messages running against the local mbox backend, investigate whether
an IMAP adapter behind atkams/ is viable for connecting to a live mail
server. The atkams/–ams/ boundary is already audited (see Stream 3 above);
this is the next architectural step toward real-world mail use.
printf/fprintf %d/%ld audit
2,597 printf-family hits with long values and %d format specifiers
logged during the scanf audit. These produce wrong output for large values
but do not corrupt memory. Address as a batch; not blocking messages work.
Xft phase 2 (deferred)
Menu text rendering via Xft. Menus are currently acceptable without it. Only remaining X core font path dependency is Andy symbol and cursor fonts.
Update quickstart.md
Remove resolved known-issues entries as each fix lands.
Not current focus
typescript,bush,orgcrashes — details consolidated under Applications to Repair; defer until after messages + M1 closechart— runtime-verified 2026-07-10 (see Completed);launchapp— inert (MK_BASIC_UTILSoff), defer
Medium-term
ANSI C conversion (M1–M4) — plan of record, assessed 2026-07-08
Absorbs the former "Prototype sweep" and "Classpp typed dispatch" entries
here plus the long-term "ANSI C modernization" entry into one ordered
plan. Analysis — June mass-conversion postmortem, keystone finding, tool
verdicts, delegation guardrails — in porting-assessment.md §14.
Keystone: .ch files already carry full ANSI method signatures; classpp
parses and discards them. Emitting them (M1) type-checks every method
call site and definition tree-wide before any mass file editing starts
— the compiler becomes the auditor instead of grep.
- M1 — classpp emits types. Typed prototypes in
.eh(today:long text__Read();) and typed casts in all.ihdispatch macros (extends the 2026-06-30 ≥9-arg fix to every method). Kills LP64 Variants 2/3/5 structurally and catches signature drift (theCUI_GetHeadersclass of bug) at compile time. The machinery already exists in classpp (usePrototypesImport/Export,-p,-Dsignature/.descfiles,$(CLASSFLAGS)hook in andrew.rls — see porting-assessment §14 "M1 mechanics"); the code change is just splitting-pinto-pi/-peand dropping the>= 8gates behind-pi, defaults untouched. The real work is the per-directory rollout — see "M1 rollout points" below. - M2 point 0 —
-Wincompatible-pointer-typestriage (census 2026-07-12, extended and partly fixed 2026-07-23/24). A cheap, high-signal precursor to the M2 sweep proper: 483 warnings tree-wide, a fixed enumerable list, not requiring-Wno-implicit-function-declarationto come off anywhere. This is M1's bug signature (real/pointer size mismatches) surfacing in plain C calls that never went through a Class dispatch macro, so M1's typed casts had no chance to catch them. Grouping the log (grep -B1 "Wincompatible-pointer-types\]" dependInstall.log) by message pattern splits cleanly into benign-idiom noise and a few real-bug clusters:- Benign, already covered by the M1 runbook's ruling — leave
alone: ~150+ instances of a subclass pointer passed where the
cast names the defining superclass (prefix-layout subtyping,
expected tree-wide); ~55 instances of
struct X * → char *across many struct types (egg,style,chartapp, ...) plus theint () → char *cluster (55, mostlyroffcmds.c/rofftext.c) — both are the pre-ANSI idiom ofchar *used as a generic pointer (this codebase'svoid *substitute, e.g.hash.c's table API and roff command-handler tables). Cosmetic; M3/M4 territory if ever cleaned up, not a bug hunt. fselect.c:65(overhead/util/lib) — confirmed real, low urgency.int *passed where libc'sselect()now wantsfd_set *: 1988-era 4.2BSD int-bitmaskselect()calling convention, never updated when the platform moved to POSIXfd_set. Currently survives by coincidence, not correctness — Darwin'sfd_setword size is 32 bits and the code clamps its fd count to<= 32, so the regionselect()actually touches stays inside the 4 bytes of theintit was given. Fragile, not an active corruption. Only live caller:cui(ams/msclients/cui/unixmach.c). Fix: realfd_set+FD_SET/FD_ISSET, own commit.oldrf.c:221(atk/raster/lib) — strong new lead on the already-logged raster RF bug, not yet root-caused.oldRF__WriteImagedeclareslong buf[BUFBITS>>5]and passes it straight topixelimage_GetRow, whose real (Class-typed) signature isGetRow(long x, long y, long length, short *dest)— along/shortsize mismatch (4x) landing directly in the read/write path. This lines up with the existing Insets to Repair → raster entry ("header fields appear 8 bytes wide";convertraster intype=RFread-back hang) closely enough that it's very likely the root cause or a major contributor — not yet traced throughGetRow's bit-packing logic far enough to hand over a fix. Same cluster (long*/short*mismatches, 11 instances) also touchesraster.c,rasterio.c,paint.c,xwdio.c,suite.c— worth surveying together once theoldrf.croot cause is nailed down, in case it's one shared bug pattern rather of five separate ones.int */long*cluster, 67 instances — CENSUS AND FIXES COMPLETE 2026-07-24. Full classification inclaude-history/m2/m2-census-REPORT.md: 13 shared root shapes across two directions, all now fixed. 22 instances (one callee,fontdesc_StringBoundingBox) were caller-has-long-but-.ch- still-int *, the odd one out among itsStringSize/TextSizesiblings — fixed by widening to match (commit0a6cf595ef). The stretch-goal sweep (functions with no warning because the mismatch crosses a K&R untyped call boundary, same shape asMS_GetConfigurationParametersearlier in this doc) additionally found and fixed a live, reachable bug:MS_ParseDatewriting a class-typedlong *into a realint *implementation, hit bycaptions__MarkRangeOfMessages's uninitializedlonglocals — worse than the usual zero-init-masked half-fill (commitf4a9d6909b). The remaining 45 instances (9 shapes) — the caller-declares-int-but-callee-wants-long *stack-overrun direction — were fixed 2026-07-24 by widening each caller's local tolongafter checking every secondary use for width assumptions (commitd8af32c158; also fixed 4 pre-existing%d-vs-longformat-string mismatches found along the way). This rollout caused a live regression, found and fixed the same session: widening threeatkams/messages/libcallers exposed a dormant 35-year-old.ch/real-implementation width drift (LP64 variant #6 —MS_GetDirInfo/MS_GetNewMessageCount/MS_GetSubscriptionEntry/MS_NameChangedMapFilearelong *inams.chbutint *in their realams/libs/msimplementations), producing a garbled subscription-status message inmessages. Corrected by narrowing.ch/wrappers back toint *and reverting those three callers toint(commit0f45da237d); seeporting-assessment.md§19 for the full writeup and the general rule it establishes — before widening any Group-A-shaped caller, check the real K&R implementation's declared width directly, not just the.ch, since.chitself can be the stale side.char ** → char *; remove &cluster, 18 instances — FIXED 2026-07-24. Census found all 18 collapse to one root cause: threeCUI_*methods (CUI_DisambiguateDir,CUI_RewriteHeaderLine,CUI_RewriteHeaderLineInternal) are typedchar *inams.chwhen their realcuilib.cimplementations takechar **— every one of the 18 callers was already correct; clang's own "remove &" fix-it would have broken all of them. Fixed by widening the three.chsignatures (commitc496c2a9ea).
- Benign, already covered by the M1 runbook's ruling — leave
alone: ~150+ instances of a subclass pointer passed where the
cast names the defining superclass (prefix-layout subtyping,
expected tree-wide); ~55 instances of
Status: M2 point 0 is done except oldrf.c and fselect.c,
which remain open (already scoped, independent of the sweeps above;
one is tied to a known open bug — see Insets to Repair → raster).
Neither blocks starting the M2 sweep proper.
M2 — Prototype sweep — COMPLETE 2026-07-25.
-Werror=implicit-function-declarationsubtree-by-subtree (src/config/darwin/system.mcrCOMPILERFLAGS); fixed by adding#includes orexterndeclarations at call sites. Closed Variant 1 permanently — it had cost debugging time on every subtree activation before this. Real total: 3,888 fallout instances fixed across 29 directories, well past the original census (2,353 instances/396 files, 2026-07-24) once every directory's malloc-family blind spot was counted. Procedure, census, fallout taxonomy, and ordering:claude-history/m2/m2-rollout-runbook.md(shared session rhythm:rollout-procedure.md). Rollout points:- [x] Pilot —
atk/eq(done 2026-07-24; 10/10 census instances fixed — 8 missing<string.h>, 2eqview_Formatcross-file forward reference with no declaring header, fixed with an untyped K&R forward decl matching the tree's one existing precedent for it. Gate green, tree-wide and subtree-local both clean — first data point (not yet a ruling) that M2 fallout stays directory-local, unlike M1's cross-directory blast radius. Found one procedure gap, folded into the runbook: directories with bison/lex-generated sources needmake dependbefore the subtree-localinstall, or the generated header's absence masks real warnings behind a fatal error.) - [x] Small/leaf directory batch —
atk/frame,atk/adew,atk/value,atk/lookz,atk/help/src,atk/extensions,overhead/cmenu,overhead/fonts/cmd(done 2026-07-24; 70/70 census instances fixed across 24 files, all three taxonomy categories exercised — seeclaude-history/m2/m2-batch2-REPORT.md. Resolved the runbook's openFoldedEQquestion: real function, not a typo. Found a third "missing in-tree/project header" sub-case: a header exists but is stale/incomplete, and the flagged directory already had its own local-extern habit for the gap (overhead/cmenu'scmdraw.h,atk/help/src'sindex.h) — matched that existing convention rather than editing the outside header. Second data point for "subtree-local gate is sufficient" — this time including a statically-linked, tree-wide-consumed directory (overhead/cmenu) — zero fallout beyond the flagged directories either time. Gate green, 8-directory runtime check user-verified (ez,help,fdbbdf), no regressions.) - Mid-size directories, batched (see runbook's proposed ordering):
- [x] Batch A —
atk/basics/x,atk/basics/common,atk/figure,atk/syntax/tlex,atk/raster/cmd(done 2026-07-24; 137/137 census instances fixed across 34 files, no new taxonomy category — seeclaude-history/m2/m2-batch3a-REPORT.md. Third data point settling "subtree-local gate is sufficient," this time including the statically-linked X11/core-class directories and M1's former largest-blast-radius directory (atk/basics/ common) — zero cross-directory fallout either time. Found and worked around (without editing) a real pre-existing bug inoverhead/cmenu/cmenu.h(_STDC_/__STDC__typo). Runtime check surfaced a realatk/figuretext-rendering bug — confirmed via controlled revert/rebuild/fresh-restart test to be pre-existing and unrelated to this fix; see Insets to Repair → figure.) - [x] Batch B —
overhead/eli/lib,ams/libs/cui,ams/msclients/nns,overhead/mail/metamail/richmail,overhead/index(done 2026-07-24; 528 instances fixed across 34 files — far past the runbook's stale "1–42 each" estimate for this bucket (ams/libs/cuialone was 350) — seeclaude-history/m2/m2-batch3b-REPORT.md. Fourth data point settling "subtree- local gate is sufficient," this time includingams/libs/cui(linked intomessages'samsn.do) at the largest volume yet — zero cross-directory fallout. Two new taxonomy sub-shapes found: a wrapper-family header (fdplumb.h) that only declares part of its family, recurring with no local precedent across 3 directories; consumer-supplied callback interfaces with no declaring header anywhere (ReportErroret al.,richmail'scontroloutput/controlputc). Resolved the openoverhead/ index/index.hquestion from rollout point 2: now thatoverhead/indexis the flagged directory, extendingindex.hdirectly was correct (no competing local-extern habit).overhead/eli/libfound to have zero live runtime consumers in this build (ams/ms/SNAP_ENVdisabled,rdemounreferenced) — structural, not a testing gap.ams/msclients/nns's pre-existing SSLLIB link failure confirmed unrelated. Runtime check user-verified (messages,cuin,help,richtext/richtoatk), no regressions.)
- [x] Batch A —
- [x] Large, dedicated-session territory (~70–140 instances each;
gate schedule ruled 2026-07-24, see
claude-history/m2/m2-rollout-runbook.md's "Gate scope" section — subtree-local gate always required, tree-wide gate only where marked below):- [x]
overhead/util/lib— subtree-local gate only (done 2026-07-24; 74/74 instances fixed across 29 files — first bucket-4 directory where the real count matched the stale estimate exactly — seeclaude-history/m2/m2-utillib-REPORT.md. Confirms rather than undermines the gate-scope ruling: statically linked into bothrunappandamsn.do, same shape as the four directories that already proved subtree-local sufficiency. Found a real methodology blind spot:malloc/realloc/freeare clang builtins, so an undeclared call to one doesn't trigger the M2 diagnostic at all — invisible to the-kcensus (caught via asvcconf.cnear-miss before it became a bug; folded intorollout-procedure.md). First live test of the new command-style guidance: zero permission prompts across ~90 tool calls, strongly positive. Runtime check user-verified (ez,messages, test email sent), no regressions.) - [x]
overhead/mail/metamail/metamail— subtree-local gate only (done 2026-07-24; 338/338 instances fixed across 7 files — far past the stale estimate of 70, mostlymetamail.c/mailto.c's own large same-file forward-reference populations — seeclaude-history/m2/m2-metamail-REPORT.md. Structurally strongest gate-scope data point yet: this directory builds onlyProgramTargets, no library at all, so cross-directory fallout is structurally impossible, not just empirically absent. Runtime check found metamail crashes (SIGTTOU inExecuteMailcapEntry'sioctlcall) andmailto/splitmailfail on a missing/usr/lib/sendmail— both confirmed pre-existing and unrelated to this fix (metamail's non-functionality on this platform was already documented before this session; root cause now identified, see "Objective: HTML mail rendering").mmencoderound-tripped correctly. User-verified, proceeding to commit.) - [x]
atk/text— subtree-local gate only (done 2026-07-24; 50 census-visible instances matched the stale estimate exactly — but that match was misleading: a directory-wide sweep for the malloc-family blind spot (see below) found 106 more call sites across 18 files, invisible to the M2 census entirely, real total 156 across 23 files — seeclaude-history/m2/m2-text-REPORT.md. Cleanest gate-scope data point yet: every function touched confirmed statically linked directly intorunappvianm -g. Found a class family (textv.do/text.do's 8 files) with three independently-invented, non-overlapping local-extern conventions — matched whichever precedent existed per file. User-verified (ezediting/ read-only/save-restore/insert-file/style-editor,Sherman.Allocrender,indexproCLI), no regressions;indexpro.c's pre-existinggets()call triggers a macOS runtime deprecation warning, unrelated to this fix, logged as a minor pre-existing finding, not fixed here.) - [x]
atk/rofftext— subtree-local gate only (done 2026-07-24; 54 census-visible instances (vs. stale estimate 47) plus 50 more from the mandatory malloc-blind-spot sweep, real total 104 across 9 files — seeclaude-history/m2/m2-rofftext-REPORT.md. New taxonomy wrinkle: one same-file forward reference fixed by adding#include <roffcmds.h>(the file that defines the whole*_cmdfamily had never included its own already-complete header) rather than a hand-written extern. Structurally the cleanest gate-scope case yet: noLibraryTargetat all, only dynamically-loaded.dotargets, confirmed vianm -gto have zero symbols inrunapp. User-verified viahelp(roff rendering correct) and the standalonerofftextconverter (well-formed.ezdatastream output, brace-matched throughout — a good correctness signal for theBeginStyle/EndStyle/CloseStylestyle-stack fixes specifically), no regressions.) - [x]
atk/table— subtree-local gate only (done 2026-07-24; 154 census-visible instances (vs. stale estimate 113) plus 32 more from the mandatory malloc-blind-spot sweep, real total 186 across 9 of 10 files (print.cneeded zero fixes) — seeclaude-history/m2/m2-table-REPORT.md. Two new findings: (1) malloc-sweep methodology gap —table.c's ownmyrealloc()wrapper false- positives under a naive substringgrep; sweep pattern is now word-boundary-anchored and space-tolerant inrollout-procedure.md; (2) new taxonomy sub-case — a class-internal double-underscore method's declaration exists inspread.ehbut only outside anAUXMODULEguard, structurally unreachable from the oneAUXMODULE-consumer file (update.c) that calls it via a macro that (unusually) dispatches directly rather than through the routine table; fixed with a commented local extern. Structurally the sameDynamicMultiObject-only shape asatk/rofftext(noLibraryTarget), confirmed zero symbols inrunapp. User-verified (menu-inserted spreadsheet, formula evaluation incl. a deliberate malformed-formula error case, save/reload round-trip, directtablebinary launch,.tablefile-type auto-load), no regressions; baretablebinary with no file opens a plain-textezbuffer with no table-insert path — matchesez's own bare-launch default, not investigated further as a possible bug.) - [x]
overhead/mail/lib— subtree-local gate only (done 2026-07-25; 112 census-visible instances (matched the stale estimate exactly) plus 12 more from the malloc-blind-spot sweep, real total 124 across 22 of 33 files — seeclaude-history/m2/m2-mail-lib-REPORT.md. Widest-fan-out directory examined yet (libmail.a, ~25 consumer directories); extranm -gverification against 3 structurally distinct real consumers (amsn.do,cuin,overhead/mail/cmd's standalone tools) found zero symbol leakage, confirming subtree-local gate holds even at this scale. No new taxonomy category; malloc-sweep findings cleanly split into three shapes (invisible blind spot; stale wrong-typed extern that only became a hard conflict once<stdlib.h>was added; dead/unused stale externs). Caught and fixed its own self-inflicted*/-in-comment syntax error immediately. User-verified (arpadatestandalone check,cuinstartup, freshmessagesprocess folder-list load), no regressions.) - [x]
atkams/messages/lib— tree-wide gate required (themessagesapp's actual backend) (done 2026-07-25; 212 census-visible instances (vs. stale estimate 140) plus 124 more from the malloc-blind-spot sweep, real total 336 across 18 of 23 files — seeclaude-history/m2/m2-messageslib-REPORT.md. Both gates required and both clean: subtree-local twice for determinism, plus the full tree-widemake Clean && make dependInstall(233,099-line log, same 4 pre-existing baseline errors every prior session has documented, zero new ones, confirmed none fall within this directory's own build span).SNAP_ENVconfirmed disabled empirically;amss.c/amss.donever enter the build graph. Concrete LP64 finding: 6 functions (CUI_ DisambiguateDir,CUI_GetHeaders,CUI_Initialize,MS_GetDirInfo,MS_MatchFolderName,MS_UnlinkFile) arelong-returning at their real definitions while ~65 sibling functions in the same two families default toint— sourced from two independent places before declaring. No new taxonomy category; explicitly ruled out a recurrence ofatk/table'sAUXMODULEsub-case. User-verified (freshmessagesprocess with a real IMAP-backed folder list, opening a message, composing/sending, folder tree, scrolling, options panel), no regressions.) - [x]
contrib/zip/lib— tree-wide gate required (tree's highest-defect-density directory) (done 2026-07-25; 145 census-visible instances (vs. stale estimate 141) plus 111 more from the malloc-blind-spot sweep, real total 256 across 24 of 41 files — seeclaude-history/m2/m2-ziplib-REPORT.md. Both gates clean, including the second subtree-local determinism pass at the directory's normal unmodified-Olevel to confirm no new anomaly near the known pre-existing-O-only rendering bug (none found).AUXMODULEsub-case explicitly ruled out (structurally, zero files define it). Third concrete LP64 finding (zip_Enparse_Stream/zip_Deparse_Stream, bothlong-returning). User-verified with two new, real, pre-existing (confirmed unrelated to M2 via direct diff inspection) findings logged for dedicated investigation: zip/ calc insets failing to load when embedded in a mixed-content document (see "Insets to Repair" below), andezhorizontal text-block drag locking at position 0 after the first drag (see "Little Annoyances" above). Bucket 4 complete — next is the fixed tree-wide checkpoint beforeams/libs/ms.) - [x] Fixed checkpoint after the last bucket-4 directory: tree-wide
gate required regardless of which directory precedes it. Done
2026-07-25, run directly by the orchestrator (pure verification,
no fix work):
make Clean && make dependInstall, exactly the same 4 pre-existing baseline errors every M2 gate has documented, zero new ones anywhere in the tree. Bucket 4 fully closed.
- [x]
- [x]
ams/libs/ms(its own dedicated session; briefed on the fdplumb history first viaclaude-history/fdplumb-REPORT.md). Done 2026-07-25; 1567 census-visible instances (vs. stale estimate 892) plus 2 more from the malloc-blind-spot sweep, real total 1569 across 102 files — by far the largest single directory in the whole sweep (114.cfiles, ~38% of the original tree-wide census) — seeclaude-history/m2/m2-amsms-REPORT.md. Both gates required and both clean: subtree-local twice for determinism, plus the full tree-wide gate (238,642-line log, same 4 pre-existing baseline errors every M2 gate has documented, zero new ones, this directory's own build span independently confirmed clean) — this gate doubles as M2's own completion gate. Strongly confirmed the runbook's "a handful of functions dominate" prediction (top 10 functions = 45.6% of the total, all 5 of the runbook's own named examples in the actual top 6); thefdplumb.hpartial-wrapper-family gap alone accounted for 300 instances, the largest such population found in the sweep. Two more concrete LP64 mixed-width findings (conv64tolong,KRHash, bothunsigned long) plus three genuine near-misses where a naive first-match grep would have picked the wrong same-named function from an unrelated directory — all correctly resolved by checking real definitions and call-site usage. Self-caught and fixed a bulk-insertion bug (new declarations briefly landing inside a dead#ifdef AFS_ENVblock; caught by the next rebuild, fixed with nesting-depth-aware insertion, re-derived all affected files fresh). Notable open finding: the malloc-family blind spot's invisibility itself stopped holding partway through this session (malloc/free/reallocbecame census-visible, independently reproduced on this machine) — most likely a toolchain update mid-project; doesn't affect correctness anywhere since the sweep was always run unconditionally regardless of census visibility. User-verified (messagesfolder list and message open,cuin, a test send,imapsync, folder subscribe/unsubscribe), no regressions.
- [x] Pilot —
M3 — Definition conversion.
ansify(revival/tools/ansify, built and validated 2026-07-08 — see porting-assessment §14): static-fix tools → class methods/classprocs by signature-DB lookup (ansify --build-db, 565 classes) → file-local helpers from their own K&R declarations, strict parser (cproto rejected: can't read macOS SDK headers) → per-file compile gate with auto-restore. Per-subtree step: add-peto the directory'sCLASSFLAGS(its.ehmust be prototyped in the same step — narrow param types likecharconflict with typeless.ehdecls otherwise; proven oneq__WriteFILE), force regen,ansify --dir, clean build, triage DRIFT reports, commit. One subtree per commit, dependency order: overhead → atk/basics+support → atk/text → insets → apps → atkams/ams → contrib. Ratchet each completed subtree from-Wno-*to-Werror=implicit-int,strict-prototypes,int-conversion,incompatible-function-pointer-types. Procedure, gate-scope reasoning (stronger locality guarantee than M2 had —.ehis never installed tree-wide, same-directory quoted include only), ordering rationale, and batching plan:claude-history/m3/m3-rollout-runbook.md. M3 complete 2026-08-01 — 15 sessions, all 91 active directories converted; retired toclaude-history/m3/(prompts, reports,m3-batches.md, the runbook itself) now that the milestone is closed.M4 — Global strictness. Tree-wide
-Werroronimplicit-int,int-conversion,incompatible-function-pointer-types,implicit-function-declaration;-Wformatthen catches any remaining scanf%d/%ld(Variant 4) automatically.strict-prototypesdropped from the set (Phase 0 finding, 2026-08-01, pending confirmation) — unlike the other three, it doesn't isolate real bugs here: ~6,024 tree-wide matches, almost all the deliberate C89 "unspecified arguments" idiom M2/M3 used correctly and on purpose, not leftover K&R. Keep-std=gnu89until conversion completes; consider c99 after. Writable-strings stays deferred. Phase 0 (audit) and Phase 1 (global flip + census) both complete 2026-08-01. Real census: 1,778 errors across 83 of 91 directories (implicit-int1,079,incompatible-function-pointer-types515,implicit-function-declaration183,int-conversion0 clean) — far past the "small residual" the plan hoped for, so this milestone does need a real directory batch map after all:m4-batches.md, 24 batches across the same 7 dependency-order waves M3 used, built from the real per-directory counts. Also found and fixed a real prerequisite blocker along the way: classpp itself (overhead/class/pp/class.candoverhead/class/lib/class.c) failed to compile under the new flags, cascading into every-pe/-piconsumer — fixed (missingstdlib.h, two missing forward declarations, two missing return types), verified, not yet committed. Task breakdown, verified starting state, thestrict-prototypesfinding, and the classpp fix in full:m4-rollout-runbook.md. Phase 3 (fixing the real fallout) not yet started.
Scale: ~13,700 K&R definitions across ~1,301 of 1,544 .c files; ~5,100
are class methods converted by .ch lookup, not inference. M2/M3 runs
are delegable (Sonnet-class) under the §14 guardrails; M1 and
.ch-vs-.c signature disagreements stay top-level.
M1 rollout points (Import half: CLASSFLAGS = -pi per directory)
Rollout state lives only in committed Imakefiles; classpp defaults
never change until step 10. Per-step rhythm: set CLASSFLAGS → force
regen (delete the directory's generated .ih/.eh or touch its
.chs) → make Clean; make dependInstall → fix consumer fallout →
runtime spot-check → commit. Clean build passing is the definition of
done. Ordering is by external-consumer count (survey 2026-07-08,
porting-assessment §14), not directory nesting: pilots on
zero-consumer leaves, then the core, largest last.
- [x] classpp:
-pi/-pesplit,>= 8gates dropped under-pi(done 2026-07-08; verified byte-identical default output, binary installed) - [x] Pilot A —
atk/eq(done 2026-07-08; clean-build gate green, eq inset visually verified inSherman.Alloc. Findings — see porting-assessment §14 "Pilot A findings": macro-parameter capture bug class, fixed structurally in classpp; DoScript stray-*DRIFT ineq.ch, a ~35-year-old typo caught by the first typed rebuild; two process wrinkles for the runbook) - [x] Pilot B —
atk/figure(done 2026-07-09; clean-build gate green, figure inset visually verified in95Summer.ez— behavior unchanged; new pre-existing menu-focus bug logged under Little Annoyances. Findings — see porting-assessment §14 "Pilot B findings": typeless.chdeclarations (MoveHandle), rock-idiomlong→void *, and a six-fileBuild(action, v)vs runtime(v, action)transposition — the.chwas wrong for ~35 years; all fixes interface-side only) - [x] First cross-directory step —
atk/raster/lib(done 2026-07-09; ZERO fallout — the seven codec.chs were accurate; consumersraster/cmd+raster/convertrebuilt clean against typed.ih; gate green. First before/after test protocol:convertrasterbattery byte-identical to pre-rollout baseline (~/src/AUIS/test-baselines/raster-pi/, incl. Xbitmap round-trip == identity invariant); user visually verified 92Sep.ez raster inset and face.raster negate/flip-lr/flip-ud before and after. Pre-existing RF read hang logged under Little Annoyances pre-flip) - [x]
atk/frame(5 classes, 95 external; done 2026-07-09; gate green, frame chrome (windows, menus, scrollbars) visually verified. Findings — see porting-assessment §14:Enumerate'slong functionDatarock retyped tovoid *; six call sites across five files (framecmd.cx4,atk/textaux/contentv.c,atk/extensions/{compile,tags,deskey}.c) carried a redundant(long)cast on the pointer they passed — a one-caller-in-five omission (framecmd.c:768, bare pointer, no cast) is what first exposed the pattern as a live disagreement, which in turn prompted a runbook revision pre-authorizing deletion of these casts as part of the rock-idiom interface fix, since they launder a pointer throughlongrather than mean anything. First rollout point with import fallout in directories other than the flagged one, confirming the blast-radius-asymmetry prediction in §14) - [x]
atk/supportviews(17 classes, 178 external; done 2026-07-09; gate green,helpapp scrollbars/panel expand-shrink/matte chrome andezvisually verified. One fallout:sbutton.ch Enumerate'slong rockretyped tovoid *— same rock-idiom pattern asatk/frame/atk/figure, all three tree-wide callers already passed bare pointers, no(long)casts to delete) - [x]
atk/text(21 classes, 321 external; done 2026-07-09; gate green,helpregression checklist andez(Cattey.Writingfnote,ex14.doctextref) visually verified. Two rock-idiom fallouts, same pattern as points 5/6:pcompch.chATKToASCII/ASCIIToATKandtext.chEnumerateEnvironmentslong rockretyped tovoid *;EnumerateEnvironmentsagain showed the bare-vs-laundered-cast split (one caller inatk/lookz/lookzv.cpassed the pointer bare, five callers inatk/textlaundered via(long)— all five casts deleted per the point-5 pre-authorized exception). No new fallout pattern) - [x]
atk/support(19 classes, 450 external; done 2026-07-09; gate green,helpapp,ia-archive/jan.90'slset/buttonVwidget (first proof of both, previously unproven insets), and aFile > Save Allbuffer command all visually verified. Two rock-idiom fallouts:buffer.chEnumerate/EnumerateViews— same pattern as points 5-7 (8 of 9 callers laundered a pointer via(long), one bare-pointer omission atframecmd.c:552exposed it).list.chEnumerate— a genuine hard stop, escalated mid-session: rock declaredchar *but two callers (dired.cFindPosProc,buttonv.cfindkey) pass reallongintegers compared numerically, disagreeing with ~40 pointer-passing callers elsewhere. Resolved as a new dual-use rock pattern (ruling added to the runbook's rock-idiom bullet): retype tovoid *; the integer call sites get an explicit(void *)cast (dired.c:348,buttonv.c:489, plus a third found while sweeping,prefs.c:513inatk/prefed, which isn't part of the default build —MK_PREFS/MK_AUX_UTILSare off — so harmless but unverified locally); pointer call sites drop their now-redundant casts; callbacks (FindPosProc,findkey) untouched, since they're invoked through typelessprocedurepointers outside-pichecking. Also: the gate surfaced an unrelated pre-existing hang — seegendemobelow — worked around, not a rollout fallout.) - [x]
atk/basics/common(41 classes, 2,351 external; done 2026-07-09; gate green after four cycles,help/ezruntime battery visually verified. The directory's own.chs had ZERO local fallout; all fallout was consumer-side rock collisions. 16 rocks retypedvoid *across 10.chs (menulist AddToML/Chain*/Unchain/GetChained, im HandleMenu/ AddZombieHandler/EnqueueEvent/SetInteractionEvent/ SetDeleteWindowCallback, keystate SetOverride, init Load, view PostResource, namespace/proctable Enumerate, message AskForStringCompleted);keymap_BindToKeystayslongunder the new integer-majority ruling. ~100 call-site cast edits in ~50 consumer files, driven by static censuses, not the gate log (censuses + mechanical edits delegated to cheaper-model agents — see §14 "Point 9 findings" and the runbook's new methodology notes). Real bugs caught: clockv.c NewString missing prototype (LP64 pointer truncation), suite.c laundered out-params, htmlview.c DisplayString arg transposition (fixed as separate commit per ruling), filetype.c DeleteEntry attributes** misuse (logged, untouched)) - [x] Breadth: remaining atk (
value,adew,apt,basics/wm,basics/x,hyplink,syntax/parse, ...), thenatkams/ams,contrib(zip/libfirst),examples— delegable batches (one session + one gate per batch, ruled 2026-07-09; exhaustive batch list + per-session prompts: revival/doc/claude-history/m1-point10-batches.md)- Batch 1 (2026-07-09):
atk/value,atk/adew,atk/apt/{apt,suite,tree},atk/controllers(inert — not in default build). Two live-LP64-bug classes fixed (suite unsigned rocks feeding every handler callback; LinkTree missing param decl), the suite+treev attribute-pair convention expanded at 95 dispatch sites across 12 files, and two long-dormant caller bugs caught (bushv title-as-code no-op; chartv*X-for-&XCaptureString corruption) — see porting-assessment §14 "Point 10 batch 1 findings" and the runbook's new unsigned-rock and variadic-by-macro bullets. - Batch 2 (2026-07-10):
atk/basics/x,atk/basics/wm(inert —WM_ENVoff). ZERO fallout: census clean (no pair macros, no rocks, overrides match the point-9-typed defining classes), gate green first pass, full ez + help regression verified. Imakefile-only, like raster/lib. Census note: classpp shares comma types like C (GrayPattern(short a, b)casts as(short, short)) — verified empirically, not drift. [Correction, batch 3: classpp does NOT comma-share — override macros take the defining class's typed decl, which is what GrayPattern showed; see batch 3 findings.] - Batch 3 (2026-07-10):
atkams/messages/libalone. Gate green first pass, all fallout local (19 errors, one ring); messages runtime fixture verified. Seven.chdrift fixes (cvEng typeless, DisplayNewBody bare params, PostMenus by-value struct, AlterSubscriptionStatus 35-year arg transposition, ReadFromFile file-privateBoolean, SetCUIRock rock→void *+ one pre-authorized(char *)cast at ams.c:120). New pattern for the runbook: an unknown type token in a.ch(proc, a file-private typedef) emits an implicit-intcast param under gnu89 — a typed cast that lies, truncating function pointers on LP64; fixedproc→procedurein ams/amsn/amss.ch and cross-directory inorgv.ch(fldtreev inherits it; classpp reads the INSTALLED parent.ch, so the fix neededmake installin atk/org). See porting-assessment §14 "Point 10 batch 3 findings". - Batch 4 (2026-07-10):
atk/image,atk/hyplink,atk/console/lib+atk/console/cmd(both inert —MK_CONSOLE/MK_BASIC_UTILSoff, no generated Makefile, noconsolebinary),atk/raster/cmd. Gate green first pass. Two known-taxonomy fallout fixes, no new patterns:image'ssliderv.ch SetCallbackrock (long→void *, sole callercmapv.cpasses a bare pointer);hyplink'spshbttn.ch ParseRGBsignature drift (unsigned char rgb_vectdeclared by value, impl + all four callers use it as an array, matching the already-correctGetFGColor/GetBGColorsiblings).raster/cmd's own four.chs were zero-fallout (fully typed already).convertrasterbattery run for due-diligence but doesn't actually verifyraster/cmd—convrast.conly includesraster/libheaders, neverraster/cmd's; byte-identical regardless. Runtime: hyplink verified viaPAPERS/conf/1995/widgets.ez(pushbutton→link→linkview), raster/cmd verified viaNEWSLETTERS/EZ/92Sep.ez's raster inset;imageaccepted gate-only (no known fixture for its picture-format codecs, zero-caller local fix only). - Batch 5 (2026-07-10):
atk/chart,atk/org,atk/bush,atk/fad,atk/layout,atk/table. Gate green first pass (all fallout caught and fixed during chart's localmake -k install, before the tree-wide gate ran). chart carried the suite-identical variadic-by-macro attribute family across two classes (chart.chChart/Item Attribute,chartv.chChart/ChangeChart Attribute) — true arity declared, ~45 dispatch call sites mechanically rewritten (all local to atk/chart, zero external consumers), pair macros fenced for*_Specification-table-only use, per the ruling already in hand.chartobj.chalso had a ~35-year signature-drift typo (SetDataObject(struct char *)→struct chart *) and four typeless declarations (WhichItem,SetChartOptions,HitChart,ObserveChart);HitChart's typeless override repeated across five subclasses (chartcsn, charthst, chartmap, chartpie, chartstk). Two dual-use-attribute-value call sites (chartobj.c,chartpie.c,PrintStringargument) were missing the(char *)cast their siblings already had — found only once the tree-wide gate walked past the local rebuild's stopping point.org.ch NodeName(node)was fully typeless (zero callers tree-wide, so zero fallout risk); typed from the impl.bush,fad,layout,tablewere all zero-fallout — census clean, gate green, no.ch/.cedits needed. No new patterns for porting-assessment §14. Runtime: chart verified interactively (create/format/label a chart); fad+table verified viaSherman.Alloc. Two pre-existing bugs surfaced by first-ever runtime tests, not regressions (both logged under Little Annoyances): org crashes loading a file (Read_Body'stmpnam/strcpymisuse, same overlapping-strcpy-under-fortify class as bush's already-logged InitTree crash); Sherman.Alloc's complex layout inset renders with excess whitespace margin (zero atk/layout files touched this batch, so presumed pre-existing). bush's pre-existing startup crash confirmed unchanged. - Batch 6 (2026-07-10):
atk/textobjects,atk/textaux,atk/rofftext,atk/srctext,atk/typescript,atk/lookz. Gate green first pass. No attribute-pair macros anywhere in this batch. Three genuine drift fixes, no new patterns:rofftext/rofftxta.chhad two typeless declarations (ParseArgs(argc,argv),InitializeObject(self)) typed to match every sibling app'sParseArgs(int argc, char **argv)and the impl'sstruct rofftextapp *self;srctext/hlptext.chandsrctext/rawtextv.cheach had a signature-driftInitializeObject/FinalizeObjecttyped to the WRONG sibling struct (struct srctext */struct srctextview *instead of their own class), caught immediately by the local rebuild since both are cast-incompatible pointer types.textobjects/dired.ch'sEnumerateAll/EnumerateMarkedrock retypedlong→void *(all three tree-wide callers indiredv.calready pass pointers, same rock-idiom precedent as frame/figure/supportviews).textobjects/chlist.ch'sAddItemAtIndexhad a ~35-year transposed-parameter signature drift (.chdeclared(str, index, ...), impl and its sole caller use(index, str, ...)) — fixed to match.srctext.ch'sLookupclassprocedure was missing the**/[]on its hash-table parameter (declaredDict hashTableby value; impl and all 8 tree-wide callers useDict *hashTable[], and its two sibling classprocsBuildTable/HashInsertalready had it right) — an isolated typo, not a pattern.textaux,typescriptwere zero-fallout. Runtime: lookz verified viaPAPERS/atk/Hansen.Algebra; textaux'scontentv(Table of Contents) verified viaPAPERS/atk/Cattey.Writing(Hansen.Algebra has no section headings, so ToC has nothing to discover — Cattey.Writing is the fixture to reuse); help app confirmed no regression (textobjects' only live consumer,panel). srctext and textobjects'dired/chlist/unknownaccepted gate-only — no srctext/ctext document exists anywhere in ia-archive, PAPERS, or NEWSLETTERS, anddired/chlist/unknownhave no live consumer in the default build (chlist's only callers are contrib/wpedit and contrib/bdffont, neither built; dired and unknown have zero call sites anywhere, presumably reflective/by-name loading for unknown). typescript crashes on launch (new pre-existing bug, logged under Little Annoyances):typescript__Createdoesn't checktypescript_New()for NULL before callingSetDataObjecton it, andNew()returns NULL becauseInitializeObjectfails atGetPtyandName("Can't connect subchannel") — zero atk/typescript files were touched this batch (fully zero-fallout), so this cannot be caused by the diff. - Batch 7 (2026-07-10, live subset only): pre-flag census found
8 of the planned 12 directories (
ezprint,preview,toez,datacat,launchapp,createinset/null,music,prefed) are currently inert —MK_BASIC_UTILS/MK_AUTHORING/MK_AUX_UTILSare all off inallsys.hand no per-app override (MK_EZPRINT,MK_PREVIEW, etc.) is defined, so none are inatk/Imakefile'sSUBDIRSand none have a generated Makefile; deferred to a future batch (user decision: split rather than flip the macros on). Theez2ascii/ez2psbinaries already inbuild/binare leftovers fromcontrib/mit/util(batch 11, gated byCONTRIB_ENV, also off) plus a csh wrapper — not built fromatk/ezprintat all, so the planned CLI byte-diff battery had no live target and was skipped along with the rest of the deferred 8. [Correction, 2026-07-10 active-tree census:CONTRIB_ENVis ON inconfig/site.h(since 2026-07-05) andcontrib/mit/utilIS in the default build — the gate log showsbuilding (dependInstall)descents into it, andez2ascii/ez2psare rebuilt live by every gate, not leftovers. The "not built from atk/ezprint" half of the finding stands; the "CONTRIB_ENV off" half was a mis-census — see the Active tree section below for the reliable liveness check.] Ran the full runbook on the 4 live directories instead:atk/ez,atk/utils,atk/help/src,atk/extensions(all unconditionally inBASICS). Gate green first pass. Six genuine drift fixes caught by census before any build, no new patterns:utils/dialog.chandutils/dialogv.cheach hadInitializeObject/FinalizeObjecttyped to the wrong sibling struct (struct sbutton *selfinstead of their own class) — same pattern as batch 6's hlptext/rawtextv;help/src/hlptextv.chhad the identical wrong-sibling-struct drift (struct srctextview *selfinstead ofstruct hlptextview *self) — a different file from batch 6's srctext/hlptext.ch, just a confusingly similar name.help/src/help.chandhelp/src/helpdb.cheach declaredInitializeClass(struct help(db) *self)with a bogus extraselfparam the implementation doesn't take (impls take onlyclassID, matching the universal zero-paramInitializeClass()convention every other class uses).extensions/ezdiff.chhad the opposite arity drift:FinalizeObject()was missing itsselfparam entirely (impl isezdiff__FinalizeObject(classID, self)).utils/dialogv.ch'sPostInputchoicerockwas a rock-idiom retype (long→void *; its one tree-wide caller,frame.c:1746, already passes a bare pointer). Traced howInitializeObject/FinalizeObject/InitializeClassarity actually matters under-pidespite the user-facing convenience macros having zero external callers tree-wide: classpp's auto-generatedDestroy/Finalizewrapper code (baked into the.eh) calls the rawclassname__FinalizeObjectfunction by the fixed(classID, self)convention regardless of what the.chdeclares, so a.charity mismatch becomes a real prototype conflict once-piis on — not dormant. Confirmedstruct thisobject *self(used pervasively forInitializeObject/FinalizeObject/ObservedChangedself params across dozens of files, including several already flagged in batch 1) is a real, working classpp idiom that resolves tovoid *even under-pi— not a bug, left alone everywhere it appears (strinput.chincluded). Runtime:ezlaunch confirmed (including an Extensions-menu command); a Quit-with-unsaved-changes confirmation dialog exercised thedialog.ch/dialogv.chfix and thePostInputrock retype directly;helplaunch confirmed, including ahlptextview-rendered topic with working hyperlinks. All three user-verified, no regressions. Checkins: bug fixes 105b96414a, rollout 165e3862b6. - Batch 9 (2026-07-10, live subset only, batch 8 skipped ahead
of per user request): pre-flag census found 21 of the 22
planned directories inert — all 19
atk/examples/ex*dirs (MK_EXAMPLESoff inallsys.h, no per-app override) and bothrdemodirs (rdemoisn't referenced anywhere insrc/Imakefile'sSUBDIRSat all — a standalone package with its ownconfig.csh/config.hgeneration, never part ofmake dependInstall). Onlyoverhead/class/testingis live. Same user ruling as batch 7: split, flag/verify the live dir now, defer the rest as Batch 9b. Both.chfiles (testobj.ch, testobj2.ch) were already clean — noInitializeObject/FinalizeObject, no pair macros, no typeless params — zero fixes needed, pure flag-and-gate. Gate green first pass; confirmed real typed casts in the local.ihfiles directly (this directory has noInstallClassFiles, so nothing copies tobuild/include). Runtime check skipped by user choice: the only artifact,testmain, is a class-loader self-test ending inwhile(1);, not part of the normal install path — matches the batch's own "gate is the whole verification" guidance. Checkin: rollout-only, no bug-fix commit needed. - Batch 8 (2026-07-10, live subset — first Sonnet-delegated
batch):
atk/syntax/{parse,tlex,sym}; ness dropped (inert, bison blocker). Gate green first pass. Six known-taxonomy drift fixes (wrong-sibling structs, int/long index params, unsigned name params, FindAll rock to impl'slong *, Create's error handler tovoid (*)()) — details in claude-history/m1-point10-batches.md. One hard stop escalated and ruled:lexan.c ParseNumberpassed along *whereTransEscapetakesint *— live LP64 bug, fixed with aninttemporary as its own commit. Runtime: ctext syntax coloring/indent user-verified on a scratch.cin ez. Checkins: d3386126d5 (.ch), 7ad519b869 (lexan.c), 6b1564ec89 (rollout). - Batch 11 (2026-07-10, live subset — Sonnet-delegated):
contrib/{mit/annot, mit/util, srctext/html, srctext/ptext, srctext/ltext, time, wpedit, demos/circlepi}. Gate green, ez2ascii battery byte-identical before/after (new baseline~/src/AUIS/test-baselines/ez2-pi/; ez2ps excluded — it execs inert ezprint + eqn/ditroff). Six .ch drift fixes (typeless SetDesired/DecidedSize/RecommendSize; wrong-struct FinalizeObject ×2 incl. wpedita.ch borrowing AMSstruct folders *; AddImage missing*; ReindentLinestruct mark *→long posmatching sibling ptext.ch) + one pre-authorized dual-use rock cast (html.c). One hard stop escalated and ruled: noteview.c/stroffetv.c defined ICONSTYLE/TITLESTYLE as the STRING LITERAL"fontdesc_Plain"— a ~35-year copy/paste bug truncating a pointer into every note/troff inset's font-styleint; fixed to the bare symbol + the missing<fontdesc.ih>includes, own commit. Census correction: wpedit is inert one level deeper than the gate log shows — descent happens but its Imakefile body is entirely#ifdef AMS_DELIVERY_ENV-gated (flag committed inside the guards, compile-unverified; runbook liveness rule refined: descent ≠ compilation). ptext/time/circlepi/mit-util zero-fallout, typed casts verified in all 27 installed.ihs. Runtime: note inset (exercises the ICONSTYLE fix path) and clock inset user-verified; htmlview surfaced a NEW PRE-EXISTING crash (ReadSubString overlapping strcpy, logged under Insets to Repair — crash precedes the batch's only html.c edit in execution order, so mechanically not a regression); ptext/ltext/circlepi/mit-util gate-only by user sign-off. Checkins: 7eaec122fd (live-bug fix), f46de124ed (rollout). - Point 10 is COMPLETE (2026-07-10): every live
.chdirectory in the active tree now builds under-pi. Only point 11 remains for M1.
- Batch 1 (2026-07-09):
- [x] Default flip (done 2026-07-10): classpp emits typed import
casts (
-pibehavior) by default (class.cusePrototypesImportAll = TRUE;-piaccepted as a no-op); all 50 per-directory-piflags deleted. Hybrid execution: classpp edit + unit proof top-level (flagless regeneration of testobj.ch byte-identical to flag-era output), mechanical remainder Sonnet-delegated. Gate green. Decisive proof: all 341 installed.ih/.ehheaders byte-identical to the pre-flip baseline (~/src/AUIS/test-baselines/ point11-headers/before/) — the default is bit-for-bit equivalent to the flags it replaces. ez/help/messages regression battery user-verified. Checkins: ff35ac3904 (classpp flip), 4f6c344e44 (flag deletions). M1 IS COMPLETE. - [ ] Export (
-pe) is not sequenced here — it rides with each subtree's M3 conversion, since its blast radius is only the implementing directory
Steps 2–4 are top-level work (learning the fix patterns); 5–10 are increasingly delegable once the patterns are documented.
Active tree — census 2026-07-10
M1's scope is the active tree: directories the default build
actually descends into. Liveness ground truth is the gate log —
grep '^building (dependInstall)' dependInstall.log — NOT Makefile
presence: stale Makefiles from before subtrees were conditionalized
out survive in atkbook, tm, bdffont, and prefed, and a
mis-census around exactly this fooled the batch-7 session into
recording CONTRIB_ENV as off (it is on, and contrib builds — see
the correction in batch 7 above).
Census result: 108 directories contain .ch files. 46 are live
(35 flagged + the 11-directory gap above); 62 are inert (4 carry
courtesy flags: basics/wm, console/lib, console/cmd,
controllers). The inert 62 break down by gate:
- Off in
allsys.h:MK_EXAMPLES(ex1–ex19);MK_BASIC_UTILS/MK_AUTHORING/MK_AUX_UTILS(ezprint, preview, toez, datacat, launchapp, createinset/null, music, prefed);WM_ENV(basics/wm);MK_CONSOLE(console/lib, console/cmd) - Off in
contrib/Imakefile:MK_ZIP(zip/lib, zip/utility — see Insets to Repair),MK_CALC,MK_CHAMP,MK_GESTURES(gtext),MK_TM,MK_BDFFONT;alinkis SunOS-only;atkbook(18 dirs),mit/neos,pobbconf,snap2aren't inSUBDIRSat all - Never wired into
src/Imakefile:rdemo/{hide,rdemosh}
Consequence of point 11: once the classpp default flips, inert
directories need no Imakefile flag ever — any inert subtree enabled
later gets typed casts automatically, and the runbook's census/fix
work simply happens at enable time as part of turning it on.
Batches 7b, 9b, 10, and 11's inert remainder are therefore obsolete
as flagging exercises; each survives only as a "run the runbook
census when enabling" note attached to its gate. M1 ends at point
11 with typed dispatch across the whole active tree. Full ANSI C —
prototypes everywhere (M2), K&R definition conversion (M3), global
-Werror (M4) — continues from that foundation.
~~Integration test: Sherman.Alloc~~ — proven
All insets in Sherman.Alloc render correctly (fad, cel, arbiter, eq, table);
zip unsupported as expected. Multi-inset compound documents confirmed working.
~~zip inset~~ — root-caused, moved
Moved to Insets to Repair → zip: it isn't broken, it was never
built (MK_ZIP never defined anywhere). Repair path documented there.
~~ness.gra bison extension~~ — moved
Moved to Insets to Repair → ness (same content).
Andy font path automation
xset fp+ build/X11fonts && xset fp rehash is currently a manual step
required each XQuartz session. Automate via a wrapper script or by
installing the PCF files into XQuartz's default font path
(/opt/X11/share/fonts/).
~~fad view "wrong icon" bug~~ — root-caused, not a regression (2026-07-12)
Suspected fad (animation) drawing bug — ams/demo/d10's diagram
showed a literal "M" instead of an icon for its "Client Program" node.
Traced to con10 (a console-app icon font the diagram happens to
reference) never being built, because MK_CONSOLE gates out all of
atk/console including console/fonts — not a fad defect at all.
Full root cause and permanent-fix options: porting-assessment.md →
"MK_CONSOLE being off silently breaks con10/con12...". Fixed and
confirmed 2026-07-12: once con10 resolves, the animation renders and
plays correctly. Codified as revival/tools/install-console-fonts
(builds only console/fonts, never touches the rest of console) —
re-run it any time a full clean rebuild wipes build/X11fonts/; not a
true upstream fix (that needs console/fonts carved out of the
MK_CONSOLE gate, or MK_CONSOLE itself enabled), but no longer a
manual multi-step recipe either.
~~Frame size reporting in help~~ — fixed
Long-term / architectural
ANSI C modernization (full K&R conversion)
Elevated to medium-term — see Medium-term → ANSI C conversion
(M1–M4). The modernize tool is no longer the starting point; see
porting-assessment.md §14 tool verdicts.
Messages application
Elevated to near-term focus — see Near-term section for the active work plan. Moved here for architectural notes only.
messages is the AUIS mail/bulletin-board client. Full AMS revival is
off the table — the AFS/shared-filesystem delivery model is a dead end.
See Near-term → Messages prerequisites for the two viable backend paths
(local store vs. IMAP adapter).
Stretch goals
Pie menus
AUIS's menu architecture is well-suited to Don Hopkins' pie menu design. The menu system is clean and the attachment points are known. A collaborative implementation project once the core system is stable.
Additional applications
bush (shell), typescript (terminal emulator), org (outliner),
chart, layout -- each is a symlink to runapp and built; exercise
and fix as interest warrants after core insets are stable.
ez2md improvements
ez2md (revival/tools/ez2md) converts .ez documents to Markdown; text,
page breaks, footnotes, and raster images are fully handled, but table, eq,
figure, fad, image, and link objects currently render as placeholder
comments (orphaned from an earlier, pre-C-revival phase of this project;
folded in here from a since-retired revival/ROADMAP.md). Two
follow-ons, not started:
- Table rendering — parse the ATK table/spreadsheet format into Markdown tables.
- Batch conversion of archive documents — convert the FAQ, README,
newsletters, and papers to Markdown for easier browsing (perhaps into
revival/converted/, alongside the originals).
Raster insets are decoded from their run-length-encoded 1bpp bitmap format
and re-encoded as inline data:image/png;base64,... images (2026-07-16) —
see revival/tools/ez2md's decode_raster/encode_png_1bit. Version-1
rasters and the refer/share/file keyword variants (rare in archived
documents) still fall back to a placeholder comment. Chosen deliberately
over sidecar .png files since ez2md is meant to be used as a stdin/stdout
filter with no natural output directory to write sidecar files into; the
tradeoff is that at least one browser Markdown-viewer extension with a
restrictive CSP won't load data: image URIs; VS Code's built-in preview
renders them correctly.