oh-my-customcode 0.78.0 → 0.78.1

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 CHANGED
@@ -235,7 +235,7 @@ Key rules: R010 (orchestrator never writes files), R009 (parallel execution mand
235
235
 
236
236
  ---
237
237
 
238
- ### Guides (31)
238
+ ### Guides (32)
239
239
 
240
240
  Reference documentation covering best practices, architecture decisions, and integration patterns. Located in `guides/` at project root, covering topics from agent design to CI/CD to observability.
241
241
 
@@ -292,7 +292,7 @@ your-project/
292
292
  │ ├── specs/ # Extracted canonical specs
293
293
  │ ├── contexts/ # 4 shared context files
294
294
  │ └── ontology/ # Knowledge graph for RAG
295
- └── guides/ # 31 reference documents
295
+ └── guides/ # 32 reference documents
296
296
  ```
297
297
 
298
298
  ---
package/dist/cli/index.js CHANGED
@@ -9325,7 +9325,7 @@ var init_package = __esm(() => {
9325
9325
  workspaces: [
9326
9326
  "packages/*"
9327
9327
  ],
9328
- version: "0.78.0",
9328
+ version: "0.78.1",
9329
9329
  description: "Batteries-included agent harness for Claude Code",
9330
9330
  type: "module",
9331
9331
  bin: {
package/dist/index.js CHANGED
@@ -1820,7 +1820,7 @@ var package_default = {
1820
1820
  workspaces: [
1821
1821
  "packages/*"
1822
1822
  ],
1823
- version: "0.78.0",
1823
+ version: "0.78.1",
1824
1824
  description: "Batteries-included agent harness for Claude Code",
1825
1825
  type: "module",
1826
1826
  bin: {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "workspaces": [
4
4
  "packages/*"
5
5
  ],
6
- "version": "0.78.0",
6
+ "version": "0.78.1",
7
7
  "description": "Batteries-included agent harness for Claude Code",
8
8
  "type": "module",
9
9
  "bin": {
@@ -189,7 +189,7 @@
189
189
  },
190
190
  {
191
191
  "type": "command",
192
- "command": "count_file=\"/tmp/.claude-loop-count-$PPID\"; if [ -f \"$count_file\" ]; then last_mod=$(stat -c%Y \"$count_file\" 2>/dev/null || stat -f%m \"$count_file\" 2>/dev/null || echo 0); now=$(date +%s); if [ $((now - last_mod)) -gt 60 ]; then echo 0 > \"$count_file\"; fi; fi; count=$(cat \"$count_file\" 2>/dev/null || echo 0); count=$((count + 1)); echo \"$count\" > \"$count_file\"; if [ \"$count\" -ge 4 ]; then echo '[AutoContinue] SAFETY: auto-continue limit (3) reached. Pausing.' >&2; fi; cat"
192
+ "command": "bash .claude/hooks/scripts/auto-continue-guard.sh"
193
193
  },
194
194
  {
195
195
  "type": "prompt",
@@ -0,0 +1,33 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ # Auto-Continue Guard
5
+ # Trigger: SubagentStop
6
+ # Purpose: Count consecutive subagent completions and warn when auto-continue limit reached
7
+ # Protocol: stdin JSON -> count check -> stdout pass-through, exit 0 always (R021)
8
+
9
+ input=$(cat)
10
+
11
+ count_file="/tmp/.claude-loop-count-${PPID}"
12
+
13
+ # Reset counter if stale (>60s since last update)
14
+ if [ -f "$count_file" ]; then
15
+ last_mod=$(stat -c%Y "$count_file" 2>/dev/null || stat -f%m "$count_file" 2>/dev/null || echo 0)
16
+ now=$(date +%s)
17
+ if [ $((now - last_mod)) -gt 60 ]; then
18
+ echo 0 > "$count_file"
19
+ fi
20
+ fi
21
+
22
+ # Increment counter
23
+ count=$(cat "$count_file" 2>/dev/null || echo 0)
24
+ count=$((count + 1))
25
+ echo "$count" > "$count_file"
26
+
27
+ # Warn if limit reached
28
+ if [ "$count" -ge 4 ]; then
29
+ echo '[AutoContinue] SAFETY: auto-continue limit (3) reached. Pausing.' >&2
30
+ fi
31
+
32
+ echo "$input"
33
+ exit 0
@@ -156,7 +156,7 @@ project/
156
156
  | +-- rules/ # 전역 규칙 (R000-R021)
157
157
  | +-- hooks/ # 훅 스크립트 (보안, 검증, HUD)
158
158
  | +-- contexts/ # 컨텍스트 파일 (ecomode)
159
- +-- guides/ # 레퍼런스 문서 (31 토픽)
159
+ +-- guides/ # 레퍼런스 문서 (32 토픽)
160
160
  ```
161
161
 
162
162
  ## 오케스트레이션
@@ -0,0 +1,135 @@
1
+ # Hook Data Flow: Stall Detection Pipeline
2
+
3
+ Added in v0.78.0. Documents the three-script pipeline that detects stalled parallel agents and emits R009 Adaptive Parallel Splitting advisories.
4
+
5
+ Related rule: `.claude/rules/MUST-parallel-execution.md` (R009 Adaptive Parallel Splitting section)
6
+
7
+ ---
8
+
9
+ ## Overview
10
+
11
+ When multiple agents run in parallel, one agent may take significantly longer than its peers. The stall detection pipeline identifies this condition at the moment any agent completes and advises the orchestrator to spawn independent pending tasks immediately — without cancelling the stalled agent.
12
+
13
+ The pipeline spans two hook events and three scripts:
14
+
15
+ | Event | Script | Role |
16
+ |-------|--------|------|
17
+ | SubagentStart | `agent-start-recorder.sh` | Record spawn timestamp |
18
+ | SubagentStop (1st) | `task-outcome-recorder.sh` | Read start time, record outcome with duration |
19
+ | SubagentStop (2nd) | `stall-detection-advisor.sh` | Read start times, compare durations, emit advisory, consume start entry |
20
+
21
+ ---
22
+
23
+ ## Data Flow
24
+
25
+ ```
26
+ SubagentStart event
27
+ └─ agent-start-recorder.sh
28
+ reads: stdin JSON (agent_type, model, description)
29
+ writes: /tmp/.claude-agent-starts-$PPID (appends 1 JSON line)
30
+
31
+ SubagentStop event [hooks execute in array order — ordering is critical]
32
+
33
+ ├─ [1] task-outcome-recorder.sh
34
+ │ reads: stdin JSON (agent_type, model, outcome)
35
+ │ reads: /tmp/.claude-agent-starts-$PPID (duration calc — entry still present)
36
+ │ writes: /tmp/.claude-task-outcomes-$PPID (appends 1 JSON line with duration_seconds)
37
+ │ writes: stderr (on failure only)
38
+
39
+ └─ [2] stall-detection-advisor.sh
40
+ reads: stdin JSON (agent_type, model, description)
41
+ reads: /tmp/.claude-agent-starts-$PPID (finds matching start entry for duration)
42
+ reads: /tmp/.claude-agent-durations-$PPID (peer durations for average calculation)
43
+ writes: /tmp/.claude-agent-durations-$PPID (appends completed agent's duration)
44
+ writes: /tmp/.claude-agent-starts-$PPID (removes consumed start entry)
45
+ writes: stderr (advisory block if stall detected — R021 advisory-only)
46
+ ```
47
+
48
+ ### Stall Detection Logic
49
+
50
+ At SubagentStop, after at least one peer has already completed:
51
+
52
+ 1. Calculate `avg_duration` from all entries in `.claude-agent-durations-$PPID`
53
+ 2. Set `stall_threshold = avg_duration * 2`
54
+ 3. Scan `.claude-agent-starts-$PPID` for agents not yet in the duration file (still running)
55
+ 4. For each still-running agent where `elapsed > stall_threshold`, emit advisory to stderr
56
+
57
+ The current agent's duration is recorded *after* stall detection so it does not inflate the average for its own check.
58
+
59
+ ### Advisory Output Format
60
+
61
+ ```
62
+ ─── [Stall Detection Advisory] ───────────────────────────
63
+ Stalled: {agent_type}:{model} ({elapsed}s elapsed, 2x avg {avg_duration}s)
64
+ Description: {description}
65
+ ⚡ Consider spawning independent pending tasks immediately
66
+ R009 Adaptive Parallel Splitting applies
67
+ ──────────────────────────────────────────────────────────
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Shared Files
73
+
74
+ | File | Writer | Readers | Lifecycle |
75
+ |------|--------|---------|-----------|
76
+ | `/tmp/.claude-agent-starts-$PPID` | `agent-start-recorder.sh` (append) | `task-outcome-recorder.sh` (read), `stall-detection-advisor.sh` (read + remove entry) | Session-scoped via PPID; ring buffer 50 entries; entry removed after `stall-detection-advisor` consumes it |
77
+ | `/tmp/.claude-task-outcomes-$PPID` | `task-outcome-recorder.sh` (append) | `feedback-collector.sh`, `eval-core-batch-save.sh` (at Stop) | Session-scoped via PPID; ring buffer 50 entries |
78
+ | `/tmp/.claude-agent-durations-$PPID` | `stall-detection-advisor.sh` (append) | `stall-detection-advisor.sh` (read for average calculation) | Session-scoped via PPID; ring buffer 50 entries |
79
+
80
+ ---
81
+
82
+ ## Execution Order Requirements
83
+
84
+ The SubagentStop hook array in `hooks.json` defines a strict ordering:
85
+
86
+ ```json
87
+ "SubagentStop": [
88
+ { "command": "bash .claude/hooks/scripts/task-outcome-recorder.sh" },
89
+ { "command": "bash .claude/hooks/scripts/stall-detection-advisor.sh" },
90
+ ...
91
+ ]
92
+ ```
93
+
94
+ **task-outcome-recorder MUST run before stall-detection-advisor.**
95
+
96
+ Reason: `stall-detection-advisor.sh` removes the matching start entry from `.claude-agent-starts-$PPID` after reading it (to prevent re-matching on the next SubagentStop). If the order were reversed, `task-outcome-recorder.sh` would find no start entry for the agent and would always record `duration_seconds=0`.
97
+
98
+ If the order is swapped:
99
+ - `task-outcome-recorder` records `duration_seconds=0` for all agents
100
+ - Model escalation decisions based on duration become unreliable
101
+ - No other visible error — silent data corruption
102
+
103
+ ---
104
+
105
+ ## Temp File Lifecycle
106
+
107
+ ```
108
+ Session start (PPID assigned)
109
+
110
+ ├─ First SubagentStart → .claude-agent-starts-$PPID created
111
+
112
+ ├─ First SubagentStop → .claude-task-outcomes-$PPID created
113
+ │ .claude-agent-durations-$PPID created
114
+
115
+ ├─ Each SubagentStop → start entry consumed (removed by stall-detection-advisor)
116
+ │ duration entry appended
117
+ │ outcome entry appended
118
+
119
+ └─ Session end (PPID released)
120
+ Files remain in /tmp — OS cleans up on reboot
121
+ Ring buffers cap each file at 50 lines to bound growth
122
+ ```
123
+
124
+ PPID (parent process ID) is used rather than PID (`$$`) to scope files to the Claude Code session rather than to individual script invocations. All three scripts use `${PPID}` consistently.
125
+
126
+ ---
127
+
128
+ ## Design Principles
129
+
130
+ - **Advisory-only (R021):** All three scripts exit 0 unconditionally. A missing `jq` binary causes silent pass-through, not a blocked hook.
131
+ - **PPID scoping:** Isolates temp files per Claude Code session. Multiple concurrent sessions do not interfere.
132
+ - **Ring buffers:** Each temp file is capped at 50 lines via `tail -50` after each append. Prevents unbounded growth in long sessions with many agents.
133
+ - **grep -F for pattern matching:** Fixed-string matching in `agent-start-recorder` and `task-outcome-recorder` avoids regex injection from agent type names.
134
+ - **Self-exclusion from average:** `stall-detection-advisor` reads the duration file *before* appending its own entry, so the completing agent is never compared against itself.
135
+ - **Sibling preservation:** When removing a start entry, `awk` removes only the first matching line — preserving sibling entries when multiple agents of the same type run in parallel.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.78.0",
2
+ "version": "0.78.1",
3
3
  "lastUpdated": "2026-03-24T00:00:00.000Z",
4
4
  "components": [
5
5
  {
@@ -24,7 +24,7 @@
24
24
  "name": "guides",
25
25
  "path": "guides",
26
26
  "description": "Reference documentation",
27
- "files": 31
27
+ "files": 32
28
28
  },
29
29
  {
30
30
  "name": "hooks",