loki-mode 5.1.2 → 5.2.0
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.
- package/README.md +1 -1
- package/SKILL.md +26 -2
- package/VERSION +1 -1
- package/bin/postinstall.js +2 -2
- package/docs/ACKNOWLEDGEMENTS.md +63 -1
- package/docs/COMPARISON.md +123 -1
- package/docs/INSTALLATION.md +1 -1
- package/package.json +1 -1
- package/references/core-workflow.md +14 -1
- package/references/memory-system.md +1097 -1
- package/skills/model-selection.md +231 -0
- package/skills/quality-gates.md +283 -0
- package/skills/troubleshooting.md +634 -1
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
- **NEVER** implement without reading task requirements first
|
|
26
26
|
|
|
27
27
|
### Review Anti-Patterns
|
|
28
|
-
- **NEVER** use
|
|
28
|
+
- **NEVER** use opus for reviews (always sonnet for balanced quality/cost)
|
|
29
29
|
- **NEVER** aggregate before all 3 reviewers complete
|
|
30
30
|
- **NEVER** skip re-review after fixes
|
|
31
31
|
|
|
@@ -45,6 +45,73 @@
|
|
|
45
45
|
|
|
46
46
|
---
|
|
47
47
|
|
|
48
|
+
## Rationalization Tables
|
|
49
|
+
|
|
50
|
+
**Source:** Superpowers (obra) - 35K+ stars GitHub project
|
|
51
|
+
|
|
52
|
+
Agents rationalize failures to avoid acknowledging mistakes. This table provides explicit counters to common rationalizations.
|
|
53
|
+
|
|
54
|
+
### Common Agent Rationalizations
|
|
55
|
+
|
|
56
|
+
| Rationalization | Why It's Wrong | Required Action |
|
|
57
|
+
|-----------------|----------------|-----------------|
|
|
58
|
+
| "I'll refactor later" | Technical debt accumulates, later never comes | Refactor now or reduce scope |
|
|
59
|
+
| "This is just an edge case" | Edge cases are features users encounter | Handle edge case or document limitation |
|
|
60
|
+
| "The tests are flaky" | Flaky tests hide real bugs | Fix flaky test before proceeding |
|
|
61
|
+
| "It works on my machine" | Only CI environment matters | Must pass CI |
|
|
62
|
+
| "This is a temporary workaround" | Temporary becomes permanent | No workarounds without issue filed |
|
|
63
|
+
| "The spec is unclear" | Unclear spec = ask for clarification | Block until spec clarified |
|
|
64
|
+
| "This is out of scope" | Scope creep rationalization | Verify against `.loki/queue/` task definition |
|
|
65
|
+
| "We can optimize later" | Performance issues compound over time | Implement acceptable performance OR document as known limitation |
|
|
66
|
+
| "This is good enough" | Premature completion before verification | Run full test suite before claiming completion |
|
|
67
|
+
| "The error is benign" | Dismissing errors without investigation | Investigate error, document root cause |
|
|
68
|
+
| "I already verified this" | Claiming verification without evidence | Show command output or test results |
|
|
69
|
+
| "The documentation is outdated" | Dismissing doc conflicts without checking | Verify claim, update docs if true, follow docs if false |
|
|
70
|
+
|
|
71
|
+
### Red Flag Detection Patterns
|
|
72
|
+
|
|
73
|
+
Behaviors that indicate rationalization in progress:
|
|
74
|
+
|
|
75
|
+
**Hedging Language**
|
|
76
|
+
- "probably" - Replace with verified facts
|
|
77
|
+
- "should be fine" - Replace with test results
|
|
78
|
+
- "most likely" - Replace with confirmed behavior
|
|
79
|
+
- "I think" - Replace with verified knowledge
|
|
80
|
+
|
|
81
|
+
**Minimization Language**
|
|
82
|
+
- "just a small change" - All changes require verification
|
|
83
|
+
- "simple fix" - Complexity is determined by test results
|
|
84
|
+
- "minor update" - Impact is determined by CI, not assumption
|
|
85
|
+
- "quick tweak" - Speed claims require evidence
|
|
86
|
+
|
|
87
|
+
**Scope Changes Mid-Task**
|
|
88
|
+
- Expanding scope without explicit justification
|
|
89
|
+
- Reducing scope without documenting limitations
|
|
90
|
+
- Changing requirements interpretation silently
|
|
91
|
+
- Adding "nice to have" features not in spec
|
|
92
|
+
|
|
93
|
+
**Verification Skipping**
|
|
94
|
+
- Moving to next task without running tests
|
|
95
|
+
- Claiming success without evidence
|
|
96
|
+
- Dismissing failed checks as irrelevant
|
|
97
|
+
- "The other component handles this" - Verify integration, don't assume
|
|
98
|
+
|
|
99
|
+
**Unverified Claims**
|
|
100
|
+
- "I checked and it's fine" without showing output
|
|
101
|
+
- Referencing tests that were not actually run
|
|
102
|
+
- Claiming compatibility without testing
|
|
103
|
+
- Asserting behavior without demonstration
|
|
104
|
+
|
|
105
|
+
### Enforcement Protocol
|
|
106
|
+
|
|
107
|
+
When rationalization is detected:
|
|
108
|
+
1. **Stop** - Do not proceed with the rationalized action
|
|
109
|
+
2. **Identify** - Name the specific rationalization from the table
|
|
110
|
+
3. **Counter** - Apply the required action from the table
|
|
111
|
+
4. **Document** - Log the rationalization attempt in `.loki/memory/episodic/`
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
48
115
|
## Multi-Tiered Fallback System
|
|
49
116
|
|
|
50
117
|
### Model-Level Fallbacks
|
|
@@ -86,6 +153,202 @@ rate_limit_handling:
|
|
|
86
153
|
state_file: ".loki/state/circuit-breakers.json"
|
|
87
154
|
```
|
|
88
155
|
|
|
156
|
+
### Circuit Breaker System
|
|
157
|
+
|
|
158
|
+
The circuit breaker prevents cascading failures by temporarily disabling operations that are repeatedly failing.
|
|
159
|
+
|
|
160
|
+
#### JSON Schema: `.loki/state/circuit-breakers.json`
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
165
|
+
"type": "object",
|
|
166
|
+
"additionalProperties": {
|
|
167
|
+
"type": "object",
|
|
168
|
+
"required": ["state", "failure_count", "last_failure_time", "last_state_change"],
|
|
169
|
+
"properties": {
|
|
170
|
+
"state": {
|
|
171
|
+
"type": "string",
|
|
172
|
+
"enum": ["CLOSED", "OPEN", "HALF_OPEN"],
|
|
173
|
+
"description": "Current circuit breaker state"
|
|
174
|
+
},
|
|
175
|
+
"failure_count": {
|
|
176
|
+
"type": "integer",
|
|
177
|
+
"minimum": 0,
|
|
178
|
+
"description": "Number of failures in current window"
|
|
179
|
+
},
|
|
180
|
+
"success_count": {
|
|
181
|
+
"type": "integer",
|
|
182
|
+
"minimum": 0,
|
|
183
|
+
"description": "Consecutive successes in HALF_OPEN state"
|
|
184
|
+
},
|
|
185
|
+
"last_failure_time": {
|
|
186
|
+
"type": "string",
|
|
187
|
+
"format": "date-time",
|
|
188
|
+
"description": "ISO 8601 timestamp of last failure"
|
|
189
|
+
},
|
|
190
|
+
"last_state_change": {
|
|
191
|
+
"type": "string",
|
|
192
|
+
"format": "date-time",
|
|
193
|
+
"description": "ISO 8601 timestamp of last state transition"
|
|
194
|
+
},
|
|
195
|
+
"cooldown_until": {
|
|
196
|
+
"type": "string",
|
|
197
|
+
"format": "date-time",
|
|
198
|
+
"description": "ISO 8601 timestamp when OPEN state expires"
|
|
199
|
+
},
|
|
200
|
+
"failure_window_start": {
|
|
201
|
+
"type": "string",
|
|
202
|
+
"format": "date-time",
|
|
203
|
+
"description": "Start of 60s failure counting window"
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
#### Example File
|
|
211
|
+
|
|
212
|
+
```json
|
|
213
|
+
{
|
|
214
|
+
"api/claude": {
|
|
215
|
+
"state": "CLOSED",
|
|
216
|
+
"failure_count": 0,
|
|
217
|
+
"success_count": 0,
|
|
218
|
+
"last_failure_time": null,
|
|
219
|
+
"last_state_change": "2025-01-20T10:30:00Z",
|
|
220
|
+
"cooldown_until": null,
|
|
221
|
+
"failure_window_start": null
|
|
222
|
+
},
|
|
223
|
+
"api/openai": {
|
|
224
|
+
"state": "OPEN",
|
|
225
|
+
"failure_count": 3,
|
|
226
|
+
"success_count": 0,
|
|
227
|
+
"last_failure_time": "2025-01-20T10:35:42Z",
|
|
228
|
+
"last_state_change": "2025-01-20T10:35:42Z",
|
|
229
|
+
"cooldown_until": "2025-01-20T10:40:42Z",
|
|
230
|
+
"failure_window_start": "2025-01-20T10:34:50Z"
|
|
231
|
+
},
|
|
232
|
+
"api/gemini": {
|
|
233
|
+
"state": "HALF_OPEN",
|
|
234
|
+
"failure_count": 0,
|
|
235
|
+
"success_count": 1,
|
|
236
|
+
"last_failure_time": "2025-01-20T10:25:00Z",
|
|
237
|
+
"last_state_change": "2025-01-20T10:30:00Z",
|
|
238
|
+
"cooldown_until": null,
|
|
239
|
+
"failure_window_start": null
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
#### State Machine
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
+-----------+
|
|
248
|
+
| CLOSED | <-- Normal operation
|
|
249
|
+
| | Requests flow through
|
|
250
|
+
+-----+-----+
|
|
251
|
+
|
|
|
252
|
+
| 3 failures within 60s
|
|
253
|
+
v
|
|
254
|
+
+-----------+
|
|
255
|
+
| OPEN | <-- Circuit tripped
|
|
256
|
+
| | All requests BLOCKED
|
|
257
|
+
+-----+-----+
|
|
258
|
+
|
|
|
259
|
+
| After cooldown (300s)
|
|
260
|
+
v
|
|
261
|
+
+-----------+
|
|
262
|
+
| HALF_OPEN | <-- Testing recovery
|
|
263
|
+
| | Limited requests allowed
|
|
264
|
+
+-----+-----+
|
|
265
|
+
/|\
|
|
266
|
+
/ | \
|
|
267
|
+
success(3) / | \ any failure
|
|
268
|
+
v | v
|
|
269
|
+
+-------+ | +-------+
|
|
270
|
+
|CLOSED | | | OPEN |
|
|
271
|
+
+-------+ | +-------+
|
|
272
|
+
|
|
|
273
|
+
partial success
|
|
274
|
+
(stay in HALF_OPEN)
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
#### State Behaviors
|
|
278
|
+
|
|
279
|
+
| State | Behavior | Requests | Transitions |
|
|
280
|
+
|-------|----------|----------|-------------|
|
|
281
|
+
| **CLOSED** | Normal operation | All requests pass through | -> OPEN: 3+ failures in 60s window |
|
|
282
|
+
| **OPEN** | Circuit tripped | All requests immediately rejected with cached error | -> HALF_OPEN: After 300s cooldown expires |
|
|
283
|
+
| **HALF_OPEN** | Recovery testing | 1 request allowed per 10s interval | -> CLOSED: 3 consecutive successes |
|
|
284
|
+
| | | | -> OPEN: Any single failure |
|
|
285
|
+
|
|
286
|
+
#### State Transition Rules
|
|
287
|
+
|
|
288
|
+
**CLOSED -> OPEN**
|
|
289
|
+
- Trigger: `failure_count >= 3` within 60-second `failure_window`
|
|
290
|
+
- Action: Set `cooldown_until = now + 300s`
|
|
291
|
+
- Effect: All requests return immediately with last error
|
|
292
|
+
|
|
293
|
+
**OPEN -> HALF_OPEN**
|
|
294
|
+
- Trigger: `current_time >= cooldown_until`
|
|
295
|
+
- Action: Reset `failure_count = 0`, `success_count = 0`
|
|
296
|
+
- Effect: One probe request allowed through
|
|
297
|
+
|
|
298
|
+
**HALF_OPEN -> CLOSED**
|
|
299
|
+
- Trigger: `success_count >= 3` (consecutive)
|
|
300
|
+
- Action: Reset all counters, clear timestamps
|
|
301
|
+
- Effect: Resume normal operation
|
|
302
|
+
|
|
303
|
+
**HALF_OPEN -> OPEN**
|
|
304
|
+
- Trigger: Any single failure
|
|
305
|
+
- Action: Set new `cooldown_until = now + 300s`
|
|
306
|
+
- Effect: Back to blocking all requests
|
|
307
|
+
|
|
308
|
+
#### Recovery Protocol
|
|
309
|
+
|
|
310
|
+
When a circuit breaker is OPEN:
|
|
311
|
+
|
|
312
|
+
1. **Check State**
|
|
313
|
+
```bash
|
|
314
|
+
cat .loki/state/circuit-breakers.json | jq '.["api/claude"]'
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
2. **Calculate Wait Time**
|
|
318
|
+
```bash
|
|
319
|
+
# Check cooldown_until timestamp
|
|
320
|
+
# Wait until: cooldown_until - current_time
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
3. **Reduce Load**
|
|
324
|
+
- Reduce parallel agent count from 5 to 2
|
|
325
|
+
- Disable non-critical background operations
|
|
326
|
+
- Queue non-urgent requests
|
|
327
|
+
|
|
328
|
+
4. **Monitor HALF_OPEN**
|
|
329
|
+
- Watch for probe request results
|
|
330
|
+
- Do not send additional requests during probing
|
|
331
|
+
|
|
332
|
+
5. **Gradual Recovery**
|
|
333
|
+
- After CLOSED state restored, gradually increase parallelism
|
|
334
|
+
- Start at 50% capacity, increase by 25% every 60s
|
|
335
|
+
- Monitor for new failures during ramp-up
|
|
336
|
+
|
|
337
|
+
6. **Log Recovery**
|
|
338
|
+
```bash
|
|
339
|
+
echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) Circuit recovered: api/claude" >> .loki/logs/circuit-recovery.log
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
#### Configuration Tuning
|
|
343
|
+
|
|
344
|
+
| Parameter | Default | Description | When to Adjust |
|
|
345
|
+
|-----------|---------|-------------|----------------|
|
|
346
|
+
| `threshold` | 3 | Failures to trip circuit | Increase for flaky networks |
|
|
347
|
+
| `window` | 60s | Failure counting window | Increase for bursty errors |
|
|
348
|
+
| `cooldown` | 300s | OPEN state duration | Decrease if errors resolve quickly |
|
|
349
|
+
| `half_open_interval` | 10s | Time between probe requests | Increase for slow recovery APIs |
|
|
350
|
+
| `recovery_threshold` | 3 | Successes to close circuit | Increase for critical paths |
|
|
351
|
+
|
|
89
352
|
---
|
|
90
353
|
|
|
91
354
|
## Recovery Procedures
|
|
@@ -107,3 +370,373 @@ rate_limit_handling:
|
|
|
107
370
|
2. Check if test is flaky vs real failure
|
|
108
371
|
3. Roll back to last passing commit if needed
|
|
109
372
|
4. Fix and re-run full test suite
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Dead Letter Queue
|
|
377
|
+
|
|
378
|
+
Tasks that fail repeatedly (5+ attempts) are moved to the dead-letter queue for structured handling. This prevents infinite retry loops while preserving failed task context for recovery or human review.
|
|
379
|
+
|
|
380
|
+
### Location
|
|
381
|
+
|
|
382
|
+
```
|
|
383
|
+
.loki/queue/dead-letter.json
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### Schema
|
|
387
|
+
|
|
388
|
+
```json
|
|
389
|
+
{
|
|
390
|
+
"tasks": [
|
|
391
|
+
{
|
|
392
|
+
"task_id": "task-uuid-here",
|
|
393
|
+
"original_queue": "pending|in-progress",
|
|
394
|
+
"failure_count": 5,
|
|
395
|
+
"first_failure": "2026-01-25T10:00:00Z",
|
|
396
|
+
"last_failure": "2026-01-25T14:30:00Z",
|
|
397
|
+
"error_summary": "Brief description of the failure pattern",
|
|
398
|
+
"attempts": [
|
|
399
|
+
{
|
|
400
|
+
"attempt_number": 1,
|
|
401
|
+
"timestamp": "2026-01-25T10:00:00Z",
|
|
402
|
+
"approach": "initial implementation",
|
|
403
|
+
"error_type": "test_failure|timeout|dependency|validation",
|
|
404
|
+
"error_message": "Full error text",
|
|
405
|
+
"agent_id": "agent-that-attempted"
|
|
406
|
+
}
|
|
407
|
+
],
|
|
408
|
+
"recovery_strategy": "retry_with_simpler_approach|dependency_blocked|requires_human_review|permanent_abandon",
|
|
409
|
+
"task_data": {
|
|
410
|
+
"title": "Original task title",
|
|
411
|
+
"description": "Original task description",
|
|
412
|
+
"dependencies": [],
|
|
413
|
+
"priority": "high|medium|low"
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
],
|
|
417
|
+
"metadata": {
|
|
418
|
+
"last_reviewed": "2026-01-25T08:00:00Z",
|
|
419
|
+
"total_abandoned": 0,
|
|
420
|
+
"total_recovered": 0
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Processing Protocol
|
|
426
|
+
|
|
427
|
+
**Daily Review Schedule:**
|
|
428
|
+
1. At session start, check if `metadata.last_reviewed` is >24h old
|
|
429
|
+
2. If stale, process dead-letter queue before new work
|
|
430
|
+
3. Update `last_reviewed` timestamp after processing
|
|
431
|
+
|
|
432
|
+
**Review Process:**
|
|
433
|
+
```
|
|
434
|
+
For each task in dead-letter.json:
|
|
435
|
+
1. Analyze failure pattern across all attempts
|
|
436
|
+
2. Check if any retry conditions now apply
|
|
437
|
+
3. Apply recovery strategy based on failure analysis
|
|
438
|
+
4. Either: retry, escalate, or permanently abandon
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Retry Conditions
|
|
442
|
+
|
|
443
|
+
A dead-letter task can be retried when:
|
|
444
|
+
|
|
445
|
+
| Condition | Action |
|
|
446
|
+
|-----------|--------|
|
|
447
|
+
| Dependency now available | Move back to pending queue with `recovery_strategy: "dependency_resolved"` |
|
|
448
|
+
| New approach identified | Reset `failure_count` to 0, document new approach in attempts |
|
|
449
|
+
| Simpler scope defined | Create new task with reduced scope, link to original |
|
|
450
|
+
| Blocking bug fixed | Re-queue with reference to fix commit |
|
|
451
|
+
|
|
452
|
+
### Permanent Abandon Criteria
|
|
453
|
+
|
|
454
|
+
A task should be permanently abandoned when:
|
|
455
|
+
|
|
456
|
+
| Criteria | Justification |
|
|
457
|
+
|----------|---------------|
|
|
458
|
+
| 10+ total attempts | Diminishing returns, likely architectural issue |
|
|
459
|
+
| Same error across 3 different approaches | Fundamental blocker, not solvable with current tools |
|
|
460
|
+
| Dependency will never be available | External blocker with no workaround |
|
|
461
|
+
| Scope no longer relevant | Project direction changed |
|
|
462
|
+
| Human explicitly abandons | Documented decision to deprioritize |
|
|
463
|
+
|
|
464
|
+
When abandoning, move task to `.loki/queue/abandoned.json` with reason documented.
|
|
465
|
+
|
|
466
|
+
### Recovery Strategies
|
|
467
|
+
|
|
468
|
+
| Strategy | When to Use | Agent Action |
|
|
469
|
+
|----------|-------------|--------------|
|
|
470
|
+
| `retry_with_simpler_approach` | Complex implementation failed multiple times | Break into smaller subtasks, reduce scope, use simpler patterns |
|
|
471
|
+
| `dependency_blocked` | Task needs output from another task that failed | Wait for dependency resolution, check daily |
|
|
472
|
+
| `requires_human_review` | Security decision, unclear spec, or irreversible action | Log to `.loki/escalations/` and notify, do not retry |
|
|
473
|
+
| `permanent_abandon` | Met abandon criteria above | Move to `abandoned.json`, document reason, move on |
|
|
474
|
+
|
|
475
|
+
### Human Escalation Triggers
|
|
476
|
+
|
|
477
|
+
Automatically escalate to human review when:
|
|
478
|
+
|
|
479
|
+
1. **Security-critical task fails** - Any task touching auth, secrets, or permissions
|
|
480
|
+
2. **Data loss risk** - Task involves deletion or migration with failed rollback
|
|
481
|
+
3. **3+ tasks with same root cause** - Systemic issue requiring architectural review
|
|
482
|
+
4. **Confidence below 0.30** - Agent cannot determine correct recovery strategy
|
|
483
|
+
5. **External service dependency** - Requires API keys, credentials, or third-party action
|
|
484
|
+
6. **Spec ambiguity detected** - Multiple valid interpretations, need human decision
|
|
485
|
+
|
|
486
|
+
**Escalation Format:**
|
|
487
|
+
```
|
|
488
|
+
File: .loki/escalations/{timestamp}-{task_id}.md
|
|
489
|
+
|
|
490
|
+
## Escalation: {task_title}
|
|
491
|
+
|
|
492
|
+
**Task ID:** {task_id}
|
|
493
|
+
**Failure Count:** {count}
|
|
494
|
+
**Trigger:** {escalation_reason}
|
|
495
|
+
|
|
496
|
+
### Failure Summary
|
|
497
|
+
{error_summary}
|
|
498
|
+
|
|
499
|
+
### Attempts Log
|
|
500
|
+
{formatted attempts array}
|
|
501
|
+
|
|
502
|
+
### Agent Analysis
|
|
503
|
+
{what was tried and why it failed}
|
|
504
|
+
|
|
505
|
+
### Recommended Options
|
|
506
|
+
1. {option with tradeoffs}
|
|
507
|
+
2. {option with tradeoffs}
|
|
508
|
+
|
|
509
|
+
### Awaiting
|
|
510
|
+
Human decision on recovery path.
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
### Agent Workflow for Dead Letter Processing
|
|
514
|
+
|
|
515
|
+
```
|
|
516
|
+
1. READ dead-letter.json at session start
|
|
517
|
+
|
|
518
|
+
2. FOR each task:
|
|
519
|
+
a. Analyze failure pattern across all attempts
|
|
520
|
+
b. Check if any retry conditions now apply
|
|
521
|
+
c. IF retry condition met:
|
|
522
|
+
- Move task back to pending queue
|
|
523
|
+
- Document recovery reason
|
|
524
|
+
- Reset failure_count if new approach
|
|
525
|
+
d. ELSE IF meets abandon criteria:
|
|
526
|
+
- Move to abandoned.json
|
|
527
|
+
- Document reason
|
|
528
|
+
e. ELSE IF needs human:
|
|
529
|
+
- Create escalation file
|
|
530
|
+
- Leave in dead-letter queue with "requires_human_review" strategy
|
|
531
|
+
f. ELSE:
|
|
532
|
+
- Leave in queue for next review cycle
|
|
533
|
+
|
|
534
|
+
3. UPDATE metadata.last_reviewed
|
|
535
|
+
|
|
536
|
+
4. CONTINUE to normal task processing
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
---
|
|
540
|
+
|
|
541
|
+
## Signal Processing
|
|
542
|
+
|
|
543
|
+
Signals are inter-process communication files in `.loki/signals/` that trigger automated responses.
|
|
544
|
+
|
|
545
|
+
### DRIFT_DETECTED Signal
|
|
546
|
+
|
|
547
|
+
**Purpose:** Alerts when agent actions diverge from original task goal.
|
|
548
|
+
|
|
549
|
+
**Schema:**
|
|
550
|
+
```json
|
|
551
|
+
{
|
|
552
|
+
"timestamp": "2026-01-25T10:30:00Z",
|
|
553
|
+
"task_id": "task-042",
|
|
554
|
+
"planned_action": "Implement user authentication",
|
|
555
|
+
"detected_drift": "Started refactoring database schema instead",
|
|
556
|
+
"severity": "medium",
|
|
557
|
+
"agent": "eng-001-backend-api",
|
|
558
|
+
"original_goal": "Add login endpoint per OpenAPI spec",
|
|
559
|
+
"drift_distance": 2
|
|
560
|
+
}
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
**Fields:**
|
|
564
|
+
- `timestamp` - ISO 8601 timestamp of detection
|
|
565
|
+
- `task_id` - Current task from queue
|
|
566
|
+
- `planned_action` - What agent intended to do
|
|
567
|
+
- `detected_drift` - What agent started doing instead
|
|
568
|
+
- `severity` - low/medium/high/critical
|
|
569
|
+
- `agent` - Agent ID that detected drift
|
|
570
|
+
- `original_goal` - Goal from `.loki/queue/current-task.json`
|
|
571
|
+
- `drift_distance` - How many steps off-track (1=adjacent, 3+=severe)
|
|
572
|
+
|
|
573
|
+
**Processing Rules:**
|
|
574
|
+
|
|
575
|
+
| Condition | Action |
|
|
576
|
+
|-----------|--------|
|
|
577
|
+
| Any drift detected | Return to REASON phase immediately |
|
|
578
|
+
| 1 drift in task | Log warning, continue with corrected action |
|
|
579
|
+
| 2 drifts in same task | Escalate to orchestrator for task review |
|
|
580
|
+
| 3+ drifts accumulated | Trigger context clear + full state reload |
|
|
581
|
+
| High/Critical severity | Pause task, dispatch opus reviewer |
|
|
582
|
+
|
|
583
|
+
**Automated Responses:**
|
|
584
|
+
```yaml
|
|
585
|
+
immediate:
|
|
586
|
+
- Stop current action
|
|
587
|
+
- Log to .loki/signals/DRIFT_DETECTED (append-only log)
|
|
588
|
+
- Return to REASON phase
|
|
589
|
+
- Re-read .loki/queue/current-task.json
|
|
590
|
+
|
|
591
|
+
accumulated_threshold: 3
|
|
592
|
+
accumulated_action:
|
|
593
|
+
- Create CONTEXT_CLEAR_REQUESTED
|
|
594
|
+
- Wait for wrapper to reset context
|
|
595
|
+
- Resume with fresh context + ledger state
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
**How to Write:**
|
|
599
|
+
```bash
|
|
600
|
+
# Agent-side: append to drift log
|
|
601
|
+
cat >> .loki/signals/DRIFT_DETECTED << EOF
|
|
602
|
+
{"timestamp":"$(date -u +%Y-%m-%dT%H:%M:%SZ)","task_id":"task-042","severity":"medium","detected_drift":"description"}
|
|
603
|
+
EOF
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
---
|
|
607
|
+
|
|
608
|
+
### CONTEXT_CLEAR_REQUESTED Signal
|
|
609
|
+
|
|
610
|
+
**Purpose:** Agent requests context window reset while preserving state.
|
|
611
|
+
|
|
612
|
+
**Schema:** File presence only (empty file is sufficient).
|
|
613
|
+
|
|
614
|
+
**When to Create:**
|
|
615
|
+
- Context feels heavy/slow
|
|
616
|
+
- After 25+ iterations
|
|
617
|
+
- Conversation history exceeds 50KB
|
|
618
|
+
- Agent detects own confusion or loops
|
|
619
|
+
- 3+ accumulated DRIFT_DETECTED events
|
|
620
|
+
|
|
621
|
+
**Processing (by run.sh wrapper):**
|
|
622
|
+
1. Detect signal file
|
|
623
|
+
2. Load ledger context from `.loki/memory/ledgers/`
|
|
624
|
+
3. Load recent handoffs from `.loki/memory/handoffs/`
|
|
625
|
+
4. Delete signal file
|
|
626
|
+
5. Start new Claude session with injected context
|
|
627
|
+
6. Continue from last CONTINUITY.md state
|
|
628
|
+
|
|
629
|
+
**How to Create:**
|
|
630
|
+
```bash
|
|
631
|
+
touch .loki/signals/CONTEXT_CLEAR_REQUESTED
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
**Thresholds:**
|
|
635
|
+
| Trigger | Threshold |
|
|
636
|
+
|---------|-----------|
|
|
637
|
+
| Iteration count | Every 25 iterations (compaction reminder) |
|
|
638
|
+
| Drift accumulation | 3+ DRIFT_DETECTED events |
|
|
639
|
+
| Agent self-assessment | "Context feels heavy" |
|
|
640
|
+
| Error loop detection | Same error 3+ times |
|
|
641
|
+
|
|
642
|
+
---
|
|
643
|
+
|
|
644
|
+
### HUMAN_REVIEW_NEEDED Signal
|
|
645
|
+
|
|
646
|
+
**Purpose:** Escalate to human when autonomous action is inappropriate.
|
|
647
|
+
|
|
648
|
+
**Schema:**
|
|
649
|
+
```json
|
|
650
|
+
{
|
|
651
|
+
"timestamp": "2026-01-25T10:30:00Z",
|
|
652
|
+
"reason": "security_decision",
|
|
653
|
+
"task_id": "task-099",
|
|
654
|
+
"context": "Requires AWS production credentials",
|
|
655
|
+
"severity": "critical",
|
|
656
|
+
"agent": "eng-001-infra",
|
|
657
|
+
"blocking": true,
|
|
658
|
+
"alternatives_considered": [
|
|
659
|
+
"Use staging credentials (rejected: insufficient for test)",
|
|
660
|
+
"Mock credentials (rejected: integration test requires real auth)"
|
|
661
|
+
]
|
|
662
|
+
}
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
**When to Create:**
|
|
666
|
+
- Confidence score below 0.40 on critical decision
|
|
667
|
+
- Security-critical operations (production credentials, key rotation)
|
|
668
|
+
- Irreversible operations without clear rollback
|
|
669
|
+
- 3+ consecutive failures on same task
|
|
670
|
+
- Ambiguous requirements that block progress
|
|
671
|
+
- Cost decisions above threshold (cloud resources > $100/hour)
|
|
672
|
+
|
|
673
|
+
**Processing:**
|
|
674
|
+
```yaml
|
|
675
|
+
immediate:
|
|
676
|
+
- Stop current task (do not proceed)
|
|
677
|
+
- Log to .loki/signals/HUMAN_REVIEW_NEEDED
|
|
678
|
+
- Move task to blocked state
|
|
679
|
+
- Continue with other unblocked tasks if available
|
|
680
|
+
|
|
681
|
+
human_action_required:
|
|
682
|
+
- Review signal file
|
|
683
|
+
- Make decision
|
|
684
|
+
- Either:
|
|
685
|
+
- Create .loki/signals/HUMAN_APPROVED with decision
|
|
686
|
+
- Update task with clarification
|
|
687
|
+
- Cancel task
|
|
688
|
+
|
|
689
|
+
timeout: 24 hours
|
|
690
|
+
timeout_action:
|
|
691
|
+
- Move task to dead letter queue
|
|
692
|
+
- Alert via configured notification channel
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
**How to Create:**
|
|
696
|
+
```bash
|
|
697
|
+
cat > .loki/signals/HUMAN_REVIEW_NEEDED << EOF
|
|
698
|
+
{
|
|
699
|
+
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
700
|
+
"reason": "security_decision",
|
|
701
|
+
"task_id": "task-099",
|
|
702
|
+
"context": "Description of what needs review",
|
|
703
|
+
"severity": "high",
|
|
704
|
+
"blocking": true
|
|
705
|
+
}
|
|
706
|
+
EOF
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
---
|
|
710
|
+
|
|
711
|
+
### Other Workflow Signals
|
|
712
|
+
|
|
713
|
+
These signals coordinate parallel worktrees (see `skills/parallel-workflows.md`):
|
|
714
|
+
|
|
715
|
+
| Signal | Purpose | Creates | Consumes |
|
|
716
|
+
|--------|---------|---------|----------|
|
|
717
|
+
| `FEATURE_READY_{name}` | Feature ready for testing | Feature stream | Testing stream |
|
|
718
|
+
| `TESTS_PASSED_{name}` | Tests green for feature | Testing stream | Merge stream |
|
|
719
|
+
| `TESTS_FAILED_{name}` | Tests failed for feature | Testing stream | Feature stream |
|
|
720
|
+
| `MERGE_REQUESTED_{branch}` | Request merge to main | Testing stream | Orchestrator |
|
|
721
|
+
| `DOCS_NEEDED` | Documentation required | Any stream | Docs stream |
|
|
722
|
+
| `BLOG_POST_QUEUED` | Significant change for blog | Docs stream | Blog stream |
|
|
723
|
+
| `PLAN_APPROVED` | Human approved plan (plan-first mode) | Human | Orchestrator |
|
|
724
|
+
|
|
725
|
+
---
|
|
726
|
+
|
|
727
|
+
### Signal Directory Structure
|
|
728
|
+
|
|
729
|
+
```
|
|
730
|
+
.loki/signals/
|
|
731
|
+
DRIFT_DETECTED # Append-only log (JSON lines)
|
|
732
|
+
CONTEXT_CLEAR_REQUESTED # Presence flag (empty file OK)
|
|
733
|
+
HUMAN_REVIEW_NEEDED # JSON with review context
|
|
734
|
+
HUMAN_APPROVED # JSON with decision
|
|
735
|
+
FEATURE_READY_auth # Worktree signal
|
|
736
|
+
FEATURE_READY_api # Worktree signal
|
|
737
|
+
TESTS_PASSED_auth # Test result signal
|
|
738
|
+
MERGE_REQUESTED_auth # Merge request signal
|
|
739
|
+
PLAN_APPROVED # Plan mode approval
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
**Cleanup:** Signals are consumed (deleted) by their processing handler. Only `DRIFT_DETECTED` persists as an append-only log for audit purposes.
|