1318c0b84132b2dd46e0d5eac8114191669ec637
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a6167629cc |
Move from npm to pnpm across the workspace, CI and the image
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> |
||
|
|
bfd2f8d95a |
Add AGENTS.md — onboarding for whoever picks this up next
CI / verify (push) Successful in 1m32s
Named by convention so a coding agent finds it without being told. Written to get someone productive from a cold start without having to reconstruct the reasoning from the diff. Four sections carry the weight. The architecture rules that must not be broken, each of which fails silently rather than loudly — intelligence never lives in the API, authentication is not authorization, cost is charged against the full commitment, sold and held are different things. The traps that have already cost time here, with the specific symptom each produces: onConflictDoNothing being a no-op without a constraint, z.coerce.boolean turning "false" into true, grid children needing min-w-0, Drizzle emitting a cast Postgres rejects, the CSP allowing exactly one inline script by hash, and the Prime Intellect API quoting node totals rather than per-GPU prices. The conventions, including that comments explain why rather than what. And an explicit start order. The last section says what not to do, which is the part most easily lost: do not copy component files from the MIT project we borrowed ideas from, do not open self-registration on a shared identity provider, do not put a production key on the CI runner, do not weaken the guard that refuses to serve the CRM unauthenticated, and do not invent email addresses for real people. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
d36762f264 |
Scaffold PIG and model the compute-GTM ontology
PIG is an agent-native CRM for two-sided AI-compute companies: businesses that buy GPU capacity from providers and resell it. Their business is the spread between two pipelines, which is precisely what a generic CRM cannot represent. The load-bearing decision is the `allocations` table, joining a capacity_commitment (what we bought, at a known cost) to a demand_deal (what we sold, at a known price). Margin, utilisation and idle capacity all fall out of that one join. Cost is charged against the full commitment rather than only the hours that sold, because unsold hours are already paid for and any other treatment flatters a block that is losing money. Domain decisions worth noting, each grounded in how this market operates: - Demand stages put `legal` second, not last. Customers do not hand workloads to an infrastructure provider before paper is executed. - Supply qualification splits technical from financial diligence, recorded attributably. Accepting capacity is a two-key decision. - Capacity carries a time SHAPE (intervals + quantities), not a window. Commitments ramp and step down; a rectangle reports availability that does not exist in the month someone wants it. - SLAs model three distinct shapes: none, a reliability tier plus credits policy, and a negotiated agreement. Aggregators generally cannot promise uptime on resold capacity, but negotiate heavyweight paper upstream. Remedies include fee abatement, which is materially better than a capped credit and is not expressible as one. - Export control is a predicate on the allocation edge, evaluated against the ULTIMATE parent's jurisdiction. Country of incorporation is not a valid key, so this cannot live as a flag on an account. - Agent-derived claims land in `facts` with a confidence band and evidence. Only verified claims self-apply; weaker ones await review. - The API never calls the agent. It writes to a leased queue, guarded by a partial unique index on unfinished work. Verified: typechecks clean, migration generates and applies to Postgres 16 (31 tables, 24 enums, 117 indexes). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |