Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions SHARED.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ the inventory underneath it is **generated**, and the number it produces is a

| Package | Install | Replaces |
|---|---|---|
| [`ai-forms`](https://github.com/catomean/ai-forms) | `npm i github:catomean/ai-forms#v0.1.0` | per-app "fill this form from prose" + conversational refinement. Headless — ships **no markup**, so each app keeps its own styling. |
| [`ai-kit`](https://github.com/catomean/ai-kit) | `npm i github:catomean/ai-kit#v0.4.0` | **the AI layer, in one install** — which model to call, whether the vendor still lists it, the three kinds of 429, fair-share of a free tier, and (re-exported) `ai-forms`. Renamed from `ai-ration` 2026-08-26: the name described one of five modules, and the package had one adopter while five repos that skipped it went down together to a retired model id. |
| [`threadkit`](https://github.com/catomean/threadkit) | `npm i threadkit` | multi-participant message threads where *permission is participation*, not a role or an ownership column. Headless pure functions, so "who may read this" is unit-testable instead of buried in a `WHERE` clause. AI participants obey the same visibility rules. **ESM-only.** |
| [`limitkit`](https://github.com/catomean/limitkit) | `npm i github:catomean/limitkit#v0.1.0` | the fleet's **12 hand-rolled rate limiters** (this file's own "next extraction" row). Sliding/fixed windows over an injectable two-method `Store`; **bounded** memory default (the unbounded-Map leak is impossible by construction); standard `X-RateLimit-*` + `Retry-After` headers — what orangecat's ADR-0002 specified seven months before anything enforced it; `clientIp()`. Refusals count nothing, so a hammered key recovers. Ships no middleware and **no limit values** — how many attempts a route allows is app semantics, asserted locally. |
| [`ai-forms`](https://github.com/bitbaum/ai-forms) | `npm i github:bitbaum/ai-forms#v0.1.0` | per-app "fill this form from prose" + conversational refinement. Headless — ships **no markup**, so each app keeps its own styling. |
| [`ai-kit`](https://github.com/bitbaum/ai-kit) | `npm i github:bitbaum/ai-kit#v0.4.0` | **the AI layer, in one install** — which model to call, whether the vendor still lists it, the three kinds of 429, fair-share of a free tier, and (re-exported) `ai-forms`. Renamed from `ai-ration` 2026-08-26: the name described one of five modules, and the package had one adopter while five repos that skipped it went down together to a retired model id. |
| [`threadkit`](https://github.com/bitbaum/threadkit) | `npm i threadkit` | multi-participant message threads where *permission is participation*, not a role or an ownership column. Headless pure functions, so "who may read this" is unit-testable instead of buried in a `WHERE` clause. AI participants obey the same visibility rules. **ESM-only.** |
| [`sitekit`](https://github.com/bitbaum/sitekit) | `npm i github:bitbaum/sitekit#v0.1.1` | **a website as data** — the closed section union (Zod as SSOT, path-addressed errors a generator can act on), one set of React renderers emitting semantic classes only (tokens stay per-site: uniform system, divergent aesthetics), and per-field provenance (`scraped`/`operator`/`inferred`/`not-found`) so `assertDeliverable()` makes "we fabricate no facts" a check instead of a promise. Extracted from substrata per orangecat ADR-0003; the planned `siteFromUrl()` extractor targets this schema. RSC-native — the Link seam stays a server-component prop (learned in v0.1.1 when the first consumer's build refused a component function crossing 'use client'). **ESM-only.** |
| [`limitkit`](https://github.com/bitbaum/limitkit) | `npm i github:bitbaum/limitkit#v0.1.0` | the fleet's **12 hand-rolled rate limiters** (this file's own "next extraction" row). Sliding/fixed windows over an injectable two-method `Store`; **bounded** memory default (the unbounded-Map leak is impossible by construction); standard `X-RateLimit-*` + `Retry-After` headers — what orangecat's ADR-0002 specified seven months before anything enforced it; `clientIp()`. Refusals count nothing, so a hammered key recovers. Ships no middleware and **no limit values** — how many attempts a route allows is app semantics, asserted locally. |

**Adopted:** `ai-forms` — fleetcrown, evig, aoz-housing, surf-your-life.
`ai-kit` — fleetcrown, aoz-housing, truthseeker, botsmann, **and this repo**
Expand Down Expand Up @@ -60,6 +61,12 @@ never by "these are all shared utilities". `threadkit` — **nobody yet**.
Map). **Next adopter should be orangecat** — it closes ADR-0002 by making its
Upstash client a 12-line `Store` adapter and deleting three of its four
implementations.
`sitekit` — substrata (proving consumer, converted the day the package
shipped: −577 lines of local renderer, and its test now validates the whole
site against the shared schema, so a breaking schema change fails in the
consumer's CI first). **Next: camille-boulangerie, aslan-tattoo, wild-spirit**
— the three real sites that make the union's gaps (images, contact, menus)
visible on sites we own before the schema is pointed at strangers.
**Not yet:** orangecat and kivvi still carry their own form-assist; kivvi, evig,
botsmann still carry their own provider layers.

Expand All @@ -74,7 +81,7 @@ CI: installed from the public registry into an empty project, imported, and got
17 named exports plus `dist/index.d.ts`.

It exists because of the bug
[`single-tenant-prod-hides-unscoped-queries`](https://github.com/catomean/dotfiles)
[`single-tenant-prod-hides-unscoped-queries`](https://github.com/bitbaum/dotfiles)
records: role-derived access is correct at one doctor / one tenant / one org and
silently wrong at two. `canRead(thread, user)` cannot express that bug, because
there is no role to check.
Expand Down Expand Up @@ -113,11 +120,11 @@ Ranked by (copies × how identical the logic is). Counts from
| Concern | Files | Why it is a good candidate |
|---|---|---|
| `auto-merge-sweep.sh` | ~~22~~ **6** | **EXTRACTED 2026-08-16/20.** Sixteen repos call the canonical as a reusable workflow, each verified to actually *run* it (a sweep that fails to start looks exactly like one with nothing to do). The six remaining are deliberate: dotfiles is the canonical home and runs it directly; ai-forms, datacat, petvity, solon had dirty working trees owned by other sessions when swept — convert when clear. The two repos that had ever *tested* their copies (evig, orangecat) had that coverage ported into the canonical suite **before** deletion: 17 cases, mutation-proven. |
| rate limiting | **14 → adopting** | **Extracted 2026-08-20 as [`limitkit`](https://github.com/catomean/limitkit)** (see registry above). fleetcrown converted as the proving consumer; 13 files remain across 8 repos, orangecat first in line (its ADR-0002 becomes a 12-line `Store` adapter + three deletions). The ratchet holds the count until each adoption lands. |
| rate limiting | **14 → adopting** | **Extracted 2026-08-20 as [`limitkit`](https://github.com/bitbaum/limitkit)** (see registry above). fleetcrown converted as the proving consumer; 13 files remain across 8 repos, orangecat first in line (its ADR-0002 becomes a 12-line `Store` adapter + three deletions). The ratchet holds the count until each adoption lands. |
| AI provider client | **16** | evig 7, orangecat 5. `ai-kit` already owns the hard part (chain, 429, budget); these are the callers. **Priced 2026-08-26, re-priced 2026-08-27:** Groq retired the llama-3.x family and the damage was far wider than the first count. Seven repos were broken, not five — the audit could not see two of them — and inside a repo the id was written down **two to four times**. Kivvi took three PRs to remove one retired id: it lived in the provider registry, an app's inline fetch body, the fallback chain, and a client hook's `FALLBACK_MODEL`. Each pass only found the copies the tooling could see. That is the cost of duplication measured rather than argued. fleetcrown, which adopted the package, was unaffected throughout. |
| logger | **10** | sbb-lost-found alone has 4. |
| health route | **8** | Identical shape in 8 repos; a 20-line contract. |
| ~~`@ai-native-cms/core`~~ | — | **Withdrawn — measurement error.** `catomean/revampit` *redirects* to `catomean/evig` (renamed in the pivot); the "two repos" with byte-identical trees were two clones of ONE repo. Nothing to extract. Two directories are not two repos: check `git remote -v` before reporting cross-repo duplication. |
| ~~`@ai-native-cms/core`~~ | — | **Withdrawn — measurement error.** `bitbaum/revampit` *redirects* to `bitbaum/evig` (renamed in the pivot); the "two repos" with byte-identical trees were two clones of ONE repo. Nothing to extract. Two directories are not two repos: check `git remote -v` before reporting cross-repo duplication. |

## What must NOT be centralized

Expand Down