session: pickup and wrap, four stores, one disposable handoff (V-445)
The pickup skill reads HANDOFF.md and the Vikunja task, then restates the assumption set and stops. That pause is the point: every wasted session here started with an agent that inferred the goal. The wrap skill runs the tests, updates the durable docs, commits in slices, pushes, records state in Vikunja, and leaves a handoff only if work remains. HANDOFF.md is gitignored and injected by a SessionStart hook. It holds what the next agent needs to resume and nothing else. Anything that would still matter next week goes to Vikunja, CLAUDE.md or docs/. .claude/ was ignored wholesale. The workflow itself is now tracked, because how a session behaves should be reviewed like code. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -213,3 +213,48 @@ data pans on a phone. Local preview + headless screenshot recipe is in `AGENTS.m
|
||||
|
||||
This repo is project **Maven** (ID 2) in Vikunja. MCP: `http://localhost:9100/mcp` (or
|
||||
`http://192.168.1.104:9100/mcp` from workpc). Feature/bug/deploy tasks go there.
|
||||
|
||||
Vikunja is the durable task store. A task holds the goal, the constraints and the
|
||||
assumption ledger. Work without a task id is work nobody can resume, so a session that
|
||||
has no id asks for one before it starts.
|
||||
|
||||
## Session workflow
|
||||
|
||||
Start with `/pickup`, end with `/wrap`. One task per session, and wrap at roughly half
|
||||
context rather than letting the session compact.
|
||||
|
||||
Four stores, and each one owns something the others must not hold:
|
||||
|
||||
| Store | Holds | Lifetime |
|
||||
|---|---|---|
|
||||
| Vikunja task | goal, constraints, assumption ledger, status | durable |
|
||||
| `CLAUDE.md`, `AGENTS.md` | what an agent must know before touching code | durable |
|
||||
| `docs/` | design, measurements, decisions | durable |
|
||||
| `HANDOFF.md` | only what the next agent needs to resume this task | one session |
|
||||
|
||||
`HANDOFF.md` is gitignored, injected at session start, and deleted the moment it is
|
||||
consumed. If a line in it would still matter next week, it is in the wrong file.
|
||||
|
||||
Docs are tiered by path, so staleness is visible from the filename. Files directly under
|
||||
`docs/` are living and carry a `Last verified: <date> @ <sha>` line. Files under
|
||||
`docs/evals/` are dated measurements and are never edited after the day — a newer number
|
||||
is a new file. Files under `docs/archive/` are dead and read by nobody by default.
|
||||
|
||||
## Git flow
|
||||
|
||||
Hooks live in `.githooks/` and are tracked, wired with `core.hooksPath`. Fresh clone:
|
||||
|
||||
```sh
|
||||
git config core.hooksPath .githooks
|
||||
```
|
||||
|
||||
- Branch per task: `scripts/task-branch.sh <vikunja-id> <slug>`. It records the parent
|
||||
branch under `.git/maven-parent/`, because git does not track where a branch came from
|
||||
and the PR needs the base.
|
||||
- `pre-commit` refuses master, and refuses more than 300 changed lines in non-markdown
|
||||
files. Markdown is exempt and may land as one batch.
|
||||
- `commit-msg` requires the subject to end with `(V-<id>)`. `V-` and not `#`, because
|
||||
Gitea autolinks `#123` to a Gitea issue, which is the wrong tracker.
|
||||
- `pre-push` opens the PR with `tea` against the recorded parent. It never blocks a push.
|
||||
|
||||
`--no-verify` exists. Using it means saying why in the commit body.
|
||||
|
||||
Reference in New Issue
Block a user