Skip to content

refactor(conformity): align package layout, installer, and plugin with generated-package standard - #22

Merged
diegohb merged 21 commits into
mainfrom
fix-conformity
Oct 3, 2026
Merged

diegohb merged 21 commits into
mainfrom
fix-conformity

Conversation

@diegohb

@diegohb diegohb commented Oct 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Restructure the package to the conformant layout: agents/, references/, and templates/ at the package root, implementation in src/, plugin.ts at the root, and index.ts as the re-export surface with a runCli(argv) entry under an import.meta.main guard.
  • Fix manifest handling: installs now use .manifest.json (with legacy-name fallback, rewrite, and sweep), and new plugin entries are written canonically as name@latest.
  • Harden install and removal: abort with a named error when bundled assets are missing, gate legacy copy migration behind --force, never block removal on unparseable read-only configs, and warn on unparseable candidates before match short-circuit.
  • Make the load hook resilient: wrap the hook body, degrade failures to a single warning plus a one-shot not-installed advisory, keep a -placeholder cache path fallback, and move hook logic into OpencodeArchitectPlugin.
  • Enforce content standards: quote all shipped agent frontmatter values (with a CI test), add a canonical single-line badge row to the README, declare content:code in package.json, and add a named CopyModeUnsupportedError.
  • Retire promoted-source leftovers from .opencode/ and fix a trailing comma in .opencode/opencode.json.

Why

The suite drifted from the very generated-package conventions it teaches. Conformance items A1–A5, B2–B6, C1–C2, D2–D9, and E1–E2 from the checklist were failing against this repo's own package; this brings the package, installer, plugin hook, and templates into parity and pins the behavior with tests.

Testing

  • New and expanded suites: installer, plugin-config, load-hook, cli, cache-cleaner, permission-registrar, agents, readme, content-declaration, and deployment-plan tests, with a shared captureConsole helper.
  • Enforcement tests scan every shipped markdown file for frontmatter quoting and contract-test the README badge row and error classes.
  • Regression tests pin legacy manifest migration, name@latest splicing, scope non-leakage, once-guard advisories, unparseable-config skip behavior, and --force-gated migration.
  • Manual: bun run index.ts install / status / uninstall flows against both fresh and legacy-layout caches.

Diego B. added 21 commits October 2, 2026 21:14
The package ships agents and registers a plugin hook, making it
code-backed; package.json now carries the content declaration the
deployment plan requires.
mode and permission values were bare; the checklist requires double
quoting for all frontmatter property values (native booleans exempt).
Adds an enforcement test over assets/agents so bare values fail CI.
…d assets (B4, D4)

The config hook could reject into config assembly when bundled assets
are absent (partial npm cache artifact), stalling startup. The entire
hook body is now wrapped: a failure degrades to a single warning plus
one advisory naming bunx opencode-architect clear-cache, the reinstall
command, and the package-qualified cache directory. The advisory
builder carries a static fallback and the emitter swallows
independently; separate once-guards; the hook never deletes cache.
…test

Reuses configFrom so the once-guard closure is exercised through the
same plugin instance without optional-call type errors.
The suite's own manifest broke the <package>.manifest.json convention
its checklist and generated templates follow, so drift against the
conformant layout forced a nonstandard record name. Installs, status,
and uninstall now read the legacy opencode-architect.json as a
fallback, rewrite the record at the conformant name, and sweep the
legacy file; README updated.
… D8)

New entries landed as the bare package name in spliced and created
configs and in the manifest record; the canonical form is name@latest.
Semantic matching is unchanged, so existing bare or pinned entries
remain zero-write no-ops. README snippets now show opencode-architect@
latest, and the surgical-editor template carries the same behavior.
…3, D2)

Copy-to-plugin migration deleted the recorded payload unconditionally,
including files the consumer edited after installing. Migration now
aborts with an explanatory error unless --force is given, matching the
template's consent-gated migrate semantics; --force help text says so.
A partial npm cache extraction could register the plugin and record a
manifest as installed with no agents on disk. Install now verifies the
agents, references, and templates directories up front and aborts with
an error naming the missing path, the package version, the cache
directory, and the clear-cache remediation command; no manifest is
written. The error class ships in the files whitelist.
…rcuit (C1)

Detection silently treated an unparseable config as unregistered, and
a matching earlier candidate short-circuited before later unparseable
candidates were ever reported. All candidates are now read up front,
each unparseable one warns, and matching/short-circuiting happens
after; the surgical-editor template carries the same behavior.
… (E2)

Aligns the suite's own installer with the corrected template pattern:
the hard copy-mode error is an identifiable class shipped in the
package, with the contract test asserting the type.
…D7, D8)

The row was missing the Bun runtime and Platforms badges the 4b markup
requires, and linked a dangling ./LICENSE.md-style path style. Now one
line directly below the heading: npm version, Bun runtime, MIT license
(linking the real LICENSE.md), URL-encoded Linux platforms anchor to
the real heading slug, and the fixed OpenCode plugin badge; DeepWiki
omitted because indexing could not be confirmed. Adds contract tests
for the row, link resolution, canonical casing, and D8 snippet keys.
The end state after promotion holds only the config holding the
reference plus hook-managed content; the source package.json, its
lockfile, and node_modules were still present (the tracked lockfile
kept collecting local churn). They are gone now; opencode.json keeps
the ../index.ts plugin registration for this checkout.
…eakage (D3)

Pins the checklist's comment-between-trailing-comma-and-closer input,
proves a version match without a live registration is never a no-op
(B6), and locks in that re-registering one scope never touches the
other (C2).
…lback (review)

Addresses the standards review: the hook concern moves from free
functions into OpencodeArchitectPlugin (classes-over-helpers), the
advisory prefix is no longer duplicated across try/catch branches, and
the metadata-unreadable fallback now keeps the package-qualified cache
path with a literal <version> placeholder (D4). The version reader is
injectable so the fallback is exercised through the public path.
…(D5, review)

The checklist requires the failure advisory and the not-installed
advisory as distinct advisories with separate once-guards; only the
failure advisory existed. After a healthy in-memory start the hook now
probes both scopes for an install manifest (read-only via
Installer.hasManifestAnywhere) and, when none exists, advises
bunx opencode-architect install once per session. Tests pin the
once-guard, suppression when a manifest exists, and independence from
the failure advisory.
…eview)

Batch-8's up-front read made removePluginEntry return blocked for an
unparseable global config.json, a file removal never writes; the
pre-change behavior was to skip it. Writable candidates still block;
read-only ones are warned about (C1) and skipped. Template carries the
same order; regression test pins warn + skip + byte preservation.
…reads (review)

readManifestRecord's path field becomes foundPath and status()
destructures; the bundled asset directory list is a named constant;
the readCandidates return shape gets a CandidateRead type in the
editor and its template. Judgement-call cleanups from the standards
review; spliceEntry's parameter list intentionally mirrors the
template and stays.
…eview)

The quoting rule covers agent definitions, SKILL.md, and command
files; the test only walked the agent filename list, so a future
SKILL.md with bare values would have slipped through. The scan now
covers every .md under assets/ with leading frontmatter.
…(review)

The warn-capture spy boilerplate repeated across load-hook and
plugin-config tests; it now lives once in test-helpers and both suites
restore through the returned handle.
…review)

Drops the legacy assets/ intermediary the suite itself teaches
packagers to retire: agents/, references/, and templates/ now sit at
the package root and implementation modules live in src/, matching the
generated-package convention (plugin.ts at the root, index.ts as the
re-export surface). Installer and plugin resolve bundled content from
the package root; agents' ../references links stay valid since both
sides of the relative path moved together. package.json bin/files and
the test suites follow; CONTEXT.md's References and Templates entries
now document the root-level directories. Also fixes this repo's own
.opencode/opencode.json trailing comma, which strict .json parsing
rightly refused.
…ate parity)

Mirrors the generated-package entry convention: src/cli.ts exports
runCli(argv) returning an exit code under an import.meta.main guard,
and index.ts dispatches to it so bun run index.ts install works the
way the packager's verify steps prescribe, while remaining the plugin
re-export surface.
@diegohb
diegohb merged commit 1a9a6c7 into main Oct 3, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant