Files
2026-05-27 23:29:53 +01:00

9.2 KiB

name, description
name description
enterprise-package-migration Use when migrating a package from `../suaveplan/` into the genesis monorepo, or when adding a new genesis-original package. Mandates reading `../suaveplan/enterprise/<pkg>.md` first, authoring `**Verified by:**` lines at draft time, completing the 4-gate triple before declaring done. Triggers on path patterns like `packages/<plugin>/<pkg>` for new packages, or when the user mentions migration from main, bringing across, or porting from `suaveplan`.

Enterprise Package Migration

This skill enforces the workflow that prevents the 17 retroactive-ticking incidents that occurred during the first migration wave. Read it end-to-end before doing anything.

When this applies

You are in this skill if:

  1. The user is creating a new package under packages/<plugin>/<pkg>/ in /mnt/s/web/genesis.
  2. The user mentions migrating, porting, or bringing across a package from ../suaveplan/.
  3. You are authoring an openspec/changes/<id>/ for a package that has an enterprise/<pkg>.md source.

If none of those apply, this skill does not apply — exit.

The non-negotiable workflow

Step 0 — Read the source

If ../suaveplan/enterprise/<pkg>.md exists, read it end-to-end before opening any other file. It is the canonical requirements source. Do not author a genesis spec from memory of what the package does — you will lose requirements that way. The 17 retroactive-ticking incidents all traced to specs written from memory rather than from a side-by-side mapping with this file.

Step 1 — Read the workflow rules

In this order:

  1. /mnt/s/web/genesis/CLAUDE.md — full read.
  2. /mnt/s/web/genesis/openspec/AGENTS.md — every section, especially 13 (spec-conformance audit) and 14 (source mapping for migrations).
  3. /mnt/s/web/genesis/openspec/templates/README.md — when and how to use the templates.

Step 2 — Author the change folder from templates

cp -r /mnt/s/web/genesis/openspec/templates/proposal.md /mnt/s/web/genesis/openspec/changes/<change-id>/proposal.md
cp -r /mnt/s/web/genesis/openspec/templates/tasks.md    /mnt/s/web/genesis/openspec/changes/<change-id>/tasks.md
mkdir -p /mnt/s/web/genesis/openspec/changes/<change-id>/specs/<cap>/
cp -r /mnt/s/web/genesis/openspec/templates/spec-delta.md /mnt/s/web/genesis/openspec/changes/<change-id>/specs/<cap>/spec.md

Do not author from scratch. Every template field exists to prevent a specific failure mode.

Step 3 — Fill ## Source mapping in proposal.md

Every requirement in the spec delta MUST cite a line range in ../suaveplan/enterprise/<pkg>.md. Format:

| Requirement | Source lines | Notes |
|---|---|---|
| Zero workspace deps | L12-L34 | verbatim |
| OTel adapter | L140-L155 | verbatim |

Requirements with no source line go in the second table with a justification:

| Requirement | Justification |
|---|---|
| 100% coverage threshold | Genesis-wide policy, not package-specific |

"Forgot to map" is not a justification.

Step 4 — Fill **Verified by:** lines in spec-delta.md

Every requirement gets a line listing the concrete it(...) titles that pin every scenario:

**Verified by:** `src/feature/feature.test.ts::"<exact title>"` AND `src/feature/feature.spec-conformance.test.ts::"<exact title>"`

This is mandatory at authoring time, not after the gates pass. If you don't know what to put, write the test name first, then write the test. Don't ship the spec without the line filled in.

Step 5 — Implement, test, document

Standard CLAUDE.md rules apply:

  • Five files per feature module (feature.ts, feature.test.ts, feature.types.ts, feature.md, index.ts).
  • 100% test coverage from day one (provider: 'istanbul', never v8).
  • Sibling .md for every implementation file (≥200 words, basic + advanced examples, full API reference).
  • { timeout: 5000 } on every it()/test().
  • NEVER use mocks — use injectable Clock/Rng/Logger/etc from @suaveplan/types.
  • Check the @suaveplan/error consumers rule: every package extends SuaveplanError EXCEPT the three testing packages.

Step 6 — Pass all 5 gates

Run in order. Stop on the first red:

cd /mnt/s/web/genesis
bun run check                                                       # gate 1 — Biome 0/0/0 across monorepo
bunx turbo lint typecheck test --filter=@suaveplan/<pkg>           # gate 2
bunx turbo test:coverage --filter=@suaveplan/<pkg>                  # gate 3 — 100/100/100/100
bun scripts/openspec-conformance.ts @suaveplan/<pkg>                # gate 4 — 0 errors
bunx turbo build --filter=@suaveplan/<pkg>                          # gate 5

Never add a biome-ignore directive on faith. Workflow:

  1. Run bun run check to see what Biome actually flags.
  2. Copy the exact rule path from Biome's output (e.g. lint/suspicious/noExplicitAny). Guessing produces parse errors — lint/suspicious/noThrowLiterals does not exist in Biome 2.x.
  3. Add the suppression, re-run bun run check, confirm it's now used.
  4. If you remove the underlying flag later, also remove the suppression — unused suppressions are errors.

If gate 3 reports drift, FIX IT INLINE. Do not punt to a follow-up change. The acceptable patterns:

  • Implementation drifts from spec → align impl to spec, OR align spec to impl if the impl is the intended design.
  • Error code registered but unused → wire it into a real production code path.
  • OTel instrument declared but not emitted → wire it into the production hot path; assert with a real in-memory MeterProvider, not vi.mock.
  • Public type returns : unknown instead of a generic → thread <T = unknown> through the public surface.

Step 7 — Pre-archive 8-row checklist

Before folding the spec delta:

# Check
1 Generics threaded; expectTypeOf assertions on every literal-type claim
2 Zod schemas wired at every declared boundary
3 Every error code in error-codes.ts thrown by ≥1 production code path
4 Strict-mode behaviors tested both on and off
5 OTel instruments emitted from production paths and asserted with real MeterProvider
6 Lifecycle dedup tested where claimed (in-flight Promise, idempotent set/load)
7 No retroactive tick — every tasks.md checkbox reflects work actually done in this change
8 No export * in any feature-module barrel (§6a). Run grep -rn "^\s*export\s\+\(type\s\+\)\?\*\s\+from" packages/<plugin>/<pkg>/src/ --include="index.ts" | grep -v "/src/index\.ts:" | grep -v "\.select/" | grep -v "\.native/index\.ts:" | grep -v "\.noble/index\.ts:" | grep -v "export \* as". Zero output expected. If the upstream library used export * barrels, convert them in this migration — every <feature>/index.ts must list its symbols by name.
9 No direct vitest / bun:test imports in test files (CLAUDE.md rule 11 / §7 / §13 step 4b). Run grep -rnE "from ['\"](vitest|bun:test)['\"]" packages/<plugin>/<pkg>/src/ --include="*.ts" --include="*.tsx". Zero output expected for any non-exempt package. The exempt allowlist is exactly five testing-infra packages (@suaveplan/testing, testing-dom, testing-e2e, testing-integration, testing-integration-step-ca). If the upstream library imported runner primitives directly from vitest, rewrite every line to from "@suaveplan/testing/runner" in this migration — not as a follow-up. The repo-wide CI gate bun scripts/lint/check-test-runner-imports.ts catches regressions but the migration commit must already be clean.

Step 8 — Archive

# fold the delta
# (manual: copy ADDED/MODIFIED/REMOVED requirement bodies into openspec/specs/<cap>/spec.md)
mv /mnt/s/web/genesis/openspec/changes/<change-id> /mnt/s/web/genesis/openspec/archive/$(date +%Y-%m-%d)-<change-id>

Refresh MANIFEST.md if package set or deps changed:

cd /mnt/s/web/genesis && bun scripts/folder-reorg/generate-manifest.ts

Update the package listing in CLAUDE.md.

Red flags — stop and ask

  • The user says "just stub it" / "we'll wire it later" / "ship it 95% done" — refuse. Genesis ships at 100% or not at all.
  • You discover the source enterprise/<pkg>.md references functionality not in scope (e.g., the file lists 5 things but the user only wants 3) — ask before scoping down. The default is "match the source"; partial migration is a judgment call.
  • A required dependency package isn't migrated yet → check MANIFEST.md for dep order. Migrate the dep first, or stop and ask.
  • The conformance script reports drift you can't fix without a breaking change to public surface → stop and ask. Breaking changes need explicit user approval.
  • The user pushes back on writing **Verified by:** lines at draft time — show them this skill and openspec/AGENTS.md Section 13. Do not skip the lines.

Reference materials

  • Canonical example: openspec/changes/error-spec-conformance/ and packages/core/error/src/base/suaveplan-error.spec-conformance.test.ts
  • The 17 retroactive-ticking failure modes: openspec/AGENTS.md Section 12 (banned archival practices) and Section 13 (audit checklist)
  • Source mapping example: any proposal.md in openspec/changes/*-spec-conformance/ after the conformance sweep