17 KiB
AGENTS.md — Canonical Agent Instructions for Veritas Kanban
Canonical source. All coding harnesses — Codex, OpenClaw, Hermes, Claude, and others — read this file first. Harness-specific supplements (e.g.
CLAUDE.md) extend, never duplicate or contradict, these rules.Version: 5.2.5 Freshness policy: update within two working days of any toolchain or architecture change. Stale fields (package manager, Node version, provider list, test commands) are caught by
pnpm check:pnpm-settingsand the smoke-test CI job.
Runtime requirements
| Tool | Required version | How to verify |
|---|---|---|
| Node.js | ≥ 22.22.1 | node --version |
| pnpm | ≥ 11.0.0 | pnpm --version |
| Git | ≥ 2.38 | git --version |
The packageManager field in package.json is pinned to pnpm@11.1.1. Do not install with npm
or yarn. Do not up-rev the pin without updating this file.
Repository layout
veritas-kanban/
├── server/ Express + TypeScript API, agent orchestration, storage
├── web/ React + Vite SPA
├── cli/ Commander.js CLI (mirrors API endpoints)
├── shared/ Shared TypeScript types and utilities
├── mcp/ MCP server
├── desktop/ Electron desktop wrapper
├── docs/ Operator and developer documentation
├── prompt-registry/ Prompt templates and cross-model review SOPs
└── .veritas-kanban/ Runtime data: agent-registry, logs, telemetry
Workspaces are declared in pnpm-workspace.yaml.
Essential commands
# Install
pnpm install
# Build (all workspaces in dependency order)
pnpm build
# Dev server (server + web, hot-reload)
pnpm dev
# Tests
pnpm test # Vitest across server, web, mcp, cli
pnpm test:unit # Per-workspace tests sequentially
pnpm test:e2e # Playwright end-to-end
# Type check (builds shared first)
pnpm typecheck
# Lint / fix
pnpm lint
pnpm lint:fix
# Smoke checks
pnpm check:pnpm-settings # Validates package manager fields match this file
pnpm smoke:cli-mcp # CLI ↔ MCP compatibility smoke test
Do not run npm install, yarn, or bun install. If lockfile conflicts arise, resolve with
pnpm install and commit the updated pnpm-lock.yaml without reformatting it.
Architecture rules
Server (Express + TypeScript)
- All routes go through centralized middleware in
server/src/middleware/. - Auth: JWT + API keys. Dev bypass:
VERITAS_AUTH_LOCALHOST_BYPASS=true. - Storage: always go through
storage/interfaces.ts. Never importfsdirectly in service files. - Error classes:
UnauthorizedError,ForbiddenError,BadRequestError,InternalError. - Pagination:
sendPaginated(res, items, { page, limit, total }). - Path traversal: always call
validatePathSegment()on any user-supplied path component, thenensureWithinBase(base, resolved)before file I/O. - SQLite journal conversion runs from the bootstrap before
server.tsimports routes. Normal startup eagerly creates many independent SQLite handles, so a live API handler cannot prove exclusive database ownership. - Governed SQLite
DELETEor expert-override mode requires the signed external policy and the reference-counted process/host ownership lock. Do not reuse the short-lived genericFileLockfor authoritative database ownership.
Web (React + Vite)
- State: Zustand stores. No prop drilling past 2 levels.
- Realtime:
useRealtimeUpdatesWebSocket hooks. Do not add polling when a hook exists. - Styling: Tailwind CSS with component-scoped overrides.
- Frontend interfaces must exactly match server response shapes. Server is the source of truth.
CLI (Commander.js)
- Every command mirrors an API endpoint.
--jsonflag for machine-readable output.- Colored output via
chalk.
Shared types
- All cross-package types live in
shared/src/types/. AgentProviderunion is the single definition consumed by both server and web. Currently supported providers:openclaw|codex-cli|codex-sdk|codex-app-server|codex-cloud|claude-code|acp-stdio|hermes-cli|ollama-local|ollama-cloud|lm-studio-local|custom- Executable task adapters are currently
openclaw,codex-cli,codex-sdk,codex-app-server,claude-code,acp-stdio, andhermes-cli. Explicitly configured providers outside that set must fail closed; never route them through an implicit OpenClaw fallback. - Probe and persist
provider-runtime-manifest/v1before mutating attempt state. New runtime controls must use the persisted evidence instead of provider-name checks, and provider version/build changes must invalidate cached conformance. IncrementPROVIDER_RUNTIME_PROBE_REVISIONwhenever probe semantics or the built-in adapter capability evidence changes. - Normalize every configured harness through
harness-support-profile/v1. Settings, API diagnostics,vk doctor, dispatch, and telemetry must use the same support tier and redacted readiness evidence. Only known legacy records whose built-in type and command both identifycodexorhermesmay infer a provider during migration; provider-less or profile/adapter-mismatched records fail closed before an attempt is created. - Credential-bound tool servers persist only exact definition/scope digests and
safe target names in
run-tool-catalog/v1. Discovery strips their source environment/header values, native provider injection omits them, and mediated invocation issues exact-action leases using the server-owned launch manifest digest. Credential-bound sessions are one-shot and raw values may exist only inside the controlled downstream dispatch callback. - Providers access credential-bound tools only through the system-owned
veritas-runMCP bridge and an opaque in-memory run handle. Codex CLI/SDK, Codex app-server, Claude Code, and ACP stdio inject this shared contract; Hermes and OpenClaw fail closed until their certified transports can enforce it. - Classify launch credentials through
run-launch-credential-plan/v1. Provider boot authentication, task integration definition IDs, and explicit high-risk environment passthrough are separate classes. Task integration credentials fail closed until an accepted tool or egress boundary proves brokered, non-bypassable delivery. - Persist
run-supervisor/v1before provider dispatch. Restart recovery must validate the exact runtime, task-envelope, launch-manifest, worktree, host, lease, and process/session identity; replay only after the durable event cursor; and record a typed recovery action instead of starting duplicate work or signaling an unverified process. - Resolve selected MCP servers through
tool-server-definition/v1and persist an immutablerun-tool-catalog/v1before provider dispatch. Required discovery failures block launch; optional failures remain visible and audited. - Native provider configuration may expose only tools with an
allowdecision. Approval-required tools must use the Veritas-mediatedcall_run_toolpath so the exact action hash is approved before dispatch. - Tool-server environment values and credential values are never persisted. Credential-bound tool definitions remain fail-closed until the provider launch credential broker is active.
Agent provider notes
OpenClaw (v2026.6.11)
- Task dispatch uses the gateway
/tools/invokeendpoint withsessions_spawn. - Required gateway policy:
sessions_spawnandsessions_sendmust be explicitly allowed on the operator-level gateway; they are blocked by default on fresh OpenClaw installs. - Set
OPENCLAW_GATEWAY_URL(defaulthttp://127.0.0.1:18789) and optionallyOPENCLAW_GATEWAY_TOKEN. - A pre-flight check is run before a task is marked active; policy denial returns an actionable configuration error.
- See
docs/AGENT-PROVIDERS.md§ OpenClaw for full setup instructions.
Hermes Agent (v2026.7.7.2)
- Dispatch uses the one-shot scripted interface:
hermes -z <prompt>. - Hermes is spawned in the task worktree without a shell; stdout captures the final response, stderr captures diagnostics.
- Project instructions are loaded automatically from
AGENTS.mdin the worktree root. - Session resume is not yet implemented;
--resume/--continueare reserved for a future provider iteration. - Provider ID:
hermes-cli. Auth probe:hermes --version. - Set
HERMES_API_KEYor the appropriate model-provider key in the operator environment. - See
docs/AGENT-PROVIDERS.md§ Hermes for full setup instructions.
Codex (OpenAI)
codex-cli:codex exec --sandbox workspace-write --jsoncodex-sdk: programmatic SDK, requires@openai/codex-sdkcodex-app-server: pinned tocodex-cli 0.145.0; supervised JSON-RPC v2 over strict stdio for one task-bound thread and turn.- App-server launch arguments are system-owned. Inherited MCP servers, hooks, plugins, apps, browser/computer tools, and remote control remain disabled. Selected run-scoped MCP servers are injected only through the immutable catalog's thread configuration.
- App-server consumes only the checked-in v0.145.0 schemas and exposes
initialize, thread start/resume/fork/compact/archive, and turn start/steer/interrupt.thread/shellCommandis never reachable. conversation-lifecycle/v1persists opaque thread, turn, item, parent, and fork identities. Resume and fork validate the source launch manifest, provider/model/policy, base revision, and worktree compatibility before a new attempt is created.- App-server command, file, permission, tool-question, and elicitation requests
use
run-approval/v1. Decisions must preserve the persisted revision and exact action hash; interruption and cancellation invalidate pending requests. - Auth:
codex login status/OPENAI_API_KEY
Claude Code (v2.1.218)
- Provider ID:
claude-code. Default command:claude. - Veritas launches
claude --bare --print --output-format stream-jsonwith static sandbox-derived permissions and no shell. - Bare mode requires explicit environment authentication. OAuth/keychain state
reported by
claude auth statusdoes not prove bare-mode readiness. - The terminal
resultrecord is authoritative. Veritas drains stdout after process close, persistssession_id, and maps partial, hook, tool, subagent, usage, cost, and result records intorun-event/v1. - Resume uses the exact persisted session through system-owned
--resume. Native history fork adds--fork-session; caller-supplied lifecycle flags remain prohibited. Run-scoped MCP uses a system-owned strict config and exposes only catalog tools with anallowdecision. - The shared approval broker is available, but Claude stays on static
dontAskpermissions until its adapter exposes a pinned interactive request/response contract.
Agent Client Protocol (ACP v1)
- Provider ID:
acp-stdio. Configure the exact ACP agent command and arguments. - Veritas launches the agent without a shell in the task worktree and negotiates stable ACP protocol version 1 before attempt mutation.
- Capability evidence comes from
initialize; resume/load, fork, and close fail closed when the runtime does not advertise them. session/updaterecords enter the causal run journal.session/request_permissionuses the durable approval broker.- Only immutable all-allow MCP server catalogs can be passed natively because ACP v1 has no per-tool allowlist. Partial catalogs fail closed.
- The built-in
buzz-agentprofile remains provideracp-stdio, pins Buzzv0.4.24at commit710ed9fff57878a1d69f809b80a6ee0416c53fc4, and rejectsbuzz-acp, version drift, session loading, and network MCP claims. - The built-in
copilotprofile remains provideracp-stdio, pins Copilot CLIv1.0.74, owns the stdio safety argv, rejects broad allow/remote/TCP/config injection, and records public-preview plus incomplete-source limitations. - The built-in
grok-buildprofile remains provideracp-stdio, pins Grok Buildv0.2.111build94172f2aa4e5, launchesgrok agent --no-leader stdio, and rejects approval bypass, reauthentication, leader, plugin, endpoint, prompt, and resume argument injection. vk acp serve --stdioexposes one Veritas-managed task as an ACP v1 server view for editors and other ACP clients. Bind with--taskor require_meta["veritas/taskId"]onsession/new; client-owned MCP catalogs fail closed.- ACP client disconnect never stops the durable Veritas run. Reconnect with
session/loadand_meta["veritas/afterSequence"]; cancellation uses the conversation interrupt path, not task termination. - See
docs/AGENT-PROVIDERS.md§ ACP stdio agent provider.
Security boundaries
- No secrets in code. Use environment variables or brokered credentials.
- Input validation. All user input is validated with Zod schemas before processing.
- Path traversal.
validatePathSegment()+ensureWithinBase()on every user-supplied path. - Env passthrough. Agents receive only the keys in the configured safe allowlist; see
server/src/utils/codex-env.ts,server/src/utils/hermes-env.ts, andserver/src/services/claude-code-adapter.tsplusserver/src/services/acp-stdio-adapter.ts. - Launch arguments. Never put credential values in provider commands or arguments; use an allowlisted environment key or run-scoped brokered credential reference.
- Log redaction. Trace logs and telemetry run through
TRACE_SECRET_PATTERNSbefore storage. - No credentials in PR descriptions, test fixtures, or log snippets.
Testing expectations
- Framework: Vitest (server, cli, mcp), React Testing Library (web).
- Test files:
*.test.tsco-located insrc/__tests__/or alongside source. - Aim for >80% coverage on critical paths (agent dispatch, auth, storage adapters).
- Use
vi.mock()/vi.fn()to isolate external processes and HTTP calls; no live credentials in unit tests. - Credential-gated smoke tests document the tested provider version in a
@smokedescribe block. - Match actual runtime schema in test fixtures — wrong field names (
status: "success"vssuccess: true) are a common source of false-passing tests.
Multi-agent runtime
- Agent registry:
.veritas-kanban/agent-registry.json(file-based). - Agent names: use ALL CAPS for acronyms (VERITAS, TARS, CASE, K-2SO, R2-D2, MAX).
- Heartbeat timeout: 5 min (configurable). Stale-check interval: 1 min.
- Activity data source of truth:
status-historyfiles, notactivity.json. - Dashboard optimistic updates: use
onMutatein Zustand mutations.
Conventions
| Artifact | Style |
|---|---|
| TS files | kebab-case.ts |
| Components | PascalCase.tsx |
| Variables | camelCase |
| Constants | UPPER_SNAKE_CASE |
| Git commits | Conventional Commits (feat:, fix:, docs:, chore:) |
| Branches | feat/description-issue-number / fix/description-issue-number |
Code quality gates
- Cross-model review required for non-trivial code changes. If Claude writes it, GPT
reviews; if GPT writes it, Claude reviews. See
prompt-registry/cross-model-review.md. - No direct
fsimports in service files — use the storage abstraction layer. - All provider schemas validated — do not guess flag names; verify against versioned docs
or provider
--helpoutput. - pnpm-lock.yaml is generated by pnpm; do not reformat or hand-edit it.
File locations quick-reference
| What | Where |
|---|---|
| API routes | server/src/routes/ |
| Services | server/src/services/ |
| Zod schemas | server/src/schemas/ |
| Storage | server/src/storage/ |
| Server utilities | server/src/utils/ |
| React components | web/src/components/ |
| Zustand stores | web/src/stores/ |
| CLI commands | cli/src/commands/ |
| Shared types | shared/src/ |
| MCP server | mcp/src/ |
| Prompt registry | prompt-registry/ |
| SOPs | docs/SOP-*.md |
| Agent registry | .veritas-kanban/agent-registry.json |
| Agent run logs | .veritas-kanban/logs/ |
| Telemetry events | .veritas-kanban/telemetry/ |
Harness-specific supplements
| Harness | File | Purpose |
|---|---|---|
| Claude | CLAUDE.md |
Claude-specific lessons, cross-model review notes |
| Codex / GPT | AGENTS.md |
This file (canonical) |
| Hermes | AGENTS.md |
This file (Hermes reads AGENTS.md first) |
| OpenClaw | AGENTS.md |
This file |