UNPKG

@eristack/ai-knowledge

Version:

Eristack knowledge pack for AI agents: recommend packages first, load the right Intent skills, and keep catalog facts in sync

162 lines (112 loc) 9.8 kB
# Development conventions Conventions for apps consuming Eristack and for contributors to the business-libs monorepo. ## Product priorities Four **design targets** govern every package (details: [`agent-workflow.md`](./agent-workflow.md) § Design targets; Cursor: `.cursor/rules/eristack-package-targets.mdc`): 1. **Cheap to implement (tokens)** — integration in ≤3 files; canonical docs; export registries/helpers consumers would copy. 2. **Predictable result** — same behavior in core, forms, and API; string-first domain values; documented defaults. 3. **High reliability** — production paths tested; Drizzle/DB default; no demo-only stores in skills. 4. **Clear boundaries** — sharp packages; recommend before inventing; app owns UX and domain tables; **consumers must not reinvent** library exports. Supporting norms: - **Correct money and identity** beat clever abstractions. - **Headless shells** — Express/Nest/React adapters stay thin. - **Agent-readable docs and skills** ship with every package (`docs/`, `skills/`). ## Monorepo layout (business-libs) | Path | Role | | --- | --- | | `packages/primitive/money` | `@eristack/money` (primitive) | | `packages/capability/doc-number` | `@eristack/doc-number` (capability) | | `packages/service/jwt-auth` | `@eristack/jwt-auth` (service) | | `packages/infrastructure/backseat` | `@eristack/backseat` (infrastructure; browser mock REST + IndexedDB) | | `packages/ui/multitab` | `@eristack/multitab` (UI; tab workspace — coming soon) | | `packages/features/` | **Under construction** — future `@eristack/feature-*`; see `roadmap/features.md` | | `packages/ai/ai-knowledge` | `@eristack/ai-knowledge` (AI; this pack) | | `packages/ai/ai-workflow` | `@eristack/ai-workflow` (AI) | | `roadmap/` | Living priority stack for future packages | | `examples/*` | Private runnable demos (not published) | | `apps/web` | Public site; renders `packages/<category>/*/docs` by category | | `_ai-docs/` | WIP (`wip/`), brainstorm, audit — see `_ai-docs/README.md` | | `_artifacts/` | Domain maps / skill specs | | `.changeset/` | Pending release notes | Category order (docs + filesystem): primitive → capability → service → infrastructure → ui → features → AI. ## Branching and releases - **GitHub Flow** — feature branches from `main`, PRs into `main` only - Do not revive a long-lived `dev` integration branch - User-facing package changes need `pnpm changeset` - Docs-only / CI-only changes do not need a changeset ### Changesets on `0.x` (contributors) | Changeset type | On `0.0.0` | On `0.1.0+` (still pre-1.0) | | --- | --- | --- | | **`patch`** | `0.0.1` | next **`0.(n+1).0`** (stay pre-1.0) | | **`minor`** | **`0.1.0`** (first publish) | **`0.2.0`** semver on 0.1.x — **breaks `^0.1.0` peers** (`<0.2.0`) and Changesets **major-bumps** all peer dependents (e.g. backseat → 12 spine packages). Use only when coordinating a release train. | Routine features/fixes on packages already past `0.0.0`: use **`patch`** (e.g. `0.1.4``0.1.5`, stays inside `^0.1.0`). Use **`minor`** on `0.0.0` for first release, or when you **mean** a 0.y line bump / exit from 0.x with peer range updates. **Peer cascade (why patch on `@eristack/backseat`):** twelve packages declare optional peer `"@eristack/backseat": "^0.1.0"`. npm treats `^0.1.0` as `>=0.1.0 <0.2.0`. A **minor** changeset on backseat at `0.1.4` becomes **`0.2.0`**, out of range — Changesets (`onlyUpdatePeerDependentsWhenOutOfRange: true`) schedules **major** bumps on jwt-auth, qups, pbac, etc. This is not `workspace:*` in `dependencies` (those are clean); it is **peer semver range** + Changesets policy. ### Changeset file shape (CI enforced) - **One `@eristack/*` package per `.changeset/*.md` file** — a multi-package frontmatter block repeats the same body in every package changelog on the Version PR. - **Body describes only that package** — no `### @eristack/foo` cross-package sections or copy-pasted monolith. - Run **`pnpm changesets:check`** in CI and locally before merge. ### Internal optional peers (Backseat spine) - Published **`peerDependencies`**: semver (`^0.1.0`), not `workspace:*` - Monorepo **`devDependencies`**: `workspace:*` - `.changeset/config.json`: `onlyUpdatePeerDependentsWhenOutOfRange: true` — dependents bump only when the new peer is outside the declared range - No **`fixed`** / **`linked`** Changesets groups Consumer upgrade steps: [`upgrading.md`](./upgrading.md) · skill `@eristack/ai-knowledge#upgrading-eristack`. ### Two-PR release model (contributors) Ship features in **one feature PR**; let Changesets + CI own version bumps in a **second PR**. Do not run `pnpm changeset version` locally on a feature branch. | Ship in the **feature PR** | Do **not** touch in the feature PR | CI / Version Packages PR | | --- | --- | --- | | Source, tests, `package.json` **exports** (not `version`) | `package.json` `version` fields | `changeset version` bumps versions | | Package `docs/` + Intent `skills/` **content** | Hand-edited `CHANGELOG.md` | Generated changelog sections | | `recipes.yaml`, `pnpm knowledge:sync` output (`catalog.ts`, `recipes.ts`, `recommend-eristack` catalog block) | Deleting skill/recipe work when reverting a mistaken local version | `pnpm knowledge:sync` again (via `version-packages`) so catalog versions match bumped `package.json` | | One or more `.changeset/*.md` files | Running `changeset publish` locally | `pnpm release` on npm after Version PR merges | **If you accidentally ran `changeset version` locally:** revert only `version` + `CHANGELOG` + lockfile drift. Keep skills, recipes, generated catalog content, and docs — those are the feature. **Feature PR green bar:** `pnpm ci` (=`pnpm build && pnpm eristack check --profile full --skip-build`). Agents: run `pnpm eristack plan --json` first for a minimal command list. **After feature PR merges to `main`:** the Release workflow opens **“chore: version packages”**. Review and merge it; npm publish runs on that merge. ### Publish gate — package exports (hard rule) 1. Every subpath imported by spine packages must appear in **`package.json` `exports`** (e.g. `"./adapters"` on `@eristack/backseat`). 2. Every export subpath must have a **`tsup` entry** that builds `dist/…`. 3. After **`pnpm build`**, run **`pnpm exports:check`** — CI enforces; catches Vite `Missing "./adapters" specifier`. 4. Add **`import("@eristack/pkg/subpath")`** tests for new public subpaths. Do not document/catalog an export unless it passes `exports:check`. ## Adapter design rules - Core entry is framework-agnostic (no Express/Nest/React/Drizzle imports in core) - Adapters are separate export paths (`/drizzle`, `/express`, `/nest`, `/client`, `/react`, …) - App injects `db`, secrets, and domain ids — libraries do not own your users table - Credentials / refresh tokens / format sequences are **child** resources ## Testing - Prefer focused unit tests next to behavior (`tests/` or `src/**/*.test.ts`) - Memory stores are for tests/ephemeral use; Drizzle stores for production paths - Examples prove end-to-end wiring; they are not published packages ## Documentation + ai-knowledge (hard rule) - Library guides: `packages/<category>/<name>/docs/*.md` + `_meta.json` - Do not duplicate library markdown inside `apps/web` - Site-only marketing/story/support pages live under `apps/web` - **Every iteration:** update `docs/` + Intent `skills/` together; update `packages/ai/ai-knowledge/knowledge/recipes.yaml` when discoverable by product language; run `pnpm knowledge:sync` / `knowledge:check` - Stale ai-knowledge after a docs/API change is incomplete work ### Token-efficient documentation (hard rule) Agents are the primary audience. **In-depth** does not mean **many files**. | Cross-cutting topic | One canonical doc | | --- | --- | | Upgrades, Backseat spine, peers, Changesets | `packages/ai/ai-knowledge/knowledge/upgrading.md` + `@eristack/ai-knowledge#upgrading-eristack` | | Product routing | `recipes.yaml` + `recommend-eristack` skill | Per-package docs: full detail for **that package’s production adapters**; for monorepo-wide Backseat wiring, **redirect** to upgrading §3 with a small delta table only. See `.cursor/rules/docs-depth-tokens.mdc`. ## AI working docs (`_ai-docs/`) Three buckets — see repo `_ai-docs/README.md`: | Bucket | Path | Rule | | --- | --- | --- | | WIP | `_ai-docs/wip/<topic>/` | Ephemeral; delete after promote | | Brainstorm | `_ai-docs/brainstorm/` | Package names before `roadmap/horizon.md` | | Audit | `_ai-docs/audit/` | Point-in-time quality snapshot | While implementing: WIP notes good enough to draft public docs (include skill/recipe impact). When finished: promote to package docs / site / skills / recipes; sync catalog; **delete** the WIP folder. ## Drizzle integration tests (Sprint A) Production paths default to Drizzle; prove them with sqlite integration tests — not memory stores in skills. | Piece | Location | | --- | --- | | Shared sqlite helper | `@internal/test-harness``createTestSqliteDb`, `execSql`, `canUseBetterSqlite` | | Hash-chain harness | `@eristack/hash-chained-ledger/testing``setupHclSqlite`, tamper helpers | | Per-package test | `packages/<layer>/<name>/tests/drizzle.integration.test.ts` | | Run all | `pnpm test:integration` (root) or `pnpm eristack check --profile integration` | **Pattern:** wrap suites in `describe.skipIf(!canUseBetterSqlite())` so CI without native bindings skips cleanly. When adding a new Drizzle store, add or extend an integration test in the same PR. ## Scope discipline - Change only what the task requires - Do not rewrite root README for agent guidance (use `AGENTS.md` / skills) - Never commit secrets or tokens into docs or AI notes