forgejo-warden
forgejo-warden keeps a Forgejo org and its repos in a declared state. Runs are dry by default, and deletes happen only where the policy says owned. Its policy is one file, and the .ts form of that file landed in forgejo-warden#33.
Author
A governance.ts is typed by the package’s own GovernanceConfig, with satisfies on its export default, and its helper is an arrow in the same file. Both forms fold under data-host.
The schema is 195 lines of hand-written interfaces over eight cycles: org settings, membership and teams; repo settings, branch protection and repo baseline; secrets and variables, and webhooks. Everything the YAML parser could not do is ordinary TypeScript. Flow style, multi-line scalars and anchors become a template literal, a const, a spread.
Check
Both phases are already in the tool. The loader validates the declared policy and reports the exact field path on a bad shape, which is a pre-synthesis rule over the folded values. The guardrails (removalDeltaCap, adminFloor) run over the computed plan before any apply, a post-synthesis rule over the artifact.
Generate
Warden reads live reality and diffs it against the declared source; the plan it prints is the generator’s direction, live to source, one step at a time. It also emits its own CI pipeline for Forgejo Actions from TypeScript, through chant’s github lexicon.
Proof
The .ts and .yml forms of the same policy load to the same object, asserted in warden’s tests, and --config-mode check asserts it for any policy by folding and running it. The evaluator is the published reference, so the consumer needs no chant install. The whole loop runs against the e2e sandbox, which is the tutorial.
Warden names the profile it runs in. At 86dc640 its loader calls foldProject with an empty host and profile: "data-host". That commit is the one the weekly demo pins. Nothing of the policy is invoked to produce the plan. A file that is not data is refused there with its rule and its reason rather than demoted to a run. That refusal is what F-Profile-DataHost requires of an evaluator with no runtime.