example leaves too; plugins/ is documentation now

Done with `tea` as admin: plugins/offscale made public, plugins/example created
public, both verified anonymously over https — which is the check that matters,
because fetch.ts clones with no credentials and a private plugin simply cannot be
installed from the marketplace.

  plugins/example    8 files, cloned back and diffed identical
  plugins/offscale   now public (was private, so was uninstallable)

`.gitignore` is one line now — `/plugins/*/`. The trailing slash is the whole
design: it ignores DIRECTORIES, so files at the top of plugins/ stay tracked. The
documentation about plugins belongs to the platform; the plugins do not.

All three are in the marketplace catalogue, which is what makes this reversible:
before this, untracking offscale meant a fresh install could never get it back.
Now the store is the way in for all three.

CatalogueEntry gains `icon` (a lucide name) alongside `iconUrl`. Both new entries
ship glyphs rather than artwork, and without it they drew the generic puzzle piece
in the store and their real icon after install — which reads as the icon changing
rather than the store not knowing it.

EXTRACTING-A-PLUGIN.md pointed at four directories a fresh checkout no longer has.
It now gives repository URLs, says up front that this directory holds documentation
rather than plugins, and carries a table of where each one went. Checked first that
no tracked source statically imports a plugin directory — none does, so a fresh
clone still builds.

tsgo clean, frontend builds, 787 pass / 7 fail (unchanged).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-15 18:21:51 +00:00
co-authored by Claude Opus 5
parent cca85a7524
commit dd26e4a688
14 changed files with 104 additions and 172 deletions
+7 -12
View File
@@ -94,18 +94,13 @@ src/databases/officer_db/src/plugin-schemas.gen.ts
# Generate one locally whenever a diff is useful to read. It stays local.
src/databases/officer_db/migrations/
# ── Marketplace-installed plugins ──
# ── plugins/ holds documentation, not plugins ──
#
# A plugin fetched from the marketplace is a CLONE with its own .git and its own repository. Left
# tracked, `git add -A` after an install commits it as a gitlink — a pointer to a commit this repo does
# not contain, which then breaks anyone who clones the platform and does not have access to that plugin.
# Happened on 2026-08-15, one commit after the marketplace landed.
# Every plugin is its own repository (gitea.officer.dev/plugins/*) and arrives here by `git clone` when
# somebody installs it. A cloned plugin carries its own .git, so leaving it tracked means `git add -A`
# commits a gitlink — a pointer to a commit this repo does not contain. That happened on 2026-08-15.
#
# The plugins that genuinely ship with the platform are re-included by name below. Adding one is a
# deliberate act, so keeping this list by hand is the right amount of friction — an unlisted plugin
# directory is an install, not a source file.
# The trailing slash matters: this ignores DIRECTORIES only, so files at the top of plugins/ —
# EXTRACTING-A-PLUGIN.md and anything beside it — stay tracked. The documentation about plugins belongs
# to the platform; the plugins do not.
/plugins/*/
# `example` is the only exception left, and only until it has a repository of its own. It is the
# reference implementation EXTRACTING-A-PLUGIN.md sends people to read, and it has no remote — the
# platform repo is its single copy, so untracking it would delete it from everywhere but this disk.
!/plugins/example/