fde-promote — count sightings, pave at three
The write side of compounding, and the only path by which anything leaves an
engagement's confidential boundary. Rule of Three (Fowler, Refactoring),
made mechanical: a pattern enters the corpus as a candidate (×1), becomes
recurring (×2), and at the third sighting is paved into the schema —
evolved_slots gains the slot, version bumps, and git diff .fde/schemas/
shows exactly what three engagements taught you. Two-layer by design: you
(LLM) decide what is durable and paraphrase out the client; the script
counts, redacts, gates, and paves.
Steps
- Resolve
<client> and <type>. Read the deliverable's .md and
.slots.yml.
- Read the corpus first:
.fde/corpus/<type>.yml. Sighting counting
works by key reuse — if a learning matches an existing entry's meaning,
you MUST reuse that entry's key (that's what increments the counter). Only
mint a new kebab-case key for a genuinely new pattern.
- Semantic anonymization (LLM): rewrite each learning you want to keep as
a generalizable pattern, not this client's situation. Strip names, people,
internal system names, industries-if-identifying, specific figures. If a
learning is too client-specific to generalize, drop it. If it names a person
or system the scripts can't know about, also add that token to
anonymization.extra_identifiers in .fde/config.yml so the gate can
enforce it forever.
- Stage the patterns as
engagements/<client>/deliverables/<type>.promote.yml:schema: <type>
patterns:
- key: sso-auth-integration # reused key -> sighting +1
slot: technical_risks # existing slot id, or a proposed new one
label: "" # label+prompt only for NEW-slot proposals
prompt: ""
pattern: "one-line generalized learning, already anonymized"
- Run the deterministic promote:
.fde/bin/fde-promote.sh <client> <type>
The script redacts figures + identifiers, merges into the corpus with
sighting counters, refuses to touch the corpus if the merged result would
leak an identifier, paves anything that hit the threshold, and re-runs
fde-validate.sh. Report its output verbatim — especially PAVED: lines
and LEAK BLOCKED: failures.
- If something paved, refresh the wall (
.fde/bin/fde-dashboard.sh) and show
the user the schema diff (git diff .fde/schemas/ if the workspace is a
repo). That diff is the payoff.
Hard rules
- The script's redaction is a backstop, not the primary control. Do the
semantic anonymization first; never rely on regex to catch a client name you
could have paraphrased away.
- If the script prints
LEAK BLOCKED, treat it as a hard failure: fix the
staged pattern text, don't work around the gate.
- Promote patterns, not client deliverables. The corpus is a library of
reusable structure, not a copy of past clients' documents.
- Never edit
.fde/corpus/*.yml or a schema's evolved_slots by hand — the
script is the only writer, so the counters stay trustworthy.
1---2name: promote3description: Use when a deliverable taught something reusable and the user wants it to benefit future engagements (e.g. "promote these learnings", "save this to the corpus", "make this reusable across clients"). Anonymizes the learnings, stages them with stable pattern keys, and runs the deterministic promote script — which counts sightings and, at the third, paves the pattern into the schema.4---56# fde-promote — count sightings, pave at three78The write side of compounding, and the only path by which anything leaves an9engagement's confidential boundary. Rule of Three (Fowler, *Refactoring*),10made mechanical: a pattern enters the corpus as a **candidate** (×1), becomes11**recurring** (×2), and at the third sighting is **paved** into the schema —12`evolved_slots` gains the slot, `version` bumps, and `git diff .fde/schemas/`13shows exactly what three engagements taught you. Two-layer by design: you14(LLM) decide *what* is durable and paraphrase out the client; the script15counts, redacts, gates, and paves.1617## Steps18191. Resolve `<client>` and `<type>`. Read the deliverable's `.md` and20 `.slots.yml`.212. **Read the corpus first**: `.fde/corpus/<type>.yml`. Sighting counting22 works by **key reuse** — if a learning matches an existing entry's meaning,23 you MUST reuse that entry's `key` (that's what increments the counter). Only24 mint a new kebab-case key for a genuinely new pattern.253. **Semantic anonymization (LLM)**: rewrite each learning you want to keep as26 a *generalizable pattern*, not this client's situation. Strip names, people,27 internal system names, industries-if-identifying, specific figures. If a28 learning is too client-specific to generalize, drop it. If it names a person29 or system the scripts can't know about, also add that token to30 `anonymization.extra_identifiers` in `.fde/config.yml` so the gate can31 enforce it forever.324. **Stage** the patterns as33 `engagements/<client>/deliverables/<type>.promote.yml`:34 ```yaml35 schema: <type>36 patterns:37 - key: sso-auth-integration # reused key -> sighting +138 slot: technical_risks # existing slot id, or a proposed new one39 label: "" # label+prompt only for NEW-slot proposals40 prompt: ""41 pattern: "one-line generalized learning, already anonymized"42 ```435. **Run the deterministic promote**:44 ```bash45 .fde/bin/fde-promote.sh <client> <type>46 ```47 The script redacts figures + identifiers, merges into the corpus with48 sighting counters, refuses to touch the corpus if the merged result would49 leak an identifier, paves anything that hit the threshold, and re-runs50 `fde-validate.sh`. Report its output verbatim — especially `PAVED:` lines51 and `LEAK BLOCKED:` failures.526. If something paved, refresh the wall (`.fde/bin/fde-dashboard.sh`) and show53 the user the schema diff (`git diff .fde/schemas/` if the workspace is a54 repo). That diff is the payoff.5556## Hard rules57- The script's redaction is a *backstop*, not the primary control. Do the58 semantic anonymization first; never rely on regex to catch a client name you59 could have paraphrased away.60- If the script prints `LEAK BLOCKED`, treat it as a hard failure: fix the61 staged pattern text, don't work around the gate.62- Promote *patterns*, not client deliverables. The corpus is a library of63 reusable structure, not a copy of past clients' documents.64- Never edit `.fde/corpus/*.yml` or a schema's `evolved_slots` by hand — the65 script is the only writer, so the counters stay trustworthy.