Dev container: init writes it, skills stop rotting, publishing is manual - #175
Merged
Merged
Conversation
The container shipped last week, but opting a model repo into it was a manual
copy from this repo — which means knowing it exists, finding the file, and
getting the path right. `init` is where a model repo already goes to be made
ready; this makes the codespace part of that.
malloyyo init → .mcp.json
index.malloy (scaffold)
.claude/skills/, .claude/settings.json
.devcontainer/devcontainer.json ← new
Never over an existing file, like everything else `init` writes. That is not
just politeness: `malloyyo init` is the container's own postCreateCommand, so
from the second rebuild onward it always runs against a repo that already has
one, and a repo that pinned a digest or added a feature keeps it.
The template moves from devcontainer/devcontainer.json to
packages/cli/src/templates/devcontainer/, beside the skill templates, and rides
into dist/ through the same copy step — so there is one copy of it, owned by
the thing that writes it, rather than a root file that could drift from what
the CLI hands out. devcontainer/ keeps the Dockerfile, which is what the image
workflow builds.
Verified: typecheck, 186 CLI tests (3 new — the file parses as JSONC and names
the published image, an existing one is never overwritten, a second init is a
no-op), lint, and the built bundle run for real in a scratch model repo, which
is what exercises the dist/ template path a published `npm i -g` uses.
Also corrects the repository this repo's own comments name as an example:
babynames lives at malloydata/malloyyo-babynames, not lloydtabb/.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E5k5Hwc5GsqxepPmqXtXMx
Signed-off-by: lloyd tabb <1093458+lloydtabb@users.noreply.github.com>
`malloyyo init` copied 520 lines of procedure into every model repo and then
never touched them again — installSkills skips any directory that exists, so a
skill was frozen the day it was created. No version stamp, no update command,
nothing to tell a reader which vintage they had. A fix shipped in the CLI
reached nobody who had already run init.
That made them the one guidance channel that could rot. The engine's other 29
topics ship in content/help/** and update with the installed CLI; the skills
even told Claude to prefer them ("lean on the author MCP, call yo_help, don't
guess") while being the exception themselves.
So the content moves to where it updates, and what stays in the repo is only
the part a file has to hold — the trigger:
content/help/site/data-site.md ← malloyyo-data-site/SKILL.md
content/help/site/auto-update.md ← malloyyo-auto-update/SKILL.md
content/help/site/data-to-parquet.md ← its reference/
content/help/site/github-pages.md ← its reference/
Each SKILL.md is now ~16 lines: unchanged front matter, and a pointer to
yo_help("site/…"). A skill fires on intent, which is what a copied file is
actually for; yo_help serves the body, which is what needs to stay current.
A stale stub still works — it routes to whatever is installed. A stale
233-line procedure misleads. Cross-references between the four became topic
names, since they no longer sit in one directory.
No code changed: content/help/** is auto-indexed, so the four are topics
because of where they are. 33 topics now, up from 29.
Verified end to end — engine 126 tests, CLI 186, then the real round trip in a
scratch repo: init writes the stubs, and yo_help("site/data-site") over a live
`malloyyo mcp --develop` stdio session returns the 228-line procedure with the
rewritten links.
Already-initialized repos keep their fat copies (init still never clobbers);
`rm -rf .claude/skills/malloyyo-*` and re-run init to pick up the stubs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: lloyd tabb <1093458+lloydtabb@users.noreply.github.com>
The image rebuilt weekly and on every merge that touched devcontainer/. Both were wrong for what it is: 5.5GB that every consuming codespace pulls, reissued on a calendar — and reissued for changes that cannot affect it, since the CLI inside is `@malloydata/malloyyo` from npm and reaches people through a normal release. Publishing is now `workflow_dispatch` and nothing else. PRs that touch devcontainer/ still build and run every smoke test, so a broken Dockerfile is still caught where it is written. The cost of manual publishing is a trap, so it is named rather than left implicit: you change the Dockerfile, CI goes green, the PR merges, and the image everyone pulls is still the old one. A PR run now writes "Built and verified — but NOT published" into its own step summary, because the green check is exactly what makes it feel finished. Docs stop promising currency they no longer deliver. The image is a FLOOR: its versions are whatever was current at the last dispatch, and a CLI release does not flow into an image that already exists. The fix for the common case doesn't need a new image at all — `npm i -g @malloydata/malloyyo@latest` inside the container, which is why the npm prefix is owned by `vscode`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: lloyd tabb <1093458+lloydtabb@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three follow-ups to the dev container that shipped in #174, each one closing a gap that showed up once it was real.
1.
malloyyo initwrites.devcontainer/devcontainer.json(f0d6319)The container existed, but opting a model repo into it meant knowing it existed, finding the template, and getting the path right.
initis already where a model repo goes to be made ready:Never over an existing file, like everything else
initwrites — which matters more than politeness here, becausemalloyyo initis the container's ownpostCreateCommand, so from the second rebuild on it always runs against a repo that already has one.The template moved from
devcontainer/devcontainer.jsontopackages/cli/src/templates/devcontainer/, beside the skill templates, riding intodist/through the same copy step — one copy, owned by the thing that writes it.devcontainer/keeps the Dockerfile, which is what the image workflow builds.2. Skills become stubs; their procedures move to
yo_help(c00698b)initcopied 520 lines of procedure into every model repo and then never touched them again —installSkillsskips any directory that exists, so a skill was frozen the day it was created. No version stamp, no update command, nothing to tell a reader which vintage they had. A fix shipped in the CLI reached nobody who had already runinit.That made them the one guidance channel that could rot. The engine's other 29 topics live in
content/help/**and update with the installed CLI — and the skills themselves kept saying "lean on the author MCP, callyo_help, don't guess" while being the exception.So the content moved to where it updates:
Each
SKILL.mdis now ~16 lines: unchanged front matter, plus a pointer toyo_help("site/…"). A skill fires on intent — which is what a copied file is actually for;yo_helpserves the body — which is what needs to stay current. A stale stub still works, because it routes to whatever is installed; a stale 233-line procedure misleads.No code changed:
content/help/**is auto-indexed, so the four are topics because of where they are. 33 topics, up from 29.3. Publishing the image is manual (
cfdad54)The image rebuilt weekly and on every merge touching
devcontainer/. Both are wrong for 5.5GB that every consuming codespace pulls — and most of what lands here can't change it anyway, since the CLI inside is@malloydata/malloyyofrom npm and reaches people through a normal release.Publishing is now
workflow_dispatchand nothing else. PRs still build and smoke-test.Manual publishing has a trap — change the Dockerfile, CI goes green, PR merges,
:latestis still old — so a PR run now writes "Built and verified — but NOT published" into its own step summary, since the green check is exactly what makes it feel finished.The docs stop promising currency they no longer deliver: the image is a floor, its versions frozen at the last dispatch, and a CLI release does not flow into an image that already exists. The common case needs no new image —
npm i -g @malloydata/malloyyo@latestinside the container, which is why the npm prefix isvscode-owned.Verification
initis a no-opinitwrites the stubs, andyo_help("site/data-site")over a livemalloyyo mcp --developstdio session returns the 228-line procedure with its cross-references rewritten to topic namesdist/, which is the path a publishednpm i -gusesAfter merge
Already-initialized repos keep their fat skill copies (
initstill never clobbers) —rm -rf .claude/skills/malloyyo-*and re-runinitto pick up the stubs. And nothing republishes the image; dispatch the workflow when you want the floor to move.