mirror of
https://github.com/himanshudongre/smriti.git
synced 2026-08-28 05:14:59 +00:00
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:
parent
8388bf8a1f
commit
f4062da76e
7 changed files with 383 additions and 54 deletions
283
AGENTS.md
283
AGENTS.md
|
|
@ -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.*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
30
DECISIONS.md
30
DECISIONS.md
|
|
@ -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.
|
||||
|
|
|
|||
15
README.md
15
README.md
|
|
@ -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
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -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** | |
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue