Found deploying 0.18.2 to this box. Not a blocker — the daemon and all four modules are healthy — but it changes behaviour for every tool invoked inside a supervised module's process tree, and the failure it produces points at the wrong thing.
Symptom
$ ck daemon
no usable subc connection file found; tried: /tmp/subc-1000.connection.json (not found)
One candidate. The daemon's connection file is at /run/user/1000/subc-connection.json, and ~/.local/share/cortexkit/run/subc-connection.json symlinks to it. Neither was tried.
The daemon is running and healthy on the same box:
$ XDG_RUNTIME_DIR=/run/user/1000 ck daemon
daemon 0.18.2 · pid 2815040 · up 52s · 8 clients · no frame drops in the last 10 minutes
Cause
c97d3473 ("mason: add daemon fleet logging", 09-15) added command.env_clear() to spawn_child. I verified it is not in 856e26f7, the build this box was running before the upgrade — it arrived with 0.18.2.
The daemon now spawns modules with a cleared environment, re-adding only SystemRoot (Windows), the module's configured spec.env minus capture-log keys, and SUBC_MODULE_ID/nonce. Measured inside a tool shell running under a supervised module after the bounce:
HOME <UNSET>
XDG_RUNTIME_DIR <UNSET>
TMPDIR <UNSET>
USER <UNSET>
connection_file::discovery_candidates reads XDG_RUNTIME_DIR and HOME to build its list. With both unset it falls back to env::temp_dir() alone — hence the single /tmp candidate.
Why this is worth a look rather than a workaround
The stated intent in the comment is narrow: stop an operator's ambient CK_LOG leaking into an otherwise unconfigured module. That is a good goal. env_clear() achieves it by removing everything, and the collateral is the whole POSIX environment.
Three consequences, in increasing order of how long they'd take to diagnose:
ck cannot find a daemon running on the same machine, from inside any module's process tree. Every module here is served that way, so this is the common case, not an edge one.
- The error names a path the file has never lived at. "tried: /tmp/subc-1000.connection.json" reads as "the daemon didn't write its file", when the truth is "this process cannot see where it was written". A reader debugging this looks at the daemon first.
- Anything else a module spawns inherits it —
git without ~/.gitconfig, cargo without CARGO_HOME, ssh, python user dirs. Those degrade quietly rather than erroring.
I nearly filed this as a ck discovery regression, which is the wrong diagnosis and worth recording: ck had worked bare all day and stopped immediately after I deployed a new one, so the timing pointed hard at the binary I had just swapped. The discriminator was restoring a single variable — with XDG_RUNTIME_DIR set, the new ck finds the daemon instantly. The binary was never the variable; its caller's environment was.
Options
I don't think this is mine to pick — it trades isolation against reachability, and the isolation was deliberate:
- Allowlist the standard environment — re-add
HOME, XDG_RUNTIME_DIR, TMPDIR, USER, PATH after clearing, keeping the scrub for everything else. Preserves the CK_LOG intent exactly; loses nothing the comment was guarding against.
- Denylist instead of clear — remove
CK_LOG and the capture-log keys specifically, inherit the rest. Smallest behavioural delta from pre-0.18.2, but it re-opens the "next leaky variable nobody thought of" hole env_clear closed.
- Keep the scrub, make discovery independent of it — have the daemon pass the connection-file path to children (it already passes
SUBC_ARG), and have ck consult a fixed well-known location. Fixes reachability without weakening isolation, but doesn't help git/cargo/ssh.
- Keep as-is and document it — the scrub is correct and callers inside a module tree are expected to pass
--subc. Defensible, but the error message should then name the real locations rather than only the temp-dir fallback.
My lean is (1), with the error message improved regardless of which is chosen: whatever the candidate list ends up being, a discovery failure that lists one path the file never occupies will send the next reader to the wrong component. If the scrub stays, that message is the part that makes it survivable.
Happy to take whichever you rule.
Found deploying 0.18.2 to this box. Not a blocker — the daemon and all four modules are healthy — but it changes behaviour for every tool invoked inside a supervised module's process tree, and the failure it produces points at the wrong thing.
Symptom
One candidate. The daemon's connection file is at
/run/user/1000/subc-connection.json, and~/.local/share/cortexkit/run/subc-connection.jsonsymlinks to it. Neither was tried.The daemon is running and healthy on the same box:
Cause
c97d3473("mason: add daemon fleet logging", 09-15) addedcommand.env_clear()tospawn_child. I verified it is not in856e26f7, the build this box was running before the upgrade — it arrived with 0.18.2.The daemon now spawns modules with a cleared environment, re-adding only
SystemRoot(Windows), the module's configuredspec.envminus capture-log keys, andSUBC_MODULE_ID/nonce. Measured inside a tool shell running under a supervised module after the bounce:connection_file::discovery_candidatesreadsXDG_RUNTIME_DIRandHOMEto build its list. With both unset it falls back toenv::temp_dir()alone — hence the single/tmpcandidate.Why this is worth a look rather than a workaround
The stated intent in the comment is narrow: stop an operator's ambient
CK_LOGleaking into an otherwise unconfigured module. That is a good goal.env_clear()achieves it by removing everything, and the collateral is the whole POSIX environment.Three consequences, in increasing order of how long they'd take to diagnose:
ckcannot find a daemon running on the same machine, from inside any module's process tree. Every module here is served that way, so this is the common case, not an edge one.gitwithout~/.gitconfig,cargowithoutCARGO_HOME,ssh, python user dirs. Those degrade quietly rather than erroring.I nearly filed this as a
ckdiscovery regression, which is the wrong diagnosis and worth recording:ckhad worked bare all day and stopped immediately after I deployed a new one, so the timing pointed hard at the binary I had just swapped. The discriminator was restoring a single variable — withXDG_RUNTIME_DIRset, the newckfinds the daemon instantly. The binary was never the variable; its caller's environment was.Options
I don't think this is mine to pick — it trades isolation against reachability, and the isolation was deliberate:
HOME,XDG_RUNTIME_DIR,TMPDIR,USER,PATHafter clearing, keeping the scrub for everything else. Preserves the CK_LOG intent exactly; loses nothing the comment was guarding against.CK_LOGand the capture-log keys specifically, inherit the rest. Smallest behavioural delta from pre-0.18.2, but it re-opens the "next leaky variable nobody thought of" holeenv_clearclosed.SUBC_ARG), and haveckconsult a fixed well-known location. Fixes reachability without weakening isolation, but doesn't helpgit/cargo/ssh.--subc. Defensible, but the error message should then name the real locations rather than only the temp-dir fallback.My lean is (1), with the error message improved regardless of which is chosen: whatever the candidate list ends up being, a discovery failure that lists one path the file never occupies will send the next reader to the wrong component. If the scrub stays, that message is the part that makes it survivable.
Happy to take whichever you rule.