Question
Answer #548's four unknowns on real hardware. Every one of them is measurable
today, with no change to dl, because the transport dl uses is ordinary
OpenSSH against an alias devpod already published: anything dl would do with
SendEnv or -R, a hand-run ssh can do first.
Two of these can void #548's design and one can make the whole map unnecessary.
Nothing in #548 should be written until this task has reported.
This task is written for an agent running on the machine. It needs herdr
installed and running, herdr integration install claude done, devpod, docker,
and one real workspace. It cannot be done from a cloud session — which is why the
parent map has sat on assumptions.
Before touching anything
dl mutates real state: metadata.json, the bare clone cache, and live devpod
workspaces. Per CLAUDE.md:
- Point everything at a scratch cache:
XDG_CACHE_HOME=/tmp/dl-measure/cache dl ....
One variable scopes the whole of what dl stores.
- That isolates the bookkeeping, not the machine. Workspaces created below are
real, appear in devpod list, and must be deleted at the end. Record their ids
as you create them.
- Do not run
dl --purge during this task. Pointed at a scratch cache it
finds every real workspace unrecognised, and its behaviour there is not what you
want while measuring. dl --prune is safe and read-only until confirmed, but is
not needed here.
- Use the released
dl, not dl-next, unless a measurement needs the tree.
Finding the transport by hand
dl hands ssh the config file explicitly as -F, because OpenSSH resolves its
default user config through getpwuid(getuid()) and reads none of the
environment that names the file (devlaunch#421). Resolve it the way dl does, in
order: an include option, then $DEVPOD_SSH_CONFIG, then a path option, then
~/.ssh/config. The alias is <workspace-id>.devpod.
CFG="${DEVPOD_SSH_CONFIG:-$HOME/.ssh/config}"
WS=<workspace-id> # from `devpod list`
ssh -F "$CFG" "$WS.devpod" 'echo inside; hostname'
Confirm that round-trips before running anything below. Note that inside the
container the hostname is the workspace id (provision.rs:546), which is a
free check that you are where you think you are.
E1 — Is screen detection already working? Run this first
The cheapest possible outcome: if a manager classifies correctly from screen
content, only the process-name half is broken, and #548 may reduce to one
host-side environment variable.
dl <ws> -- claude pipes the agent's own TUI through the pane, so the pane's
screen holds Claude's real output, not an ssh banner.
- In a herdr pane, start an aid session:
aid <owner/repo>@<branch> and give it
a prompt that takes a while.
- Record what herdr's agents tab says while it works, and again when it stops and
wants input. Screenshot or transcribe the row.
- Record the host's view of the pane process:
ps -o pid,comm,args -p <pane pid>
cat /proc/<pane pid>/comm /proc/<pane pid>/cmdline | tr '\0' ' '
- Repeat with
HERDR_AGENT=claude exported before the launch — herdr documents
it for "VMs and wrappers", which is exactly what dl is.
Report: does herdr show working/blocked correctly in either case? If yes with
HERDR_AGENT, say so loudly and stop — #548 collapses to documenting one
variable, and E2 to E4 are moot.
E2 — Does the sshd accept arbitrary environment names?
SendEnv is half a handshake; the server must AcceptEnv the name or it is
dropped silently. GH_TOKEN arriving today proves nothing about a novel name:
it may be arriving because something configures that one specifically.
# What the server actually permits
ssh -F "$CFG" "$WS.devpod" 'grep -i acceptenv /etc/ssh/sshd_config /etc/ssh/sshd_config.d/* 2>/dev/null'
# A novel name, end to end
HERDR_PANE_ID=probe-42 ssh -F "$CFG" -o SendEnv=HERDR_PANE_ID \
"$WS.devpod" 'echo "[${HERDR_PANE_ID:-UNSET}]"'
Report: the AcceptEnv lines verbatim, and whether [probe-42] or [UNSET]
came back. UNSET means #548's env half needs the server configured too, which is
a different and larger change — say so.
E3 — Does -R unix-socket forwarding survive the ProxyCommand?
The alias tunnels through devpod ssh --stdio. A ProxyCommand carries the ssh
protocol, so remote forwards should work, but this has never been exercised here.
# Forward a socket in; then reach it from inside.
ssh -F "$CFG" -R /tmp/probe.sock:"$HERDR_SOCKET_PATH" \
-o StreamLocalBindUnlink=yes \
"$WS.devpod" 'ls -l /tmp/probe.sock && nc -U /tmp/probe.sock </dev/null; echo rc=$?'
Then the real thing, which is the actual acceptance test for the whole map: lend
the binary in by hand and make the manager's own report call from inside the
container.
ssh -F "$CFG" -R /tmp/probe.sock:"$HERDR_SOCKET_PATH" -o StreamLocalBindUnlink=yes \
"$WS.devpod" 'HERDR_SOCKET_PATH=/tmp/probe.sock /path/to/lent/herdr \
pane report-agent "<pane id>" --source custom:probe --agent claude --state working'
Check the herdr UI changed. Three specific ways this can fail, each worth
reporting distinctly rather than as "it did not work":
AllowStreamLocalForwarding disabled on the sshd (default is yes).
- The container user cannot create the remote path.
/tmp is used above for that
reason; if it still fails, report the path and the uid.
- Peer credentials. herdr may validate the connecting process with
SO_PEERCRED. The container user is typically vscode at uid 1000 and the host
user may not be, so a refusal here is a uid mismatch and not a transport
failure. Report the container's id -u alongside the host's.
E4 — Does a forward collide with ControlMaster reuse?
A remote forward belongs to the master connection, so a later trip joining an
existing master gets the first trip's forwards, not its own. This is the failure
control_key's length-prefixing comment describes, one level up.
- Open a master with a forward to socket A and keep it alive (
ControlMaster=auto,
ControlPersist, as dl sets them).
- Run a second trip over the same alias asking for a forward to socket B.
- From inside, determine which socket is actually reachable.
Report: whether B was honoured, ignored, or errored. If the second trip
silently inherits A, #548 must take the forward spec as a control_key field, and
the task should say so in as many words.
Recording
Post one comment on #548 with, per experiment: the commands as run, the output,
and a one-line verdict. Where a measurement contradicts something #547 or #548
asserts, say which sentence is wrong — both tickets were written from a cloud
session with no hardware, and #547 has already had its mechanism corrected once.
Cleanup
Delete every workspace created here (dl <ws> --rm, or devpod delete <ws>), and
remove /tmp/dl-measure. Confirm devpod list is back to what it was, and say so
in the report — a measurement that leaves workspaces behind costs the next person
the confusion this task exists to remove.
Question
Answer #548's four unknowns on real hardware. Every one of them is measurable
today, with no change to
dl, because the transportdluses is ordinaryOpenSSH against an alias devpod already published: anything
dlwould do withSendEnvor-R, a hand-runsshcan do first.Two of these can void #548's design and one can make the whole map unnecessary.
Nothing in #548 should be written until this task has reported.
This task is written for an agent running on the machine. It needs herdr
installed and running,
herdr integration install claudedone, devpod, docker,and one real workspace. It cannot be done from a cloud session — which is why the
parent map has sat on assumptions.
Before touching anything
dlmutates real state:metadata.json, the bare clone cache, and live devpodworkspaces. Per
CLAUDE.md:XDG_CACHE_HOME=/tmp/dl-measure/cache dl ....One variable scopes the whole of what
dlstores.real, appear in
devpod list, and must be deleted at the end. Record their idsas you create them.
dl --purgeduring this task. Pointed at a scratch cache itfinds every real workspace unrecognised, and its behaviour there is not what you
want while measuring.
dl --pruneis safe and read-only until confirmed, but isnot needed here.
dl, notdl-next, unless a measurement needs the tree.Finding the transport by hand
dlhands ssh the config file explicitly as-F, because OpenSSH resolves itsdefault user config through
getpwuid(getuid())and reads none of theenvironment that names the file (devlaunch#421). Resolve it the way
dldoes, inorder: an
includeoption, then$DEVPOD_SSH_CONFIG, then a path option, then~/.ssh/config. The alias is<workspace-id>.devpod.Confirm that round-trips before running anything below. Note that inside the
container the hostname is the workspace id (
provision.rs:546), which is afree check that you are where you think you are.
E1 — Is screen detection already working? Run this first
The cheapest possible outcome: if a manager classifies correctly from screen
content, only the process-name half is broken, and #548 may reduce to one
host-side environment variable.
dl <ws> -- claudepipes the agent's own TUI through the pane, so the pane'sscreen holds Claude's real output, not an ssh banner.
aid <owner/repo>@<branch>and give ita prompt that takes a while.
wants input. Screenshot or transcribe the row.
HERDR_AGENT=claudeexported before the launch — herdr documentsit for "VMs and wrappers", which is exactly what
dlis.Report: does herdr show working/blocked correctly in either case? If yes with
HERDR_AGENT, say so loudly and stop — #548 collapses to documenting onevariable, and E2 to E4 are moot.
E2 — Does the sshd accept arbitrary environment names?
SendEnvis half a handshake; the server mustAcceptEnvthe name or it isdropped silently.
GH_TOKENarriving today proves nothing about a novel name:it may be arriving because something configures that one specifically.
Report: the
AcceptEnvlines verbatim, and whether[probe-42]or[UNSET]came back.
UNSETmeans #548's env half needs the server configured too, which isa different and larger change — say so.
E3 — Does
-Runix-socket forwarding survive the ProxyCommand?The alias tunnels through
devpod ssh --stdio. AProxyCommandcarries the sshprotocol, so remote forwards should work, but this has never been exercised here.
Then the real thing, which is the actual acceptance test for the whole map: lend
the binary in by hand and make the manager's own report call from inside the
container.
Check the herdr UI changed. Three specific ways this can fail, each worth
reporting distinctly rather than as "it did not work":
AllowStreamLocalForwardingdisabled on the sshd (default is yes)./tmpis used above for thatreason; if it still fails, report the path and the uid.
SO_PEERCRED. The container user is typicallyvscodeat uid 1000 and the hostuser may not be, so a refusal here is a uid mismatch and not a transport
failure. Report the container's
id -ualongside the host's.E4 — Does a forward collide with ControlMaster reuse?
A remote forward belongs to the master connection, so a later trip joining an
existing master gets the first trip's forwards, not its own. This is the failure
control_key's length-prefixing comment describes, one level up.ControlMaster=auto,ControlPersist, asdlsets them).Report: whether B was honoured, ignored, or errored. If the second trip
silently inherits A, #548 must take the forward spec as a
control_keyfield, andthe task should say so in as many words.
Recording
Post one comment on #548 with, per experiment: the commands as run, the output,
and a one-line verdict. Where a measurement contradicts something #547 or #548
asserts, say which sentence is wrong — both tickets were written from a cloud
session with no hardware, and #547 has already had its mechanism corrected once.
Cleanup
Delete every workspace created here (
dl <ws> --rm, ordevpod delete <ws>), andremove
/tmp/dl-measure. Confirmdevpod listis back to what it was, and say soin the report — a measurement that leaves workspaces behind costs the next person
the confusion this task exists to remove.