ward-kdl: scaffold the remaining spec areas into the per-tier folders (move specs + placeholders, no keyword tiering yet) #344

Closed
opened 2026-06-25 18:30:16 +00:00 by coilysiren · 2 comments
Owner

Goal

Mechanical structural prep for the tier migration (epic ward#339): give every remaining spec-dialect area a home in the per-tier folders, matching how forgejo (ward#240/#278) and signoz (ward#338) already sit, before any per-verb tiering. This is deliberately low-stakes plumbing - no can/never/override authoring, no keyword work (that is the later fan-out, gated on cli-guard#169). Just move the specs into their proper folders and stand up placeholders.

Kai: "we can start simply moving the various KDL specs into their proper folders. no keyword updates yet, just moving things around and maybe adding some placeholders."

Scope

The spec-dialect areas not yet tiered: trello, tailscale, glitchtip, glama, skillsmp (forgejo + signoz are done; exec-dialect areas - docker, aws, kubectl, git, brew, the agent launchers - have exec blocks, not specs, and are a separate later axis, out of scope here).

For each of those five areas, scaffold its presence in cmd/ward-kdl/ward-kdl-{read,write,admin}/:

  • A placeholder tier guardfile per tier (ward-kdl.<area>.<tier>.guardfile.kdl) following the established shape: the read file is the singleton-bearing root (wrap ward-kdl-read ops <area>, declaring spec/base-url/auth, plus restrict if the area needs a scope gate); write and admin inherit their sibling tier by relative path. Carry no curated verbs - a placeholder holds the structure and singletons only, with a // TODO(ward#339): tier verbs marker where the grants will go.
  • The area's spec vendored where the tier build needs it, per the ward#338 lesson: an inheriting write/admin member resolves spec relative to its own dir and go:embed cannot reach a sibling, so the vendored spec sits in each tier dir. Reuse #338's mechanism - the build copies the spec per tier keyed off the read guardfile's spec line, copies gitignored, the base file at cmd/ward-kdl/ staying the single source of truth. Do not duplicate the spec into git.

Constraints (do not break the base)

  • Leave forgejo + signoz tier dirs untouched (already authored).
  • Do not move or alter the base monolith guardfiles (cmd/ward-kdl/ward-kdl.<area>.guardfile.kdl) or the root specs they consume. The base ward-kdl binary, ward's auto-mounted exec surfaces, and ward ops forgejo (opsassets) still depend on them. This is additive scaffolding beside the base, not a migration of it.
  • Keep the build green. make build, make build-ward-kdl, the generalized tier build target (ward#338), and make test all pass. If a verbless placeholder cannot lock/build, stage it without wiring it into the tier build (leave it discoverable but excluded until its verbs land) and list which areas are staged-only. Do not add a placeholder that reds the build.
  • No cli-guard#169 dependency - this touches file layout only, never the never/override semantics.

Acceptance

  • Each of the five areas has placeholder read/write/admin guardfiles in the tier dirs, structured like forgejo/signoz but verbless, with a clear TODO marker pointing at the fan-out.
  • Specs are vendored per the #338 per-tier-dir pattern (gitignored copies, base file canonical), not committed duplicates.
  • forgejo + signoz unchanged; base monolith guardfiles, root specs, ward ops forgejo, and the auto-mounted exec surfaces all unchanged.
  • Full build + tests green; if any placeholder is staged-but-unwired, that is listed in the issue close comment with why.
  • A one-paragraph note (issue comment or a short docs stub) telling the fan-out where each area's tier guardfiles live and what "placeholder" means, so each per-area run starts from the skeleton instead of recreating it.

References

ward#339 (epic), ward#342 (deploy model), ward#338 (the per-tier-dir vendored-spec mechanism to reuse), ward#240/#278 (forgejo tier layout to match), ward#241 (signoz layout to match).

## Goal Mechanical structural prep for the tier migration (epic ward#339): give every remaining **spec-dialect** area a home in the per-tier folders, matching how forgejo (ward#240/#278) and signoz (ward#338) already sit, **before** any per-verb tiering. This is deliberately low-stakes plumbing - **no `can`/`never`/`override` authoring, no keyword work** (that is the later fan-out, gated on cli-guard#169). Just move the specs into their proper folders and stand up placeholders. Kai: "we can start simply moving the various KDL specs into their proper folders. no keyword updates yet, just moving things around and maybe adding some placeholders." ## Scope The spec-dialect areas **not yet tiered**: **trello, tailscale, glitchtip, glama, skillsmp** (forgejo + signoz are done; exec-dialect areas - docker, aws, kubectl, git, brew, the agent launchers - have `exec` blocks, not specs, and are a separate later axis, out of scope here). For each of those five areas, scaffold its presence in `cmd/ward-kdl/ward-kdl-{read,write,admin}/`: - A **placeholder tier guardfile** per tier (`ward-kdl.<area>.<tier>.guardfile.kdl`) following the established shape: the **read** file is the singleton-bearing root (`wrap ward-kdl-read ops <area>`, declaring `spec`/`base-url`/`auth`, plus `restrict` if the area needs a scope gate); **write** and **admin** `inherit` their sibling tier by relative path. Carry **no curated verbs** - a placeholder holds the structure and singletons only, with a `// TODO(ward#339): tier verbs` marker where the grants will go. - The area's **spec vendored where the tier build needs it**, per the ward#338 lesson: an inheriting write/admin member resolves `spec` relative to **its own dir** and go:embed cannot reach a sibling, so the vendored spec sits in each tier dir. Reuse #338's mechanism - the build copies the spec per tier keyed off the read guardfile's `spec` line, copies gitignored, the base file at `cmd/ward-kdl/` staying the single source of truth. Do not duplicate the spec into git. ## Constraints (do not break the base) - **Leave forgejo + signoz tier dirs untouched** (already authored). - **Do not move or alter the base monolith guardfiles** (`cmd/ward-kdl/ward-kdl.<area>.guardfile.kdl`) or the root specs they consume. The base `ward-kdl` binary, ward's auto-mounted exec surfaces, and `ward ops forgejo` (opsassets) still depend on them. This is **additive** scaffolding beside the base, not a migration of it. - **Keep the build green.** `make build`, `make build-ward-kdl`, the generalized tier build target (ward#338), and `make test` all pass. If a verbless placeholder cannot `lock`/`build`, **stage it without wiring it into the tier build** (leave it discoverable but excluded until its verbs land) and list which areas are staged-only. Do not add a placeholder that reds the build. - **No cli-guard#169 dependency** - this touches file layout only, never the never/override semantics. ## Acceptance - Each of the five areas has placeholder read/write/admin guardfiles in the tier dirs, structured like forgejo/signoz but verbless, with a clear TODO marker pointing at the fan-out. - Specs are vendored per the #338 per-tier-dir pattern (gitignored copies, base file canonical), not committed duplicates. - forgejo + signoz unchanged; base monolith guardfiles, root specs, `ward ops forgejo`, and the auto-mounted exec surfaces all unchanged. - Full build + tests green; if any placeholder is staged-but-unwired, that is listed in the issue close comment with why. - A one-paragraph note (issue comment or a short docs stub) telling the fan-out where each area's tier guardfiles live and what "placeholder" means, so each per-area run starts from the skeleton instead of recreating it. ## References ward#339 (epic), ward#342 (deploy model), ward#338 (the per-tier-dir vendored-spec mechanism to reuse), ward#240/#278 (forgejo tier layout to match), ward#241 (signoz layout to match).
Author
Owner

🔒 Reserved by ward agent --driver claude — container ward-ward-issue-344-claude-91aded58 on host 4f2062d4fed1 is carrying this issue (reserved 2026-06-25T18:30:24Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

— Claude (she/her), via ward agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent --driver claude` — container `ward-ward-issue-344-claude-91aded58` on host `4f2062d4fed1` is carrying this issue (reserved 2026-06-25T18:30:24Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Author
Owner

Felt less like authoring and more like mapping the build's blast radius — which was the interesting part. The placeholders themselves are trivial: five areas, three tiers, copy the singletons off each monolith. The real question was the one the issue flagged, and the answer surprised me. A verbless placeholder doesn't just fail its own lock — specgen's discovery is directory-wide, so it fails the whole tier's lock with "spec has no paths", taking forgejo and signoz down with it. So "stage without wiring" couldn't be a loop skip; it had to dodge the *.guardfile.kdl glob outright. The .guardfile.kdl.placeholder suffix does that, with the bonus that wiring later is a pure git mv + verb-add — the inherit paths already point at the final names, so nothing needs re-editing. No Makefile change at all.

All five ended up staged-only (none can lock verbless), which the issue anticipated. Confidence is high: I replicated the full tier loop by hand to confirm the real guardfiles stay green with placeholders present, and ward exec build-ward-kdl + ward exec test are clean with no drift.

Two honest rough edges for the fan-out, both noted in docs/ward-kdl-tiers.md: kdlfmt only globs .kdl, so it skips the .placeholder files — they won't be format-checked until renamed (I matched the existing style by hand). And the per-tier spec copies don't materialize until an area is wired, so "specs vendored" is satisfied as mechanism-ready (gitignore + the #338 copy step), not as files on disk today.

Felt less like authoring and more like mapping the build's blast radius — which was the interesting part. The placeholders themselves are trivial: five areas, three tiers, copy the singletons off each monolith. The real question was the one the issue flagged, and the answer surprised me. A verbless placeholder doesn't just fail its *own* lock — specgen's discovery is directory-wide, so it fails the *whole tier's* lock with "spec has no paths", taking forgejo and signoz down with it. So "stage without wiring" couldn't be a loop skip; it had to dodge the `*.guardfile.kdl` glob outright. The `.guardfile.kdl.placeholder` suffix does that, with the bonus that wiring later is a pure `git mv` + verb-add — the inherit paths already point at the final names, so nothing needs re-editing. No Makefile change at all. All five ended up staged-only (none can lock verbless), which the issue anticipated. Confidence is high: I replicated the full tier loop by hand to confirm the real guardfiles stay green with placeholders present, and `ward exec build-ward-kdl` + `ward exec test` are clean with no drift. Two honest rough edges for the fan-out, both noted in docs/ward-kdl-tiers.md: kdlfmt only globs `.kdl`, so it skips the `.placeholder` files — they won't be format-checked until renamed (I matched the existing style by hand). And the per-tier spec copies don't materialize until an area is wired, so "specs vendored" is satisfied as *mechanism-ready* (gitignore + the #338 copy step), not as files on disk today.
Sign in to join this conversation.
No milestone
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/ward#344
No description provided.