docs: add session-hygiene intent/approach/work docs and synod research
This commit is contained in:
parent
0c37d3f2f9
commit
90114b451a
File diff suppressed because one or more lines are too long
158
docs/approach/2026-01-24-session-hygiene.md
Normal file
158
docs/approach/2026-01-24-session-hygiene.md
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
# Approach: Session Hygiene Extension
|
||||
|
||||
## Strategy
|
||||
|
||||
**Core philosophy**: Ambient awareness, not active management.
|
||||
|
||||
The extension provides a persistent footer widget showing git state. The user glances at it when they want to. A `/commit` command offers a guided flow with auto-drafted messages when they're ready to commit. No nudges, no prompts, no interruptions.
|
||||
|
||||
**Key Decisions**:
|
||||
|
||||
1. **Widget vs Status**: Widget (multi-character, always visible) vs setStatus (footer slot, subtle)
|
||||
→ **Widget** — needs to be glanceable without hunting for it
|
||||
|
||||
2. **Polling vs Events**: Poll git status periodically vs hook into tool_result events
|
||||
→ **Hook tool_result** — only re-check after bash/write/edit tools that might change files. Avoids polling overhead.
|
||||
|
||||
3. **Grouping strategy**: No grouping vs LLM-driven grouping
|
||||
→ **LLM-driven grouping** — LLM sees changed files + session context, proposes logical groups with conventional commit messages. Always runs, even for 1-3 files.
|
||||
|
||||
4. **Confirmation flow**: Always confirm vs LLM discretion
|
||||
→ **LLM discretion** — LLM decides when to ask questions (ambiguous grouping, orphan files) vs proceed. User already invoked `/commit`, so trust the intent.
|
||||
|
||||
5. **Orphan files**: Auto-bucket into "misc" vs ask
|
||||
→ **Ask** — if a file doesn't fit any logical group, LLM should ask user where it belongs.
|
||||
|
||||
6. **Staging**: Auto-stage all vs let user stage manually
|
||||
→ **Auto-stage all (`git add -A`)** — matches "just commit everything" simplicity. User can unstage manually before `/commit` if needed.
|
||||
|
||||
## Architecture
|
||||
|
||||
### New Components
|
||||
|
||||
```
|
||||
~/.pi/agent/extensions/session-hygiene/
|
||||
├── index.ts # Extension entry point
|
||||
└── git.ts # Git helpers (status, commit, etc.)
|
||||
```
|
||||
|
||||
### Extension Structure
|
||||
|
||||
```typescript
|
||||
// index.ts
|
||||
export default function(pi: ExtensionAPI) {
|
||||
// State
|
||||
let dirtyCount = 0;
|
||||
|
||||
// 1. Widget: show dirty count in footer
|
||||
pi.on("session_start", updateWidget);
|
||||
pi.on("tool_result", maybeUpdateWidget); // Only after bash/write/edit
|
||||
|
||||
// 2. Command: /commit
|
||||
pi.registerCommand("commit", { handler: commitFlow });
|
||||
}
|
||||
```
|
||||
|
||||
### Data Flow
|
||||
|
||||
```
|
||||
[tool_result event]
|
||||
│
|
||||
▼
|
||||
is bash/write/edit?
|
||||
│ yes
|
||||
▼
|
||||
git status --porcelain
|
||||
│
|
||||
▼
|
||||
count changed files
|
||||
│
|
||||
▼
|
||||
ctx.ui.setWidget("hygiene", ["● 14 files"])
|
||||
```
|
||||
|
||||
```
|
||||
[/commit command]
|
||||
│
|
||||
▼
|
||||
git status --porcelain → list of changed files
|
||||
│
|
||||
▼
|
||||
extract session context:
|
||||
- recent messages (user prompts, assistant responses)
|
||||
- file touchpoints (which files were read/written/edited when)
|
||||
│
|
||||
▼
|
||||
LLM prompt:
|
||||
"Here are the changed files and session context.
|
||||
Group into logical commits. For each group:
|
||||
- list files
|
||||
- conventional commit message
|
||||
If a file doesn't fit, ask the user.
|
||||
If grouping is ambiguous, ask.
|
||||
Otherwise, proceed and execute commits."
|
||||
│
|
||||
▼
|
||||
LLM executes commits via tool calls (git add <files>, git commit -m "...")
|
||||
│
|
||||
▼
|
||||
update widget (now shows 0 or remaining)
|
||||
```
|
||||
|
||||
### Commit Tool
|
||||
|
||||
The `/commit` command injects context and lets the LLM drive. It needs a `git_commit` tool:
|
||||
|
||||
```typescript
|
||||
pi.registerTool({
|
||||
name: "git_commit",
|
||||
description: "Stage specific files and commit with a message",
|
||||
parameters: Type.Object({
|
||||
files: Type.Array(Type.String(), { description: "Files to stage (relative paths)" }),
|
||||
message: Type.String({ description: "Commit message (conventional format)" }),
|
||||
}),
|
||||
async execute(toolCallId, params, onUpdate, ctx, signal) {
|
||||
// git add <files...>
|
||||
// git commit -m <message>
|
||||
// return success/failure
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
This lets the LLM make multiple commits in sequence, asking questions in between if needed.
|
||||
|
||||
## Risks
|
||||
|
||||
### Known Unknowns
|
||||
|
||||
- **Widget placement**: `setWidget` defaults to above editor. Need to verify `belowEditor` placement looks right for a small status indicator.
|
||||
- **LLM latency**: Drafting commit message adds a few seconds. Acceptable? Could show "Drafting..." in UI.
|
||||
- **Model availability**: Need a model for commit message drafting. What if user doesn't have API key for it?
|
||||
|
||||
### Failure Modes
|
||||
|
||||
- **Not a git repo**: `git status` returns non-zero. Extension silently does nothing (no widget, `/commit` shows error).
|
||||
- **Detached HEAD / merge conflict**: Unusual git states. `/commit` should detect and warn rather than corrupt state.
|
||||
- **Empty commit**: All changes already staged and committed. `/commit` should detect "nothing to commit" and notify.
|
||||
|
||||
### Blast Radius
|
||||
|
||||
- **Minimal**: Extension only reads git state and runs `git add -A` + `git commit`. No force pushes, no rebase, no destructive operations.
|
||||
- **Worst case**: User commits something they didn't want to. Recoverable via `git reset HEAD~1`.
|
||||
|
||||
## Phases
|
||||
|
||||
### Phase 1: Widget + git_commit Tool
|
||||
- Footer widget showing dirty file count
|
||||
- Updates after file-mutating tools
|
||||
- `git_commit` tool registered (LLM can use it anytime)
|
||||
|
||||
### Phase 2: /commit Command
|
||||
- `/commit` command injects context and triggers LLM-driven grouping
|
||||
- LLM proposes groups, asks questions if uncertain, executes commits
|
||||
- Widget updates as commits land
|
||||
|
||||
### Phase 3: Polish (Future)
|
||||
- Stash support (`/stash`)
|
||||
- Undo last commit (`/uncommit`)
|
||||
- Integration with worklog skill (prompt to commit after worklog)
|
||||
38
docs/intent/2026-01-24-session-hygiene.md
Normal file
38
docs/intent/2026-01-24-session-hygiene.md
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# Intent: Session Hygiene Extension
|
||||
|
||||
## Motivation
|
||||
|
||||
Working in pi across long sessions, it's easy to lose track of what's changed. You finish a session with dozens of uncommitted files, unclear what goes with what, and the commit history becomes a mess of grab-bag commits. The problem isn't catastrophic — nothing is lost — but it erodes organization over time.
|
||||
|
||||
## Need
|
||||
|
||||
Ambient awareness of git state while working, so commits happen naturally at good moments rather than as panicked cleanup at session end.
|
||||
|
||||
## Use-Cases
|
||||
|
||||
- **Mid-session glance**: You're deep in a refactor, glance at the footer, see "14 files" — mental note that there's a chunk of work building up. You might commit now, or keep going. Either way, you're aware.
|
||||
|
||||
- **Natural stopping point**: You finish a logical unit of work. The footer reminds you there's uncommitted work. You run `/commit`, get a suggested message based on what we discussed, and commit cleanly.
|
||||
|
||||
- **Session end**: You're about to close pi. Footer shows dirty state. You either commit, stash, or consciously leave it — but you're not surprised by 48 files later.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- Footer widget shows uncommitted file count for current repo at all times
|
||||
- `/commit` command triggers guided flow with auto-drafted commit message from conversation context
|
||||
- User never feels nagged, blocked, or guilty — just informed
|
||||
- Commits end up logical and well-messaged because awareness came early
|
||||
|
||||
## Constraints
|
||||
|
||||
- Single repo only (the one we're in)
|
||||
- Must work as a pi extension (TypeScript, pi extension API)
|
||||
- No external dependencies beyond git
|
||||
|
||||
## Anti-Goals
|
||||
|
||||
- **No auto-commit**: Never commit without explicit user action
|
||||
- **No blocking prompts**: Never interrupt flow with modal dialogs
|
||||
- **No guilt mechanics**: No "you should commit" nudges, red warnings, or escalating alerts
|
||||
- **No multi-repo tracking**: Don't watch repos outside current working directory
|
||||
- **No push**: This is about local commits only
|
||||
49
docs/work/2026-01-24-session-hygiene.md
Normal file
49
docs/work/2026-01-24-session-hygiene.md
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Work: Session Hygiene Extension
|
||||
|
||||
## Intent
|
||||
Link to: [docs/intent/2026-01-24-session-hygiene.md](../intent/2026-01-24-session-hygiene.md)
|
||||
|
||||
## Approach
|
||||
Link to: [docs/approach/2026-01-24-session-hygiene.md](../approach/2026-01-24-session-hygiene.md)
|
||||
|
||||
## Checklist
|
||||
|
||||
### Phase 1: Widget + git_commit Tool
|
||||
|
||||
- [x] **W001**: Create extension directory structure
|
||||
- Verification: `ls ~/.pi/agent/extensions/session-hygiene/index.ts`
|
||||
|
||||
- [x] **W002**: Implement git status helper
|
||||
- Verification: `pi -e ~/.pi/agent/extensions/session-hygiene -p "test" 2>&1 | head -5` (no syntax errors)
|
||||
|
||||
- [ ] **W003**: Implement footer widget showing dirty file count
|
||||
- Verification: Start pi in a dirty repo, observe widget shows file count
|
||||
|
||||
- [ ] **W004**: Hook tool_result to update widget after bash/write/edit
|
||||
- Verification: In pi, write a file, observe widget count increases
|
||||
|
||||
- [ ] **W005**: Implement git_commit tool (stage files + commit)
|
||||
- Verification: `pi -p "Use git_commit to commit README.md with message 'test: verify tool'"` in test repo
|
||||
|
||||
### Phase 2: /commit Command
|
||||
|
||||
- [ ] **W006**: Implement session context extraction (recent messages, file touchpoints)
|
||||
- Verification: `/commit` in pi shows context being gathered (log or notify)
|
||||
|
||||
- [ ] **W007**: Implement /commit command that injects context and triggers LLM
|
||||
- Verification: `/commit` in dirty repo triggers LLM response with grouping proposal
|
||||
|
||||
- [ ] **W008**: Verify full flow: /commit → LLM groups → git_commit calls → widget updates
|
||||
- Verification: End-to-end test in a repo with 5+ changed files across different paths
|
||||
|
||||
## Verification Evidence
|
||||
|
||||
- (2026-01-24 23:xx) W001: `ls ~/.pi/agent/extensions/session-hygiene/index.ts` → exists
|
||||
- (2026-01-24 23:xx) W002: jiti load fails on missing module (expected) — syntax valid
|
||||
|
||||
## Notes
|
||||
|
||||
- Extension location: `~/.pi/agent/extensions/session-hygiene/`
|
||||
- Will use `belowEditor` widget placement — need to verify it looks right
|
||||
- For /commit context injection, use `pi.sendUserMessage()` or `before_agent_start` message injection
|
||||
- Model for grouping: use whatever model is currently active (no separate API key needed)
|
||||
Loading…
Reference in a new issue