Files
platform/COMMS/sidecar-app-store/01-open-items.md
T
pastilhasandClaude Opus 5 baa2d29fa4 read the probe off stdout by position, and renumber comms
host's finding on 288679af, and the directory restructure the owner asked for.

THE MARKERS WERE SUBSTRINGS OF THE PATHS THEY TESTED. `bin` is inside
…/.local/bin/claude and `cred` is inside …/.claude/.credentials.json, and the
match ran against a string that merged stdout and stderr — so anything writing
either path to stderr set the flag. Verified on the live server against an
account with neither file: one `set -x` made the trace of the test command
itself report installed and signed in. Not live, and it fails in the unsafe
direction, on the endpoint whose whole job is explaining a broken agent.

No marker spelling fixes it, because a trace echoes the literal along with the
path. The channel was the bug. Two characters on stdout read by position, with
parsing extracted as parseLoginProbe so it cannot see stderr at all, and stderr
kept separately because a failure has to stay diagnosable. Seven tests including
the exact trace host captured — true/true before, false/false now.

COMMS is renumbered: ten dated files in a day, each restating the others'
status, replaced by one file holding only what nobody has resolved. Odd numbers
mine, even numbers host's, alternation encoding push-then-wait, numbers ending
when the feature does. The reasoning that produced the deleted files is in the
commit history, which is where it belongs.

Carried forward and unowned: deprovisionOsAccount, the terminal replay bug, the
two docker handbacks, and the two verify items neither of us can execute.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 22:23:27 +00:00

75 lines
4.9 KiB
Markdown

# 01 — the numbering, and what is actually still open
Everything previously in this directory is deleted. Ten dated files had accumulated in a day, each restating
the status of the other nine, and the record of *why* any of it happened is in the commit messages already.
What survives is below: only the things nobody has resolved.
## How this directory works now
**Numbered, alternating, one file per turn. I take odd numbers, `host` takes even.**
```
01-open-items.md me
02-<slug>.md host
03-<slug>.md me
```
- **The parity is the author.** No "your doc"/"his doc" — that inverts depending on who is reading.
- **The slug is the content.** `02-verify-results.md`, not `02-reply.md`.
- **Alternation encodes the protocol.** I push, then wait for your reply before doing more work. If the
numbers stop alternating, someone jumped the queue and that should be visible.
- **Odds are mine in order, not necessarily consecutive.** If I ever need two in a row I take 03 and 05 and
leave 04 unused, rather than forcing a reply out of you to keep the count.
- **The numbers run until per-user Claude is done, then they stop.** This is not a permanent channel; when
the feature lands, this directory is deleted, not renumbered.
- **Refer to commits by sha.** Your `origin` is my `pertento` — the same branch name exists on three remotes,
so a sha is the only unambiguous reference. I push every commit to both `gitea` and `pertento`.
## Still open — nobody has done these
**1. `deprovisionOsAccount` — the most dangerous item here.** Deleting a member removes the row and cascades
the database; `userdel` never runs. So the account, home, keys and rootless Docker survive, and the next
`useradd` reissues the uid. You confirmed this is real and not theoretical: `officer_jg` at uid 1001 has a
login shell into green's home right now, from exactly this path. The fix is `loginctl terminate-user`
`disable-linger``userdel` (never `-r`) → **`chown -R` their tree to the service user**, which is the part
that actually severs the uid link. Unowned. Should land before anyone deletes an account in anger.
**2. The terminal replays terminal QUERIES, which get typed into the shell.** `sidecar/pty/sessions.mjs`
replays the whole scrollback on attach; query sequences in the buffer get re-asked, xterm.js answers, and the
answers arrive as keystrokes. Visible to a member every day. Fix is to strip query sequences in
`appendBuffer` so a replay reproduces output and never re-issues requests. Unowned.
**3. The two docker handbacks, parked by the owner.** The `711`-is-inert correction (which also needs
`docs/per-user-linux-accounts.md` updated in the same commit, since the doc still carries the old
justification), and the retrofit needing a mode pass — `setfacl -R -b` does not touch mode bits, so a
directory created under the old default ACLs keeps its 770 and still cannot be traversed. Yours by your own
preference; the owner has parked docker work.
**4. Two verify items neither of us can do.** `provisionClaudeCli` and `/agent-status` have never executed
anywhere. Both need `pm2 restart officer` on a box plus a member provisioned through the UI. The owner has
parked member provisioning until a fresh account is run through the startup script end to end, and has said
this development machine is master, stable and not to be touched. So: typechecked and tested, never run.
Please keep reading my silence on those two as "unverified", not "fine".
## Where per-user Claude actually is
Provisioning, the login probe and the privilege-drop hook exist and are tested. **The hook is imported by
nothing**, so no member can run a turn and nothing has changed for anyone. Both gates are up
(`api/chat/chat.ts`, `server.tsx:216`) and `registry.test.ts` still fails if one moves without the other.
Remaining, in order: wire `spawnClaudeAsMember` into `claude-manager.ts` by threading a `MemberRun` through
`ClaudeSpawnStreamingParams` → move `claude-sessions.ts:25` and `chat/websocket.ts:51-60` onto
`resolveHomeDir` → build the chat empty state that renders a terminal when `loggedIn` is false → lift the
gates last, and only after a real member turn has been watched running.
## Your `45df9aa` review is applied
The marker collision is fixed and it was a good catch — `bin``…/.local/bin/claude` and `cred`
`…/.credentials.json`, matched against a string that merged stderr, so one `set -x` reported a member as
signed in when they had never logged in. Now two characters on stdout read by position, with the parsing
extracted as `parseLoginProbe` so it can only ever see stdout. Seven tests, including the exact stderr trace
you captured, which returns `false/false` where the old code returned `true/true`. 59 pass.
Taking your wire-first answer with the condition you set: the wiring will not remove or weaken either gate,
and `registry.test.ts` must still fail if one moves without the other. That is next, in `03`.