Files
Vincent 769412d297 chore(skills): consolidate marketplace — 185→178 skills, 67 authoring fixes (#19)
* chore(skills): consolidate marketplace — 185→178 skills, 67 authoring fixes

Adversarially-verified removals (7):
- fold review-pr's unique checks into code-review (unintended-public-endpoint
  auth posture; API-doc decorator presence), then delete review-pr
- delete analytics-expert, serializer-specialist, claude-code-guide,
  workflow-automation, nestjs-testing-expert, plasmo-extension-architect
- strip 6 dangling delegation references to the removed skills

Authoring-standard fixes (67 across 66 skills):
- add disable-model-invocation guards to side-effecting skills (deploy/PR/git/
  vercel/file-write/network)
- add ## Contract sections wherever allowed-tools or CONTRACT_REQUIRED demands
- rewrite first-person and stub descriptions to third-person + concrete triggers
- remove broken /impeccable hard dependencies (layout, polish, quieter,
  critique, shape, audit)
- middleware.ts -> proxy.ts (Next.js 16); npm/npx/yarn -> bun/bunx
- nest version/tags/author under metadata; quote tags; ${CLAUDE_SKILL_DIR}
  script paths
- strip stale model benchmarks and Created/Updated footers; drop persona
  injections and boilerplate When-to-Use/Limitations sections
- decouple hardcoded product content (copywriter, design-consistency-auditor,
  roadmap-analyzer) into discover-from-project guidance
- extract oversized inline blocks to references/scripts/assets
  (full-code-review, fullstack-workspace-init, quick-view, shadcn-setup,
  business-model-auditor, business-operator)

Regenerate 16 category bundles + marketplace.json (194 plugins).
validate-skill-sync: 0 errors / 0 warnings. markdownlint: clean.

* feat(provenance): track 26 external upstreams + add UPSTREAM-TRACKING index

Make every derived skill auditable against its source so upstream
improvements can be diffed and ported home.

Provenance applied (SKILL.md metadata + README ## Upstream section):
- 7 newly verified externals: agent-browser (vercel-labs, Apache-2.0),
  changelog-generator (ComposioHQ), context-fundamentals +
  context-optimization (muratcankoylan, MIT), humanizer (ankshvayt),
  shadcn + tailwind (pproenca/dot-skills, MIT)
- already-tracked: impeccable-7 (tagged), superpowers-5, anthropic-6,
  dimillian-1 (rolling) — refreshed via apply-provenance.py

Each external upstream was verified by fetching the real file and
pinning the exact commit/tag; nothing was guessed.

License flags: ComposioHQ/awesome-claude-skills and ankshvayt/humanizer
ship NO LICENSE file (GitHub license API 404, no LICENSE in root) —
recorded as "Unspecified (all-rights-reserved by default)" and flagged
for review rather than fabricating a license.

Corrections:
- removed incorrect `author: Ship Shit Dev` from three obra/superpowers
  ports (writing-plans, receiving-code-review, finishing-a-development-branch)

Tooling:
- scripts/apply-provenance.py — idempotent provenance applier
- scripts/provenance-manifest.json — 19 rolling/tagged entries
- scripts/classify-provenance.workflow.js — 144-agent verification sweep
  (biome-excluded: Workflow-runtime script with intentional top-level return)
- validate-skill-sync.sh check_provenance() — warns on missing
  ## Upstream or last_synced >90 days

Docs:
- .agents/SYSTEM/UPSTREAM-TRACKING.md — index of all derived skills
  across 4 buckets (26 external / 4 vitae internal-port / own-repo
  re-homes / ~148 in-house)

Regenerated bundles. Validator: 178 skills, 0 errors, 0 warnings.

* refactor(commands): shorten 5 slash triggers to one word

Triggers are filename-derived, so renaming the file renames the command:
  /check-domain    -> /domain
  /co-founder      -> /cofounder
  /env-setup       -> /env
  /optimize-prompt -> /prompt
  /security-audit  -> /scan

In-file /usage self-references fixed in domain.md and env.md.
/security-audit -> /scan (not /audit) because /audit collides with the
impeccable audit skill. The security-audit SKILL and its cross-references
(structural-review, marketplace.json) are unchanged — only the command
trigger moved.
2026-06-12 22:14:49 +02:00

123 lines
4.8 KiB
Python

#!/usr/bin/env python3
"""Apply upstream provenance to a skill's SKILL.md frontmatter + README.md.
Idempotent. Operates ONLY inside the `metadata:` block of the YAML frontmatter
(never touches a top-level `license:`). Strips any pre-existing provenance keys
inside that block, then inserts a canonical provenance block right after the
`version:` line. Generates/refreshes the README `## Upstream` section.
Driven by a JSON manifest on argv[1]:
{ "skills": [ { skill, desc, source, source_path, upstream_repo, upstream_ref,
upstream_commit, last_synced, license, modifications, mode,
upstream_version, upstream_latest } ] }
mode: "rolling" (main + commit) | "tagged" (upstream_version/upstream_latest)
"""
import json
import sys
import pathlib
PROV_KEYS = {
"source", "upstream_repo", "upstream_ref", "upstream_commit",
"upstream_version", "upstream_latest", "last_synced",
} # metadata-block `license` is managed here too; top-level `license:` untouched.
SKILLS_DIR = pathlib.Path(__file__).resolve().parent.parent / "skills"
def split_frontmatter(text):
lines = text.split("\n")
if not lines or lines[0].strip() != "---":
raise ValueError("no frontmatter")
for i in range(1, len(lines)):
if lines[i].strip() == "---":
return lines[1:i], lines[i + 1:]
raise ValueError("unterminated frontmatter")
def edit_metadata(fm_lines, entry):
start = next((i for i, l in enumerate(fm_lines) if l.rstrip() == "metadata:"), None)
if start is None:
raise ValueError("no metadata: block")
end = len(fm_lines)
for i in range(start + 1, len(fm_lines)):
l = fm_lines[i]
if l.strip() == "":
continue
if not l.startswith(" "):
end = i
break
block = fm_lines[start + 1:end]
drop = PROV_KEYS | {"license"}
if entry.get("drop_author"):
drop = drop | {"author"}
kept = [l for l in block
if (l.strip().split(":", 1)[0] if ":" in l else "") not in drop]
prov = [f" source: {entry['source']}"]
if entry.get("mode") == "tagged":
prov.append(f" upstream_version: {entry['upstream_version']}")
prov.append(f" upstream_latest: {entry['upstream_latest']}")
else:
prov.append(f" upstream_repo: {entry['upstream_repo']}")
prov.append(f" upstream_ref: {entry['upstream_ref']}")
prov.append(f" upstream_commit: {entry['upstream_commit']}")
prov.append(f' last_synced: "{entry["last_synced"]}"')
prov.append(f" license: {entry['license']}")
vidx = next((i for i, l in enumerate(kept) if l.strip().startswith("version:")), -1)
at = vidx + 1 if vidx >= 0 else 0
new_block = kept[:at] + prov + kept[at:]
return fm_lines[:start + 1] + new_block + fm_lines[end:]
def render_readme(entry):
name = entry["skill"]
repo = entry["upstream_repo"]
src = entry["source"]
src_label = f"`{entry['source_path']}`"
rows = [f"| Source | [{src_label}]({src}) |"]
if entry.get("mode") == "tagged":
rows.append(f"| Forked at | `{entry['upstream_version']}` |")
rows.append(f"| Upstream latest | `{entry['upstream_latest']}` |")
check = f"diff [{src_label}]({src}) against tag `{entry['upstream_version']}`"
else:
rows.append(f"| Upstream ref | `{entry['upstream_ref']}` |")
rows.append(f"| Synced at commit | `{entry['upstream_commit']}` |")
check = (f"diff [{src_label}]({src}) on `{entry['upstream_ref']}` since commit "
f"`{entry['upstream_commit']}`")
rows.append(f"| Last synced | {entry['last_synced']} |")
rows.append(f"| License | {entry['license']} |")
table = "\n".join(rows)
desc = entry.get("desc", "").strip()
desc_block = f"\n{desc}\n" if desc else ""
repo_url = f"https://github.com/{repo}"
return f"""# {name}
{desc_block}
## Upstream
Derived from **[{repo}]({repo_url})** ({entry['license']}).
| Field | Value |
|-------|-------|
{table}
**Local modifications:** {entry['modifications']}
**Checking for upstream changes:** when upstream has moved ahead of the synced marker above, {check}, port anything worth bringing home, then bump `metadata.upstream_commit` (or `metadata.upstream_version`) and `metadata.last_synced` in `SKILL.md` and this table.
"""
def main():
manifest = json.loads(pathlib.Path(sys.argv[1]).read_text())
for entry in manifest["skills"]:
sd = SKILLS_DIR / entry["skill"]
sk = sd / "SKILL.md"
fm, body = split_frontmatter(sk.read_text())
fm2 = edit_metadata(fm, entry)
body_text = "\n".join(body)
sk.write_text("---\n" + "\n".join(fm2) + "\n---\n" + body_text.lstrip("\n"))
(sd / "README.md").write_text(render_readme(entry))
print(f"{entry['skill']}")
if __name__ == "__main__":
main()