{"owner":"jeremylongshore","repo":"claude-code-plugins-plus-skills","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md","CLAUDE.md"],"skills":{"AGENTS.md":"# Repository Guidelines\n\n## Project Structure\n\nThis is the Tons of Skills Claude Code plugin marketplace. Author plugins under `plugins/<category>/<plugin-name>/`; a plugin commonly contains `skills/`, `commands/`, `.claude-plugin/plugin.json`, and a README. The editable catalog is `.claude-plugin/marketplace.extended.json`; its `marketplace.json`, generated plugin `package.json` files, and the README table of contents are derived. Shared tooling lives in `scripts/`, workspace packages in `packages/`, Python regression tests in `tests/`, and the Astro site in `marketplace/`.\n\n## Build, Test, and Development\n\nUse Node 20+ and pnpm 9.15.9+ at the repository root; `marketplace/` deliberately uses npm.\n\n```bash\npnpm install\n./scripts/quick-test.sh                 # fast repository sanity check\npnpm test && pnpm typecheck && pnpm lint\npnpm run verify                         # CI-equivalent verification pipeline\npnpm run sync-marketplace               # regenerate catalog-derived files\ncd marketplace && npm run dev           # local Astro site, port 4321\ncd marketplace && npx playwright test   # website end-to-end tests\n```\n\nDo not hand-edit generated catalog artifacts. Run `pnpm run sync-marketplace` before committing catalog or plugin changes. Validate skill metadata with `python3 scripts/validate-skills-schema.py --marketplace --verbose`; use `python3 scripts/validate-unicode-hygiene.py` for changed skill content.\n\n## Style and Naming\n\nFollow the existing file’s style; use Prettier for JavaScript, TypeScript, JSON, YAML, and Markdown (`pnpm run format:check`) and ESLint (`pnpm lint`) for code. Use two-space indentation in JS/TS and JSON. Name plugin folders lowercase kebab-case (for example, `plugins/mcp/example-plugin`) and skills as `skills/<skill-name>/SKILL.md`. Keep frontmatter compliant with the schema validator rather than inventing local variants.\n\n## Tests\n\nAdd or update focused tests beside the affected package or in `tests/`; Python tests use `test_*.py` and TypeScript tests commonly use `*.test.ts`. Run the narrowest relevant test first, then the commands above. Changes to validators, schemas, or catalog generation require their targeted regression suite plus the marketplace schema validation.\n\n## Commits and Pull Requests\n\nUse Conventional Commit-style subjects visible in history, such as `fix(ci): harden validation` or `docs(contributing): clarify workflow`. Keep each commit scoped. PRs should explain the user-facing change, link the beads issue, include screenshots for visual site changes, and include regenerated derived files when applicable. Use `bd` for task tracking: run `bd ready`, claim the issue, and close it when complete. Before finishing, commit, pull/rebase, run `bd sync`, push, and confirm `git status` is up to date.\n\n## Merge gates (do not weaken)\n\nRequired branch-protection contexts on `main`: **`ci-required`**, **`gitleaks`**, **`skill-conform`**.\n\n- `skill-conform` is a **separate** always-report workflow (`audit-harness conform --strict`). Never add it (or any path-scoped / provider-dependent job) to `ci-required`'s `needs:`.\n- Behavioral skill eval (`skill-eval-advisory.yml`) is **advisory only** until explicitly graduated.\n- Full gate architecture, validator SSoT rules, and non-negotiables: see `CLAUDE.md`.\n","CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Repository Overview\n\nTons of Skills — Claude Code plugins marketplace. Live at https://tonsofskills.com\n\n**Runtime:** Node `>=20.0.0`, pnpm `>=9.15.9`. Node 18 causes silent workspace-resolution failures.\n\n**Package manager:** `pnpm` everywhere **except** `marketplace/` which uses `npm` (CI-enforced).\n\n**Contributor guidelines live in `AGENTS.md`** — project structure, build/test/dev commands, style and naming, test conventions, commit/PR expectations, and the merge gates. Read it before starting work. (Session protocol lives in this file: the beads workflow in § Beads Issue Tracker — where `bd prime` is also the post-compaction context-recovery step — and the end-of-session push checklist in § Session Completion.)\n\n## Cross-session coordination — another Claude session may be in this repo\n\nThis repo is frequently worked in **parallel** with the `intent-eval-platform` umbrella session (that platform's CCPI validator + jrig-cli + kernel reach into this repo). Sessions are separate processes that share only the filesystem, so stay in sync via the shared surfaces:\n\n- **Read + append the shared journal** on cross-repo work: `~/000-projects/CROSS-SESSION-LOG.md` (append a dated line: what / branch or PR# / status).\n- **Durable cross-cutting tasks:** umbrella beads `~/000-projects/.beads/`, label `cross-session` (`bd list --label cross-session`).\n- **Guard the working tree:** this repo has ONE checkout; a concurrent session can `git checkout`/`reset` it out from under you and **wipe UNCOMMITTED work** (happened 2026-07-01). Commit early, or do multi-step file work in a `git worktree`.\n\nFull protocol (loaded by every session under `/home/jeremy`): `/home/jeremy/CLAUDE.md` § \"Cross-session coordination\".\n\n## Essential Commands\n\n```bash\n# Before ANY commit — regenerates marketplace.json, plugin package.jsons, README TOC\npnpm run sync-marketplace\n\n# Quick sanity check (~30s)\n./scripts/quick-test.sh\n\n# Build & test\npnpm install && pnpm build\npnpm test && pnpm typecheck\npnpm lint\npnpm run verify                   # Full pipeline — what CI's `verify` job runs\n\n# Validator (schema 4.0.0 — see 000-docs/SCHEMA_CHANGELOG.md)\npython3 scripts/validate-skills-schema.py --verbose\npython3 scripts/validate-skills-schema.py --marketplace --verbose\npython3 scripts/validate-skills-schema.py --marketplace --populate-db freshie/inventory.sqlite\npython3 scripts/validate-skills-schema.py --agents-only --verbose   # agents only (kernel-strict gate)\n\n# Unicode hygiene gate — Trapdoor / Trojan Source defense for SKILL.md /\n# plugin.json / agent / command files. Default mode blocks on tag chars\n# (U+E0000-E007F) + bidi overrides (CVE-2021-42574). --strict also blocks\n# on zero-width / format chars outside the BOM position.\npython3 scripts/validate-unicode-hygiene.py\npython3 scripts/validate-unicode-hygiene.py --strict           # tighter\npython3 scripts/validate-unicode-hygiene.py path/to/file.md    # one file\npython3 -m unittest tests.test_validate_unicode_hygiene -v     # regression suite\n\n# Marketplace website\ncd marketplace/ && npm run dev    # localhost:4321\ncd marketplace/ && npm run build\ncd marketplace/ && npx playwright test\n\n# Single test\ncd packages/cli && pnpm test -- --grep \"pattern\"\n\n# JRig behavioral eval — the published @intentsolutions/jrig-cli (bin `j-rig`),\n# pinned as a root devDep. Invoke via `pnpm exec j-rig` so it resolves the\n# repo's pinned version (node_modules/.bin/j-rig), NOT a global shim.\npnpm exec j-rig --version         # → 0.1.2 (the real 7-layer CLI)\npnpm exec j-rig check <skill-dir> # Tier 3A: deterministic (~seconds, free, no API key, no DB)\n\n# Real behavioral eval (opt-in, ~$2-5/skill) — needs the native better-sqlite3\n# build (run `pnpm rebuild better-sqlite3` once; the build script is not\n# auto-run on install). ALWAYS route through the wrapper — it runs j-rig\n# against a /dev/shm scratch DB and records the verdict into forge_proofs via\n# scripts/record-jrig-proofs.mjs. NEVER pass freshie/inventory.sqlite to\n# `j-rig eval --db` directly: j-rig writes its own run tables into whatever\n# --db it is given, which contaminates the tracked CMDB (and, pre-allowlist,\n# leaked those tables to the public DoltHub record).\nscripts/run-jrig-eval.sh --skill-dir <skill-dir> --plugin <catalog-name> \\\n  --inventory-db freshie/inventory.sqlite\n# DEEPSEEK_API_KEY is SOPS-decrypted in-process by the wrapper\n# (intent-eval-lab/.env.sops; see the IEP umbrella CLAUDE.md credential\n# table). Defaults: --provider deepseek --models deepseek-v4-flash — a real\n# behavioral provider, this is ground truth; other providers (haiku/sonnet/\n# opus via Anthropic, etc.) remain available via --provider/--models.\n```\n\n## Two Catalog System — Critical\n\n| File                                       | Purpose                        | Edit?     |\n| ------------------------------------------ | ------------------------------ | --------- |\n| `.claude-plugin/marketplace.extended.json` | Source of truth                | **Yes**   |\n| `.claude-plugin/marketplace.json`          | CLI-compatible, auto-generated | **Never** |\n\n`pnpm run sync-marketplace` regenerates all three derived artifacts: `marketplace.json`, any missing `plugins/**/package.json` files, and the `README.md` AUTO-TOC block. The pre-commit hook runs this automatically when `marketplace.extended.json` is staged.\n\nCI fails if any derived file is out of sync. Never hand-edit auto-generated files.\n\n## Marketplace Build Pipeline\n\n`npm run build` in `marketplace/` runs 7 sequential steps via `scripts/build.mjs`: discover-skills → extract-readme-sections → sync-catalog → enrich-jrig-data → generate-unified-search → build-cowork-zips → astro build.\n\n`discover-skills.mjs` emits two artifacts (schema 3.4.0+): `skills-index.json` (L0, ~97 KB gzipped, metadata only — for trigger-match / browse) and `skills-catalog.json` (L1, ~5.5 MB gzipped, full body HTML). Both carry top-level `schemaVersion` + `level` fields. CLI flag `--level=metadata|full|file` (default `full`).\n\n**Gotcha:** `compressHTML` is disabled in `astro.config.mjs` — iOS Safari fails on lines > 5000 chars. CI enforces this.\n\nPerformance budgets (CI-enforced): 40 MB total gzipped, 1 MB largest file, < 30s build, 2,800–4,000 routes.\n\n## Auto-cowork contract\n\n**Author flow.** Add a plugin to `.claude-plugin/marketplace.extended.json` and run `pnpm run sync-marketplace`. That is the entire authoring step. The pre-commit hook regenerates `marketplace.json`, plugin `package.json`s, and the README AUTO-TOC. There is no separate \"update the cowork page\" step.\n\n**Pipeline (deterministic from the catalog).** `cd marketplace && npm run build` runs `scripts/build.mjs`, which on every invocation:\n\n1. `cowork:zips` (`scripts/build-cowork-zips.mjs`) — wipes `marketplace/public/downloads/{plugins,bundles}` and rebuilds them from `marketplace.extended.json`. Produces individual plugin zips, category bundle zips, the mega-zip, `downloads/manifest.json`, and the Astro-consumed `marketplace/src/data/cowork-manifest.json`. Skips `category: mcp` entries (MCP plugins do not appear in cowork).\n2. `cowork:validate` (`scripts/validate-cowork-manifest.mjs`) — drift gate. Fails the build if catalog ↔ manifest ↔ disk fall out of alignment (orphan zips, missing entries, or stale manifest rows). Runs again in CI as a discrete step in `.github/workflows/validate-plugins.yml` so the failure signal is clearly named.\n3. `astro build` — copies `marketplace/public/` → `marketplace/dist/`. The `/cowork/` page reads `cowork-manifest.json` at build time and renders the download grid.\n\n**Deploy propagates the wipe.** The VPS force-command script `/usr/local/sbin/deploy-tonsofskills` ends with `rsync -a --delete /srv/tonsofskills/build/marketplace/dist/ /srv/tonsofskills/dist/`, so orphan files removed by the cowork build are also pruned from the served `dist/`. Current deployment authority is `intent-os/ops/deploy/`.\n\n**Don't commit downloads/.** `marketplace/public/downloads/` is gitignored (see `.gitignore:146`). CI checks out fresh and rebuilds from scratch — local state cannot leak to prod. Never commit or hand-edit anything under that directory.\n\n**Don't wire cowork build into `sync-marketplace`.** `sync-marketplace` is the fast (<2s) per-commit hook; `cowork:zips` is the slow (~30s) per-build step. They run on different cadences by design.\n\n## External Plugin Sync (mirror-by-default)\n\nAdopted model: **mirror by default · upstream improvements · never clobber.** Decision record: `000-docs/694-AT-DECR-external-sync-mirror-by-default-model.md`; pipeline audit + hardening: `000-docs/691-AT-AUDT-sync-external-pipeline-audit-and-hardening.md`.\n\n**Scale first — external is a minority augment, not the core.** ~470 plugins total (per `marketplace.extended.json`), but only 63 are externally synced (57 third-party sources + 6 of Jeremy's own repos, per `sources.yaml`). The other ~407 (~87%) are in-repo Intent Solutions work. The sync is a curated side-channel, not the marketplace — treat external contributors as a respected minority augment, never the center of gravity.\n\n**How sync works.** `sources.yaml` registers each external source. `.github/workflows/sync-external.yml` runs weekly (Mondays 06:00 UTC) and on demand (`workflow_dispatch` / `repository_dispatch`), invoking `scripts/sync-external.mjs` to mirror a source's files into `plugins/` and open an automated PR. A human reviews every auto-PR — historically ~1 in 10 sync PRs merges. The contributor's own repo is the source of truth; we do NOT locally edit a pure-mirror plugin.\n\n**Mirror vs curate.** Default is a pure mirror — the upstream repo governs, and improvements flow by upstreaming (see below), so the mirror becomes A-grade naturally with nothing to revert. Only when we deliberately harden a plugin past its upstream do we mark it `curated:` and freeze it.\n\n**Never-clobber guard (`curated:` freeze).** A source with `curated: true` in `sources.yaml` is FROZEN: `sync-external.mjs` logs `Curated — mirror frozen`, writes no files (no clone, no overwrite, no orphan-prune), and only keeps the catalog entry current — so even a `--force` sync can never revert our edits. `tonone`, `servicegraph`, and `schedule-after-usage-reset` carry `curated: true` today; `hyperflow` does NOT — it is the completed off-ramp example (its frontmatter hardening merged upstream, so the flag was dropped in #1008). This guard exists because a prior `--force` run reverted ~100 A-graded agents back to 3-field upstream stubs — the ~18.9k-line deletion that motivated the whole model. Note `curated:` (we hardened it locally) and `verified:` (a maintainer vetted quality/trust) are orthogonal: all three curated sources are `curated: true` but `verified: false`, an honest state and exactly why the two flags are separate.\n\n**Pileup auto-close (≤1 open sync PR).** `sync-external.yml` runs a \"Close superseded sync PRs\" step before Create-PR: it closes older open `automation/sync-external-*` PRs (with `--delete-branch`), keeping at most one open sync PR. The safe unique-per-run-branch model (from the 691 audit, which fixed an earlier shared-branch clobber) is preserved — this only prunes the pileup that model produced.\n\n**How we upstream respectfully.** Want a plugin at our A-grade bar? We bring THEIR plugin to standard on THEIR repo: a friendly issue first (\"we featured your plugin and hardened its frontmatter to our A-grade bar — would you be open to a PR upstreaming it?\"), then a PR the contributor owns and merges. No surprise PRs; credit preserved; they decide. Once merged upstream, the mirror is A-grade naturally and `curated:` can be dropped. **Any contributor-facing post (issue or PR body) gets Jeremy's wording sign-off BEFORE posting.**\n\n## Plugin Structure\n\n**AI instruction plugins** (`plugins/[category]/[name]/`): `.claude-plugin/plugin.json` + `README.md` + optional `commands/*.md`, `agents/*.md`, `skills/[name]/SKILL.md`.\n\n**MCP server plugins** (`plugins/mcp/[name]/`): TypeScript source in `src/`, built to `dist/index.js` (must be executable: shebang + `chmod +x`).\n\n**Forge-generated plugins** include a `.forge/` audit trail dir (`research.md`, `ecosystem.md`, `proofs.md`) — build-time only, not used at runtime. Canonical example: `plugins/productivity/plane/`.\n\n### SKILL.md Required Frontmatter (marketplace tier — all 8 fields)\n\n```yaml\n---\nname: skill-name\ndescription: |\n  Capability summary. Use when ... Trigger with \"...\".\nallowed-tools: Read, Write, Edit, Bash(npm:*), Glob\nversion: 1.0.0\nauthor: Name <email>\nlicense: MIT\ncompatibility: Designed for Claude Code\ntags: [devops, ci]\n---\n```\n\nBeyond the 8 required fields, schema 3.5.0+ adds optional visibility-gating fields, 3.6.0+ adds self-declared config fields, and 3.7.0+ adds `disallowed-tools` — see the Optional frontmatter section below.\n\n`compatible-with` is deprecated. Migrate with: `python3 scripts/batch-remediate.py --migrate-compatible-with`\n\n**Agents use `disallowedTools` (camelCase denylist).** Skills use `allowed-tools` (allowlist) AND optionally `disallowed-tools` (kebab-case denylist, schema 3.7.0+). The two field names are intentionally different — do NOT use camelCase on skills or kebab-case on agents; the validator rejects either mismatch. Agent-only fields: `effort`, `maxTurns`.\n\n**Agent gate is kernel-strict (schema 3.10.0, NOT tier-gated).** Every authored agent must carry the kernel-floor 8 (`name, description, tools, model, color, version, author, tags`) plus the enterprise live set (`disallowedTools`, `skills`, `background`; + `hooks`, `mcpServers`, `permissionMode` on standalone agents) — all **errors** at every tier. Banned fields (`capabilities`, `expertise_level`, `activation_priority`, `type`, `category`, `compatible-with`, `when_to_use`) are errors; `fable` is an accepted model. **Corpus status (measured 2026-08-11, doc 721):** the advisory `--agents-only` lane recorded a baseline of **253 errors** across the agent corpus — the earlier \"all agents A-grade\" claim is retired until the lane is re-baselined clean; treat A-grade as the bar, not the current state. **Schema 3.11.0** added a body-vs-allowlist check: an agent whose body invokes `mcp__server__tool` not in its `tools` allowlist is an error (it would runtime-block). Validate with `--agents-only`.\n\n### Optional frontmatter (schema 3.5.0 / 3.6.0 / 3.7.0 — all default to off)\n\n- **Visibility gating (3.5.0):** `requires_env` / `requires_tools` / `fallback_for_env` / `fallback_for_tools` — list-of-strings. Skill hidden unless deps met; fallback form is the inverse. Cross-field overlap (`requires_X` + `fallback_for_X` of same value) is an ERROR.\n- **Self-declared config (3.6.0):** `required_environment_variables` (top-level list, each entry needs `name` + `prompt`) and `metadata.intent-solutions.config` (nested list, each entry needs `key` + `description` + `default`). Full reference: `000-docs/264-DR-GUID-skill-config-pattern.md`.\n- **Defense-in-depth disallow list (3.7.0):** `disallowed-tools` — kebab-case string or YAML list of tool patterns. Removes those tools from the model while the skill is active. Parallel to (not a replacement for) `allowed-tools`. Cross-field overlap with `allowed-tools` is an ERROR (mirrors the 3.5.0 visibility-gating overlap rule). Defense-in-depth for skills that legitimately need broad `allowed-tools` but should never reach for specific high-risk operations (`rm`, `curl`, `wget`, `.env` writes). Full reference: `000-docs/681-AT-ADEC-claude-code-platform-changelog-impact.md` § Change 1.\n- **NON-NEGOTIABLE:** these are optional. `ALWAYS_REQUIRED` is still the 8-field set above. See issue #612 + `000-docs/681-AT-ADEC-claude-code-platform-changelog-impact.md` § Implementation directives before proposing any change to required fields — the 8-field set is preserved; `disallowed-tools` is additive, not required.\n\n## CI gate architecture — three required checks (rebuilt 2026-07; skill-conform added 2026-07-23)\n\n**Branch protection on `main` requires THREE always-reporting contexts: `ci-required` + `gitleaks` + `skill-conform`** (GitHub Actions app; `strict:false`, `enforce_admins:false`, 1 approving review).\n\n- **`ci-required`** is the final job in `.github/workflows/validate-plugins.yml` — `if: always()`, `needs:` all 19 gate jobs (validate, verify, test, check-package-manager, marketplace-validation, cli-smoke-tests, shellcheck-skills, skill-codeblock-syntax, typescript-coverage-audit, eslint-check, format-check, ruff-check, ruff-format-check, markdownlint, scan-synced-content, promote-curated-check, check-submission-docs). It fails if any needed job ended `failure`/`cancelled`; a `skipped` result counts as PASS — legitimate **only** for a designed job-level `if:`.\n- **`gitleaks`** comes from `secret-scan.yml` (also unfiltered).\n- **`skill-conform`** is its **own** workflow (`.github/workflows/skill-conform.yml`) — `pnpm exec audit-harness conform --strict` over the full marketplace corpus. Always-reports (no path filter). **Never** folded into `ci-required`'s `needs:` (doc 110 § 5: a skippable/path-scoped job must not green the aggregate). Baseline after #1108/#1118: thousands PASS / 0 FAIL; remaining ADVISORY is the harness-side missing marketplace schema only.\n- **Advisory (never required):** `.github/workflows/skill-eval-advisory.yml` — j-rig behavioral eval on changed skills that already carry `eval-spec.yaml`. Kill-switch `vars.ENABLE_SKILL_EVAL=true` + same-repo guard + `MINIMAX_API_KEY`. Graduation to required needs Jeremy + ≥4-week clean flap window (doc 110).\n- **Ruff pin:** `validate-plugins.yml` installs **`ruff==0.15.22`** for both ruff-check and ruff-format-check. Unpinned install pulled 0.16.0 mid-2026-07-23 and treated SKILL.md fenced Python as format targets (~1132 files). Do not unpin without a deliberate corpus reformat.\n\n**Why, and the rules that keep it fixed (do not regress):** the previous 10-context required set sourced checks from path-filtered workflows, so a PR without matching files left them \"Expected\" forever and could never merge (the #778/#964 stuck-PR class).\n\n1. `validate-plugins.yml` runs on **every** `pull_request` — never add a `paths:` filter to it.\n2. **Never add a path-filtered workflow's context to the required-status set.** To make a new check blocking: add it as a job in `validate-plugins.yml` and list it in `ci-required`'s `needs:`.\n3. A job in the aggregate's `needs:` may only skip via a _designed_ `if:` — an undesigned skip silently passes the gate.\n4. The five split lint workflows (`lint-markdown/python/shell/typescript/skill-codeblocks.yml`) were retired 2026-07; their identically-named jobs live in `validate-plugins.yml`. Do not re-split them. `tests/ci/test_path_routing.py` pins this invariant.\n\n**Supply-chain gate:** `scan-synced-content` (the REFUSE/CHALLENGE/FLAG scanner over `plugins/**`, `scripts/scan-synced-content.mjs`) blocks via the aggregate. A `sources.yaml`-only PR scans zero files and deliberately fails with a **waivable** `sources-change-unscanned` CHALLENGE — a reviewer clears it with a `sources.yaml:sources-change-unscanned  <reason>` line in `scripts/scan-allowlist.txt` after confirming the source is vetted and pinned in `sources.lock.json`. REFUSE is never waivable.\n\n**Submission-docs intake gate:** `check-submission-docs` (`scripts/check-submission-docs.mjs`) blocks via the aggregate. A PR that adds a NEW plugin directory (its `.claude-plugin/plugin.json` is an added file in the diff) must ship the tiered submission documents per the matrix in `templates/skill-docs/README.md` (micro → `docs/PRD.md`; standard → + `docs/ADR.md`; pack, 2+ skills → + `docs/ONE-PAGER.md`; `CFO-ONE-PAGER.md` stays review-enforced — \"money is the pitch\" isn't deterministic). External mirror plugins (dir contains `.source.json`) are exempt — their docs live upstream. A PR adding no new plugin passes clean INSIDE the script (the designed skip), so the job always reports. Standard: `000-docs/700-DR-GUID-skill-submission-standard.md`.\n\n**Advisory lanes (report, never block — never promote into the required set from a side PR):** the two kernel lanes (next section); agent frontmatter (`validate-skills-schema.py --agents-only`, report-only with a tracked `REPORT-ONLY-UNTIL:` marker — corpus unbaselined); `.mcp.json` (`scripts/validate-mcp-config.mjs`, never `--strict` — that promotion belongs to the DR-049 soak checklist); CodeQL (PR trigger scoped to `packages/**` + `marketplace/src/**` so it adds no fan-out to plugin PRs); and the PR pre-screen (below).\n\n### AI review — Greptile is active and advisory; CI is the only merge gate\n\n**As of 2026-07-23 Greptile is active through the GitHub App and has reviewed recent CCPI PRs.** Its version-controlled policy lives under `.greptile/`; treat its findings as advisory semantic-review input, not a merge signal. Gemini Code Assist consumer product is **sunset** (bot posts a sunset notice only; `.gemini/config.yaml` has `code_review.disable: true`). Fully removing Apps is a UI/admin action. Optional future path: SHA-pinned MiniMax review (`MINIMAX_API_KEY` + `ENABLE_MINIMAX_REVIEW`) as already patterned in `minimax-review.yml`.\n\n**Operationally: never block a merge waiting for an AI review.** Required contexts are **`ci-required` + `gitleaks` + `skill-conform`**.\n\n### PR pre-screen (advisory respond leg)\n\n`pr-prescreen.yml` (`pull_request_target`; kill switch `vars.ENABLE_PR_PRESCREEN`) grades changed plugins with the pinned validator and responds in two low-noise ways: a **`prescreen-grade` commit status** on every run (advisory forever — never a required context) and **one upserted marker comment** only on `CHANGES_REQUESTED`/`HARD_BLOCK` (silent on PASS; re-runs edit the same comment). Two hard-won invariants:\n\n- **The validator anchors its scan root to its own script location** (`Path(__file__).resolve().parents[1]`), not the cwd. Prescreen therefore copies the BASE-authored validator into the PR tree and runs the copy — invoking `../base/scripts/…` directly grades **main's** tree and false-PASSes every frontmatter change (the 2026-07 bug, fixed in #980). Do not \"simplify\" this back.\n- **Never checkout or execute PR-authored code in a `pull_request_target` workflow.** Applies equally to `plane-sync.yml` (which runs on `pull_request_target` so fork-PR close-outs get secrets — it reads event context only).\n\n## Validation & the kernel SSoT — CI/CD posture\n\nTwo things grade frontmatter in this repo today, and the relationship between them is the load-bearing context to preserve.\n\n### The two validators\n\n- **Prose-spec validator (authoritative):** `scripts/validate-skills-schema.py`. This is the canonical gate. It runs at standard and marketplace tiers, it grades both frontmatter AND markdown body sections, and at marketplace tier a missing required field is an **ERROR** (not a warning). Its CI jobs block merges through the `ci-required` aggregate (see \"CI gate architecture\" above). `ALWAYS_REQUIRED` (the IS 8-field set) is hand-authored here and stays **AUTHORITATIVE** — read `000-docs/SCHEMA_CHANGELOG.md` § NON-NEGOTIABLES before touching it. The IS rubric sits on top of Anthropic's permissive spec; the marketplace tier is intentionally strict. Do not reduce the 8-field set, do not demote marketplace errors to warnings, and do not \"realign\" to Anthropic's floor — any change to required-fields / tier model / error-vs-warning semantics is approval-gated per that doc.\n\n- **Kernel machine-spec (the SSoT being migrated to):** `@intentsolutions/core` — its `schemas/authoring/v1` family (byte-frozen) plus the strict fork `authoring/v2` — is the single internal source of truth for \"what is a valid agent-native artifact.\" The kernel's `skill-frontmatter` schema encodes the **same** IS 8-field required set as a pure `allOf` of upstream-base + universal folds + the IS overlay. The plan of record is for `validate-skills-schema.py` to **consume the kernel folds** instead of its hand-rolled rule sets. That migration is in progress; the kernel pin is **exactly `0.9.0`** in `package.json` (no `^`/`~`) — currently **behind** the published `0.10.0`, see the staleness note below. The `authoring/v1` schema family is byte-frozen across kernel package versions, so a pin bump tracks the latest published kernel without changing the `authoring/v1` contract the shadow lane reads. Contract semantics for `authoring/v1` fields are canonical in the kernel's own changelog — cite it, do not duplicate it (see `000-docs/SCHEMA_CHANGELOG.md` § \"Kernel changelog citation\").\n\n### Two advisory lanes (never block) running the soak\n\nBoth are `continue-on-error: true`, neither is in the required-status set, and neither mutates anything:\n\n- **kernel-shadow soak** — `.github/workflows/kernel-shadow-validation.yml` + `scripts/kernel-shadow-validation.mjs`. Runs the kernel-pinned `skill-frontmatter` schema (from `@intentsolutions/core@0.9.0`) over the same SKILL.md corpus the prose-spec validator grades and logs per-file AGREE / DISAGREE deviation to `scripts/.kernel-shadow/report.json`. This is the DR-049 shadow soak (the \"zero-on-corpus shadow signal\"). The cutover-relevant number is the **frontmatter-scoped** deviation — a file that fails the prose-spec on missing `[body]` sections but has valid frontmatter is a scope difference, not a kernel gap, and is excluded.\n- **kernel-vendor-hash gate** — `.github/workflows/kernel-vendor-hash.yml` + `scripts/kernel-vendor-hash.mjs`. Enforces the version-coupling invariant **V ≤ C ≤ K** (vendored ≤ CCPI-declared ≤ kernel-latest) plus a ≤7-day staleness bound. Soak-aware: it reads the `0.9.0` pin, polices ordering/staleness only, and must never pressure a pin bump or change validator authority.\n\nThe validator itself does a kernel-loaded **shadow read** of `ALWAYS_REQUIRED` (`load_kernel_required()` / `--kernel-shadow`) — it compares the kernel's effective required set against the hand-authored one and reports drift. The hand-authored `ALWAYS_REQUIRED` stays authoritative; the shadow read is observational only.\n\n### Do-not-flip soak discipline (do not lose this)\n\n**The kernel pin and the authority flip are two SEPARATE axes — do not conflate them.** The pin is _intended_ to track the latest published kernel; bumping it keeps the shadow lane reading a current, byte-frozen `authoring/v1` contract and is a routine governance/coupling update, not an authority change.\n\n> ⚠️ **The pin is currently BEHIND (as of 2026-07-26).** Root pin is exactly `0.9.0` (no `^`/`~`) but `@intentsolutions/core@0.10.0` published 2026-07-09 — so the ≤7-day staleness bound has been breached since roughly 2026-07-16, and the `kernel-vendor-hash` daily sweep has been reporting `❌ VIOLATION: STALENESS` on every run. It is ADVISORY (exit 0), which is why it went unnoticed. Catching this up is a **lockstep** change: `@intentsolutions/jrig-cli@0.1.2` depends on `core@0.9.0` _exactly_, so core must move together with jrig-cli (`0.2.0`, published 2026-07-10) or the two resolve to separate un-hoisted copies of the kernel. Do not read the staleness report as pressure to flip authority — the two axes remain separate, and re-baselining the shadow-soak agreement numbers is part of the bump.\n\nWhat stays frozen is the **authority**: do **NOT** flip the kernel-shadow lane from advisory to authoritative (blocking) until ALL of these hold:\n\n1. ≥99.5% corpus agreement (deterministic folds must be 100%; the 0.5% band is reserved for non-deterministic surfaces only);\n2. ≥30 days of advisory soak;\n3. zero open P0 blockers;\n4. the Rekor superseding-event rollback protocol implemented and tested;\n5. governance sign-off from the CTO + CISO + VP-DevRel triple; and\n6. a ≥14-day public deprecation-window notice to affected skill authors.\n\nAs of now the soak has **not** met the bar — agreement sits below 99.5%, and the open disagreements are real tool-safety / shell-substitution security cases that the prose-spec validator correctly blocks (so flipping early would weaken a real gate). Until every condition above is satisfied, validator authority stays with `validate-skills-schema.py` and both kernel lanes stay advisory. Promotion to blocking is a separate, later cutover step gated by these conditions — never a side effect of an unrelated PR.\n\n**Alignment note (`@intentsolutions/jrig-cli`).** The `j-rig` behavioral-eval CLI is a root devDep pinned to **exactly `@intentsolutions/jrig-cli@0.1.2`**, which depends on **`@intentsolutions/core@0.9.0` (exact)** — the same version the **root** `@intentsolutions/core` pin carries — so they resolve to one shared root-hoisted copy and the kernel-shadow + kernel-vendor lanes read it directly. (The `0.1.2` cut carries the eval→Evidence-Bundle bridge `j-rig eval --emit-bundle` [jrig #172], a functional-exec `max_tokens` / length-truncation fix [jrig #173], `j-rig scaffold-spec` from a `SKILL.md` [jrig #174], and a judge-verdict recovery from truncated / fenced JSON that had inflated NO-SHIP [jrig #175]; it also retains the per-test-case `criteria_ids` scoping fix [jrig #162], so `pnpm exec j-rig eval` scopes each criterion to its own test case. A transitive dep, `@intentsolutions/refiner-core@0.2.0`, still peer-wants `core@^0.8.0`; pnpm surfaces that as a non-fatal warning until refiner-core widens its peer range.) The pin bump is a coupling update only; the authority flip and the root-pin cutover to `authoring/v2` remain the separate, gated steps above.\n\n### Validator consolidation (already landed)\n\nA recent cleanup removed 74 dead duplicate `validation.sh` stubs, collapsed previously-diverged secondary validators into delegating wrappers around the canonical `validate-skills-schema.py`, and added the kernel-loaded shadow read described above. There is now one canonical validator; secondary entry points delegate to it.\n\n### auto-bump posture for contributors\n\n`.github/workflows/auto-bump-on-pr.yml` auto-bumps changed plugins' patch versions on PRs (only on `plugins/**` / `packages/**` changes). For a docs-only or otherwise non-release PR, put **`[skip auto-bump]`** in the PR title or body so the auto-bumper steps aside. Minor/major bumps stay a deliberate human choice — hand-edit the version in the same PR. It stays on `pull_request` (not `pull_request_target`) by design — the bump needs a write token, which must never be handed to fork code; fork PRs are skipped cleanly, and a first-time fork contributor's queued \"Approve and run\" entry just no-ops when approved.\n\n## Adding a New Plugin\n\n**Hand-authored:** copy from `templates/`, add catalog entry to `marketplace.extended.json`, run `pnpm run sync-marketplace`, validate with `--marketplace`.\n\n**Forge-generated:** `/skill-creator --forge <api-name>` — runs 8-gate workflow, requires a NOI (Name of Identity), produces Grade-A skill + `.forge/` audit trail + catalog entry.\n\nTo regenerate against a current API: `/skill-creator --reforge <plugin-name>`.\n\n## Design System\n\nConstitution: `marketplace/DESIGN.md` (Data-Dense Pro family, locked 2026-05-06). If a component disagrees with it, the component is wrong.\n\nKey tokens (`marketplace/src/styles/tokens.css`): `--bg`, `--panel`, `--rule`, `--ink`, `--signal`. Old aliases (`--primary`, `--surface`, `--text`, `--border`) remain mapped for back-compat. CSS colors: **OKLCH only, never hex/rgb**.\n\nReject: gradients on cards, glassmorphism, drop-shadow stacks, `hover:scale-105` on whole cards.\n\n## Killer Skill of the Week\n\nEditorial — Jeremy picks manually. Tooling only syncs two render surfaces.\n\n```bash\n# Promote a new spotlight\nnode scripts/promote-spotlight.mjs path/to/new-spotlight.json\n\n# Sync README block only (no rotation)\nnode scripts/render-spotlight.mjs\n```\n\nSource of truth: `marketplace/src/data/spotlights.json`.\n\n## Key Identifiers — Do Not \"Normalize\"\n\n- **GitHub repo (canonical):** `jeremylongshore/claude-code-plugins-plus-skills`\n- **Marketplace catalog id:** `claude-code-plugins-plus`\n- **Public install slug:** `jeremylongshore/claude-code-plugins` (legacy, GitHub 301s to canonical — hardcoded in CLI, Hero snippet, hundreds of READMEs — renaming is a breaking API change)\n\n## Freshie Inventory\n\nCMDB with a hybrid storage model: `freshie/inventory.sqlite` is the **local\nruntime format** every tool reads/writes (UNTRACKED — the blob is out of git);\nthe **versioned system of record is Dolt**, exported by\n`freshie/scripts/dolt-sync.py` into `freshie/dolt/` (gitignored) and pushed to\npublic DoltHub `jeremylongshore/freshie-inventory` with a `run-N` tag per\ninventory run. The tracked compact export (`freshie/grades.csv` +\n`freshie/grade-histogram.json`) is regenerated by every sync — its git diff is\nthe \"skill X went B→A\" story.\n\nThe full cycle:\n\n```bash\npython3 freshie/scripts/rebuild-inventory.py                         # 1. New discovery run\npython3 scripts/validate-skills-schema.py --marketplace --populate-db freshie/inventory.sqlite  # 2. Compliance\npython3 freshie/scripts/dolt-sync.py                                 # 3. Dolt commit + tag + DoltHub push\npython3 freshie/scripts/promote-to-curated.py                        # 4. Refresh skills/.curated/ (skills.sh mirror)\nsqlite3 freshie/inventory.sqlite \"SELECT grade, COUNT(*) FROM skill_compliance GROUP BY grade;\"  # runtime queries\npython3 freshie/scripts/batch-remediate.py --dry-run && python3 freshie/scripts/batch-remediate.py --all --execute\n```\n\n**skills.sh curated mirror** (`freshie/scripts/promote-to-curated.py`): rebuilds\n`skills/.curated/` as a generated mirror of the repo's best **A+B** plugin skills (our own;\nexternal `.source.json` mirrors excluded → ~1,881) so skills.sh can index them — it only\ncrawls root `skills/` / `.curated/`, never `plugins/**/skills/`. The plugin skill stays the\nsource of truth; the mirror is wipe-and-rebuilt from the tracked `grades.csv` (not the\ngit-ignored `inventory.sqlite`, so the CI drift gate is reproducible), copies only\ngit-tracked files, and re-grades each candidate in-process (promote iff fresh grade still\nA/B). Audit trail: `skills/.curated/MANIFEST.json`. It is excluded from the README count\n(`generate-readme-toc.mjs`) and the inventory scan (`validate-skills-schema.py`\n`find_skill_files`) so a mirror copy is never double-counted. Self-maintaining:\n`promote-curated.yml` refreshes it weekly (PR on change, Slack-on-fail); the\n`promote-curated-check` gate in `ci-required` fails a PR that edits a promoted source\nwithout regenerating. Repo-page branding: root `skills.sh.json`.\n\nHistory queries go to Dolt (`cd freshie/dolt/freshie`): `WHERE run_id = N`,\n`AS OF 'run-N'`, `dolt diff run-7 run-8 --stat` — the run_id model is\nappend-only, so diffs between run tags show added rows, not cell changes.\nClone-free check: `curl \"https://www.dolthub.com/api/v1alpha1/jeremylongshore/freshie-inventory/main?q=SELECT+COUNT(*)+FROM+skill_compliance\"`.\n\n**Interactive/MCP history — the in-repo `dolt-mcp-vcs` plugin** (`plugins/mcp/dolt-mcp-vcs/`,\nregistered as this project's MCP server → freshie Dolt on `127.0.0.1:3308`). Use it to query the\nrun-over-run history conversationally instead of hand-writing `dolt sql`:\n\n- **Start the sql-server first** — the MCP client connects to a _running_ server; it is NOT\n  auto-started. From `freshie/dolt/freshie`: `dolt sql-server -H 127.0.0.1 -P 3308` (run\n  detached; log to a scratch path). Do NOT pass `-u`/`-p` — dolt ≥2 removed them from\n  `sql-server`; the default `root` is passwordless, matching the MCP config's `DOLT_PASSWORD=\"\"`.\n  Then load tools with `ToolSearch\nquery=\"select:mcp__dolt-mcp-vcs__query,mcp__dolt-mcp-vcs__list_dolt_commits,mcp__dolt-mcp-vcs__list_dolt_diff_changes_by_table_name\"`\n  — `query` for `AS OF 'run-N'` reads, the diff tools for per-run deltas; expert agents\n  `dolt-sync-advisor` / `bead-epic-auditor` / `dolt-mcp-vcs:beads-guru` are also available.\n- **⚠️ Stop the sql-server before `freshie/scripts/dolt-sync.py`** — both write\n  `freshie/dolt/freshie`; a live server holds the lock and the sync will clobber/deadlock. `kill\n<server-pid>`, sync, then restart if you still need it.\n- **Mutation gate**: destructive verbs (`push`/`merge`/`reset`/`branch-delete`) are\n  **recommend-only** — the plugin surfaces them but won't execute, so DoltHub pushes still go\n  through the one-way `dolt-sync.py` exporter, never the MCP.\n\n**Rules:** local is the sole writer — never merge DoltHub PRs or web-edit the\npublic database (the exporter is one-way and will clobber them). A failed\nDoltHub push exits non-zero on purpose: until pushed, Dolt history is\nsingle-copy on this box. Exporter unit tests: `python3 -m unittest\ntests.test_dolt_sync`. Full details + restore path: `freshie/README.md`.\n\nKey tables: `skill_compliance` (scores, grades, JRig columns), `forge_proofs` (drives JRig-Verified badges on plugin detail pages — `enrich-jrig-data.mjs` preserves the committed `jrig-data.json` when the local DB is absent, e.g. in CI).\n\n## npm Publish Pipeline\n\nPatch version bumps happen automatically on PR (via `auto-bump-on-pr.yml`). For minor/major bumps, hand-edit the version in the same PR. Merge to main triggers publish + tag + GitHub Release via `publish-changed-packages.yml`. See `RELEASING.md` for the full operator flow.\n\n<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:7510c1e2 -->\n\n## Beads Issue Tracker\n\nThis project uses **bd (beads)** for issue tracking. Run `bd prime` to see full workflow context and commands.\n\n### Quick Reference\n\n```bash\nbd ready              # Find available work\nbd show <id>          # View issue details\nbd update <id> --claim  # Claim work\nbd close <id>         # Complete work\n```\n\n### Rules\n\n- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists\n- Run `bd prime` for detailed command reference and session close protocol\n- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files\n\n**Architecture in one line:** issues live in a local Dolt DB; sync uses `refs/dolt/data` on your git remote; `.beads/issues.jsonl` is a passive export. See https://github.com/gastownhall/beads/blob/main/docs/SYNC_CONCEPTS.md for details and anti-patterns.\n\n## Session Completion\n\n**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.\n\n**MANDATORY WORKFLOW:**\n\n1. **File issues for remaining work** - Create issues for anything that needs follow-up\n2. **Run quality gates** (if code changed) - Tests, linters, builds\n3. **Update issue status** - Close finished work, update in-progress items\n4. **PUSH TO REMOTE** - This is MANDATORY:\n\n   ```bash\n   git pull --rebase\n   git push\n   git status  # MUST show \"up to date with origin\"\n   ```\n\n5. **Clean up** - Clear stashes, prune remote branches\n6. **Verify** - All changes committed AND pushed\n7. **Hand off** - Provide context for next session\n\n**CRITICAL RULES:**\n\n- Work is NOT complete until `git push` succeeds\n- NEVER stop before pushing - that leaves work stranded locally\n- NEVER say \"ready to push when you are\" - YOU must push\n- If push fails, resolve and retry until it succeeds\n<!-- END BEADS INTEGRATION -->\n"},"files":{"AGENTS.md":"# Repository Guidelines\n\n## Project Structure\n\nThis is the Tons of Skills Claude Code plugin marketplace. Author plugins under `plugins/<category>/<plugin-name>/`; a plugin commonly contains `skills/`, `commands/`, `.claude-plugin/plugin.json`, and a README. The editable catalog is `.claude-plugin/marketplace.extended.json`; its `marketplace.json`, generated plugin `package.json` files, and the README table of contents are derived. Shared tooling lives in `scripts/`, workspace packages in `packages/`, Python regression tests in `tests/`, and the Astro site in `marketplace/`.\n\n## Build, Test, and Development\n\nUse Node 20+ and pnpm 9.15.9+ at the repository root; `marketplace/` deliberately uses npm.\n\n```bash\npnpm install\n./scripts/quick-test.sh                 # fast repository sanity check\npnpm test && pnpm typecheck && pnpm lint\npnpm run verify                         # CI-equivalent verification pipeline\npnpm run sync-marketplace               # regenerate catalog-derived files\ncd marketplace && npm run dev           # local Astro site, port 4321\ncd marketplace && npx playwright test   # website end-to-end tests\n```\n\nDo not hand-edit generated catalog artifacts. Run `pnpm run sync-marketplace` before committing catalog or plugin changes. Validate skill metadata with `python3 scripts/validate-skills-schema.py --marketplace --verbose`; use `python3 scripts/validate-unicode-hygiene.py` for changed skill content.\n\n## Style and Naming\n\nFollow the existing file’s style; use Prettier for JavaScript, TypeScript, JSON, YAML, and Markdown (`pnpm run format:check`) and ESLint (`pnpm lint`) for code. Use two-space indentation in JS/TS and JSON. Name plugin folders lowercase kebab-case (for example, `plugins/mcp/example-plugin`) and skills as `skills/<skill-name>/SKILL.md`. Keep frontmatter compliant with the schema validator rather than inventing local variants.\n\n## Tests\n\nAdd or update focused tests beside the affected package or in `tests/`; Python tests use `test_*.py` and TypeScript tests commonly use `*.test.ts`. Run the narrowest relevant test first, then the commands above. Changes to validators, schemas, or catalog generation require their targeted regression suite plus the marketplace schema validation.\n\n## Commits and Pull Requests\n\nUse Conventional Commit-style subjects visible in history, such as `fix(ci): harden validation` or `docs(contributing): clarify workflow`. Keep each commit scoped. PRs should explain the user-facing change, link the beads issue, include screenshots for visual site changes, and include regenerated derived files when applicable. Use `bd` for task tracking: run `bd ready`, claim the issue, and close it when complete. Before finishing, commit, pull/rebase, run `bd sync`, push, and confirm `git status` is up to date.\n\n## Merge gates (do not weaken)\n\nRequired branch-protection contexts on `main`: **`ci-required`**, **`gitleaks`**, **`skill-conform`**.\n\n- `skill-conform` is a **separate** always-report workflow (`audit-harness conform --strict`). Never add it (or any path-scoped / provider-dependent job) to `ci-required`'s `needs:`.\n- Behavioral skill eval (`skill-eval-advisory.yml`) is **advisory only** until explicitly graduated.\n- Full gate architecture, validator SSoT rules, and non-negotiables: see `CLAUDE.md`.\n","CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Repository Overview\n\nTons of Skills — Claude Code plugins marketplace. Live at https://tonsofskills.com\n\n**Runtime:** Node `>=20.0.0`, pnpm `>=9.15.9`. Node 18 causes silent workspace-resolution failures.\n\n**Package manager:** `pnpm` everywhere **except** `marketplace/` which uses `npm` (CI-enforced).\n\n**Contributor guidelines live in `AGENTS.md`** — project structure, build/test/dev commands, style and naming, test conventions, commit/PR expectations, and the merge gates. Read it before starting work. (Session protocol lives in this file: the beads workflow in § Beads Issue Tracker — where `bd prime` is also the post-compaction context-recovery step — and the end-of-session push checklist in § Session Completion.)\n\n## Cross-session coordination — another Claude session may be in this repo\n\nThis repo is frequently worked in **parallel** with the `intent-eval-platform` umbrella session (that platform's CCPI validator + jrig-cli + kernel reach into this repo). Sessions are separate processes that share only the filesystem, so stay in sync via the shared surfaces:\n\n- **Read + append the shared journal** on cross-repo work: `~/000-projects/CROSS-SESSION-LOG.md` (append a dated line: what / branch or PR# / status).\n- **Durable cross-cutting tasks:** umbrella beads `~/000-projects/.beads/`, label `cross-session` (`bd list --label cross-session`).\n- **Guard the working tree:** this repo has ONE checkout; a concurrent session can `git checkout`/`reset` it out from under you and **wipe UNCOMMITTED work** (happened 2026-07-01). Commit early, or do multi-step file work in a `git worktree`.\n\nFull protocol (loaded by every session under `/home/jeremy`): `/home/jeremy/CLAUDE.md` § \"Cross-session coordination\".\n\n## Essential Commands\n\n```bash\n# Before ANY commit — regenerates marketplace.json, plugin package.jsons, README TOC\npnpm run sync-marketplace\n\n# Quick sanity check (~30s)\n./scripts/quick-test.sh\n\n# Build & test\npnpm install && pnpm build\npnpm test && pnpm typecheck\npnpm lint\npnpm run verify                   # Full pipeline — what CI's `verify` job runs\n\n# Validator (schema 4.0.0 — see 000-docs/SCHEMA_CHANGELOG.md)\npython3 scripts/validate-skills-schema.py --verbose\npython3 scripts/validate-skills-schema.py --marketplace --verbose\npython3 scripts/validate-skills-schema.py --marketplace --populate-db freshie/inventory.sqlite\npython3 scripts/validate-skills-schema.py --agents-only --verbose   # agents only (kernel-strict gate)\n\n# Unicode hygiene gate — Trapdoor / Trojan Source defense for SKILL.md /\n# plugin.json / agent / command files. Default mode blocks on tag chars\n# (U+E0000-E007F) + bidi overrides (CVE-2021-42574). --strict also blocks\n# on zero-width / format chars outside the BOM position.\npython3 scripts/validate-unicode-hygiene.py\npython3 scripts/validate-unicode-hygiene.py --strict           # tighter\npython3 scripts/validate-unicode-hygiene.py path/to/file.md    # one file\npython3 -m unittest tests.test_validate_unicode_hygiene -v     # regression suite\n\n# Marketplace website\ncd marketplace/ && npm run dev    # localhost:4321\ncd marketplace/ && npm run build\ncd marketplace/ && npx playwright test\n\n# Single test\ncd packages/cli && pnpm test -- --grep \"pattern\"\n\n# JRig behavioral eval — the published @intentsolutions/jrig-cli (bin `j-rig`),\n# pinned as a root devDep. Invoke via `pnpm exec j-rig` so it resolves the\n# repo's pinned version (node_modules/.bin/j-rig), NOT a global shim.\npnpm exec j-rig --version         # → 0.1.2 (the real 7-layer CLI)\npnpm exec j-rig check <skill-dir> # Tier 3A: deterministic (~seconds, free, no API key, no DB)\n\n# Real behavioral eval (opt-in, ~$2-5/skill) — needs the native better-sqlite3\n# build (run `pnpm rebuild better-sqlite3` once; the build script is not\n# auto-run on install). ALWAYS route through the wrapper — it runs j-rig\n# against a /dev/shm scratch DB and records the verdict into forge_proofs via\n# scripts/record-jrig-proofs.mjs. NEVER pass freshie/inventory.sqlite to\n# `j-rig eval --db` directly: j-rig writes its own run tables into whatever\n# --db it is given, which contaminates the tracked CMDB (and, pre-allowlist,\n# leaked those tables to the public DoltHub record).\nscripts/run-jrig-eval.sh --skill-dir <skill-dir> --plugin <catalog-name> \\\n  --inventory-db freshie/inventory.sqlite\n# DEEPSEEK_API_KEY is SOPS-decrypted in-process by the wrapper\n# (intent-eval-lab/.env.sops; see the IEP umbrella CLAUDE.md credential\n# table). Defaults: --provider deepseek --models deepseek-v4-flash — a real\n# behavioral provider, this is ground truth; other providers (haiku/sonnet/\n# opus via Anthropic, etc.) remain available via --provider/--models.\n```\n\n## Two Catalog System — Critical\n\n| File                                       | Purpose                        | Edit?     |\n| ------------------------------------------ | ------------------------------ | --------- |\n| `.claude-plugin/marketplace.extended.json` | Source of truth                | **Yes**   |\n| `.claude-plugin/marketplace.json`          | CLI-compatible, auto-generated | **Never** |\n\n`pnpm run sync-marketplace` regenerates all three derived artifacts: `marketplace.json`, any missing `plugins/**/package.json` files, and the `README.md` AUTO-TOC block. The pre-commit hook runs this automatically when `marketplace.extended.json` is staged.\n\nCI fails if any derived file is out of sync. Never hand-edit auto-generated files.\n\n## Marketplace Build Pipeline\n\n`npm run build` in `marketplace/` runs 7 sequential steps via `scripts/build.mjs`: discover-skills → extract-readme-sections → sync-catalog → enrich-jrig-data → generate-unified-search → build-cowork-zips → astro build.\n\n`discover-skills.mjs` emits two artifacts (schema 3.4.0+): `skills-index.json` (L0, ~97 KB gzipped, metadata only — for trigger-match / browse) and `skills-catalog.json` (L1, ~5.5 MB gzipped, full body HTML). Both carry top-level `schemaVersion` + `level` fields. CLI flag `--level=metadata|full|file` (default `full`).\n\n**Gotcha:** `compressHTML` is disabled in `astro.config.mjs` — iOS Safari fails on lines > 5000 chars. CI enforces this.\n\nPerformance budgets (CI-enforced): 40 MB total gzipped, 1 MB largest file, < 30s build, 2,800–4,000 routes.\n\n## Auto-cowork contract\n\n**Author flow.** Add a plugin to `.claude-plugin/marketplace.extended.json` and run `pnpm run sync-marketplace`. That is the entire authoring step. The pre-commit hook regenerates `marketplace.json`, plugin `package.json`s, and the README AUTO-TOC. There is no separate \"update the cowork page\" step.\n\n**Pipeline (deterministic from the catalog).** `cd marketplace && npm run build` runs `scripts/build.mjs`, which on every invocation:\n\n1. `cowork:zips` (`scripts/build-cowork-zips.mjs`) — wipes `marketplace/public/downloads/{plugins,bundles}` and rebuilds them from `marketplace.extended.json`. Produces individual plugin zips, category bundle zips, the mega-zip, `downloads/manifest.json`, and the Astro-consumed `marketplace/src/data/cowork-manifest.json`. Skips `category: mcp` entries (MCP plugins do not appear in cowork).\n2. `cowork:validate` (`scripts/validate-cowork-manifest.mjs`) — drift gate. Fails the build if catalog ↔ manifest ↔ disk fall out of alignment (orphan zips, missing entries, or stale manifest rows). Runs again in CI as a discrete step in `.github/workflows/validate-plugins.yml` so the failure signal is clearly named.\n3. `astro build` — copies `marketplace/public/` → `marketplace/dist/`. The `/cowork/` page reads `cowork-manifest.json` at build time and renders the download grid.\n\n**Deploy propagates the wipe.** The VPS force-command script `/usr/local/sbin/deploy-tonsofskills` ends with `rsync -a --delete /srv/tonsofskills/build/marketplace/dist/ /srv/tonsofskills/dist/`, so orphan files removed by the cowork build are also pruned from the served `dist/`. Current deployment authority is `intent-os/ops/deploy/`.\n\n**Don't commit downloads/.** `marketplace/public/downloads/` is gitignored (see `.gitignore:146`). CI checks out fresh and rebuilds from scratch — local state cannot leak to prod. Never commit or hand-edit anything under that directory.\n\n**Don't wire cowork build into `sync-marketplace`.** `sync-marketplace` is the fast (<2s) per-commit hook; `cowork:zips` is the slow (~30s) per-build step. They run on different cadences by design.\n\n## External Plugin Sync (mirror-by-default)\n\nAdopted model: **mirror by default · upstream improvements · never clobber.** Decision record: `000-docs/694-AT-DECR-external-sync-mirror-by-default-model.md`; pipeline audit + hardening: `000-docs/691-AT-AUDT-sync-external-pipeline-audit-and-hardening.md`.\n\n**Scale first — external is a minority augment, not the core.** ~470 plugins total (per `marketplace.extended.json`), but only 63 are externally synced (57 third-party sources + 6 of Jeremy's own repos, per `sources.yaml`). The other ~407 (~87%) are in-repo Intent Solutions work. The sync is a curated side-channel, not the marketplace — treat external contributors as a respected minority augment, never the center of gravity.\n\n**How sync works.** `sources.yaml` registers each external source. `.github/workflows/sync-external.yml` runs weekly (Mondays 06:00 UTC) and on demand (`workflow_dispatch` / `repository_dispatch`), invoking `scripts/sync-external.mjs` to mirror a source's files into `plugins/` and open an automated PR. A human reviews every auto-PR — historically ~1 in 10 sync PRs merges. The contributor's own repo is the source of truth; we do NOT locally edit a pure-mirror plugin.\n\n**Mirror vs curate.** Default is a pure mirror — the upstream repo governs, and improvements flow by upstreaming (see below), so the mirror becomes A-grade naturally with nothing to revert. Only when we deliberately harden a plugin past its upstream do we mark it `curated:` and freeze it.\n\n**Never-clobber guard (`curated:` freeze).** A source with `curated: true` in `sources.yaml` is FROZEN: `sync-external.mjs` logs `Curated — mirror frozen`, writes no files (no clone, no overwrite, no orphan-prune), and only keeps the catalog entry current — so even a `--force` sync can never revert our edits. `tonone`, `servicegraph`, and `schedule-after-usage-reset` carry `curated: true` today; `hyperflow` does NOT — it is the completed off-ramp example (its frontmatter hardening merged upstream, so the flag was dropped in #1008). This guard exists because a prior `--force` run reverted ~100 A-graded agents back to 3-field upstream stubs — the ~18.9k-line deletion that motivated the whole model. Note `curated:` (we hardened it locally) and `verified:` (a maintainer vetted quality/trust) are orthogonal: all three curated sources are `curated: true` but `verified: false`, an honest state and exactly why the two flags are separate.\n\n**Pileup auto-close (≤1 open sync PR).** `sync-external.yml` runs a \"Close superseded sync PRs\" step before Create-PR: it closes older open `automation/sync-external-*` PRs (with `--delete-branch`), keeping at most one open sync PR. The safe unique-per-run-branch model (from the 691 audit, which fixed an earlier shared-branch clobber) is preserved — this only prunes the pileup that model produced.\n\n**How we upstream respectfully.** Want a plugin at our A-grade bar? We bring THEIR plugin to standard on THEIR repo: a friendly issue first (\"we featured your plugin and hardened its frontmatter to our A-grade bar — would you be open to a PR upstreaming it?\"), then a PR the contributor owns and merges. No surprise PRs; credit preserved; they decide. Once merged upstream, the mirror is A-grade naturally and `curated:` can be dropped. **Any contributor-facing post (issue or PR body) gets Jeremy's wording sign-off BEFORE posting.**\n\n## Plugin Structure\n\n**AI instruction plugins** (`plugins/[category]/[name]/`): `.claude-plugin/plugin.json` + `README.md` + optional `commands/*.md`, `agents/*.md`, `skills/[name]/SKILL.md`.\n\n**MCP server plugins** (`plugins/mcp/[name]/`): TypeScript source in `src/`, built to `dist/index.js` (must be executable: shebang + `chmod +x`).\n\n**Forge-generated plugins** include a `.forge/` audit trail dir (`research.md`, `ecosystem.md`, `proofs.md`) — build-time only, not used at runtime. Canonical example: `plugins/productivity/plane/`.\n\n### SKILL.md Required Frontmatter (marketplace tier — all 8 fields)\n\n```yaml\n---\nname: skill-name\ndescription: |\n  Capability summary. Use when ... Trigger with \"...\".\nallowed-tools: Read, Write, Edit, Bash(npm:*), Glob\nversion: 1.0.0\nauthor: Name <email>\nlicense: MIT\ncompatibility: Designed for Claude Code\ntags: [devops, ci]\n---\n```\n\nBeyond the 8 required fields, schema 3.5.0+ adds optional visibility-gating fields, 3.6.0+ adds self-declared config fields, and 3.7.0+ adds `disallowed-tools` — see the Optional frontmatter section below.\n\n`compatible-with` is deprecated. Migrate with: `python3 scripts/batch-remediate.py --migrate-compatible-with`\n\n**Agents use `disallowedTools` (camelCase denylist).** Skills use `allowed-tools` (allowlist) AND optionally `disallowed-tools` (kebab-case denylist, schema 3.7.0+). The two field names are intentionally different — do NOT use camelCase on skills or kebab-case on agents; the validator rejects either mismatch. Agent-only fields: `effort`, `maxTurns`.\n\n**Agent gate is kernel-strict (schema 3.10.0, NOT tier-gated).** Every authored agent must carry the kernel-floor 8 (`name, description, tools, model, color, version, author, tags`) plus the enterprise live set (`disallowedTools`, `skills`, `background`; + `hooks`, `mcpServers`, `permissionMode` on standalone agents) — all **errors** at every tier. Banned fields (`capabilities`, `expertise_level`, `activation_priority`, `type`, `category`, `compatible-with`, `when_to_use`) are errors; `fable` is an accepted model. **Corpus status (measured 2026-08-11, doc 721):** the advisory `--agents-only` lane recorded a baseline of **253 errors** across the agent corpus — the earlier \"all agents A-grade\" claim is retired until the lane is re-baselined clean; treat A-grade as the bar, not the current state. **Schema 3.11.0** added a body-vs-allowlist check: an agent whose body invokes `mcp__server__tool` not in its `tools` allowlist is an error (it would runtime-block). Validate with `--agents-only`.\n\n### Optional frontmatter (schema 3.5.0 / 3.6.0 / 3.7.0 — all default to off)\n\n- **Visibility gating (3.5.0):** `requires_env` / `requires_tools` / `fallback_for_env` / `fallback_for_tools` — list-of-strings. Skill hidden unless deps met; fallback form is the inverse. Cross-field overlap (`requires_X` + `fallback_for_X` of same value) is an ERROR.\n- **Self-declared config (3.6.0):** `required_environment_variables` (top-level list, each entry needs `name` + `prompt`) and `metadata.intent-solutions.config` (nested list, each entry needs `key` + `description` + `default`). Full reference: `000-docs/264-DR-GUID-skill-config-pattern.md`.\n- **Defense-in-depth disallow list (3.7.0):** `disallowed-tools` — kebab-case string or YAML list of tool patterns. Removes those tools from the model while the skill is active. Parallel to (not a replacement for) `allowed-tools`. Cross-field overlap with `allowed-tools` is an ERROR (mirrors the 3.5.0 visibility-gating overlap rule). Defense-in-depth for skills that legitimately need broad `allowed-tools` but should never reach for specific high-risk operations (`rm`, `curl`, `wget`, `.env` writes). Full reference: `000-docs/681-AT-ADEC-claude-code-platform-changelog-impact.md` § Change 1.\n- **NON-NEGOTIABLE:** these are optional. `ALWAYS_REQUIRED` is still the 8-field set above. See issue #612 + `000-docs/681-AT-ADEC-claude-code-platform-changelog-impact.md` § Implementation directives before proposing any change to required fields — the 8-field set is preserved; `disallowed-tools` is additive, not required.\n\n## CI gate architecture — three required checks (rebuilt 2026-07; skill-conform added 2026-07-23)\n\n**Branch protection on `main` requires THREE always-reporting contexts: `ci-required` + `gitleaks` + `skill-conform`** (GitHub Actions app; `strict:false`, `enforce_admins:false`, 1 approving review).\n\n- **`ci-required`** is the final job in `.github/workflows/validate-plugins.yml` — `if: always()`, `needs:` all 19 gate jobs (validate, verify, test, check-package-manager, marketplace-validation, cli-smoke-tests, shellcheck-skills, skill-codeblock-syntax, typescript-coverage-audit, eslint-check, format-check, ruff-check, ruff-format-check, markdownlint, scan-synced-content, promote-curated-check, check-submission-docs). It fails if any needed job ended `failure`/`cancelled`; a `skipped` result counts as PASS — legitimate **only** for a designed job-level `if:`.\n- **`gitleaks`** comes from `secret-scan.yml` (also unfiltered).\n- **`skill-conform`** is its **own** workflow (`.github/workflows/skill-conform.yml`) — `pnpm exec audit-harness conform --strict` over the full marketplace corpus. Always-reports (no path filter). **Never** folded into `ci-required`'s `needs:` (doc 110 § 5: a skippable/path-scoped job must not green the aggregate). Baseline after #1108/#1118: thousands PASS / 0 FAIL; remaining ADVISORY is the harness-side missing marketplace schema only.\n- **Advisory (never required):** `.github/workflows/skill-eval-advisory.yml` — j-rig behavioral eval on changed skills that already carry `eval-spec.yaml`. Kill-switch `vars.ENABLE_SKILL_EVAL=true` + same-repo guard + `MINIMAX_API_KEY`. Graduation to required needs Jeremy + ≥4-week clean flap window (doc 110).\n- **Ruff pin:** `validate-plugins.yml` installs **`ruff==0.15.22`** for both ruff-check and ruff-format-check. Unpinned install pulled 0.16.0 mid-2026-07-23 and treated SKILL.md fenced Python as format targets (~1132 files). Do not unpin without a deliberate corpus reformat.\n\n**Why, and the rules that keep it fixed (do not regress):** the previous 10-context required set sourced checks from path-filtered workflows, so a PR without matching files left them \"Expected\" forever and could never merge (the #778/#964 stuck-PR class).\n\n1. `validate-plugins.yml` runs on **every** `pull_request` — never add a `paths:` filter to it.\n2. **Never add a path-filtered workflow's context to the required-status set.** To make a new check blocking: add it as a job in `validate-plugins.yml` and list it in `ci-required`'s `needs:`.\n3. A job in the aggregate's `needs:` may only skip via a _designed_ `if:` — an undesigned skip silently passes the gate.\n4. The five split lint workflows (`lint-markdown/python/shell/typescript/skill-codeblocks.yml`) were retired 2026-07; their identically-named jobs live in `validate-plugins.yml`. Do not re-split them. `tests/ci/test_path_routing.py` pins this invariant.\n\n**Supply-chain gate:** `scan-synced-content` (the REFUSE/CHALLENGE/FLAG scanner over `plugins/**`, `scripts/scan-synced-content.mjs`) blocks via the aggregate. A `sources.yaml`-only PR scans zero files and deliberately fails with a **waivable** `sources-change-unscanned` CHALLENGE — a reviewer clears it with a `sources.yaml:sources-change-unscanned  <reason>` line in `scripts/scan-allowlist.txt` after confirming the source is vetted and pinned in `sources.lock.json`. REFUSE is never waivable.\n\n**Submission-docs intake gate:** `check-submission-docs` (`scripts/check-submission-docs.mjs`) blocks via the aggregate. A PR that adds a NEW plugin directory (its `.claude-plugin/plugin.json` is an added file in the diff) must ship the tiered submission documents per the matrix in `templates/skill-docs/README.md` (micro → `docs/PRD.md`; standard → + `docs/ADR.md`; pack, 2+ skills → + `docs/ONE-PAGER.md`; `CFO-ONE-PAGER.md` stays review-enforced — \"money is the pitch\" isn't deterministic). External mirror plugins (dir contains `.source.json`) are exempt — their docs live upstream. A PR adding no new plugin passes clean INSIDE the script (the designed skip), so the job always reports. Standard: `000-docs/700-DR-GUID-skill-submission-standard.md`.\n\n**Advisory lanes (report, never block — never promote into the required set from a side PR):** the two kernel lanes (next section); agent frontmatter (`validate-skills-schema.py --agents-only`, report-only with a tracked `REPORT-ONLY-UNTIL:` marker — corpus unbaselined); `.mcp.json` (`scripts/validate-mcp-config.mjs`, never `--strict` — that promotion belongs to the DR-049 soak checklist); CodeQL (PR trigger scoped to `packages/**` + `marketplace/src/**` so it adds no fan-out to plugin PRs); and the PR pre-screen (below).\n\n### AI review — Greptile is active and advisory; CI is the only merge gate\n\n**As of 2026-07-23 Greptile is active through the GitHub App and has reviewed recent CCPI PRs.** Its version-controlled policy lives under `.greptile/`; treat its findings as advisory semantic-review input, not a merge signal. Gemini Code Assist consumer product is **sunset** (bot posts a sunset notice only; `.gemini/config.yaml` has `code_review.disable: true`). Fully removing Apps is a UI/admin action. Optional future path: SHA-pinned MiniMax review (`MINIMAX_API_KEY` + `ENABLE_MINIMAX_REVIEW`) as already patterned in `minimax-review.yml`.\n\n**Operationally: never block a merge waiting for an AI review.** Required contexts are **`ci-required` + `gitleaks` + `skill-conform`**.\n\n### PR pre-screen (advisory respond leg)\n\n`pr-prescreen.yml` (`pull_request_target`; kill switch `vars.ENABLE_PR_PRESCREEN`) grades changed plugins with the pinned validator and responds in two low-noise ways: a **`prescreen-grade` commit status** on every run (advisory forever — never a required context) and **one upserted marker comment** only on `CHANGES_REQUESTED`/`HARD_BLOCK` (silent on PASS; re-runs edit the same comment). Two hard-won invariants:\n\n- **The validator anchors its scan root to its own script location** (`Path(__file__).resolve().parents[1]`), not the cwd. Prescreen therefore copies the BASE-authored validator into the PR tree and runs the copy — invoking `../base/scripts/…` directly grades **main's** tree and false-PASSes every frontmatter change (the 2026-07 bug, fixed in #980). Do not \"simplify\" this back.\n- **Never checkout or execute PR-authored code in a `pull_request_target` workflow.** Applies equally to `plane-sync.yml` (which runs on `pull_request_target` so fork-PR close-outs get secrets — it reads event context only).\n\n## Validation & the kernel SSoT — CI/CD posture\n\nTwo things grade frontmatter in this repo today, and the relationship between them is the load-bearing context to preserve.\n\n### The two validators\n\n- **Prose-spec validator (authoritative):** `scripts/validate-skills-schema.py`. This is the canonical gate. It runs at standard and marketplace tiers, it grades both frontmatter AND markdown body sections, and at marketplace tier a missing required field is an **ERROR** (not a warning). Its CI jobs block merges through the `ci-required` aggregate (see \"CI gate architecture\" above). `ALWAYS_REQUIRED` (the IS 8-field set) is hand-authored here and stays **AUTHORITATIVE** — read `000-docs/SCHEMA_CHANGELOG.md` § NON-NEGOTIABLES before touching it. The IS rubric sits on top of Anthropic's permissive spec; the marketplace tier is intentionally strict. Do not reduce the 8-field set, do not demote marketplace errors to warnings, and do not \"realign\" to Anthropic's floor — any change to required-fields / tier model / error-vs-warning semantics is approval-gated per that doc.\n\n- **Kernel machine-spec (the SSoT being migrated to):** `@intentsolutions/core` — its `schemas/authoring/v1` family (byte-frozen) plus the strict fork `authoring/v2` — is the single internal source of truth for \"what is a valid agent-native artifact.\" The kernel's `skill-frontmatter` schema encodes the **same** IS 8-field required set as a pure `allOf` of upstream-base + universal folds + the IS overlay. The plan of record is for `validate-skills-schema.py` to **consume the kernel folds** instead of its hand-rolled rule sets. That migration is in progress; the kernel pin is **exactly `0.9.0`** in `package.json` (no `^`/`~`) — currently **behind** the published `0.10.0`, see the staleness note below. The `authoring/v1` schema family is byte-frozen across kernel package versions, so a pin bump tracks the latest published kernel without changing the `authoring/v1` contract the shadow lane reads. Contract semantics for `authoring/v1` fields are canonical in the kernel's own changelog — cite it, do not duplicate it (see `000-docs/SCHEMA_CHANGELOG.md` § \"Kernel changelog citation\").\n\n### Two advisory lanes (never block) running the soak\n\nBoth are `continue-on-error: true`, neither is in the required-status set, and neither mutates anything:\n\n- **kernel-shadow soak** — `.github/workflows/kernel-shadow-validation.yml` + `scripts/kernel-shadow-validation.mjs`. Runs the kernel-pinned `skill-frontmatter` schema (from `@intentsolutions/core@0.9.0`) over the same SKILL.md corpus the prose-spec validator grades and logs per-file AGREE / DISAGREE deviation to `scripts/.kernel-shadow/report.json`. This is the DR-049 shadow soak (the \"zero-on-corpus shadow signal\"). The cutover-relevant number is the **frontmatter-scoped** deviation — a file that fails the prose-spec on missing `[body]` sections but has valid frontmatter is a scope difference, not a kernel gap, and is excluded.\n- **kernel-vendor-hash gate** — `.github/workflows/kernel-vendor-hash.yml` + `scripts/kernel-vendor-hash.mjs`. Enforces the version-coupling invariant **V ≤ C ≤ K** (vendored ≤ CCPI-declared ≤ kernel-latest) plus a ≤7-day staleness bound. Soak-aware: it reads the `0.9.0` pin, polices ordering/staleness only, and must never pressure a pin bump or change validator authority.\n\nThe validator itself does a kernel-loaded **shadow read** of `ALWAYS_REQUIRED` (`load_kernel_required()` / `--kernel-shadow`) — it compares the kernel's effective required set against the hand-authored one and reports drift. The hand-authored `ALWAYS_REQUIRED` stays authoritative; the shadow read is observational only.\n\n### Do-not-flip soak discipline (do not lose this)\n\n**The kernel pin and the authority flip are two SEPARATE axes — do not conflate them.** The pin is _intended_ to track the latest published kernel; bumping it keeps the shadow lane reading a current, byte-frozen `authoring/v1` contract and is a routine governance/coupling update, not an authority change.\n\n> ⚠️ **The pin is currently BEHIND (as of 2026-07-26).** Root pin is exactly `0.9.0` (no `^`/`~`) but `@intentsolutions/core@0.10.0` published 2026-07-09 — so the ≤7-day staleness bound has been breached since roughly 2026-07-16, and the `kernel-vendor-hash` daily sweep has been reporting `❌ VIOLATION: STALENESS` on every run. It is ADVISORY (exit 0), which is why it went unnoticed. Catching this up is a **lockstep** change: `@intentsolutions/jrig-cli@0.1.2` depends on `core@0.9.0` _exactly_, so core must move together with jrig-cli (`0.2.0`, published 2026-07-10) or the two resolve to separate un-hoisted copies of the kernel. Do not read the staleness report as pressure to flip authority — the two axes remain separate, and re-baselining the shadow-soak agreement numbers is part of the bump.\n\nWhat stays frozen is the **authority**: do **NOT** flip the kernel-shadow lane from advisory to authoritative (blocking) until ALL of these hold:\n\n1. ≥99.5% corpus agreement (deterministic folds must be 100%; the 0.5% band is reserved for non-deterministic surfaces only);\n2. ≥30 days of advisory soak;\n3. zero open P0 blockers;\n4. the Rekor superseding-event rollback protocol implemented and tested;\n5. governance sign-off from the CTO + CISO + VP-DevRel triple; and\n6. a ≥14-day public deprecation-window notice to affected skill authors.\n\nAs of now the soak has **not** met the bar — agreement sits below 99.5%, and the open disagreements are real tool-safety / shell-substitution security cases that the prose-spec validator correctly blocks (so flipping early would weaken a real gate). Until every condition above is satisfied, validator authority stays with `validate-skills-schema.py` and both kernel lanes stay advisory. Promotion to blocking is a separate, later cutover step gated by these conditions — never a side effect of an unrelated PR.\n\n**Alignment note (`@intentsolutions/jrig-cli`).** The `j-rig` behavioral-eval CLI is a root devDep pinned to **exactly `@intentsolutions/jrig-cli@0.1.2`**, which depends on **`@intentsolutions/core@0.9.0` (exact)** — the same version the **root** `@intentsolutions/core` pin carries — so they resolve to one shared root-hoisted copy and the kernel-shadow + kernel-vendor lanes read it directly. (The `0.1.2` cut carries the eval→Evidence-Bundle bridge `j-rig eval --emit-bundle` [jrig #172], a functional-exec `max_tokens` / length-truncation fix [jrig #173], `j-rig scaffold-spec` from a `SKILL.md` [jrig #174], and a judge-verdict recovery from truncated / fenced JSON that had inflated NO-SHIP [jrig #175]; it also retains the per-test-case `criteria_ids` scoping fix [jrig #162], so `pnpm exec j-rig eval` scopes each criterion to its own test case. A transitive dep, `@intentsolutions/refiner-core@0.2.0`, still peer-wants `core@^0.8.0`; pnpm surfaces that as a non-fatal warning until refiner-core widens its peer range.) The pin bump is a coupling update only; the authority flip and the root-pin cutover to `authoring/v2` remain the separate, gated steps above.\n\n### Validator consolidation (already landed)\n\nA recent cleanup removed 74 dead duplicate `validation.sh` stubs, collapsed previously-diverged secondary validators into delegating wrappers around the canonical `validate-skills-schema.py`, and added the kernel-loaded shadow read described above. There is now one canonical validator; secondary entry points delegate to it.\n\n### auto-bump posture for contributors\n\n`.github/workflows/auto-bump-on-pr.yml` auto-bumps changed plugins' patch versions on PRs (only on `plugins/**` / `packages/**` changes). For a docs-only or otherwise non-release PR, put **`[skip auto-bump]`** in the PR title or body so the auto-bumper steps aside. Minor/major bumps stay a deliberate human choice — hand-edit the version in the same PR. It stays on `pull_request` (not `pull_request_target`) by design — the bump needs a write token, which must never be handed to fork code; fork PRs are skipped cleanly, and a first-time fork contributor's queued \"Approve and run\" entry just no-ops when approved.\n\n## Adding a New Plugin\n\n**Hand-authored:** copy from `templates/`, add catalog entry to `marketplace.extended.json`, run `pnpm run sync-marketplace`, validate with `--marketplace`.\n\n**Forge-generated:** `/skill-creator --forge <api-name>` — runs 8-gate workflow, requires a NOI (Name of Identity), produces Grade-A skill + `.forge/` audit trail + catalog entry.\n\nTo regenerate against a current API: `/skill-creator --reforge <plugin-name>`.\n\n## Design System\n\nConstitution: `marketplace/DESIGN.md` (Data-Dense Pro family, locked 2026-05-06). If a component disagrees with it, the component is wrong.\n\nKey tokens (`marketplace/src/styles/tokens.css`): `--bg`, `--panel`, `--rule`, `--ink`, `--signal`. Old aliases (`--primary`, `--surface`, `--text`, `--border`) remain mapped for back-compat. CSS colors: **OKLCH only, never hex/rgb**.\n\nReject: gradients on cards, glassmorphism, drop-shadow stacks, `hover:scale-105` on whole cards.\n\n## Killer Skill of the Week\n\nEditorial — Jeremy picks manually. Tooling only syncs two render surfaces.\n\n```bash\n# Promote a new spotlight\nnode scripts/promote-spotlight.mjs path/to/new-spotlight.json\n\n# Sync README block only (no rotation)\nnode scripts/render-spotlight.mjs\n```\n\nSource of truth: `marketplace/src/data/spotlights.json`.\n\n## Key Identifiers — Do Not \"Normalize\"\n\n- **GitHub repo (canonical):** `jeremylongshore/claude-code-plugins-plus-skills`\n- **Marketplace catalog id:** `claude-code-plugins-plus`\n- **Public install slug:** `jeremylongshore/claude-code-plugins` (legacy, GitHub 301s to canonical — hardcoded in CLI, Hero snippet, hundreds of READMEs — renaming is a breaking API change)\n\n## Freshie Inventory\n\nCMDB with a hybrid storage model: `freshie/inventory.sqlite` is the **local\nruntime format** every tool reads/writes (UNTRACKED — the blob is out of git);\nthe **versioned system of record is Dolt**, exported by\n`freshie/scripts/dolt-sync.py` into `freshie/dolt/` (gitignored) and pushed to\npublic DoltHub `jeremylongshore/freshie-inventory` with a `run-N` tag per\ninventory run. The tracked compact export (`freshie/grades.csv` +\n`freshie/grade-histogram.json`) is regenerated by every sync — its git diff is\nthe \"skill X went B→A\" story.\n\nThe full cycle:\n\n```bash\npython3 freshie/scripts/rebuild-inventory.py                         # 1. New discovery run\npython3 scripts/validate-skills-schema.py --marketplace --populate-db freshie/inventory.sqlite  # 2. Compliance\npython3 freshie/scripts/dolt-sync.py                                 # 3. Dolt commit + tag + DoltHub push\npython3 freshie/scripts/promote-to-curated.py                        # 4. Refresh skills/.curated/ (skills.sh mirror)\nsqlite3 freshie/inventory.sqlite \"SELECT grade, COUNT(*) FROM skill_compliance GROUP BY grade;\"  # runtime queries\npython3 freshie/scripts/batch-remediate.py --dry-run && python3 freshie/scripts/batch-remediate.py --all --execute\n```\n\n**skills.sh curated mirror** (`freshie/scripts/promote-to-curated.py`): rebuilds\n`skills/.curated/` as a generated mirror of the repo's best **A+B** plugin skills (our own;\nexternal `.source.json` mirrors excluded → ~1,881) so skills.sh can index them — it only\ncrawls root `skills/` / `.curated/`, never `plugins/**/skills/`. The plugin skill stays the\nsource of truth; the mirror is wipe-and-rebuilt from the tracked `grades.csv` (not the\ngit-ignored `inventory.sqlite`, so the CI drift gate is reproducible), copies only\ngit-tracked files, and re-grades each candidate in-process (promote iff fresh grade still\nA/B). Audit trail: `skills/.curated/MANIFEST.json`. It is excluded from the README count\n(`generate-readme-toc.mjs`) and the inventory scan (`validate-skills-schema.py`\n`find_skill_files`) so a mirror copy is never double-counted. Self-maintaining:\n`promote-curated.yml` refreshes it weekly (PR on change, Slack-on-fail); the\n`promote-curated-check` gate in `ci-required` fails a PR that edits a promoted source\nwithout regenerating. Repo-page branding: root `skills.sh.json`.\n\nHistory queries go to Dolt (`cd freshie/dolt/freshie`): `WHERE run_id = N`,\n`AS OF 'run-N'`, `dolt diff run-7 run-8 --stat` — the run_id model is\nappend-only, so diffs between run tags show added rows, not cell changes.\nClone-free check: `curl \"https://www.dolthub.com/api/v1alpha1/jeremylongshore/freshie-inventory/main?q=SELECT+COUNT(*)+FROM+skill_compliance\"`.\n\n**Interactive/MCP history — the in-repo `dolt-mcp-vcs` plugin** (`plugins/mcp/dolt-mcp-vcs/`,\nregistered as this project's MCP server → freshie Dolt on `127.0.0.1:3308`). Use it to query the\nrun-over-run history conversationally instead of hand-writing `dolt sql`:\n\n- **Start the sql-server first** — the MCP client connects to a _running_ server; it is NOT\n  auto-started. From `freshie/dolt/freshie`: `dolt sql-server -H 127.0.0.1 -P 3308` (run\n  detached; log to a scratch path). Do NOT pass `-u`/`-p` — dolt ≥2 removed them from\n  `sql-server`; the default `root` is passwordless, matching the MCP config's `DOLT_PASSWORD=\"\"`.\n  Then load tools with `ToolSearch\nquery=\"select:mcp__dolt-mcp-vcs__query,mcp__dolt-mcp-vcs__list_dolt_commits,mcp__dolt-mcp-vcs__list_dolt_diff_changes_by_table_name\"`\n  — `query` for `AS OF 'run-N'` reads, the diff tools for per-run deltas; expert agents\n  `dolt-sync-advisor` / `bead-epic-auditor` / `dolt-mcp-vcs:beads-guru` are also available.\n- **⚠️ Stop the sql-server before `freshie/scripts/dolt-sync.py`** — both write\n  `freshie/dolt/freshie`; a live server holds the lock and the sync will clobber/deadlock. `kill\n<server-pid>`, sync, then restart if you still need it.\n- **Mutation gate**: destructive verbs (`push`/`merge`/`reset`/`branch-delete`) are\n  **recommend-only** — the plugin surfaces them but won't execute, so DoltHub pushes still go\n  through the one-way `dolt-sync.py` exporter, never the MCP.\n\n**Rules:** local is the sole writer — never merge DoltHub PRs or web-edit the\npublic database (the exporter is one-way and will clobber them). A failed\nDoltHub push exits non-zero on purpose: until pushed, Dolt history is\nsingle-copy on this box. Exporter unit tests: `python3 -m unittest\ntests.test_dolt_sync`. Full details + restore path: `freshie/README.md`.\n\nKey tables: `skill_compliance` (scores, grades, JRig columns), `forge_proofs` (drives JRig-Verified badges on plugin detail pages — `enrich-jrig-data.mjs` preserves the committed `jrig-data.json` when the local DB is absent, e.g. in CI).\n\n## npm Publish Pipeline\n\nPatch version bumps happen automatically on PR (via `auto-bump-on-pr.yml`). For minor/major bumps, hand-edit the version in the same PR. Merge to main triggers publish + tag + GitHub Release via `publish-changed-packages.yml`. See `RELEASING.md` for the full operator flow.\n\n<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:7510c1e2 -->\n\n## Beads Issue Tracker\n\nThis project uses **bd (beads)** for issue tracking. Run `bd prime` to see full workflow context and commands.\n\n### Quick Reference\n\n```bash\nbd ready              # Find available work\nbd show <id>          # View issue details\nbd update <id> --claim  # Claim work\nbd close <id>         # Complete work\n```\n\n### Rules\n\n- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists\n- Run `bd prime` for detailed command reference and session close protocol\n- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files\n\n**Architecture in one line:** issues live in a local Dolt DB; sync uses `refs/dolt/data` on your git remote; `.beads/issues.jsonl` is a passive export. See https://github.com/gastownhall/beads/blob/main/docs/SYNC_CONCEPTS.md for details and anti-patterns.\n\n## Session Completion\n\n**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.\n\n**MANDATORY WORKFLOW:**\n\n1. **File issues for remaining work** - Create issues for anything that needs follow-up\n2. **Run quality gates** (if code changed) - Tests, linters, builds\n3. **Update issue status** - Close finished work, update in-progress items\n4. **PUSH TO REMOTE** - This is MANDATORY:\n\n   ```bash\n   git pull --rebase\n   git push\n   git status  # MUST show \"up to date with origin\"\n   ```\n\n5. **Clean up** - Clear stashes, prune remote branches\n6. **Verify** - All changes committed AND pushed\n7. **Hand off** - Provide context for next session\n\n**CRITICAL RULES:**\n\n- Work is NOT complete until `git push` succeeds\n- NEVER stop before pushing - that leaves work stranded locally\n- NEVER say \"ready to push when you are\" - YOU must push\n- If push fails, resolve and retry until it succeeds\n<!-- END BEADS INTEGRATION -->\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# Repository Guidelines\n\n## Project Structure\n\nThis is the Tons of Skills Claude Code plugin marketplace. Author plugins under `plugins/<category>/<plugin-name>/`; a plugin commonly contains `skills/`, `commands/`, `.claude-plugin/plugin.json`, and a README. The editable catalog is `.claude-plugin/marketplace.extended.json`; its `marketplace.json`, generated plugin `package.json` files, and the README table of contents are derived. Shared tooling lives in `scripts/`, workspace packages in `packages/`, Python regression tests in `tests/`, and the Astro site in `marketplace/`.\n\n## Build, Test, and Development\n\nUse Node 20+ and pnpm 9.15.9+ at the repository root; `marketplace/` deliberately uses npm.\n\n```bash\npnpm install\n./scripts/quick-test.sh                 # fast repository sanity check\npnpm test && pnpm typecheck && pnpm lint\npnpm run verify                         # CI-equivalent verification pipeline\npnpm run sync-marketplace               # regenerate catalog-derived files\ncd marketplace && npm run dev           # local Astro site, port 4321\ncd marketplace && npx playwright test   # website end-to-end tests\n```\n\nDo not hand-edit generated catalog artifacts. Run `pnpm run sync-marketplace` before committing catalog or plugin changes. Validate skill metadata with `python3 scripts/validate-skills-schema.py --marketplace --verbose`; use `python3 scripts/validate-unicode-hygiene.py` for changed skill content.\n\n## Style and Naming\n\nFollow the existing file’s style; use Prettier for JavaScript, TypeScript, JSON, YAML, and Markdown (`pnpm run format:check`) and ESLint (`pnpm lint`) for code. Use two-space indentation in JS/TS and JSON. Name plugin folders lowercase kebab-case (for example, `plugins/mcp/example-plugin`) and skills as `skills/<skill-name>/SKILL.md`. Keep frontmatter compliant with the schema validator rather than inventing local variants.\n\n## Tests\n\nAdd or update focused tests beside the affected package or in `tests/`; Python tests use `test_*.py` and TypeScript tests commonly use `*.test.ts`. Run the narrowest relevant test first, then the commands above. Changes to validators, schemas, or catalog generation require their targeted regression suite plus the marketplace schema validation.\n\n## Commits and Pull Requests\n\nUse Conventional Commit-style subjects visible in history, such as `fix(ci): harden validation` or `docs(contributing): clarify workflow`. Keep each commit scoped. PRs should explain the user-facing change, link the beads issue, include screenshots for visual site changes, and include regenerated derived files when applicable. Use `bd` for task tracking: run `bd ready`, claim the issue, and close it when complete. Before finishing, commit, pull/rebase, run `bd sync`, push, and confirm `git status` is up to date.\n\n## Merge gates (do not weaken)\n\nRequired branch-protection contexts on `main`: **`ci-required`**, **`gitleaks`**, **`skill-conform`**.\n\n- `skill-conform` is a **separate** always-report workflow (`audit-harness conform --strict`). Never add it (or any path-scoped / provider-dependent job) to `ci-required`'s `needs:`.\n- Behavioral skill eval (`skill-eval-advisory.yml`) is **advisory only** until explicitly graduated.\n- Full gate architecture, validator SSoT rules, and non-negotiables: see `CLAUDE.md`.\n","category":"root","tokens":825},{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Repository Overview\n\nTons of Skills — Claude Code plugins marketplace. Live at https://tonsofskills.com\n\n**Runtime:** Node `>=20.0.0`, pnpm `>=9.15.9`. Node 18 causes silent workspace-resolution failures.\n\n**Package manager:** `pnpm` everywhere **except** `marketplace/` which uses `npm` (CI-enforced).\n\n**Contributor guidelines live in `AGENTS.md`** — project structure, build/test/dev commands, style and naming, test conventions, commit/PR expectations, and the merge gates. Read it before starting work. (Session protocol lives in this file: the beads workflow in § Beads Issue Tracker — where `bd prime` is also the post-compaction context-recovery step — and the end-of-session push checklist in § Session Completion.)\n\n## Cross-session coordination — another Claude session may be in this repo\n\nThis repo is frequently worked in **parallel** with the `intent-eval-platform` umbrella session (that platform's CCPI validator + jrig-cli + kernel reach into this repo). Sessions are separate processes that share only the filesystem, so stay in sync via the shared surfaces:\n\n- **Read + append the shared journal** on cross-repo work: `~/000-projects/CROSS-SESSION-LOG.md` (append a dated line: what / branch or PR# / status).\n- **Durable cross-cutting tasks:** umbrella beads `~/000-projects/.beads/`, label `cross-session` (`bd list --label cross-session`).\n- **Guard the working tree:** this repo has ONE checkout; a concurrent session can `git checkout`/`reset` it out from under you and **wipe UNCOMMITTED work** (happened 2026-07-01). Commit early, or do multi-step file work in a `git worktree`.\n\nFull protocol (loaded by every session under `/home/jeremy`): `/home/jeremy/CLAUDE.md` § \"Cross-session coordination\".\n\n## Essential Commands\n\n```bash\n# Before ANY commit — regenerates marketplace.json, plugin package.jsons, README TOC\npnpm run sync-marketplace\n\n# Quick sanity check (~30s)\n./scripts/quick-test.sh\n\n# Build & test\npnpm install && pnpm build\npnpm test && pnpm typecheck\npnpm lint\npnpm run verify                   # Full pipeline — what CI's `verify` job runs\n\n# Validator (schema 4.0.0 — see 000-docs/SCHEMA_CHANGELOG.md)\npython3 scripts/validate-skills-schema.py --verbose\npython3 scripts/validate-skills-schema.py --marketplace --verbose\npython3 scripts/validate-skills-schema.py --marketplace --populate-db freshie/inventory.sqlite\npython3 scripts/validate-skills-schema.py --agents-only --verbose   # agents only (kernel-strict gate)\n\n# Unicode hygiene gate — Trapdoor / Trojan Source defense for SKILL.md /\n# plugin.json / agent / command files. Default mode blocks on tag chars\n# (U+E0000-E007F) + bidi overrides (CVE-2021-42574). --strict also blocks\n# on zero-width / format chars outside the BOM position.\npython3 scripts/validate-unicode-hygiene.py\npython3 scripts/validate-unicode-hygiene.py --strict           # tighter\npython3 scripts/validate-unicode-hygiene.py path/to/file.md    # one file\npython3 -m unittest tests.test_validate_unicode_hygiene -v     # regression suite\n\n# Marketplace website\ncd marketplace/ && npm run dev    # localhost:4321\ncd marketplace/ && npm run build\ncd marketplace/ && npx playwright test\n\n# Single test\ncd packages/cli && pnpm test -- --grep \"pattern\"\n\n# JRig behavioral eval — the published @intentsolutions/jrig-cli (bin `j-rig`),\n# pinned as a root devDep. Invoke via `pnpm exec j-rig` so it resolves the\n# repo's pinned version (node_modules/.bin/j-rig), NOT a global shim.\npnpm exec j-rig --version         # → 0.1.2 (the real 7-layer CLI)\npnpm exec j-rig check <skill-dir> # Tier 3A: deterministic (~seconds, free, no API key, no DB)\n\n# Real behavioral eval (opt-in, ~$2-5/skill) — needs the native better-sqlite3\n# build (run `pnpm rebuild better-sqlite3` once; the build script is not\n# auto-run on install). ALWAYS route through the wrapper — it runs j-rig\n# against a /dev/shm scratch DB and records the verdict into forge_proofs via\n# scripts/record-jrig-proofs.mjs. NEVER pass freshie/inventory.sqlite to\n# `j-rig eval --db` directly: j-rig writes its own run tables into whatever\n# --db it is given, which contaminates the tracked CMDB (and, pre-allowlist,\n# leaked those tables to the public DoltHub record).\nscripts/run-jrig-eval.sh --skill-dir <skill-dir> --plugin <catalog-name> \\\n  --inventory-db freshie/inventory.sqlite\n# DEEPSEEK_API_KEY is SOPS-decrypted in-process by the wrapper\n# (intent-eval-lab/.env.sops; see the IEP umbrella CLAUDE.md credential\n# table). Defaults: --provider deepseek --models deepseek-v4-flash — a real\n# behavioral provider, this is ground truth; other providers (haiku/sonnet/\n# opus via Anthropic, etc.) remain available via --provider/--models.\n```\n\n## Two Catalog System — Critical\n\n| File                                       | Purpose                        | Edit?     |\n| ------------------------------------------ | ------------------------------ | --------- |\n| `.claude-plugin/marketplace.extended.json` | Source of truth                | **Yes**   |\n| `.claude-plugin/marketplace.json`          | CLI-compatible, auto-generated | **Never** |\n\n`pnpm run sync-marketplace` regenerates all three derived artifacts: `marketplace.json`, any missing `plugins/**/package.json` files, and the `README.md` AUTO-TOC block. The pre-commit hook runs this automatically when `marketplace.extended.json` is staged.\n\nCI fails if any derived file is out of sync. Never hand-edit auto-generated files.\n\n## Marketplace Build Pipeline\n\n`npm run build` in `marketplace/` runs 7 sequential steps via `scripts/build.mjs`: discover-skills → extract-readme-sections → sync-catalog → enrich-jrig-data → generate-unified-search → build-cowork-zips → astro build.\n\n`discover-skills.mjs` emits two artifacts (schema 3.4.0+): `skills-index.json` (L0, ~97 KB gzipped, metadata only — for trigger-match / browse) and `skills-catalog.json` (L1, ~5.5 MB gzipped, full body HTML). Both carry top-level `schemaVersion` + `level` fields. CLI flag `--level=metadata|full|file` (default `full`).\n\n**Gotcha:** `compressHTML` is disabled in `astro.config.mjs` — iOS Safari fails on lines > 5000 chars. CI enforces this.\n\nPerformance budgets (CI-enforced): 40 MB total gzipped, 1 MB largest file, < 30s build, 2,800–4,000 routes.\n\n## Auto-cowork contract\n\n**Author flow.** Add a plugin to `.claude-plugin/marketplace.extended.json` and run `pnpm run sync-marketplace`. That is the entire authoring step. The pre-commit hook regenerates `marketplace.json`, plugin `package.json`s, and the README AUTO-TOC. There is no separate \"update the cowork page\" step.\n\n**Pipeline (deterministic from the catalog).** `cd marketplace && npm run build` runs `scripts/build.mjs`, which on every invocation:\n\n1. `cowork:zips` (`scripts/build-cowork-zips.mjs`) — wipes `marketplace/public/downloads/{plugins,bundles}` and rebuilds them from `marketplace.extended.json`. Produces individual plugin zips, category bundle zips, the mega-zip, `downloads/manifest.json`, and the Astro-consumed `marketplace/src/data/cowork-manifest.json`. Skips `category: mcp` entries (MCP plugins do not appear in cowork).\n2. `cowork:validate` (`scripts/validate-cowork-manifest.mjs`) — drift gate. Fails the build if catalog ↔ manifest ↔ disk fall out of alignment (orphan zips, missing entries, or stale manifest rows). Runs again in CI as a discrete step in `.github/workflows/validate-plugins.yml` so the failure signal is clearly named.\n3. `astro build` — copies `marketplace/public/` → `marketplace/dist/`. The `/cowork/` page reads `cowork-manifest.json` at build time and renders the download grid.\n\n**Deploy propagates the wipe.** The VPS force-command script `/usr/local/sbin/deploy-tonsofskills` ends with `rsync -a --delete /srv/tonsofskills/build/marketplace/dist/ /srv/tonsofskills/dist/`, so orphan files removed by the cowork build are also pruned from the served `dist/`. Current deployment authority is `intent-os/ops/deploy/`.\n\n**Don't commit downloads/.** `marketplace/public/downloads/` is gitignored (see `.gitignore:146`). CI checks out fresh and rebuilds from scratch — local state cannot leak to prod. Never commit or hand-edit anything under that directory.\n\n**Don't wire cowork build into `sync-marketplace`.** `sync-marketplace` is the fast (<2s) per-commit hook; `cowork:zips` is the slow (~30s) per-build step. They run on different cadences by design.\n\n## External Plugin Sync (mirror-by-default)\n\nAdopted model: **mirror by default · upstream improvements · never clobber.** Decision record: `000-docs/694-AT-DECR-external-sync-mirror-by-default-model.md`; pipeline audit + hardening: `000-docs/691-AT-AUDT-sync-external-pipeline-audit-and-hardening.md`.\n\n**Scale first — external is a minority augment, not the core.** ~470 plugins total (per `marketplace.extended.json`), but only 63 are externally synced (57 third-party sources + 6 of Jeremy's own repos, per `sources.yaml`). The other ~407 (~87%) are in-repo Intent Solutions work. The sync is a curated side-channel, not the marketplace — treat external contributors as a respected minority augment, never the center of gravity.\n\n**How sync works.** `sources.yaml` registers each external source. `.github/workflows/sync-external.yml` runs weekly (Mondays 06:00 UTC) and on demand (`workflow_dispatch` / `repository_dispatch`), invoking `scripts/sync-external.mjs` to mirror a source's files into `plugins/` and open an automated PR. A human reviews every auto-PR — historically ~1 in 10 sync PRs merges. The contributor's own repo is the source of truth; we do NOT locally edit a pure-mirror plugin.\n\n**Mirror vs curate.** Default is a pure mirror — the upstream repo governs, and improvements flow by upstreaming (see below), so the mirror becomes A-grade naturally with nothing to revert. Only when we deliberately harden a plugin past its upstream do we mark it `curated:` and freeze it.\n\n**Never-clobber guard (`curated:` freeze).** A source with `curated: true` in `sources.yaml` is FROZEN: `sync-external.mjs` logs `Curated — mirror frozen`, writes no files (no clone, no overwrite, no orphan-prune), and only keeps the catalog entry current — so even a `--force` sync can never revert our edits. `tonone`, `servicegraph`, and `schedule-after-usage-reset` carry `curated: true` today; `hyperflow` does NOT — it is the completed off-ramp example (its frontmatter hardening merged upstream, so the flag was dropped in #1008). This guard exists because a prior `--force` run reverted ~100 A-graded agents back to 3-field upstream stubs — the ~18.9k-line deletion that motivated the whole model. Note `curated:` (we hardened it locally) and `verified:` (a maintainer vetted quality/trust) are orthogonal: all three curated sources are `curated: true` but `verified: false`, an honest state and exactly why the two flags are separate.\n\n**Pileup auto-close (≤1 open sync PR).** `sync-external.yml` runs a \"Close superseded sync PRs\" step before Create-PR: it closes older open `automation/sync-external-*` PRs (with `--delete-branch`), keeping at most one open sync PR. The safe unique-per-run-branch model (from the 691 audit, which fixed an earlier shared-branch clobber) is preserved — this only prunes the pileup that model produced.\n\n**How we upstream respectfully.** Want a plugin at our A-grade bar? We bring THEIR plugin to standard on THEIR repo: a friendly issue first (\"we featured your plugin and hardened its frontmatter to our A-grade bar — would you be open to a PR upstreaming it?\"), then a PR the contributor owns and merges. No surprise PRs; credit preserved; they decide. Once merged upstream, the mirror is A-grade naturally and `curated:` can be dropped. **Any contributor-facing post (issue or PR body) gets Jeremy's wording sign-off BEFORE posting.**\n\n## Plugin Structure\n\n**AI instruction plugins** (`plugins/[category]/[name]/`): `.claude-plugin/plugin.json` + `README.md` + optional `commands/*.md`, `agents/*.md`, `skills/[name]/SKILL.md`.\n\n**MCP server plugins** (`plugins/mcp/[name]/`): TypeScript source in `src/`, built to `dist/index.js` (must be executable: shebang + `chmod +x`).\n\n**Forge-generated plugins** include a `.forge/` audit trail dir (`research.md`, `ecosystem.md`, `proofs.md`) — build-time only, not used at runtime. Canonical example: `plugins/productivity/plane/`.\n\n### SKILL.md Required Frontmatter (marketplace tier — all 8 fields)\n\n```yaml\n---\nname: skill-name\ndescription: |\n  Capability summary. Use when ... Trigger with \"...\".\nallowed-tools: Read, Write, Edit, Bash(npm:*), Glob\nversion: 1.0.0\nauthor: Name <email>\nlicense: MIT\ncompatibility: Designed for Claude Code\ntags: [devops, ci]\n---\n```\n\nBeyond the 8 required fields, schema 3.5.0+ adds optional visibility-gating fields, 3.6.0+ adds self-declared config fields, and 3.7.0+ adds `disallowed-tools` — see the Optional frontmatter section below.\n\n`compatible-with` is deprecated. Migrate with: `python3 scripts/batch-remediate.py --migrate-compatible-with`\n\n**Agents use `disallowedTools` (camelCase denylist).** Skills use `allowed-tools` (allowlist) AND optionally `disallowed-tools` (kebab-case denylist, schema 3.7.0+). The two field names are intentionally different — do NOT use camelCase on skills or kebab-case on agents; the validator rejects either mismatch. Agent-only fields: `effort`, `maxTurns`.\n\n**Agent gate is kernel-strict (schema 3.10.0, NOT tier-gated).** Every authored agent must carry the kernel-floor 8 (`name, description, tools, model, color, version, author, tags`) plus the enterprise live set (`disallowedTools`, `skills`, `background`; + `hooks`, `mcpServers`, `permissionMode` on standalone agents) — all **errors** at every tier. Banned fields (`capabilities`, `expertise_level`, `activation_priority`, `type`, `category`, `compatible-with`, `when_to_use`) are errors; `fable` is an accepted model. **Corpus status (measured 2026-08-11, doc 721):** the advisory `--agents-only` lane recorded a baseline of **253 errors** across the agent corpus — the earlier \"all agents A-grade\" claim is retired until the lane is re-baselined clean; treat A-grade as the bar, not the current state. **Schema 3.11.0** added a body-vs-allowlist check: an agent whose body invokes `mcp__server__tool` not in its `tools` allowlist is an error (it would runtime-block). Validate with `--agents-only`.\n\n### Optional frontmatter (schema 3.5.0 / 3.6.0 / 3.7.0 — all default to off)\n\n- **Visibility gating (3.5.0):** `requires_env` / `requires_tools` / `fallback_for_env` / `fallback_for_tools` — list-of-strings. Skill hidden unless deps met; fallback form is the inverse. Cross-field overlap (`requires_X` + `fallback_for_X` of same value) is an ERROR.\n- **Self-declared config (3.6.0):** `required_environment_variables` (top-level list, each entry needs `name` + `prompt`) and `metadata.intent-solutions.config` (nested list, each entry needs `key` + `description` + `default`). Full reference: `000-docs/264-DR-GUID-skill-config-pattern.md`.\n- **Defense-in-depth disallow list (3.7.0):** `disallowed-tools` — kebab-case string or YAML list of tool patterns. Removes those tools from the model while the skill is active. Parallel to (not a replacement for) `allowed-tools`. Cross-field overlap with `allowed-tools` is an ERROR (mirrors the 3.5.0 visibility-gating overlap rule). Defense-in-depth for skills that legitimately need broad `allowed-tools` but should never reach for specific high-risk operations (`rm`, `curl`, `wget`, `.env` writes). Full reference: `000-docs/681-AT-ADEC-claude-code-platform-changelog-impact.md` § Change 1.\n- **NON-NEGOTIABLE:** these are optional. `ALWAYS_REQUIRED` is still the 8-field set above. See issue #612 + `000-docs/681-AT-ADEC-claude-code-platform-changelog-impact.md` § Implementation directives before proposing any change to required fields — the 8-field set is preserved; `disallowed-tools` is additive, not required.\n\n## CI gate architecture — three required checks (rebuilt 2026-07; skill-conform added 2026-07-23)\n\n**Branch protection on `main` requires THREE always-reporting contexts: `ci-required` + `gitleaks` + `skill-conform`** (GitHub Actions app; `strict:false`, `enforce_admins:false`, 1 approving review).\n\n- **`ci-required`** is the final job in `.github/workflows/validate-plugins.yml` — `if: always()`, `needs:` all 19 gate jobs (validate, verify, test, check-package-manager, marketplace-validation, cli-smoke-tests, shellcheck-skills, skill-codeblock-syntax, typescript-coverage-audit, eslint-check, format-check, ruff-check, ruff-format-check, markdownlint, scan-synced-content, promote-curated-check, check-submission-docs). It fails if any needed job ended `failure`/`cancelled`; a `skipped` result counts as PASS — legitimate **only** for a designed job-level `if:`.\n- **`gitleaks`** comes from `secret-scan.yml` (also unfiltered).\n- **`skill-conform`** is its **own** workflow (`.github/workflows/skill-conform.yml`) — `pnpm exec audit-harness conform --strict` over the full marketplace corpus. Always-reports (no path filter). **Never** folded into `ci-required`'s `needs:` (doc 110 § 5: a skippable/path-scoped job must not green the aggregate). Baseline after #1108/#1118: thousands PASS / 0 FAIL; remaining ADVISORY is the harness-side missing marketplace schema only.\n- **Advisory (never required):** `.github/workflows/skill-eval-advisory.yml` — j-rig behavioral eval on changed skills that already carry `eval-spec.yaml`. Kill-switch `vars.ENABLE_SKILL_EVAL=true` + same-repo guard + `MINIMAX_API_KEY`. Graduation to required needs Jeremy + ≥4-week clean flap window (doc 110).\n- **Ruff pin:** `validate-plugins.yml` installs **`ruff==0.15.22`** for both ruff-check and ruff-format-check. Unpinned install pulled 0.16.0 mid-2026-07-23 and treated SKILL.md fenced Python as format targets (~1132 files). Do not unpin without a deliberate corpus reformat.\n\n**Why, and the rules that keep it fixed (do not regress):** the previous 10-context required set sourced checks from path-filtered workflows, so a PR without matching files left them \"Expected\" forever and could never merge (the #778/#964 stuck-PR class).\n\n1. `validate-plugins.yml` runs on **every** `pull_request` — never add a `paths:` filter to it.\n2. **Never add a path-filtered workflow's context to the required-status set.** To make a new check blocking: add it as a job in `validate-plugins.yml` and list it in `ci-required`'s `needs:`.\n3. A job in the aggregate's `needs:` may only skip via a _designed_ `if:` — an undesigned skip silently passes the gate.\n4. The five split lint workflows (`lint-markdown/python/shell/typescript/skill-codeblocks.yml`) were retired 2026-07; their identically-named jobs live in `validate-plugins.yml`. Do not re-split them. `tests/ci/test_path_routing.py` pins this invariant.\n\n**Supply-chain gate:** `scan-synced-content` (the REFUSE/CHALLENGE/FLAG scanner over `plugins/**`, `scripts/scan-synced-content.mjs`) blocks via the aggregate. A `sources.yaml`-only PR scans zero files and deliberately fails with a **waivable** `sources-change-unscanned` CHALLENGE — a reviewer clears it with a `sources.yaml:sources-change-unscanned  <reason>` line in `scripts/scan-allowlist.txt` after confirming the source is vetted and pinned in `sources.lock.json`. REFUSE is never waivable.\n\n**Submission-docs intake gate:** `check-submission-docs` (`scripts/check-submission-docs.mjs`) blocks via the aggregate. A PR that adds a NEW plugin directory (its `.claude-plugin/plugin.json` is an added file in the diff) must ship the tiered submission documents per the matrix in `templates/skill-docs/README.md` (micro → `docs/PRD.md`; standard → + `docs/ADR.md`; pack, 2+ skills → + `docs/ONE-PAGER.md`; `CFO-ONE-PAGER.md` stays review-enforced — \"money is the pitch\" isn't deterministic). External mirror plugins (dir contains `.source.json`) are exempt — their docs live upstream. A PR adding no new plugin passes clean INSIDE the script (the designed skip), so the job always reports. Standard: `000-docs/700-DR-GUID-skill-submission-standard.md`.\n\n**Advisory lanes (report, never block — never promote into the required set from a side PR):** the two kernel lanes (next section); agent frontmatter (`validate-skills-schema.py --agents-only`, report-only with a tracked `REPORT-ONLY-UNTIL:` marker — corpus unbaselined); `.mcp.json` (`scripts/validate-mcp-config.mjs`, never `--strict` — that promotion belongs to the DR-049 soak checklist); CodeQL (PR trigger scoped to `packages/**` + `marketplace/src/**` so it adds no fan-out to plugin PRs); and the PR pre-screen (below).\n\n### AI review — Greptile is active and advisory; CI is the only merge gate\n\n**As of 2026-07-23 Greptile is active through the GitHub App and has reviewed recent CCPI PRs.** Its version-controlled policy lives under `.greptile/`; treat its findings as advisory semantic-review input, not a merge signal. Gemini Code Assist consumer product is **sunset** (bot posts a sunset notice only; `.gemini/config.yaml` has `code_review.disable: true`). Fully removing Apps is a UI/admin action. Optional future path: SHA-pinned MiniMax review (`MINIMAX_API_KEY` + `ENABLE_MINIMAX_REVIEW`) as already patterned in `minimax-review.yml`.\n\n**Operationally: never block a merge waiting for an AI review.** Required contexts are **`ci-required` + `gitleaks` + `skill-conform`**.\n\n### PR pre-screen (advisory respond leg)\n\n`pr-prescreen.yml` (`pull_request_target`; kill switch `vars.ENABLE_PR_PRESCREEN`) grades changed plugins with the pinned validator and responds in two low-noise ways: a **`prescreen-grade` commit status** on every run (advisory forever — never a required context) and **one upserted marker comment** only on `CHANGES_REQUESTED`/`HARD_BLOCK` (silent on PASS; re-runs edit the same comment). Two hard-won invariants:\n\n- **The validator anchors its scan root to its own script location** (`Path(__file__).resolve().parents[1]`), not the cwd. Prescreen therefore copies the BASE-authored validator into the PR tree and runs the copy — invoking `../base/scripts/…` directly grades **main's** tree and false-PASSes every frontmatter change (the 2026-07 bug, fixed in #980). Do not \"simplify\" this back.\n- **Never checkout or execute PR-authored code in a `pull_request_target` workflow.** Applies equally to `plane-sync.yml` (which runs on `pull_request_target` so fork-PR close-outs get secrets — it reads event context only).\n\n## Validation & the kernel SSoT — CI/CD posture\n\nTwo things grade frontmatter in this repo today, and the relationship between them is the load-bearing context to preserve.\n\n### The two validators\n\n- **Prose-spec validator (authoritative):** `scripts/validate-skills-schema.py`. This is the canonical gate. It runs at standard and marketplace tiers, it grades both frontmatter AND markdown body sections, and at marketplace tier a missing required field is an **ERROR** (not a warning). Its CI jobs block merges through the `ci-required` aggregate (see \"CI gate architecture\" above). `ALWAYS_REQUIRED` (the IS 8-field set) is hand-authored here and stays **AUTHORITATIVE** — read `000-docs/SCHEMA_CHANGELOG.md` § NON-NEGOTIABLES before touching it. The IS rubric sits on top of Anthropic's permissive spec; the marketplace tier is intentionally strict. Do not reduce the 8-field set, do not demote marketplace errors to warnings, and do not \"realign\" to Anthropic's floor — any change to required-fields / tier model / error-vs-warning semantics is approval-gated per that doc.\n\n- **Kernel machine-spec (the SSoT being migrated to):** `@intentsolutions/core` — its `schemas/authoring/v1` family (byte-frozen) plus the strict fork `authoring/v2` — is the single internal source of truth for \"what is a valid agent-native artifact.\" The kernel's `skill-frontmatter` schema encodes the **same** IS 8-field required set as a pure `allOf` of upstream-base + universal folds + the IS overlay. The plan of record is for `validate-skills-schema.py` to **consume the kernel folds** instead of its hand-rolled rule sets. That migration is in progress; the kernel pin is **exactly `0.9.0`** in `package.json` (no `^`/`~`) — currently **behind** the published `0.10.0`, see the staleness note below. The `authoring/v1` schema family is byte-frozen across kernel package versions, so a pin bump tracks the latest published kernel without changing the `authoring/v1` contract the shadow lane reads. Contract semantics for `authoring/v1` fields are canonical in the kernel's own changelog — cite it, do not duplicate it (see `000-docs/SCHEMA_CHANGELOG.md` § \"Kernel changelog citation\").\n\n### Two advisory lanes (never block) running the soak\n\nBoth are `continue-on-error: true`, neither is in the required-status set, and neither mutates anything:\n\n- **kernel-shadow soak** — `.github/workflows/kernel-shadow-validation.yml` + `scripts/kernel-shadow-validation.mjs`. Runs the kernel-pinned `skill-frontmatter` schema (from `@intentsolutions/core@0.9.0`) over the same SKILL.md corpus the prose-spec validator grades and logs per-file AGREE / DISAGREE deviation to `scripts/.kernel-shadow/report.json`. This is the DR-049 shadow soak (the \"zero-on-corpus shadow signal\"). The cutover-relevant number is the **frontmatter-scoped** deviation — a file that fails the prose-spec on missing `[body]` sections but has valid frontmatter is a scope difference, not a kernel gap, and is excluded.\n- **kernel-vendor-hash gate** — `.github/workflows/kernel-vendor-hash.yml` + `scripts/kernel-vendor-hash.mjs`. Enforces the version-coupling invariant **V ≤ C ≤ K** (vendored ≤ CCPI-declared ≤ kernel-latest) plus a ≤7-day staleness bound. Soak-aware: it reads the `0.9.0` pin, polices ordering/staleness only, and must never pressure a pin bump or change validator authority.\n\nThe validator itself does a kernel-loaded **shadow read** of `ALWAYS_REQUIRED` (`load_kernel_required()` / `--kernel-shadow`) — it compares the kernel's effective required set against the hand-authored one and reports drift. The hand-authored `ALWAYS_REQUIRED` stays authoritative; the shadow read is observational only.\n\n### Do-not-flip soak discipline (do not lose this)\n\n**The kernel pin and the authority flip are two SEPARATE axes — do not conflate them.** The pin is _intended_ to track the latest published kernel; bumping it keeps the shadow lane reading a current, byte-frozen `authoring/v1` contract and is a routine governance/coupling update, not an authority change.\n\n> ⚠️ **The pin is currently BEHIND (as of 2026-07-26).** Root pin is exactly `0.9.0` (no `^`/`~`) but `@intentsolutions/core@0.10.0` published 2026-07-09 — so the ≤7-day staleness bound has been breached since roughly 2026-07-16, and the `kernel-vendor-hash` daily sweep has been reporting `❌ VIOLATION: STALENESS` on every run. It is ADVISORY (exit 0), which is why it went unnoticed. Catching this up is a **lockstep** change: `@intentsolutions/jrig-cli@0.1.2` depends on `core@0.9.0` _exactly_, so core must move together with jrig-cli (`0.2.0`, published 2026-07-10) or the two resolve to separate un-hoisted copies of the kernel. Do not read the staleness report as pressure to flip authority — the two axes remain separate, and re-baselining the shadow-soak agreement numbers is part of the bump.\n\nWhat stays frozen is the **authority**: do **NOT** flip the kernel-shadow lane from advisory to authoritative (blocking) until ALL of these hold:\n\n1. ≥99.5% corpus agreement (deterministic folds must be 100%; the 0.5% band is reserved for non-deterministic surfaces only);\n2. ≥30 days of advisory soak;\n3. zero open P0 blockers;\n4. the Rekor superseding-event rollback protocol implemented and tested;\n5. governance sign-off from the CTO + CISO + VP-DevRel triple; and\n6. a ≥14-day public deprecation-window notice to affected skill authors.\n\nAs of now the soak has **not** met the bar — agreement sits below 99.5%, and the open disagreements are real tool-safety / shell-substitution security cases that the prose-spec validator correctly blocks (so flipping early would weaken a real gate). Until every condition above is satisfied, validator authority stays with `validate-skills-schema.py` and both kernel lanes stay advisory. Promotion to blocking is a separate, later cutover step gated by these conditions — never a side effect of an unrelated PR.\n\n**Alignment note (`@intentsolutions/jrig-cli`).** The `j-rig` behavioral-eval CLI is a root devDep pinned to **exactly `@intentsolutions/jrig-cli@0.1.2`**, which depends on **`@intentsolutions/core@0.9.0` (exact)** — the same version the **root** `@intentsolutions/core` pin carries — so they resolve to one shared root-hoisted copy and the kernel-shadow + kernel-vendor lanes read it directly. (The `0.1.2` cut carries the eval→Evidence-Bundle bridge `j-rig eval --emit-bundle` [jrig #172], a functional-exec `max_tokens` / length-truncation fix [jrig #173], `j-rig scaffold-spec` from a `SKILL.md` [jrig #174], and a judge-verdict recovery from truncated / fenced JSON that had inflated NO-SHIP [jrig #175]; it also retains the per-test-case `criteria_ids` scoping fix [jrig #162], so `pnpm exec j-rig eval` scopes each criterion to its own test case. A transitive dep, `@intentsolutions/refiner-core@0.2.0`, still peer-wants `core@^0.8.0`; pnpm surfaces that as a non-fatal warning until refiner-core widens its peer range.) The pin bump is a coupling update only; the authority flip and the root-pin cutover to `authoring/v2` remain the separate, gated steps above.\n\n### Validator consolidation (already landed)\n\nA recent cleanup removed 74 dead duplicate `validation.sh` stubs, collapsed previously-diverged secondary validators into delegating wrappers around the canonical `validate-skills-schema.py`, and added the kernel-loaded shadow read described above. There is now one canonical validator; secondary entry points delegate to it.\n\n### auto-bump posture for contributors\n\n`.github/workflows/auto-bump-on-pr.yml` auto-bumps changed plugins' patch versions on PRs (only on `plugins/**` / `packages/**` changes). For a docs-only or otherwise non-release PR, put **`[skip auto-bump]`** in the PR title or body so the auto-bumper steps aside. Minor/major bumps stay a deliberate human choice — hand-edit the version in the same PR. It stays on `pull_request` (not `pull_request_target`) by design — the bump needs a write token, which must never be handed to fork code; fork PRs are skipped cleanly, and a first-time fork contributor's queued \"Approve and run\" entry just no-ops when approved.\n\n## Adding a New Plugin\n\n**Hand-authored:** copy from `templates/`, add catalog entry to `marketplace.extended.json`, run `pnpm run sync-marketplace`, validate with `--marketplace`.\n\n**Forge-generated:** `/skill-creator --forge <api-name>` — runs 8-gate workflow, requires a NOI (Name of Identity), produces Grade-A skill + `.forge/` audit trail + catalog entry.\n\nTo regenerate against a current API: `/skill-creator --reforge <plugin-name>`.\n\n## Design System\n\nConstitution: `marketplace/DESIGN.md` (Data-Dense Pro family, locked 2026-05-06). If a component disagrees with it, the component is wrong.\n\nKey tokens (`marketplace/src/styles/tokens.css`): `--bg`, `--panel`, `--rule`, `--ink`, `--signal`. Old aliases (`--primary`, `--surface`, `--text`, `--border`) remain mapped for back-compat. CSS colors: **OKLCH only, never hex/rgb**.\n\nReject: gradients on cards, glassmorphism, drop-shadow stacks, `hover:scale-105` on whole cards.\n\n## Killer Skill of the Week\n\nEditorial — Jeremy picks manually. Tooling only syncs two render surfaces.\n\n```bash\n# Promote a new spotlight\nnode scripts/promote-spotlight.mjs path/to/new-spotlight.json\n\n# Sync README block only (no rotation)\nnode scripts/render-spotlight.mjs\n```\n\nSource of truth: `marketplace/src/data/spotlights.json`.\n\n## Key Identifiers — Do Not \"Normalize\"\n\n- **GitHub repo (canonical):** `jeremylongshore/claude-code-plugins-plus-skills`\n- **Marketplace catalog id:** `claude-code-plugins-plus`\n- **Public install slug:** `jeremylongshore/claude-code-plugins` (legacy, GitHub 301s to canonical — hardcoded in CLI, Hero snippet, hundreds of READMEs — renaming is a breaking API change)\n\n## Freshie Inventory\n\nCMDB with a hybrid storage model: `freshie/inventory.sqlite` is the **local\nruntime format** every tool reads/writes (UNTRACKED — the blob is out of git);\nthe **versioned system of record is Dolt**, exported by\n`freshie/scripts/dolt-sync.py` into `freshie/dolt/` (gitignored) and pushed to\npublic DoltHub `jeremylongshore/freshie-inventory` with a `run-N` tag per\ninventory run. The tracked compact export (`freshie/grades.csv` +\n`freshie/grade-histogram.json`) is regenerated by every sync — its git diff is\nthe \"skill X went B→A\" story.\n\nThe full cycle:\n\n```bash\npython3 freshie/scripts/rebuild-inventory.py                         # 1. New discovery run\npython3 scripts/validate-skills-schema.py --marketplace --populate-db freshie/inventory.sqlite  # 2. Compliance\npython3 freshie/scripts/dolt-sync.py                                 # 3. Dolt commit + tag + DoltHub push\npython3 freshie/scripts/promote-to-curated.py                        # 4. Refresh skills/.curated/ (skills.sh mirror)\nsqlite3 freshie/inventory.sqlite \"SELECT grade, COUNT(*) FROM skill_compliance GROUP BY grade;\"  # runtime queries\npython3 freshie/scripts/batch-remediate.py --dry-run && python3 freshie/scripts/batch-remediate.py --all --execute\n```\n\n**skills.sh curated mirror** (`freshie/scripts/promote-to-curated.py`): rebuilds\n`skills/.curated/` as a generated mirror of the repo's best **A+B** plugin skills (our own;\nexternal `.source.json` mirrors excluded → ~1,881) so skills.sh can index them — it only\ncrawls root `skills/` / `.curated/`, never `plugins/**/skills/`. The plugin skill stays the\nsource of truth; the mirror is wipe-and-rebuilt from the tracked `grades.csv` (not the\ngit-ignored `inventory.sqlite`, so the CI drift gate is reproducible), copies only\ngit-tracked files, and re-grades each candidate in-process (promote iff fresh grade still\nA/B). Audit trail: `skills/.curated/MANIFEST.json`. It is excluded from the README count\n(`generate-readme-toc.mjs`) and the inventory scan (`validate-skills-schema.py`\n`find_skill_files`) so a mirror copy is never double-counted. Self-maintaining:\n`promote-curated.yml` refreshes it weekly (PR on change, Slack-on-fail); the\n`promote-curated-check` gate in `ci-required` fails a PR that edits a promoted source\nwithout regenerating. Repo-page branding: root `skills.sh.json`.\n\nHistory queries go to Dolt (`cd freshie/dolt/freshie`): `WHERE run_id = N`,\n`AS OF 'run-N'`, `dolt diff run-7 run-8 --stat` — the run_id model is\nappend-only, so diffs between run tags show added rows, not cell changes.\nClone-free check: `curl \"https://www.dolthub.com/api/v1alpha1/jeremylongshore/freshie-inventory/main?q=SELECT+COUNT(*)+FROM+skill_compliance\"`.\n\n**Interactive/MCP history — the in-repo `dolt-mcp-vcs` plugin** (`plugins/mcp/dolt-mcp-vcs/`,\nregistered as this project's MCP server → freshie Dolt on `127.0.0.1:3308`). Use it to query the\nrun-over-run history conversationally instead of hand-writing `dolt sql`:\n\n- **Start the sql-server first** — the MCP client connects to a _running_ server; it is NOT\n  auto-started. From `freshie/dolt/freshie`: `dolt sql-server -H 127.0.0.1 -P 3308` (run\n  detached; log to a scratch path). Do NOT pass `-u`/`-p` — dolt ≥2 removed them from\n  `sql-server`; the default `root` is passwordless, matching the MCP config's `DOLT_PASSWORD=\"\"`.\n  Then load tools with `ToolSearch\nquery=\"select:mcp__dolt-mcp-vcs__query,mcp__dolt-mcp-vcs__list_dolt_commits,mcp__dolt-mcp-vcs__list_dolt_diff_changes_by_table_name\"`\n  — `query` for `AS OF 'run-N'` reads, the diff tools for per-run deltas; expert agents\n  `dolt-sync-advisor` / `bead-epic-auditor` / `dolt-mcp-vcs:beads-guru` are also available.\n- **⚠️ Stop the sql-server before `freshie/scripts/dolt-sync.py`** — both write\n  `freshie/dolt/freshie`; a live server holds the lock and the sync will clobber/deadlock. `kill\n<server-pid>`, sync, then restart if you still need it.\n- **Mutation gate**: destructive verbs (`push`/`merge`/`reset`/`branch-delete`) are\n  **recommend-only** — the plugin surfaces them but won't execute, so DoltHub pushes still go\n  through the one-way `dolt-sync.py` exporter, never the MCP.\n\n**Rules:** local is the sole writer — never merge DoltHub PRs or web-edit the\npublic database (the exporter is one-way and will clobber them). A failed\nDoltHub push exits non-zero on purpose: until pushed, Dolt history is\nsingle-copy on this box. Exporter unit tests: `python3 -m unittest\ntests.test_dolt_sync`. Full details + restore path: `freshie/README.md`.\n\nKey tables: `skill_compliance` (scores, grades, JRig columns), `forge_proofs` (drives JRig-Verified badges on plugin detail pages — `enrich-jrig-data.mjs` preserves the committed `jrig-data.json` when the local DB is absent, e.g. in CI).\n\n## npm Publish Pipeline\n\nPatch version bumps happen automatically on PR (via `auto-bump-on-pr.yml`). For minor/major bumps, hand-edit the version in the same PR. Merge to main triggers publish + tag + GitHub Release via `publish-changed-packages.yml`. See `RELEASING.md` for the full operator flow.\n\n<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:7510c1e2 -->\n\n## Beads Issue Tracker\n\nThis project uses **bd (beads)** for issue tracking. Run `bd prime` to see full workflow context and commands.\n\n### Quick Reference\n\n```bash\nbd ready              # Find available work\nbd show <id>          # View issue details\nbd update <id> --claim  # Claim work\nbd close <id>         # Complete work\n```\n\n### Rules\n\n- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists\n- Run `bd prime` for detailed command reference and session close protocol\n- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files\n\n**Architecture in one line:** issues live in a local Dolt DB; sync uses `refs/dolt/data` on your git remote; `.beads/issues.jsonl` is a passive export. See https://github.com/gastownhall/beads/blob/main/docs/SYNC_CONCEPTS.md for details and anti-patterns.\n\n## Session Completion\n\n**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.\n\n**MANDATORY WORKFLOW:**\n\n1. **File issues for remaining work** - Create issues for anything that needs follow-up\n2. **Run quality gates** (if code changed) - Tests, linters, builds\n3. **Update issue status** - Close finished work, update in-progress items\n4. **PUSH TO REMOTE** - This is MANDATORY:\n\n   ```bash\n   git pull --rebase\n   git push\n   git status  # MUST show \"up to date with origin\"\n   ```\n\n5. **Clean up** - Clear stashes, prune remote branches\n6. **Verify** - All changes committed AND pushed\n7. **Hand off** - Provide context for next session\n\n**CRITICAL RULES:**\n\n- Work is NOT complete until `git push` succeeds\n- NEVER stop before pushing - that leaves work stranded locally\n- NEVER say \"ready to push when you are\" - YOU must push\n- If push fails, resolve and retry until it succeeds\n<!-- END BEADS INTEGRATION -->\n","category":"root","tokens":9786}]}