Commit graph

49 commits

Author SHA1 Message Date
Himanshu Dongre
3161c1a3c1 Close the skill-pack and API docs staleness before the website sprint
Skill pack (template.md -> AGENTS.md, .claude/skills/smriti/SKILL.md):
- §3.2 Repo reconciliation: lead with `## Repo state`'s automated drift
  signals; keep the manual git log checks as the documented fallback
  for checkpoints without recorded git state.
- §3.5 Backend reachability: lead with `smriti doctor` as the
  structured health check; keep `curl /health` as the raw fallback.
- Bump skill pack version 2.4 -> 2.5; re-render AGENTS.md (the
  .claude/skills/smriti/SKILL.md install is local-only and untracked).
- test_skill_pack: bump the expected version; add four single-line
  required phrases proving the new content shipped (`Repo state`,
  `smriti doctor`, "ahead of the last checkpoint", "checkpoint taken
  on a different branch").

docs/API.md:
- POST /api/v4/chat/commit: add `repo_state` to the request body
  example and a paragraph explaining its purpose (drift detection),
  persistence (`context_blob`), and read-back path (V4 state endpoint).
- DELETE /api/v2/repos/{repo_id}: add the missing section with the
  `force` query param, 204/404/409 responses, and the structured
  detail shape for the 409 refusal.

CLI suite: 253 passed. AGENTS.md and SKILL.md verified byte-identical
to fresh render(target) output.
2026-05-20 20:40:58 +05:30
Himanshu Dongre
3b6ef000dc Detect repo drift against the last checkpoint
The repo-state section added by the previous commit shows working-tree
and git-upstream drift. It does not answer the question Smriti's trust
story actually needs: has the repo moved since the last checkpoint?

Record git provenance on checkpoints and compare against it. The CLI
captures the git HEAD and branch when it creates a checkpoint; the V4
commit endpoint stores that under the commit's context_blob and returns
it on read. `smriti state` then compares the working repo against the
latest checkpoint's recorded HEAD/branch and surfaces:
  - repo unchanged since the last checkpoint
  - repo is N commit(s) ahead — recorded state may be stale
  - repo history has diverged from the last checkpoint
  - the last checkpoint was taken on a different branch

All local and read-only: no fetch, no reconciliation. Checkpoints made
before this feature (or by the MCP server) record no git state and are
simply left uncompared.
2026-05-19 23:22:22 +05:30
Himanshu Dongre
14e99a4616 Show local repo drift in state output 2026-05-19 22:43:46 +05:30
Himanshu Dongre
e303f7a547 Require force to delete a non-empty space at the API layer
The deletion-safety thread guarded the CLI (`--force`) and the MCP tool
(`confirm_space`), but `DELETE /api/v2/repos/{id}` itself still cascade-
deleted a fully populated space — every checkpoint, session, and turn —
with no server-side check. Any client that bypassed the CLI/MCP guards
(a direct API call, the web UI, a future client) reopened the incident
path.

Gate the route: `delete_repo` now counts the space's checkpoints and
refuses with 409 plus a structured detail (`message`, `checkpoint_count`,
`requires_force`) unless `?force=true` is passed — the same shape as the
`checkpoint delete` dependent-guard. An empty space still deletes with no
force.

Wire the existing clients through the new signal so their behavior is
unchanged: the CLI passes `force=args.force` (its own `--force` gate),
the MCP tool passes `force=true` after its `confirm_space` gate, and
quickstart passes `force=true` to tear down its own demo space.
2026-05-19 01:36:58 +05:30
Himanshu Dongre
727990d899 Require MCP confirmation for space deletion 2026-05-19 01:12:49 +05:30
Himanshu Dongre
4a1976a905 Require --force to delete a non-empty or attached space
A destructive-operations incident: `smriti space delete <space> -y`
cascade-deleted a fully populated space. `-y` skipped the only gate (the
confirmation prompt), and `cmd_space_delete` never checked how much the
space held — so one flag irreversibly deleted the space and every
checkpoint, session, and turn under it.

Gate destructive deletes in `cmd_space_delete`: a space that holds
checkpoints, or that the current repo is attached to (.smriti.json), now
requires an explicit `--force` — `-y` alone is refused, with a message
naming the reason and the flag. `--force` and `-y` stay orthogonal, the
same shape as `checkpoint delete --cascade`. Empty, unattached spaces keep
the existing `-y` convenience. CLI-side only; no backend change.
2026-05-19 00:51:33 +05:30
Himanshu Dongre
0c8f6922f4 Update skill pack for attached repo workflow 2026-05-19 00:07:52 +05:30
Himanshu Dongre
b3734f3dc3 Add durable project attachment so repos remember their Smriti space
Smriti was repo-local wiring: every command needed an explicit <space>, and
the SessionStart hook hard-coded the space name, so working across projects
and sessions meant re-stating the space constantly.

Add a `.smriti.json` attachment file at the repo root binding the repo to a
space. The CLI resolves `<space>` from it — walking up from the working
directory the way git finds `.git` — so `<space>` is now optional on the
everyday commands (state, current, metrics, claim, checkpoint, branch,
worktree). `smriti attach <space>` is the explicit binding verb (`smriti
attach` with no argument shows the current binding); `smriti init` also
writes the attachment. The generated SessionStart hook is now space-agnostic
— `smriti state --compact` resolves from the attachment, so the hook is
identical for every project and survives re-attaching.

`space delete` still requires an explicit space. No backend changes —
attach/init reuse the existing set_project_root endpoint.
2026-05-18 00:52:37 +05:30
Himanshu Dongre
ab8d6f6b6f Clarify claim completion metrics 2026-05-18 00:07:42 +05:30
Himanshu Dongre
eb60d03f4b Render list-valued blocked_by consistently in state --compact
`smriti current` already normalizes a list-valued blocked_by to a clean
comma-separated string via the backend CurrentTask validator, but `smriti
state` rendered it through an f-string and leaked the raw Python list repr
(['a', 'b']) into the state brief — the surface agents read at session start.

Add a `_coerce_blocked_by` helper in the CLI formatters mirroring that
validator, and apply it in `_normalize_task_item` so every `smriti state`
task line renders blocked_by the same way `smriti current` does. Adds
regression tests.
2026-05-18 00:02:07 +05:30
Himanshu Dongre
c43310caa1 Make doctor runtime checks external-project aware 2026-05-17 19:16:56 +05:30
Himanshu Dongre
76f6f4c2c7 Polish external validation output and docs 2026-05-17 12:15:14 +05:30
Himanshu Dongre
2ac2abcfae Handle SQLite checkpoint timestamps in CLI formatters 2026-05-17 11:22:30 +05:30
Himanshu Dongre
98edf48a5d Merge doctor-activation and init portability into the activation sprint 2026-05-17 10:50:01 +05:30
Himanshu Dongre
1afca2bda2 Add smriti quickstart and a shipped demo space
A fresh install opens to an empty space, so Smriti's value — which only
shows once reasoning has accumulated — is invisible on day one. `smriti
quickstart` seeds one small, finished project (a rate-limiting feature
built by two agents, with a branch explored and dropped) and prints a
short guided walkthrough.

The demo space `smriti-demo` carries a marker in its description: --remove
only deletes a marked space, --reset rebuilds it, and seeding rolls back a
half-built space on failure. The fixture is plain structured data with
content-integrity tests guarding counts, intent types, note kinds, the
demo marker, and branch divergence.
2026-05-17 10:49:52 +05:30
Himanshu Dongre
5c31d3d0f0 Preserve init API URL in hooks and MCP hints 2026-05-17 00:52:24 +05:30
Himanshu Dongre
ae9d367c08 Make init startup hooks portable 2026-05-17 00:49:44 +05:30
Himanshu Dongre
448484c4c3 Expand doctor activation diagnostics 2026-05-17 00:26:03 +05:30
Himanshu Dongre
8388bf8a1f Add local-first setup onboarding 2026-05-16 22:39:38 +05:30
Himanshu Dongre
704f28570c Add Project Current State CLI surface 2026-05-16 20:55:01 +05:30
Himanshu Dongre
7c8f259342 Add smriti doctor CLI diagnostics 2026-05-16 20:29:02 +05:30
Himanshu Dongre
c470947477
Polish worktree short ids and clean finish (#5) 2026-05-04 15:28:19 +05:30
Himanshu Dongre
8c963198e1 Add canonical project root for spaces 2026-05-04 13:43:44 +05:30
Himanshu Dongre
3cb514b279 Add V3 dirty paths and skill pack v2.1 2026-05-04 13:11:20 +05:30
Himanshu Dongre
1bab89cdea Populate worktree list probe columns 2026-05-04 12:52:35 +05:30
Himanshu Dongre
39003a8aa6 Add V2 worktree-bound claims 2026-05-04 12:16:32 +05:30
Himanshu Dongre
b5ccdce758 Add V1 worktree primitive
Adds WorkTree schema and migration, /api/v5/worktrees CRUD, CLI and MCP worktree surfaces, targeted regression tests, health capability, and minimal docs. Live Postgres migration/manual localhost verification intentionally remain pending until the full backend provider-config gate is resolved.
2026-05-04 00:58:30 +05:30
Himanshu Dongre
beae3b5c9b Add stable task IDs and task-referenced claims for collision detection
Tasks gain an optional id field (short slug like "impl-1", "docs-arch").
Claims gain an optional task_id field referencing a specific task. The
state brief shows (id: X) on tasks and (task: X) on claims, making it
precise which task a claim covers.

Skill pack v1.9 teaches the recheck pattern: after creating a claim,
re-read state to detect if another agent claimed the same task_id in
the race window. If collision detected, abandon and pivot.

This solves the near-simultaneous start problem from the autonomy
validation where both agents picked [docs] because claims had no
task-level identity.
2026-04-14 00:16:46 +05:30
Himanshu Dongre
6da93ae856 Add capabilities manifest to /health for stale-backend detection
The health endpoint now returns git_sha and a capabilities list so
agents can detect when the running backend is missing features they
need (e.g., claims, structured_tasks). Skill pack v1.8 teaches the
capabilities probe: check /health when a 404 or missing section
suggests the backend is stale, tell the human to restart.

Diagnosed from the autonomy validation where Codex hit a backend
without /api/v5/claims — the backend process was running old code.
2026-04-13 23:06:34 +05:30
Himanshu Dongre
73f26e721c Add structured tasks with intent hints for autonomous work selection
Tasks in checkpoints evolve from flat strings to objects with optional
intent_hint (implement/review/investigate/docs/test), blocked_by
(dependency label), and status (open/done). Agents reading the state
brief can now self-select complementary work by matching task intents
against active claim intent_types — no founder routing needed.

Backward-compatible: old string tasks normalize at render time. No
schema migration. JSONB handles both shapes. Skill pack v1.7 teaches
the autonomous selection reflex.
2026-04-13 22:27:32 +05:30
Himanshu Dongre
ae94d73ad3 Skill pack v1.6: teach checkpoint notes, fix stale tool count (16→17) 2026-04-13 20:52:49 +05:30
Himanshu Dongre
51cc91ec60 Teach freshness reflex in skill pack: check --since before checkpointing 2026-04-13 18:22:14 +05:30
Himanshu Dongre
44db645460 Add --since freshness parameter to smriti state for pull-time staleness detection 2026-04-13 18:05:05 +05:30
Himanshu Dongre
208f04ebda Fix stats honesty: compute from actual rendered sections, never silently no-op 2026-04-13 16:28:50 +05:30
Himanshu Dongre
c613e45512 Add --stats flag for compact-mode savings measurement 2026-04-13 16:11:45 +05:30
Himanshu Dongre
b8e6e0403d Add --compact mode to smriti state: artifact labels only with recovery instruction 2026-04-13 15:37:41 +05:30
Himanshu Dongre
3a98e9daa5 Add smriti init for one-step agent onboarding 2026-04-13 14:25:42 +05:30
Himanshu Dongre
0e1f3de8af Add CLI and MCP tests for branch close 2026-04-13 13:37:06 +05:30
Himanshu Dongre
6f52770b8e Teach work-claim reflex in skill pack v1.5 2026-04-12 23:35:53 +05:30
Himanshu Dongre
17c236ce35 Document shared runtime model for multi-agent local development 2026-04-12 22:24:56 +05:30
Himanshu Dongre
7a2443c4bf Add clean-start and clean-finish rules to skill pack v1.3 2026-04-12 21:02:37 +05:30
Himanshu Dongre
6aab2165d9 Update skill pack to v1.2 with repo reconciliation rule 2026-04-12 19:55:45 +05:30
Himanshu Dongre
bea192d25d Update Smriti skill pack for cross-agent continuation 2026-04-12 11:50:39 +05:30
Himanshu Dongre
7586e8ec6a Add skills CLI subcommand and smriti_install_skill MCP tool
CLI:
  smriti skills list                         — enumerate targets + version
  smriti skills show <target>                — print rendered content to stdout
  smriti skills install <target>             — write to target's default destination
  smriti skills install <target> --dry-run   — preview without writing
  smriti skills install <target> --force     — overwrite same-or-newer version
  smriti skills install <target> --destination PATH   — override default path

The skills group does not hit the backend; rendering is a local
package-data lookup. Version-aware refusal is already implemented in
the renderer — install prints a clear "Skipped: already has version X"
message and exits non-zero without --force.

MCP:
  smriti_install_skill(target: str) -> str

Returns the rendered skill pack wrapped in a fenced markdown block with
the suggested destination path at the top. Unlike the CLI, the MCP
tool does NOT write any files — the MCP server runs in the host's
arbitrary working directory, so the agent is expected to read the
suggested destination and write the file using its host's own file
tools (Edit/Write/Bash). This keeps the MCP server read-only from the
host filesystem's perspective.

Thirteen tools total now registered on the FastMCP instance.
2026-04-12 02:10:16 +05:30
Himanshu Dongre
ec0139f707 Add Smriti agent skill pack source and renderer
The skill pack is an instruction file installed into an agent host's
project directory so Smriti's workflow lives in the agent's system
context instead of documentation nobody reads. A single versioned
template.md renders for both Claude Code (MCP-primary) and Codex
(CLI-primary) via a pure-function substituter, keeping content in
sync mechanically across targets.

template.md contains 15 sections. The load-bearing one is Section 5,
When NOT to checkpoint, with equal weight to Section 4. Agents are
told explicitly not to checkpoint after every small step, not to
produce end-of-session blobs, not to treat commits as a save button,
not to stack commits on inconsistent state, not to restate existing
state, and not to checkpoint just because the user asked when there
is no real inflection point. A frequency target (2-4 checkpoints per
4-hour session) and a three-question signal test give agents concrete
criteria for every call.

Other sections cover the read-state-first reflex, when to fork, when
to review, when to compare, when to restore, drift detection,
explicit anti-patterns (HANDOFF.md, silent state reads, inconsistent
author_agent, /chat/send), and the phrases the agent should say out
loud so the human watching has an audit trail.

Renderer API (all pure functions): load_template, get_version, render,
install. install is version-aware: refuses to overwrite a destination
whose installed version is >= the template version unless force=True.
Dry-run mode returns the rendered content without writing.

Content-integrity tests parametrized over both targets assert that
every anti-pattern rule, the signal test, the frequency target, and
the drift-detection guidance appear in the rendered output. If a
future template edit drops any of them, tests fail loudly.

22 skill pack tests, all green.
2026-04-12 02:07:47 +05:30
Himanshu Dongre
491c7316b1 Surface multi-branch state in CLI and MCP by default
smriti state and smriti_state now default to the /state endpoint from
the previous commit, which returns main HEAD plus active non-main
branches plus a lightweight divergence signal. The main continuation
brief still renders first and is unchanged; the two new sections are
appended after it and elided cleanly when there is no fork activity.

Output shape for a single-agent project is byte-identical to before,
so existing users see no change. Projects with multiple agents on
different branches now see one line per active branch in an Active
branches section, and if any branch disagrees with main on decisions
a Divergence signal section names the specific conflicting decisions
and points at smriti compare for the full diff.

Hard caps from the endpoint (5 branches, 2 divergent pairs, 3
decisions per side) keep the aggregate output digestible no matter
how busy the project is.

--main-only (CLI) / main_only=True (MCP) falls back to the legacy
two-call get_head + get_commit path for scripts that parsed the old
shape.

format_state_brief gains an optional space_state kwarg; existing
callers passing only positional args are unaffected.
2026-04-12 02:02:03 +05:30
Himanshu Dongre
332929374a Polish MCP server: full UUIDs, quieter logs, docs notes
Round 5 dogfood surfaced three small friction items:

- smriti_list_checkpoints only rendered short hashes, forcing agents to
  make a second round trip to get the UUID they needed for fork/compare/
  restore. format_commit_list now appends the full UUID in parentheses
  when c["id"] is populated; legacy callers without ids still render a
  clean line. CLI output benefits equally since formatters are shared.
- The mcp SDK logs "Processing request of type ..." at INFO on every
  tool call, cluttering host log panels. smriti-mcp main() now defaults
  the mcp logger to WARNING. Set SMRITI_MCP_LOG_LEVEL=INFO (or DEBUG)
  in the host's env block to re-enable verbose logging when debugging.
- Add README notes acknowledging that the mcp SDK negotiates the
  protocol version on its own during initialize, and documenting the
  new log-level env var.
2026-04-12 01:09:54 +05:30
Himanshu Dongre
2258231c30 Add MCP server wrapping all CLI commands as 12 tools
Round 4 validated that the Smriti CLI surface is complete. This is the
next transport: an MCP stdio server that exposes the same operations as
tools inside MCP-aware hosts (Claude Code, Cursor, Windsurf) so agents
can read and write reasoning state natively in their session instead of
shelling out to the `smriti` binary.

The server lives inside the existing CLI package as a sibling to
client.py and main.py. One `pip install -e ./cli` installs both the
`smriti` and `smriti-mcp` console scripts. Architecture is a thin shim:
each tool builds a SmritiClient, calls 1-2 client methods, pipes the
result through an existing formatter, and returns a string. FastMCP
auto-wraps the string into TextContent. Errors raise SmritiToolError
(wrapping SmritiError with HTTP status + structured detail); FastMCP
converts raised exceptions into MCP error responses.

Zero reimplementation of API logic, zero duplicated formatting, zero
changes to client.py, formatters.py, main.py, or the backend.

Twelve tools, 1:1 with the CLI verbs:

  smriti_list_spaces        smriti_state
  smriti_create_space       smriti_list_checkpoints
  smriti_delete_space       smriti_show_checkpoint
  smriti_create_checkpoint  smriti_review_checkpoint
  smriti_delete_checkpoint  smriti_restore
  smriti_fork               smriti_compare

Two deliberate differences from the CLI:

  - No `-y` confirmation flag on destructive tools. The MCP host's
    tool-approval UI is the gate.
  - smriti_create_checkpoint uses the extract path only (no
    --from-json mode) and does NOT auto-capture cwd as project_root.
    MCP servers run in the host's arbitrary working directory, so
    cwd would plant garbage paths. Callers pass project_root
    explicitly when they want it populated.

Testing: 33 unit tests across all 12 tools using a
MagicMock(spec=SmritiClient) fixture in tests/conftest.py. Each tool
has at least one happy path and one error path; the complex ones
(smriti_state, smriti_create_checkpoint, smriti_delete_checkpoint)
have extra tests for their branches (no-checkpoints short-circuit,
dry-run, existing-session, 409-with-dependents formatting,
409-with-non-dict-fallback, empty-content pre-check).

End-to-end stdio protocol smoke verified independently: the
`smriti-mcp` binary responds to `initialize` with protocol version
2025-03-26 and returns all 12 tools on `tools/list`. Ready for
`mcp dev smriti_cli.mcp_server:mcp` Inspector UI exploration or
direct Claude Code connection.

cli/README.md gets a new MCP server section with installation,
example Claude Code config, tool list, and notes on the project_root
and confirmation-gate differences from the CLI.
2026-04-12 00:54:40 +05:30
Himanshu Dongre
e5db6d8116 Add mcp dependency and pytest harness skeleton
First two steps of V3 Build 2 (the MCP server transport):

  - Pin `mcp>=1.27.0,<2.0.0` in cli/pyproject.toml. FastMCP has been
    the high-level API across the entire 1.x line and is what the
    server will use for tool registration. Verified importable as
    `from mcp.server.fastmcp import FastMCP`.
  - Add `[project.optional-dependencies].dev` with pytest>=7.0 and
    `[tool.pytest.ini_options]` so `pip install -e "./cli[dev]"`
    gets the full dev loop. The cli package previously had no tests.
  - Create cli/tests/ with __init__.py, an empty conftest.py (soon
    to host the shared mock_client fixture), and a smoke test that
    just confirms `smriti_cli` imports. Gives us a working `pytest`
    command from the first commit.

The `smriti-mcp` entry point + actual MCP server code land in the
next commit alongside mcp_server.py so every commit leaves the
package in an installable state.
2026-04-12 00:46:34 +05:30