Add Motion: the go-to-market operating system on top of the ledger

The ledger answers which contracted capacity is sold, to whom, at what
margin. It says nothing about the motion — the repeatable practice that
turns a customer conversation into a scoped deployment, and turns that
deployment into something the next one reuses.

Motion is deliberately not a parallel entity tree. DEMAND_STAGES already
is the motion, so Motion binds reusable artefacts to the stages of a
demand deal that already exists: an engagement hangs off one deal,
cascade deleted, one per deal by unique constraint.

Nine closed kinds, each declaring which stages it serves, and a starter
library of twelve templates covering all eight open stages.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-17 18:27:03 -07:00
parent 99d165b5e5
commit 516685526c
61 changed files with 13013 additions and 29 deletions
+29 -11
View File
@@ -31,19 +31,21 @@ Everything else is plumbing that exists to keep that ledger honest.
```
packages/core Ontology (stages, tiers, enums) + permissions + margin + palette
packages/db Drizzle schema (47 tables), migrations, seeds
+ motion.ts (template kinds, integer qualification scoring)
packages/db Drizzle schema (51 tables), migrations, seeds
schema/motion.ts — the library, engagements and the loop
packages/prime Typed client for the Prime Intellect compute API
apps/api Hono HTTP API, auth, capacity/contract/calendar services
apps/api Hono HTTP API, auth, capacity/contract/calendar/motion services
apps/web React + Vite + Tailwind + shadcn-idiom components
apps/piggy The agent — lease-based queue worker + private chat server
apps/mcp MCP server (stdio) — 9 tools
apps/mcp MCP server (stdio) — 10 tools
apps/cli `pig`, the HTTP surface for scripts and agent kernels
docs/ ontology.md, build-plan.md, agents.md, seed-data.md
docs/ ontology.md, motion.md, build-plan.md, agents.md, seed-data.md
deploy/ README.md (deployment), Caddyfile example, autodeploy units
```
~45,000 lines including tests. 261 tests across five packages
(core 62, prime 24, api 157, piggy 13, cli 5), plus a critical-path E2E suite
~48,000 lines including tests. 382 tests across five packages
(core 78, prime 24, api 212, piggy 63, cli 5), plus a critical-path E2E suite
under `apps/api/e2e`. Node 22+.
| | |
@@ -231,11 +233,27 @@ Pass `reasoning_effort: "none"` for tool use, routing and extraction.
**A route file with green tests can still be unmounted.** Every route module is
a factory returning a `Hono` app, and `createApp` has to call it. The tests
mount the factory themselves, so they pass whether or not `app.ts` ever does.
Four modules are in exactly that state right now — `read-guards.ts`,
`learn.ts`, `hubspot.ts`, `hubspot-webhook.ts` — which is why read
authorisation is unenforced and `/learn` answers 404 from a page that is in the
navigation. After adding a route file, curl the path against a running server;
the test suite cannot tell you.
`read-guards.ts` and `learn.ts` were in exactly that state — which is why read
authorisation went unenforced and `/learn` answered 404 from a page that was in
the navigation — and are now mounted. `hubspot.ts` and `hubspot-webhook.ts`
still are not. After adding a route file, curl the path against a running
server; the test suite cannot tell you.
**A stale dev server on :8920 makes a mounted route look unmounted.** The curl
check the entry above recommends is only as good as the process answering it. `pnpm run dev:api` prints its `EADDRINUSE` and keeps running under
the process manager, so a server started hours earlier from an older checkout
goes on answering — and every new route 404s with a perfectly plausible
`{"error":"Not found"}` JSON body. Found this way: five Motion routes that were
correctly mounted read as missing for twenty minutes. Check
`ss -lptn 'sport = :8920'` before believing a 404, and read the dev server's log
rather than only its port.
**The demo seed skips an account it has already seen, and the rows hanging off
that account never appear.** `seedDemo` is idempotent per account, so a database
carrying a partial demo book from an earlier run silently produces no demand
deals — and anything that looks a deal up by name, as `seed/demo/motion.ts`
does, then reports zero and reads exactly like a broken loader. The fix is
`pnpm db:demo -- --clear` and a reseed, not a patch to the lookup.
**Deployment traps** live in `deploy/README.md` — chiefly that every Caddy site
block on that host needs `bind 10.0.0.2`, and that the CI runner uses