Self-contained skill for tracking technical changes with structured JSON records, an enforced state machine, and a session handoff format that lets a new AI session resume work cleanly when a previous one expires. Includes: - 5 stdlib-only Python scripts (init, create, update, status, validator) all supporting --help and --json - 3 reference docs (lifecycle state machine, JSON schema, handoff format) - /tc dispatcher in commands/tc.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5.2 KiB
Session Handoff Format
The handoff block is the most important part of a TC for AI continuity. When a session expires, the next session reads this block to resume work cleanly without re-deriving context.
Where it lives
session_context.handoff inside tc_record.json.
Structure
{
"progress_summary": "string",
"next_steps": ["string", "..."],
"blockers": ["string", "..."],
"key_context": ["string", "..."],
"files_in_progress": [
{
"path": "src/foo.py",
"state": "editing|needs_review|partially_done|ready",
"notes": "string|null"
}
],
"decisions_made": [
{
"decision": "string",
"rationale": "string",
"timestamp": "ISO 8601"
}
]
}
Field-by-field rules
progress_summary (string)
A 1-3 sentence narrative of what has been done. Past tense. Concrete.
GOOD:
"Implemented JWT signing with HS256, wired the auth middleware into the main router, and added two passing unit tests for the happy path."
BAD:
"Working on auth." (too vague) "Wrote a bunch of code." (no specifics)
next_steps (array of strings)
Ordered list of remaining actions. Each step should be small enough to complete in 5-15 minutes. Use imperative mood.
GOOD:
- "Add integration test for invalid token (401)"
- "Update README with the new POST /login endpoint"
- "Run
pytest tests/auth/and capture output as evidence T2"
BAD:
- "Finish the feature" (not actionable)
- "Make it better" (no measurable outcome)
blockers (array of strings)
Things preventing progress RIGHT NOW. If empty, the TC should not be in blocked status.
GOOD:
- "Test fixtures for the user model do not exist; need to create
tests/fixtures/user.py" - "Waiting for product to confirm whether refresh tokens are in scope (asked in #product channel)"
BAD:
- "It's hard." (not a blocker)
- "I'm tired." (not a blocker)
key_context (array of strings)
Critical decisions, gotchas, patterns, or constraints the next session MUST know. Things that took the current session significant effort to discover.
GOOD:
- "The
legacy_authmodule is being phased out — do NOT extend it. New code goes insrc/auth/." - "We use HS256 (not RS256) because the secret rotation tooling does not support asymmetric keys yet."
- "There is a hidden import cycle if you import
Userfrommodels.userinstead ofmodels. Always usefrom models import User."
BAD:
- "Be careful." (not specific)
- "There might be bugs." (not actionable)
files_in_progress (array of objects)
Files currently mid-edit or partially complete. Include the state so the next session knows whether to read, edit, or review.
| state | meaning |
|---|---|
editing |
Actively being modified, may not compile |
needs_review |
Changes complete but unverified |
partially_done |
Some functions done, others stubbed |
ready |
Complete and tested |
decisions_made (array of objects)
Architectural decisions taken during the current session, with rationale and timestamp. These should also be promoted to a project-wide decision log when significant.
{
"decision": "Use HS256 instead of RS256 for JWT signing",
"rationale": "Secret rotation tooling does not support asymmetric keys; we accept the tradeoff because token lifetime is 15 minutes",
"timestamp": "2026-04-05T14:32:00+00:00"
}
Handoff Lifecycle
When to write the handoff
- At every natural milestone (feature complete, tests passing, EOD)
- BEFORE the session is likely to expire
- Whenever a blocker is hit
- Whenever a non-obvious decision is made
How to write it (non-blocking)
Spawn a background subagent so the main agent doesn't pause:
"Read
docs/TC/records/<TC-ID>/tc_record.json. Update the handoff section with: progress_summary='...'; add next_step '...'; add blocker '...'. Usetc_update.pyso revision history is appended. Then updatelast_activeand write atomically."
How the next session reads it
- Read
docs/TC/tc_registry.jsonand find TCs with statusin_progressorblocked. - Read
tc_record.jsonfor each. - Display the handoff block to the user.
- Ask: "Resume ? (y/n)"
- If yes:
- Archive the previous session's
current_sessionintosession_historywith anendedtimestamp and a summary. - Create a new
current_sessionfor the new bot. - Append a revision: "Session resumed by <platform/model>".
- Walk through
next_stepsin order.
- Archive the previous session's
Quality Bar
A handoff is "good" if a fresh AI session, with no other context, can pick up the work and make progress within 5 minutes of reading the record. If the next session has to ask "what was I doing?" or "what does this code do?", the previous handoff failed.
Anti-patterns
| Anti-pattern | Why it's bad |
|---|---|
| Empty handoff at session end | Defeats the entire purpose |
next_steps: ["continue"] |
Not actionable |
| Handoff written but never updated as work progresses | Goes stale within an hour |
Decisions buried in notes instead of decisions_made |
Loses the rationale |
Files mid-edit but not listed in files_in_progress |
Next session reads stale code |
Blockers in notes instead of blockers array |
TC status cannot be set to blocked |