commit 1f7a85b7d13b594095fa56c398d2176a8c507383 Author: Travis Herbranson Date: Mon Apr 27 20:17:06 2026 -0400 Initial session-notes skill: convention enforcer for coding sessions Skill that triggers at the end of every coding session where files changed. Enforces structured session notes with label, narrative, and four fields (What, Why, How, Touches) at one-entry-per-logical-change granularity. Includes reference examples from the Loom project and review-ready CLAUDE.md with key patterns documented. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..996cdd0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.skill +__pycache__/ +.DS_Store diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..385e3a1 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,53 @@ +# Session Notes Skill + +Claude Code skill that enforces structured session note documentation +at the end of every coding session. + +## Architecture + +``` +session-notes-skill/ + session-notes/ + SKILL.md — Skill definition (triggers, format, rules) + references/ + example-session.md — Reference examples at correct granularity +``` + +## Key Patterns + +**Skill-as-convention enforcer.** This skill doesn't generate code or +transform files — it enforces a documentation convention. The SKILL.md +teaches the agent what to write, when, and at what granularity. The +reference file provides concrete examples to calibrate quality. + +**Granularity rule.** The core constraint is one entry per logical change. +This is the hardest thing to get right — agents naturally want to +summarize. The skill explicitly calls out the anti-pattern (rolling +multiple changes into one entry) and provides a "too coarse" vs "right +granularity" comparison. + +**Progressive disclosure.** SKILL.md body is always loaded when triggered +(~100 lines). The reference examples in `references/` are loaded on +demand when the agent needs to calibrate its output quality. + +**Session notes live in the project, not the skill.** The skill tells +the agent to write to `sessions/.md` in whatever project it's +working on. The skill itself doesn't store any session data. + +## Development + +```bash +# Package as .skill file +cd session-notes && zip -r ../session-notes.skill SKILL.md references/ +``` + +## Session Notes + +After each coding session, append a session entry to +`sessions/session-notes-skill.md` in this project folder. +See that file for the format convention and existing entries. + +Granularity: one entry per logical change. A new function, a new route, +a new template, a new config setting, or a bug fix each get their own +entry. Don't combine multiple changes into one entry. If it would be a +separate item in a code review, it's a separate entry here. diff --git a/session-notes/SKILL.md b/session-notes/SKILL.md new file mode 100644 index 0000000..3bd5442 --- /dev/null +++ b/session-notes/SKILL.md @@ -0,0 +1,121 @@ +--- +name: session-notes +description: > + Write structured session notes at the end of every coding session. Triggers + automatically when a session involves code changes — new files, bug fixes, + refactors, features, config changes, or any modification to project files. + Also triggers when the user says "write session notes", "log this session", + "document what we did", "wrap up", or "end of session". If you made code + changes during this session, use this skill before the conversation ends. + Do not wait to be asked. +--- + +# Session Notes + +At the end of every coding session where code was changed, write a structured +session note capturing each individual change. This is how future sessions, +reviewers, and the Loom dashboard understand what happened. + +## When to Write + +Write session notes when any of these are true: +- You created, modified, or deleted project files during this session +- The user asks you to log, document, or wrap up the session +- The conversation is ending and you made changes + +Do not write session notes for conversations that were purely discussion, +planning, or Q&A with no file changes. + +## Where to Write + +Session notes live in the project directory at `sessions/.md`. +If the file doesn't exist, create it with the header template. If it exists, +append a new dated session entry at the bottom. + +The project slug is the kebab-case project name — usually matches the +directory name (e.g., `work-index-dashboard`, `cli-standardization`). + +## Format + +Each session entry is a dated heading followed by one or more change entries. +Each change has a label, a narrative, and four structured fields. + +```markdown +## Session — YYYY-MM-DD + +### + + +- **What:** +- **Why:** +- **How:** +- **Touches:** +``` + +## Granularity + +This is the most important rule: **one entry per logical change.** + +A logical change is a new function, a new route, a new template, a config +addition, a bug fix, or a refactor. If you'd explain it as a separate thing +in a code review, it's a separate entry. + +The test: could someone read this single entry and understand what was +changed without looking at the diff? If yes, the granularity is right. +If they'd need to mentally decompose it into sub-changes, it's too coarse. + +**Too coarse** (don't do this): +```markdown +### Built the data layer +Created vault reader, Trello client, and join layer. +``` + +**Right granularity** (do this): +```markdown +### Vault Frontmatter Reader +Scans all .md files in the vault and extracts YAML frontmatter into +VaultProject dataclasses... + +### Trello REST Client +Wraps the Trello board API with httpx... + +### Join Layer +Merges vault projects and Trello cards into a unified ProjectView... +``` + +## Writing Quality + +The narrative is the most important part — it's what a human reads first. +Write it as if you're explaining the change to a colleague who knows the +project but wasn't in this session. Be specific about what was built, +not just that something was built. + +For the structured fields: +- **What** should be a single line, specific enough to be useful in a list +- **Why** should state the actual motivation, not just "it was needed" +- **How** should name the key functions, patterns, or libraries — enough + that someone could find the relevant code without grepping +- **Touches** should list every file that was created or modified, with + `(new)` for new files + +## File Header + +If creating the session notes file for the first time, use this header: + +```markdown +# — Session Notes + +Session log for the project. Each session is a dated +heading with a list of changes. Each change has a label, narrative, and +four structured fields (What, Why, How, Touches). + +--- +``` + +Then append the first session entry below the `---`. + +## Reference + +See `references/example-session.md` for a complete example of a +well-written session entry at the right granularity level. diff --git a/session-notes/references/example-session.md b/session-notes/references/example-session.md new file mode 100644 index 0000000..c79ca0d --- /dev/null +++ b/session-notes/references/example-session.md @@ -0,0 +1,60 @@ +# Example Session Entry + +This is a reference example showing the right granularity and writing +style for session notes. Each change is its own entry with specific +detail about what, why, how, and what files were touched. + +--- + +## Session — 2026-04-27 + +### Trello REST Client +Wraps the Trello board API with httpx. Fetches lists and cards, groups +cards by label name (which is the project slug). Includes in-memory cache +with configurable TTL so the dashboard doesn't hit Trello on every page +load. + +- **What:** `TrelloClient` class with card grouping and TTL cache +- **Why:** Dashboard needs live Trello card state joined to vault data +- **How:** httpx.Client with 15s timeout. `_fetch_all()` populates cache + dict with lists and cards. `get_cards_by_project()` groups cards by + label name. `get_list_for_project()` returns highest-priority list + name using a priority map (Active=0, On Deck=1, etc). `refresh()` + invalidates cache. +- **Touches:** data/trello.py (new) + +### Loose Thread Scanner +Scans all vault .md files for unchecked `- [ ]` checkbox items. Returns +them as LooseThread objects with the text, project slug, and source file. +Found 862 items across the real vault. + +- **What:** `find_loose_threads()` returns list of LooseThread +- **Why:** "What loose threads have I left" — unfiled commitments +- **How:** Regex `^(\s*)-\s+\[\s\]\s+(.+)$` with MULTILINE flag. Scans + all .md files regardless of type. Uses project slug from frontmatter + if available, falls back to filename stem. +- **Touches:** data/sessions.py + +### Path Traversal Fix +Gemini CLI review caught that _log_session accepted arbitrary slugs that +could write outside the vault directory via `../../` paths. Added slug +validation regex and resolved-path containment check. + +- **What:** Slug validation + path containment for MCP write tools +- **Why:** Security — prevent path traversal via malicious slug input +- **How:** _SLUG_RE regex `^[a-z][a-z0-9-]*$` rejects anything with dots, + slashes, or uppercase. _validate_slug() returns error message or None. + Additional check: `filepath.resolve().is_relative_to(vault_path.resolve())`. + Applied to both _log_session and _update_project_status. +- **Touches:** mcp/server.py + +### Pydantic Settings +App configuration using pydantic-settings with LOOM_ env prefix. Covers +host, port, vault path, Trello credentials, and cache TTL. Reads from +.env file. + +- **What:** `Settings` class with LOOM_ prefix and vault_dir property +- **Why:** Centralized config with env-file support +- **How:** pydantic-settings BaseSettings with env_prefix="LOOM_". vault_dir + is a @property that returns Path(vault_path). +- **Touches:** core/config.py diff --git a/sessions/session-notes-skill.md b/sessions/session-notes-skill.md new file mode 100644 index 0000000..c400168 --- /dev/null +++ b/sessions/session-notes-skill.md @@ -0,0 +1,48 @@ +# Session Notes Skill — Session Notes + +Session log for the session-notes-skill project. Each session is a dated +heading with a list of changes. Each change has a label, narrative, and +four structured fields (What, Why, How, Touches). + +--- + +## Session — 2026-04-27 + +### SKILL.md Definition +Wrote the core skill definition with trigger description, format template, +granularity rule, and writing quality guidance. The trigger is set to fire +automatically at the end of any coding session where files changed, and +also responds to manual invocations like "write session notes" or "wrap up." + +- **What:** SKILL.md with session notes convention and auto-trigger +- **Why:** Need a reusable skill that enforces consistent session documentation + across all projects and all Claude Code sessions +- **How:** YAML frontmatter with pushy description for reliable triggering. + Body covers when/where/format/granularity. Includes good-vs-bad granularity + comparison and file header template for new projects. +- **Touches:** session-notes/SKILL.md (new) + +### Reference Examples +Created a reference file with four real session entries from the Loom +project (work-index-dashboard) showing the correct granularity and style. +Covers different change types: new function, scanner utility, security fix, +and config setup. + +- **What:** Example session entries for agent calibration +- **Why:** The granularity rule needs concrete examples to be effective — + abstract rules alone lead to over-summarization +- **How:** Extracted and lightly edited four entries from the Loom session + notes that were validated as "right granularity" by Travis. +- **Touches:** session-notes/references/example-session.md (new) + +### Project Documentation +Added CLAUDE.md with key patterns section documenting the skill-as-convention +approach, granularity rule importance, progressive disclosure pattern, and +the separation between skill (convention) and session data (in each project). + +- **What:** CLAUDE.md with architecture and key patterns +- **Why:** Future sessions working on this skill need to understand the + design decisions, not just the file tree +- **How:** Follows the review-ready CLAUDE.md convention established in the + Loom project — file tree plus key patterns plus session notes pointer. +- **Touches:** CLAUDE.md (new)