Open work only, one item per line. A finished item's line is deleted.
What the tool does today: ../commands.md (generated). How it is built:
ARCHITECTURE.md. What the owner ruled: docs_ai/DECISIONS.md.
- An id is permanent and never reused. Take one with
bin/next-id <PREFIX>: one counter for every worktree on the machine, under a lock, and never below the highest number on any branch. - Prefixes:
RESresearch and measurement ·OPSrepository, tooling, CI, release ·COREcli-core·SPECprotocol spec and generator ·MAXdomain, client, transport, session ·CLIcommands and output ·DOChandwritten docs ·PROTOprotocol unknowns ·RISKrisks. - One item: the task as a title, then where the work starts (
path:lineor a REQUIREMENTS §). Analysis goes to a plan indocs_ai/plans/, a ruling toDECISIONS.md. - Priority: P1 blocks work or breaks something real · P2 this cycle · P3 someday.
- Mark: none — not started · 🚧
<branch>— taken · 🟡 — half done, the rest named · ⏸️ — deferred by the owner · 🚩 — waits on an owner decision. - Claim before code: put
🚧 <branch>on the line in the first push of the branch, so two agents never build the same item. - Close in the PR that ships the work: delete the line here in that PR. Users read what shipped in
CHANGELOG.md.
-
MAX-71 · P3 · Research left: join requests on a public group (a private group ignores
JOIN_REQUEST; a channel keeps it — MAX-73). -
CLI-71 · P3 · HTML reports from statistics and charts: standalone report pages with summary numbers and embedded charts, reusing the shared neutral chart data and replaceable renderer. Starts in cli-messaging
src/charts/andsrc/cli/messenger/stats-command.ts; plan the report structure and command surface before implementation. -
CLI-68 · P3 ·
mcp --httpas a background service:server installfor it (systemd/launchd), so the browser apps reach a machine without an open terminal. Follows CLI-58's live check (NEED-595 A: foreground first).
From the PyMax comparison (2026-09-24, NEED-175). Each is what PyMax's source declares
(MaxApiTeam/PyMax, src/pymax/api/, commit 53103f0) — a claim until measured. Every writing
operation is measured first in Saved messages (chat 0), as replies and reactions were (NEED-150),
and needs the owner's yes before it ships. Deleting messages was ruled out (NEED-32) until the owner asked for it on 2026-09-24 (MAX-47); marking
read only on an explicit flag (CLI-33, REQUIREMENTS §19).
-
MAX-48 · P3 · Send a round video note ("кружок"): opcode 82
{type: 1, uploaderType: 1},thumbhashfrom the upload answer,_type: "VIDEO"withvideoType: 1. MAX refuses a file that is not 480×480,yuv420p, limited range, bt709, baseline, AAC 48 kHz mono (PyMax #94).thumbhashis bytes — aUint8Arrayin a payload goes out as MessagePack bin sinceMAX-40. -
MAX-49 · P3 · Two-step password: log in when MAX asks for it (
passwordChallengein the login answer, thenAUTH_LOGIN_CHECK_PASSWORD115{trackId, password}), and set or remove one (112 → 107 → 111). PyMax 2.4.1, code; a user logged in with it on the mobile client (PyMax #106). The password is typed at a prompt, never an argument.ts:51`). Left: setting and removing one (112 → 107 → 111). -
MAX-34 · 🟡 P3 · Live events: a long-running
max listenthat prints new messages, edits, reactions and typing as they arrive (PyMax'son_message,on_message_edit,on_reaction_update…). Conflicts with one-shot commands (CLAUDE.mdconstraint 4), so it needs a ruling first. What is new since the last check is alreadymax inbox(CLI-23).max serveholds the connection andmax watchprints new messages as they arrive (src/server/server.ts,#pushed). What is left is edits, reactions and typing. The server receives them but passes on only new messages (opcode 128).Done 2026-09-25 from the third tab recording:
max watch --eventsprints edits (128 withstatus: EDITED), deletions (128 withstatus: REMOVED) and reactions (155); the plain stream is unchanged. Left: typing — MAX pushes 129 only after75 {chatId, subscribe: true}, which the tab sends for the chat it has open and repeats every 60 s;max servesubscribes to nothing. Done 2026-10-08 (MAX-67): reads (130) and chat changes (135, or a 128 carrying the chat). -
MAX-4 · 🟡 P3 · Chat addressing. Done: an id, or a title matched exactly then as a fragment, an ambiguous one refused (
resolve,src/client.ts:325;pickChat,src/resolve.ts:13). Left:@username, a phone number, a chat the account is not in.max.ru computes it. -
CLI-36 · P3 · The local copy made optional: a setting under which
maxwrites no chats or messages to disk and answers everything from MAX (--offlineandsearch messagesthen refuse). The option controls shared adapter recording and the login record (src/record.ts). -
CLI-5 · P3 ·
max raw <operation>— a debug escape hatch, validated against the spec, never arbitrary frames (REQUIREMENTS §22). -
MAX-52 · 🟡 P2 · The requests a real tab sends right after LOGIN: 21 on a fresh start (
48 48 272 35 32 302 163 208 27×4 209 28 22 48 28 35 53 209 35) and 9 after a re-login.maxsends none, which shows on every login — a stronger difference than telemetry. Decide per request: the read-only ones (272 folders, 302 banners, 163 call history, 27) could be copied; 22 subscribes to push and changes state. Captured 2026-09-25,docs/dev/capture/2026-09-25-web-tab.md. Names by PyMax (53103f0): 22CONFIG, 27ASSETS_UPDATE, 28ASSETS_GET_BY_IDS, 32CONTACT_INFO, 35CONTACT_PRESENCE, 48CHAT_INFO, 53CHATS_LIST, 208/209 stories, 272FOLDERS_GET, 302BANNERS_GET; 163 is not in its list. Onlymax servewill send them. 2026-09-25: the recording kept 27'stypeonly as"string", and no answer bodies, so what 27 asks for and which sync value each re-login sends back are unknown. The recorder now keeps both; the code waits on the next recording (withMAX-51).Done 2026-09-25 from the second recording (
docs_ai/captures/2026-09-25-web-tab-2.jsonl):max servesends 272, 302, 163 and 27 ×4 (STICKER,FAVORITE_STICKER,REACTION,ANIMOJI_SET) after every login, each re-login with the sync its previous answer returned (src/client.ts,live.readLikeTab). Left: 48{chatIds}, 32 and 35{contactIds}, 28, and the stories 208/209. Never: 22, which subscribes to push. -
RES-5 · 🟡 P2 · Does
LOGINmove presence? Known: reading history marks nothing; the tab's LOGIN sendsinteractive: false,trueonly in pings while its window has focus; the tab marks a chat read with an explicit opcode 50, and 49 withoutinteractivemoves nothing. Left: whether LOGIN itself moves presence — needs a second device watching. -
RES-7 · P3 · What a real client sends as opcode 36's payload.
{},{marker}are refused and{marker, count}closes the connection (pnpm probe:contacts), so only a capture answers it. It is the only route to contacts who share no chat. ClosesPROTO-1. -
PROTO-1 · 🟡 P3 · What opcode 36 returns: other clients call it
CONTACT_LIST, the protocol notes call itGET_BLOCKED. Waits onRES-7. -
PROTO-3 · P3 · The upper bound on
chatsCountinLOGIN: 100 works, 200 is refused. The spec caps it at 100 (src/spec/operations/session.ts:109). -
PROTO-6 · P3 · What the
messagesobject in theLOGINanswer holds. Nothing reads it (src/spec/operations/session.ts:156);pnpm probe:idsprints its type and key count. -
SPEC-3 · 🟡 P3 · Sanitized protocol fixtures, synthetic values only (REQUIREMENTS §24). Done: the web client's frames, headers and payload structure without values (
src/testing/fixtures/web-capture-2026-09-25.json,MAX-40), and the recorder for more (scripts/capture/web-recorder.js). Left: fixtures of MAX's answers to our own operations — response shapes are still tested with made-up payloads insrc/spec/. -
SPEC-4 · P3 · A generated list of implemented operations (§8, §30). Deferred: listing what MAX has and we lack means maintaining MAX's whole surface (§10).
Group moderation on the personal account (NEED-306…NEED-314, plan
docs_ai/plans/2026-09-27-group-moderation.md). review --unanswered shipped as CLI-43, chats events as CLI-44, chats members list as CLI-45, chats rules and chats check as CLI-46, MCP max_chats_check as CLI-47.
-
CLI-48 · P3 · Roles in
chats members listcome from the chat as the login carried it, which lags: right afteradmins addthe bot still showed asmember, whilebot admins listalready had it. Refresh the chat (opcode 48,CHAT_INFO) before reading roles, or say the roles may be old. -
MAX-62 · P3 · Lifting a bot's ban.
max <bot> bot members remove --block(andbot chats check) ban a person from rejoining by the invite link (measured 2026-09-27). The Bot API has no unblock, and the owner found no ban list in the MAX app. Re-adding the person by an admin works, but whether it lifts the ban is unknown — after leaving, the link may still refuse them. Find where MAX keeps the ban (a capture of the web client's group settings, orCHAT_MEMBERS59 with anothertype), then offermax chats members unban.
- CORE-10 · P3 · Plugins from npm, only from an allow-list kept in the CLI itself — package
names with pinned versions and integrity hashes — never an arbitrary package: a plugin runs inside
a program holding the token of a personal account. oclif's
plugin-pluginsis the model. - CORE-11 · P3 · Installers and standalone archives per platform (oclif's
pack), after a single-file build (G4 §3.9: Bun only). Lowest priority.
Added by the owner on 2026-09-24. Each one goes against REQUIREMENTS §3 or §18, and the line says which; the plan for it starts by saying so.
- CLI-27 · P3 · Hooks for workflows:
maxruns a configured command when a check finds something new. Asked by the owner 2026-09-24 (NEED-172). Two things to settle in the plan: the message text reaches that command, so it must go as data on stdin and never into the command line; andmax watch --jsonl | <command>on a runningmax serve(MAX-35) already does this for live messages, asmax inbox --newon a schedule does for batches — say what a hook adds over those two pipes.