docs: record stage 0 as deployed, and what the first deploy cost
All checks were successful
deploy / deploy (push) Successful in 5m32s

The status said "nothing has been deployed to bob, the workflow has never run",
which stopped being true at run 8. Leaving it would be the same class of
misleading state this repo keeps trying to remove.

Also record the seven faults it took to get green, because six of the eight were
silent rather than loud: a runner label that meant the job was never scheduled,
a vhost that nginx -t accepts and the SNI router never reaches, a cert whose SAN
only the client checks, an ordering trap, a --chmod that stops applying after
the first deploy, an API that looks healthy from the host it is unreachable on,
and a health probe checking a unit name that expanded to nothing.

The pattern is the useful part for later stages: the expensive faults were the
ones where a check passed while measuring nothing.

Closes #9

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013TxK1CWPkFXqdcXMJ4hVe6
This commit is contained in:
rob thijssen
2026-08-07 17:06:59 +03:00
parent 8067cde288
commit ffa2ad7f72
2 changed files with 34 additions and 4 deletions

View File

@@ -611,8 +611,34 @@ There is no invariant here that is merely written down.
loads at `tireless.internal`, all three units are active, `tireless preflight`
reports the expected billing mode, and the deploy workflow is green end to end.
*Not done yet:* nothing in this stage has been deployed to bob. The workflow has
never run.
**Deployed and verified, 2026-08-07.** The workflow runs green end to end;
`tireless-api` and `tireless-poller` are active on bob; `https://tireless.internal`
serves the dashboard and proxies `/v1`; the served certificate matches disk.
*Outstanding, and deliberately so:* `tireless-runner` is in `failed`, because the
interactive agent login has not been done as the service account on bob
(`script/infra-setup.sh` step 1). That is the invariant working — a runner with
no credentials refuses to start rather than pretending — and it is the one thing
in stage 0 that cannot be automated.
Seven faults were found getting the first deploy green, and they are worth
knowing because most were invisible rather than loud:
| Fault | Why it did not announce itself |
| --- | --- |
| `runs-on: fedora-43-rust` — no such runner label | Job was never scheduled; two earlier runs sat queued and were reaped as "cancelled" |
| Vhost bound `:443`, which the stream SNI router owns | `nginx -t` passes; symptom is the wrong certificate on a working handshake |
| Cert path pointed at the host identity cert | Its SAN is bob's FQDN, so only a client verifying `tireless.internal` fails |
| `--rsync-path` word-split by an unquoted variable | Loud, but only on the half of the deploy that used the variable |
| `restorecon` on a directory that cannot exist yet | Ordering: the account that owns it is created later in the same deploy |
| Config shipped `0640 root:root`, unreadable by the service user | Compounded by `--chmod` being a no-op without `-p`, so the fix would have applied once and then silently stopped |
| API bound the clap default, ignoring `[api] bind` | The service looks perfectly healthy *from the host*; only the proxy that fronts it fails |
| Health probe expanded `$unit` remotely | Checked `.service`, i.e. nothing — and would have reported healthy regardless |
The pattern is worth carrying into later stages: the expensive faults were the
ones where a check passed while measuring nothing. Where a probe exists, it
should be able to fail — which is why the health probe now runs from the proxy
rather than bob's loopback.
### Stage 1 — Forge ingestion (read-only)

View File

@@ -28,11 +28,15 @@ Full design, constraints and the staged implementation plan:
## Status
**Stage 0 (foundations) is built and passes its gate; nothing is deployed yet.**
**Stage 0 (foundations) is built, deployed and verified.**
Working: the domain model, routing, budgets, plan validation, the policy guards,
configuration loading and validation, the four system prompts, and preflight.
`tireless preflight` runs today.
The API and poller run on bob, the dashboard is served at
`https://tireless.internal`, and the deploy workflow is green end to end.
`tireless-runner` deliberately refuses to start until the interactive agent
login has been completed as the service account — see `script/infra-setup.sh`.
Not built: Postgres persistence, the forge clients, the poll loop, and every
agent executor. Stages 18 in §7 of the design document say what lands when.