70-thin-catalog.sh: renders the thin-catalog end-state into --workspace (never the live tree). git-archive HEAD -> remove plugins/ + shared/ + scripts/sync-design-system.mjs(+test) -> extract CLAUDE.md conventions into CONVENTIONS.md (D6) -> thin the catalog CLAUDE.md -> rewrite README.md with external Forgejo repo links and versions re-stated from plugin-map.json (M15 coupled to the D6 rewrite). Verify: workspace has no plugins/ or shared/, CONVENTIONS.md present; rewritten README has 0 local links and corrects the stale playground-design-system v0.1 -> v0.6.0. Test 4/4. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
135 lines
5.7 KiB
Bash
135 lines
5.7 KiB
Bash
#!/usr/bin/env bash
|
|
# Step 9 — catalog-thinning script (staged for the operator window).
|
|
#
|
|
# Renders the THIN-CATALOG end-state into a --workspace. NEVER mutates the live tree
|
|
# (forbidden_paths: plugins, shared, CLAUDE.md, README.md) — every write lands inside --workspace.
|
|
# After the operator window the catalog repo hosts only the marketplace manifest + the catalog-level
|
|
# docs; the 10 plugins + the design-system live in their own Forgejo repos under
|
|
# https://git.fromaitochitta.com/open/. This script produces that state for inspection/staging:
|
|
#
|
|
# 1. archives the tracked catalog (git archive HEAD) into --workspace (clean: no .git, no untracked)
|
|
# 2. removes plugins/, shared/, scripts/sync-design-system.mjs (+ its test)
|
|
# 3. extracts the marketplace conventions from CLAUDE.md into CONVENTIONS.md (D6)
|
|
# 4. thins the catalog CLAUDE.md to catalog-maintenance only
|
|
# 5. rewrites the landing README.md to point at the external plugin repos, re-stating every version
|
|
# from plugin-map.json (the verified source). M15 is COUPLED to this D6 rewrite, not a ride-along:
|
|
# a roster that re-states versions/counts must state the verified ones or it ships a false document.
|
|
#
|
|
# NULL push (D8): writes only inside --workspace.
|
|
#
|
|
# Usage: 70-thin-catalog.sh --workspace <dir>
|
|
set -uo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
|
MAP="$SCRIPT_DIR/plugin-map.json"
|
|
|
|
WS=""
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--workspace) WS="${2:-}"; shift 2 ;;
|
|
*) echo "unknown arg: $1" >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
[ -n "$WS" ] || { echo "usage: 70-thin-catalog.sh --workspace <dir>" >&2; exit 2; }
|
|
[ -f "$MAP" ] || { echo "plugin-map.json missing at $MAP" >&2; exit 1; }
|
|
|
|
# --- 1. Archive the tracked catalog into the workspace (no .git, no untracked) ---
|
|
rm -rf "$WS"
|
|
mkdir -p "$WS"
|
|
git -C "$REPO_ROOT" archive HEAD | tar -x -C "$WS"
|
|
|
|
# --- 2. Remove the components that move out to their own repos ---
|
|
rm -rf "$WS/plugins" "$WS/shared" \
|
|
"$WS/scripts/sync-design-system.mjs" "$WS/scripts/sync-design-system.test.mjs"
|
|
rmdir "$WS/scripts" 2>/dev/null || true
|
|
|
|
# --- 3. Extract conventions -> CONVENTIONS.md (D6) ---
|
|
{
|
|
echo "# Conventions — ktg-plugin-marketplace catalog"
|
|
echo
|
|
echo "> Extracted from the marketplace CLAUDE.md (D6). These are the marketplace-wide conventions"
|
|
echo "> every plugin repo inherits under fork-and-own. See GOVERNANCE.md for the governance model."
|
|
echo
|
|
awk '
|
|
/^## Konvensjoner/ { f=1; print; next }
|
|
f && /^## / { exit }
|
|
f { print }
|
|
' "$WS/CLAUDE.md"
|
|
} > "$WS/CONVENTIONS.md"
|
|
|
|
# --- 4. Thin the catalog CLAUDE.md to catalog-maintenance only ---
|
|
cat > "$WS/CLAUDE.md" <<'MD'
|
|
# ktg-plugin-marketplace (catalog)
|
|
|
|
Catalog repository for the ktg-plugin-marketplace. After the polyrepo migration this repo hosts only
|
|
the marketplace manifest and the catalog-level docs; every plugin and the shared design-system live in
|
|
their own Forgejo repositories under `https://git.fromaitochitta.com/open/`.
|
|
|
|
## What lives here
|
|
|
|
- `.claude-plugin/marketplace.json` — the marketplace manifest (plugin entries point at external repos)
|
|
- `README.md` — the landing/catalog page
|
|
- `CONVENTIONS.md` — marketplace-wide conventions inherited by every plugin repo
|
|
- `GOVERNANCE.md` — governance + fork-and-own model
|
|
- `.mailmap`, `.gitleaks.toml`, `.gitleaksignore` — shared git-hygiene baselines
|
|
|
|
## Catalog maintenance
|
|
|
|
- Marketplace conventions: see CONVENTIONS.md.
|
|
- Adding/updating a plugin entry: edit `.claude-plugin/marketplace.json` (external `source: "url"` with
|
|
a pinned `ref`) and re-state the plugin in README.md with its verified version.
|
|
- Plugin source, issues, and releases live in each plugin's own repository — not here.
|
|
MD
|
|
|
|
# --- 5. Rewrite the landing README.md: external repo links + versions re-stated from plugin-map.json ---
|
|
python3 - "$MAP" "$WS/README.md" <<'PY'
|
|
import json, re, sys
|
|
|
|
map_path, readme_path = sys.argv[1], sys.argv[2]
|
|
targets = json.load(open(map_path))["targets"]
|
|
|
|
def browse(key):
|
|
u = targets[key]["repo_url"]
|
|
return u[:-4] if u.endswith(".git") else u
|
|
|
|
tag = {k: targets[k].get("tag", "") for k in targets}
|
|
# shared/playground-examples/ is bundled into the playground-design-system repo (plugin-map path_renames)
|
|
EXAMPLES_OWNER = "playground-design-system"
|
|
|
|
src = open(readme_path).read()
|
|
|
|
def link_repl(m):
|
|
container, key, sub = m.group(1), m.group(2), (m.group(3) or "")
|
|
sub = sub.lstrip("/")
|
|
if container == "shared" and key == "playground-examples":
|
|
owner = EXAMPLES_OWNER
|
|
subpath = ("playground-examples/" + sub) if sub else ""
|
|
elif key in targets:
|
|
owner = key
|
|
subpath = sub
|
|
else:
|
|
return m.group(0) # unknown — leave as-is (surfaced by the no-local-links assertion)
|
|
base = browse(owner)
|
|
if not subpath or subpath == "README.md":
|
|
return "](%s)" % base
|
|
return "](%s/src/branch/main/%s)" % (base, subpath)
|
|
|
|
# swap every local ](plugins/<key>/...) / ](shared/<key>/...) link to its external repo
|
|
src = re.sub(r"\]\((plugins|shared)/([a-z0-9-]+)(/[^)]*)?\)", link_repl, src)
|
|
|
|
# re-state the version backtick on heading lines that now link to a known external repo
|
|
def fix_version(line):
|
|
m = re.search(r"\]\(https://git\.fromaitochitta\.com/open/([a-z0-9-]+)\)", line)
|
|
if m and m.group(1) in tag and tag[m.group(1)]:
|
|
line = re.sub(r"`v[0-9][^`]*`", "`%s`" % tag[m.group(1)], line, count=1)
|
|
return line
|
|
|
|
out = "\n".join(fix_version(l) for l in src.split("\n"))
|
|
open(readme_path, "w").write(out)
|
|
PY
|
|
|
|
echo "thin-catalog ready at $WS"
|
|
echo " removed: plugins/ shared/ scripts/sync-design-system.mjs"
|
|
echo " added: CONVENTIONS.md (extracted from CLAUDE.md conventions)"
|
|
echo " README.md rewritten: external repo links + versions re-stated from plugin-map.json"
|