feat: import Layered Soul skills into Colibri (+ integration doc)
Some checks failed
CI / rust (pull_request) Has been cancelled
CI / markdown (pull_request) Has been cancelled

Wires clawdie/layered-soul (the portable identity/context source) into Colibri.
scripts/import-layered-soul.sh reads its reviewed skills/**/*.md into the existing
`skills` catalog (mirrors import-clawdie-skills.sh; idempotent, frontmatter
name/description, category from the skill's parent dir).

Honest scope: only skills are wired. The adapter's "Layered Memory Fabric"
(system_brain / system_ops + a richer system_skills) is design-only
(COLIBRI-SKILLS-PLAN.md), so curated memory is reported-but-not-imported and the
gap is documented in docs/INTEGRATION-LAYERED-SOUL.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Sam & Claude 2026-06-13 22:14:14 +02:00
parent 6a72befbb4
commit 252c282298
2 changed files with 119 additions and 0 deletions

View file

@ -0,0 +1,43 @@
# Integration: Layered Soul → Colibri
[clawdie/layered-soul](https://code.smilepowered.org/clawdie/layered-soul) is the
portable, harness-agnostic source of durable identity + reviewed context. This doc
records how Colibri consumes it **today**, and what is still **planned** — so the
contract isn't mistaken for fully-built.
## What's wired (works now)
Reviewed **skills** import into Colibri's existing `skills` catalog:
scripts/import-layered-soul.sh <layered-soul-dir> <colibri.sqlite>
It reads `skills/**/*.md` (frontmatter `name` / `description`; category derived
from the skill's parent dir), and `INSERT OR IGNORE`s rows into the `skills`
table. Same mechanism and table as `clawdie-iso/scripts/import-clawdie-skills.sh`;
idempotent, safe to re-run.
## What's deferred (planned, not built)
The `adapters/colibri.md` in layered-soul names a "Layered Memory Fabric" with
three stores — `system_skills`, `system_brain`, `system_ops`. As of 2026-06-13
only a single flat `skills` table exists; the rest is **design only**
(`docs/COLIBRI-SKILLS-PLAN.md`), so the importer intentionally does not target it.
| Layered Soul source | Target (planned) | Status |
| ---------------------------- | ---------------- | -------------------------------------------------------- |
| `skills/**/*.md` | `system_skills` | imported into the flat `skills` table today |
| `memories/curated/**/*.md` | `system_brain` | NOT imported — no store yet (the importer reports a count) |
| converted task/job manifests | `system_ops` | NOT implemented |
## Direction (one-way)
`layered-soul` (git) is the **source of truth**; Colibri is a **consumer**. Import
flows one way (repo → Colibri). Don't hand-edit the imported runtime copy and
expect it to flow back — curate in the repo, then re-import.
## Closing the gap (future work)
1. Implement `system_brain` per `COLIBRI-SKILLS-PLAN.md`, then extend the importer
to load `memories/curated/`.
2. Migrate the flat `skills` table to the planned `system_skills` schema.
3. Define and import `system_ops` task/job manifests.

76
scripts/import-layered-soul.sh Executable file
View file

@ -0,0 +1,76 @@
#!/bin/sh
# Import a Layered Soul repo's reviewed skills into the Colibri skills catalog.
#
# Layered Soul (clawdie/layered-soul) is the portable, harness-agnostic source of
# durable identity + curated context. This wires its reviewed `skills/**/*.md`
# into Colibri's existing `skills` SQLite table.
#
# Scope note (see docs/INTEGRATION-LAYERED-SOUL.md): only skills are imported.
# Curated memory (`memories/curated/**/*.md`) is reported but NOT imported yet —
# Colibri has no `system_brain` store; `system_brain`/`system_ops` and the
# "Layered Memory Fabric" are planned (docs/COLIBRI-SKILLS-PLAN.md), not built.
#
# Usage:
# scripts/import-layered-soul.sh <layered-soul-dir> <colibri-sqlite-db>
set -eu
SOUL="${1:?usage: $0 <layered-soul-dir> <colibri-sqlite-db>}"
DB="${2:?usage: $0 <layered-soul-dir> <colibri-sqlite-db>}"
command -v sqlite3 >/dev/null 2>&1 || { echo "error: sqlite3 not available" >&2; exit 1; }
# Sanity: looks like a Layered Soul repo?
if [ ! -f "$SOUL/manifest.json" ] || [ ! -f "$SOUL/SOUL.md" ]; then
echo "error: $SOUL does not look like a layered-soul repo (no manifest.json / SOUL.md)" >&2
exit 1
fi
sqlite3 "$DB" "CREATE TABLE IF NOT EXISTS skills (
id TEXT PRIMARY KEY NOT NULL,
name TEXT NOT NULL UNIQUE,
description TEXT,
category TEXT,
created_at TEXT NOT NULL
);" 2>/dev/null || true
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
# Reviewed skills: skills/**/*.md (skip READMEs). find|while runs in a subshell,
# so keep the counters + summary together inside one { } group.
find "$SOUL/skills" -type f -name '*.md' ! -iname 'README.md' 2>/dev/null | sort | {
imported=0
skipped=0
while IFS= read -r skill_md; do
[ -f "$skill_md" ] || continue
frontmatter=$(sed -n '/^---$/,/^---$/p' "$skill_md" | sed '1d;$d')
name=$(printf '%s\n' "$frontmatter" | grep -m1 '^name:' | sed 's/^name: *//' | tr -d '"')
# Fall back to the file's basename when there is no frontmatter name.
[ -n "$name" ] || name=$(basename "$skill_md" .md)
[ -n "$name" ] || { skipped=$((skipped + 1)); continue; }
description=$(printf '%s\n' "$frontmatter" | grep -m1 '^description:' | sed 's/^description: *//' | tr -d '"')
[ -n "$description" ] || description="Layered Soul skill: $name"
# Category = the skill's parent dir under skills/, else "soul".
rel=${skill_md#"$SOUL"/skills/}
case "$rel" in
*/*) category=$(printf '%s' "$rel" | cut -d/ -f1) ;;
*) category="soul" ;;
esac
id=$(uuidgen 2>/dev/null || python3 -c 'import uuid;print(uuid.uuid4())' 2>/dev/null || echo "soul-skill-$name")
if sqlite3 "$DB" "INSERT OR IGNORE INTO skills (id, name, description, category, created_at)
VALUES ('$id', '$(printf '%s' "$name" | sed "s/'/''/g")', '$(printf '%s' "$description" | sed "s/'/''/g")', '$(printf '%s' "$category" | sed "s/'/''/g")', '$NOW');" 2>/dev/null; then
imported=$((imported + 1))
else
skipped=$((skipped + 1))
fi
done
echo " layered-soul skills: $imported imported, $skipped skipped"
}
# Curated memory: reported only (no destination store yet).
mem_count=$(find "$SOUL/memories/curated" -type f -name '*.md' ! -iname 'README.md' 2>/dev/null | wc -l | tr -d ' ')
if [ "${mem_count:-0}" -gt 0 ]; then
echo " NOTE: $mem_count curated memory file(s) found — NOT imported."
echo " Colibri has no system_brain store yet (planned: docs/COLIBRI-SKILLS-PLAN.md);"
echo " see docs/INTEGRATION-LAYERED-SOUL.md."
fi