--- name: colette-bridge description: | Bridges ArcheFlow with the Colette writing platform. Auto-detects colette.yaml in the project root, resolves voice profiles, personas, and character sheets, then builds a summarized context bundle that gets injected into every agent prompt via artifact routing. Eliminates manual copy-pasting of writing context into agent prompts. Automatically loaded when colette.yaml is detected at run.start User: "archeflow:run" in a project with colette.yaml --- # Colette Bridge — Writing Context Auto-Loader When ArcheFlow detects `colette.yaml` in the project root, this skill automatically loads voice profiles, personas, character sheets, and project rules into a context bundle that every agent receives (filtered by archetype role). ## Prerequisites - `archeflow:domains` — Colette Bridge sets domain to `writing` automatically - `archeflow:artifact-routing` — bundle is injected via the artifact routing system - `archeflow:run` — bridge hooks into run initialization ## Trigger At `run.start`, after domain detection but before the Plan phase: 1. Check if `colette.yaml` exists in the project root 2. If found, activate Colette Bridge 3. If not found, skip silently (no error, no warning) When the bridge activates, it emits a decision event: ```bash ./lib/archeflow-event.sh "$RUN_ID" decision init "" \ '{"what":"colette_bridge","chosen":"activated","signal":"colette.yaml found","files_resolved":}' ``` --- ## File Resolution Colette projects reference files by ID (e.g., `vp-giesing-gschichten-v1`) but the actual YAML files may live in different locations. The bridge resolves files using this search order: ### Search Priority (highest first) | Priority | Location | Example | |----------|----------|---------| | 1 | Explicit path in `colette.yaml` | `voice.profile: ../writing.colette/profiles/custom.yaml` | | 2 | Project root subdirectories | `./profiles/vp-giesing-gschichten-v1.yaml` | | 3 | Parent directory + `writing.colette/` | `../writing.colette/profiles/vp-giesing-gschichten-v1.yaml` | ### What Gets Resolved | Source | colette.yaml field | Search paths | |--------|-------------------|-------------| | Voice profile | `voice.profile` | `profiles/.yaml`, `../writing.colette/profiles/.yaml` | | Persona | `writing.persona` or inferred from profile | `personas/.yaml`, `../writing.colette/personas/.yaml` | | Characters | Auto-discovered | `characters/*.yaml` | | Series config | `series` section (if present) | `colette.yaml` itself, `../writing.colette/series/.yaml` | | Project rules | Always | `CLAUDE.md` in project root | ### Resolution Procedure ``` for each reference in colette.yaml: 1. If the field contains a path (has / or .yaml) → use as-is, verify exists 2. If the field contains an ID (e.g., "vp-giesing-gschichten-v1"): a. Check ./profiles/.yaml (or ./personas/.yaml) b. Check ../writing.colette/profiles/.yaml (or ../writing.colette/personas/.yaml) c. If not found → warn in event log, skip this file 3. For characters/ → glob characters/*.yaml in project root 4. For CLAUDE.md → check project root ``` If a referenced file cannot be found at any location, emit a warning event but do not abort: ```bash ./lib/archeflow-event.sh "$RUN_ID" decision init "" \ '{"what":"colette_bridge_warning","chosen":"skip","file":"vp-giesing-gschichten-v1","reason":"not found in any search path"}' ``` --- ## Context Bundle The bridge generates `.archeflow/context/colette-bundle.md` — a summarized, token-efficient Markdown file that agents receive as part of their prompt context. ### Bundle Structure ```markdown # Writing Context (auto-loaded from Colette) ## Voice Profile: **Tone:** **Perspective:** **Density:** **Attitude:** **Sharpness:** **Humor:** **Tempo:** **Reader relationship:** ### Forbidden - ### Allowed - ### Style models - ## Persona: **Name:** **Bio:** **Genres:** ### Rules - ## Characters ### () - **Age:** - **Key traits:** - **Speech:** - **Relationships:** [Repeated for each character in characters/*.yaml] ## Series Context [Only if series config found in colette.yaml] - **Shared concepts:** - **Glossary:** - **Forbidden cross-story:** ## Project Rules (from CLAUDE.md) [Key writing rules extracted from CLAUDE.md, summarized as bullet points] - - - ... ``` ### Summarization Rules The bundle is **summarized**, not a raw YAML dump. This reduces token cost: - Voice profile dimensions: key name + value (no YAML formatting, no `dimensionen:` wrapper) - Verboten/erlaubt: bullet list, strip explanation after the dash if over 15 words - Characters: name, role, age, top 3 traits, first sentence of speech pattern, relationships - Persona bio: max 2 sentences - CLAUDE.md: extract only rules/style sections, skip meta/git/cost config - Target: bundle should be under 1500 tokens for a typical project --- ## Caching The bundle is regenerated only when source files have changed. Cache validation uses file modification times. ### Cache Check Procedure ``` bundle_path = .archeflow/context/colette-bundle.md if bundle_path does not exist → generate if bundle_path exists: bundle_mtime = mtime of bundle_path for each resolved source file: if source_mtime > bundle_mtime → regenerate, break if no source file is newer → use cached bundle ``` When the cache is valid, emit: ```bash ./lib/archeflow-event.sh "$RUN_ID" decision init "" \ '{"what":"colette_bundle_cache","chosen":"reuse","reason":"all sources older than bundle"}' ``` When regenerating: ```bash ./lib/archeflow-event.sh "$RUN_ID" decision init "" \ '{"what":"colette_bundle_cache","chosen":"regenerate","reason":" modified since last bundle"}' ``` --- ## Per-Agent Attention Filters Not every agent needs the full bundle. The bridge defines attention filters that control which sections each archetype receives. This extends the base attention filters from `archeflow:attention-filters`. | Archetype | Bundle sections injected | Rationale | |-----------|------------------------|-----------| | **Explorer** | Full bundle | Needs all context for research — setting, characters, voice, rules | | **Creator** | Voice dimensions + persona rules + characters | Designs outline — needs to know who speaks how, who exists, what's allowed | | **Maker** | Full bundle | Writes prose — needs voice for style, characters for dialogue, rules for guardrails | | **Guardian** | Characters + series shared_concepts | Checks consistency — needs character facts and cross-story constraints | | **Sage** | Voice profile (full, including verboten/erlaubt) + persona rules | Checks voice drift — needs the complete voice spec and persona constraints | | **Trickster** | Characters + series glossary | Tests continuity — needs character facts and terminology for contradiction checks | ### Filter Implementation When injecting the bundle into an agent prompt, extract only the relevant sections: ``` # For Guardian: Extract: "## Characters" section (all characters) Extract: "## Series Context" section (if present) Skip: everything else # For Sage: Extract: "## Voice Profile" section (full, with forbidden/allowed) Extract: "## Persona" section (rules subsection) Skip: characters, series, project rules # For Explorer and Maker: Inject: full bundle as-is ``` The filtering happens at prompt assembly time, not at bundle generation time. One bundle, multiple filtered views. ### Custom Archetypes Custom archetypes (e.g., `story-explorer`, `story-sage`) inherit the filter of their closest base archetype: | Custom archetype | Inherits filter from | Override | |-----------------|---------------------|----------| | `story-explorer` | Explorer | Full bundle | | `story-sage` | Sage | Full voice profile + persona rules | | `story-guardian` | Guardian | Characters + series | If a custom archetype needs a different filter, define it in the archetype's markdown frontmatter: ```yaml --- name: story-sage colette_filter: [voice_profile, persona, characters] --- ``` The `colette_filter` field accepts section keys: `voice_profile`, `persona`, `characters`, `series`, `project_rules`, `full`. --- ## Integration with Run Skill The Colette Bridge hooks into `archeflow:run` initialization. The sequence is: ``` run.start ├── Domain detection (from archeflow:domains) │ └── colette.yaml found → domain = writing ├── Colette Bridge activation │ ├── Resolve files (voice profile, persona, characters, CLAUDE.md) │ ├── Check bundle cache │ ├── Generate/refresh bundle → .archeflow/context/colette-bundle.md │ └── Register bundle path in artifact routing └── Continue to Plan phase ``` ### Artifact Routing Registration The bundle path is registered so that every phase's context injection includes the (filtered) bundle: ``` artifact_routing.register_context( path = ".archeflow/context/colette-bundle.md", inject_at = "all_phases", filter_by = "archetype" # Apply per-agent attention filters ) ``` In practice, this means the run skill prepends the filtered bundle content to each agent's prompt, after the standard task description but before phase-specific artifacts. ### Prompt Injection Order ``` 1. Archetype definition (from SKILL.md or custom archetype .md) 2. Domain-specific review focus (from archeflow:domains) 3. Colette bundle (filtered for this archetype) 4. Task description 5. Phase-specific artifacts (Explorer output, Creator proposal, etc.) 6. Cycle feedback (if cycle 2+) ``` --- ## Example: Giesing Gschichten Given this `colette.yaml`: ```yaml project: name: "Giesing Gschichten" author: "C. Nennemann" language: de type: fiction voice: profile: vp-giesing-gschichten-v1 writing: target_words: 6000 style: "Ich-Erzaehler, lakonisch, Eberhofer-meets-Grossstadt" ``` The bridge: 1. Reads `voice.profile: vp-giesing-gschichten-v1` 2. Searches for `./profiles/vp-giesing-gschichten-v1.yaml` — not found 3. Searches for `../writing.colette/profiles/vp-giesing-gschichten-v1.yaml` — found 4. Infers persona from voice profile ID pattern or searches `personas/` — finds `giesinger.yaml` at `../writing.colette/personas/giesinger.yaml` 5. Globs `characters/*.yaml` — finds `alex.yaml` (and others if present) 6. Reads `CLAUDE.md` for writing rules 7. Generates bundle: ```markdown # Writing Context (auto-loaded from Colette) ## Voice Profile: vp-giesing-gschichten-v1 **Tone:** Lakonisch, warmherzig-genervt, trockener Humor **Perspective:** Ich-Erzaehler (Alex), nah dran, subjektiv **Density:** Alltagsdetails die Atmosphaere schaffen **Attitude:** Lakonisch, leicht genervt, aber mit Herz **Sharpness:** Beobachtungsscharf, sprachlich reduziert **Humor:** Trocken, Understatement, absurde Situationen **Tempo:** Gemaechlich mit Spannungsspitzen, Slow Burn **Reader relationship:** Kumpel am Stammtisch ### Forbidden - Hochdeutsch-Sterilitaet - Krimi-Klischees (CSI, Profiler, Tatort) - Lederhosen-Kitsch und Oktoberfest-Folklore - Dialekt-Overkill - Moralisieren oder Erklaeren - Kuenstliche Spannungsaufbauten - Adverb-Orgien und Adjektiv-Ketten - Infodumps ### Allowed - Bairische Einsprengsel in Hochdeutsch-Prosa - Essen und Trinken als Leitmotiv - Kiffer-Humor und Slow-Motion-Beobachtungen - Gentrification-Satire - Echte Giesinger Orte und Strassen - Skurrile Nachbarn - Kriminalplot aus dem Alltag - Kurze, lakonische Dialoge ### Style models - Rita Falk (Erzaehlton), Wolf Haas (lakonisch), Helmut Dietl (Muenchner Milieu), Friedrich Ani (duester), Bukowski (Anti-Held) ## Persona: giesinger **Name:** Der Giesinger **Bio:** Erzaehlt Geschichten aus Muenchen-Giesing. Eberhofer meets Grossstadt. **Genres:** Krimi, Kurzgeschichte, Milieustudie ### Rules - Ich-Erzaehler, immer — Alex erzaehlt - Hauptsaechlich Hochdeutsch mit bairischen Einsprengsel - Jede Geschichte hat einen Kriminalplot - Essen/Trinken in jeder Geschichte - Echte Giesinger Orte und Strassen - Humor durch Understatement - Alex ist kein Ermittler - Figuren reden wie echte Menschen ## Characters ### Alex (protagonist) - **Age:** Mitte 30 - **Key traits:** Lakonisch, funktionaler Kiffer, unmotiviert aber nicht dumm - **Speech:** Kurze Saetze, Hochdeutsch mit bairischen Einsprengsel. - **Relationships:** Mo — Nachbar, Kumpel und Unruhestifter ## Project Rules (from CLAUDE.md) - Jede Geschichte beginnt mit einer Alltagsszene - Kriminalplot ergibt sich organisch aus dem Alltag - Essen/Trinken in jeder Geschichte - Echte Giesinger Orte verwenden - Kein Moralisieren, kein Erklaerbaer - Ende muss nicht alles aufloesen ``` --- ## Design Principles 1. **Summarize, don't dump.** Raw YAML wastes tokens and confuses agents. The bundle is a curated briefing. 2. **Cache aggressively.** Voice profiles and characters rarely change mid-run. Only regenerate when mtimes change. 3. **Filter per agent.** A Guardian checking plot consistency does not need the full voice profile. A Sage checking voice drift does not need character sheets. 4. **Graceful degradation.** Missing files are warned about, not fatal. A project with `colette.yaml` but no characters/ still works — the Characters section is simply empty. 5. **One bundle, filtered views.** Generate the full bundle once. Filter at injection time per archetype. This keeps caching simple. 6. **Additive to existing skills.** The bridge does not replace domain detection or artifact routing — it hooks into them. Remove the bridge, everything still works (just without auto-loaded writing context).