feat(dowel): give engineer its build surface and name it the owner of its own puts #954

Merged
coilysiren merged 1 commit from aos/claude/dowel-site-work into main 2026-08-18 15:37:54 +00:00
Member

Everything the sirens-dowel lane needs from the prose and composition layers to work the site on camera. Follow-on to #952. No deploy values and no MCP definition: those stay with the engineer on coilyco-bridge/deploy#658.

1. engineer had no allowlist entry at all

roles.kdl carried one role, creator. A role with no entry composes the roster identity alone, which for engineer is six skills and zero catalogue sources: no coding, delivery, diagnosis, or verification doctrine.

Flipping the lane to engineer without this would have staged an agent to do work on camera with a bundle holding none of the skills for it. That is the "not my lane, sorry" failure arriving through the bundle rather than through the prose.

The entry admits coding-*, the engineering tooling-* surfaces, tooling-ops-*, tooling-qa-*, and the four aosk build helpers.

tooling-ops-* is deliberate rather than borrowed. There is no operator seat behind this lane during the session, so change risk, diagnosis, and remediation are its own doctrine here.

Every entry is a glob on purpose. DeniedComposedSkills errors on a denied skill named exactly and silently drops one reached by a pattern. Two denied entries sit under surfaces this set reaches: kai-engineering-voice ("code review and eng-channel posts, not this agent") and tooling-cross-repo-infra ("fleet mutation surface"). Globs let the deny list do its job instead of turning a policy decision into a parse failure.

What it costs, measured before landing

  • creator today - about 48 KB of skill bodies
  • engineer with this set - about 113 KB

So the flip adds roughly 64 KB to a fixed prefix measured at 116 KB. That lands on the surface deploy#932 is open about, and it is recorded rather than hidden. That issue already decided the prefix problem is a caching failure rather than a roster size, and rejected cutting the roster on those grounds, so this set is not trimmed on count alone. If it has to come down, trim it against a measurement.

2. Dowel owns deployment, said in the prompt rather than left to section order

The composed bundle carries boundary-modify-live-system, which hands changes to running systems over to DevOps. There is no DevOps seat on this lane during the demo. Left alone, that boundary is exactly the instruction that makes Dowel narrate an edit to an operator who is not coming.

site-work.md now names the winner directly, which is the pattern composedVoicePolicy already establishes for voice, described in its own comment as naming the winner rather than leaving it to section order. The boundary governs systems this lane has no tool for, the site is its own granted work surface, and where they disagree about the site the local file wins.

It also closes the size-based escape hatch, which is the likelier failure in practice: fixing a word, a typo, a heading, or an ordering is squarely the job, and "too small to be worth a put" and "too live to touch" are the same refusal wearing different clothes.

The honest limit stays the tool list rather than the org chart. Rollback, serving, and nginx have no verb here, so they are declined as absent tools and never as another role's work.

Why this works without an agent-compose change

BuildSystemPrompt emits <composed-identity> before <local-policy>, so the lane's own skill root is the later and more specific instruction. Naming the precedence explicitly is what makes that reliable rather than positional.

agent-compose has no way to compose a role with boundaries dropped. ParseRequest accepts nine keys and none of them touches boundaries, which come from role.kdl declarations plus owned-boundary affinity. Building that knob is the durable fix and it is filed separately. It is not a change to make across three repositories and an image publish inside this window.

Verification

  • go test ./internal/community/ passes.
  • pre-commit run passes on every changed file.

Still not wired, and still the other engineer's file

sirens-dowel-definition.yml needs .agents/skills/sirens-dowel in local_skill_roots, or none of the prose loads, and its identity still reads Sirens Deep of Coilyco. deploy#658 is the role flip itself.

Refs coilyco-bridge/deploy#658, coilyco-bridge/deploy#932, #952

🤖 Generated with Claude Code

Everything the `sirens-dowel` lane needs from the prose and composition layers to work the site on camera. Follow-on to #952. No deploy values and no MCP definition: those stay with the engineer on coilyco-bridge/deploy#658. ## 1. engineer had no allowlist entry at all `roles.kdl` carried one role, `creator`. A role with no entry composes the roster identity alone, which for `engineer` is six skills and **zero catalogue sources**: no coding, delivery, diagnosis, or verification doctrine. Flipping the lane to `engineer` without this would have staged an agent to do work on camera with a bundle holding none of the skills for it. That is the "not my lane, sorry" failure arriving through the bundle rather than through the prose. The entry admits `coding-*`, the engineering `tooling-*` surfaces, `tooling-ops-*`, `tooling-qa-*`, and the four aosk build helpers. **`tooling-ops-*` is deliberate rather than borrowed.** There is no operator seat behind this lane during the session, so change risk, diagnosis, and remediation are its own doctrine here. **Every entry is a glob on purpose.** `DeniedComposedSkills` errors on a denied skill named exactly and silently drops one reached by a pattern. Two denied entries sit under surfaces this set reaches: `kai-engineering-voice` ("code review and eng-channel posts, not this agent") and `tooling-cross-repo-infra` ("fleet mutation surface"). Globs let the deny list do its job instead of turning a policy decision into a parse failure. ### What it costs, measured before landing * `creator` today - about 48 KB of skill bodies * `engineer` with this set - about 113 KB So the flip adds roughly **64 KB to a fixed prefix measured at 116 KB**. That lands on the surface deploy#932 is open about, and it is recorded rather than hidden. That issue already decided the prefix problem is a caching failure rather than a roster size, and rejected cutting the roster on those grounds, so this set is not trimmed on count alone. If it has to come down, trim it against a measurement. ## 2. Dowel owns deployment, said in the prompt rather than left to section order The composed bundle carries `boundary-modify-live-system`, which hands changes to running systems over to DevOps. **There is no DevOps seat on this lane during the demo.** Left alone, that boundary is exactly the instruction that makes Dowel narrate an edit to an operator who is not coming. `site-work.md` now names the winner directly, which is the pattern `composedVoicePolicy` already establishes for voice, described in its own comment as naming the winner rather than leaving it to section order. The boundary governs systems this lane has no tool for, the site is its own granted work surface, and where they disagree about the site the local file wins. It also closes the size-based escape hatch, which is the likelier failure in practice: fixing a word, a typo, a heading, or an ordering is squarely the job, and "too small to be worth a put" and "too live to touch" are the same refusal wearing different clothes. The honest limit stays the tool list rather than the org chart. Rollback, serving, and nginx have no verb here, so they are declined as absent tools and never as another role's work. ## Why this works without an agent-compose change `BuildSystemPrompt` emits `<composed-identity>` before `<local-policy>`, so the lane's own skill root is the later and more specific instruction. Naming the precedence explicitly is what makes that reliable rather than positional. agent-compose has **no** way to compose a role with boundaries dropped. `ParseRequest` accepts nine keys and none of them touches boundaries, which come from `role.kdl` declarations plus owned-boundary affinity. Building that knob is the durable fix and it is filed separately. It is not a change to make across three repositories and an image publish inside this window. ## Verification * `go test ./internal/community/` passes. * `pre-commit run` passes on every changed file. ## Still not wired, and still the other engineer's file `sirens-dowel-definition.yml` needs `.agents/skills/sirens-dowel` in `local_skill_roots`, or none of the prose loads, and its `identity` still reads `Sirens Deep of Coilyco`. deploy#658 is the role flip itself. Refs coilyco-bridge/deploy#658, coilyco-bridge/deploy#932, #952 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(dowel): carry the site write surface as the lane's landing workflow
All checks were successful
ci / image-build (pull_request) Successful in 3s
ci / test (pull_request) Successful in 55s
ci / publish-echo-image (pull_request) Has been skipped
ci / publish-observed (pull_request) Has been skipped
3586718b35
The demo's work surface is a guarded MCP over markdown fragments: list, read,
put, no delete. The rule that matters for this lane is that those verbs are the
whole landing workflow, so a successful put is delivered work rather than a
change awaiting promotion. Without saying so, the engineer charter's deferral of
live mutation reads a site put as an operator action and hands off the exact
work the demo exists to show.

Draws the line rather than waiving it: rollback, serving, and nginx stay out of
reach and out of the agent's promises, because no verb reaches them.

Carries the operating discipline the surface actually needs: one file per
concern so a new section is a new file, read-then-put because a put rewrites the
file whole and there is no append verb, minimal flat front matter or none at all
since indentation is the one visible way to break a page, and one put per
section because the audience sees each one within about two seconds.

Names the collision with capability.md rather than leaving it to be guessed. That
file forbids describing work as queued, and the changelog protocol asks for a
queued line. The rule is about work outliving the turn, so a line for a put that
lands before the reply is sent is a record rather than a promise.

Refs coilyco-bridge/deploy#658

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Angie <coilyco-ops@coilysiren.me>
Co-authored-by: Claude <noreply@anthropic.com>
coilyco-ops changed title from feat(dowel): carry the site write surface as the lane's landing workflow to feat(dowel): give engineer its build surface and name it the owner of its own puts 2026-08-18 15:49:03 +00:00
Sign in to join this conversation.
No reviewers
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-gaming/sirens-echo!954
No description provided.