Skip to content

feat(seeds): ship starter instincts library for common stacks#8

Open
NestorPVsf wants to merge 2 commits into
Luispitik:mainfrom
NestorPVsf:cortex-fusion-20260418
Open

feat(seeds): ship starter instincts library for common stacks#8
NestorPVsf wants to merge 2 commits into
Luispitik:mainfrom
NestorPVsf:cortex-fusion-20260418

Conversation

@NestorPVsf

Copy link
Copy Markdown
Contributor

Motivation

Empty-install UX is harsh: new users see the whole observability pipeline (instincts-index, proposals, dashboard, dream cycle) but zero accumulated knowledge. Until they generate enough observations to crystallize their own instincts, Sinapsis sits idle.

This PR ships 7 seed instincts that activate immediately for common Claude Code stacks — Supabase, Stripe, Next.js, Playwright, Vercel, and conventional commits.

What's included

Seeds (seeds/instincts/*.yaml)

Seed Domain Confidence Maps to
conventional-commits workflow-general 0.90 permanent
supabase-rls-auth-uid database 0.85 confirmed
service-role-cross-user security 0.85 confirmed
nextjs-suspense-boundary web-development 0.80 confirmed
stripe-webhook-verify saas-development 0.80 confirmed
e2e-playwright-selectors testing 0.75 confirmed
security-headers-vercel security 0.75 confirmed

Importer (core/_seed-import.py)

  • Idempotent: skips IDs already in _instincts-index.json. Safe to re-run.
  • origin is prefixed seed: so Dream Cycle / dashboard can distinguish seeded vs learned knowledge.
  • CLI flags: --skip <id,…>, --force-draft <id,…>, --seeds-dir, --index-path, --dry-run.
  • Portable (respects SINAPSIS_HOME, cygpath-aware tests).

Install integration (install.sh)

Two lines added in Step 5 — copy seed YAMLs + run importer. Idempotency makes upgrades a no-op.

Tests (tests/test-seeds.sh)

8 TDD tests, 8/8 GREEN on Git Bash (Windows). Covers: file presence, seed count, fresh import, idempotency, origin prefix, confidence→permanent mapping, --skip, --force-draft.

Seed format attribution

The YAML format comes from fs-cortex (MIT © Fernando Montero). Each imported seed carries the attribution header. Sinapsis extends the format by mapping the continuous confidence field to its existing discrete levels via thresholds:

confidence ≥0.90  → permanent
confidence 0.70-0.89 → confirmed
confidence <0.70  → draft

Nothing about the promotion ritual (/promote, /evolve) changes. Seeds enter at their mapped level and participate in the same lifecycle — decay via Dream Cycle, downvote, promotion. Users can filter them out via origin or --skip them at install.

Test plan

  • bash tests/test-seeds.sh → 8/8 passed
  • Fresh install on Windows (Git Bash) — seeds imported, existing instincts untouched
  • Re-run installer — 0 new imports, all 7 reported as "already present"
  • Maintainer: verify on macOS / Linux (cygpath path branch is Windows-only; POSIX path branch should work transparently)

Follow-ups not in this PR

  • seeds/laws/ tier (always-injected one-liners) — exploring in a separate PR once this design lands
  • Additional starter seeds for other stacks (Prisma, tRPC, Vue, etc.) — community contributions welcome once the mechanism is in place

Continues the pattern of #3 (regression sweep) and #7 (dashboard schema fix).

🤖 Generated with Claude Code

Empty-install UX is harsh: new users see the whole observability pipeline
but zero accumulated knowledge. This PR ships 7 seed instincts that
activate immediately for common Claude Code stacks — Supabase, Stripe,
Next.js, Playwright, Vercel, and conventional commits.

Seed format
───────────
YAML frontmatter with id, trigger (regex), action (inject), confidence
(0.0-1.0), domain, tags, scope, source, first_seen, last_seen,
occurrences, and evidence. The format originated in fs-cortex (MIT ©
Fernando Montero, https://github.com/fermonterom/fs-cortex). Each YAML
in this PR carries attribution. Sinapsis extends the format by mapping
confidence to the existing discrete levels via thresholds:

  confidence ≥0.90 → permanent
  confidence 0.70-0.89 → confirmed
  confidence <0.70 → draft

What's included
───────────────
seeds/instincts/
  conventional-commits.yaml           workflow-general   0.90 → permanent
  supabase-rls-auth-uid.yaml          database           0.85 → confirmed
  service-role-cross-user.yaml        security           0.85 → confirmed
  nextjs-suspense-boundary.yaml       web-development    0.80 → confirmed
  stripe-webhook-verify.yaml          saas-development   0.80 → confirmed
  e2e-playwright-selectors.yaml       testing            0.75 → confirmed
  security-headers-vercel.yaml        security           0.75 → confirmed

core/_seed-import.py                  Importer (idempotent, safe)
tests/test-seeds.sh                   8 TDD tests (8/8 GREEN)

Importer design
───────────────
* Idempotent: skips IDs already present in _instincts-index.json. Safe
  to re-run on every upgrade.
* origin field prefixed "seed:" so Dream Cycle / dashboard can
  distinguish seeded knowledge from learned knowledge.
* Optional CLI flags for user control:
    --skip <id,id,...>         Don't import these
    --force-draft <id,id,...>  Import but force level=draft
    --seeds-dir <path>         Override source
    --index-path <path>        Override destination
    --dry-run                  Show what would happen
* Portable: respects SINAPSIS_HOME env var, cygpath-aware tests.

Install integration
───────────────────
install.sh now (a) copies seed YAMLs to $SKILLS_DIR/_seeds/instincts/
and (b) runs the importer automatically. On upgrades, idempotency
means existing installs with matching IDs are unaffected.

Tests
─────
tests/test-seeds.sh: 8/8 passing
  1. importer file exists
  2. seeds directory populated
  3. fresh import creates N instincts (7)
  4. second run is idempotent
  5. origin field is prefixed "seed:"
  6. confidence ≥0.90 → permanent (conventional-commits)
  7. --skip flag excludes IDs
  8. --force-draft flag forces level=draft

Philosophy
──────────
This does not change Sinapsis's promotion ritual (draft/confirmed/permanent
with /promote, /evolve). Seeds enter at their mapped level and participate
in the same lifecycle as any learned instinct — decay, downvote, promotion.
They are distinguishable via origin="seed:*" if a user wants to filter
them out. Users can --skip individual seeds at install time if they already
have equivalent passive rules or instincts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@Luispitik Luispitik left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gracias @NestorPVsf. Implementación técnica sólida (CI verde 3/3, idempotencia, --skip/--force-draft/--dry-run, cygpath, atribución correcta a fs-cortex). El mérito está.

Pero no puedo mergear tal cual porque rompe el foco y la filosofía base de Sinapsis. Sinapsis es un sistema de aprendizaje continuo autónomo: observa al operador, cristaliza sus patrones, los valida con occurrence tracking + multi-session auto-promote, y los purga con Dream Cycle. La estructura interna (_instincts-index.json, niveles, pipeline) existe para ese propósito. Inyectar 7 instincts ajenos por default en cada install contamina esa estructura y convierte el sistema en "learn-from-you + librería pre-cocinada", lo cual es otro producto.

Cambios requeridos antes de merge

1. NO importar seeds en install.sh

El installer debe permanecer agnóstico. Remueve el bloque "Step 5c" del install automático. El import tiene que ser opt-in explícito:

  • Opción A (preferida): comando dedicado /seed-import documentado en commands/seed-import.md. El usuario lo ejecuta conscientemente cuando lo quiera.
  • Opción B: flag SINAPSIS_SEEDS=1 bash install.sh para quien sí quiera bootstrap. Default = 0.

El importer + YAMLs + tests del PR se quedan; solo se elimina la activación automática.

2. Separar namespace de seeds del instinct-index canónico

Metes seeds directamente en _instincts-index.json junto a instincts reales aprendidos. Eso mezcla knowledge del operador con knowledge ajeno.

Opciones a discutir (abre issue, no bloquea el PR):

  • Tabla separada en el mismo JSON (instincts[] vs seeds[]), activator lee ambas pero dashboard/instinct-status las muestra por separado.
  • Fichero propio: _seeds-index.json + cambios en activator para consultar ambos.

Mientras tanto, con el origin: seed:* actual al menos es filtrable a posteriori — aceptable como v1.

3. Bajar TODOS los seeds a confirmed máximo (nada permanent)

permanent en Sinapsis significa "validado por occurrence + multi-session real". Un seed sin ninguna activación real no puede entrar permanent — viola el invariante del sistema y lo vuelve inmune a Dream Cycle y /downvote.

Cambia el mapping en confidence_to_level():

if c >= 0.85: return 'confirmed'  # nada de permanent desde seed
return 'draft'

O alternativamente: fuerza level=draft para todo seed, independientemente de confidence. Que la validación real lo promueva.

4. Estrechar triggers

Varios son excesivamente amplios y van a inyectar ruido. Ejemplos:

  • stripe-webhook-verify: stripe|webhook|payment|subscription|checkout → dispara con cualquier mención casual de "payment" o "checkout" que no sea Stripe. Estrecha a stripe.*webhook|constructEvent|STRIPE_WEBHOOK_SECRET.
  • conventional-commits: git commit|commit message|conventional → dispara al leer cualquier texto sobre commits. Estrecha a algo que solo matchee en contexto de redacción real: ^(feat|fix|chore|docs|refactor|test|perf|ci)\(|git commit -m.
  • Revisa los otros 5 con el mismo criterio.

5. Documentar en README que Sinapsis NO viene con seeds por default

Añade sección corta explicando: (a) que Sinapsis es learn-from-you, (b) que existe /seed-import como bootstrap opt-in para quien lo quiera, (c) cómo ver qué importarías antes con --dry-run.

6. Parser YAML ad-hoc

Aceptable como v1 — añade un comentario en parse_yaml_simple() documentando que rompe silenciosamente en nested/listas y que si se amplía el formato hay que migrar a PyYAML.

Nota sobre fs-cortex

El formato y los seeds vienen de Fernando Montero (MIT). La atribución en headers y PR body está bien. Cuando mergeemos esto, abriré issue en fs-cortex para confirmar que el crédito a él es suficiente — tu implementación del importer es original, el conocimiento no.

Resumen

  • Mérito del trabajo: reconocido.
  • Bloqueantes: (1) no instalar por default, (3) no permanent desde seed, (4) triggers estrechos, (5) doc filosofía.
  • Cambios menores: (6) comentario parser.
  • Post-merge / issue aparte: (2) namespace separado.

Cuando hagas los cambios, re-push y CI corre. Gracias.

Addresses 3 bugs flagged by Codex CLI during PR Luispitik#9 review. All 3 are
pre-existing in the feat(seeds) commit of PR Luispitik#8.

P1: install.sh hardcoded `python` instead of `$PYTHON_CMD` detected in
Step 1. On systems with only python3 in PATH, seed import failed and was
silently swallowed by `|| true`. Uses `$PYTHON_CMD` now with a warning
fallback when Python is unavailable.

P2: parse_yaml_simple stripped quotes but did not decode backslash
escapes. Seeds with `"spec\.ts"` were stored with literal backslashes,
producing invalid regex. Added _decode_yaml_double_quoted (handles
\ \" \n \t \r) and _decode_yaml_single_quoted (`''` → `'`). Fixes 3
broken seeds: e2e-playwright-selectors, security-headers-vercel,
supabase-rls-auth-uid.

P2: _instinct-activator.sh pre-filters by ALWAYS_DOMAINS + stack-detected
domains when context.md exists. Seed domains workflow-general, testing,
web-development, saas-development are outside both sets so those seeds
never reached regex evaluation. Added DOMAIN_MAP in importer:
workflow-general → operations, testing → quality, web-development →
frontend, saas-development → stripe. original_domain preserved for
traceability.

Tests: 3 new in test-seeds.sh (9-11). Suite 8/8 → 11/11 GREEN.

Credit: bugs identified by Codex CLI (cross-model review).
@NestorPVsf

Copy link
Copy Markdown
Contributor Author

Update: adds fix commit 3a1397a addressing 3 bugs flagged by Codex CLI (cross-model review) during development of PR #9:

P1install.sh:186 used hardcoded python instead of $PYTHON_CMD. On Linux/macOS systems with only python3 in PATH (the common case), the seed import failed silently (swallowed by || true) and no seeds were imported. Switched to $PYTHON_CMD with fallback warning.

P2parse_yaml_simple stripped quotes but did not decode backslash escapes. Seeds with "spec\.ts" or "vercel\.json" were stored with literal backslashes, producing invalid regex. Added _decode_yaml_double_quoted (handles \ \" \n \t \r) + _decode_yaml_single_quoted ('''). Fixes 3 broken seeds: e2e-playwright-selectors, security-headers-vercel, supabase-rls-auth-uid.

P3_instinct-activator.sh pre-filters by ALWAYS_DOMAINS + stack-detected domains when context.md exists. Seed domains workflow-general, testing, web-development, saas-development were outside both sets, so those seeds never reached regex evaluation. Added DOMAIN_MAP: workflow-general → operations, testing → quality, web-development → frontend, saas-development → stripe. original_domain preserved for traceability.

Tests: 3 new in tests/test-seeds.sh (9-11). Suite 8/8 → 11/11 GREEN.

No breaking changes to the seed YAML format or importer CLI flags.

@Luispitik

Copy link
Copy Markdown
Owner

Thanks Nestor — the importer is genuinely well built (idempotent, --dry-run, origin: 'seed:', impeccable MIT attribution to fs-cortex) and the empty-install UX diagnosis is legitimate. Closing on scope, with a technical blocker on top:

Scope. Since the v4.3.2 separation (2026-04-12) Sinapsis is exclusively autonomous learning — a curated per-stack knowledge library is content distribution, the opposite of learning from the user's own sessions, and it carries a permanent curation cost (every seed is a dated technical claim someone has to keep current). Cold-start is deliberately covered by the generic instincts already shipped in core/_instincts-index.json.

Dead on arrival as written (verified). The importer writes last_triggered=2026-04-04 from the YAML, and the v4.4 confidence decay runs before matching: the 6 confirmed seeds get demoted to draft on the very first tool use after install (60+ days inactive), and drafts don't inject — so the feature as shipped never delivers its "useful from day one" proposition. Also verified: the PR conflicts with main (CHANGELOG.md, install.sh — it predates v4.5/v4.6); conventional-commits enters as permanent (a level reserved for explicit /promote) and duplicates main's git-commit-conventional under a different id/domain, so both would inject; createServiceRoleClient() isn't a real Supabase API (a third party following that instinct hits a function that doesn't exist); install.bat gets no seeds; and test-seeds.sh hardcodes python (8 of 11 tests fail on python3-only systems) while its own Test 11 checks install.sh for exactly that sin. Triggers like admin, headers, payment are also broad enough to consume injection slots in unrelated third-party projects.

If you want to rescue the cold-start idea without reopening the scope question: a PR adding 2-3 extra generic instincts (level confirmed, ALWAYS_DOMAINS domains, narrow triggers) directly into core/_instincts-index.json — no seeds/ dir, no importer, no external YAML format — would only touch fresh installs, and I'd review it gladly. And the merger craftsmanship here has a better home: see the review on #12, which I do want to land after a rebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants