Rename ward-mcp to mcp-beaver #48

Closed
opened 2026-08-12 08:58:09 +00:00 by coilyco-ops · 3 comments
Member

Decision

Rename this repo from ward-mcp to mcp-beaver.

Why

ward-mcp reads as "the MCP server for Ward." It isn't. Ward's fixed broker and the guarded operator surface are independent, neither reads policy from the other, and no drift check forces them to match. The actual lineage is cli-guard and specgen: this repo eats the same KDL guardfiles and emits a Streamable HTTP service and image instead of a static binary.

The name was wrong because the repo was miscategorized at creation. The flight deck's implicit rule is that thin wrappers around someone else's API get descriptive names (bluesky-mcp, reddit-mcp, node-stats-mcp) and original products get evocative ones (Ward, Atlas, Lore). This is an original product that got a wrapper's name.

mcp-beaver over the alternates:

  • specgen-mcp and mcp-guard were both correct and both stylistic outliers next to Ward and Atlas
  • kdl-mcp promises a KDL manipulation server, which is a different real product
  • mcp-lock collides with lockfile convention, including specverb.lock and aosguard-lock in our own tree
  • Castor lost on search competition. Castor oil alone buries it

The mcp- prefix is load-bearing rather than indecisive, since it is the half carrying the search term.

Copy to land

Repo description, and the first line of the README, identical because it goes on the banner:

A guarded MCP server generator

Five words, house banner form: indefinite article, sentence case, noun phrase, no verb, no period, lands on a category noun. Matches An agent role and personality framework (agent-compose) and A discord community agent harness (sirens-echo).

README head:

# mcp-beaver

A guarded MCP server generator

**A dam is not a wall. It decides what gets through.**

mcp-beaver turns a cli-guard policy file into a guarded MCP server and a
container image. You declare the operations an agent may reach, down to the
leaf. Everything you declared works. Nothing else is in the artifact.

Description line does the indexing, tagline does the arguing, paragraph does the explaining.

Blocked: the last sentence must change before this ships. See "Verify before publishing" below. Everything above it stands.

Verify before publishing — done, and it failed

The sentence "Nothing else is in the artifact" was drafted from the cli-guard and specgen docs rather than this repo's source. Checked against source. It does not hold, and the reason is a design feature rather than a defect.

The artifact is deliberately generic. From the Dockerfile's own header: "the ONE generic runtime image. It carries no guardfile: the spec is mounted or COPYed in by the consumer." That is mount-not-bake (#6), and deploy depends on it — every service in deploy/services/* pins this one image and supplies a different spec. The image does not contain the declared operations and exclude the rest. It contains a runtime that will render any spec handed to it.

Upstream proxy mode resolves at request time. internal/mcpserver/upstream.go connects to a live upstream MCP, snapshots its tool list, registers only allowlisted tools (upstream.go:107-109), then re-checks membership on every call (upstream.go:155-156). Sound defense-in-depth, but the undeclared operations exist, behind an endpoint the container holds credentials for. Unreachable, not absent.

Inline mode is the strong case and still wants different wording. Tools come from the KDL spec and register at startup (server.go:123); an undeclared operation has no handler at all. Real and defensible — but a claim about the running server, not the artifact.

Two words do the damage: artifact and in. Constraint for the rewrite: claim the server, not the image, and claim unreachable, not absent. Direction, with wording left to Content:

Everything you declared works. Nothing else is reachable.

Blast radius — measured, and far smaller than first written

grep -rIE "ward[-_]mcp" across the local checkouts finds 342 occurrences in 113 files across 6 repos (deploy 77 files, infrastructure 18, agentic-os-kai 13, singles elsewhere). None of it is required for the rename.

scripts/publish-image.sh hardcodes the image name rather than deriving it from the repo:

registry="forgejo.coilysiren.me"
image_name="coilyco-flight-deck/ward-mcp"

It never reads ${{ github.repository }}. After the rename, CI keeps publishing to the existing package path and every consumer pin keeps resolving. Forgejo names packages by publisher, not by repo, so the package does not move when the repo does.

Confirmed untouched by a Forgejo repo rename:

  • ward-mcp-ssm IAM user and its inline SSM policy — an AWS identity, unrelated to the Forgejo path
  • nameOverride: ward-mcp on the four live releases, and the ward-mcp container name in ingress-public-authed — live cluster resources with no link to the repo name
  • the 11+ image.repository pins across deploy/services/* — see above
  • go.mod's forgejo.coilysiren.me/coilyco-flight-deck/ward-mcp — satisfies in-repo imports only, and CI builds inside the checkout, so the path is never resolved over the network
  • ansible/roles/tailscale-proxy/files/compose.yaml, infrastructure docs, skills, the profile README — all descriptive text

Verify rather than edit: the scoped publisher runner. infrastructure/deploy/forgejo-runners-scoped/publisher-ward-mcp-repository/kustomization.yaml carries ward-mcp in a nameSuffix, a coilyco.io/runner-scope label, resource names, and the SSM registration-token path /forgejo/runner-registration/repo/coilyco-flight-deck/ward-mcp. Those are names, not live bindings — the runner is registered and Forgejo binds it to the repo entity, which follows a rename. It should survive. Called out because #10 is exactly this failure and it is silent: a push matches no runner and the repo queues zero tasks.

Breaks only if separately touched:

  • the local clone directory and the repo-ward-mcp skill pointer at ~/projects/coilyco-flight-deck/ward-mcp/; the git remote follows the redirect
  • the GitHub mirror, which keeps pushing to the old GitHub name until retargeted

Correction to the original list: Homebrew tap and Scoop bucket appear to be template inheritance rather than real coupling. This repo has one workflow, .forgejo/workflows/ci.yml, and no release or tag lane — it ships an image, not a binary. Confirm before spending time there.

Unblocked

Namespace availability confirmed clear on all four:

Namespace Result
npm mcp-beaver 404, free
PyPI mcp-beaver 404, free
crates.io mcp-beaver 404, free
GitHub org/user mcp-beaver 404, free

GitHub repo search for mcp-beaver in:name returns zero exact matches. Near-misses are inverted or qualified and none exceeds one star: alanko0511/beaver-mcp, eduard256/beaver-notes-mcp, Danissimode/BeaverBoardKanban-mcp.

Post-rename verification

The whole hypothesis rides on the second one.

  • Old path coilyco-flight-deck/ward-mcp redirects — confirmed live: an API call to the old path returned a redirect to /repos/coilyco-flight-deck/mcp-beaver/
  • Push a trivial commit and confirm the publish lane picks it up and produces an image at the unchanged package path — this is the #10 check
  • Package forgejo.coilysiren.me/coilyco-flight-deck/ward-mcp still lists and pulls
  • No live MCP service disrupted (no rollout should have been triggered at all)

Acceptance criteria

  • mcp-beaver confirmed free on GitHub, npm, PyPI, crates
  • Repo renamed, redirect verified from the old path
  • Repo description set to the line above
  • README first line matches the description exactly
  • "Nothing else is in the artifact" verified against source — it fails, see above
  • Sentence rewritten by Content under the stated constraint, before any public surface ships
  • Blast radius resolved: nothing outside this repo requires migration for the rename; the 342 occurrences are explicitly deferred as cosmetic debt
  • Publisher lane verified green after the rename
  • Banner landed (see aosx issue)

Standing state after the rename

Repo mcp-beaver publishes a package named ward-mcp against a Go module named ward-mcp. That mismatch is stable indefinitely — deliberate cosmetic debt, not a broken state awaiting a follow-up. The sweep can happen later, in pieces, or never.

Ownership

Copy and naming rationale are Content, including the rewrite the verification now requires. The rename itself is Engineer. The deferred sweep, if it is ever taken up, is Engineer and DevOps.

## Decision Rename this repo from `ward-mcp` to `mcp-beaver`. ## Why `ward-mcp` reads as "the MCP server for Ward." It isn't. Ward's fixed broker and the guarded operator surface are independent, neither reads policy from the other, and no drift check forces them to match. The actual lineage is cli-guard and specgen: this repo eats the same KDL guardfiles and emits a Streamable HTTP service and image instead of a static binary. The name was wrong because the repo was miscategorized at creation. The flight deck's implicit rule is that thin wrappers around someone else's API get descriptive names (`bluesky-mcp`, `reddit-mcp`, `node-stats-mcp`) and original products get evocative ones (`Ward`, `Atlas`, `Lore`). This is an original product that got a wrapper's name. `mcp-beaver` over the alternates: - `specgen-mcp` and `mcp-guard` were both correct and both stylistic outliers next to Ward and Atlas - `kdl-mcp` promises a KDL manipulation server, which is a different real product - `mcp-lock` collides with lockfile convention, including `specverb.lock` and `aosguard-lock` in our own tree - `Castor` lost on search competition. Castor oil alone buries it The `mcp-` prefix is load-bearing rather than indecisive, since it is the half carrying the search term. ## Copy to land Repo description, and the first line of the README, identical because it goes on the banner: ``` A guarded MCP server generator ``` Five words, house banner form: indefinite article, sentence case, noun phrase, no verb, no period, lands on a category noun. Matches `An agent role and personality framework` (agent-compose) and `A discord community agent harness` (sirens-echo). README head: ```markdown # mcp-beaver A guarded MCP server generator **A dam is not a wall. It decides what gets through.** mcp-beaver turns a cli-guard policy file into a guarded MCP server and a container image. You declare the operations an agent may reach, down to the leaf. Everything you declared works. Nothing else is in the artifact. ``` Description line does the indexing, tagline does the arguing, paragraph does the explaining. > **Blocked: the last sentence must change before this ships.** See "Verify before publishing" below. Everything above it stands. ## Verify before publishing — done, and it failed The sentence **"Nothing else is in the artifact"** was drafted from the cli-guard and specgen docs rather than this repo's source. Checked against source. It does not hold, and the reason is a design feature rather than a defect. **The artifact is deliberately generic.** From the Dockerfile's own header: *"the ONE generic runtime image. It carries no guardfile: the spec is mounted or COPYed in by the consumer."* That is mount-not-bake (#6), and deploy depends on it — every service in `deploy/services/*` pins this one image and supplies a different spec. The image does not contain the declared operations and exclude the rest. It contains a runtime that will render any spec handed to it. **Upstream proxy mode resolves at request time.** `internal/mcpserver/upstream.go` connects to a live upstream MCP, snapshots its tool list, registers only allowlisted tools (`upstream.go:107-109`), then re-checks membership on every call (`upstream.go:155-156`). Sound defense-in-depth, but the undeclared operations exist, behind an endpoint the container holds credentials for. Unreachable, not absent. **Inline mode is the strong case and still wants different wording.** Tools come from the KDL spec and register at startup (`server.go:123`); an undeclared operation has no handler at all. Real and defensible — but a claim about the running server, not the artifact. Two words do the damage: *artifact* and *in*. Constraint for the rewrite: **claim the server, not the image, and claim unreachable, not absent.** Direction, with wording left to Content: ``` Everything you declared works. Nothing else is reachable. ``` ## Blast radius — measured, and far smaller than first written `grep -rIE "ward[-_]mcp"` across the local checkouts finds 342 occurrences in 113 files across 6 repos (deploy 77 files, infrastructure 18, agentic-os-kai 13, singles elsewhere). **None of it is required for the rename.** `scripts/publish-image.sh` hardcodes the image name rather than deriving it from the repo: ```sh registry="forgejo.coilysiren.me" image_name="coilyco-flight-deck/ward-mcp" ``` It never reads `${{ github.repository }}`. After the rename, CI keeps publishing to the existing package path and every consumer pin keeps resolving. Forgejo names packages by publisher, not by repo, so the package does not move when the repo does. Confirmed untouched by a Forgejo repo rename: - `ward-mcp-ssm` IAM user and its inline SSM policy — an AWS identity, unrelated to the Forgejo path - `nameOverride: ward-mcp` on the four live releases, and the `ward-mcp` container name in `ingress-public-authed` — live cluster resources with no link to the repo name - the 11+ `image.repository` pins across `deploy/services/*` — see above - `go.mod`'s `forgejo.coilysiren.me/coilyco-flight-deck/ward-mcp` — satisfies in-repo imports only, and CI builds inside the checkout, so the path is never resolved over the network - `ansible/roles/tailscale-proxy/files/compose.yaml`, infrastructure docs, skills, the profile README — all descriptive text **Verify rather than edit:** the scoped publisher runner. `infrastructure/deploy/forgejo-runners-scoped/publisher-ward-mcp-repository/kustomization.yaml` carries `ward-mcp` in a `nameSuffix`, a `coilyco.io/runner-scope` label, resource names, and the SSM registration-token path `/forgejo/runner-registration/repo/coilyco-flight-deck/ward-mcp`. Those are names, not live bindings — the runner is registered and Forgejo binds it to the repo entity, which follows a rename. It should survive. Called out because #10 is exactly this failure and it is silent: a push matches no runner and the repo queues zero tasks. Breaks only if separately touched: - the local clone directory and the `repo-ward-mcp` skill pointer at `~/projects/coilyco-flight-deck/ward-mcp/`; the git remote follows the redirect - the GitHub mirror, which keeps pushing to the old GitHub name until retargeted **Correction to the original list:** Homebrew tap and Scoop bucket appear to be template inheritance rather than real coupling. This repo has one workflow, `.forgejo/workflows/ci.yml`, and no release or tag lane — it ships an image, not a binary. Confirm before spending time there. ## Unblocked Namespace availability confirmed clear on all four: | Namespace | Result | |---|---| | npm `mcp-beaver` | 404, free | | PyPI `mcp-beaver` | 404, free | | crates.io `mcp-beaver` | 404, free | | GitHub org/user `mcp-beaver` | 404, free | GitHub repo search for `mcp-beaver in:name` returns zero exact matches. Near-misses are inverted or qualified and none exceeds one star: `alanko0511/beaver-mcp`, `eduard256/beaver-notes-mcp`, `Danissimode/BeaverBoardKanban-mcp`. ## Post-rename verification The whole hypothesis rides on the second one. - [x] Old path `coilyco-flight-deck/ward-mcp` redirects — confirmed live: an API call to the old path returned a redirect to `/repos/coilyco-flight-deck/mcp-beaver/` - [ ] Push a trivial commit and confirm the publish lane picks it up and produces an image at the unchanged package path — this is the #10 check - [ ] Package `forgejo.coilysiren.me/coilyco-flight-deck/ward-mcp` still lists and pulls - [ ] No live MCP service disrupted (no rollout should have been triggered at all) ## Acceptance criteria - [x] `mcp-beaver` confirmed free on GitHub, npm, PyPI, crates - [x] Repo renamed, redirect verified from the old path - [ ] Repo description set to the line above - [ ] README first line matches the description exactly - [x] "Nothing else is in the artifact" verified against source — it fails, see above - [ ] Sentence rewritten by Content under the stated constraint, before any public surface ships - [x] Blast radius resolved: nothing outside this repo requires migration for the rename; the 342 occurrences are **explicitly deferred** as cosmetic debt - [ ] Publisher lane verified green after the rename - [ ] Banner landed (see aosx issue) ## Standing state after the rename Repo `mcp-beaver` publishes a package named `ward-mcp` against a Go module named `ward-mcp`. That mismatch is stable indefinitely — deliberate cosmetic debt, not a broken state awaiting a follow-up. The sweep can happen later, in pieces, or never. ## Ownership Copy and naming rationale are Content, including the rewrite the verification now requires. The rename itself is Engineer. The deferred sweep, if it is ever taken up, is Engineer and DevOps.
Author
Member

Engineer pass on the two blockers, plus a bare-rename finding

1. Namespace availability — clear on all four

Namespace Result
npm mcp-beaver 404, free
PyPI mcp-beaver 404, free
crates.io mcp-beaver 404, free
GitHub org/user mcp-beaver 404, free

GitHub repo search for mcp-beaver in:name returns zero exact matches. Three near-misses exist, all inverted or qualified and none above one star: alanko0511/beaver-mcp, eduard256/beaver-notes-mcp, Danissimode/BeaverBoardKanban-mcp. Search competition holds up.

Unblocks the first acceptance box.

2. "Nothing else is in the artifact" — does not survive contact with the source

The sentence is wrong on the plainest reading, and the reason is a feature, not a bug.

The artifact is deliberately generic. From the Dockerfile's own header: "the ONE generic runtime image. It carries no guardfile: the spec is mounted or COPYed in by the consumer." That is mount-not-bake (#6), and deploy depends on it — every service in deploy/services/* pins the same image and supplies a different spec. So the image does not contain the declared operations and exclude the rest. It contains a runtime that will render any spec you hand it.

In upstream proxy mode it is request-time filtering, which is the case this issue flagged. internal/mcpserver/upstream.go connects to a live upstream MCP, snapshots its tool list, and registers only allowlisted tools (upstream.go:107-109), then re-checks membership on every call (upstream.go:155-156). That double check is good defense-in-depth, but the undeclared operations plainly exist, behind an endpoint the container holds credentials for. They are unreachable, not absent.

Inline mode is the strong case, and even it wants different wording. Tools come from the KDL spec and are registered at startup (server.go:123); an undeclared operation has no handler at all. That is a real and defensible claim — but about the running server, not the artifact.

Two words are doing the damage: artifact and in. The true version is about the server and about reachability. Something in the direction of:

Everything you declared works. Nothing else is reachable.

Wording is Content's call. The constraint from source is: claim the server, not the image, and claim unreachable, not absent.

Second acceptance box is answered — the sentence needs a rewrite before it goes public.

3. A bare rename is very close to free, and cheaper than this issue assumes

Checked on the hypothesis that we rename the repo and change nothing else.

The image path does not derive from the repo name. scripts/publish-image.sh hardcodes it:

registry="forgejo.coilysiren.me"
image_name="coilyco-flight-deck/ward-mcp"

It never reads ${{ github.repository }}. So after a rename CI keeps publishing to the existing package path, and every consumer pin keeps resolving. This is stronger than "the images can idle" — new publishes keep landing too. The Forgejo package is named by the publisher, not by the repo, so it does not move when the repo does.

Untouched by a repo rename, confirmed rather than assumed:

  • ward-mcp-ssm IAM user and its policy — an AWS identity, unrelated to the Forgejo path
  • nameOverride: ward-mcp and the ward-mcp container name in ingress-public-authed — live cluster resources, no link to repo name
  • the 11+ image.repository pins in deploy — see above
  • go.mod's forgejo.coilysiren.me/coilyco-flight-deck/ward-mcp — only satisfies in-repo imports, and CI builds inside the checkout, so the path is never resolved over the network

The one thing to verify rather than edit is the scoped publisher runner. infrastructure/deploy/forgejo-runners-scoped/publisher-ward-mcp-repository/kustomization.yaml carries ward-mcp in a nameSuffix, a coilyco.io/runner-scope label, resource names, and the SSM registration-token path /forgejo/runner-registration/repo/coilyco-flight-deck/ward-mcp. All of those are names, not live bindings — the runner is already registered and Forgejo binds it to the repo entity, which follows a rename. It should survive. It gets called out anyway because #10 is exactly the failure where a push matched no runner and the repo queued zero tasks, and that failure is silent.

Cheap proof: rename, push a trivial commit, watch the publish lane produce an image. That single test covers the whole hypothesis.

Breaks only if separately touched:

  • the local clone directory and the repo-ward-mcp skill pointer at ~/projects/coilyco-flight-deck/ward-mcp/ — the git remote itself follows the redirect
  • the GitHub mirror, which keeps pushing to the old GitHub name until retargeted

Correction to the blast radius list above: Homebrew tap and Scoop bucket look like template inheritance rather than real coupling. This repo has one workflow, .forgejo/workflows/ci.yml, and no release or tag lane — it ships an image, not a binary. Worth confirming before anyone spends time there.

What this changes

A bare rename is not step one of the migration, it is a complete and safe step on its own. It leaves repo mcp-beaver publishing a package named ward-mcp against a Go module named ward-mcp, and that mismatch is stable indefinitely — it is cosmetic debt, taken deliberately, not a broken state waiting on a follow-up. The 342 occurrences across 113 files can be swept whenever, or never, without holding the name hostage.

## Engineer pass on the two blockers, plus a bare-rename finding ### 1. Namespace availability — clear on all four | Namespace | Result | |---|---| | npm `mcp-beaver` | 404, free | | PyPI `mcp-beaver` | 404, free | | crates.io `mcp-beaver` | 404, free | | GitHub org/user `mcp-beaver` | 404, free | GitHub repo search for `mcp-beaver in:name` returns zero exact matches. Three near-misses exist, all inverted or qualified and none above one star: `alanko0511/beaver-mcp`, `eduard256/beaver-notes-mcp`, `Danissimode/BeaverBoardKanban-mcp`. Search competition holds up. Unblocks the first acceptance box. ### 2. "Nothing else is in the artifact" — does not survive contact with the source The sentence is wrong on the plainest reading, and the reason is a feature, not a bug. **The artifact is deliberately generic.** From the Dockerfile's own header: *"the ONE generic runtime image. It carries no guardfile: the spec is mounted or COPYed in by the consumer."* That is mount-not-bake (#6), and deploy depends on it — every service in `deploy/services/*` pins the same image and supplies a different spec. So the image does not contain the declared operations and exclude the rest. It contains a runtime that will render *any* spec you hand it. **In upstream proxy mode it is request-time filtering, which is the case this issue flagged.** `internal/mcpserver/upstream.go` connects to a live upstream MCP, snapshots its tool list, and registers only allowlisted tools (`upstream.go:107-109`), then re-checks membership on every call (`upstream.go:155-156`). That double check is good defense-in-depth, but the undeclared operations plainly exist, behind an endpoint the container holds credentials for. They are unreachable, not absent. **Inline mode is the strong case, and even it wants different wording.** Tools come from the KDL spec and are registered at startup (`server.go:123`); an undeclared operation has no handler at all. That is a real and defensible claim — but about the running server, not the artifact. Two words are doing the damage: *artifact* and *in*. The true version is about the server and about reachability. Something in the direction of: ``` Everything you declared works. Nothing else is reachable. ``` Wording is Content's call. The constraint from source is: claim the server, not the image, and claim unreachable, not absent. Second acceptance box is answered — the sentence needs a rewrite before it goes public. ### 3. A bare rename is very close to free, and cheaper than this issue assumes Checked on the hypothesis that we rename the repo and change nothing else. **The image path does not derive from the repo name.** `scripts/publish-image.sh` hardcodes it: ```sh registry="forgejo.coilysiren.me" image_name="coilyco-flight-deck/ward-mcp" ``` It never reads `${{ github.repository }}`. So after a rename CI keeps publishing to the existing package path, and every consumer pin keeps resolving. This is stronger than "the images can idle" — new publishes keep landing too. The Forgejo package is named by the publisher, not by the repo, so it does not move when the repo does. Untouched by a repo rename, confirmed rather than assumed: - `ward-mcp-ssm` IAM user and its policy — an AWS identity, unrelated to the Forgejo path - `nameOverride: ward-mcp` and the `ward-mcp` container name in `ingress-public-authed` — live cluster resources, no link to repo name - the 11+ `image.repository` pins in deploy — see above - `go.mod`'s `forgejo.coilysiren.me/coilyco-flight-deck/ward-mcp` — only satisfies in-repo imports, and CI builds inside the checkout, so the path is never resolved over the network **The one thing to verify rather than edit** is the scoped publisher runner. `infrastructure/deploy/forgejo-runners-scoped/publisher-ward-mcp-repository/kustomization.yaml` carries `ward-mcp` in a `nameSuffix`, a `coilyco.io/runner-scope` label, resource names, and the SSM registration-token path `/forgejo/runner-registration/repo/coilyco-flight-deck/ward-mcp`. All of those are names, not live bindings — the runner is already registered and Forgejo binds it to the repo entity, which follows a rename. It should survive. It gets called out anyway because #10 is exactly the failure where a push matched no runner and the repo queued zero tasks, and that failure is silent. Cheap proof: rename, push a trivial commit, watch the publish lane produce an image. That single test covers the whole hypothesis. Breaks only if separately touched: - the local clone directory and the `repo-ward-mcp` skill pointer at `~/projects/coilyco-flight-deck/ward-mcp/` — the git remote itself follows the redirect - the GitHub mirror, which keeps pushing to the old GitHub name until retargeted **Correction to the blast radius list above:** Homebrew tap and Scoop bucket look like template inheritance rather than real coupling. This repo has one workflow, `.forgejo/workflows/ci.yml`, and no release or tag lane — it ships an image, not a binary. Worth confirming before anyone spends time there. ### What this changes A bare rename is not step one of the migration, it is a complete and safe step on its own. It leaves repo `mcp-beaver` publishing a package named `ward-mcp` against a Go module named `ward-mcp`, and that mismatch is stable indefinitely — it is cosmetic debt, taken deliberately, not a broken state waiting on a follow-up. The 342 occurrences across 113 files can be swept whenever, or never, without holding the name hostage.
Author
Member

Post-rename verification: all four pass. The hypothesis holds.

Verified by outcome rather than by a green checkmark — the image is tagged with the full source SHA, so its existence proves runner match, build, and publish in one artifact.

1. Redirect. Confirmed at both layers. A PATCH to the old API path returned a redirect to /repos/coilyco-flight-deck/mcp-beaver/ (correctly refused rather than silently followed, since it was a mutating verb). At the git layer, a clone still carrying the old remote fetches fine:

$ git ls-remote --heads origin
warning: redirecting to https://forgejo.coilysiren.me/coilyco-flight-deck/mcp-beaver/
30304d20535620845f73f137de88973c31a9c4f1  refs/heads/feat/46-lint-upstream

2. Publisher lane — the #10 check. Green. Post-rename push 6e8d2f5b9675ce05f9c6177b3eb662911a001a58 ("Update README.md", 10:52:35Z). Its manifest exists:

GET /v2/coilyco-flight-deck/ward-mcp/manifests/6e8d2f5b9675ce05f9c6177b3eb662911a001a58
HTTP 200

The scoped runner matched a push to the renamed repo, built, and pushed. No silent zero-task queue. The runner registration follows the repo entity, as expected — repo id 75 was unchanged by the rename.

3. Package intact at the unchanged path. GET /v2/coilyco-flight-deck/ward-mcp/tags/list → HTTP 200, 17 tags, every historical SHA still present, with the new one appended. The package did not move when the repo did, exactly as scripts/publish-image.sh hardcoding the name predicted.

4. Zero disruption to live services. Ten pods run this image across nine namespaces. All Running, all restart_count: 0, all aged 12h55m–12h59m — comfortably older than the rename, so nothing rolled:

aws-ssm-mcp      aws-ssm-ingress-public-authed     Running  0  12h59m
discord-mcp      discord-ingress-public-authed     Running  0  12h59m
forgejo-mcp      forgejo-ward-mcp                  Running  0  12h58m
glama-mcp        glama-ingress-public-authed       Running  0  12h58m
signoz-telegram  signoz-telegram                   Running  0  12h57m
sirens-deep      sirens-deep-forgejo-mcp           Running  0  12h56m
sirens-echo      sirens-echo-discord-mcp           Running  0  12h57m
sirens-echo      sirens-echo-forgejo-mcp           Running  0  12h57m
skillsmp-mcp     skillsmp-ward-mcp                 Running  0  12h56m
trello-mcp       trello-ward-mcp                   Running  0  12h55m

All ten still pinned to 97a100274a72, a pre-rename SHA, still resolving from forgejo.coilysiren.me/coilyco-flight-deck/ward-mcp. Pulls and pins both survive the rename untouched.

Incidental confirmation of the deferred debt: the pod names show the split cleanly. forgejo-ward-mcp, skillsmp-ward-mcp, and trello-ward-mcp carry nameOverride, while the rest sit on ingress-public-authed. Those three names are the immutable-field cost documented above, and they remain a deliberate deferral.

Conclusion

A bare rename cost nothing and broke nothing. What remains is copy and art, neither of which touches running infrastructure.

## Post-rename verification: all four pass. The hypothesis holds. Verified by outcome rather than by a green checkmark — the image is tagged with the full source SHA, so its existence proves runner match, build, and publish in one artifact. **1. Redirect.** Confirmed at both layers. A PATCH to the old API path returned a redirect to `/repos/coilyco-flight-deck/mcp-beaver/` (correctly refused rather than silently followed, since it was a mutating verb). At the git layer, a clone still carrying the old remote fetches fine: ``` $ git ls-remote --heads origin warning: redirecting to https://forgejo.coilysiren.me/coilyco-flight-deck/mcp-beaver/ 30304d20535620845f73f137de88973c31a9c4f1 refs/heads/feat/46-lint-upstream ``` **2. Publisher lane — the #10 check. Green.** Post-rename push `6e8d2f5b9675ce05f9c6177b3eb662911a001a58` ("Update README.md", 10:52:35Z). Its manifest exists: ``` GET /v2/coilyco-flight-deck/ward-mcp/manifests/6e8d2f5b9675ce05f9c6177b3eb662911a001a58 HTTP 200 ``` The scoped runner matched a push to the renamed repo, built, and pushed. No silent zero-task queue. The runner registration follows the repo entity, as expected — repo id 75 was unchanged by the rename. **3. Package intact at the unchanged path.** `GET /v2/coilyco-flight-deck/ward-mcp/tags/list` → HTTP 200, 17 tags, every historical SHA still present, with the new one appended. The package did not move when the repo did, exactly as `scripts/publish-image.sh` hardcoding the name predicted. **4. Zero disruption to live services.** Ten pods run this image across nine namespaces. All `Running`, all `restart_count: 0`, all aged **12h55m–12h59m** — comfortably older than the rename, so nothing rolled: ``` aws-ssm-mcp aws-ssm-ingress-public-authed Running 0 12h59m discord-mcp discord-ingress-public-authed Running 0 12h59m forgejo-mcp forgejo-ward-mcp Running 0 12h58m glama-mcp glama-ingress-public-authed Running 0 12h58m signoz-telegram signoz-telegram Running 0 12h57m sirens-deep sirens-deep-forgejo-mcp Running 0 12h56m sirens-echo sirens-echo-discord-mcp Running 0 12h57m sirens-echo sirens-echo-forgejo-mcp Running 0 12h57m skillsmp-mcp skillsmp-ward-mcp Running 0 12h56m trello-mcp trello-ward-mcp Running 0 12h55m ``` All ten still pinned to `97a100274a72`, a pre-rename SHA, still resolving from `forgejo.coilysiren.me/coilyco-flight-deck/ward-mcp`. Pulls and pins both survive the rename untouched. Incidental confirmation of the deferred debt: the pod names show the split cleanly. `forgejo-ward-mcp`, `skillsmp-ward-mcp`, and `trello-ward-mcp` carry `nameOverride`, while the rest sit on `ingress-public-authed`. Those three names are the immutable-field cost documented above, and they remain a deliberate deferral. ### Conclusion A bare rename cost nothing and broke nothing. What remains is copy and art, neither of which touches running infrastructure.
Author
Member

Worked the open acceptance items against the live forge. One of the issue's central predictions no longer holds, and it has a cross-repo consequence.

The package path DID move. The blast-radius section reasoned:

scripts/publish-image.sh hardcodes the image name rather than deriving it from the repo [...] After the rename, CI keeps publishing to the existing package path and every consumer pin keeps resolving.

A later commit changed that deliberately - 61ee2b3, "chore(publish): move the runtime image to coilyco-flight-deck/mcp-beaver". The script now reads image_name="coilyco-flight-deck/mcp-beaver". The forge carries two packages:

  • ward-mcp - last published 2026-08-13 14:51, sha a5667056...
  • mcp-beaver - carrying every build since, currently c61a7f29...

So the "standing state after the rename" paragraph is superseded: the package no longer stays behind, and the deferred sweep is no longer purely cosmetic on this axis.

Cross-repo consequence, which is deploy's to action and is not taken here. 13 image.repository pins still name .../ward-mcp:

  • deploy/charts/ingress-public-authed/values.yaml
  • deploy/services/{signoz-telegram,discord-mcp,aws-ssm-mcp,glama-mcp,signoz-mcp,skillsmp-mcp,forgejo-mcp}/values.yaml
  • five under deploy/services/sirens-echo/deploy/

Nothing is broken today - the old package is retained, so every existing pinned sha still resolves. The next bump to a post-rename sha will not pull.

Fixed in-repo (21ab242), since these are this repo's own artifacts and were pointing at a package that receives no new tags:

  • chart/values.yaml - image.repository default now .../mcp-beaver
  • docs/FEATURES.md - the published-image reference
  • AGENTS.md - scope and boundary lines, plus an explicit note that the in-tree ward-mcp naming is deliberate debt and must not be swept as incidental cleanup. That note is there because an agent reading the tree will otherwise keep re-deciding this.

Acceptance items I can now tick:

  • Publisher lane verified green after the rename - ci.yml runs #79 through #88, all successful, including the publish job on every push to main. That is the #10 check.
  • Package still lists and pulls - both do; ward-mcp is frozen, mcp-beaver is live.
  • No live MCP service disrupted - no rollout triggered, and existing pins resolve unchanged.

Still yours, not mine:

  • Repo description and README first line. These already match each other, at "A MCP server generator with a natural flow" rather than the drafted "A guarded MCP server generator". That looks like a deliberate later Content decision (it carries the dam/flow metaphor), so I have not overwritten it. Flagging only that it reads "A MCP" where "An MCP" is the spoken form.
  • The banner tagline and the corrected claim are landed in the README: "A dam is not a wall. It decides what gets through." plus the rewrite under your stated constraint - claiming the server, not the image, and unreachable, not absent. The paragraph now also states plainly that the image is deliberately generic and that upstream-proxy mode leaves undeclared tools unreachable rather than absent. Content should confirm the wording; the factual constraint is satisfied.
  • The aosx banner issue.
Worked the open acceptance items against the live forge. One of the issue's central predictions no longer holds, and it has a cross-repo consequence. **The package path DID move.** The blast-radius section reasoned: > `scripts/publish-image.sh` hardcodes the image name rather than deriving it from the repo [...] After the rename, CI keeps publishing to the existing package path and every consumer pin keeps resolving. A later commit changed that deliberately - `61ee2b3`, *"chore(publish): move the runtime image to coilyco-flight-deck/mcp-beaver"*. The script now reads `image_name="coilyco-flight-deck/mcp-beaver"`. The forge carries two packages: * `ward-mcp` - last published 2026-08-13 14:51, sha `a5667056...` * `mcp-beaver` - carrying every build since, currently `c61a7f29...` So the "standing state after the rename" paragraph is superseded: the package no longer stays behind, and the deferred sweep is no longer purely cosmetic on this axis. **Cross-repo consequence, which is deploy's to action and is not taken here.** 13 `image.repository` pins still name `.../ward-mcp`: * `deploy/charts/ingress-public-authed/values.yaml` * `deploy/services/{signoz-telegram,discord-mcp,aws-ssm-mcp,glama-mcp,signoz-mcp,skillsmp-mcp,forgejo-mcp}/values.yaml` * five under `deploy/services/sirens-echo/deploy/` **Nothing is broken today** - the old package is retained, so every existing pinned sha still resolves. The next bump to a post-rename sha will not pull. Fixed in-repo (21ab242), since these are this repo's own artifacts and were pointing at a package that receives no new tags: * `chart/values.yaml` - `image.repository` default now `.../mcp-beaver` * `docs/FEATURES.md` - the published-image reference * `AGENTS.md` - scope and boundary lines, plus an explicit note that the *in-tree* `ward-mcp` naming is deliberate debt and must not be swept as incidental cleanup. That note is there because an agent reading the tree will otherwise keep re-deciding this. **Acceptance items I can now tick:** - [x] Publisher lane verified green after the rename - `ci.yml` runs #79 through #88, all successful, including the `publish` job on every push to `main`. That is the #10 check. - [x] Package still lists and pulls - both do; `ward-mcp` is frozen, `mcp-beaver` is live. - [x] No live MCP service disrupted - no rollout triggered, and existing pins resolve unchanged. **Still yours, not mine:** * **Repo description and README first line.** These already match each other, at *"A MCP server generator with a natural flow"* rather than the drafted *"A guarded MCP server generator"*. That looks like a deliberate later Content decision (it carries the dam/flow metaphor), so I have not overwritten it. Flagging only that it reads *"A MCP"* where *"An MCP"* is the spoken form. * **The banner tagline and the corrected claim** are landed in the README: *"A dam is not a wall. It decides what gets through."* plus the rewrite under your stated constraint - claiming the server, not the image, and unreachable, not absent. The paragraph now also states plainly that the image is deliberately generic and that upstream-proxy mode leaves undeclared tools unreachable rather than absent. Content should confirm the wording; the factual constraint is satisfied. * The aosx banner issue.
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/mcp-beaver#48
No description provided.