Decide whether 15 repos keep declaring .ward/ward.yaml, now that no validator reads it #1329

Open
opened 2026-08-27 10:28:25 +00:00 by coilyco-ops · 4 comments
Owner

The question

.ward/ward.yaml exists in 15 of the 16 repositories on this host. No validator requires it and no validator reads it. catalog-trifecta dropped it as a fourth trifecta member under coilysiren/inbox#385, and Ward's loader is being cut under #1299.

It is not dead, which is what makes this a decision rather than a cleanup. The surviving contract and its real consumers are now written down in docs/ward-specs.md, landed in #1328.

What actually reads it today

Swept across every repository on this host before filing.

  • agentic-os-kai/scripts/pull-capabilities.py reads a capabilities: list of provider/skill-dir strings and symlinks those skills into a leaf repo for qwen-opencode. Only coilyco-gaming/galaxy-gen declares it. This key was never in Ward's documented schema.
  • eco-mods/scripts/ci-root-hygiene.sh runs test -f .ward/ward.yaml, so that repo's CI fails if the file is removed.
  • Nothing reads catalog.description or catalog.dependsOn. They are declared nearly everywhere. The comment in this repo's own copy calls them "catalog metadata for the cross-repo knowledge graph", and no code on this host consumes that graph.

The options, and what each costs

  • Keep all 15 as they are. Zero work. The cost is 15 files that read as configuration, that a validator will not catch drifting, and that each carry an agent: block whose runtime no longer exists.
  • Trim the retired keys, keep the file. Remove agent.image, agent.release-channel, and agent.workflow from each, leaving catalog and any capabilities. Honest about what survives, and touches every repo.
  • Remove the file wherever nothing reads it. Keep it in galaxy-gen for capabilities and in eco-mods until its CI check moves. Smallest surviving surface, and it breaks the README, AGENTS, and FEATURES "See also" links that still point at the file in every repo carrying one.
  • Give catalog a real consumer. The knowledge graph was the reason the block exists. If it is worth having, something should read it, and that is a build rather than a cleanup.

I am not picking here. The third option is the one that looks obviously right and has the largest hidden cost, which is the reason to make it deliberately.

Why it wants deciding before the archive

Not urgent, and cheaper now than later. While Ward's docs are still readable, anyone can check what a key meant. Once the repository is read-only and the runtime is gone, a file nobody validates and nobody reads becomes archaeology, and the answer to "can I delete this" gets more expensive every month.

Boundaries

  • Whatever is decided, .ward/ward.yaml in this repository is the one the catalog hooks historically pinned, so it is the wrong place to start experimenting.
  • The ward: AGENTS.md frontmatter key is unrelated and stays. It is read by agentic_os.generators.generate_git_workflow and is vocabulary rather than a runtime.
  • Any option past the first is a fleet-wide mutation, so it is an ansible rollout rather than a hand sweep, per the authoring-versus-rollout split in AGENTS.md.

Labels

Could not be applied. AWS credentials are stale on this host, so the org label IDs were unreachable. Intended: priority/P3 and autonomy/async-consult, because the fork is a judgment call rather than a mechanical one.

  • #1299 - the Ward freeze and archive.
  • #1328 - the schema documentation this issue is the follow-on to.
  • coilysiren/inbox#385 - where catalog-trifecta dropped the requirement.
## The question `.ward/ward.yaml` exists in 15 of the 16 repositories on this host. **No validator requires it and no validator reads it.** `catalog-trifecta` dropped it as a fourth trifecta member under `coilysiren/inbox#385`, and Ward's loader is being cut under #1299. It is not dead, which is what makes this a decision rather than a cleanup. The surviving contract and its real consumers are now written down in [`docs/ward-specs.md`](docs/ward-specs.md), landed in #1328. ## What actually reads it today Swept across every repository on this host before filing. * **`agentic-os-kai/scripts/pull-capabilities.py`** reads a `capabilities:` list of `provider/skill-dir` strings and symlinks those skills into a leaf repo for qwen-opencode. Only `coilyco-gaming/galaxy-gen` declares it. This key was never in Ward's documented schema. * **`eco-mods/scripts/ci-root-hygiene.sh`** runs `test -f .ward/ward.yaml`, so that repo's CI fails if the file is removed. * **Nothing reads `catalog.description` or `catalog.dependsOn`.** They are declared nearly everywhere. The comment in this repo's own copy calls them "catalog metadata for the cross-repo knowledge graph", and no code on this host consumes that graph. ## The options, and what each costs * **Keep all 15 as they are.** Zero work. The cost is 15 files that read as configuration, that a validator will not catch drifting, and that each carry an `agent:` block whose runtime no longer exists. * **Trim the retired keys, keep the file.** Remove `agent.image`, `agent.release-channel`, and `agent.workflow` from each, leaving `catalog` and any `capabilities`. Honest about what survives, and touches every repo. * **Remove the file wherever nothing reads it.** Keep it in `galaxy-gen` for `capabilities` and in `eco-mods` until its CI check moves. Smallest surviving surface, and it breaks the README, AGENTS, and FEATURES "See also" links that still point at the file in every repo carrying one. * **Give `catalog` a real consumer.** The knowledge graph was the reason the block exists. If it is worth having, something should read it, and that is a build rather than a cleanup. I am not picking here. The third option is the one that looks obviously right and has the largest hidden cost, which is the reason to make it deliberately. ## Why it wants deciding before the archive Not urgent, and cheaper now than later. While Ward's docs are still readable, anyone can check what a key meant. Once the repository is read-only and the runtime is gone, a file nobody validates and nobody reads becomes archaeology, and the answer to "can I delete this" gets more expensive every month. ## Boundaries * Whatever is decided, `.ward/ward.yaml` in **this** repository is the one the catalog hooks historically pinned, so it is the wrong place to start experimenting. * The `ward:` AGENTS.md frontmatter key is unrelated and stays. It is read by `agentic_os.generators.generate_git_workflow` and is vocabulary rather than a runtime. * Any option past the first is a fleet-wide mutation, so it is an ansible rollout rather than a hand sweep, per the authoring-versus-rollout split in AGENTS.md. ## Labels Could not be applied. AWS credentials are stale on this host, so the org label IDs were unreachable. Intended: `priority/P3` and `autonomy/async-consult`, because the fork is a judgment call rather than a mechanical one. ## Related * #1299 - the Ward freeze and archive. * #1328 - the schema documentation this issue is the follow-on to. * `coilysiren/inbox#385` - where catalog-trifecta dropped the requirement.
Author
Owner

This was litigated in coilysiren/inbox#385, and that issue's central premise has since gone stale

Kai pointed me at prior litigation rather than re-deciding, and it is coilysiren/inbox#385, still open: "Epic: finish the ward retirement - relocate the catalog block, then drop .ward/ and the launch scaffolding".

#385 reached the opposite conclusion this issue reaches, and it did so for a specific reason:

agentic-os-kai/scripts/build-catalog-graph.py reads the catalog: block and emits data/catalog-graph.yaml, which feeds compile-repo-digests.py and check-catalog-cross-org.py. Thirty nodes today. Live, load-bearing, and nothing to do with ward.

So the catalog block needs a new home, not a delete.

That is why #385 built a four-step Track A around relocating the block to .catalog.yaml before anything could be deleted, and why it explicitly overrode agentic-os#1081's closure in favour of ward#1660.

That reader is gone. I checked rather than inferred.

Swept in the agentic-os-kai checkout just now:

  • scripts/build-catalog-graph.py - does not exist
  • data/catalog-graph.yaml - does not exist
  • just build-catalog-graph - verb does not exist
  • just check-catalog-cross-org - verb does not exist
  • .forgejo/workflows/build-catalog-graph.yml and the .github equivalent - neither exists

What survives is scripts/ci/rebuild-catalog-graph.sh, which still opens with "Invoked as a single-line run step from build-catalog-graph.yml" and calls both retired verbs. It is dead code: its generator, its output, its verbs, and its workflow are all gone. Nothing invokes it, and it would fail immediately if anything did.

What that changes

This issue's factual claim is correct and current. Nothing reads catalog.description or catalog.dependsOn. #385's finding was true when written on 2026-08-19 and is not true now.

#385's Track A is moot as written. Relocating the catalog block to .catalog.yaml was justified entirely by a consumer that no longer exists. Doing that work today would move a block from one place nothing reads to another place nothing reads, across 29 repos.

That does not settle the fork this issue poses, because "give catalog a real consumer" is still a live option and rebuilding the graph is exactly what would make relocation worth doing. But it does mean the decision is cheaper and more open than #385 implies, and anyone reading #385 first will over-estimate the constraint. Worth reconciling the two before either is worked.

The other two readers #385 names are unaffected: check_catalog_block and check_catalog_trifecta are lint, and catalog-trifecta already dropped the requirement under inbox#385 itself.

Two loose ends, neither of which I acted on

  • scripts/ci/rebuild-catalog-graph.sh in agentic-os-kai should be deleted or revived. I left it rather than sweeping it, because it belongs to #385's Track B scaffolding cleanup and a surprise deletion is worse than a filed finding.
  • #385's Track B flags that every repo's AGENTS.md carries ward: workflow: frontmatter and asks where the PR-lane convention lives if ward goes. That is now answered and worth recording there: the frontmatter key is read by agentic_os.generators.generate_git_workflow, rendered into a managed AGENTS.md block by git-workflow, and as of #1330 it is also what pr-guard consults before standing down on a merge-remote-main push. The key has three live consumers and is unrelated to Ward's runtime, so it stays regardless of what happens to .ward/ward.yaml.
## This was litigated in coilysiren/inbox#385, and that issue's central premise has since gone stale Kai pointed me at prior litigation rather than re-deciding, and it is **coilysiren/inbox#385**, still open: *"Epic: finish the ward retirement - relocate the catalog block, then drop .ward/ and the launch scaffolding"*. #385 reached the opposite conclusion this issue reaches, and it did so for a specific reason: > **`agentic-os-kai/scripts/build-catalog-graph.py`** reads the `catalog:` block and emits `data/catalog-graph.yaml`, which feeds `compile-repo-digests.py` and `check-catalog-cross-org.py`. Thirty nodes today. **Live, load-bearing, and nothing to do with ward.** > > So the catalog block needs **a new home**, not a delete. That is why #385 built a four-step Track A around relocating the block to `.catalog.yaml` before anything could be deleted, and why it explicitly overrode agentic-os#1081's closure in favour of ward#1660. ## That reader is gone. I checked rather than inferred. Swept in the `agentic-os-kai` checkout just now: * `scripts/build-catalog-graph.py` - **does not exist** * `data/catalog-graph.yaml` - **does not exist** * `just build-catalog-graph` - **verb does not exist** * `just check-catalog-cross-org` - **verb does not exist** * `.forgejo/workflows/build-catalog-graph.yml` and the `.github` equivalent - **neither exists** What survives is `scripts/ci/rebuild-catalog-graph.sh`, which still opens with *"Invoked as a single-line run step from build-catalog-graph.yml"* and calls both retired verbs. It is dead code: its generator, its output, its verbs, and its workflow are all gone. Nothing invokes it, and it would fail immediately if anything did. ## What that changes **This issue's factual claim is correct and current.** Nothing reads `catalog.description` or `catalog.dependsOn`. #385's finding was true when written on 2026-08-19 and is not true now. **#385's Track A is moot as written.** Relocating the catalog block to `.catalog.yaml` was justified entirely by a consumer that no longer exists. Doing that work today would move a block from one place nothing reads to another place nothing reads, across 29 repos. That does not settle the fork this issue poses, because "give `catalog` a real consumer" is still a live option and rebuilding the graph is exactly what would make relocation worth doing. But it does mean the decision is **cheaper and more open than #385 implies**, and anyone reading #385 first will over-estimate the constraint. Worth reconciling the two before either is worked. The other two readers #385 names are unaffected: `check_catalog_block` and `check_catalog_trifecta` are lint, and `catalog-trifecta` already dropped the requirement under inbox#385 itself. ## Two loose ends, neither of which I acted on * `scripts/ci/rebuild-catalog-graph.sh` in `agentic-os-kai` should be deleted or revived. I left it rather than sweeping it, because it belongs to #385's Track B scaffolding cleanup and a surprise deletion is worse than a filed finding. * #385's Track B flags that every repo's `AGENTS.md` carries `ward: workflow:` frontmatter and asks where the PR-lane convention lives if ward goes. **That is now answered and worth recording there**: the frontmatter key is read by `agentic_os.generators.generate_git_workflow`, rendered into a managed AGENTS.md block by `git-workflow`, and as of #1330 it is also what `pr-guard` consults before standing down on a `merge-remote-main` push. The key has three live consumers and is unrelated to Ward's runtime, so it stays regardless of what happens to `.ward/ward.yaml`.
Author
Owner

The deadline this issue named has now passed

coilyco-flight-deck/ward is archived as of 2026-08-28T04:22:22Z. This issue's own argument for deciding sooner was:

While Ward's docs are still readable, anyone can check what a key meant. Once the repository is read-only and the runtime is gone, a file nobody validates and nobody reads becomes archaeology, and the answer to "can I delete this" gets more expensive every month.

That is now the state, so the cost curve this issue described has started. Recording it rather than acting, since the fork is still Kai's.

What the archive settles and what it does not

Settles: the agent: block. Its runtime is gone and the repository that defined it is read-only, so agent.image, agent.release-channel, and agent.workflow describe nothing that can run. Whatever happens to the file, those three keys are dead weight rather than a judgment call.

Does not settle: catalog. That is still the real fork, and per my note above it is more open than coilysiren/inbox#385 implies, because the graph consumer #385 was built around no longer exists.

Unaffected: the ward: AGENTS.md frontmatter key, which this issue already scoped out. It now has three live consumers rather than two: generate_git_workflow, the git-workflow hook, and as of #1330 pr-guard, which reads it before standing down on a merge-remote-main push. It survives the archive completely and is worth keeping distinct from .ward/ward.yaml in any decision here, since the shared name is the main thing that makes them look linked.

One correction that follows

Anything written this week describing ward as "not archived yet" is stale, including a paragraph I wrote on coilysiren/inbox#457 about two minutes before the archive landed. That issue is now closed and carries the correction.

## The deadline this issue named has now passed `coilyco-flight-deck/ward` is archived as of `2026-08-28T04:22:22Z`. This issue's own argument for deciding sooner was: > While Ward's docs are still readable, anyone can check what a key meant. Once the repository is read-only and the runtime is gone, a file nobody validates and nobody reads becomes archaeology, and the answer to "can I delete this" gets more expensive every month. That is now the state, so the cost curve this issue described has started. Recording it rather than acting, since the fork is still Kai's. ## What the archive settles and what it does not **Settles:** the `agent:` block. Its runtime is gone and the repository that defined it is read-only, so `agent.image`, `agent.release-channel`, and `agent.workflow` describe nothing that can run. Whatever happens to the file, those three keys are dead weight rather than a judgment call. **Does not settle:** `catalog`. That is still the real fork, and per my note above it is more open than coilysiren/inbox#385 implies, because the graph consumer #385 was built around no longer exists. **Unaffected:** the `ward:` AGENTS.md frontmatter key, which this issue already scoped out. It now has three live consumers rather than two: `generate_git_workflow`, the `git-workflow` hook, and as of #1330 `pr-guard`, which reads it before standing down on a `merge-remote-main` push. It survives the archive completely and is worth keeping distinct from `.ward/ward.yaml` in any decision here, since the shared name is the main thing that makes them look linked. ## One correction that follows Anything written this week describing ward as "not archived yet" is stale, including a paragraph I wrote on coilysiren/inbox#457 about two minutes before the archive landed. That issue is now closed and carries the correction.
Author
Owner

Current inventory, swept just now. It is 16 of 21, and there are two keys and one reader this issue does not list.

Who carries it

keys declared repos
catalog only 12: deploy, eco-app, eco-ops, eco-mods, steam-ops, sirens-echo, factorio-mods, factory-game-v3, agent-compose, agentic-os-kai, agentic-os-hardware, voice-corpus
security + catalog 2: agentic-os-xxx, agent-proxy
agent + catalog 1: agentic-os itself
name + capabilities + catalog + security 1: galaxy-gen

agentic-os is the only repo still carrying an agent: block, and it is the one this issue warns is the wrong place to start experimenting. Its runtime is now archived, so that block is the single clearest piece of dead weight in the whole set.

Who reads it

catalog.description / catalog.dependsOn - nothing. Confirmed three ways rather than assumed: check_catalog_block.py is gone from main with no hook id and no console entry point; check_catalog_trifecta.py's own docstring records that the fourth member "was required here until ward was" retired; and the graph builder is gone, per my earlier note. Declared in all 16, read by none.

capabilities - live, one repo. agentic-os-kai/scripts/pull-capabilities.py still exists and mount-skills.sh documents the symlink path. Only galaxy-gen declares it.

Existence, not content - live. eco-mods/scripts/ci-root-hygiene.sh:8 runs test -f .ward/ward.yaml. Deleting the file breaks that repo's CI regardless of what is in it.

security: - nothing, and this issue does not mention the key at all. Three repos declare it. The only reference anywhere is a docstring in agentic-os-kai/scripts/sweep-ward-to-just.py noting the block "survives byte-identical" through that sweep, which is a statement about not disturbing it rather than a consumer.

tailnet.shortcut - a live reader with no data, also not listed here. infrastructure/scripts/generate-caddy-shortcuts.py walks every repo on Forgejo, fetches each default branch's .ward/ward.yaml, and generates Caddy site snippets from tailnet.shortcut declarations. It runs in Forgejo Actions and writes real config on kai-server. Zero of the 16 declare tailnet, so it reads the file on every run, finds nothing, and falls through to its coily.yaml / config.yml fallbacks.

That last one is the most interesting for the fork. It is not a reason to keep the file as it stands, but it does mean "nothing reads .ward/ward.yaml" is too strong: a production job reads the path, and a future shortcut declaration would land there.

A correction on my own method

I first reported deploy as declaring tailnet, because I grepped the whole file and matched the word inside its catalog.description prose, where it describes signoz-mcp as "private tailnet-only". Re-checked against top-level keys, deploy carries catalog alone. Flagging it because it is the same class of mistake as reading a description instead of the thing, one level down.

What this changes about the options

The third option, remove where nothing reads it, is now cheaper than this issue estimated for the agent: and security: blocks and unchanged for catalog. The two hard edges are eco-mods' existence check and galaxy-gen's capabilities, both already named here, plus the caddy generator's path expectation, which was not.

## Current inventory, swept just now. It is 16 of 21, and there are two keys and one reader this issue does not list. ### Who carries it | keys declared | repos | | --- | --- | | `catalog` only | 12: deploy, eco-app, eco-ops, eco-mods, steam-ops, sirens-echo, factorio-mods, factory-game-v3, agent-compose, agentic-os-kai, agentic-os-hardware, voice-corpus | | `security` + `catalog` | 2: agentic-os-xxx, agent-proxy | | `agent` + `catalog` | 1: **agentic-os itself** | | `name` + `capabilities` + `catalog` + `security` | 1: galaxy-gen | **agentic-os is the only repo still carrying an `agent:` block**, and it is the one this issue warns is the wrong place to start experimenting. Its runtime is now archived, so that block is the single clearest piece of dead weight in the whole set. ### Who reads it **`catalog.description` / `catalog.dependsOn` - nothing.** Confirmed three ways rather than assumed: `check_catalog_block.py` is gone from `main` with no hook id and no console entry point; `check_catalog_trifecta.py`'s own docstring records that the fourth member "was required here until ward was" retired; and the graph builder is gone, per my earlier note. Declared in all 16, read by none. **`capabilities` - live, one repo.** `agentic-os-kai/scripts/pull-capabilities.py` still exists and `mount-skills.sh` documents the symlink path. Only galaxy-gen declares it. **Existence, not content - live.** `eco-mods/scripts/ci-root-hygiene.sh:8` runs `test -f .ward/ward.yaml`. Deleting the file breaks that repo's CI regardless of what is in it. **`security:` - nothing, and this issue does not mention the key at all.** Three repos declare it. The only reference anywhere is a docstring in `agentic-os-kai/scripts/sweep-ward-to-just.py` noting the block "survives byte-identical" through that sweep, which is a statement about not disturbing it rather than a consumer. **`tailnet.shortcut` - a live reader with no data, also not listed here.** `infrastructure/scripts/generate-caddy-shortcuts.py` walks every repo on Forgejo, fetches each default branch's `.ward/ward.yaml`, and generates Caddy site snippets from `tailnet.shortcut` declarations. It runs in Forgejo Actions and writes real config on kai-server. **Zero of the 16 declare `tailnet`**, so it reads the file on every run, finds nothing, and falls through to its `coily.yaml` / `config.yml` fallbacks. That last one is the most interesting for the fork. It is not a reason to keep the file as it stands, but it does mean "nothing reads `.ward/ward.yaml`" is too strong: a production job reads the path, and a future shortcut declaration would land there. ### A correction on my own method I first reported `deploy` as declaring `tailnet`, because I grepped the whole file and matched the word inside its `catalog.description` prose, where it describes signoz-mcp as "private tailnet-only". Re-checked against top-level keys, `deploy` carries `catalog` alone. Flagging it because it is the same class of mistake as reading a description instead of the thing, one level down. ### What this changes about the options The third option, remove where nothing reads it, is now cheaper than this issue estimated for the `agent:` and `security:` blocks and unchanged for `catalog`. The two hard edges are eco-mods' existence check and galaxy-gen's `capabilities`, both already named here, plus the caddy generator's path expectation, which was not.
Author
Owner

Decided by Kai, 2026-08-29: delete everywhere, move capabilities elsewhere. The most work of the three options and the cleanest end state.

So .ward/ward.yaml goes from all 15 repos, and the one real consumer gets its input from somewhere that is not a Ward-shaped file in every repository on the fleet.

The consumer is the whole job

agentic-os-kai/scripts/pull-capabilities.py reads a capabilities: list of provider/skill-dir strings out of that file and symlinks those skills into a leaf repo for qwen-opencode. Deleting the files without rehoming that list breaks it silently, which is the shape this estate has spent the week fixing.

So the order is fixed: rehome the capabilities list first, prove the consumer reads the new location, then delete the 15 files. Not the other way round, and not both in one commit.

Where it lands is a question this issue does not answer. The natural candidates are pyproject.toml under [tool.agentic-os.*], where every other per-repo opt-out already lives, or the consumer owning its own list in agentic-os-kai rather than reading it out of each repo. The second is more consistent with config placement: the consumer is one script in one repo, so a list it maintains for itself is config at the lowest layer that fully determines it.

What survives

#1299 freezes Ward as a contract and explicitly keeps the .ward/ward.yaml schema and the ward: AGENTS.md lane vocabulary. This decision deletes the files, not the schema and not the lane keys. The lane declaration lives in AGENTS.md frontmatter and is read constantly, including by every agent resolving its own workflow, so nothing here touches it.

Done-condition

A sweep for .ward/ward.yaml across the fleet returning nothing, and pull-capabilities.py working against its new source with a run that proves it rather than an assumption that it still resolves.

**Decided by Kai, 2026-08-29: delete everywhere, move capabilities elsewhere.** The most work of the three options and the cleanest end state. So `.ward/ward.yaml` goes from all 15 repos, and the one real consumer gets its input from somewhere that is not a Ward-shaped file in every repository on the fleet. ## The consumer is the whole job `agentic-os-kai/scripts/pull-capabilities.py` reads a `capabilities:` list of `provider/skill-dir` strings out of that file and symlinks those skills into a leaf repo for qwen-opencode. Deleting the files without rehoming that list breaks it silently, which is the shape this estate has spent the week fixing. So the order is fixed: **rehome the capabilities list first, prove the consumer reads the new location, then delete the 15 files.** Not the other way round, and not both in one commit. Where it lands is a question this issue does not answer. The natural candidates are `pyproject.toml` under `[tool.agentic-os.*]`, where every other per-repo opt-out already lives, or the consumer owning its own list in `agentic-os-kai` rather than reading it out of each repo. The second is more consistent with config placement: the consumer is one script in one repo, so a list it maintains for itself is config at the lowest layer that fully determines it. ## What survives `#1299` freezes Ward as a contract and explicitly keeps the `.ward/ward.yaml` **schema** and the `ward:` AGENTS.md lane vocabulary. This decision deletes the files, not the schema and not the lane keys. The lane declaration lives in AGENTS.md frontmatter and is read constantly, including by every agent resolving its own workflow, so nothing here touches it. ## Done-condition A sweep for `.ward/ward.yaml` across the fleet returning nothing, and `pull-capabilities.py` working against its new source with a run that proves it rather than an assumption that it still resolves.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agentic-os#1329
No description provided.