Skip to content

fix(autostart): the logon task runs hidden and quiet - #1408

Open
joelteply wants to merge 1 commit into
canaryfrom
memento/quiet-autostart-join
Open

fix(autostart): the logon task runs hidden and quiet#1408
joelteply wants to merge 1 commit into
canaryfrom
memento/quiet-autostart-join

Conversation

@joelteply

Copy link
Copy Markdown
Contributor

The complaint

Joel, on his own machine this morning, after a Windows Update restart:

"this is in a terminal window every restart, and I left running, but hacky looking nonetheless to see in one of MANY terminal windows that appear, but this is the only one that is there more than briefly."

The airc-join logon task works — it brought airc back by itself after the restart, which is the behaviour we want. This PR is only about how it looks doing it.

Why a window appears at all

Register-ScheduledTask was called without a -Principal, so the task got the default: an interactive logon. A console application given an interactive logon gets a console. And because join is long-running by design, that console stays open for the life of the mesh connection.

It is the only long-lived window among many that flash past at startup, so it is the one that gets looked at. In order, it shows:

⚠ airc binary is 2 commits behind canary — run `airc update` ...
  cd "$(cat ~/.airc/install-source)" && git checkout canary && git pull && ./install.sh
airc: provisioning daemon with GH_TOKEN (len 40) for the account rendezvous
joined default account context:
  #general (5eedf7b1-...)
default: #k3-serving
wire:    \?\C:\Users\joelt\.airc\wires\k3-serving
scope:   \?\C:\Users\joelt\.airc
mesh:    machine-account home (this is the canonical `\?\C:\...` — ...)
runtime: installed AIRC Codex turn contract in C:\Users\joelt\.codex\config.toml
attached — Ctrl-C to detach.
work board cache: snapshot ...json has format v1 (current v2) — rebuilding projection from scratch

A staleness banner, a two-line git checkout recovery incantation for a known hang class, a token length, extended-length paths, wire/scope/mesh internals, and a benign cache migration phrased like a failure. Nothing is broken. It reads as scaffolding someone forgot to remove.

The changes

1. The task runs hidden. An S4U principal ("run whether logged on or not", no stored password) runs without an interactive desktop, so no console is allocated; -Hidden also keeps it out of the default Task Scheduler view. airc needs no desktop — it writes under the user profile and talks over a socket — and still runs as the user, so $HOME/.airc resolves identically.

2. join --quiet, which the task now passes. Hiding the window alone would trade noise for blindness — a start that failed would have nowhere to say so. So the flag is deliberately narrow.

What --quiet does NOT suppress

  • Warnings and errors, all still on stderr. A default-room change (card 1eae6f3e exists precisely so that is never silent), an unresolvable gh token, a failed attach. A start that fails silently is worse than one that is noisy.
  • The room-doctrine block. Agent runner harnesses scrape that region from join stdout (card 745e93f0) — it is a transport, not decoration.

staleness::warn_if_stale() moves after Cli::parse() so a quiet join can opt out. It is a nudge for a human at a prompt; nobody at a logon screen can act on it.

Interactive airc join is byte-for-byte unchanged. Every suppression sits behind a flag only the autostart task passes.

Validation

cargo check -p airc-cli                    exit 0, zero errors
install.ps1 via PowerShell AST parser      parses clean
non-ASCII lines in install.ps1             8 before, 8 after (added none)

The live airc-join task on this machine is deliberately not re-registered — that is a deploy action on a running node and belongs to whoever runs the installer.

Not in scope

Two things this deliberately leaves alone:

  • The work board cache: ... rebuilding projection from scratch line comes from airc-lib on a normal migration and is phrased like a failure. Worth softening, but it is a different crate and a different concern.
  • The continuum core has no equivalent autostart task, which is why airc came back after the restart and the node did not. That is CambrianTech/continuum#3943; airc-join is the working precedent it should copy.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Q4NU4VNiELPQfBpCacDZGc

The `airc-join` logon task registers with the DEFAULT principal, which is an
interactive logon. A console application given an interactive logon gets a
console — and because `join` is long-running by design, that console stays
open for the life of the mesh connection.

Joel, on his own machine: "this is in a terminal window every restart, and I
left running, but hacky looking nonetheless to see in one of MANY terminal
windows that appear, but this is the only one that is there more than briefly."

It is the only long-lived window among many that flash past at startup, so it
is the one the operator looks at. What it shows, in order, is a staleness
banner, a two-line `git checkout` recovery incantation for a known hang class,
`GH_TOKEN (len 40)`, extended-length UNC-style paths, wire/scope/mesh internals,
and a cache-format migration phrased like a failure. Nothing is broken; it
reads as scaffolding somebody forgot to remove.

TWO CHANGES:

1. The task registers with an S4U principal and `-Hidden`. S4U ("run whether
   logged on or not", no stored password) runs without an interactive desktop,
   so no console is allocated. airc needs no desktop — it writes under the user
   profile and talks over a socket — and still runs AS the user, so
   `$HOME/.airc` resolves identically.

2. `join --quiet` suppresses the informational attach banner, and the task uses
   it. Hiding the window alone would trade noise for BLINDNESS, so the flag is
   deliberately narrow.

WHAT --quiet DOES NOT SUPPRESS, and why:

  - warnings and errors, all still on stderr. A default-room change (card
    1eae6f3e exists precisely so that is never silent), an unresolvable gh
    token, a failed attach. A start that fails silently is worse than one that
    is noisy.
  - the room-doctrine block. Agent runner harnesses scrape that region from
    join stdout (card 745e93f0); it is a transport, not decoration.

`staleness::warn_if_stale()` moves after `Cli::parse()` so a quiet join can opt
out of the banner. It is a nudge for a human at a prompt; nobody at a logon
screen can act on it.

Interactive `airc join` is byte-for-byte unchanged — every suppression is
behind an explicit flag that only the autostart task passes.

Validated: `cargo check -p airc-cli` exits 0 with zero errors; install.ps1
parses clean via the PowerShell AST parser. The live `airc-join` task on this
machine is deliberately NOT re-registered — that is a deploy action on a
running node and belongs to whoever runs the installer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4NU4VNiELPQfBpCacDZGc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant