Repository navigation
Description
Context
The project uses agent-hub design specs: Markdown files with id, type and paths frontmatter; the hub names the covering spec when a task touches those paths, and AGENTS.md requires updating the owning spec with a change to a contract it states.
- verified 2026-11-09: the three files in
docs/specs/have no frontmatter, so no code is covered. Only fleet/monitoring and tenant have any design record. - verified: the tenant spec contradicts itself (sshpiper listed out of scope, then shipped in feat(tenant): one SSH port for all tenants through sshpiper #80/feat(tenant): one SSH port for all tenants through sshpiper (#80) #81; sync "daily" vs every 2 minutes since v0.17.0); the fleet spec still reads "approved for implementation" and lacks
--skip-unreachable, apply-pending, Prometheus reload, doctor disk thresholds and the exporter firewall guard. docs/specs/2026-10-03-rollout-verification.mdis a one-off deployment checklist.
Implementation starts only on the owner's go-ahead.
Decisions
-
Specs describe current behaviour (living documents), one per feature, at
docs/specs/<id>.md. Dated design files are folded into them; history stays in git and the linked issues. -
Every non-test Go file,
scripts/*,.goreleaser.yamland the workflows are covered by exactly one spec. Shared files belong to the spec that owns their contract. -
Allowed types:
goal(one),architecture(one),module,submodule; non-goal specs setparent. -
verified-againstis stamped by a person (ahub specs stamp), never by an agent. -
2026-11-09: partition table amended to what ahub accepts:
status: active; host-base, ssh-access, security, users, docker-nvidia, gpu-allocation, cloudflared, monitoring-exporters and doctor-schedule useparent: architecturewithdepends-on: [engine](a module cannot be the child of a module); paths are listed per file. Basis:ahub specs checkin PR docs(specs): per-feature design specs covering every source file #107.
Design
Each spec: frontmatter (id, type, title, status, parent, paths) then Purpose → Contracts and invariants → Behaviour (Check/Apply, CLI) → Distro support → Safety → Tests that pin it → Open decisions.
| id | type | parent | paths |
|---|---|---|---|
rootfiles |
goal | - | (none) scope, users, non-goals |
architecture |
architecture | rootfiles | cmd/rootfiles/main.go, internal/ui/** |
cli-runtime |
module | architecture | internal/cli/{root,runtime,output,provenance,native_system}.go |
engine |
module | architecture | internal/module/{module,preflight,package_commands}.go, internal/cli/{apply,check,status}.go |
config |
module | architecture | internal/config/{config,loader,validate,fingerprint,snapshot,detector}.go, internal/config/profiles/**, internal/cli/configcmd.go |
distro-rocky |
module | architecture | internal/config/distro.go, internal/module/{ssh_rocky,security_rocky}.go, internal/exec/rpm.go |
exec-packages |
module | architecture | internal/exec/{runner,apt,package_manager}.go, internal/module/packages.go |
state-rollback |
module | architecture | internal/state/**, internal/exec/backup.go, internal/cli/{rollback,backup}.go |
host-base |
module | engine | internal/module/{locale,system,storage}.go |
ssh-access |
module | engine | internal/module/{ssh,access,network}.go |
security |
module | engine | internal/module/security.go |
users |
module | engine | internal/module/{users,accounts,lifecycle,quota}.go, internal/cli/{user,userlife}.go |
docker-nvidia |
module | engine | internal/module/{docker,daemonjson,nvidia}.go |
gpu-allocation |
module | engine | internal/module/{gpu,mig}.go, internal/cli/gpu.go |
cloudflared |
module | engine | internal/module/cloudflared.go, internal/cli/tunnel.go |
monitoring-exporters |
module | engine | internal/module/{monitoring,monitoring_exporters,monitoring_firewall,monitoring_guard}.go, internal/module/assets/**, internal/config/{monitoring,monitoring_validate}.go |
monitoring-hub |
submodule | monitoring-exporters | internal/module/monitoring_hub.go, internal/config/monitoring_discovery.go |
doctor-schedule |
module | engine | internal/module/doctor.go, internal/cli/{doctor,schedule}.go |
self-update |
module | architecture | internal/cli/upgrade.go, scripts/*, .goreleaser.yaml, .github/workflows/** |
fleet |
module | architecture | internal/fleet/**, internal/cli/fleet.go, internal/module/fleet_sudo.go |
tenant |
module | architecture | internal/tenant/**, internal/module/{tenant,tenant_piper}.go, internal/cli/tenant.go |
Changes
- New
docs/specs/<id>.mdfor every row;git mvthe tenant and fleet design files totenant.md/fleet.mdand update them; monitoring parts of the fleet spec move tomonitoring-exporters/monitoring-hub; delete2026-10-03-rollout-verification.mdafter folding its verification table intofleetanddistro-rocky. - Update links (README, docs/tenant.md, AGENTS.md architecture line).
- AGENTS.md: one line pointing to
docs/specs/as the owner of contracts.
Acceptance criteria
- AC1:
ahub specs checkexits 0 (no errors; warnings listed in the PR). - AC2:
ahub specs covers <file>names exactly one spec for every non-test Go file,scripts/*,.goreleaser.yamland.github/workflows/*(script overgit ls-files, output in the PR). - AC3: the tenant and fleet contradictions listed in Context are resolved.
- AC4: every spec states the open items from the 2026-11-09 audit issues that touch its paths, linking the issue.
Tasks
- T1: goal + architecture specs, partition table final (AC1)
- T2: module specs for engine, config, cli-runtime, state, exec, distro
- T3: module specs for host-base, ssh-access, security, users, docker-nvidia, gpu, cloudflared, monitoring, doctor, self-update
- T4: convert fleet and tenant, retire the rollout checklist (AC3)
- T5: coverage script and audit links (AC2, AC4)
Out of scope
- Stamping
verified-against(the owner does it after review).
Activity
docs(specs): correct cloudflared, config, engine and self-update clai…
docs(specs): per-feature design specs covering every source file (#107)