openvibers/openvibe.codes Commits
AGENTS.md: the context an agent starts from (#429)
Changes
nnew file mode 100644@@@ -0,0 +1,168 @@++# AGENTS.md — OpenVibe.Codes++++## Project overview++++The open coding-agent harness: one place to send a coding task to the agent that fits it (by what the++task needs first, then cost), hand it over when an agent gets stuck, and keep the run in one place.++The same package runs on a person's own machine with their CLIs and keys; the site is the front door,++the router and the record. Node.js/Express + the `harness/` package, PostgreSQL (`ov_codes`),++CommonJS, **no build step**.++++- Service id `codes`, port `4900`, origin `https://openvibe.codes`, unit `openvibe-codes.service`,++ release root `/opt/openvibe.codes`; live on openvibe-ovh.++- Design: plan T16 and [ADR-050](docs/adr/050-codes-harness-fabric.md). The developer console that++ used to live here moved to **OpenVibe.Services** on 2026-10-08; every one of its addresses here is++ a permanent redirect there.++- `package.json` `main` is [harness/index.js](harness/index.js) — the installable harness — while++ `npm start` runs [server/index.js](server/index.js), the site.++++## What it owns++++- The harness catalog and routing policy over it; placement itself is `openvibe-sdk/placement`.++- The harness package ([harness/](harness/), [bin/](bin/)): adapters for Claude Code, Codex, OpenCode,++ Command Code, Aider, the DeepSeek API and self-hosted models; the shared event format, hand-offs++ and the local run store.++- The site's records: `run_tasks` (tasks started on the site or API), `codes_session_lines`,++ attempts/hand-offs, inbound Run events and the `codes.task.*` outbox.++- Knowledge (`codes_knowledge`), skills/Rules/MCP/commands/hooks with immutable versions++ (`codes_skills`, `codes_skill_versions`), sharing, the task API/SSE stream and the agent catalog.++- Pages: `/`, `/start`, `/run`, `/run/tasks/:id`, `/knowledge`, `/skills`, `/harnesses`, `/improve`,++ `/policy*`, `/updates`, and the machine endpoints.++++Not owned: the sandboxes/browsers (OpenVibe.Run), the machine's Link plugin (Link), the OpenVibe Git++host (`git.openvibe.codes`, repo OpenVibe-Git), the AI model runs (`openvibe.ai`, called through the++catalog), identity/grants (Network/Services), and the console that moved to Services.++++## Who calls it, and whom it calls++++- Callers: people in the browser; services with a Network service token audience `openvibe.codes` and++ `codes.task.start|read|cancel` (OpenVibe.Actor is the main one), using `X-OV-Subject` (and++ `X-OV-Project`) to act for a person; the CLI `openvibe-codes task` with the person's own token.++- Depends on: **Network** (SSO client `codes`, PKCE, JWKS); **AI** (`ai.openvibe.services` — the++ model catalog and completion); **Run** (`server/domain/run-client.js` — jobs in class `code`,++ artifact `[email protected]`, `trust: user-owned`, placed only on the person's machines);++ **Link** (`openvibe-codes job` in the machine's job sandbox); **Network projects** for delegation;++ **Git** (`git.openvibe.codes` — branch push and pull request with Codes' service token acting for++ the person); PostgreSQL and Valkey; Events for the outbox.++++## Repository map++++- **Site entry:** [server/index.js](server/index.js) — `createApp()`, listen, graceful stop.++- **App:** [server/app.js](server/app.js) — helmet/CSP, `/internal/events`,++ `/internal/sandbox-workers`, `/auth`, `/shared`, `/api/v1` (agent, task, knowledge, skills and++ resource routers), pages, moved-address redirects, machine endpoints.++- **Harness entry:** [harness/index.js](harness/index.js) — `createHarness({ env, fetch, store })`,++ `agents()`, `route()`, `run()` and the event stream; [harness/job.js](harness/job.js) is the job the++ Link runs.++- **Domain:** [server/domain/](server/domain/) — `run-tasks.js`, `attempts.js`, `harnesses.js`,++ `harness-placement.js`, `knowledge.js`, `skills.js`, `run-client.js`, `github.js`, `redact.js`.++- **HTTP:** [server/http/](server/http/) — `pages.js`, `api.js`, `tasks-api.js`, `run.js`,++ `knowledge.js`, `skills-pages.js`, `moved.js`, `discovery.js`, `openapi.js`.++- **Catalog:** [server/data/harness-offers.json](server/data/harness-offers.json) (validated at boot).++- **Browser:** [public/js/run.js](public/js/run.js), `composer.js`, `chat.js`, `c4.js`, `copy.js`,++ `setup.js`; CSS in [public/css/](public/css/).++- **Sandbox:** [sandbox/](sandbox/) (bwrap/seccomp/egress, worker/supervisor),++ [deploy/sandbox/](deploy/sandbox/).++- **Deploy:** [deploy/systemd/openvibe-codes.service](deploy/systemd/openvibe-codes.service),++ [deploy/nginx/openvibe.codes.conf](deploy/nginx/openvibe.codes.conf).++++## Commands++++```bash++npm ci++npm run dev # NODE_ENV=development node server/index.js++npm start # node server/index.js, http://127.0.0.1:4900++npm test # test/run.js, temp PGlite, mock Network/Events/Media++npm run test:pg # same suite on PostgreSQL (CODES_TEST_STORE=pg)++npm test -- schedule # filter by file name; --strict makes a skip fail++ov test # the harness's sharded run of what the change reaches++```++++The harness is also run from a machine:++++```bash++npm install -g <this repo tarball>++openvibe-codes agents # what this machine can run, and why not the rest++openvibe-codes run "…" # routed, handed off on failure, kept++```++++## Database and migrations++++PostgreSQL database `ov_codes` on the host's data role (ADR-035); PGlite in development/tests.++Async through `openvibe-sdk/db`; migrations `migrations/NNNN_*.sql` applied at boot with the owner++connection (`DATABASE_DIRECT_URL`). Never edit an applied migration. **Migration 0002 dropped the old++console tables** (rows were copied into `ov_services`): a rollback to a release before it finds no++console tables, so roll forward or restore `ov_codes` from the pre-deploy backup. Skills are++versioned: every save is an immutable version and a rollback copies an old version into a new one —++never UPDATE a version body.++++## Auth and task ownership++++- The site signs people in with Network SSO (OAuth client `codes`, PKCE S256); session tokens are++ HttpOnly cookies. A FedCM assertion, an app token or a service token is never a session.++- The task API accepts either the person's own Network access token (they see every task they own,++ whoever started it) or a first-party service token with the route's capability plus++ `X-OV-Subject`; a service reads/cancels only the tasks it started for that person (otherwise 404).++- `idempotency_key` makes a retry answer the first task (`200`, `created: false`).++- Per-person budgets: starts and cancels 6/minute, 60/hour. `permission` is `review` (read-only),++ `edit` (default) or `full`.++- Codes never sends or accepts a shared loopback key (tested by grep and at runtime).++++## Frontend loading model++++Everything on the site is **server-rendered and usable without JavaScript**; small no-build scripts++under [public/js/](public/js/) enhance the run view, composer, chat and C4 pages. There is no SPA,++bundler or transpiler. `openvibe-shared` supplies the Frame, the session view++(`openvibe-shared/agent-session.js`) and `/shared/*` from the pinned node_modules. CSP is in++[server/app.js](server/app.js); crawl files use `openvibe-shared/seo` and IndexNow on deploy.++++## Deploy++++`sudo ovhost deploy codes` (git-checkout: fetch, fast-forward `/opt/openvibe.codes`, install on a++lockfile change, restart, wait for `/api/ready`). Unit `openvibe-codes.service` on `127.0.0.1:4900`,++env `/etc/openvibe/codes.env`; vhost++[deploy/nginx/openvibe.codes.conf](deploy/nginx/openvibe.codes.conf). Rollback++`sudo ovhost rollback codes --to <sha>` — mind migration 0002 above. The sandbox worker is a separate++unit/service installed from [deploy/sandbox/install.sh](deploy/sandbox/install.sh).++++## Tests++++`npm test` runs each `test/*.test.js` in its own process through `openvibe-shared/test-runner`, with++PGlite and in-process Network/Events/Media mocks. It covers the harness adapters and hand-offs,++routing/catalog, the task API and attempts/SSE, knowledge and skills, redaction, the moved redirects,++the pages/llms/openapi, sandbox rules and the contracts. `ov test` runs the same.++++## Conventions++++- CommonJS, 4-space indent, single quotes, semicolons; domain logic in `server/domain/`, HTTP in++ `server/http/`, harness in `harness/`; injectable config/db/clock/fetch/log.++- The harness is standalone: it must not need OpenVibe to run, and nothing about a local run goes++ through OpenVibe unless the person asks.++- Errors are RFC 9457 problem+json with stable codes (`harness.invalid`, `harness.task_unknown`,++ `codes.no_project`); never leak a path, a key or a request body.++- IDs and capability names come from `openvibe-contracts`; bump the pin before using a new one.++++## Pitfalls++++- **Never push the branch a task started from.** A job may push a new branch (never the base) and open++ a pull request only when asked and the machine holds `GITHUB_TOKEN`.++- **The API loop stays in the working directory**, never reads `.env`, never writes under `.git`;++ the permission levels (`review`/`edit`/`full`) are enforced by the adapters, not by prompt text.++- **`/run` tasks run on the person's own machine**, not OpenVibe's. A task with no `/run` project is++ `409 codes.no_project`; do not "fix" it by placing work anywhere else.++- **Knowledge is private by default and redacted** before storage; a shared row goes through the++ share gate, never a raw link.++- **Skills are immutable versions**; a rollback is a new version.++- **Moved addresses are 301 for GET/HEAD and 308 for anything else**, preserving path, query, method++ and body — do not reintroduce the console.++- **`/metrics` is loopback only**; readiness is truthful (database + catalog required).++- **A service may act only for the person it names** and only on the tasks it started.++++## Documentation++++- [README.md](README.md) — every surface, the harness, API, configuration and deploy.++- [docs/adr/050-codes-harness-fabric.md](docs/adr/050-codes-harness-fabric.md) — the boundaries.++- [docs/harness-runtime.md](docs/harness-runtime.md), [docs/cli.md](docs/cli.md),++ [docs/checkpoints.md](docs/checkpoints.md), [docs/agent-runs.md](docs/agent-runs.md).++- [docs/model-plans.md](docs/model-plans.md), [docs/g3-local-clone.md](docs/g3-local-clone.md),++ [docs/governance/](docs/governance/), [CONTRIBUTING.md](CONTRIBUTING.md).nnew file mode 100644@@@ -0,0 +1 @@
new file mode 100644
new file mode 100644
@@ -0,0 +1,168 @@
@@ -0,0 +1,168 @@
+# AGENTS.md — OpenVibe.Codes
+
+## Project overview
+
+The open coding-agent harness: one place to send a coding task to the agent that fits it (by what the
+task needs first, then cost), hand it over when an agent gets stuck, and keep the run in one place.
+The same package runs on a person's own machine with their CLIs and keys; the site is the front door,
+the router and the record. Node.js/Express + the `harness/` package, PostgreSQL (`ov_codes`),
+CommonJS, **no build step**.
+
+- Service id `codes`, port `4900`, origin `https://openvibe.codes`, unit `openvibe-codes.service`,
+ release root `/opt/openvibe.codes`; live on openvibe-ovh.
+- Design: plan T16 and [ADR-050](docs/adr/050-codes-harness-fabric.md). The developer console that
+ used to live here moved to **OpenVibe.Services** on 2026-10-08; every one of its addresses here is
+ a permanent redirect there.
+- `package.json` `main` is [harness/index.js](harness/index.js) — the installable harness — while
+ `npm start` runs [server/index.js](server/index.js), the site.
+
+## What it owns
+
+- The harness catalog and routing policy over it; placement itself is `openvibe-sdk/placement`.
+- The harness package ([harness/](harness/), [bin/](bin/)): adapters for Claude Code, Codex, OpenCode,
+ Command Code, Aider, the DeepSeek API and self-hosted models; the shared event format, hand-offs
+ and the local run store.
+- The site's records: `run_tasks` (tasks started on the site or API), `codes_session_lines`,
+ attempts/hand-offs, inbound Run events and the `codes.task.*` outbox.
+- Knowledge (`codes_knowledge`), skills/Rules/MCP/commands/hooks with immutable versions
+ (`codes_skills`, `codes_skill_versions`), sharing, the task API/SSE stream and the agent catalog.
+- Pages: `/`, `/start`, `/run`, `/run/tasks/:id`, `/knowledge`, `/skills`, `/harnesses`, `/improve`,
+ `/policy*`, `/updates`, and the machine endpoints.
+
+Not owned: the sandboxes/browsers (OpenVibe.Run), the machine's Link plugin (Link), the OpenVibe Git
+host (`git.openvibe.codes`, repo OpenVibe-Git), the AI model runs (`openvibe.ai`, called through the
+catalog), identity/grants (Network/Services), and the console that moved to Services.
+
+## Who calls it, and whom it calls
+
+- Callers: people in the browser; services with a Network service token audience `openvibe.codes` and
+ `codes.task.start|read|cancel` (OpenVibe.Actor is the main one), using `X-OV-Subject` (and
+ `X-OV-Project`) to act for a person; the CLI `openvibe-codes task` with the person's own token.
+- Depends on: **Network** (SSO client `codes`, PKCE, JWKS); **AI** (`ai.openvibe.services` — the
+ model catalog and completion); **Run** (`server/domain/run-client.js` — jobs in class `code`,
+ artifact `[email protected]`, `trust: user-owned`, placed only on the person's machines);
+ **Link** (`openvibe-codes job` in the machine's job sandbox); **Network projects** for delegation;
+ **Git** (`git.openvibe.codes` — branch push and pull request with Codes' service token acting for
+ the person); PostgreSQL and Valkey; Events for the outbox.
+
+## Repository map
+
+- **Site entry:** [server/index.js](server/index.js) — `createApp()`, listen, graceful stop.
+- **App:** [server/app.js](server/app.js) — helmet/CSP, `/internal/events`,
+ `/internal/sandbox-workers`, `/auth`, `/shared`, `/api/v1` (agent, task, knowledge, skills and
+ resource routers), pages, moved-address redirects, machine endpoints.
+- **Harness entry:** [harness/index.js](harness/index.js) — `createHarness({ env, fetch, store })`,
+ `agents()`, `route()`, `run()` and the event stream; [harness/job.js](harness/job.js) is the job the
+ Link runs.
+- **Domain:** [server/domain/](server/domain/) — `run-tasks.js`, `attempts.js`, `harnesses.js`,
+ `harness-placement.js`, `knowledge.js`, `skills.js`, `run-client.js`, `github.js`, `redact.js`.
+- **HTTP:** [server/http/](server/http/) — `pages.js`, `api.js`, `tasks-api.js`, `run.js`,
+ `knowledge.js`, `skills-pages.js`, `moved.js`, `discovery.js`, `openapi.js`.
+- **Catalog:** [server/data/harness-offers.json](server/data/harness-offers.json) (validated at boot).
+- **Browser:** [public/js/run.js](public/js/run.js), `composer.js`, `chat.js`, `c4.js`, `copy.js`,
+ `setup.js`; CSS in [public/css/](public/css/).
+- **Sandbox:** [sandbox/](sandbox/) (bwrap/seccomp/egress, worker/supervisor),
+ [deploy/sandbox/](deploy/sandbox/).
+- **Deploy:** [deploy/systemd/openvibe-codes.service](deploy/systemd/openvibe-codes.service),
+ [deploy/nginx/openvibe.codes.conf](deploy/nginx/openvibe.codes.conf).
+
+## Commands
+
+```bash
+npm ci
+npm run dev # NODE_ENV=development node server/index.js
+npm start # node server/index.js, http://127.0.0.1:4900
+npm test # test/run.js, temp PGlite, mock Network/Events/Media
+npm run test:pg # same suite on PostgreSQL (CODES_TEST_STORE=pg)
+npm test -- schedule # filter by file name; --strict makes a skip fail
+ov test # the harness's sharded run of what the change reaches
+```
+
+The harness is also run from a machine:
+
+```bash
+npm install -g <this repo tarball>
+openvibe-codes agents # what this machine can run, and why not the rest
+openvibe-codes run "…" # routed, handed off on failure, kept
+```
+
+## Database and migrations
+
+PostgreSQL database `ov_codes` on the host's data role (ADR-035); PGlite in development/tests.
+Async through `openvibe-sdk/db`; migrations `migrations/NNNN_*.sql` applied at boot with the owner
+connection (`DATABASE_DIRECT_URL`). Never edit an applied migration. **Migration 0002 dropped the old
+console tables** (rows were copied into `ov_services`): a rollback to a release before it finds no
+console tables, so roll forward or restore `ov_codes` from the pre-deploy backup. Skills are
+versioned: every save is an immutable version and a rollback copies an old version into a new one —
+never UPDATE a version body.
+
+## Auth and task ownership
+
+- The site signs people in with Network SSO (OAuth client `codes`, PKCE S256); session tokens are
+ HttpOnly cookies. A FedCM assertion, an app token or a service token is never a session.
+- The task API accepts either the person's own Network access token (they see every task they own,
+ whoever started it) or a first-party service token with the route's capability plus
+ `X-OV-Subject`; a service reads/cancels only the tasks it started for that person (otherwise 404).
+- `idempotency_key` makes a retry answer the first task (`200`, `created: false`).
+- Per-person budgets: starts and cancels 6/minute, 60/hour. `permission` is `review` (read-only),
+ `edit` (default) or `full`.
+- Codes never sends or accepts a shared loopback key (tested by grep and at runtime).
+
+## Frontend loading model
+
+Everything on the site is **server-rendered and usable without JavaScript**; small no-build scripts
+under [public/js/](public/js/) enhance the run view, composer, chat and C4 pages. There is no SPA,
+bundler or transpiler. `openvibe-shared` supplies the Frame, the session view
+(`openvibe-shared/agent-session.js`) and `/shared/*` from the pinned node_modules. CSP is in
+[server/app.js](server/app.js); crawl files use `openvibe-shared/seo` and IndexNow on deploy.
+
+## Deploy
+
+`sudo ovhost deploy codes` (git-checkout: fetch, fast-forward `/opt/openvibe.codes`, install on a
+lockfile change, restart, wait for `/api/ready`). Unit `openvibe-codes.service` on `127.0.0.1:4900`,
+env `/etc/openvibe/codes.env`; vhost
+[deploy/nginx/openvibe.codes.conf](deploy/nginx/openvibe.codes.conf). Rollback
+`sudo ovhost rollback codes --to <sha>` — mind migration 0002 above. The sandbox worker is a separate
+unit/service installed from [deploy/sandbox/install.sh](deploy/sandbox/install.sh).
+
+## Tests
+
+`npm test` runs each `test/*.test.js` in its own process through `openvibe-shared/test-runner`, with
+PGlite and in-process Network/Events/Media mocks. It covers the harness adapters and hand-offs,
+routing/catalog, the task API and attempts/SSE, knowledge and skills, redaction, the moved redirects,
+the pages/llms/openapi, sandbox rules and the contracts. `ov test` runs the same.
+
+## Conventions
+
+- CommonJS, 4-space indent, single quotes, semicolons; domain logic in `server/domain/`, HTTP in
+ `server/http/`, harness in `harness/`; injectable config/db/clock/fetch/log.
+- The harness is standalone: it must not need OpenVibe to run, and nothing about a local run goes
+ through OpenVibe unless the person asks.
+- Errors are RFC 9457 problem+json with stable codes (`harness.invalid`, `harness.task_unknown`,
+ `codes.no_project`); never leak a path, a key or a request body.
+- IDs and capability names come from `openvibe-contracts`; bump the pin before using a new one.
+
+## Pitfalls
+
+- **Never push the branch a task started from.** A job may push a new branch (never the base) and open
+ a pull request only when asked and the machine holds `GITHUB_TOKEN`.
+- **The API loop stays in the working directory**, never reads `.env`, never writes under `.git`;
+ the permission levels (`review`/`edit`/`full`) are enforced by the adapters, not by prompt text.
+- **`/run` tasks run on the person's own machine**, not OpenVibe's. A task with no `/run` project is
+ `409 codes.no_project`; do not "fix" it by placing work anywhere else.
+- **Knowledge is private by default and redacted** before storage; a shared row goes through the
+ share gate, never a raw link.
+- **Skills are immutable versions**; a rollback is a new version.
+- **Moved addresses are 301 for GET/HEAD and 308 for anything else**, preserving path, query, method
+ and body — do not reintroduce the console.
+- **`/metrics` is loopback only**; readiness is truthful (database + catalog required).
+- **A service may act only for the person it names** and only on the tasks it started.
+
+## Documentation
+
+- [README.md](README.md) — every surface, the harness, API, configuration and deploy.
+- [docs/adr/050-codes-harness-fabric.md](docs/adr/050-codes-harness-fabric.md) — the boundaries.
+- [docs/harness-runtime.md](docs/harness-runtime.md), [docs/cli.md](docs/cli.md),
+ [docs/checkpoints.md](docs/checkpoints.md), [docs/agent-runs.md](docs/agent-runs.md).
+- [docs/model-plans.md](docs/model-plans.md), [docs/g3-local-clone.md](docs/g3-local-clone.md),
+ [docs/governance/](docs/governance/), [CONTRIBUTING.md](CONTRIBUTING.md).
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@