- skills/memory: cross-run learning from recurring findings + lib/archeflow-memory.sh - skills/convergence: oscillation detection + early termination in multi-cycle runs - skills/colette-bridge: auto-inject voice profiles, personas, characters from colette.yaml - skills/templates: workflow/team/archetype gallery with init/save/share - skills/progress: live .archeflow/progress.md during runs - skills/effectiveness: per-archetype signal-to-noise + cost efficiency scoring - skills/git-integration: auto-branch per run, commit per phase, rollback support
393 lines
14 KiB
Markdown
393 lines
14 KiB
Markdown
---
|
|
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.
|
|
<example>Automatically loaded when colette.yaml is detected at run.start</example>
|
|
<example>User: "archeflow:run" in a project with colette.yaml</example>
|
|
---
|
|
|
|
# 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":<count>}'
|
|
```
|
|
|
|
---
|
|
|
|
## 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/<id>.yaml`, `../writing.colette/profiles/<id>.yaml` |
|
|
| Persona | `writing.persona` or inferred from profile | `personas/<id>.yaml`, `../writing.colette/personas/<id>.yaml` |
|
|
| Characters | Auto-discovered | `characters/*.yaml` |
|
|
| Series config | `series` section (if present) | `colette.yaml` itself, `../writing.colette/series/<name>.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/<id>.yaml (or ./personas/<id>.yaml)
|
|
b. Check ../writing.colette/profiles/<id>.yaml (or ../writing.colette/personas/<id>.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: <id>
|
|
**Tone:** <tone_summary from meta>
|
|
**Perspective:** <perspektive>
|
|
**Density:** <dichte>
|
|
**Attitude:** <haltung>
|
|
**Sharpness:** <schaerfe>
|
|
**Humor:** <humor>
|
|
**Tempo:** <tempo>
|
|
**Reader relationship:** <leser_beziehung>
|
|
|
|
### Forbidden
|
|
- <each item from verboten>
|
|
|
|
### Allowed
|
|
- <each item from erlaubt>
|
|
|
|
### Style models
|
|
- <each item from vorbilder, name only + one-word tag>
|
|
|
|
## Persona: <id>
|
|
**Name:** <name>
|
|
**Bio:** <bio, max 2 sentences>
|
|
**Genres:** <genres, comma-separated>
|
|
|
|
### Rules
|
|
- <each item from rules>
|
|
|
|
## Characters
|
|
### <name> (<role>)
|
|
- **Age:** <age>
|
|
- **Key traits:** <first 3 personality items>
|
|
- **Speech:** <speech_pattern, first sentence only>
|
|
- **Relationships:** <key relationships, one line each>
|
|
|
|
[Repeated for each character in characters/*.yaml]
|
|
|
|
## Series Context
|
|
[Only if series config found in colette.yaml]
|
|
- **Shared concepts:** <list>
|
|
- **Glossary:** <key terms>
|
|
- **Forbidden cross-story:** <items>
|
|
|
|
## Project Rules (from CLAUDE.md)
|
|
[Key writing rules extracted from CLAUDE.md, summarized as bullet points]
|
|
- <rule 1>
|
|
- <rule 2>
|
|
- ...
|
|
```
|
|
|
|
### 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":"<file> 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).
|