Development record
Sharpens iss-2608270559313719, which reports that abcd's release flow cannot serve a managed repo that is not a plugin. That record lists the symptoms; this one names the single line that causes most of them, and shows that abcd already solved the neighbouring problem, so the fix has a precedent inside the same file.
Sharpens iss-2608270559313719, which reports that abcd's release flow cannot serve a managed repo that is not a plugin. That record lists the symptoms; this one names the single line that causes most of them, and shows that abcd already solved the neighbouring problem, so the fix has a precedent inside the same file.
ResolveInstallSurface reads .claude-plugin/plugin.json unconditionally, and readManifest returns an error when the file cannot be READ, not only when it cannot be parsed. A repo that ships something other than a plugin has no such file, so resolution fails before anything else runs. Observed as abcd changelog refusing with "reading .claude-plugin/plugin.json: no such file or directory" in a managed repository whose artefact is a platform application bundle.
The precedent is in the same file, eight lines above the failing read. The constant's own comment says: "Unlike the VERSION location (which version-location.json makes negotiable per adr-19), the manifest's own path is fixed by the harness's discovery rule — a plugin.json anywhere else is not found at all". The reasoning for the fixed PATH is sound: the harness really does discover a plugin manifest at one location only. But it answers a different question from the one that bites. Where the manifest lives and whether the artefact has one are separate facts, and adr-19 already established that a release-shaped fact can be declared per repo rather than assumed.
So the defect is not that the path is a constant. It is that a MISSING manifest is treated as a broken payload rather than as "this artefact is not a plugin": one unconditional read, sitting next to a sibling problem abcd chose to make negotiable.
What this costs a non-plugin repo, in the order a maintainer meets it. launch --dry-run, changelog and launch ship all refuse, so the derived changelog never runs; the repo falls back to a hand-written CHANGELOG; and the convention that a user-facing change is accompanied by a RECORD rather than hand-written release prose becomes unenforceable exactly where it was meant to bind. The release still ships, because the repo carries its own tag-driven workflow, but abcd's release gates are absent from it, silently, and nothing says so at release time.
Needed: let a repo declare its artefact kind, or treat an absent plugin manifest as an absent plugin rather than an unreadable payload, so that InstallSurface carries no plugin name instead of failing. A repo that ships a binary, an application bundle or a library could then use the derived changelog, the payload scan and the release gates, which is the part of launch that has nothing to do with being a plugin.
Related, filed separately: the same repo's adoption gap (no launch payload config, no version location for a non-plugin artefact, launch scaffold writing a generic Linux Go workflow over a platform-specific one).
Grounds
- pursued: we expect absence-is-absence to be the smaller and safer of the record's two options because it adds no configuration surface and leaves every present-manifest failure exactly as it was; it is shown wrong if a repository legitimately needs to declare that it has no plugin, rather than simply not having one
Frontmatter
| id | iss-2609100506255436 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | major |
.abcd/work/issues/resolved/iss-2609100506255436-launch-is-gated-by-one-unconditional.md
open on GitHub ↗ · commit history ↗
mentions2
- adr-19The plugin version lives ONLY in the released artifact; the working tree stays unversioned, and the version location is chosen by a schema-validated decision, not hard-coded
- iss-2608270559313719abcd launch --dry-run (and ship) in a NON-plugin-payload repo dies with a raw 'include config not found: .abcd/config/launch-payload.json' (LoadIncludes preflight in internal/core/launch/includes.go), giving the operator no idea WHY. launch preview/ship is a plugin-payload-repo feature (it needs launch-payload.json, and ship additionally needs .claude-plugin/plugin.json); a repo that ships no plugin bundle legitimately has neither and should be told so, not handed a missing-file error. Fix (loud-staging/legibility): when the launch config is absent AND the repo is not a plugin-payload repo, the dry-run should explain 'launch preview/ship applies to plugin-payload repos; this repo's release path is launch scaffold + the CHANGELOG roll + auto-release' rather than reporting a raw missing include config. Surfaced from a Testimony (non-plugin repo) onboarding session.