Files
FabledScribe/plugin/skills/family-canon/SKILL.md
T
bvandeusenandClaude Opus 5.5 07169e1274
CI & Build / Plugin hooks (push) Successful in 15s
CI & Build / Python lint (push) Successful in 2s
CI & Build / TypeScript typecheck (push) Successful in 1m9s
CI & Build / integration (push) Successful in 1m21s
CI & Build / Python tests (push) Successful in 2m2s
CI & Build / Build & push image (push) Successful in 1m29s
feat(family): an idea links to the rule topic holding its norms - set_family_topic, the readouts name the rules, the idea row shows the link (milestone 463 step 1 gap, found in step 7, #4993)
Step 1 added family_ideas.topic_id but nothing could set it, so the note<->topic
link the milestone promised existed only as a column. set_family_topic links or
unlinks (0) a topic in a rulebook the caller owns, one idea per topic; the
version does not move. get_family_idea and get_family_adoption list the topic's
rules; list_family_ideas and the Family page name the topic. The model
docstrings no longer claim the topic's rules are platform-scoped in retrieval.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 14:27:33 -04:00

97 lines
5.1 KiB
Markdown

---
name: family-canon
description: Use when family canon reaches the session — a `family_hint` on a create (a record may be a pattern every project on a platform will need), a `family` key from enter_project (ideas this project has not answered, owes, or must recheck), a `family_owed` list when a task closes, or the operator asks whether a pattern is shared between projects. Triggers on "family", "shared between projects", "promote", "canon idea", "owed", "adopt", "every Android app", "every project on".
metadata:
moments: work.record
---
# Family canon — good ideas spread by criteria, not by approval
Some patterns are not one app's: every project on a platform meets the same
problem (an Android app that ships its own APK, a Go service behind a
reverse proxy). Family canon is how such an idea is recorded once, reaches
every project on that platform, and gets an answer from each. Nobody
approves anything. **You decide, against written criteria, and the decision
log keeps you consistent with the last decision like it.** The tools quote
the criteria, the outcomes and the conflict order in full; this skill is when
to reach for them and what a good answer looks like.
The shape is the point, not identical code: the same idea in Kotlin and in
Go is one idea with two reference implementations.
## When an idea is evaluated for promotion
A `family_hint` on a create_note / create_snippet response means a trigger
opened an evaluation: the record cites another project's record as its
source, or it repeats a record in a project on a shared platform. The source
is now a `candidate`. Evaluate it in the same turn, while you know why you
wrote what you wrote:
1. `get_family_idea(id)` — the candidate, its decisions, and the precedents
(decisions on the ideas nearest it).
2. Judge the three criteria from `promote_family_idea`'s description. Each
needs support you can name; **one criterion with no support vetoes it**.
3. Promote it, or leave it a candidate with the reason. A held candidate is
precedent too, so the reason is the record — never skip writing it.
4. If rules already bind the idea — a rule topic written for it — link that
topic with `set_family_topic`. The note teaches; the topic's rules bind,
and every assessment then reads them beside the idea.
A milestone closing on a platform project hints without recording anything:
ask whether what it built is something every project on the platform will
face, and if so write the note that carries the idea.
## Answering an idea in a project
enter_project's `family` key counts what this project owes the family:
`unassessed`, `owed`, `needs_recheck`, each with the call that lists them.
Answer an idea **when your work reaches its area**, not as a chore list at
session start — the count is there so it is never invisible, not so it
preempts the operator's task.
- `get_family_adoption(project_id, idea_id)` first: the idea, the project's
current answer, the precedents, and the reference implementations with the
project's languages.
- Judge the outcomes **in the order `assess_family_adoption` lists them**,
stopping at the first that holds. Every outcome needs a reason; `adopted`
needs evidence naming where.
- **When the code is in the shape ledger, answer there instead:**
`classify_shapes` the shape with `idea_id=` as an `instance` or a
`variant`, and the adoption answer moves with it. An answer the shapes
contradict is refused — fix the shapes, not the answer.
- `owed` files a task in THAT project and stops. Nothing here edits another
repository; the project's own session picks the task up.
### What counts as a reason
A reason names a **fact about this project**: "the app is installed by a
managed store, never sideloaded", "the service has no user accounts". A
preference, a taste, or "we already did it another way" is not a reason —
that is `owed`, or, if this project's way is better rather than different, a
conflict. Write the reason so a session in another project can tell whether
the same fact holds there; that is how it becomes precedent.
### The precedent reflex
Before answering, read what was answered before: the same idea in other
projects, and this project's answers to the nearest ideas. Answer
consistently unless this project differs in a way you can name — and then
the difference IS the reason. The engine records the precedents it found
whether or not you cite them, so an inconsistent answer is visible later.
## When two projects disagree
Two projects solving one idea differently, each sure of its way, is a
conflict — settle it with `resolve_family_conflict`, which states the order.
The first ground that applies wins, and **every ground above it must be said
not to apply** — you cannot skip to the one you like. The losing side's
reasoning is folded into the idea's note (as a trap, an alternative, or the
branch for its condition) and never dropped; the version moves, so every
other project's answer reads as needing a recheck.
## Reporting it
A `family_owed` list on a closing task is work you filed into other projects
while it was open: name each one in the report, by project and idea — it is
waiting there now.