--- 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. 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.