Skip to content

Commit d8b483f

Browse files
SafetyMPSage Hart
andauthored
feat: autonomous company reference (approved dossier r1) (#37)
* feat: ship autonomous company reference (approved dossier r1) Rebuild CorpOS as the open firm-model + work-contracts + control-plane reference per corpos-autonomous-company, with thesis-first docs and CI on Node 22+. * fix(ci): run harness verify and repair deploy/action pins CI typecheck failed without a prior workspace build; drive PRs through scripts/harness instead. Fix Fly setup-flyctl ref and pin Docker/CodeQL actions. --------- Co-authored-by: Sage Hart <sagehart@MacBookAir.attlocal.net>
1 parent b368730 commit d8b483f

106 files changed

Lines changed: 5579 additions & 8044 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.corp-harness/site.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"schema": "corporate-site-site/v1",
33
"site_id": "corpos",
4-
"corporate_program": null,
5-
"corporate_handoff_sha256": null,
4+
"corporate_program": "corpos-autonomous-company",
5+
"corporate_handoff_sha256": "c0bb90e70fdfe705192e435869c30ab401339ec6b47c0576be34d7f48bae1975",
66
"verify_argv": ["./scripts/harness/verify.sh"],
77
"adversarial_argv": ["./scripts/harness/adversarial.sh"]
88
}

.env.example

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,21 @@
22
# NEVER commit a real `.env` (it is gitignored). Keep secrets out of code,
33
# logs, and agent output.
44

5-
# ── Model providers ──────────────────────────────────────────────────
6-
# Provide the key(s) for the provider(s) you actually use.
7-
# OpenRouter is the default for agent reasoning (model: Owl Alpha).
5+
# ── Runtime mode ─────────────────────────────────────────────────────
6+
# local (default): approvals/kill do not require a shared token.
7+
# shared: require DASHBOARD_API_TOKEN for approval and kill mutations.
8+
# CORPOS_MODE=local
9+
# DASHBOARD_API_TOKEN=
10+
11+
# ── Data ─────────────────────────────────────────────────────────────
12+
# Local libsql / SQLite file used by the firm store (default: data/company.db).
13+
# CORPOS_DB=data/company.db
14+
15+
# ── HTTP ─────────────────────────────────────────────────────────────
16+
# PORT=3000
17+
18+
# ── Model providers (optional; SimulationProvider used in CI) ────────
819
# OPENROUTER_API_KEY=
920
# OPENROUTER_MODEL=openrouter/owl-alpha
10-
# OPENROUTER_REFERER=https://corpos.local
11-
# OPENROUTER_TITLE=CorpOS
1221
# ANTHROPIC_API_KEY=
1322
# OPENAI_API_KEY=
14-
# GOOGLE_API_KEY=
15-
# GROQ_API_KEY=
16-
17-
# ── MCP servers ──────────────────────────────────────────────────────
18-
# Referenced from kilo.jsonc mcp.*.headers via ${VAR} interpolation.
19-
# MCP_TOKEN=
20-
21-
# ── Project ──────────────────────────────────────────────────────────
22-
# APP_ENV=development
23-
# LOG_LEVEL=info
24-
# DATABASE_URL=

.github/workflows/ci.yml

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,37 +10,41 @@ permissions:
1010
contents: read
1111

1212
jobs:
13-
lint:
13+
verify:
1414
runs-on: ubuntu-latest
15-
timeout-minutes: 5
15+
timeout-minutes: 15
16+
strategy:
17+
fail-fast: false
18+
matrix:
19+
node-version: [22, 24]
1620
steps:
1721
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
1822
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
1923
with:
20-
node-version: 20
24+
node-version: ${{ matrix.node-version }}
2125
cache: npm
22-
- run: npm ci
23-
- name: ESLint
24-
run: npm run lint
25-
- name: Prettier check
26-
run: npm run format:check
26+
- name: Activate packageManager npm
27+
run: |
28+
corepack enable
29+
corepack prepare npm@10.9.2 --activate
30+
- name: Site verify (build, typecheck, test, lint, format)
31+
run: ./scripts/harness/verify.sh
2732

28-
build:
33+
adversarial:
2934
runs-on: ubuntu-latest
3035
timeout-minutes: 10
31-
strategy:
32-
fail-fast: false
33-
matrix:
34-
node-version: [20, 22, 24]
36+
needs: verify
3537
steps:
3638
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
37-
- name: Use Node.js ${{ matrix.node-version }}
38-
uses: actions/setup-node@v6
39+
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
3940
with:
40-
node-version: ${{ matrix.node-version }}
41+
node-version: 22
4142
cache: npm
43+
- name: Activate packageManager npm
44+
run: |
45+
corepack enable
46+
corepack prepare npm@10.9.2 --activate
4247
- run: npm ci
43-
- name: Typecheck
44-
run: npm run typecheck
45-
- name: Test
46-
run: npm test
48+
- run: npm run build
49+
- name: Site adversarial
50+
run: ./scripts/harness/adversarial.sh

.github/workflows/codeql.yml

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ on:
44
push:
55
branches: [main]
66
paths:
7-
- "src/**"
7+
- "apps/**"
8+
- "packages/**"
9+
- "scripts/**"
810
- "test/**"
911
pull_request:
1012
branches: [main]
1113
paths:
12-
- "src/**"
14+
- "apps/**"
15+
- "packages/**"
16+
- "scripts/**"
1317
- "test/**"
1418
schedule:
1519
- cron: "27 6 * * 1"
@@ -29,15 +33,15 @@ jobs:
2933
steps:
3034
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
3135
- name: Initialize CodeQL
32-
uses: github/codeql-action/init@v3
36+
uses: github/codeql-action/init@4187e74d05793876e9989daffde9c3e66b4acd07 # v3
3337
with:
3438
languages: ${{ matrix.language }}
3539
queries: +security-and-quality
3640

3741
- name: Autobuild
38-
uses: github/codeql-action/autobuild@v3
42+
uses: github/codeql-action/autobuild@4187e74d05793876e9989daffde9c3e66b4acd07 # v3
3943

4044
- name: Perform CodeQL Analysis
41-
uses: github/codeql-action/analyze@v3
45+
uses: github/codeql-action/analyze@4187e74d05793876e9989daffde9c3e66b4acd07 # v3
4246
with:
4347
category: "/language:${{ matrix.language }}"

.github/workflows/deploy.yml

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
name: Deploy to Fly.io
22

3-
# Deploys the control plane to Fly.io when a release is published.
4-
# Requires the FLY_API_TOKEN repo secret (create with: flyctl tokens create deploy -a <app>).
5-
# Skips automatically if the secret is absent.
3+
# Optional release deploy for the reference demo. Skips cleanly when
4+
# FLY_API_TOKEN is unset. Requires fly.toml + Dockerfile.
65
on:
76
release:
87
types: [published]
@@ -16,20 +15,27 @@ jobs:
1615
runs-on: ubuntu-latest
1716
timeout-minutes: 15
1817
steps:
19-
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
20-
- name: Abort if Fly token not configured
21-
if: ${{ secrets.FLY_API_TOKEN == '' }}
18+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
19+
20+
- name: Check Fly token
21+
id: fly
22+
env:
23+
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
2224
run: |
23-
echo "FLY_API_TOKEN secret is not set — skipping deploy."
24-
echo "Create it with: flyctl tokens create deploy -a <your-app>"
25-
exit 0
25+
if [ -z "${FLY_API_TOKEN}" ]; then
26+
echo "configured=false" >> "$GITHUB_OUTPUT"
27+
echo "FLY_API_TOKEN secret is not set — skipping deploy."
28+
else
29+
echo "configured=true" >> "$GITHUB_OUTPUT"
30+
fi
2631
32+
# setup-flyctl only publishes @master (not version tags); pin the commit.
2733
- name: Set up Flyctl
28-
if: ${{ secrets.FLY_API_TOKEN != '' }}
29-
uses: superfly/flyctl-actions/setup-flyctl@1.5
34+
if: steps.fly.outputs.configured == 'true'
35+
uses: superfly/flyctl-actions/setup-flyctl@ed8efb33836e8b2096c7fd3ba1c8afe303ebbff1 # master
3036

3137
- name: Deploy
32-
if: ${{ secrets.FLY_API_TOKEN != '' }}
38+
if: steps.fly.outputs.configured == 'true'
3339
run: flyctl deploy --remote-only --strategy=rolling
3440
env:
3541
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

.github/workflows/docker.yml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ on:
44
push:
55
branches: [main]
66
paths:
7-
- "src/**"
7+
- "apps/**"
8+
- "packages/**"
9+
- "scripts/**"
810
- "test/**"
911
- "package.json"
1012
- "package-lock.json"
@@ -29,21 +31,21 @@ jobs:
2931
steps:
3032
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
3133
- name: Set up QEMU
32-
uses: docker/setup-qemu-action@v4
34+
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4
3335

3436
- name: Set up Docker Buildx
35-
uses: docker/setup-buildx-action@v4
37+
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
3638

3739
- name: Log in to GHCR
38-
uses: docker/login-action@v3
40+
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
3941
with:
4042
registry: ${{ env.REGISTRY }}
4143
username: ${{ github.actor }}
4244
password: ${{ secrets.GITHUB_TOKEN }}
4345

4446
- name: Derive image metadata
4547
id: meta
46-
uses: docker/metadata-action@v6
48+
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6
4749
with:
4850
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
4951
tags: |
@@ -53,7 +55,7 @@ jobs:
5355
type=raw,value=latest,enable={{is_default_branch}}
5456
5557
- name: Build and push
56-
uses: docker/build-push-action@v6
58+
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
5759
with:
5860
context: .
5961
platforms: linux/amd64,linux/arm64

.github/workflows/scorecard.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
publish_results: true
3131

3232
- if: always()
33-
uses: github/codeql-action/upload-sarif@v3
33+
uses: github/codeql-action/upload-sarif@4187e74d05793876e9989daffde9c3e66b4acd07 # v3
3434
with:
3535
sarif_file: results.sarif
3636
category: scorecard

.prettierignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ dist/
22
node_modules/
33
data/
44
docs/
5+
_archives/
6+
_legacy_src/
7+
_legacy_test/
58
.kilo/
69
.playwright-mcp/
710
package-lock.json

CONTEXT.md

Lines changed: 7 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,11 @@
1-
# Project context — loaded into every agent session via `instructions` in kilo.jsonc.
1+
# Project context
22

3-
# Keep this short and factual. It orients agents to THIS project specifically
3+
CorpOS is the open reference implementation of an autonomous company:
4+
firm model + work contracts + control plane. Simulation-first.
45

5-
# (unlike AGENTS.md, which states universal rules).
6+
Workspaces: `packages/core`, `packages/mcp-knowledge`, `apps/api`, `apps/console`.
67

7-
## What this project is
8+
Commands: `npm run dev`, `npm test`, `npm run scenario`, `npm run audit:verify`,
9+
`./scripts/harness/verify.sh`, `./scripts/harness/adversarial.sh`.
810

9-
`CorpOS` — an autonomous company operating system: a TypeScript multi-agent
10-
runtime plus a control plane (policy engine, approval gates, spend caps, audit,
11-
REST/WebSocket API, dashboard). Department "agents" (support, sales, ops,
12-
finance, engineering) reason via an LLM, call permissioned tools, and coordinate
13-
through a shared orchestrator. Every consequential action is policy-gated.
14-
15-
## Architecture (in brief)
16-
17-
- **Runtime layer** (`src/core/`): `types`, `llm`, `logger`, `event-bus`, `store`
18-
(SQLite via better-sqlite3), `tool` (typed registry + permissions), `policy`
19-
(allow/deny/approve decisions + spend tracking), `memory`, `agent` (reasoning
20-
loop), `orchestrator` (lifecycle, dispatch, concurrency, retries), `app`
21-
(composition root).
22-
- **Agents** (`src/agents/`): one file per department; each declares a system
23-
prompt, a tool subset, and owns its domain tools.
24-
- **Tools** (`src/tools/`): CRM, comms, billing, knowledge, system packs.
25-
Every tool declares a `ToolPermission` (category + optional cost cap +
26-
`requiresApproval`).
27-
- **Control plane** (`src/api/`): Express REST + WebSocket; serves the dashboard.
28-
29-
## Key conventions
30-
31-
- TypeScript, ESM (`"type": "module"`), strict. Node >= 20.
32-
- 2-space indent, LF, no trailing whitespace (see `.editorconfig`).
33-
- IDs via `nanoid`. JSON-schema for tool parameter validation; `zod` only where
34-
ergonomic.
35-
- No comments unless genuinely necessary.
36-
- Consequential tools (spend, external comms, mutating) MUST route through the
37-
policy engine and produce audit events. Nothing destructive runs autonomously.
38-
- Agent reasoning loop is LLM-driven but fully reproducible under the
39-
`SimulationProvider` (scripted responses) — all tests run without network.
40-
41-
## Commands
42-
43-
- Install: `npm install`
44-
- Typecheck: `npm run typecheck`
45-
- Build: `npm run build`
46-
- Run server (API + dashboard): `npm run dev` (boots on `$PORT` or 3000)
47-
- Run a recorded multi-agent scenario: `npm run scenario`
48-
- Tests: `npm test` (vitest)
49-
50-
## LLM provider
51-
52-
Agents call **OpenRouter** via its OpenAI-compatible endpoint
53-
(`https://openrouter.ai/api/v1`), model **Owl Alpha**, key from
54-
`OPENROUTER_API_KEY` and slug from `OPENROUTER_MODEL` (default
55-
`openrouter/owl-alpha` — set the real OpenRouter slug for Owl Alpha there).
56-
Optional `OPENROUTER_REFERER` / `OPENROUTER_TITLE` set the OpenRouter
57-
`HTTP-Referer` / `X-Title` headers. Z.AI and OpenAI remain supported as
58-
alternatives (`provider: "zai"|"openai"`); the factory auto-detects by key.
59-
60-
**Gotcha: no key is set in this environment.** The system runs
61-
**simulation-first** — the `SimulationProvider` returns scripted/tool-driven
62-
responses so the full system is demonstrable and tested without network. Provide
63-
`OPENROUTER_API_KEY` to switch the default agent provider to live OpenRouter.
64-
Never log keys.
65-
66-
## Gotchas
67-
68-
- Do NOT edit `package-lock.json` directly (permission-denied by design); run
69-
`npm install` to change the lockfile.
70-
- Agent Manager run-script derives a per-worktree `$PORT` from the worktree path;
71-
parallel worktrees bind different ports — read `$PORT`, don't hardcode 3000.
72-
- SQLite file (`data/company.db`) is created at runtime; do not commit it.
73-
- The reasoning loop is non-deterministic under a live LLM; deterministic tests
74-
rely on `SimulationProvider` scripts.
11+
Site id: `corpos`. Program: `corpos-autonomous-company`.

Dockerfile

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,12 @@
1-
# CorpOS control-plane image.
2-
#
3-
# Runs the app under tsx (the same ESM resolver used in dev). The codebase
4-
# uses directory/extensionless imports that tsx resolves; a compiled image
5-
# would require a bundler step, which is out of scope for this reference.
6-
# Simulation-first: works with zero configuration (no API key required).
7-
8-
FROM node:20-alpine AS base
9-
1+
FROM node:22-bookworm-slim
102
WORKDIR /app
11-
12-
# Install dependencies first for better layer caching.
13-
COPY package.json package-lock.json ./
14-
RUN npm ci && npm cache clean --force
15-
16-
# Copy the application source (dashboard + runtime + tools + tests).
17-
COPY . .
18-
19-
# SQLite writes here at runtime; ensure the non-root user owns it.
20-
RUN mkdir -p data && chown -R node:node /app
21-
22-
ENV NODE_ENV=production \
23-
PORT=3000 \
24-
LOG_LEVEL=info
25-
26-
USER node
27-
3+
COPY package.json package-lock.json* .npmrc* ./
4+
COPY packages ./packages
5+
COPY apps ./apps
6+
COPY scripts ./scripts
7+
COPY tsconfig*.json vitest.config.ts eslint.config.mjs ./
8+
RUN corepack enable && corepack prepare npm@10.9.2 --activate \
9+
&& npm ci && npm run build
10+
ENV PORT=3000
2811
EXPOSE 3000
29-
30-
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
31-
CMD wget -qO- "http://127.0.0.1:${PORT:-3000}/api/health" >/dev/null 2>&1 || exit 1
32-
33-
# No API key set → simulation mode. Set OPENROUTER_API_KEY (etc.) to go live.
34-
CMD ["npx", "tsx", "src/index.ts"]
12+
CMD ["npm", "run", "start"]

0 commit comments

Comments
 (0)