Skip to content

docs: Commons integration — README, docs site, roadmap, launch draft#10

Merged
zakelfassi merged 26 commits into
mainfrom
docs/commons-integration
Jul 2, 2026
Merged

docs: Commons integration — README, docs site, roadmap, launch draft#10
zakelfassi merged 26 commits into
mainfrom
docs/commons-integration

Conversation

@zakelfassi

Copy link
Copy Markdown
Owner

Phase 4 of docs/plans/2026-07-skdd-commons.md. Stacked on #9 (which stacks on #8) — merge in order 8 → 9 → 10 and each retargets automatically.

  • Main README gains the Commons section (thesis, skdd add one-liner, current drop).
  • docs/commons.md + Starlight mirror with a new 'Commons' sidebar group — site builds clean (28 pages).
  • ROADMAP: Commons tranche added as shipped-launch-pending; deferred items under 'Commons v2' with skdd update (three-way evolution merge) flagged as the highest-value follow-up.
  • Announcement copy drafted at docs/plans/2026-07-commons-announcement.md — for review, not auto-posted.
  • Plan §9 updated with the full execution log + the manual launch checklist (repo flip to public, branch protection, marketplace submissions, announcement).

skdd add <source> [selector]: install a drop (or one skill) from a
Commons repo — GitHub shorthand, git URL (#ref), or local path. Strict
validation before install, collision check with --rename escape hatch,
registry provenance owner/repo@shortsha (drop-id), full sha recorded in
.skdd-lock.json, mirrors refreshed via the existing safe (never forced)
link path. --dry-run/--json/--non-interactive/-g.

skdd push <skill|pack>: ship a skill upstream as a PR via gh. Strips
machine-local state (usage-count -> "0", last-used dropped), preserves
forged-* provenance. Upstream-known skills branch as evolve/<name> with
a diff summary; new skills branch as skill/<name> into incoming/ (or an
existing drop via --drop, updating drops.json). Local-path targets are
a --dry-run test seam. Default target from ~/.skdd/config.toml commons
key (smol-toml, already a dependency).

skdd drops [--from]: list a Commons' drops (table/json).

No new runtime dependencies. 24 new tests incl. a regression test that
add never force-replaces a populated mirror dir.
…e-the-session reminder

Two gates in plugins/skdd-claude (v0.3.0), both OFF by default:

- finish-loop-gate.mjs (Stop): when the session changed non-test product
  source and the final report claims success without observed evidence,
  bounce the stop once with instructions to verify or say it's
  unverified. Blocks at most once per session (state in $TMPDIR) — the
  codex gate's anti-loop pattern.
- freeze-reminder.mjs (SessionEnd + PreCompact): non-blocking
  systemMessage when a substantive session ends with the colony registry
  untouched since session start. Deterministic heuristics; silent when
  unsure.
- session-start.mjs seeds the session-start timestamp; lib/state.mjs
  holds state + toggle reads (.claude/skdd.local.md via /skdd-hooks).

A skill is a procedure the model follows when it decides to; a hook is
a gate for when it forgets. Node >=20 built-ins only; 11 e2e tests spawn
the real scripts.
…e, roadmap tranche, launch draft

- README: 'SkDD Commons — skills that evolve in public' section with the
  add one-liner and current-drop link
- docs/commons.md (+ site mirror & sidebar group): drops, add/push flow,
  security posture, hooks pointer
- ROADMAP: Commons tranche (shipped, launch pending) + Commons v2
  deferred list (skdd update three-way merge flagged highest-value)
- docs/plans/2026-07-commons-announcement.md: launch copy drafted for
  review, not posted
- plan §9: phases 1-4 logged, manual launch checklist queued
The site's prebuild sync copies canonical docs into src/content/docs and
removes strays — a hand-copied mirror gets deleted on the next build.
commons.md now flows through the manifest like every other doc, and the
generated mirror is gitignored.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3f3a333163

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread site/astro.config.mjs
},
{
label: "Commons",
items: [{ label: "SkDD Commons & drops", link: "/commons/" }],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add the Commons page to the docs sync mapping

Because site/scripts/sync-docs.mjs cleans generated docs and only copies explicit mappings, and docs/commons.md was not added there, prebuild will leave no site/src/content/docs/commons.md. This new sidebar item therefore sends users to /commons/ with no Starlight page after every docs build; add the Commons doc to the sync mapping before exposing the nav entry.

Useful? React with 👍 / 👎.

…yload

Codex adversarial review findings:

- [high] drops.json ids/names were used as filesystem path segments
  unchecked, so a malicious Commons could list a skill like
  '../escape-skill' and write outside the colony. Every manifest parse
  site now enforces the lowercase-kebab-case grammar (no slashes, dots,
  or absolute paths) and add asserts source/destination containment as
  defense in depth.
- [medium] push copied the entire local skill directory into the PR
  clone, so dotfiles, logs, .env files, or symlinked content could leak
  to a public Commons PR. Only an allowlisted payload travels now
  (SKILL.md + regular files under scripts/, references/, assets/);
  dry-run enumerates exactly what travels and what stays home.

+5 adversarial tests (hostile manifests, payload exclusion incl.
symlinks and .env); 899 total green.
# Conflicts:
#	docs/plans/2026-07-skdd-commons.md
# Conflicts:
#	docs/plans/2026-07-skdd-commons.md
readFileSync follows symlinks, so a symlinked SKILL.md (or a symlinked
skill directory) could exfiltrate arbitrary file contents into a Commons
PR even with the payload allowlist. push now lstats both and refuses;
collectPublishablePayload throws defensively. +2 tests.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 50a3a70b23

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

{ src: "docs/global-colony.md", dest: "global-colony.md" },
{ src: "docs/mcp-sync.md", dest: "mcp-sync.md" },
// Commons — community drops + the add/push evolution loop.
{ src: "docs/commons.md", dest: "commons.md" },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Untrack the generated Commons page

With this new mapping, site/scripts/sync-docs.mjs rewrites site/src/content/docs/commons.md on every pnpm build/prebuild, but that generated page is already tracked in this branch and differs from the new canonical docs/commons.md content; adding it to .gitignore does not untrack it. In the inspected repo, running the sync script immediately leaves site/src/content/docs/commons.md dirty, so docs builds will keep producing uncommitted changes unless the generated copy is removed from the index or regenerated and committed consistently.

Useful? React with 👍 / 👎.

zakelfassi added 15 commits July 1, 2026 19:41
…s loop

Pack discovery called parseSkill (readFileSync follows symlinks) before
the items-loop symlink guard, so a pack push dereferenced a symlinked
skill while scanning. Hoisted the check into a skillDirIsSymlinked helper
applied at discovery: direct pushes refuse, pack scans skip+warn, and the
items-loop check remains as defense in depth. +1 pack-scan test.
- add/push honor .colony.json canonicalSkillsDir (pass to runLink; resolve
  before scanning) — .colony.json users could not add/push before
- reject symlinks anywhere in a fetched Commons skill tree (add), matching
  the push-side guard
- registry cells escape pipes/newlines and the parser unescapes, so an
  untrusted Commons description can't inject fake rows
- push: metadata stripping scoped to frontmatter only (body examples with
  usage-count/last-used lines are preserved)
- push: validate each local skill --strict before opening a PR CI would
  reject; distinguish an empty diff from a real git commit failure and hint
  at missing git identity; validate pack ids as git-ref-safe branch slugs;
  clear the upstream dir before an evolve copy so deleted files don't linger
- parseSource splits #ref before local-path detection (../commons#feature)
  and local #ref checks out from a clean clone (never mutates the user repo)
- local dirty repos record a -dirty provenance marker + lock flag
- malformed ~/.skdd/config.toml surfaces instead of silently defaulting
- extract lib/colony.ts (canonicalDirName) shared by add/push

+11 tests (hostile symlink/name-mismatch in add, frontmatter-only strip,
registry injection round-trip, parseSource #ref, provenance dirty). 914 green.
- finish-loop measures product-source changes against the SessionStart
  baseline (a file already dirty before the session no longer triggers),
  recognizes suffix-style test names (foo_test.go, test_foo.py), fails
  OPEN when the anti-loop flag can't be persisted, and resolves the
  toggle by searching upward so a repo-root toggle works from a subdir
- freeze counts untracked files and commits-since-start as substantive
  (not just git diff HEAD), recognizes .skills-registry.json, and never
  invents a start time (silent when SessionStart didn't seed state)
- SessionStart snapshots HEAD + changed paths and resets per-run state,
  so a resumed session doesn't inherit a stale finishLoopBlocked/baseline
- saveState reports success; lib/state.mjs gains repoSnapshot/commitsSince

+7 hook tests. Node >=20 built-ins only; 932 total green.
The baseline-by-path check ignored any path present at SessionStart, so a
further edit to an already-dirty product file went unnoticed. SessionStart
now hashes each dirty file; sessionChangedPaths content-compares, so both
newly-dirty files AND edits to pre-dirty files count, while a pre-dirty
file left untouched is still ignored. finish-loop and freeze both use it.
+1 regression test; 933 green.
git status emits cwd-relative paths, so when SessionStart and the Stop
gate ran from different directories (subdirectory sessions) the baseline
hash keys didn't align and an edit to a pre-dirty file was missed or
misattributed. repoSnapshot now resolves git rev-parse --show-toplevel
and runs status + hashes files from the repo root, making paths and
hashes independent of each hook's invocation cwd. +1 regression test
(SessionStart from root, edit + Stop from a subdir → blocks). 934 green.
- local #ref add clones with --branch (branch/tag refs resolve; sha
  falls back to detach) instead of failing on origin-only branches
- --dry-run (including -g) no longer creates ~/.skdd
- reject symlinked pack ancestors via realpath containment (a Commons
  making packs/ or the drop dir a symlink can't serve outside bytes)
- validate pack ids with a full git-ref rule (reject foo.lock, a..b, …)
- push payload skips non-regular files (FIFO/socket/device would hang cp)
- strip an emptied metadata: block so the pushed SKILL.md has no null key
- push validates the stripped payload (what the Commons CI sees)
- rewrite drops.json only when a new skill is actually added

Deferred: renamed-then-pushed skills classify by local name (niche).
+8 tests; 919 green.
- finish-loop counts committed product changes since session start (the
  commit-before-final-report workflow left a clean worktree and slipped
  through), and fails open when no SessionStart baseline exists
- tighten the 'I ran' evidence marker to require a real run object, so an
  explicitly-unverified 'I ran out of time … should work' still bounces
- freeze treats a large single-file change as substantive (line count),
  finds a repo-root registry from a subdirectory, and takes the max mtime
  across .md/.json (touching either active format counts as frozen)
- bound the toggle search at the git/project root so a parent-workspace
  .claude/skdd.local.md can't opt a nested repo in

+8 tests; 943 green.
@zakelfassi zakelfassi changed the base branch from feat/plugin-hooks to main July 2, 2026 05:24
# Conflicts:
#	docs/plans/2026-07-skdd-commons.md
@zakelfassi zakelfassi merged commit 8cbdffc into main Jul 2, 2026
2 checks passed
@zakelfassi zakelfassi deleted the docs/commons-integration branch July 2, 2026 05:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant