Skip to content

Commit d14edbe

Browse files
LastStepclaude
andauthored
feat(catalog): Plan 21 session-start dedup + Phase C sensors (#46)
Cuts session-start context redundancy and completes Plan 08 Phase C: - session-context sensor now filters memory/session-start protocols (duplicates of sensor-injected content), skips empty FieldNotes, summarizes pending reports instead of full-cat, drops misfired end-of-session reminder block, and scopes to SessionStart matcher startup|resume|clear so /compact can be handled by a separate sensor. - session-start protocol rewritten to assume sensor did the heavy lifting — no more 10-step re-read list. - context-guard gains verify + plan pattern detection with word-boundary (not end-anchored) regex; planning reminder suppressed when wrap-up already fired to avoid triple-stacking. - new compact-recovery sensor (matcher=compact) re-injects minimal context (Quick Triggers + Work State) after /compact, <2000 chars in normal conditions. - station self-awareness.md trimmed: durable UX preferences moved to memory.md Feedback section where they structurally belong. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 525ee11 commit d14edbe

21 files changed

Lines changed: 427 additions & 142 deletions

File tree

.bonsai.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ agents:
3939
- agent-review
4040
- dispatch-guard
4141
- subagent-stop-review
42+
- compact-recovery
4243
routines:
4344
- backlog-hygiene
4445
- dependency-audit

catalog/protocols/session-start/session-start.md

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
tags: [protocol, session]
3-
description: Ordered startup sequence — always steps + conditional loading by task type.
3+
description: Session startup — act on the context the session-context sensor already injected.
44
---
55

66
# Protocol: Session Start
@@ -10,37 +10,34 @@ description: Ordered startup sequence — always steps + conditional loading by
1010
1111
---
1212

13-
## Always (every session)
13+
## Always
1414

15-
1. Read [agent/Core/identity.md](../Core/identity.md) — confirm role and mindset
16-
2. Read [agent/Core/memory.md](../Core/memory.md) — surface pending flags, check work state
17-
3. Read [agent/Core/self-awareness.md](../Core/self-awareness.md) — refresh context monitoring rules
18-
4. Read [INDEX.md](../../INDEX.md) — get project snapshot
19-
5. Read [Playbook/Status.md](../../Playbook/Status.md) — see what's in progress and pending
20-
6. Scan [Playbook/Backlog.md](../../Playbook/Backlog.md) — check for P0 items not yet in Status.md (escalate immediately if found)
21-
7. Read [Logs/FieldNotes.md](../../Logs/FieldNotes.md) — check for user updates since last session
22-
8. Check [Reports/Pending/](../../Reports/Pending/) — process any unreviewed agent reports
23-
9. Read [agent/Protocols/security.md](security.md) — refresh security constraints (if installed)
24-
10. Read [agent/Protocols/scope-boundaries.md](scope-boundaries.md) — refresh what you own (if installed)
15+
The session-context sensor injects the following at SessionStart: identity.md, memory.md, self-awareness.md, INDEX.md, Status.md, FieldNotes.md (when non-empty), Reports/Pending summary, and always-on Protocols (security, scope-boundaries). Health warnings (stale memory, Backlog P0, pending reports, log freshness) are also surfaced.
16+
17+
Your job:
18+
19+
1. **Address any flags** in the injected `memory.md` Flags section.
20+
2. **Confirm work state** from `memory.md` — resume in-flight tasks or start fresh as appropriate.
21+
3. **Act on health warnings** the sensor raised (stale memory, P0 items, pending reports).
22+
4. **Process pending reports** by reading each file in `Reports/Pending/` (sensor gave summaries only).
2523

2624
> [!note]
27-
> Paths like `INDEX.md`, `Playbook/`, `Logs/`, and `Reports/` refer to the project docs location configured during `bonsai init`. Check your workspace CLAUDE.md → External References for the exact paths.
28-
> Backlog.md is a scan, not a full read — look for P0 items only. Full backlog review is handled by the backlog-hygiene routine.
25+
> If the session-context sensor is NOT installed (headless agent), fall back to reading core files manually: identity, memory, self-awareness, INDEX, Status, then scan Backlog P0 and check Reports/Pending.
2926
3027
---
3128

3229
## Conditional (by task type)
3330

3431
### If executing a plan
3532

36-
- Read the assigned plan in full before writing any code
33+
- Read the assigned plan in full before any dispatch
3734
- Read [Playbook/Standards/SecurityStandards.md](../../Playbook/Standards/SecurityStandards.md)
38-
- Read relevant coding standards from [agent/Skills/](../Skills/)
35+
- Read relevant skills from [agent/Skills/](../Skills/)
3936

4037
### If starting new work
4138

42-
- Check if a plan exists in [Playbook/Plans/Active/](../../Playbook/Plans/Active/) — if not, ask the user
43-
- Read scope boundaries before touching any files
39+
- Check for an existing plan in [Playbook/Plans/Active/](../../Playbook/Plans/Active/); ask the user if none
40+
- Re-read scope-boundaries if touching new files
4441

4542
### If reviewing or reporting
4643

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env bash
2+
# Compact Recovery — {{ .AgentDisplayName }}
3+
# Re-injects minimal context after Claude Code /compact. Target: <2000 chars.
4+
5+
ROOT="${1:-.}"
6+
WORKSPACE="${ROOT}/{{ .Workspace }}"
7+
8+
echo "=== POST-COMPACT RECOVERY ==="
9+
echo ""
10+
11+
# 1. Extract Quick Triggers table from workspace CLAUDE.md
12+
if [[ -f "${WORKSPACE}CLAUDE.md" ]]; then
13+
echo "--- Quick Triggers (from CLAUDE.md) ---"
14+
awk '/^### Quick Triggers/,/^### Protocols/' "${WORKSPACE}CLAUDE.md" | sed '/^### Protocols/d'
15+
echo ""
16+
fi
17+
18+
# 2. Extract Work State section from memory.md
19+
if [[ -f "${WORKSPACE}agent/Core/memory.md" ]]; then
20+
echo "--- Work State (from memory.md) ---"
21+
awk '/^## Work State/,/^## Notes/' "${WORKSPACE}agent/Core/memory.md" | sed '/^## Notes/d'
22+
echo ""
23+
fi
24+
25+
echo "Context compacted. Resume from Work State above. If uncertain, re-read memory.md and Status.md."
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
name: compact-recovery
2+
description: Re-injects minimal context after /compact (Quick Triggers + Work State only)
3+
agents: all
4+
required: all
5+
event: SessionStart
6+
matcher: "compact"

catalog/sensors/context-guard/context-guard.sh.tmpl

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,53 @@ if triggered:
119119
)
120120
injection = (injection + '\\n' + checklist) if injection else checklist
121121
122+
# ── Verification triggers — word-boundary only, not end-anchored ────────────
123+
124+
verify_patterns = [
125+
r'\\bverify\\s+(everything|it\\s+all)\\b',
126+
r'\\bcheck\\s+(your|the)\\s+work\\b',
127+
r'\\bcheck\\s+if\\s+you\\s+missed\\b',
128+
r'\\breview\\s+(your|the)\\s+changes\\b',
129+
r'\\breview\\s+before\\s+(commit|push|ship)\\b',
130+
r'\\bdoes\\s+everything\\s+look\\s+(right|good)\\b',
131+
]
132+
133+
verify_hit = any(re.search(p, normalized) for p in verify_patterns)
134+
135+
if verify_hit:
136+
checklist = (
137+
'\\nVERIFICATION REQUESTED. Before proceeding:\\n'
138+
'1. Re-read your own changes — check for bugs, edge cases, regressions\\n'
139+
'2. Verify all tests pass (if applicable)\\n'
140+
'3. Check for stale references in documentation\\n'
141+
'4. Confirm no security issues introduced'
142+
)
143+
injection = (injection + '\\n' + checklist) if injection else checklist
144+
145+
# ── Planning triggers — word-boundary only ──────────────────────────────────
146+
147+
plan_patterns = [
148+
r'\\b(lets|let\\s+us)\\s+plan\\b',
149+
r'\\bplan\\s+(this|the|a)\\b',
150+
r'\\bcreate\\s+a\\s+plan\\b',
151+
r'\\bdesign\\s+(this|the|a)\\b',
152+
r'\\barchitect\\s+(this|the|a)\\b',
153+
]
154+
155+
plan_hit = any(re.search(p, normalized) for p in plan_patterns)
156+
157+
if plan_hit:
158+
reminder = (
159+
'\\nPLANNING DETECTED. Before drafting a plan:\\n'
160+
'1. Load planning workflow: {workspace}agent/Workflows/planning.md\\n'
161+
'2. Load planning-template skill: {workspace}agent/Skills/planning-template.md\\n'
162+
'3. Follow the Tier rules and Verification requirements'
163+
).replace('{workspace}', os.path.join(root, ''))
164+
# Only inject planning reminder if no wrap-up trigger already fired
165+
# (avoid triple-stacking injections)
166+
if not triggered:
167+
injection = (injection + '\\n' + reminder) if injection else reminder
168+
122169
# ── Output ──────────────────────────────────────────────────────────────────
123170
124171
if not injection:

catalog/sensors/session-context/meta.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ description: Injects core identity, memory, protocols, and project status at ses
33
agents: all
44
required: all
55
event: SessionStart
6+
matcher: "startup|resume|clear"

catalog/sensors/session-context/session-context.sh.tmpl

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,32 +40,71 @@ if [[ -n "$DOCS" ]]; then
4040
cat "${DOCS}Playbook/Status.md"
4141
fi
4242

43+
# FieldNotes: skip dump when file is effectively empty (only header/separators).
44+
# Effectively empty = 1 or fewer non-blank, non-header-marker, non-frontmatter lines
45+
# after removing the top YAML frontmatter block and markdown headings.
4346
if [[ -f "${DOCS}Logs/FieldNotes.md" ]]; then
44-
echo ""
45-
echo "=== Logs/FieldNotes.md ==="
46-
cat "${DOCS}Logs/FieldNotes.md"
47+
content_lines=$(awk '
48+
BEGIN { in_fm = 0; fm_done = 0 }
49+
NR == 1 && /^---[[:space:]]*$/ { in_fm = 1; next }
50+
in_fm && /^---[[:space:]]*$/ { in_fm = 0; fm_done = 1; next }
51+
in_fm { next }
52+
/^[[:space:]]*$/ { next }
53+
/^#/ { next }
54+
/^---[[:space:]]*$/ { next }
55+
/^>/ { next }
56+
{ count++ }
57+
END { print count + 0 }
58+
' "${DOCS}Logs/FieldNotes.md")
59+
if [[ "$content_lines" -gt 1 ]]; then
60+
echo ""
61+
echo "=== Logs/FieldNotes.md ==="
62+
cat "${DOCS}Logs/FieldNotes.md"
63+
fi
4764
fi
4865

49-
# Pending reports
66+
# Pending reports: summarize (name + description) instead of full cat.
5067
if [[ -d "${DOCS}Reports/Pending/" ]] && [ -n "$(ls -A "${DOCS}Reports/Pending/" 2>/dev/null)" ]; then
5168
echo ""
5269
echo "=== Reports/Pending/ ==="
5370
for f in "${DOCS}Reports/Pending/"*; do
71+
[[ -f "$f" ]] || continue
5472
echo ""
5573
echo "--- $(basename "$f") ---"
56-
cat "$f"
74+
# Try to extract description from YAML frontmatter first
75+
desc=$(awk '
76+
BEGIN { in_fm = 0 }
77+
NR == 1 && /^---[[:space:]]*$/ { in_fm = 1; next }
78+
in_fm && /^---[[:space:]]*$/ { exit }
79+
in_fm && /^description:/ {
80+
sub(/^description:[[:space:]]*/, "")
81+
print
82+
exit
83+
}
84+
' "$f")
85+
if [[ -n "$desc" ]]; then
86+
echo "$desc"
87+
else
88+
# Fallback: first non-empty, non-separator line
89+
awk '
90+
/^---[[:space:]]*$/ { next }
91+
/^[[:space:]]*$/ { next }
92+
{ print; exit }
93+
' "$f"
94+
fi
5795
done
5896
fi
5997
fi
6098

6199
# ── Protocols ───────────────────────────────────────────────────────────────
62-
{{ range .Protocols }}
63-
100+
{{ range .Protocols -}}
101+
{{ if and (ne . "memory") (ne . "session-start") }}
64102
if [[ -f "${WORKSPACE}agent/Protocols/{{ . }}.md" ]]; then
65103
echo ""
66104
echo "=== PROTOCOL: {{ . }}.md ==="
67105
cat "${WORKSPACE}agent/Protocols/{{ . }}.md"
68106
fi
107+
{{ end -}}
69108
{{ end }}
70109

71110
# ── Health checks ───────────────────────────────────────────────────────────
@@ -115,10 +154,3 @@ if [[ -n "$DOCS" ]] && [[ -d "${DOCS}Logs/" ]]; then
115154
fi
116155
fi
117156
fi
118-
119-
# End-of-session reminder
120-
echo ""
121-
echo "REMINDER: Before ending this session:"
122-
echo " - Update memory.md with current work state"
123-
echo " - Update Status.md if any tasks changed status"
124-
echo " - Write session log if significant work was done"

station/.claude/settings.json

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,47 @@
1616
"hooks": [
1717
{
1818
"type": "command",
19-
"command": "bash -c 'r=\"$PWD\"; while [ \"$r\" != \"/\" ] \u0026\u0026 [ ! -f \"$r/.bonsai.yaml\" ]; do r=$(dirname \"$r\"); done; bash \"$r/station/agent/Sensors/dispatch-guard.sh\" \"$r\"'"
19+
"command": "bash -c 'r=\"$PWD\"; while [ \"$r\" != \"/\" ] \u0026\u0026 [ ! -f \"$r/.bonsai.yaml\" ]; do r=$(dirname \"$r\"); done; bash \"$r/station/agent/Sensors/scope-guard-files.sh\" \"$r\"'"
2020
}
2121
],
22-
"matcher": "Agent"
22+
"matcher": "Edit|Write"
2323
},
2424
{
2525
"hooks": [
2626
{
2727
"type": "command",
28-
"command": "bash -c 'r=\"$PWD\"; while [ \"$r\" != \"/\" ] \u0026\u0026 [ ! -f \"$r/.bonsai.yaml\" ]; do r=$(dirname \"$r\"); done; bash \"$r/station/agent/Sensors/scope-guard-files.sh\" \"$r\"'"
28+
"command": "bash -c 'r=\"$PWD\"; while [ \"$r\" != \"/\" ] \u0026\u0026 [ ! -f \"$r/.bonsai.yaml\" ]; do r=$(dirname \"$r\"); done; bash \"$r/station/agent/Sensors/dispatch-guard.sh\" \"$r\"'"
2929
}
3030
],
31-
"matcher": "Edit|Write"
31+
"matcher": "Agent"
3232
}
3333
],
3434
"SessionStart": [
3535
{
3636
"hooks": [
37-
{
38-
"type": "command",
39-
"command": "bash -c 'r=\"$PWD\"; while [ \"$r\" != \"/\" ] \u0026\u0026 [ ! -f \"$r/.bonsai.yaml\" ]; do r=$(dirname \"$r\"); done; bash \"$r/station/agent/Sensors/session-context.sh\" \"$r\"'"
40-
},
4137
{
4238
"type": "command",
4339
"command": "bash -c 'r=\"$PWD\"; while [ \"$r\" != \"/\" ] \u0026\u0026 [ ! -f \"$r/.bonsai.yaml\" ]; do r=$(dirname \"$r\"); done; bash \"$r/station/agent/Sensors/routine-check.sh\" \"$r\"'"
4440
}
4541
]
42+
},
43+
{
44+
"hooks": [
45+
{
46+
"type": "command",
47+
"command": "bash -c 'r=\"$PWD\"; while [ \"$r\" != \"/\" ] \u0026\u0026 [ ! -f \"$r/.bonsai.yaml\" ]; do r=$(dirname \"$r\"); done; bash \"$r/station/agent/Sensors/compact-recovery.sh\" \"$r\"'"
48+
}
49+
],
50+
"matcher": "compact"
51+
},
52+
{
53+
"hooks": [
54+
{
55+
"type": "command",
56+
"command": "bash -c 'r=\"$PWD\"; while [ \"$r\" != \"/\" ] \u0026\u0026 [ ! -f \"$r/.bonsai.yaml\" ]; do r=$(dirname \"$r\"); done; bash \"$r/station/agent/Sensors/session-context.sh\" \"$r\"'"
57+
}
58+
],
59+
"matcher": "startup|resume|clear"
4660
}
4761
],
4862
"Stop": [
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
name: code-review
3+
description: Reviewing agent output against the plan for correctness and standards. Checking implementation changes before merging
4+
when_to_use: Reviewing agent output against the plan for correctness and standards; Checking implementation changes before merging
5+
---
6+
7+
Load and follow the **Code Review** workflow at `station/agent/Workflows/code-review.md`.
8+
9+
## Examples
10+
11+
> **User:** "Review the changes on the feature branch"
12+
> **Action:** Load code-review workflow, diff branch against main, check plan compliance
13+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
name: issue-to-implementation
3+
description: Taking an issue from intake through to shipped code. Running the full autonomous implementation workflow
4+
when_to_use: Taking an issue from intake through to shipped code; Running the full autonomous implementation workflow
5+
---
6+
7+
Load and follow the **Issue To Implementation** workflow at `station/agent/Workflows/issue-to-implementation.md`.
8+
9+
## Examples
10+
11+
> **User:** "Pick up issue #15 and ship it"
12+
> **Action:** Load issue-to-implementation workflow, analyze issue, plan, dispatch, review, merge
13+

0 commit comments

Comments
 (0)