@colin4k1024/tsp 2.5.1 → 2.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -37,6 +37,11 @@ const TARGET_METADATA = Object.freeze({
37
37
  installPath: '~/.config/opencode/',
38
38
  scope: 'home-level',
39
39
  },
40
+ cangming: {
41
+ label: 'Cangming',
42
+ installPath: '~/.config/cangming/',
43
+ scope: 'home-level',
44
+ },
40
45
  codebuddy: {
41
46
  label: 'CodeBuddy',
42
47
  installPath: './.codebuddy/',
@@ -0,0 +1,105 @@
1
+ # Dashboard Command
2
+
3
+ Real-time progress visibility for goals, waves, and triage. Shows what the loop
4
+ is doing, how much budget remains, and what needs human attention.
5
+
6
+ ## Usage
7
+
8
+ `/dashboard`
9
+
10
+ ## Output
11
+
12
+ ```
13
+ ╔══════════════════════════════════════════════════════════════╗
14
+ ║ LOOP ENGINEERING DASHBOARD ║
15
+ ╠══════════════════════════════════════════════════════════════╣
16
+ ║ ║
17
+ ║ ACTIVE GOALS ║
18
+ ║ ───────────── ║
19
+ ║ ▶ [goal-a1b2c3d4] "Fix all failing tests" ║
20
+ ║ Iteration: 3/15 | Budget: $1.20/$10 | Time: 25m/2h ║
21
+ ║ Last oracle: FAIL — 2 tests still failing in auth module ║
22
+ ║ Next hint: Focus on token refresh mock ║
23
+ ║ ║
24
+ ║ ⏸ [goal-e5f6g7h8] "Achieve 80% coverage" ║
25
+ ║ Iteration: 7/15 | Budget: $3.50/$10 | Paused ║
26
+ ║ ║
27
+ ║ HEARTBEAT ║
28
+ ║ ───────────── ║
29
+ ║ Status: Running (interval: 30m) ║
30
+ ║ Last run: 12m ago — 2/3 passed, 1 goal created ║
31
+ ║ Next run: 18m ║
32
+ ║ Budget: $0.80/$2.00 per hour ║
33
+ ║ ║
34
+ ║ TRIAGE INBOX ║
35
+ ║ ───────────── ║
36
+ ║ [3 pending] [1 high] [2 medium] ║
37
+ ║ • HIGH: sentry — 5 unresolved errors (2h ago) ║
38
+ ║ • MED: lint — 4 new lint errors (30m ago) ║
39
+ ║ • MED: deps — 2 moderate vulnerabilities (1d ago) ║
40
+ ║ ║
41
+ ║ WAVE EXECUTION ║
42
+ ║ ───────────── ║
43
+ ║ (No active waves) ║
44
+ ║ ║
45
+ ║ REWORK TRACKING ║
46
+ ║ ───────────── ║
47
+ ║ Persistent trouble spots: 1 ║
48
+ ║ • src/auth/refresh.ts — 3 attempts, last: fail ║
49
+ ║ ║
50
+ ╚══════════════════════════════════════════════════════════════╝
51
+ ```
52
+
53
+ ## Data Sources
54
+
55
+ The dashboard aggregates from:
56
+
57
+ | Source | Location |
58
+ |--------|----------|
59
+ | Active goals | `~/.claude/goals/*.json` |
60
+ | Heartbeat state | `~/.claude/heartbeat-last-run.json` |
61
+ | Triage inbox | `~/.claude/triage/inbox.jsonl` |
62
+ | Wave progress | Worker `status.md` files in coordination dirs |
63
+ | Rework tracking | `~/.claude/rework-tracking.json` |
64
+ | Cost tracking | Goal history `costDollars` fields |
65
+
66
+ ## Sections
67
+
68
+ ### Active Goals
69
+ - State icon: ▶ (active), ⏸ (paused), ✓ (converged), ⚠ (escalated)
70
+ - Progress: iteration/max, cost/budget, time/duration
71
+ - Last oracle verdict and hint
72
+
73
+ ### Heartbeat
74
+ - Running/stopped status
75
+ - Last run results (passed/failed count)
76
+ - Time to next run
77
+ - Hourly budget usage
78
+
79
+ ### Triage Inbox
80
+ - Pending count by severity
81
+ - Top 3 most recent items with source and age
82
+ - Action hint: "Use /triage to act on items"
83
+
84
+ ### Wave Execution
85
+ - Active wave index / total waves
86
+ - Per-worker status and progress estimate
87
+ - Critical path and ETA (when workers report progress)
88
+
89
+ ### Rework Tracking
90
+ - Persistent trouble spots (files with 3+ rework attempts)
91
+ - Escalation recommendations
92
+
93
+ ## Integration
94
+
95
+ - **`/goal status`**: Dashboard includes goal details
96
+ - **`/heartbeat status`**: Dashboard includes heartbeat state
97
+ - **`/triage stats`**: Dashboard includes inbox summary
98
+ - **Wave execution**: Dashboard tracks parallel worker progress
99
+
100
+ ## Arguments
101
+
102
+ $ARGUMENTS:
103
+ - (none) — Show full dashboard
104
+ - `--compact` — One-line summary per section
105
+ - `--json` — Machine-readable output
@@ -0,0 +1,142 @@
1
+ # Goal Command
2
+
3
+ Define and run a goal-oriented autonomous loop with an external completion oracle.
4
+
5
+ The goal primitive keeps iterating until verifiable stopping conditions are met,
6
+ checked by a SEPARATE model (the oracle) to eliminate author-bias.
7
+
8
+ ## Usage
9
+
10
+ `/goal <subcommand> [args]`
11
+
12
+ ## Subcommands
13
+
14
+ ### Create & Start
15
+
16
+ ```
17
+ /goal "make all tests pass"
18
+ /goal "achieve 80% coverage" --budget-iterations 10 --budget-dollars 5
19
+ /goal "fix lint errors in src/" --checker sonnet
20
+ ```
21
+
22
+ Creates a new goal, infers stopping conditions from the objective, and starts
23
+ the maker-oracle loop immediately.
24
+
25
+ **Auto-inferred stopping conditions:**
26
+ - "tests pass" → `npm test` exit code 0
27
+ - "coverage N%" → coverage report >= N
28
+ - "lint clean" → `npm run lint` exit code 0
29
+ - "build passes" → `npm run build` exit code 0
30
+ - Custom: specify with `--condition "command"`
31
+
32
+ ### Status
33
+
34
+ ```
35
+ /goal status
36
+ /goal status <goalId>
37
+ ```
38
+
39
+ Show active goals with current iteration, oracle verdict history, budget usage,
40
+ and estimated remaining iterations.
41
+
42
+ ### Resume
43
+
44
+ ```
45
+ /goal resume
46
+ /goal resume <goalId>
47
+ ```
48
+
49
+ Resume an active goal from a previous session. Reads state from
50
+ `~/.claude/goals/{goalId}.json` and re-enters the maker loop with the oracle's
51
+ last `nextHint` as guidance.
52
+
53
+ ### Pause
54
+
55
+ ```
56
+ /goal pause
57
+ /goal pause <goalId>
58
+ ```
59
+
60
+ Pause without abandoning. State is persisted for later `/goal resume`.
61
+
62
+ ### List
63
+
64
+ ```
65
+ /goal list
66
+ ```
67
+
68
+ Show all goals (active, paused, converged, escalated) with summary stats.
69
+
70
+ ## The Maker-Oracle Loop
71
+
72
+ ```
73
+ ┌─────────────────────────────────────────────────────┐
74
+ │ /goal "fix all tests" │
75
+ │ │
76
+ │ ┌─────────┐ ┌─────────┐ ┌──────────┐ │
77
+ │ │ MAKER │───▶│ ORACLE │───▶│ CONVERGE │ │
78
+ │ │(primary)│ │(checker)│ │ or LOOP │ │
79
+ │ └─────────┘ └─────────┘ └──────────┘ │
80
+ │ ▲ │ │ │
81
+ │ │ verdict: fail │ │
82
+ │ │ + nextHint │ │
83
+ │ └──────────────┘ │ │
84
+ │ │ │
85
+ │ Budget exhausted? ──▶ ESCALATE to triage│ │
86
+ └─────────────────────────────────────────────────────┘
87
+ ```
88
+
89
+ 1. **Maker** (your primary model) executes one iteration toward the objective
90
+ 2. **Oracle** (different model, read-only) evaluates ALL stopping conditions
91
+ 3. If all pass → goal state becomes `converged`
92
+ 4. If any fail → oracle provides `nextHint` → maker iterates again
93
+ 5. If budget exhausted → goal becomes `escalated` → lands in triage inbox
94
+
95
+ ## Oracle Behavior
96
+
97
+ The oracle:
98
+ - Uses a DIFFERENT model than the maker (default: haiku for speed/cost)
99
+ - Has READ-ONLY tool access (Read, Bash without writes)
100
+ - Cannot modify code — only evaluate conditions
101
+ - Returns structured verdict: `{converged, reasons[], nextHint}`
102
+ - Is the reason you can walk away from a running loop
103
+
104
+ ## Budget Controls
105
+
106
+ | Control | Default | Flag |
107
+ |---------|---------|------|
108
+ | Max iterations | 15 | `--budget-iterations N` |
109
+ | Max duration | 2h | `--budget-duration Nh` |
110
+ | Max cost | $10 | `--budget-dollars N` |
111
+ | Checker model | haiku | `--checker model` |
112
+
113
+ When ANY budget limit is hit, the goal escalates rather than continuing blindly.
114
+
115
+ ## State Persistence
116
+
117
+ Goals persist to `~/.claude/goals/{goalId}.json` (follows goal.schema.json).
118
+
119
+ - Active goals survive session restarts
120
+ - SessionStart hook displays active goal reminder
121
+ - Full iteration history is preserved for debugging
122
+
123
+ ## Integration
124
+
125
+ - **Triage inbox:** Escalated goals create triage items (`/triage`)
126
+ - **Heartbeat:** Heartbeat scans can auto-create goals (`/heartbeat`)
127
+ - **Checkpoint:** Each iteration creates an implicit checkpoint
128
+ - **Verification loop:** Oracle uses verification-loop patterns internally
129
+
130
+ ## Arguments
131
+
132
+ $ARGUMENTS:
133
+ - `<objective>` — Natural language goal description (quoted string)
134
+ - `--budget-iterations N` — Max iterations (default 15)
135
+ - `--budget-duration Nm|Nh` — Max wall time (default 2h)
136
+ - `--budget-dollars N` — Max cost USD (default 10)
137
+ - `--checker model` — Oracle model (default haiku)
138
+ - `--condition "command"` — Additional stopping condition command
139
+ - `status [goalId]` — Show goal status
140
+ - `resume [goalId]` — Resume paused/interrupted goal
141
+ - `pause [goalId]` — Pause active goal
142
+ - `list` — List all goals
@@ -0,0 +1,129 @@
1
+ # Heartbeat Command
2
+
3
+ Run discovery scans on a schedule to find issues, auto-create goals, or surface
4
+ findings to the triage inbox. The heartbeat is what makes a loop an actual loop —
5
+ not a one-shot run.
6
+
7
+ ## Usage
8
+
9
+ `/heartbeat <subcommand> [args]`
10
+
11
+ ## Subcommands
12
+
13
+ ### Start
14
+
15
+ ```
16
+ /heartbeat start
17
+ /heartbeat start --interval 30m
18
+ /heartbeat start --scan test-health,lint-drift
19
+ ```
20
+
21
+ Registers a recurring CronCreate job that runs configured scans. Empty runs
22
+ (all scans pass) archive themselves silently.
23
+
24
+ ### Stop
25
+
26
+ ```
27
+ /heartbeat stop
28
+ ```
29
+
30
+ Cancels the recurring heartbeat job via CronDelete.
31
+
32
+ ### Status
33
+
34
+ ```
35
+ /heartbeat status
36
+ ```
37
+
38
+ Shows:
39
+ - Last scan time and results
40
+ - Next scheduled run
41
+ - Budget usage (cost per hour)
42
+ - Active scan configurations
43
+
44
+ ### Run Once
45
+
46
+ ```
47
+ /heartbeat run
48
+ ```
49
+
50
+ Execute all configured scans immediately (one-shot, no scheduling).
51
+
52
+ ## Configuration
53
+
54
+ Heartbeat reads from `.claude/heartbeat.yaml` in the project root:
55
+
56
+ ```yaml
57
+ heartbeat:
58
+ interval: "30m" # How often to tick (default: 30m)
59
+ scans:
60
+ - name: "test-health"
61
+ command: "npm test 2>&1 | tail -10"
62
+ onFailure: "auto-goal" # auto-create a goal to fix it
63
+ description: "Run test suite"
64
+ - name: "lint-drift"
65
+ command: "npm run lint -- --quiet 2>&1 | wc -l"
66
+ threshold: 0 # numeric threshold: pass if output <= threshold
67
+ onFailure: "triage" # surface to triage inbox for human
68
+ description: "Check lint errors"
69
+ - name: "dependency-audit"
70
+ command: "npm audit --production 2>&1 | grep -c 'vulnerabilities'"
71
+ threshold: 0
72
+ onFailure: "triage"
73
+ description: "Audit dependencies"
74
+ - name: "type-check"
75
+ command: "npx tsc --noEmit 2>&1; echo EXIT:$?"
76
+ onFailure: "auto-goal"
77
+ description: "TypeScript type checking"
78
+ budget:
79
+ maxDollarsPerHour: 2.0 # Pause heartbeat if cost exceeds this
80
+ pauseOnExhaust: true # Pause vs stop on budget exhaust
81
+ ```
82
+
83
+ ## Scan Classification
84
+
85
+ Each scan result is classified into an action:
86
+
87
+ | Action | Behavior |
88
+ |--------|----------|
89
+ | `auto-goal` | Create a goal automatically from the failure (e.g., "fix 3 failing tests") |
90
+ | `triage` | Append to triage inbox for human review |
91
+ | `notify` | Desktop notification only (informational) |
92
+ | `ignore` | Log silently, take no action |
93
+
94
+ ## Flow
95
+
96
+ ```
97
+ ┌────────────────────────────────────────────┐
98
+ │ /heartbeat start │
99
+ │ │
100
+ │ CronCreate (every 30m) │
101
+ │ │ │
102
+ │ ▼ │
103
+ │ Run all scans │
104
+ │ │ │
105
+ │ ┌────┼────────┬──────────┐ │
106
+ │ ▼ ▼ ▼ ▼ │
107
+ │ PASS FAIL FAIL FAIL │
108
+ │ │ (goal) (triage) (notify) │
109
+ │ │ │ │ │ │
110
+ │ ▼ ▼ ▼ ▼ │
111
+ │ Skip /goal /triage Desktop │
112
+ │ create inbox notification │
113
+ └────────────────────────────────────────────┘
114
+ ```
115
+
116
+ ## Integration
117
+
118
+ - **`/goal`**: Heartbeat auto-creates goals from `auto-goal` scan failures
119
+ - **`/triage`**: Heartbeat populates triage inbox from `triage` scan failures
120
+ - **Budget**: Integrates with cost tracking; pauses if hourly budget exceeded
121
+ - **Hooks**: Uses CronCreate/CronDelete for scheduling (7-day auto-expiry applies)
122
+
123
+ ## Arguments
124
+
125
+ $ARGUMENTS:
126
+ - `start [--interval Nm|Nh] [--scan name1,name2]` — Start recurring heartbeat
127
+ - `stop` — Cancel heartbeat
128
+ - `status` — Show heartbeat state
129
+ - `run` — Execute scans once (no scheduling)
@@ -0,0 +1,108 @@
1
+ # Triage Command
2
+
3
+ View and act on findings that the loop could not auto-resolve. The triage inbox
4
+ is where issues land when they need human judgment.
5
+
6
+ ## Usage
7
+
8
+ `/triage [subcommand] [args]`
9
+
10
+ ## Subcommands
11
+
12
+ ### List (default)
13
+
14
+ ```
15
+ /triage
16
+ /triage list
17
+ /triage list --source heartbeat
18
+ /triage list --severity high
19
+ ```
20
+
21
+ Show pending triage items with source, severity, and suggested actions.
22
+
23
+ ### Act
24
+
25
+ ```
26
+ /triage act <id> goal # Promote to a goal (auto-fix)
27
+ /triage act <id> dismiss # Dismiss (not actionable)
28
+ /triage act <id> defer # Defer to next session
29
+ ```
30
+
31
+ Take action on a triage item. `goal` creates a goal from the finding.
32
+
33
+ ### Stats
34
+
35
+ ```
36
+ /triage stats
37
+ ```
38
+
39
+ Show inbox health metrics: pending count, sources breakdown, age distribution.
40
+
41
+ ### Clear
42
+
43
+ ```
44
+ /triage clear --resolved
45
+ /triage clear --older-than 7d
46
+ ```
47
+
48
+ Remove resolved or stale items.
49
+
50
+ ## Triage Item Structure
51
+
52
+ Each item in the inbox has:
53
+
54
+ | Field | Description |
55
+ |-------|-------------|
56
+ | `id` | Unique identifier (e.g., `triage-lq4x8`) |
57
+ | `source` | Where it came from (e.g., `heartbeat:lint-drift`, `goal:escalated`) |
58
+ | `severity` | `high`, `medium`, `low` |
59
+ | `summary` | One-line description |
60
+ | `detail` | Full scan output or error context |
61
+ | `suggestedActions` | What the system recommends |
62
+ | `createdAt` | When the item was created |
63
+ | `status` | `pending`, `acted`, `dismissed`, `deferred` |
64
+
65
+ ## Sources
66
+
67
+ Items enter triage from:
68
+
69
+ 1. **Heartbeat scans** with `onFailure: "triage"` classification
70
+ 2. **Escalated goals** that exhausted their budget without converging
71
+ 3. **Manual** items added by the user
72
+ 4. **Connectors** (MCP) that discover issues from external tools
73
+
74
+ ## Flow
75
+
76
+ ```
77
+ ┌──────────────┐ ┌─────────┐ ┌──────────────┐
78
+ │ Heartbeat │────▶│ TRIAGE │────▶│ /triage act │
79
+ │ Goal escape │ │ INBOX │ │ goal/dismiss│
80
+ │ Connectors │ │ (.jsonl)│ │ /defer │
81
+ └──────────────┘ └─────────┘ └──────────────┘
82
+
83
+
84
+ Statusline: [Triage: N]
85
+ ```
86
+
87
+ ## Storage
88
+
89
+ Inbox is stored as newline-delimited JSON at `~/.claude/triage/inbox.jsonl`.
90
+ This format is:
91
+ - Append-only (safe for concurrent writes)
92
+ - Human-readable (one JSON object per line)
93
+ - Easy to grep and filter
94
+
95
+ ## Integration
96
+
97
+ - **`/heartbeat`**: Primary source of triage items
98
+ - **`/goal`**: Escalated goals create triage items; triage items can become goals
99
+ - **Statusline**: Hook shows `[Triage: N]` count when items are pending
100
+ - **Session start**: Active triage items mentioned in session context
101
+
102
+ ## Arguments
103
+
104
+ $ARGUMENTS:
105
+ - `list [--source name] [--severity level]` — List pending items (default)
106
+ - `act <id> goal|dismiss|defer` — Take action on an item
107
+ - `stats` — Show inbox metrics
108
+ - `clear --resolved|--older-than Nd` — Clean up resolved/stale items
@@ -1,4 +1,8 @@
1
1
  #!/usr/bin/env node
2
+ // DEPRECATED: This hook's functionality has been merged into suggest-compact.js.
3
+ // The strategic-compact hook now covers all thresholds (65/70/85/95%).
4
+ // This file is retained for backward compatibility but is no longer registered in hooks.json.
5
+ //
2
6
  // harness-context-monitor.js — PostToolUse hook (all tools)
3
7
  // Reads context metrics from the bridge file written by harness-statusline.js
4
8
  // and injects advisory warnings into agent context when usage is high.
@@ -52,22 +52,45 @@ process.stdin.on('end', () => {
52
52
  if (remaining != null) {
53
53
  const usableRemaining = Math.max(0, ((remaining - AUTO_COMPACT_BUFFER_PCT) / (100 - AUTO_COMPACT_BUFFER_PCT)) * 100);
54
54
  usedPct = Math.max(0, Math.min(100, Math.round(100 - usableRemaining)));
55
+ } else if (data.transcript_path) {
56
+ // Parse actual token usage from transcript JSONL (CCometixLine approach)
57
+ try {
58
+ const { resolveTranscriptMetrics } = require('../scripts/lib/transcript-usage');
59
+ const modelId = (data.model && data.model.id) || process.env.CLAUDE_MODEL || null;
60
+ const metrics = resolveTranscriptMetrics(data.transcript_path, modelId);
61
+ if (metrics) {
62
+ usedPct = Math.max(0, Math.min(100, Math.round(metrics.usagePct)));
63
+ }
64
+ } catch (_) { /* ignore */ }
55
65
 
56
- // Write bridge file for harness-context-monitor.js
57
- if (session) {
66
+ // Final fallback: file size estimate
67
+ if (usedPct == null) {
58
68
  try {
59
- const bridgePath = path.join(os.tmpdir(), `harness-ctx-${session}.json`);
60
- fs.writeFileSync(bridgePath, JSON.stringify({
61
- session_id: session,
62
- remaining_percentage: remaining,
63
- used_pct: usedPct,
64
- active_role: activeRole,
65
- timestamp: Math.floor(Date.now() / 1000),
66
- }));
69
+ const stat = fs.statSync(data.transcript_path);
70
+ const estimatedTokens = Math.round(stat.size * 0.25);
71
+ if (estimatedTokens > 0) {
72
+ usedPct = Math.max(0, Math.min(100, Math.round((estimatedTokens / 200000) * 100)));
73
+ }
67
74
  } catch (_) { /* ignore */ }
68
75
  }
76
+ }
77
+
78
+ // Write bridge file for downstream hooks (suggest-compact, context-monitor)
79
+ if (usedPct != null && session) {
80
+ try {
81
+ const bridgePath = path.join(os.tmpdir(), `harness-ctx-${session}.json`);
82
+ fs.writeFileSync(bridgePath, JSON.stringify({
83
+ session_id: session,
84
+ remaining_percentage: remaining != null ? remaining : null,
85
+ used_pct: usedPct,
86
+ active_role: activeRole,
87
+ timestamp: Math.floor(Date.now() / 1000),
88
+ }));
89
+ } catch (_) { /* ignore */ }
90
+ }
69
91
 
70
- // Build progress bar (10 segments)
92
+ // Build progress bar (10 segments)
93
+ if (usedPct != null) {
71
94
  const filled = Math.floor(usedPct / 10);
72
95
  const bar = '█'.repeat(filled) + '░'.repeat(10 - filled);
73
96
  if (usedPct < 50) {
package/hooks/hooks.json CHANGED
@@ -68,6 +68,17 @@
68
68
  "description": "Doc file warning: warn about non-standard documentation files (exit code 0; warns only)",
69
69
  "id": "pre:write:doc-file-warning"
70
70
  },
71
+ {
72
+ "matcher": "*",
73
+ "hooks": [
74
+ {
75
+ "type": "command",
76
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/harness-statusline.js\""
77
+ }
78
+ ],
79
+ "description": "Display current role and context usage statusline (must run before strategic-compact to write bridge file)",
80
+ "id": "pre:all:harness-statusline"
81
+ },
71
82
  {
72
83
  "matcher": "*",
73
84
  "hooks": [
@@ -77,7 +88,7 @@
77
88
  "timeout": 10
78
89
  }
79
90
  ],
80
- "description": "Suggest strategic context compaction when context usage crosses 70/85/95% thresholds",
91
+ "description": "Suggest strategic context compaction when context usage crosses 65/70/85/95% thresholds",
81
92
  "id": "pre:all:strategic-compact"
82
93
  },
83
94
  {
@@ -152,28 +163,6 @@
152
163
  "description": "Check MCP server health before MCP tool execution and block unhealthy MCP calls",
153
164
  "id": "pre:mcp-health-check"
154
165
  },
155
- {
156
- "matcher": "*",
157
- "hooks": [
158
- {
159
- "type": "command",
160
- "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/harness-statusline.js\""
161
- }
162
- ],
163
- "description": "Display current role and context usage statusline",
164
- "id": "pre:all:harness-statusline"
165
- },
166
- {
167
- "matcher": "*",
168
- "hooks": [
169
- {
170
- "type": "command",
171
- "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/harness-context-monitor.js\""
172
- }
173
- ],
174
- "description": "Monitor context budget, warn at 35%/25% thresholds",
175
- "id": "pre:all:harness-context-monitor"
176
- },
177
166
  {
178
167
  "matcher": "Bash",
179
168
  "hooks": [
@@ -234,6 +223,17 @@
234
223
  "description": "Load previous context and detect package manager on new session",
235
224
  "id": "session:start"
236
225
  },
226
+ {
227
+ "matcher": "*",
228
+ "hooks": [
229
+ {
230
+ "type": "command",
231
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/session-start-goal-resume.js\""
232
+ }
233
+ ],
234
+ "description": "Check for active goals from previous sessions and inject resume reminder",
235
+ "id": "session:goal-resume"
236
+ },
237
237
  {
238
238
  "matcher": "*",
239
239
  "hooks": [