Implements the deployment loop end-to-end on the CIS490 side:
shipper/
config.py ShipperConfig (host_id, paths, receiver endpoint, mTLS)
transport.py httpx-based PUT + ping with mTLS + bearer support
queue.py scan data/episodes/, tar+zstd via system zstd, ship,
retire to data/shipped/. Idempotent across crashes per
the state machine in docs/transport.md.
__main__.py CLI: --ping (smoke test), --once (one pass), or daemon
receiver/app.py: new POST /v1/ping that requires the same auth as PUT
/v1/episodes but writes nothing. Used by `cis490-shipper --ping`
during lab-host bring-up to verify the WG/Caddy/mTLS path before
shipping any real bytes.
etc/
cis490-shipper.service systemd unit for the lab-host shipper
cis490-orchestrator.service systemd unit for the lab-host queue
(kept disabled by default until queue
mode lands)
lab-host.toml.example config template
scripts/
install-lab-host.sh idempotent installer; verifies prereqs,
creates cis490 service user, syncs repo to
/opt/cis490, builds venv, drops systemd units
and config template
install-receiver.sh same, for the receiver role on the central WG
node (Pi5 in our setup)
tests/test_shipper.py 11 end-to-end tests against a real Uvicorn
server hosting the receiver app. Exercises
ping, tar+ship, idempotent re-ship, 409
conflict, transient (receiver down), tarball
round-trip via system zstd.
AGENTS.md guidance for AI agents working on this and sibling repos.
Headline: when you hit an issue you can't fully fix in
scope, file a Forgejo issue rather than leaving a TODO.
51/51 tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.4 KiB
3.4 KiB
AGENTS.md — guidance for AI agents working on this repo
This project is part of the spectral lab (http://maxgit.wg/spectral/).
The conventions below also apply to sibling repos (wg-enroll,
wg-pki, caddy, iptmonads, matrix, forgejo, vault,
openclaw-deploy).
File an issue when you hit a problem
When you run into an issue you cannot fully resolve in the current turn, file it as a Forgejo issue on the relevant repo before moving on. Do not silently log a TODO comment, leave a partial workaround, or assume someone else will remember. The issue tracker is the durable record.
This applies to:
- a build / test / typecheck failure you can't fix in scope
- a bug you discover but aren't tasked with fixing
- a missing dep, missing config, or env-only failure that blocks E2E
- a design gap you've worked around but want a follow-up to fix properly
- a scope-out you made (e.g. "deferred Tier 4 sample fetch") that needs an owner so it doesn't get lost
Don't file an issue when:
- the user is in the conversation and you can just tell them
- it's already filed (search first:
GET /api/v1/repos/<owner>/<repo>/issues?state=open&q=<keyword>) - it's truly a non-issue (a one-line edit you're about to make this same turn)
How to file (Forgejo API)
The local Forgejo at http://10.100.0.1:3000 accepts API calls with a
token-bearer header:
curl -s -X POST \
-H "Authorization: token <TOKEN>" \
-H "Content-Type: application/json" \
http://10.100.0.1:3000/api/v1/repos/spectral/<repo>/issues \
-d '{
"title": "<short, action-oriented title>",
"body": "<context, repro, attempted fixes, suggested next step>"
}'
The token comes from the user's session — never embed one in code or commits.
What a good issue body contains
- Context — one sentence on what was being attempted.
- What happened — the actual error, log line, or unexpected behavior. Paste exact output.
- What was tried — every workaround you attempted and why it didn't stick.
- Suggested next step — the smallest change that would resolve it, if you have a guess. "Unknown" is a fine answer.
- Related — link the commit / PR / file:line where the issue surfaced.
What a good title looks like
| Bad | Good |
|---|---|
tests broken |
tests/test_episode.py: race when t_mono_origin_ns is set in run() not __init__ |
caddy thing |
Caddy: client_auth requires absolute path; relative trusted_ca_cert_file silently fails |
fix later |
shipper: 5xx backoff cap is 5min, doc says 1min — pick one |
After filing
- Reference the issue number in the next commit message:
Refs spectral/<repo>#<n>orCloses spectral/<repo>#<n>if your current change actually fixes it. - If the issue is on a different repo than the one you're committing
to, fully qualify:
spectral/wg-pki#3.
Other conventions
- Naming: never coin USB / device / service names on the user's behalf. Ask first. Reusing an old name is especially bad.
/etcconfigs:Readfirst, copy second. Never overwrite a/etc/...file from a template without checking what's actually there.- wg-enroll scope: creation-only. Don't add admin / service-activation features to it.
- Don't expand a project's binary name beyond its own boundary:
openclawis the queue/permissions binary inopenclaw-deploy. This repo iswg-enroll(or its caller). Don't conflate.