# Charter Charter is a Jazz-native workspace for spec-driven development. The invariant is intentionally blunt: the spec is the product surface, and Jazz is the coordination truth. Humans edit documents. Charter turns meaningful document changes, spans, comments, prompt changes, and agent lifecycle activity into project events, durable work items, consumer packets, and inspectable agent runs. This repo's `spec/` directory is Charter's own local Markdown projection. The database is the canonical coordination surface for sync, cursors, work queues, consumers, packets, provenance, optional APIs, future UI, and runners. ## Current contents - `spec/` - local filesystem projection of Charter's product spec. - `src/markdown.ts` - Markdown/frontmatter parser. - `src/spec-files.ts` - `spec/**/*.md` scanner and import-plan builder. - `src/db/jazz.ts` - default Charter database adapter; persistent Jazz 2 tables with optional sync-server participation. - `src/db/json.ts` - local JSON projection adapter for tests/fallback (`CHARTER_DB_ADAPTER=json`). - `src/jazz/schema.ts` - Jazz 2 schema for projects, sources, documents, work, workers, leases, packets, and runs. - `src/server.ts` - shared runtime/watch helpers plus optional local HTTP inspection API/status page. - `src/status.ts` - truthful project-state summary over projection drift, database durability, events, work, consumers, packets, and requests. - `src/cli.ts` - CLI with `watch`, `status`, `serve`, `start`, `frontend`, `scan`, `index`, `search`, `changes`, `events`, `work`, `agent`, `queue`, `report`, `requests`, and `sync` commands. ## Target product The desired first-class product command is: ```bash charter watch ``` That starts the local runtime: - watches `spec/**/*.md`. - ingests filesystem edits into the Jazz-backed database. - writes semantic project events and durable work items. - matches registered consumer agents. - emits structured JSONL terminal logs. - runs agents as subordinate processes when invoked. - records packets, reports, failures, stdout, stderr, and provenance. A browser/editor UI is optional future surface. It is not the product center right now. The product center is the runtime, the database, the spec files, and the event stream. ## Commands ```bash npm install npm run watch npm run status npm run scan npm run index npm run search -- agent runtime npm run changes npm run events npm run work npm run agent npm run report -- --request --status done --message "Implemented and checked." npm run requests npm run sync -- --dry-run npm run sync npm run sync -- --jazz-runtime npm run check npm test ``` After build, the binary is `charter`: ```bash npm run build node dist/src/cli.js scan ``` `npm run watch` starts the local controller and emits structured JSONL logs while it ingests selected files. `npm run serve` is an optional local inspection surface, not the distributed runtime boundary. `npm run sync` writes native Jazz 2 rows. `.spec/state/jazz.sqlite` is the durable local Jazz replica; `.spec/state/jazz-runtime.json` is an inspection receipt, not a bootstrap mirror. Set `JAZZ_SERVER_URL` plus backend identity configuration to join distributed sync. `npm run sync -- --jazz-runtime` prints the active Jazz row ids and durability mode. `npm run index` writes a disposable lexical cache. Work, consumer, packet, request, and report commands operate on the configured database rather than a controller-owned HTTP API. `npm run status` is the first answer to “what is happening?” It reports the configured database shape and its actual durability limit, filesystem/database drift, event count, queue state, registered consumers, packet/request state, recent activity, and structural warnings. Runtime-process presence is currently reported as unknown rather than inferred from a state file; Charter does not yet persist a watch-process heartbeat. Local replica, path-mapping, secret-reference, and cache files are ignored by Git. The Jazz project is shared coordination truth; each controller's replica and filesystem mapping remain machine-local. ## Project spec Start with `spec/index.md` and `spec/product-vision.md`. Root README is operational. Product intent lives in database-backed spec documents; Markdown is the local projection in this repo. ## Document identity A Markdown file may declare a stable id: ```yaml --- id: runtime-architecture title: Runtime Architecture kind: architecture --- ``` If `id` is omitted, the importer derives one from the relative file path without `.md`. Example: `spec/runtime/architecture.md` becomes `runtime/architecture`. Pin `id` before renaming a spec file if the rename should preserve identity. ## Watch loop The current default loop is: 1. run `charter watch` or `npm run watch`. 2. edit spec documents in Zed, Obsidian, or another filesystem editor. 3. watch the runtime ingest changes and emit JSONL events. 4. run `charter status` to inspect projection drift, database durability, queue state, registered consumers, packets, requests, and recent activity. 5. create and run a consumer-scoped request packet with `charter agent next --exec ...` when a subordinate runner should execute. The manual CLI loop is still available: 1. edit spec documents through Markdown, a database-native client, or another adapter. 2. run `charter changes` to see what changed against the current database state. 3. run `charter sync` to accept projection edits into database state, append project events, and queue durable work items. 4. run `charter work` or `charter queue` to inspect queued work. 5. run `charter agent` to create a database-backed agent request from queued work items. 6. run `charter agent --exec --agent-command ` when a runner should actually execute. For Codex, use `codex exec -` because Codex reads the prompt from stdin. 7. the agent calls `charter report --request "$CHARTER_REQUEST_ID" --status done|failed|blocked|ignored --message ` before exit. 8. run `charter requests` to inspect the structured report, exit code, stdout, and stderr captured from the run. 9. run `charter events` to inspect the project event feed. Agent context is attached through spec document ids, spans, comments, prompt documents, and packets. There is no separate memory primitive; durable context belongs in one or more spec documents or explicit activity/provenance objects. Completion is written back through Charter, not inferred from prose alone; stdout/stderr capture is the fallback audit trail. ## Running agents Create work from spec changes: ```bash npm run changes npm run sync npm run work ``` Inspect and run one queued work item at a time: ```bash npm run queue npm run queue -- next npm run agent -- next --exec --letta-agent agent-0ddda04a-3d4c-410a-9fb7-d1940281a93f ``` `queue` shows only unclaimed queued work by default; use `npm run work -- --all` for the full ledger. `queue next` and `agent next` select the oldest queued item. Creating an agent request without `--exec` does not claim work; work moves to `running` only when the runner starts. Old planned claims remain explicit: inspect them with `npm run queue -- next --status claimed` or run one with `npm run agent -- next --status claimed --exec ...`. Run queued work with Codex instead: ```bash npm run agent -- next --exec --agent-command 'codex exec -s workspace-write -' ``` The prompt is sent on stdin. Tools that need a file can use `{promptFile}` in the command string, but Codex does not support `--prompt-file`. Codex also needs a writable sandbox for tests/build caches; otherwise Vitest can fail before collecting tests because it cannot write temp/cache files. The Letta convenience runner uses `{promptFile}` internally as `letta --agent --new -p "$(cat {promptFile})"`. Agent completion contract: ```bash npm run report -- --request "$CHARTER_REQUEST_ID" --status done --message "Implemented the requested work and checks pass." npm run report -- --request "$CHARTER_REQUEST_ID" --status failed --message "Failed because ..." npm run report -- --request "$CHARTER_REQUEST_ID" --status blocked --message "Blocked because ..." npm run report -- --request "$CHARTER_REQUEST_ID" --status ignored --message "Ignored because ..." ``` The runner captures stdout, stderr, and exit code automatically. An explicit report is canonical; captured output is the audit trail and fallback report when the agent exits without reporting. Inspect runs: ```bash npm run requests npm run requests -- --request ``` ## Jazz status The executable path uses Jazz 2 alpha and `jazz-napi` by default. Native rows persist across independent CLI processes; tests exercise shutdown, restart, and row-id continuity without `.spec/state/spec-db.json`. With no sync server, status honestly reports `native-jazz-local`. With `JAZZ_SERVER_URL`, app id, and backend identity configured, it uses edge durability and reports `native-jazz-synced`. Distributed identity provisioning and production project-role policies remain deployment work. The schema already represents project membership, sources, workers, capabilities, leases, packets, manifests, and runs so that work does not require another data-model reset. See `spec/runtime-architecture.md` and `spec/jazz-git-boundary.md` for the contract.