Sync docs and regenerate skill pack for the current product surface

Packaging/readiness pass — documentation only, no feature or behavior change.

- REPO_STRUCTURE.md, CONTRIBUTING.md: corrected test counts (156 integration,
  133 unit, 151 CLI), local-first setup flow (make setup-local / dev-local),
  command count, new routes/types/test files.
- README.md: refreshed dogfood metrics, added Project Current State and
  smriti doctor to the surfaces, SQLite to the tech stack.
- cli/README.md: MCP tool count 17 -> 21 (added the four worktree tools),
  documented the smriti worktree commands.
- ARCHITECTURE.md: API table now lists the Project Current State and metrics
  endpoints; new Database modes section (local SQLite / Postgres).
- DECISIONS.md: recorded the local-first SQLite mode and Project Current
  State surface decisions.
- AGENTS.md: regenerated from skill pack template v2.3 (was a stale v1.5
  render); the .claude/ claude-code render was likewise refreshed locally.

.env.example, docs/DEMO_SCRIPT.md, and CLAUDE.md were reviewed and left as-is.
This commit is contained in:
Himanshu Dongre 2026-05-17 00:03:59 +05:30
parent 8388bf8a1f
commit f4062da76e
7 changed files with 383 additions and 54 deletions

283
AGENTS.md
View file

@ -1,5 +1,5 @@
---
smriti_skill_pack_version: 1.5
smriti_skill_pack_version: 2.3
title: Smriti — how to use it well
target: Codex
---
@ -198,15 +198,32 @@ next agent.
- "Branch `X` needs review before merge." or
- "Branch `X` is exploratory / not ready." or
- "Work was done directly on main."
3. **Push your branch.** If your work is on a branch, push it to
3. **Close any worktrees you opened.** If you opened a worktree at the
start of this session via `smriti worktree open`, close it before
ending:
```
smriti worktree close <worktree-id>
```
`smriti worktree close` refuses if you have uncommitted changes —
that's the safety net. Either commit the work, abandon the
intentionally-discarded changes with `--force`, or leave the
worktree active and tell the human in your final message that
you're handing it off intentionally.
Leftover worktrees mislead the next agent: the state brief shows
them as active, suggesting work-in-progress that has actually
stopped.
4. **Push your branch.** If your work is on a branch, push it to
origin so the next agent (and the human) can see it. A
local-only branch is invisible to everyone else.
4. **Clean up local residue.** Do not leave unexplained modified
5. **Clean up local residue.** Do not leave unexplained modified
files, stash entries, or temporary files in the working tree.
If you created a stash during reconciliation, either drop it
(if the stashed content is no longer needed) or note in your
checkpoint that the stash exists and what it contains.
5. **Do not leave the repo on a dead branch.** If your branch has
6. **Do not leave the repo on a dead branch.** If your branch has
been merged or is no longer active, switch back to main before
ending the session so the next agent starts in a clean state.
@ -214,7 +231,7 @@ Say out loud: **"Session complete. Branch pushed, checkpoint
written, working tree clean."** or **"Stopping — checkpointed
findings, branch is [disposition]."**
### 3.5 Backend reachability
### 3.5 Backend reachability and capabilities
The Smriti backend is a shared service started by the human. You
are a client of it. You do not own it.
@ -231,14 +248,25 @@ are a client of it. You do not own it.
tool loop creates environment-variable inheritance issues that
cause silent mock fallback on all LLM-backed endpoints. The
human starts the backend; you use it.
- **Runtime freshness after code changes.** If backend code has
been merged to main since the backend was last started (e.g.,
new API routes, schema changes, config fixes), the backend
must be restarted before agents can rely on the new endpoints.
Check `git log --oneline -5` against the running server's
behavior. If a new endpoint returns 404 or the behavior does
not match the merged code, tell the human: "The backend may
need a restart to pick up recent changes on main."
- **Check capabilities before using advanced features.** After
reading state, before creating claims or using features like
structured tasks, probe the backend:
`curl -s http://localhost:8000/health`
The response includes `git_sha` and a `capabilities` list. If
you need `claims` but the capabilities list does not include it,
the backend is running stale code. Tell the human: "The backend
at localhost:8000 does not support [feature]. Its git_sha is
[sha] but the current repo is at [repo sha]. Please restart
the backend with the same mode you are using (`make dev-local`
or `make dev-postgres`) to pick up recent changes."
For worktree-aware coordination, the capabilities list should include
both `worktrees` and `worktree_binding`.
- **When to check capabilities:** You do NOT need to check on every
session. Check when:
- A Smriti API call returns 404 on a route you expect to exist
- The state brief is missing sections you expect (e.g., no
`## Active work` when you know claims were recently merged)
- You are about to use a feature for the first time in a session
### 3.6 Work claims: declare intent before working
@ -299,6 +327,109 @@ so other agents can see your base state.
Say out loud: **"Claiming: [intent_type] — <scope>."** before
creating the claim.
### 3.6.1 Worktrees: when and how
If multiple agents are working on the same project on the same machine,
each agent should work in its own git worktree. Sharing a working tree
across agents is the single highest-cost failure mode — staged files
from one agent can land in another agent's commit, and the wrong code
ships to main. The chaanbeen-web retros documented exactly this incident.
The reflex: when you start substantial work on a project where another
agent might be active, open a worktree before your first edit.
```
smriti worktree open <project> --agent <your-id>
```
This returns a path. Use that path as your working directory for the
rest of the session. Your edits, your staging index, your commits all
live in that worktree. Other agents have their own worktrees; their
filesystem state is invisible to you and yours to them.
When you create your work claim, bind it to the worktree:
```
smriti claim create <project> --agent <your-id> \
--scope "..." --intent-type implement \
--task-id <task-id> --worktree <worktree-id>
```
MCP tools call this field `worktree_id`; the CLI flag is `--worktree`.
The state brief now shows a worktree info line under your claim:
which path, which branch, how many dirty files, ahead/behind vs main,
last commit. Other agents seeing your claim know exactly what state
your tree is in without asking.
When your work is done and merged, close the worktree. This is also
part of session-end hygiene in Section 3.4 — Clean finish:
```
smriti worktree close <worktree-id>
```
This refuses if you have uncommitted changes (correct default — stop
and decide before destroying work). Pass `--force` only after you've
confirmed the dirty changes are intentionally being discarded.
When NOT to open a worktree:
- Solo work on a project with no other active agents.
- Quick read-only investigations that won't produce commits.
- Documentation-only work that's clearly disjoint from anyone else's
track (e.g. you're writing in `docs/` while another agent is in
`backend/`). Worktrees are cheap but not zero cost; the discipline
is "open one when there's actual filesystem contention risk,"
not "open one for every session."
Say out loud: **"Opening a worktree for this session."** before the
first worktree open. **"Binding my claim to worktree <id>."** when
claiming. **"Closing the worktree."** when done.
The state brief now shows you which files other agents are actively
editing, not just how many. Each active claim's worktree drift line
includes the first 3 dirty paths inline:
```
· branch: ... · 3 dirty (cli/main.py, backend/app/main.py, +1 more) · ...
```
This is your file-level coordination signal. Before editing a file in
your worktree, scan the active-claim drift lines for that path. If
another agent already has it dirty, hold off or pick a different file.
The signal is best-effort — it shows the first 3 dirty paths only and
the cache is 60 seconds — but it catches the common case where two
agents drift into the same file by accident.
If your shell tool resets the working directory between commands (some
agent harnesses do this — every Bash call starts in the original cwd
even after `cd <worktree-path>`), use absolute paths to the worktree
throughout. Example:
```
WT=/Users/.../.smriti/worktrees/<space>/<agent-slug>
cat $WT/some/file.py
edit $WT/some/file.py
```
The skill pack used to say "use the worktree path as your cwd" — that
works for persistent shells, but absolute-path discipline works
everywhere. Capture the worktree path from `smriti worktree open` once
and reuse it.
The default branch name when you `smriti worktree open` is
`smriti/<agent>/<short-uuid>`. That's fine for the system but ugly for
PR titles. Pass `--branch <name>` to use a custom branch name instead:
```
smriti worktree open <space> --agent <id> --branch v3-feature-name
```
Use this when the worktree maps cleanly to a single feature/PR. Stick
with the default when the worktree is short-lived or when several
related branches will live in it.
### 3.7 Check freshness before checkpointing
If you have been working for more than a few minutes, check whether
@ -329,6 +460,80 @@ untangle.
Say out loud: **"Checking freshness before checkpointing."**
### 3.8 Autonomous work selection from the task list
Tasks in the state brief may carry structured annotations that help
you pick complementary work without waiting for the human to route you.
Each task can have:
- **`[intent]`** — one of `implement`, `review`, `investigate`, `docs`,
`test`. This tells you the kind of work the task requires.
- **`→ blocked by: <label>`** — this task depends on another task being
done first.
- **`(done)`** — this task is already completed.
**How to self-select work:**
1. Read the `## In progress` section. Note which tasks have intents,
IDs, and which are blocked.
2. Read the `## Active work` section. Note existing claims — especially
their `task:` references if present.
3. **Pick a task that is not already referenced by any active claim.**
If tasks have IDs (`id: arch-docs`), check whether any claim shows
`(task: arch-docs)`. If so, that task is taken — pick a different
one. If tasks have no IDs, fall back to scope matching.
4. **Prefer complementary intents.** If someone is `implement`ing,
look for `test`, `docs`, or `review` tasks. Same-intent is fine
if the tasks are clearly different (two distinct `[docs]` tasks
with different IDs).
5. **Skip blocked tasks.** If a task says `→ blocked by: X`, check
whether task X is done. If X is still open or claimed, skip the
blocked task — pick something unblocked instead.
6. **Skip done tasks.** Tasks marked `(done)` need no work.
7. **If no complementary unblocked task exists:** tell the human.
**Claim with task ID when available.** When you create a claim for a
task that has an ID, reference it:
`smriti claim create <project> --agent <your-agent> --scope "..." --task-id arch-docs --intent-type docs`
This makes your claim precisely traceable to a task, not just loosely
matched by scope text.
**Recheck after claiming.** If another agent might be starting at the
same time (e.g., you were both launched together), re-read the state
briefly after creating your claim:
`smriti state <project> --compact`
Check `## Active work` for duplicate `task:` references. If another
agent claimed the same task ID, abandon your claim and pick a
different task. This catches near-simultaneous collisions within
seconds.
**When tasks have no IDs:** fall back to the scope-comparison logic
from Section 3.6. Compare each task's text against active claim
scopes and pick work that does not overlap. This is the same behavior
as before — task IDs just make collision detection precise instead
of fuzzy.
**When writing tasks with IDs:** use short, stable slugs derived from
the task content: `impl-freshness`, `test-e2e`, `docs-arch`. If a
task persists across nearby checkpoints, reuse the same ID when
practical — this makes cross-checkpoint task tracking easier. But do
not block work when old checkpoints or legacy tasks have no IDs.
**When writing checkpoints with tasks:** include intent hints on
tasks you create. When you checkpoint your work, the tasks in your
freeform markdown should indicate what kind of work each one requires.
Write naturally — the extractor will classify them:
```
## Tasks
- Implement the freshness endpoint (implement)
- Write integration tests for freshness (test, blocked by freshness endpoint)
- Update cli/README freshness walkthrough (docs, blocked by freshness endpoint)
```
Say out loud: **"Selecting complementary work from the task list."**
when you self-select a task based on intent hints.
---
## 4. When to checkpoint
@ -373,6 +578,45 @@ Always tag `author_agent` with a stable identifier for your agent
agents know who wrote what on the shared timeline. Inconsistent or
missing `author_agent` makes divergence unattributable.
### 4.1 Checkpoint notes: annotating without checkpointing
Sometimes you need to add context to an existing checkpoint without
creating a new one. Checkpoint notes are additive annotations —
founder commentary, milestone markers, or noise labels — that attach
to a checkpoint without modifying its immutable fields.
```
smriti checkpoint note <id> --text "<note text>" --kind note
```
**Three kinds:**
- `note` (default): General commentary. "This decision held up well
during implementation."
- `milestone`: Marks a checkpoint as a significant project moment.
"This was the turning point — everything after built on this."
- `noise`: Marks a checkpoint as low-signal or superseded. "Extractor
was degraded when this was written; decisions are unreliable."
**When to use notes instead of a new checkpoint:**
- You want to annotate a past checkpoint after the fact — adding
hindsight without rewriting history.
- The human wants to mark a checkpoint as a milestone or as noise
for timeline legibility.
- You are reviewing another agent's checkpoint and want to leave
commentary without creating a full review checkpoint.
**When NOT to use notes:**
- Do not use notes to record new decisions. That is a checkpoint.
- Do not use notes as a running commentary on every checkpoint in
the lineage. Notes are sparse annotations, not a comment thread.
Notes appear in the LineagePage timeline as indicators (★ for
milestones, ◌ for noise, ● for plain notes) and in checkpoint detail
views. They are visible to all agents reading the state.
---
## 5. When NOT to checkpoint
@ -630,6 +874,12 @@ Section 5.
Duplicating completed work wastes a full session and creates noise
in the timeline.
- **Do not share a working tree between agents on the same project on
the same machine.** Open a worktree per agent. The chaanbeen
retrospectives documented one cross-agent commit pollution incident
that took ~1 hour to recover and degraded prod for ~6 endpoints —
this is the failure worktrees were built to prevent.
- **Do not use `smriti_install_skill` to overwrite an in-project
skill pack that you did not write.** If the project already has
a skill pack of an older version, the install tool will tell you.
@ -653,6 +903,11 @@ Use them literally.
| reconcile state against repo | "Checking whether the flagged tasks are already reflected in the repo before starting." |
| verify repo hygiene at start | "Repo is clean and synced against origin." or "Found local residue — classifying before proceeding." |
| declare a work claim | "Claiming: [intent_type] — <scope>." |
| open a worktree | "Opening a worktree for this session." |
| bind a claim to a worktree | "Binding my claim to worktree <id>." |
| close a worktree | "Closing the worktree." |
| add a note to a checkpoint | "Adding a [kind] note to checkpoint X." |
| self-select complementary work | "Selecting complementary work from the task list." |
| check freshness before checkpoint | "Checking freshness before checkpointing." |
| finish a session | "Session complete. Branch pushed, checkpoint written, working tree clean." |
| surface drift to the human | "I'm seeing scope divergence between the state brief and my work. Stopping to reconcile before continuing." |
@ -709,7 +964,7 @@ tell you. Do not guess.
---
*Smriti skill pack version cli-1.5 — this file is
*Smriti skill pack version cli-2.2 — this file is
authoritative for agent behaviour on this project. If you catch it
contradicting itself or your observed behaviour of the tools, tell
the human; the skill pack is versioned and meant to be updated.*

View file

@ -306,7 +306,7 @@ pivot, not an incremental change.
| `/api/v1` | Legacy | Transcript paste ingestion → session/artifact pipeline. Not part of current workflow. |
| `/api/v2` | Partial | Space CRUD, checkpoint read by ID, checkpoint list by space. `CommitResponse` includes `assumptions` and `artifacts` so programmatic clients (CLI, agents) can read full checkpoints via this surface. |
| `/api/v4` | Current | Chat sessions, message sending, provider management. The primary chat API. Also the canonical checkpoint write path (`POST /chat/commit`) because it accepts the full schema including `assumptions` and `artifacts`. Multi-branch continuation brief served from `GET /chat/spaces/{id}/state` — the agent-facing default; `GET /chat/spaces/{id}/head` remains as the main-only legacy endpoint. |
| `/api/v5` | Current | Checkpoint drafting, review, fork, compare, lineage. Isolated from chat API by design. |
| `/api/v5` | Current | Checkpoint drafting, review, fork, compare, lineage, project metrics, and the Project Current State aggregate (`GET /current/spaces/{id}`). Isolated from chat API by design. |
V1 remains registered for compatibility but is not used by the frontend or CLI.
@ -316,6 +316,26 @@ path. This allows different latency budgets and error handling strategies for ea
---
## Database modes
Smriti runs against two storage backends, selected by `SMRITI_DB_MODE`:
- **`local`** (the default when unconfigured) — a file-backed SQLite database at
`~/.smriti/smriti.db`, overridable via `SMRITI_LOCAL_DB_PATH`. No Docker, no
database server. The schema is created on first use via `create_all`; Alembic
is not used in local mode. This is the low-friction path for a solo builder.
- **`postgres`** — the canonical shared/team backend. An explicitly-set Postgres
`DATABASE_URL` resolves to Postgres mode even when `SMRITI_DB_MODE` is unset,
so existing deployments are unaffected. Alembic owns the Postgres schema.
The ORM models are dialect-portable: JSON columns render as `JSONB` on
PostgreSQL and as generic `JSON` on SQLite (`backend/app/db/types.py`), so the
same models and the same `create_all` work against either backend. Postgres
remains the stronger mode for real multi-writer concurrency; local mode targets
single-user solo/dev use.
---
## Smriti as an agent-facing backend
The REST API is the canonical interface to Smriti. The chat UI, the CLI, the

View file

@ -7,7 +7,8 @@ environment running, how to run tests, and how to propose changes.
## Dev environment
**Prerequisites:** Python 3.11+, Node 18+, Docker (for Postgres).
**Prerequisites:** Python 3.11+, Node 18+. Docker is optional — needed only
for Postgres (shared/team) mode.
```bash
git clone https://github.com/himanshudongre/smriti
@ -17,18 +18,20 @@ cp .env.example .env
# Edit .env to add your API keys (OpenAI, Anthropic, or both).
# Leave keys commented out to use mock mode (no real LLM calls).
docker compose up -d postgres # start the database
make setup # backend venv + deps + migrations + CLI + frontend
make setup-local # backend venv + deps + CLI + frontend (no Docker)
# Start backend (terminal 1)
make dev
make dev-local
# Start frontend (terminal 2)
make dev-frontend
```
`make setup` installs the backend, the CLI (`smriti` + `smriti-mcp`), and the
frontend. The CLI is installed into the backend venv at `backend/.venv/bin/`.
`make setup-local` runs Smriti in local-first SQLite mode — no Docker, no
Postgres; state lives in `~/.smriti/smriti.db`. It installs the backend, the
CLI (`smriti` + `smriti-mcp`), and the frontend. For Postgres-backed
shared/team mode, use `make setup-postgres` + `make dev-postgres` instead. The
CLI is installed into the backend venv at `backend/.venv/bin/`.
Activate the venv to use it from your shell:
```bash
@ -67,8 +70,8 @@ fixtures — no running backend required.
| Changed area | Run |
|---|---|
| `backend/app/` | `make test` (122 integration + 125 unit tests) |
| `cli/smriti_cli/` | `cd cli && pytest` (122 tests) |
| `backend/app/` | `make test` (156 integration + 133 unit tests) |
| `cli/smriti_cli/` | `cd cli && pytest` (151 tests) |
| `cli/smriti_cli/skill_pack/template.md` | `cd cli && pytest tests/test_skill_pack.py` — content-integrity tests catch dropped sections |
| `frontend/src/` | `cd frontend && npx tsc --noEmit` |
| Both backend + CLI | Both suites — they share no test infrastructure but both call the same backend API |
@ -132,7 +135,7 @@ EXPECTED_OUTCOMES at minimum.
Smriti has three agent-facing surfaces beyond the chat UI:
- **CLI** (`cli/smriti_cli/main.py`) — `smriti` command, 8 subcommand groups
- **CLI** (`cli/smriti_cli/main.py`) — `smriti` command, 14 commands
- **MCP server** (`cli/smriti_cli/mcp_server.py`) — `smriti-mcp` command, 21 tools
- **Skill pack** (`cli/smriti_cli/skill_pack/`) — versioned instruction files for Claude Code and Codex

View file

@ -594,6 +594,36 @@ use while preserving explicit override via `smriti space set-project-root`.
---
### Why an optional local-first SQLite mode, not a Postgres replacement
Operating a PostgreSQL server was the single biggest first-run barrier for a
solo builder evaluating Smriti: install Docker, start a container, run
migrations, keep the database process alive. Smriti now defaults to a
file-backed SQLite database at `~/.smriti/smriti.db` when unconfigured, so the
solo path needs no Docker and no database server.
It is an *optional mode*, not a replacement. Postgres remains the canonical
shared/team backend — the stronger choice for real multi-writer concurrency —
and an explicitly-set Postgres `DATABASE_URL` preserves Postgres behavior with
no change for existing deployments. Local mode uses `create_all` rather than
Alembic: a fresh single-user database has no migration history to honor, and
porting the entire Alembic chain to SQLite would be disproportionate to the
goal. The ORM models were made dialect-portable instead, so one schema
definition serves both backends.
### Why a Project Current State surface
`smriti state` is a continuation brief — what the next agent needs to resume
work. It is not a legibility surface for a human asking "where is this project
right now?" `smriti current` (and `GET /api/v5/current/spaces/{id}`) packages
that answer: current direction, counts, attention signals, active work, recent
milestones, open tasks grouped by intent, and recent activity — computed on
demand from existing data, with no new schema. It is deliberately a read-only
aggregate, not a new primitive: it surfaces what checkpoints, claims, and notes
already record, rather than introducing a new kind of state.
---
## Open questions and deferred decisions
- **Multi-user Spaces** — deferred. No auth, no user model.

View file

@ -16,10 +16,10 @@ Smriti replaces that with a structured reasoning-state layer. Agents read the cu
The entire coordination substrate was developed with Claude Code and Codex working in parallel on the same codebase, coordinating through Smriti's own state. Current project metrics (`smriti metrics smriti-dev`):
- **56 checkpoints** across **2 agents** (Claude Code: 35, Codex: 21)
- **30 cross-agent continuations** — checkpoints where a different agent picked up where the previous one left off
- **37 work claims** with **100% completion** — every declared intent was finished, none abandoned
- **2 milestones** marking proven coordination proofs
- **87 checkpoints** across **2 agents** (Claude Code: 51, Codex: 36)
- **47 cross-agent continuations** — checkpoints where a different agent picked up where the previous one left off
- **53 work claims** at **98% completion** — nearly every declared intent finished
- **7 milestones** marking proven coordination proofs
The strongest proof: two agents started near-simultaneously, read the same task surface (4 tasks with stable IDs and intent hints), and independently picked different complementary tasks — one chose `[test]`, the other chose `[implement]` — without any human routing. No orchestrator. No task queue. Just structured metadata on the shared state.
@ -54,10 +54,11 @@ One project, one Smriti Space, multiple agents. Each reads the state, declares i
- **Freshness checks** (`--since`) — agents detect whether the state has moved since their base before checkpointing.
- **Branch disposition** — branches are explicitly marked `integrated`, `abandoned`, or `active` so the state brief stays clean.
- **Checkpoint notes** — additive annotations (note, milestone, noise) on existing checkpoints without modifying the immutable reasoning state.
- **Backend capabilities** (`/health`) — the backend advertises its feature surface so agents can detect stale backends.
- **Backend capabilities** (`/health`) — the backend advertises its feature surface so agents can detect stale backends. `smriti doctor` diagnoses backend reachability and runtime/code mismatches.
- **Compact mode** (`--compact`) — artifact content omitted for token efficiency; labels and recovery instructions preserved.
- **Project metrics** (`smriti metrics <space>`) — coordination, state quality, and branch lifecycle KPIs computed on demand from existing data.
- **Worktrees** (`smriti worktree open/list/show/close`) — first-class git worktree primitive so multiple agents can work on the same project without sharing one checkout. Each agent gets its own working tree and staging index, eliminating the cross-agent commit pollution failure mode that motivated the feature. Claims can be bound to a worktree (`smriti claim create --worktree <id>`); the state brief surfaces per-claim working-tree drift (branch, dirty count, ahead/behind vs origin/main, last commit) so agents can see what other agents are editing without asking. Skill pack v2.0 teaches the reflex.
- **Project Current State** (`smriti current <space>`) — a compact, packaged snapshot of where a project is right now: current direction, counts, attention signals, active work, recent milestones, open tasks by intent, and recent activity. Founder- and agent-facing; also rendered as a panel in the chat UI.
- **Worktrees** (`smriti worktree open/list/show/close`) — first-class git worktree primitive so multiple agents can work on the same project without sharing one checkout. Each agent gets its own working tree and staging index, eliminating the cross-agent commit pollution failure mode that motivated the feature. Claims can be bound to a worktree (`smriti claim create --worktree <id>`); the state brief surfaces per-claim working-tree drift (branch, dirty count, ahead/behind vs origin/main, last commit) so agents can see what other agents are editing without asking. The skill pack teaches the reflex.
---
@ -287,7 +288,7 @@ Or use mock mode (no API keys needed) for trying the product without real LLM ca
## Tech stack
FastAPI · SQLAlchemy · PostgreSQL · React + TypeScript + Vite
FastAPI · SQLAlchemy · PostgreSQL / SQLite · React + TypeScript + Vite
---

View file

@ -6,7 +6,7 @@ smriti/
├── README.md Product overview, core concepts, setup,
│ coding-agent quick start
├── ARCHITECTURE.md System model, isolation mechanism, API versioning,
│ multi-branch state, skill pack surface
│ multi-branch state, local-first DB modes, skill pack surface
├── DECISIONS.md Key architectural and product decisions
├── CONTRIBUTING.md Development setup and contribution guide
├── AGENTS.md Smriti skill pack for Codex (generated, committed)
@ -20,15 +20,17 @@ smriti/
│ ├── app/
│ │ ├── main.py FastAPI app factory, CORS, router registration,
│ │ │ startup provider validation
│ │ ├── config.py Pydantic settings (DATABASE_URL, DEBUG)
│ │ ├── config.py Pydantic settings; local SQLite / Postgres db-mode resolution
│ │ ├── config_loader.py Provider config loader (dotenv + providers.yaml
│ │ │ + env vars), reset_config() for dev reloads
│ │ ├── schemas/
│ │ │ └── __init__.py Pydantic request/response schemas
│ │ ├── db/
│ │ │ ├── database.py SQLAlchemy engine and session factory
│ │ │ └── models.py ORM models: RepoModel, CommitModel, ChatSession,
│ │ │ TurnEvent, WorkClaim, WorkTree
│ │ │ ├── database.py SQLAlchemy engine + session factory; SQLite/Postgres
│ │ │ │ engine setup, local first-run bootstrap
│ │ │ ├── models.py ORM models: RepoModel, CommitModel, ChatSession,
│ │ │ │ TurnEvent, WorkClaim, WorkTree
│ │ │ └── types.py Portable column types (JSONB↔JSON, vector↔JSON)
│ │ ├── domain/
│ │ │ └── enums.py SessionStatus, TargetTool, etc.
│ │ ├── api/
@ -36,6 +38,8 @@ smriti/
│ │ │ ├── chat.py V4: sessions, send_message, commit, head,
│ │ │ │ multi-branch state (/state), provider status
│ │ │ ├── checkpoint.py V5: draft, review, extract
│ │ │ ├── current.py V5: Project Current State aggregate surface
│ │ │ ├── metrics.py V5: project coordination / quality metrics
│ │ │ ├── lineage.py V5: fork, branch tree, checkpoint compare,
│ │ │ │ reachable checkpoints
│ │ │ ├── claims.py V5: work claims (create, update, list)
@ -64,16 +68,18 @@ smriti/
│ │ └── providers.yaml Your keys (gitignored, not committed)
│ ├── alembic/ Database migrations (15 versions)
│ ├── tests/
│ │ ├── integration/ API integration tests (140 tests)
│ │ ├── integration/ API integration tests (156 tests)
│ │ │ ├── test_api_v4_chat.py
│ │ │ ├── test_api_v5_lineage.py
│ │ │ ├── test_multi_branch_state.py
│ │ │ ├── test_current_state.py
│ │ │ ├── test_claims.py
│ │ │ ├── test_claim_worktree_binding.py
│ │ │ ├── test_project_root_migration.py
│ │ │ ├── test_repos_project_root.py
│ │ │ ├── test_worktrees.py
│ │ │ ├── test_checkpoint_extract.py
│ │ │ ├── test_local_sqlite_smoke.py
│ │ │ └── test_delete_endpoints.py
│ │ └── unit/ Unit tests (133 tests)
│ │ ├── test_config_loader.py
@ -108,19 +114,21 @@ smriti/
│ ├── pyproject.toml Installable as `pip install -e ./cli`
│ │ → `smriti` + `smriti-mcp` on PATH
│ ├── smriti_cli/
│ │ ├── main.py argparse dispatcher: init, space, state,
│ │ │ checkpoint, fork, restore, compare,
│ │ │ branch, claim, worktree, skills
│ │ ├── main.py argparse dispatcher: init, doctor, space, state,
│ │ │ current, checkpoint, fork, restore, compare,
│ │ │ branch, claim, worktree, skills, metrics
│ │ ├── mcp_server.py FastMCP server (21 tools, stdio transport)
│ │ ├── client.py SmritiClient HTTP wrapper (includes claims/worktrees)
│ │ ├── formatters.py Continuation-oriented markdown renderers
│ │ │ (multi-branch, active claims, divergence)
│ │ └── skill_pack/ Agent skill pack source and renderer
│ │ ├── template.md Single source of truth (v2.2, 15 sections)
│ │ ├── template.md Single source of truth (v2.3, 15 sections)
│ │ ├── renderer.py Pure-function render + versioned install
│ │ └── targets.py Target configs (claude-code, codex)
│ └── tests/ CLI + MCP tests (141 tests)
│ └── tests/ CLI + MCP tests (151 tests)
│ ├── test_branch_close.py
│ ├── test_current_cli.py
│ ├── test_doctor_cli.py
│ ├── test_init.py
│ ├── test_mcp_server.py
│ ├── test_skill_pack.py
@ -131,7 +139,8 @@ smriti/
│ └── test_worktree_mcp.py
├── docs/
│ └── API.md V2, V4, and V5 endpoint reference
│ ├── API.md V2, V4, and V5 endpoint reference
│ └── DEMO_SCRIPT.md Demo recording script
└── demos/
└── branching-reasoning-demo/ Complete demo scenario with runbook,
@ -147,32 +156,34 @@ smriti/
| `/api/v1` | `sessions.py` | Legacy | Transcript paste ingestion |
| `/api/v2` | `repos.py`, `commits.py` | Current | Space CRUD, checkpoint read/list. `CommitResponse` includes `assumptions` and `artifacts`. |
| `/api/v4` | `chat.py` | Current | Chat sessions, send_message, commit, head, multi-branch state (`/state` with active branches, active claims, and divergence signal). Provider status. |
| `/api/v5` | `checkpoint.py`, `lineage.py`, `claims.py`, `worktrees.py` | Current | Checkpoint draft/review/extract, fork, lineage tree, compare, work claims with optional worktree binding, git worktrees. |
| `/api/v5` | `checkpoint.py`, `current.py`, `metrics.py`, `lineage.py`, `claims.py`, `worktrees.py` | Current | Checkpoint draft/review/extract, Project Current State, project metrics, fork, lineage tree, compare, work claims with optional worktree binding, git worktrees. |
---
## Make targets
```
make setup Install all deps (backend + CLI + frontend) + run migrations
make dev Run backend dev server (port 8000)
make setup-local Solo setup: venv + deps + CLI + frontend (local SQLite, no Docker)
make setup-postgres Shared/team setup: venv + deps + Docker Postgres + migrations
make dev-local Run backend in local-first SQLite mode (port 8000)
make dev-postgres Run backend in Postgres mode (port 8000)
make dev-frontend Run frontend dev server (port 5173)
make up Start all services via Docker Compose
make down Stop all services
make test Run all backend tests
make lint Lint backend code (ruff)
make format Format backend code (ruff)
make migrate Run pending Alembic migrations
make migrate Run pending Alembic migrations (Postgres mode)
make migration Create a new migration (usage: make migration msg="...")
```
---
## Test counts (as of V5a worktree polish)
## Test counts (as of local-first SQLite mode)
| Suite | Count | Location |
|---|---|---|
| Backend integration | 140 | `backend/tests/integration/` |
| Backend integration | 156 | `backend/tests/integration/` |
| Backend unit | 133 | `backend/tests/unit/` |
| CLI + MCP | 141 | `cli/tests/` |
| **Total** | **414** | |
| CLI + MCP | 151 | `cli/tests/` |
| **Total** | **440** | |

View file

@ -49,7 +49,7 @@ Run Smriti as a local MCP server so agents inside Claude Code, Cursor, or Windsu
Restart the host and the `smriti_*` tools appear in the tool picker.
**Available tools (17):**
**Available tools (21):**
| Tool | Purpose |
|---|---|
@ -69,6 +69,10 @@ Restart the host and the `smriti_*` tools appear in the tool picker.
| `smriti_close_branch` | Mark a branch as integrated, abandoned, or active |
| `smriti_claim` | Declare a work claim before starting work (pre-work intent visibility) |
| `smriti_claim_done` | Mark a work claim as done or abandoned |
| `smriti_worktree_open` | Open a git worktree for an agent in a space |
| `smriti_worktree_list` | List worktrees in a space, with cached git drift |
| `smriti_worktree_show` | Show one worktree by id or short-id prefix |
| `smriti_worktree_close` | Close a worktree and remove it from disk |
| `smriti_install_skill` | Return the Smriti agent skill pack for a host (`claude-code` / `codex`) |
**Example.** In a Claude Code session with Smriti MCP connected, ask *"show me the current state of my-project"*. The agent calls `smriti_state(space="my-project")`, the MCP server hits the backend, pipes the result through the same `format_state_brief` formatter the CLI uses, and returns the continuation brief you'd otherwise get from `smriti state my-project` at the terminal — directly inside the chat context.
@ -87,7 +91,7 @@ Restart the host and the `smriti_*` tools appear in the tool picker.
mcp dev smriti_cli.mcp_server:mcp
```
Opens a browser-based tool explorer connected over stdio. Click through `tools/list` (expect 17 entries, all prefixed `smriti_`) and try each tool interactively.
Opens a browser-based tool explorer connected over stdio. Click through `tools/list` (expect 21 entries, all prefixed `smriti_`) and try each tool interactively.
## Installing the Smriti skill pack
@ -162,6 +166,11 @@ smriti fork <checkpoint-id> [--branch <name>] # new session from chec
smriti restore <checkpoint-id> # brief of a specific checkpoint
smriti compare <checkpoint-a> <checkpoint-b> # structured diff
smriti worktree open <space> --agent <name> # open a git worktree for an agent
smriti worktree list <space> # list worktrees with git drift
smriti worktree show <id-or-prefix> # show one worktree
smriti worktree close <id-or-prefix> # close and remove a worktree
smriti checkpoint create <space> # reads JSON from stdin
smriti checkpoint create <space> --from-json <path> # from JSON file
smriti checkpoint create <space> --extract # reads markdown, LLM extracts schema fields
@ -265,7 +274,7 @@ Surfaces possible contradictions, hidden assumptions, already-resolved open ques
A second agent (different process, different model family, different session) starts fresh. It runs `smriti state my-project` — or calls `smriti_state` from inside its MCP host — and receives the same brief the first agent just wrote. There is no prose handoff, no pasting markdown between windows, no re-explaining. The agent picks up where the previous one left off and continues working.
This is the core loop. Rounds 3 through 5 of dogfood testing exercised exactly this pattern across Claude Code ↔ Codex handoffs, same-family Codex ↔ Codex handoffs, and a round 5 end-to-end test that drove all 17 MCP tools from a host-less Python client. The shape holds.
This is the core loop. Rounds 3 through 5 of dogfood testing exercised exactly this pattern across Claude Code ↔ Codex handoffs, same-family Codex ↔ Codex handoffs, and a round 5 end-to-end test that drove every MCP tool then defined from a host-less Python client. The shape holds.
## Branching when you want to explore an alternative