AUIS revival

roadmap.md at tip
Login

File revival/doc/roadmap.md from the latest check-in


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

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.

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:

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:

  1. 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.
  2. 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.
  3. 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


Little Annoyances to clean up

Keymap:

make Clean transiently deletes src/atk/adew/Arb:

messages: X_OpenFont BadValue (observed 2026-07-23, not yet investigated)

ez: horizontal text-block drag locks at position 0 after first drag (observed 2026-07-25, not yet investigated)

filetype.c DeleteEntry:


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.

typescript — crashes on launch (PTY failure + missing NULL check)


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:

zip — builds and loads now; solid-black render bug at -O, RESOLVED 2026-07-11

zip / calc / raster — insets fail to load when embedded inside a mixed-content document — RESOLVED 2026-07-26 (calc/zip/raster all runtime-confirmed)

<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

htmlview — crashed reading any HTML file (ReadSubString overlapping strcpy) — FIXED 2026-07-10, runtime-confirmed

layout — excess whitespace — RESOLVED (transient, not reproduced 2026-07-24)

figure — menu commands ignored until inset regains input focus — RESOLVED (LP64 #3 fix, 2026-07-04)

figure — figotext label rendering garbled — RESOLVED 2026-07-24

figure — italic text: non-monotonic sizing, distinct from the fix above (found 2026-07-24, open)

eq — integral symbol missing (suspect font pipeline, not eq)

raster — convertraster RF read-back hang

~~clock — face never draws~~ — working again, likely font/session state, not code (2026-07-12)

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)


Questions


Major milestones


Completed

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:

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

  1. Startup: window opens showing "A Guided Tour of Andrew" in the main panel
  2. Overviews pane: right panel top section shows entries (Andrew Tour, Multimedia, Mail, Programming); text is readable
  3. 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
  4. Overviews link: click "Andrew Tour" in Overviews → main panel changes to that document
  5. Programs link: click any entry in Programs → main panel changes to that help topic
  6. In-text links: click a cross-reference link in the main panel text → navigates to linked topic
  7. Expand/Shrink Programs pane: use Panels menu → "Expand Programs" / "Shrink Programs" → pane resizes correctly
  8. Show History: use Panels menu → "Show History" → history pane appears listing previously visited topics
  9. 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.

  1. 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...)
  2. Clock inset: insert fresh via <ESC><TAB>clock and 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)


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:

  1. It reads its 23 demo posts (d1/d1.heads ... d23/d23.heads) relative to the current directory, not $ANDREWDIR — those files live only in src/ams/demo/ and are never installed. Must cd src/ams/demo before invoking it (ANDREWDIR is only used to find cui/arpadate).
  2. With cwd fixed, cui's final recon step segfaulted on the very first address caption it tried to build. Root cause: a new bug class — flex regenerates overhead/mail/lib/parsel.c at build time (no fossil history), and modern flex inverted the meaning of an internal init flag that a hand-written pareset_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 in porting-assessment.md §13, session detail in porting-changelog.md's 2026-07-07 entry. Verified: recon completes ("Reconstructed folder ~/.MESSAGES/amsdemo with twenty-three entries") repeatably, no crash.

Next up — two threads:

  1. ~~New, unrelated intermittent crash found while re-verifying recon~~ — root-caused and fixed 2026-07-11. The memmove heap 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 just prsdate — assumes every LALR table is a short, 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 as parsedateheader() 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 (the memmove overrun) badly enough to occasionally take unbounded time (the UE hang). Full root-cause writeup: porting-assessment.md §15. Since the crash is gone, gendemo's auto-invocation from src/ams/demo/Imakefile's install.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 changes dependInstall's default behavior.
  2. Once recon is fully stable, verify messages can actually browse and read the populated amsdemo folder 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


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.

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.

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.

  1. [x] classpp: -pi/-pe split, >= 8 gates dropped under -pi (done 2026-07-08; verified byte-identical default output, binary installed)
  2. [x] Pilot A — atk/eq (done 2026-07-08; clean-build gate green, eq inset visually verified in Sherman.Alloc. Findings — see porting-assessment §14 "Pilot A findings": macro-parameter capture bug class, fixed structurally in classpp; DoScript stray-* DRIFT in eq.ch, a ~35-year-old typo caught by the first typed rebuild; two process wrinkles for the runbook)
  3. [x] Pilot B — atk/figure (done 2026-07-09; clean-build gate green, figure inset visually verified in 95Summer.ez — behavior unchanged; new pre-existing menu-focus bug logged under Little Annoyances. Findings — see porting-assessment §14 "Pilot B findings": typeless .ch declarations (MoveHandle), rock-idiom longvoid *, and a six-file Build(action, v) vs runtime (v, action) transposition — the .ch was wrong for ~35 years; all fixes interface-side only)
  4. [x] First cross-directory step — atk/raster/lib (done 2026-07-09; ZERO fallout — the seven codec .chs were accurate; consumers raster/cmd + raster/convert rebuilt clean against typed .ih; gate green. First before/after test protocol: convertraster battery 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)
  5. [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's long functionData rock retyped to void *; six call sites across five files (framecmd.c x4, 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 through long rather than mean anything. First rollout point with import fallout in directories other than the flagged one, confirming the blast-radius-asymmetry prediction in §14)
  6. [x] atk/supportviews (17 classes, 178 external; done 2026-07-09; gate green, help app scrollbars/panel expand-shrink/matte chrome and ez visually verified. One fallout: sbutton.ch Enumerate's long rock retyped to void * — same rock-idiom pattern as atk/frame/atk/figure, all three tree-wide callers already passed bare pointers, no (long) casts to delete)
  7. [x] atk/text (21 classes, 321 external; done 2026-07-09; gate green, help regression checklist and ez (Cattey.Writing fnote, ex14.doc textref) visually verified. Two rock-idiom fallouts, same pattern as points 5/6: pcompch.ch ATKToASCII/ASCIIToATK and text.ch EnumerateEnvironments long rock retyped to void *; EnumerateEnvironments again showed the bare-vs-laundered-cast split (one caller in atk/lookz/lookzv.c passed the pointer bare, five callers in atk/text laundered via (long) — all five casts deleted per the point-5 pre-authorized exception). No new fallout pattern)
  8. [x] atk/support (19 classes, 450 external; done 2026-07-09; gate green, help app, ia-archive/jan.90's lset/buttonV widget (first proof of both, previously unproven insets), and a File > Save All buffer command all visually verified. Two rock-idiom fallouts: buffer.ch Enumerate/EnumerateViews — same pattern as points 5-7 (8 of 9 callers laundered a pointer via (long), one bare-pointer omission at framecmd.c:552 exposed it). list.ch Enumerate — a genuine hard stop, escalated mid-session: rock declared char * but two callers (dired.c FindPosProc, buttonv.c findkey) pass real long integers 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 to void *; the integer call sites get an explicit (void *) cast (dired.c:348, buttonv.c:489, plus a third found while sweeping, prefs.c:513 in atk/prefed, which isn't part of the default build — MK_PREFS/MK_AUX_UTILS are off — so harmless but unverified locally); pointer call sites drop their now-redundant casts; callbacks (FindPosProc, findkey) untouched, since they're invoked through typeless procedure pointers outside -pi checking. Also: the gate surfaced an unrelated pre-existing hang — see gendemo below — worked around, not a rollout fallout.)
  9. [x] atk/basics/common (41 classes, 2,351 external; done 2026-07-09; gate green after four cycles, help/ez runtime battery visually verified. The directory's own .chs had ZERO local fallout; all fallout was consumer-side rock collisions. 16 rocks retyped void * 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_BindToKey stays long under 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))
  10. [x] Breadth: remaining atk (value, adew, apt, basics/wm, basics/x, hyplink, syntax/parse, ...), then atkams/ ams, contrib (zip/lib first), 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-&X CaptureString 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_ENV off). 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/lib alone. Gate green first pass, all fallout local (19 errors, one ring); messages runtime fixture verified. Seven .ch drift fixes (cvEng typeless, DisplayNewBody bare params, PostMenus by-value struct, AlterSubscriptionStatus 35-year arg transposition, ReadFromFile file-private Boolean, 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-int cast param under gnu89 — a typed cast that lies, truncating function pointers on LP64; fixed procprocedure in ams/amsn/amss.ch and cross-directory in orgv.ch (fldtreev inherits it; classpp reads the INSTALLED parent .ch, so the fix needed make install in 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_UTILS off, no generated Makefile, no console binary), atk/raster/cmd. Gate green first pass. Two known-taxonomy fallout fixes, no new patterns: image's sliderv.ch SetCallback rock (longvoid *, sole caller cmapv.c passes a bare pointer); hyplink's pshbttn.ch ParseRGB signature drift (unsigned char rgb_vect declared by value, impl + all four callers use it as an array, matching the already-correct GetFGColor/GetBGColor siblings). raster/cmd's own four .chs were zero-fallout (fully typed already). convertraster battery run for due-diligence but doesn't actually verify raster/cmdconvrast.c only includes raster/lib headers, never raster/cmd's; byte-identical regardless. Runtime: hyplink verified via PAPERS/conf/1995/widgets.ez (pushbutton→link→linkview), raster/cmd verified via NEWSLETTERS/EZ/92Sep.ez's raster inset; image accepted 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 local make -k install, before the tree-wide gate ran). chart carried the suite-identical variadic-by-macro attribute family across two classes (chart.ch Chart/Item Attribute, chartv.ch Chart/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.ch also 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, PrintString argument) 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, table were all zero-fallout — census clean, gate green, no .ch/.c edits needed. No new patterns for porting-assessment §14. Runtime: chart verified interactively (create/format/label a chart); fad+table verified via Sherman.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's tmpnam/strcpy misuse, 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.ch had two typeless declarations (ParseArgs(argc,argv), InitializeObject(self)) typed to match every sibling app's ParseArgs(int argc, char **argv) and the impl's struct rofftextapp *self; srctext/hlptext.ch and srctext/rawtextv.ch each had a signature-drift InitializeObject/FinalizeObject typed 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's EnumerateAll/ EnumerateMarked rock retyped longvoid * (all three tree-wide callers in diredv.c already pass pointers, same rock-idiom precedent as frame/figure/supportviews). textobjects/chlist.ch's AddItemAtIndex had a ~35-year transposed-parameter signature drift (.ch declared (str, index, ...), impl and its sole caller use (index, str, ...)) — fixed to match. srctext.ch's Lookup classprocedure was missing the **/[] on its hash-table parameter (declared Dict hashTable by value; impl and all 8 tree-wide callers use Dict *hashTable[], and its two sibling classprocs BuildTable/HashInsert already had it right) — an isolated typo, not a pattern. textaux, typescript were zero-fallout. Runtime: lookz verified via PAPERS/atk/Hansen.Algebra; textaux's contentv (Table of Contents) verified via PAPERS/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/unknown accepted gate-only — no srctext/ctext document exists anywhere in ia-archive, PAPERS, or NEWSLETTERS, and dired/chlist/unknown have 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__Create doesn't check typescript_New() for NULL before calling SetDataObject on it, and New() returns NULL because InitializeObject fails at GetPtyandName ("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_UTILS are all off in allsys.h and no per-app override (MK_EZPRINT, MK_PREVIEW, etc.) is defined, so none are in atk/Imakefile's SUBDIRS and none have a generated Makefile; deferred to a future batch (user decision: split rather than flip the macros on). The ez2ascii/ez2ps binaries already in build/bin are leftovers from contrib/mit/util (batch 11, gated by CONTRIB_ENV, also off) plus a csh wrapper — not built from atk/ezprint at 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_ENV is ON in config/site.h (since 2026-07-05) and contrib/mit/util IS in the default build — the gate log shows building (dependInstall) descents into it, and ez2ascii/ez2ps are 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 in BASICS). Gate green first pass. Six genuine drift fixes caught by census before any build, no new patterns: utils/dialog.ch and utils/dialogv.ch each had InitializeObject/FinalizeObject typed to the wrong sibling struct (struct sbutton *self instead of their own class) — same pattern as batch 6's hlptext/rawtextv; help/src/hlptextv.ch had the identical wrong-sibling-struct drift (struct srctextview *self instead of struct hlptextview *self) — a different file from batch 6's srctext/hlptext.ch, just a confusingly similar name. help/src/help.ch and help/src/helpdb.ch each declared InitializeClass(struct help(db) *self) with a bogus extra self param the implementation doesn't take (impls take only classID, matching the universal zero-param InitializeClass() convention every other class uses). extensions/ezdiff.ch had the opposite arity drift: FinalizeObject() was missing its self param entirely (impl is ezdiff__FinalizeObject(classID, self)). utils/dialogv.ch's PostInput choicerock was a rock-idiom retype (longvoid *; its one tree-wide caller, frame.c:1746, already passes a bare pointer). Traced how InitializeObject/FinalizeObject/InitializeClass arity actually matters under -pi despite the user-facing convenience macros having zero external callers tree-wide: classpp's auto-generated Destroy/Finalize wrapper code (baked into the .eh) calls the raw classname__FinalizeObject function by the fixed (classID, self) convention regardless of what the .ch declares, so a .ch arity mismatch becomes a real prototype conflict once -pi is on — not dormant. Confirmed struct thisobject *self (used pervasively for InitializeObject/FinalizeObject/ObservedChanged self params across dozens of files, including several already flagged in batch 1) is a real, working classpp idiom that resolves to void * even under -pi — not a bug, left alone everywhere it appears (strinput.ch included). Runtime: ez launch confirmed (including an Extensions-menu command); a Quit-with-unsaved-changes confirmation dialog exercised the dialog.ch/dialogv.ch fix and the PostInput rock retype directly; help launch confirmed, including a hlptextview-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_EXAMPLES off in allsys.h, no per-app override) and both rdemo dirs (rdemo isn't referenced anywhere in src/Imakefile's SUBDIRS at all — a standalone package with its own config.csh/config.h generation, never part of make dependInstall). Only overhead/class/testing is live. Same user ruling as batch 7: split, flag/verify the live dir now, defer the rest as Batch 9b. Both .ch files (testobj.ch, testobj2.ch) were already clean — no InitializeObject/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 .ih files directly (this directory has no InstallClassFiles, so nothing copies to build/include). Runtime check skipped by user choice: the only artifact, testmain, is a class-loader self-test ending in while(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's long *, Create's error handler to void (*)()) — details in claude-history/m1-point10-batches.md. One hard stop escalated and ruled: lexan.c ParseNumber passed a long * where TransEscape takes int * — live LP64 bug, fixed with an int temporary as its own commit. Runtime: ctext syntax coloring/indent user-verified on a scratch .c in 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 AMS struct folders *; AddImage missing *; ReindentLine struct mark *long pos matching 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-style int; 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 .ch directory in the active tree now builds under -pi. Only point 11 remains for M1.
  11. [x] Default flip (done 2026-07-10): classpp emits typed import casts (-pi behavior) by default (class.c usePrototypesImportAll = TRUE; -pi accepted as a no-op); all 50 per-directory -pi flags 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/.eh headers 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.
  12. [ ] 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:

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:

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.