<!-- Authored per the the-loop:writing skill. -->
Tasks: the hosted ingress set follows the config
Phase 4 of 4. Each task names the requirement it satisfies and the testing-plan row that proves it; the test lands with the change (red first).
Task list
- [x] A1 —
_wanted(config)andstart_hosted_ingresseson it. The starter list composed fromcore.lifecycle.enabled_services, in boot order; the boot path unchanged in behaviour. Req: R1.2, R1.3 · Test: T1. - [x] A2 —
HostedIngresses.start/stop/reconcile, the supervisor thread on aReloader, the lock around reconcile-vs-stop,reasonon_HostedIngress.stopand the two events,config.reloadedwith a detail. Req: R1.1, R1.2, R1.4–R1.6 · Test: T2, T8. Deps: A1. - [x] A3 — the lifespan holds the supervisor.
build_lifespan(config_path=…);create_appandTheLoop.lifespanpass their paths;hostIngresses: falsebuilds nothing. Req: R1.6, R1.7 · Test: T12. Deps: A2. - [x] B1 —
statuswording. The running-but-disabled flag, hosted and standalone. Req: R2.1, R2.2 · Test: T7. - [x] C1 — catalogue and docs.
eventlog.EVENT_TYPESdescriptions;docs/capabilities/control-plane.md(hot-reload requirement, history row);docs/capabilities/channels.md(hosted-listener bullet, history row);docs/cli/supervision.mdanddocs/guide/slack.md(a savedread.modechange takes effect without a restart); the e2e report's B5 links the issue; evidence files. Deps: A1–B1.
Dependency graph (DAG)
Checkpoints
- After A2:
tests/test_hosted_reconcile.pygreen;tests/test_hosted_listener.pystill green. - After A3:
tests/test_hosted_ingress_integration.py,tests/test_sdk*.pygreen. - After C1: full suite, ruff, pyright, markdownlint.
Review comments
None yet.