Data Model: Opt-in hosted drain and ledger flags
Configuration (operator-facing contract)
.kittify/config.yaml (repository, committed):
hosted:
drain: false # repository permits live drain (default false/absent)
ledger:
projection: true # auto-refresh .kittify/derived/<mission>/ (default true)
Runtime-root config.toml (personal; ~/.spec-kitty/config.toml on POSIX, $SPEC_KITTY_HOME/config.toml when set):
[hosted]
drain = true # personal activation (default false/absent)
[sync]
server_url = "https://team.example" # hosted endpoint (no built-in default)
Value objects
personal_source: str, narrowed_by: str | None (env kill switch), reason: str. Invariant: enabled == (repo_value is True and personal_value is True and narrowed_by is None).
- DrainPosture —
enabled: bool,repo_value: bool | None,repo_source: str,personal_value: bool | None, - LedgerPosture —
enabled: bool(default True),source: str. - ResolvedServerTarget — unchanged shape (
resolved_server_url: str);PACKAGED_DEFAULTis removed. An unconfigured machine yieldsHostedEndpointUnconfigured(explicit callers) orNonefromresolve_server_target_or_none()(automatic callers).
Errors
DrainDisabled(RuntimeError)— raised at a network edge; carries a one-line human reason.HostedEndpointUnconfigured(ConfigurationError)— raised by the resolver for explicit callers; carries the guidance line with the resolved config path.
State: execution-state projection
.kittify/derived/<mission_slug>/status.json, board-summary.json (+ progress.json, lifecycle.json when write-free generators allow). Gitignored, derived, rebuildable with spec-kitty materialize; never read as authority.