Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .claude/knowledge/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Knowledge Index

## Architecture
- `architecture/skill-design-conventions.md` — Context economy as design principle; description budget + `skillListingBudgetFraction`; Trigger-line format
- `architecture/skill-composition.md` — Flag contracts (`--no-poll`/`--auto`), shared scripts, format contracts, soft coupling
- `architecture/model-economics.md` — Which model per skill and why (Haiku/Sonnet/session-model)

## Features
- `features/backfill-and-origin-metadata.md` — `/backfill-knowledge` significance bar + origin-reconstruction cascade
- `features/statusline-integration.md` — Status-line segment: plugins can't own `statusLine.command`; marker-block injection

## Deployment
- `deployment/ci-structure-checks.md` — `check-structure.py` as the single automated guard for a build-less repo
53 changes: 53 additions & 0 deletions .claude/knowledge/architecture/model-economics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
title: "Model Economics: Picking the Model per Skill"
createdAt: 2026-06-18
updatedAt: 2026-06-19
createdFrom: "branch: task/dogfood-knowledge-system"
updatedFrom: "branch: task/dogfood-knowledge-system"
pluginVersion: 1.8.0
prime: true
---

# Model Economics

Each subagent-backed skill picks its model from the **task shape and invocation
frequency**, not a default. The reasoning is recorded in each skill's "Model
rationale" section; this is the cross-cutting summary.

## The assignments and why

- **`/query` → Haiku** (the knowledge agent's `model: haiku`). The task is a
bounded lookup: read the index, pick relevant files, summarize. No reasoning
over ambiguous requirements, no architectural judgment. `/query` is invoked
*often* — potentially before every non-trivial change — so cost compounds;
Haiku keeps it cheap enough to stay usable, and fast (<2s).

- **`/query` Explore fallback → session model (no override).** When knowledge
has a gap and the skill falls back to codebase exploration, that work is
open-ended (which files matter, when to stop) and needs session-model
reasoning quality. It runs rarely, so its higher cost is negligible.

- **`/reindex` → Sonnet, background.** A semantic reasoning task — judging
duplicates, cross-links, frontmatter correctness across the whole graph.
Haiku would miss subtle overlaps; Opus is overkill for structured analysis.
Sonnet hits the quality/cost sweet spot. It runs `run_in_background: true`
because a thorough pass reads many files over 1–3 minutes; blocking the
session would be hostile.

## The principle

Match model tier to the *kind* of thinking required, then weight by how often
the skill runs:

- **Bounded, mechanical, frequent** → cheapest capable model (Haiku).
- **Semantic judgment, occasional** → mid tier (Sonnet).
- **Open-ended reasoning, rare** → inherit the session model rather than pin a
tier.

A second axis is **context hygiene**: `/query` and `/reindex` run as subagents
(not in-context) specifically to keep the main window clean — they read many
files and return a dense answer instead of dragging file contents into the
primary session. `/prime` is the deliberate inverse: it loads content *into*
the main context on purpose, so it runs in-context with no subagent.

Related: [[skill-design-conventions]], [[skill-composition]].
69 changes: 69 additions & 0 deletions .claude/knowledge/architecture/skill-composition.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: "Skill Composition: Flag Contracts, Shared Scripts, Soft Coupling"
createdAt: 2026-06-18
updatedAt: 2026-06-19
createdFrom: "branch: task/dogfood-knowledge-system"
updatedFrom: "branch: task/dogfood-knowledge-system"
pluginVersion: 1.8.0
prime: true
---

# Skill Composition

Skills in this marketplace compose rather than duplicate. Three mechanisms make
that work, and a fourth keeps plugins loosely coupled so they can split apart
cleanly later.

## 1. Flag contracts (one skill as another's subroutine)

A skill that a parent invokes exposes flags that suppress interaction the parent
has already handled. The canonical example is `/rebase`, called as a subroutine
by `/open`, `/cycle`, and `/merge`, with `--no-poll` (the parent does its own
review polling) and `--auto` (the parent's invocation *is* the authorization, so
the subroutine skips menus it would otherwise show).

The principle, not the exact flag mechanics (which live in
`plugins/pr-flow/skills/rebase/SKILL.md` and evolve there): a parent-authorized
flag removes **prompts**, never **safety stops**. Conflicts still abort,
missing-upstream still stops — `--auto` only drops the confirmation the parent
already implied by calling. Re-prompting after an explicit opt-in is its own
anti-pattern. Refer to the rebase skill for the current, authoritative
semantics rather than relying on this summary.

## 2. Shared scripts as single source of truth

Logic used by multiple skills lives in one script, not copied prose.
`plugins/pr-flow/scripts/claude-review.sh` (poll / latest / latest-after) is
shared by five skills — `/check`, `/cycle`, `/merge`, `/open`, `/rebase`
(note: `/fix` does **not** use it; it only consumes the review *format* below).
One implementation to harden — real-world fixes (fractional-seconds parsing,
merge-method detection from PR history, `mergeStateStatus` interpretation) land
once and all callers benefit.

## 3. Format contracts between skills

When one skill must parse another's output, the format is pinned in a shared
spec. `plugins/pr-flow/docs/REVIEW-OUTPUT-FORMAT.md` lets `/fix` deterministically
parse the findings table `/cycle` produces. The contract is the interface;
neither side reverse-engineers the other.

## 4. Soft coupling for a future split

Plugins detect each other generically, never by hard dependency.
pr-flow recognizes knowledge systems by convention (`.claude/knowledge/`,
`.cursor/rules/`, `AGENTS.md`, …) rather than importing the knowledge-system
plugin; `/merge` *offers* `/close` instead of calling it. This keeps the
plugins independently installable and is the right shape for an eventual
extraction (e.g. the Codex split).

## Why extract-to-shared-spec is the standing remedy

Duplicated logic across two skills drifts. The fix is always to pull the shared
part into one source the callers reference — exactly mechanisms 2 and 3. The
doc-readiness checks once duplicated between `/open` and `/merge` were resolved
this way: both now read `plugins/pr-flow/docs/READINESS-CHECKS.md` instead of
each carrying their own copy. When you see the same logic in two skills, that is
the move.

Related: [[skill-design-conventions]]. See also the `cwd-safety` rule
(`.claude/rules/cwd-safety.md`).
72 changes: 72 additions & 0 deletions .claude/knowledge/architecture/skill-design-conventions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
title: "Skill Design Conventions & Context Economy"
createdAt: 2026-06-18
updatedAt: 2026-06-19
createdFrom: "branch: task/dogfood-knowledge-system"
updatedFrom: "PR #8"
pluginVersion: 1.8.0
prime: true
---

# Skill Design Conventions & Context Economy

The governing design principle across every plugin in this marketplace:
**anything that lands in always-loaded session context is paid for in every
session, not just the one that uses the feature.** Always-loaded surfaces are
skill `description` frontmatter, auto-loaded rule files, `CLAUDE.md` content,
status-line output, and plugin metadata. Detail belongs in the file body the
model reads *on demand* when it invokes the skill — not in the activation
surface.

## Why skill descriptions must stay short

Each skill's `description` frontmatter is loaded into every session for
activation matching. It counts against `skillListingBudgetFraction` (default
1% of context). When the combined descriptions exceed that budget, Claude Code
**truncates** them — and a truncated description can stop matching its trigger
phrases, so the skill silently becomes harder to invoke. This is the concrete
failure mode that justifies the budget discipline; it is not a stylistic
preference.

## The conventions

The concrete rules — description length budget, the `Trigger:`-line structure,
English-only, no feature lists in the description — are stated as the
always-loaded source of truth in CLAUDE.md's "Skill descriptions: keep them
short" section. They are deliberately **not** restated here: a second copy in an
on-demand doc only drifts from the always-loaded one. This file captures the
*why* and the mechanism (above and below); CLAUDE.md is the checklist.

## How to apply

Before writing anything destined for an always-loaded surface, ask: does this
need to be always-on, or can it live in an on-demand body? Can the same meaning
be expressed in half the words? Is it already loaded somewhere else (avoid
duplication that drifts)? Err terse. The marketplace has lived this — see the
commit "Compact skill descriptions to fit listing budget."

## Plugin-global vs per-project always-loaded surface

A corollary of the cost principle: **a plugin should not ship always-loaded
rule files**. A rule bundled in the plugin (e.g. the former `auto-query.md` /
`auto-curate.md`) loads into *every* session of *every* project that has the
plugin installed — even projects that never use the feature. That is a tax the
non-user pays.

The fix is to move that guidance into a **per-project file written by `/init`**
(`.claude/rules/knowledge-system-usage.md`):

- It costs nothing for projects that haven't run `/init`.
- It is committed alongside the project, so it is team-shared and reviewable.
- A single per-project surface also resolves contradictions — two competing
plugin-global rules (inline-vs-`/query`) collapse into one authored file.

The trade-off this creates is **staleness**: a committed project file can fall
behind the plugin's current guidance. Solved with a **template-version marker**
(`knowledge-system-usage template-vN`) carried in the file. The number is bumped
only when the template content changes (independent of plugin version), and
`/reindex` compares each project copy's marker against the plugin's current
number to flag drift — surfacing staleness without ever auto-mutating a
committed project file.

Related: [[skill-composition]], [[model-economics]], [[ci-structure-checks]].
43 changes: 43 additions & 0 deletions .claude/knowledge/deployment/ci-structure-checks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
title: "CI Structure Checks"
createdAt: 2026-06-18
updatedAt: 2026-06-19
createdFrom: "PR #6"
updatedFrom: "PR #6"
pluginVersion: 1.8.0
prime: false
---

# CI Structure Checks

This repo is declarative Markdown + JSON with **no build step**, so there is no
compiler to catch structural regressions — they stay invisible until live use.
`scripts/check-structure.py` is the **single automated guard**, run identically
in CI (`.github/workflows/structure-checks.yml`) and locally before pushing.

## What it verifies

The script groups its checks into four functions:

1. **JSON validity + version sync** — every `plugin.json` / `marketplace.json`
parses, and each plugin's version matches between the two. Version drift is a
hard error, so it acts as a merge gate (the two-file version rule itself is
documented in CLAUDE.md's "Versioning" section).
2. **SKILL.md frontmatter** — required fields present, and the `description`
word budget (thresholds live in the script's `DESC_WORDS_*` constants).
Enforced mechanically because an over-budget description gets silently
truncated in sessions and can stop matching its triggers (see
[[skill-design-conventions]]).
3. **Internal `${CLAUDE_PLUGIN_ROOT}` references** — paths referenced in skills
actually exist, catching dangling cross-references.
4. **Shell script syntax** — bundled `.sh` files parse.

## Why it exists

The architecture review named "zero verification" the system's single biggest
risk: for a system whose "code" is prose, CI is the only substitute for a
compiler. This check closes the most common failure class (broken JSON, version
drift, dangling refs, budget violations) cheaply and mechanically. Keep it green;
it runs on every PR and push to main.

Related: [[skill-design-conventions]].
56 changes: 56 additions & 0 deletions .claude/knowledge/features/backfill-and-origin-metadata.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
title: "Backfill from History & Origin Metadata"
createdAt: 2026-06-18
updatedAt: 2026-06-19
createdFrom: "PR #2"
updatedFrom: "PR #2"
pluginVersion: 1.8.0
prime: false
---

# Backfill from History & Origin Metadata

Two related knowledge-system capabilities for retroactively populating a
knowledge base and tracking where each entry came from.

## `/backfill-knowledge` — mine merged PRs

Bootstraps (or extends) a knowledge base from merged-PR history. Shape:

- A **background Sonnet agent** fetches each PR's metadata, commits, and diff
and judges it against a **strict significance bar** — only new user-facing
features, architecture changes, or durable major insights pass. Bug fixes,
refactors, tests, deps-bumps, chores are rejected. Target acceptance is
~10–20%; a bloated base is worse than a small one.
- The agent **never writes files** — it returns a candidate report. The user
approves a selection, then `/curate` runs per pick with `--origin "PR #<N>"`.
- **Idempotency** comes from two sources unioned together: PR numbers already
anchored in `createdFrom`/`updatedFrom` frontmatter, plus a persistent log
(`.claude/logs/backfill-knowledge.md`). The log's "Skipped — not significant"
bucket is critical: without it, every run re-judges every rejected PR and
regenerates the same noise.

## Origin metadata (`createdFrom` / `updatedFrom`)

Knowledge files record their provenance so a later reader (or `/reindex`) knows
where the learning originated. The value is one of `"PR #<N>"`,
`"branch: <name>"`, or `"session: <date>"`.

The **reconstruction cascade** resolves a commit SHA to a PR. Its full,
authoritative definition lives in `/reindex` (step B) — that is the single
source; do not re-enumerate or reimplement it here. The shape:

- **Primary (online):** `gh pr list --search <sha> --state merged`. GitHub knows
which PR a commit belongs to regardless of merge mode (merge, squash,
rebase-FF), so this covers virtually all online cases.
- **Offline fallbacks:** parse the commit subject — both the squash suffix
`(#<N>)` and the classic merge-commit `Merge pull request #<N>` form — and
the branch name, in the order `/reindex` defines.
- **Don't guess:** if nothing resolves unambiguously, the field is left **empty**
rather than filled with a guess.

A `"branch: <name>"` value is upgraded to `"PR #<N>"` later by `/reindex` once
the branch merges — re-running the cascade on the same SHAs, never on the branch
name (the branch may be deleted post-merge).

Related: [[skill-design-conventions]] (frontmatter as managed surface).
51 changes: 51 additions & 0 deletions .claude/knowledge/features/statusline-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
title: "Status-Line Integration"
createdAt: 2026-06-18
updatedAt: 2026-06-19
createdFrom: "PR #3"
updatedFrom: "PR #3"
pluginVersion: 1.8.0
prime: false
---

# Status-Line Integration

How the `/statusline` skill surfaces knowledge-system info (`[cks rules|knowledge]`)
in the Claude Code status line.

## The design

The status line is owned by the user's own `~/.claude/statusline.sh`. The
`/statusline` skill does **not** replace it — it requires an existing custom
status line and coexists with it:

- **Marker-block injection**: the install step injects a delimited block into
the user's existing `~/.claude/statusline.sh` rather than overwriting it.
Re-running is idempotent (replace in place between markers); uninstall removes
the block. The same install step copies the renderer to
`~/.claude/cks-statusline.sh` (version-gated via a `CKS_STATUSLINE_VERSION`
line) and is atomic/restorable (session backup + post-write verify).
- **Standalone renderer**: the installed renderer at `~/.claude/cks-statusline.sh`
is independently usable — one arg (workspace dir), an ANSI-coloured block on
stdout, no trailing newline. A third-party status-line tool (ccstatusline,
CCometixLine, ccusage) can call it directly from its custom-command slot:
`bash "$HOME/.claude/cks-statusline.sh" "$DIR"`. (Its source lives in the
plugin at `scripts/statusline-cks.sh`.)
- **Per-project opt-out via sentinel**: a sentinel file disables the segment in
a given project, so opt-out is local and needs no global config mutation.

## Where the logic lives

All install/enable/disable/uninstall/status logic lives in one deterministic,
locally-testable script — `plugins/knowledge-system/scripts/statusline-install.sh`
— and the skill is a thin wrapper that parses the argument, runs the script, and
relays its output. The script is the source of truth; don't look in the SKILL.md
prose for the behavior.

## Why this matters beyond statusline

The "inject a marked block into a user-owned file you don't control" pattern
recurs — `/init` does the same to `CLAUDE.md`. Idempotent marker blocks are the
plugin's standard mechanism for editing files the user also edits.

Related: [[skill-composition]] (shared-script single-source), [[ci-structure-checks]].
12 changes: 12 additions & 0 deletions .claude/logs/backfill-knowledge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Backfill Log

## 2026-06-18 — knowledge-system v1.7.0 — range: --last 20 (11 merged PRs, #1–#12)

Accepted (4):
- PR #2 → features/backfill-and-origin-metadata.md (new)
- PR #3 → features/statusline-integration.md (new)
- PR #6 → deployment/ci-structure-checks.md (new)
- PR #8 → architecture/skill-design-conventions.md (updated)

Skipped — not significant (7):
- #1, #4, #5, #7, #9, #10, #12
Loading
Loading