loki-mode 5.1.3 → 5.2.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.
@@ -25,7 +25,7 @@
25
25
  - **NEVER** implement without reading task requirements first
26
26
 
27
27
  ### Review Anti-Patterns
28
- - **NEVER** use sonnet for reviews (always opus for deep analysis)
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.