a6167629cc
CI / verify (push) Successful in 3m23s
The monorepo was on npm workspaces. pnpm gives it a content-addressed store shared between the eight packages, a lockfile that records the whole graph rather than a flattened view of it, and — the reason this mattered in practice — `workspace:*`, which makes an internal dependency unambiguous instead of a version range that npm may satisfy from the registry. Mechanics: - `packageManager: pnpm@11.21.0` pins the version; corepack installs it in CI and in the image, so all three environments resolve identically. - The npm `workspaces` array is replaced by `pnpm-workspace.yaml`. pnpm ignores the former, and keeping both would leave two sources of truth. - All six internal dependencies moved to `workspace:*`. - Root scripts use `pnpm -r --if-present` and `pnpm -F <pkg>`. Two findings worth recording, both from running it rather than reading it: `tsx` was a devDependency, but the server runs TypeScript directly in production — the container's command is `pnpm exec tsx apps/api/src/server.ts`. Under npm this was concealed by the runtime stage re-installing tsx by hand after pruning dev dependencies. Under `pnpm install --prod` that sleight of hand stops working and the image simply fails to start. tsx is now declared in `dependencies`, which is what it has always actually been. The first image build failed with ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY. That is not a pnpm bug: it had decided the modules directory was stale and wanted confirmation before deleting it, which a non-interactive build cannot give. The trigger was the host's `node_modules` reaching the build context — there was no `.dockerignore` at all. pnpm's tree is symlinks into a content-addressed store, so copying it into an image produces dangling links and a directory pnpm rightly considers corrupt. Fixed by adding `.dockerignore` and setting `CI=true`, which is required in any non-interactive pnpm build. `esbuild` is denied install scripts via `allowBuilds`. Its platform binary arrives through the optional dependency `@esbuild/linux-x64` and the postinstall only verifies it; confirmed by running the binary directly, which reports 0.25.12. Verified under pnpm: typecheck clean, 150 tests / 0 failures, e2e passes, web builds. The image was built and booted against a real Postgres — health ok, `/api/dashboard` 401 with an issuer configured, `/` and `/capacity` serve the SPA, `/og.png` serves as image/png, and the migrator runs from the pruned runtime stage. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
184 lines
7.4 KiB
Markdown
184 lines
7.4 KiB
Markdown
<div align="center">
|
|
|
|
# 🐷 PIG — Prime Intellect Growth
|
|
|
|
**An open-source, agent-native CRM for two-sided AI-compute companies.**
|
|
|
|
[](./LICENSE)
|
|
|
|
*Self-hostable. Auditable. Built for teams that buy compute on one side and sell it on the other.*
|
|
|
|
</div>
|
|
|
|
---
|
|
|
|
## Why this exists
|
|
|
|
A company that aggregates GPU capacity and resells it does not run one pipeline.
|
|
It runs two, and its business is the spread between them.
|
|
|
|
Generic CRMs — Salesforce, HubSpot, Attio — model a single pipeline of deals
|
|
against companies. They have no concept of **inventory**, no concept of a
|
|
**commitment you already bought and are paying for**, and therefore no way to
|
|
answer the question the business actually turns on:
|
|
|
|
> Which contracted capacity is sold, to whom, at what margin — and what is idle
|
|
> right now?
|
|
|
|
PIG is built around that question. One table, [`allocations`](./packages/db/src/schema/allocations.ts),
|
|
joins a `capacity_commitment` (what you bought from a provider) to a
|
|
`demand_deal` (what you sold to a customer). Revenue minus cost is margin per
|
|
GPU-hour. Committed capacity with no allocation is money burning. Everything
|
|
else in PIG is ordinary CRM plumbing that exists to keep that ledger honest.
|
|
|
|
## Who it's for
|
|
|
|
PIG models three teams, because two-sided compute companies have three
|
|
constituencies competing for the same scarce capacity:
|
|
|
|
| Team | Job to be done |
|
|
|---|---|
|
|
| **Supply** | Source, qualify, price, and contract GPU capacity from providers |
|
|
| **Demand** | Sell compute and post-training; renew and expand accounts |
|
|
| **Research** | Consume capacity internally — real burn, no revenue |
|
|
|
|
Research is a first-class tenant rather than an afterthought. Internal research
|
|
burn competes with revenue for the same GPUs, and margin math that cannot see it
|
|
is wrong.
|
|
|
|
The team set is configurable. PIG ships with these three because they match the
|
|
structure of the company it was designed for, not because they are universal.
|
|
|
|
## Agent-native, not agent-decorated
|
|
|
|
PIG is a first-class application for agents *and* for humans, and neither is a
|
|
degraded view of the other.
|
|
|
|
- **An MCP server** ([`apps/mcp`](./apps/mcp)) exposes the CRM over both stdio
|
|
and Streamable HTTP. Any MCP client connects: **Claude Code**, **Codex**,
|
|
**[prime-agent](https://github.com/PrimeIntellect-ai/prime-agent)**, or a
|
|
**[Buzz](https://github.com/block/buzz)** workspace agent via its ACP bridge.
|
|
Each team member points their own agent at PIG and works from the terminal.
|
|
- **Piggy**, the in-app agent, drains a leased database queue rather than being
|
|
called over HTTP — so work survives the agent being down, and every action it
|
|
takes is recorded with an idempotency key.
|
|
- **Every agent-derived fact carries evidence.** Enrichment writes to a `facts`
|
|
table with a confidence score, a band (verified / probable / possible), a
|
|
source URL, and a status. Strong signals apply automatically; weak ones become
|
|
proposals a human approves. A CRM that lets an agent write unattributed claims
|
|
into the record is a hallucination store, not a database.
|
|
|
|
### The architectural rule
|
|
|
|
> **Intelligence never lives in the API.**
|
|
|
|
The API does HTTP, auth, validation, and sync. All research, enrichment,
|
|
scoring, and identity matching lives in the agent. They communicate through a
|
|
table, never a direct call. This separation is borrowed from
|
|
[Comp AI CRM](https://github.com/trycompai/crm) and it is the single most
|
|
load-bearing decision in the codebase.
|
|
|
|
## What makes it compute-native
|
|
|
|
- **`inventory_listings`** mirrors the Prime Intellect availability API
|
|
field-for-field — `gpuType`, `socket`, `interconnectType`, `stockStatus`,
|
|
`security` (secure vs community cloud), `prices.onDemand`, `provisioningTime`.
|
|
Sync is a straight mapping, not an ETL project.
|
|
- **`capacity_commitments`** records what you bought: term, GPU-hours,
|
|
cost per GPU-hour, floor and ceiling.
|
|
- **`contracts`** is polymorphic over party and type — MSA, DPA, SLA, order
|
|
form, capacity commitment — because the supply side negotiates heavyweight
|
|
paper while the self-serve demand side runs on a reliability tier and a
|
|
credits policy instead of a signed uptime guarantee.
|
|
- **Two real pipelines**, with stages taken from how this market actually
|
|
operates rather than invented:
|
|
|
|
```
|
|
Demand: qualification → legal → scoping → proposal → procurement
|
|
→ POC → deployment → expansion
|
|
|
|
Supply: sourced → qualifying → technical diligence → financial diligence
|
|
→ pricing → contracting → onboarding → live → renewal
|
|
```
|
|
|
|
Note that **legal sits second** in the demand pipeline. MSA and DPA execution
|
|
gates the deal rather than closing it. Most CRMs put contracts at the end and
|
|
are wrong about it for this market.
|
|
|
|
## Stack
|
|
|
|
| Layer | Choice |
|
|
|---|---|
|
|
| Web | React + Vite + TypeScript, Tailwind, shadcn/ui, light + dark |
|
|
| API | Hono + tRPC on Node 22+ |
|
|
| Database | PostgreSQL 16, Drizzle ORM |
|
|
| Auth | Supabase (JWT verification only — PIG stores no passwords) |
|
|
| Agent | Piggy — a worker draining a leased task queue |
|
|
| MCP | `@modelcontextprotocol/sdk` — stdio + Streamable HTTP |
|
|
| Deploy | Docker Compose behind any reverse proxy |
|
|
|
|
Authorization comes from PIG's own `users` table, never from the mere existence
|
|
of an auth account. An identity provider that PIG shares with another
|
|
application must not grant access here.
|
|
|
|
## Quick start
|
|
|
|
```bash
|
|
git clone <this-repo> pig && cd pig
|
|
pnpm install
|
|
cp .env.example .env # then edit it
|
|
pnpm run db:migrate
|
|
pnpm run db:seed # optional — public, sourced, confidence-graded
|
|
pnpm run dev:api # :8920
|
|
pnpm run dev:web # :5173
|
|
```
|
|
|
|
Connect an agent:
|
|
|
|
```bash
|
|
claude mcp add pig -- npx -y @pig/mcp # stdio
|
|
# or point any MCP client at https://<your-host>/mcp
|
|
```
|
|
|
|
## Repository layout
|
|
|
|
```
|
|
apps/
|
|
web/ React + Vite front end
|
|
api/ Hono + tRPC API, Supabase JWT verification
|
|
mcp/ MCP server — stdio and Streamable HTTP
|
|
packages/
|
|
db/ Drizzle schema, migrations, seed
|
|
core/ Shared domain types and the ontology
|
|
prime/ Typed client for the Prime Intellect compute API
|
|
docs/ Ontology, deployment, seed-data provenance
|
|
deploy/ Compose files and reverse-proxy snippets
|
|
```
|
|
|
|
## Documentation
|
|
|
|
- **[AGENTS.md](./AGENTS.md) — start here if you are joining this codebase.**
|
|
Architecture rules, the traps that have already bitten, conventions, and
|
|
where to start.
|
|
- [Build plan](./docs/build-plan.md) — what remains, in dependency order
|
|
- [Ontology](./docs/ontology.md) — the domain model, and why it is shaped this way
|
|
- [Seed data provenance](./docs/seed-data.md) — every claim, graded and cited
|
|
- [Agent integration](./docs/agents.md) — Claude Code, Codex, prime-agent, Buzz
|
|
- [Deployment](./docs/deploy.md) — self-hosting
|
|
|
|
## A note on seed data
|
|
|
|
PIG ships with a roster of publicly documented people so the application is
|
|
legible on first run. Every record carries a confidence grade and a source URL.
|
|
**No email addresses are included or inferred.** Records that could not be
|
|
independently sourced are marked as such rather than quietly presented as fact,
|
|
and people who are demonstrably *not* staff — alumni, residency participants —
|
|
are labelled accordingly. See [docs/seed-data.md](./docs/seed-data.md).
|
|
|
|
If you are seeded here and would rather not be, open an issue and it will be
|
|
removed.
|
|
|
|
## Licence
|
|
|
|
Apache License 2.0 — see [LICENSE](./LICENSE) and [NOTICE](./NOTICE).
|