invar-tools 1.12.0__py3-none-any.whl → 1.15.0__py3-none-any.whl

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.
@@ -0,0 +1,480 @@
1
+ # /invar-reflect Configuration
2
+
3
+ **Status**: Phase B - Hook Integration (Proposed)
4
+
5
+ This document describes the configuration for automatic feedback collection using the `/invar-reflect` skill.
6
+
7
+ ---
8
+
9
+ ## Overview
10
+
11
+ The `/invar-reflect` skill can be triggered:
12
+ 1. **Manually**: User calls `/invar-reflect`
13
+ 2. **Automatically** (Phase B): Via `PostTaskCompletion` hook when conditions are met
14
+
15
+ ---
16
+
17
+ ## Proposed Hook Schema
18
+
19
+
20
+ ### Message Count Trigger (Implemented - DX-79)
21
+
22
+ **Status**: ✅ Implemented in v1.15.0
23
+
24
+ Both Claude Code and Pi now support automatic feedback triggering via **message count threshold**.
25
+
26
+ **Configuration in `.claude/settings.local.json`**:
27
+
28
+ ```json
29
+ {
30
+ "feedback": {
31
+ "enabled": true,
32
+ "min_messages": 30
33
+ }
34
+ }
35
+ ```
36
+
37
+ **Hook Parameters**:
38
+
39
+ | Parameter | Type | Default | Description |
40
+ |-----------|------|---------|-------------|
41
+ | `enabled` | boolean | true | Enable feedback collection |
42
+ | `min_messages` | number | 30 | Minimum messages before trigger |
43
+
44
+ **How it works**:
45
+
46
+ 1. **Message counting**: Both hooks track message count per session
47
+ 2. **Threshold trigger**: At `min_messages`, hook displays reminder
48
+ 3. **User action**: Agent sees reminder and can run `/invar-reflect`
49
+
50
+ **Cross-platform implementation**:
51
+
52
+ | Platform | Hook File | Mechanism |
53
+ |----------|-----------|-----------|
54
+ | **Claude Code** | `.claude/hooks/invar.UserPromptSubmit.sh` | Bash script with jq config parsing |
55
+ | **Pi** | `.pi/hooks/invar.ts` | TypeScript with fs config reading |
56
+
57
+ Both read the same `.claude/settings.local.json` configuration file.
58
+
59
+ ### PostTaskCompletion Hook (Waiting for Claude Code Support)
60
+
61
+ **Proposed configuration in `.claude/settings.json`**:
62
+
63
+ ```json
64
+ {
65
+ "hooks": {
66
+ "PostTaskCompletion": [
67
+ {
68
+ "hooks": [
69
+ {
70
+ "type": "skill",
71
+ "skill": "invar-reflect",
72
+ "mode": "silent",
73
+ "conditions": {
74
+ "min_messages": 30,
75
+ "min_duration_hours": 2
76
+ }
77
+ }
78
+ ]
79
+ }
80
+ ]
81
+ },
82
+ "feedback": {
83
+ "enabled": true,
84
+ "auto_trigger": true,
85
+ "retention_days": 90
86
+ }
87
+ }
88
+ ```
89
+
90
+ **Hook Parameters**:
91
+
92
+ | Parameter | Type | Default | Description |
93
+ |-----------|------|---------|-------------|
94
+ | `type` | string | - | Must be `"skill"` |
95
+ | `skill` | string | - | Skill name: `"invar-reflect"` |
96
+ | `mode` | string | `"silent"` | Silent mode (no user interruption) |
97
+ | `conditions.min_messages` | number | 30 | Minimum messages in session |
98
+ | `conditions.min_duration_hours` | number | 2 | Minimum session duration |
99
+
100
+ **Feedback Config**:
101
+
102
+ | Parameter | Type | Default | Description |
103
+ |-----------|------|---------|-------------|
104
+ | `enabled` | boolean | true | Enable feedback collection |
105
+ | `auto_trigger` | boolean | true | Auto-run via hook |
106
+ | `retention_days` | number | 90 | Auto-cleanup old files |
107
+
108
+ ---
109
+
110
+ ## Triggering Conditions
111
+
112
+
113
+ The hook triggers when the message count reaches the configured threshold (default: 30).
114
+
115
+ **Conditions**:
116
+
117
+ 1. ✅ **Message count >= min_messages** (default: 30)
118
+ 2. ✅ **Feedback enabled** (`feedback.enabled = true`)
119
+
120
+ **No hard frequency cap**: Users can run `/invar-reflect` manually at any time.
121
+
122
+ **Customizing threshold**:
123
+
124
+ ```json
125
+ {
126
+ "feedback": {
127
+ "enabled": true,
128
+ "min_messages": 50 // Trigger at 50 messages instead of 30
129
+ }
130
+ }
131
+ ```
132
+
133
+ ## Silent Mode
134
+
135
+
136
+ The hook displays a **reminder** when the threshold is reached:
137
+
138
+ ```
139
+ <system-reminder>
140
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
141
+ 📊 Invar: Auto-triggering usage feedback (30 messages)
142
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
143
+
144
+ Session has reached 30 messages. Consider running /invar-reflect
145
+ to generate usage feedback.
146
+
147
+ To disable: Set feedback.enabled=false in .claude/settings.local.json
148
+ </system-reminder>
149
+ ```
150
+
151
+ **Note**: The agent sees this reminder and can choose to invoke `/invar-reflect` or continue working.
152
+
153
+ ## User Control
154
+
155
+ ### Enable/Disable
156
+
157
+ **During init** (Phase C):
158
+ ```bash
159
+ $ invar init
160
+ ...
161
+ Enable automatic feedback collection? [Y/n]: n
162
+ ```
163
+
164
+ **After init**:
165
+ ```json
166
+ // .claude/settings.json
167
+ {
168
+ "feedback": {
169
+ "enabled": false // Disable feedback collection
170
+ }
171
+ }
172
+ ```
173
+
174
+ Or disable auto-trigger only (manual `/invar-reflect` still works):
175
+ ```json
176
+ {
177
+ "feedback": {
178
+ "enabled": true,
179
+ "auto_trigger": false // Manual only
180
+ }
181
+ }
182
+ ```
183
+
184
+ ### File Management
185
+
186
+ Feedback files location:
187
+ ```
188
+ .invar/feedback/
189
+ ├── feedback-2026-01-03.md # All sessions from Jan 3
190
+ ├── feedback-2026-01-04.md # All sessions from Jan 4
191
+ └── feedback-2026-01-10.md # Jan 10 (gaps are OK)
192
+ ```
193
+
194
+ **Auto-cleanup**: Files older than `retention_days` are automatically deleted.
195
+
196
+ **Manual cleanup**:
197
+ ```bash
198
+ # Delete all feedback
199
+ rm -rf .invar/feedback/
200
+
201
+ # Delete specific file
202
+ rm .invar/feedback/feedback-2026-01-03.md
203
+ ```
204
+
205
+ ---
206
+
207
+ ## Workaround: Using Stop Hook (Until PostTaskCompletion is Available)
208
+
209
+
210
+ ### Implementation Details
211
+
212
+ **Claude Code Hook** (`.claude/hooks/invar.UserPromptSubmit.sh`):
213
+
214
+ ```bash
215
+ # DX-79: Feedback trigger at threshold
216
+ FEEDBACK_ENABLED=true
217
+ MIN_MESSAGES=30
218
+
219
+ if [[ -f ".claude/settings.local.json" ]]; then
220
+ if command -v jq &> /dev/null; then
221
+ FEEDBACK_ENABLED=$(jq -r '.feedback.enabled // true' .claude/settings.local.json)
222
+ MIN_MESSAGES=$(jq -r '.feedback.min_messages // 30' .claude/settings.local.json)
223
+ fi
224
+ fi
225
+
226
+ if [[ "$FEEDBACK_ENABLED" == "true" && $COUNT -eq $MIN_MESSAGES ]]; then
227
+ echo "<system-reminder>"
228
+ echo "📊 Invar: Auto-triggering usage feedback ($COUNT messages)"
229
+ echo "Consider running /invar-reflect to generate usage feedback."
230
+ echo "</system-reminder>"
231
+ fi
232
+ ```
233
+
234
+ **Pi Hook** (`.pi/hooks/invar.ts`):
235
+
236
+ ```typescript
237
+ // DX-79: Helper to read feedback configuration
238
+ function readFeedbackConfig() {
239
+ try {
240
+ const fs = require("fs");
241
+ const settingsPath = ".claude/settings.local.json";
242
+ if (fs.existsSync(settingsPath)) {
243
+ const settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
244
+ return {
245
+ enabled: settings.feedback?.enabled ?? true,
246
+ min_messages: settings.feedback?.min_messages ?? 30,
247
+ };
248
+ }
249
+ } catch {
250
+ // Ignore errors, use defaults
251
+ }
252
+ return { enabled: true, min_messages: 30 };
253
+ }
254
+
255
+ pi.on("agent_start", async () => {
256
+ msgCount++;
257
+
258
+ // ... protocol refresh logic ...
259
+
260
+ const feedbackConfig = readFeedbackConfig();
261
+ if (msgCount === feedbackConfig.min_messages && feedbackConfig.enabled) {
262
+ pi.send(`<system-reminder>
263
+ 📊 Invar: Auto-triggering usage feedback (${msgCount} messages)
264
+ Consider running /invar-reflect to generate usage feedback.
265
+ </system-reminder>`);
266
+ }
267
+ });
268
+ ```
269
+
270
+ **Installation**: Hooks are automatically installed via `invar init --claude` or `invar init --pi`.
271
+
272
+ ### Stop Hook Implementation
273
+
274
+ Create `.claude/hooks/invar.FeedbackTrigger.sh`:
275
+
276
+ ```bash
277
+ #!/bin/bash
278
+ # Invar Feedback Trigger (Stop Hook Workaround)
279
+ # DX-79 Phase B: Auto-trigger /invar-reflect on session end
280
+
281
+ # Read feedback config
282
+ FEEDBACK_ENABLED=$(jq -r '.feedback.enabled // true' .claude/settings.local.json 2>/dev/null)
283
+ AUTO_TRIGGER=$(jq -r '.feedback.auto_trigger // true' .claude/settings.local.json 2>/dev/null)
284
+
285
+ if [[ "$FEEDBACK_ENABLED" != "true" ]] || [[ "$AUTO_TRIGGER" != "true" ]]; then
286
+ exit 0 # Feedback disabled
287
+ fi
288
+
289
+ # Check session conditions (requires session state tracking)
290
+ STATE_DIR="${CLAUDE_STATE_DIR:-/tmp/invar_hooks_$(id -u)}"
291
+ SESSION_START_FILE="$STATE_DIR/session_start"
292
+ MESSAGE_COUNT_FILE="$STATE_DIR/message_count"
293
+
294
+ # Calculate duration
295
+ if [[ -f "$SESSION_START_FILE" ]]; then
296
+ SESSION_START=$(cat "$SESSION_START_FILE")
297
+ SESSION_END=$(date +%s)
298
+ DURATION_HOURS=$(( (SESSION_END - SESSION_START) / 3600 ))
299
+ else
300
+ DURATION_HOURS=0
301
+ fi
302
+
303
+ # Read message count
304
+ MESSAGE_COUNT=$(cat "$MESSAGE_COUNT_FILE" 2>/dev/null || echo 0)
305
+
306
+ # Check conditions
307
+ if [[ $MESSAGE_COUNT -ge 30 ]] && [[ $DURATION_HOURS -ge 2 ]]; then
308
+ echo ""
309
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
310
+ echo "📊 Invar: Generating usage feedback..."
311
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
312
+ echo ""
313
+ echo "Session complete: $MESSAGE_COUNT messages, ${DURATION_HOURS}h duration"
314
+ echo "Feedback will be saved to .invar/feedback/feedback-$(date +%Y-%m-%d).md"
315
+ echo ""
316
+ echo "To review or share: cat .invar/feedback/feedback-$(date +%Y-%m-%d).md"
317
+ echo "To disable: Set feedback.auto_trigger=false in .claude/settings.local.json"
318
+ fi
319
+
320
+ # Cleanup session state
321
+ rm -rf "$STATE_DIR" 2>/dev/null
322
+ ```
323
+
324
+ **Note**: This workaround provides notification but doesn't actually generate feedback automatically. Full auto-generation requires:
325
+ 1. Claude Code to support skill invocation from hooks, OR
326
+ 2. Hook to write state file that triggers `/invar-reflect` on next user interaction
327
+
328
+ ---
329
+
330
+ ## Configuration Template (for `invar init`)
331
+
332
+ When Phase C is complete, `invar init` will generate this configuration:
333
+
334
+ ```json
335
+ {
336
+ "permissions": {
337
+ "allow": [
338
+ // ... existing permissions ...
339
+ ]
340
+ },
341
+ "hooks": {
342
+ "PostTaskCompletion": [
343
+ {
344
+ "hooks": [
345
+ {
346
+ "type": "skill",
347
+ "skill": "invar-reflect",
348
+ "mode": "silent",
349
+ "conditions": {
350
+ "min_messages": 30,
351
+ "min_duration_hours": 2
352
+ }
353
+ }
354
+ ]
355
+ }
356
+ ],
357
+ // ... existing hooks ...
358
+ },
359
+ "feedback": {
360
+ "enabled": true,
361
+ "auto_trigger": true,
362
+ "retention_days": 90
363
+ }
364
+ }
365
+ ```
366
+
367
+ **Init prompt** (Phase C):
368
+
369
+ ```
370
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
371
+ 📊 Usage Feedback (Optional)
372
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
373
+
374
+ Invar can automatically reflect on tool usage to help improve
375
+ the framework. Feedback is:
376
+ - Stored locally in .invar/feedback/
377
+ - Never sent automatically
378
+ - You decide what (if anything) to share
379
+
380
+ Enable automatic feedback collection? [Y/n]:
381
+ ```
382
+
383
+ ---
384
+
385
+ ## Privacy & Security
386
+
387
+ **What's stored**:
388
+ - Tool usage statistics (counts, success/failure)
389
+ - Error types (NO error messages)
390
+ - Session metadata (duration, message count)
391
+ - User's subjective experience (generated by AI)
392
+
393
+ **What's NOT stored**:
394
+ - Source code
395
+ - File paths (anonymized)
396
+ - Error messages (might contain code)
397
+ - Project-specific details
398
+
399
+ **All data stays local** in `.invar/feedback/`. User reviews before sharing.
400
+
401
+ ---
402
+
403
+ ## Testing (Phase B Acceptance Criteria)
404
+
405
+ ### Manual Testing
406
+
407
+ 1. **Test manual invocation**:
408
+ ```bash
409
+ # In Claude Code session
410
+ /invar-reflect
411
+ ```
412
+ - ✅ Generates feedback file
413
+ - ✅ Saves to `.invar/feedback/feedback-{today}.md`
414
+ - ✅ No errors
415
+
416
+ 2. **Test config disable**:
417
+ ```json
418
+ // .claude/settings.local.json
419
+ { "feedback": { "enabled": false } }
420
+ ```
421
+ - ✅ `/invar-reflect` still works (manual override)
422
+ - ✅ Hook doesn't trigger (when implemented)
423
+
424
+ 3. **Test same-day merge**:
425
+ ```bash
426
+ # Session 1: Morning
427
+ /invar-reflect
428
+ # Creates feedback-2026-01-03.md
429
+
430
+ # Session 2: Afternoon (same day)
431
+ /invar-reflect
432
+ # Updates feedback-2026-01-03.md (not create new file)
433
+ ```
434
+ - ✅ Single file per day
435
+ - ✅ Intelligent merging (semantic understanding)
436
+ - ✅ Daily summary regenerated
437
+
438
+ ### Automated Testing (when hook is implemented)
439
+
440
+ 1. **Test condition thresholds**:
441
+ - Session < 30 messages: Hook doesn't trigger
442
+ - Session < 2 hours: Hook doesn't trigger
443
+ - Session >= 30 messages AND >= 2 hours: Hook triggers
444
+
445
+ 2. **Test silent mode**:
446
+ - Hook triggers in background
447
+ - No interruption to conversation
448
+ - Notification shown only
449
+
450
+ 3. **Test retention**:
451
+ - Files older than 90 days auto-deleted
452
+ - Configurable via `retention_days`
453
+
454
+ ---
455
+
456
+ ## Phase B Status
457
+
458
+
459
+ **Completed** (v1.15.0):
460
+ - ✅ Message Count trigger strategy designed
461
+ - ✅ Cross-platform implementation (Claude Code + Pi)
462
+ - ✅ Shared configuration structure
463
+ - ✅ Hook templates updated
464
+ - ✅ Installation via `invar init`
465
+
466
+ **Replaced PostTaskCompletion with Message Count** because:
467
+ - PostTaskCompletion hook not supported by Claude Code or Pi
468
+ - Message count is universally implementable
469
+ - Simpler, more predictable trigger mechanism
470
+ - User has full control via config
471
+
472
+ **Testing**:
473
+ - Manual `/invar-reflect` invocation: Works
474
+ - Hook trigger at threshold: Implemented
475
+ - Config disable: Honored by both hooks
476
+ - Multi-agent setup: Both hooks installed
477
+
478
+ **Next Steps**:
479
+ - Monitor user feedback on threshold defaults
480
+ - Consider adding reminder messages at other checkpoints (e.g., 60, 90 messages)