Session brief¶
get_project_status tells you what you were doing. The session brief tells you what changed while you were away — commits landed, the branch moved, the working tree got dirty, tasks changed status, blockers appeared, a decision was logged.
Every start_session call embeds a brief automatically (pass brief: false to skip it), and you can also fetch one without opening a session via get_session_brief. It's fully deterministic — no LLM calls happen inside mindpm — and it never touches the network: everything comes from local git subprocess calls and the local SQLite database.
To get git activity in the brief, tell mindpm where your repo lives:
set_project_repo_path(project: "my-app", repo_path: "/Users/you/code/my-app")
(or pass repo_path directly to create_project). Without a configured repo, the brief still reports the task/blocker/decision delta — it just skips the git section.
Example output:
{
"project": "my-app",
"degraded": false,
"degraded_reasons": [],
"gap": {
"last_session_ended_at": "2026-08-08T22:14:03.000Z",
"hours_elapsed": 11.3,
"label": "overnight"
},
"handoff": {
"last_session_summary": "Finished the auth refactor",
"next_steps": "Wire up rate limiting, then tackle the webhook retry bug"
},
"git": {
"available": true,
"anchor": "sha",
"branch_then": "feat/phase-3",
"branch_now": "feat/phase-3",
"branch_changed": false,
"commits": [
{ "sha": "a1b2c3d", "author": "umit", "date": "2026-08-09T09:02:11+00:00", "subject": "Add rate limit middleware" }
],
"commit_count": 4,
"commits_truncated": false,
"files_changed": [
{ "path": "src/middleware/rate-limit.ts", "added": 82, "deleted": 11 }
],
"files_changed_truncated": false,
"working_tree_dirty": true,
"untracked_count": 2,
"stash_count": 0
},
"tasks": {
"changed": [
{ "id": "a1b2c3d4", "title": "Add rate limiting", "from_status": "in_progress", "to_status": "done", "at": "2026-08-09T09:05:00.000Z" }
],
"claimed_now": [{ "id": "e5f6a7b8", "title": "Webhook retry bug" }],
"next_suggested": [{ "id": "c9d0e1f2", "title": "Write API docs", "priority": "high" }]
},
"blockers": [],
"decisions_since": [
{ "id": "9f8e7d6c", "title": "Use token bucket for rate limiting", "at": "2026-08-09T09:00:00.000Z" }
],
"notes_since_count": 3,
"awaiting_acceptance": {
"low_risk": [{ "task_id": "a1b2c3d4", "key": "my-app-14", "title": "Document the JSON report format", "risk_level": "low", "waiting_hours": 5.2 }],
"needs_ui": [{ "task_id": "b2c3d4e5", "key": "my-app-12", "title": "Inactivity timeout", "risk_level": "medium", "waiting_hours": 20.1,
"kanban_url": "http://localhost:3131?project=<project-id>&task=my-app-12" }],
"hint": "Show this to the user. ..."
}
}
awaiting_acceptance lists work waiting for a human: submitted tasks when the project's verification is off, verified ones when it is on. Agents show it at the start of a session; low-risk tasks can be accepted from chat with accept_tasks, medium and high risk only in the Kanban UI.
gap.label is same-day (<6h), overnight (6-20h), multi-day (20h-14d), or stale (>14d) — a stale gap adds a gap.hint telling the agent to re-verify context rather than trust next_steps at face value.
The git delta is anchored on the exact commit sha recorded when the prior session ended (via end_session), not on a timestamp — sha-based anchoring survives rebases and amends that would break a clock-based diff. If that sha becomes unreachable (force-push, rebase, or the repo was pruned), the brief transparently falls back to a timestamp anchor and reports it in degraded_reasons. A broken or missing repo never fails the brief — it just comes back with git.available: false and degraded: true, while the task/blocker/decision delta is unaffected.