oh-my-customcode 1.1.48 → 1.1.49
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 +7 -6
- package/dist/cli/index.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/templates/.claude/agents/agora-runner.md +114 -0
- package/templates/.claude/hooks/scripts/agent-teams-advisor.sh +6 -1
- package/templates/.claude/hooks/scripts/r007-r008-drift-advisor.sh +41 -3
- package/templates/.claude/hooks/scripts/session-env-check.sh +29 -3
- package/templates/.claude/rules/MAY-optimization.md +4 -0
- package/templates/.claude/rules/MUST-agent-design.md +2 -0
- package/templates/.claude/rules/MUST-completion-verification.md +25 -0
- package/templates/.claude/rules/MUST-enforcement-policy.md +3 -3
- package/templates/.claude/rules/MUST-orchestrator-coordination.md +39 -0
- package/templates/.claude/rules/MUST-parallel-execution.md +56 -7
- package/templates/.claude/rules/MUST-sync-verification.md +16 -0
- package/templates/.claude/rules/MUST-tool-identification.md +22 -4
- package/templates/.claude/skills/agora/SKILL.md +325 -0
- package/templates/.claude/skills/agora/scripts/agora.sh +761 -0
- package/templates/.claude/skills/agora/scripts/anonymize.sh +492 -0
- package/templates/.claude/skills/agora/scripts/judge.sh +427 -0
- package/templates/.claude/skills/agora/scripts/response-schema.json +26 -0
- package/templates/.claude/skills/agora/scripts/reviewers.sh +312 -0
- package/templates/.claude/skills/agora/scripts/verdict-schema.json +34 -0
- package/templates/.claude/skills/hada-scout/SKILL.md +1 -1
- package/templates/.claude/skills/help/SKILL.md +1 -1
- package/templates/.claude/skills/pipeline/workflows/auto-dev.yaml +21 -3
- package/templates/.claude/skills/sauron-watch/SKILL.md +1 -1
- package/templates/.claude/skills/status/SKILL.md +3 -3
- package/templates/.claude/skills/token-efficiency-audit/SKILL.md +1 -1
- package/templates/CLAUDE.md +3 -3
- package/templates/CLAUDE.md.en +3 -3
- package/templates/CLAUDE.md.ko +3 -3
- package/templates/README.md +5 -5
- package/templates/guides/agent-eval/README.md +1 -1
- package/templates/manifest.json +3 -3
- package/templates/workflows/auto-dev.yaml +21 -3
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# reviewers.sh — parallel 3-vendor adapter.
|
|
3
|
+
# Spec: docs/superpowers/plans/2026-08-15-agora-anonymous-consensus-design.md §3 §11
|
|
4
|
+
set -uo pipefail
|
|
5
|
+
|
|
6
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
|
+
SCHEMA_PATH="$SCRIPT_DIR/response-schema.json"
|
|
8
|
+
|
|
9
|
+
# Ruling 12 (controller): keep the bare binary names as defaults — `claude`
|
|
10
|
+
# and `agy` are the user's shell ALIASES, not distinct binaries, and the
|
|
11
|
+
# alias-appended flags below are added explicitly in invoke_vendor() because
|
|
12
|
+
# aliases do not expand under non-interactive `bash script.sh` execution.
|
|
13
|
+
# omx has no alias (spec §2 measured: /opt/homebrew/bin/omx), so its default
|
|
14
|
+
# stays the absolute path.
|
|
15
|
+
AGORA_CLAUDE_BIN="${AGORA_CLAUDE_BIN:-claude}"
|
|
16
|
+
AGORA_OMX_BIN="${AGORA_OMX_BIN:-/opt/homebrew/bin/omx}"
|
|
17
|
+
AGORA_AGY_BIN="${AGORA_AGY_BIN:-agy}"
|
|
18
|
+
AGORA_TIMEOUT_SECS="${AGORA_TIMEOUT_SECS:-300}"
|
|
19
|
+
|
|
20
|
+
# ---------------------------------------------------------------------------
|
|
21
|
+
# _child_env_strip — the `env -u NAME` list that removes every AGORA_*
|
|
22
|
+
# variable from a vendor CLI's environment.
|
|
23
|
+
#
|
|
24
|
+
# The anonymity of this process rests on the vendors and the judge never
|
|
25
|
+
# reaching the sealed session material. Two guards already covered that:
|
|
26
|
+
# agora.sh exports nothing of its own, and no session path is ever passed in
|
|
27
|
+
# argv. Neither covers what the OPERATOR's shell exported before agora.sh
|
|
28
|
+
# ever ran. Measured: with AGORA_OUTPUT_ROOT set in the invoking shell, that
|
|
29
|
+
# value is inherited straight through agora.sh into every vendor CLI spawned
|
|
30
|
+
# here, and the whole session tree — sealed round records included — sits one
|
|
31
|
+
# glob below it. "We do not pass it" is no defence against a value that is
|
|
32
|
+
# already in the environment.
|
|
33
|
+
#
|
|
34
|
+
# Prefix rule rather than a hardcoded name list, deliberately: a name list
|
|
35
|
+
# leaks silently the day someone adds AGORA_SOMETHING_NEW, whereas the prefix
|
|
36
|
+
# fails CLOSED — a new variable is stripped unless someone argues it back in.
|
|
37
|
+
# Nothing outside the prefix is touched, so PATH, HOME, the vendors' own auth
|
|
38
|
+
# tokens and proxy settings all survive; `env -i` would leave the CLIs unable
|
|
39
|
+
# to authenticate at all.
|
|
40
|
+
#
|
|
41
|
+
# Read time and pass time are separate: the config reads above have already
|
|
42
|
+
# happened, so this script goes on using AGORA_CLAUDE_BIN, AGORA_TIMEOUT_SECS
|
|
43
|
+
# and friends as ordinary shell variables. Only the CHILD's copy is removed,
|
|
44
|
+
# which is why test-injected configuration still works.
|
|
45
|
+
#
|
|
46
|
+
# Built from the exported names actually present (compgen -e), so a prefixed
|
|
47
|
+
# variable this script has never heard of is covered too.
|
|
48
|
+
# ---------------------------------------------------------------------------
|
|
49
|
+
_child_env_strip=()
|
|
50
|
+
while IFS= read -r _agora_env_name; do
|
|
51
|
+
[ -n "$_agora_env_name" ] || continue
|
|
52
|
+
_child_env_strip+=(-u "$_agora_env_name")
|
|
53
|
+
done < <(compgen -e 2>/dev/null | grep '^AGORA_' || true)
|
|
54
|
+
unset _agora_env_name
|
|
55
|
+
|
|
56
|
+
# ---------------------------------------------------------------------------
|
|
57
|
+
# run_with_timeout <seconds> <cmd>... — R005: macOS ships no GNU timeout.
|
|
58
|
+
# Returns 124 on timeout, otherwise the command's own exit code.
|
|
59
|
+
#
|
|
60
|
+
# AGORA_FORCE_TIMEOUT_FALLBACK=1 is a TEST-ONLY switch (default off, never
|
|
61
|
+
# set in production) that forces the wait-based fallback branch even when
|
|
62
|
+
# gtimeout is installed locally, so both the gtimeout path and the fallback
|
|
63
|
+
# path can be exercised deterministically regardless of what happens to be
|
|
64
|
+
# on the machine running the tests (dev boxes have coreutils; GitHub-hosted
|
|
65
|
+
# macos CI runners may not).
|
|
66
|
+
#
|
|
67
|
+
# F1 (review round 2, controller-measured): the fallback watchdog kills the
|
|
68
|
+
# WHOLE PROCESS GROUP of the backgrounded command, not just its direct PID.
|
|
69
|
+
# `kill -TERM "$pid"` alone only reaches the direct child — a vendor CLI
|
|
70
|
+
# that forks a grandchild (common in Node-wrapped CLIs) orphans it, and the
|
|
71
|
+
# orphan keeps running (and, against a real vendor, keeps making API calls)
|
|
72
|
+
# after this function has already reported the vendor as timed out/missing.
|
|
73
|
+
# Measured: `kill -TERM "$pid"` left 2/3 descendants of a forking stub
|
|
74
|
+
# alive; `kill -TERM -- -"$pid"` (negative PID = process group) left 0.
|
|
75
|
+
# `gtimeout`'s own default (non `--foreground`) mode already targets the
|
|
76
|
+
# whole group, so only this fallback branch needed the fix.
|
|
77
|
+
#
|
|
78
|
+
# Getting a process group AT ALL requires job control (`set -m`) to be on —
|
|
79
|
+
# without it, `"$@" &` inherits this shell's own process group, and a
|
|
80
|
+
# negative-PID kill would hit this script's group, not just the timed-out
|
|
81
|
+
# command's. macOS ships no `setsid`, so `set -m` is the only portable way
|
|
82
|
+
# to get the backgrounded command its own group here. Scoped strictly to
|
|
83
|
+
# this function: only turned on if not already on, and turned back off
|
|
84
|
+
# before returning, so the rest of reviewers.sh (and any caller) is
|
|
85
|
+
# unaffected by the job-control side effects (e.g. "Terminated" job
|
|
86
|
+
# notifications on stray fds).
|
|
87
|
+
# ---------------------------------------------------------------------------
|
|
88
|
+
run_with_timeout() {
|
|
89
|
+
local secs="$1"; shift
|
|
90
|
+
if [ "${AGORA_FORCE_TIMEOUT_FALLBACK:-0}" != "1" ] && command -v gtimeout >/dev/null 2>&1; then
|
|
91
|
+
gtimeout "$secs" "$@"
|
|
92
|
+
return $?
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
local restore_job_control=0
|
|
96
|
+
case $- in
|
|
97
|
+
*m*) ;;
|
|
98
|
+
*) set -m; restore_job_control=1 ;;
|
|
99
|
+
esac
|
|
100
|
+
|
|
101
|
+
"$@" &
|
|
102
|
+
local pid=$!
|
|
103
|
+
# Negative PID targets the whole process group (job-control-assigned pgid
|
|
104
|
+
# == the group leader's pid), so grandchildren the command forks are
|
|
105
|
+
# reaped too, not just the direct child.
|
|
106
|
+
( sleep "$secs"; kill -TERM -- "-$pid" 2>/dev/null ) &
|
|
107
|
+
local watcher=$!
|
|
108
|
+
|
|
109
|
+
local rc=0
|
|
110
|
+
# 2>/dev/null: suppresses this shell's own job-control "Terminated"
|
|
111
|
+
# notification, which (only under `set -m`) prints as a side effect of
|
|
112
|
+
# `wait` reaping a signal-killed background job — noise, not a diagnostic
|
|
113
|
+
# this script itself emits.
|
|
114
|
+
wait "$pid" 2>/dev/null || rc=$?
|
|
115
|
+
# F1 (review round 3, measured): the watchdog must be torn down by PROCESS
|
|
116
|
+
# GROUP for exactly the reason the command itself is — `kill -TERM
|
|
117
|
+
# "$watcher"` reaches only the subshell, and its `sleep` child is orphaned
|
|
118
|
+
# and re-parented to init, where it lingers for the full AGORA_TIMEOUT_SECS
|
|
119
|
+
# (default 300). This is the SUCCESS path: when the command finishes first
|
|
120
|
+
# the watchdog's sleep is still running, so every completed vendor call
|
|
121
|
+
# leaked one. Measured before the fix: 1 orphaned `sleep` per call — up to
|
|
122
|
+
# 6 per round (3 reviewers + 3 judge attempts). On timeout nothing leaked,
|
|
123
|
+
# because the sleep had already elapsed by definition, which is why the
|
|
124
|
+
# existing timeout-path tests never saw it.
|
|
125
|
+
# Safe under `set -m` (guaranteed on in this branch by the block above):
|
|
126
|
+
# measured pgid(watcher) == pid(watcher) != pgid(this script), so the
|
|
127
|
+
# negative-PID kill cannot reach this script's own group. The pid also
|
|
128
|
+
# cannot have been recycled onto an unrelated group, because $watcher is
|
|
129
|
+
# still an unreaped child here — its zombie holds both the pid and the
|
|
130
|
+
# group until the `wait` below.
|
|
131
|
+
kill -TERM -- "-$watcher" 2>/dev/null || true
|
|
132
|
+
wait "$watcher" 2>/dev/null || true
|
|
133
|
+
|
|
134
|
+
[ "$restore_job_control" -eq 1 ] && set +m
|
|
135
|
+
|
|
136
|
+
# 143 = SIGTERM from the watchdog; normalize to the GNU timeout convention.
|
|
137
|
+
[ "$rc" -eq 143 ] && rc=124
|
|
138
|
+
return "$rc"
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
# ---------------------------------------------------------------------------
|
|
142
|
+
# run_sanitized <seconds> <cmd>... — run_with_timeout with the AGORA_*
|
|
143
|
+
# variables removed from the command's environment (see _child_env_strip).
|
|
144
|
+
# Wrapping the command in `env` rather than unsetting the variables in this
|
|
145
|
+
# shell is what keeps the read/pass split above intact. `env` execs the
|
|
146
|
+
# command in place, so the pid and process group that run_with_timeout's
|
|
147
|
+
# watchdog targets are the command's own, exactly as before.
|
|
148
|
+
# ---------------------------------------------------------------------------
|
|
149
|
+
run_sanitized() {
|
|
150
|
+
local secs="$1"; shift
|
|
151
|
+
run_with_timeout "$secs" env ${_child_env_strip[@]+"${_child_env_strip[@]}"} "$@"
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
# ---------------------------------------------------------------------------
|
|
155
|
+
# invoke_vendor <slug> <prompt_file> — dispatches to the vendor-specific CLI
|
|
156
|
+
# argument shape (spec §2 REQ-1) and applies run_sanitized uniformly, so
|
|
157
|
+
# every vendor is launched under both the timeout and the env strip.
|
|
158
|
+
# ---------------------------------------------------------------------------
|
|
159
|
+
invoke_vendor() {
|
|
160
|
+
local slug="$1" prompt_file="$2"
|
|
161
|
+
local prompt; prompt=$(cat "$prompt_file")
|
|
162
|
+
case "$slug" in
|
|
163
|
+
claude)
|
|
164
|
+
# --enable-auto-mode: the user's shell `claude` alias appends this
|
|
165
|
+
# flag (Ruling 12 measured); aliases do not expand under
|
|
166
|
+
# non-interactive `bash script.sh` execution, so it must be passed
|
|
167
|
+
# explicitly here or the CLI runs without it.
|
|
168
|
+
run_sanitized "$AGORA_TIMEOUT_SECS" "$AGORA_CLAUDE_BIN" \
|
|
169
|
+
-p --model claude-opus-4-8 --enable-auto-mode "$prompt"
|
|
170
|
+
;;
|
|
171
|
+
omx)
|
|
172
|
+
# omx is a plain binary, not a shell alias (spec §2 measured) — no
|
|
173
|
+
# extra flag is needed.
|
|
174
|
+
run_sanitized "$AGORA_TIMEOUT_SECS" "$AGORA_OMX_BIN" exec "$prompt"
|
|
175
|
+
;;
|
|
176
|
+
agy)
|
|
177
|
+
# --dangerously-skip-permissions: the user's shell `agy` alias appends
|
|
178
|
+
# this flag (Ruling 12 measured); aliases do not expand under
|
|
179
|
+
# non-interactive `bash script.sh` execution, so it must be passed
|
|
180
|
+
# explicitly here or the CLI may block on a permission prompt.
|
|
181
|
+
run_sanitized "$AGORA_TIMEOUT_SECS" "$AGORA_AGY_BIN" \
|
|
182
|
+
-p --model gemini-3.1-pro-high --output-format json \
|
|
183
|
+
--json-schema "$SCHEMA_PATH" --dangerously-skip-permissions "$prompt"
|
|
184
|
+
;;
|
|
185
|
+
*) return 65 ;;
|
|
186
|
+
esac
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
# ---------------------------------------------------------------------------
|
|
190
|
+
# _emit_vendor_stderr_tail <slug> <err_file> — F2 (review round 2): print the
|
|
191
|
+
# last 20 lines of a vendor's captured stderr as part of THIS script's own
|
|
192
|
+
# diagnostic output, so a failure's actual cause (auth, rate-limit, model
|
|
193
|
+
# deprecation, network) is debuggable instead of silently discarded. A
|
|
194
|
+
# vendor's session/hook logs can be long (omx in particular), so only the
|
|
195
|
+
# tail is surfaced, not the whole file.
|
|
196
|
+
# ---------------------------------------------------------------------------
|
|
197
|
+
_emit_vendor_stderr_tail() {
|
|
198
|
+
local slug="$1" err_file="$2"
|
|
199
|
+
if [ -s "$err_file" ]; then
|
|
200
|
+
printf '[agora] %s stderr (last 20 lines):\n' "$slug" >&2
|
|
201
|
+
tail -n 20 "$err_file" >&2
|
|
202
|
+
fi
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
# ---------------------------------------------------------------------------
|
|
206
|
+
# call_vendor <slug> <prompt_file> <out_file> — one retry, then missing
|
|
207
|
+
# (spec §11). Writes <out_file> ONLY on a verified-parseable success; a
|
|
208
|
+
# missing vendor leaves no file at all (silent-failure avoidance: callers
|
|
209
|
+
# distinguish "responded" from "missing" by file existence, never by an
|
|
210
|
+
# empty/partial file).
|
|
211
|
+
#
|
|
212
|
+
# F2 (review round 2): each attempt's vendor stderr is captured to
|
|
213
|
+
# <out_dir>/<slug>.attempt-<N>.stderr.log — inside SEALED/raw/round-N/, the
|
|
214
|
+
# same trust boundary as the raw response itself (never under anon/). On
|
|
215
|
+
# success the log is removed (no noise from chatty vendors); on failure it
|
|
216
|
+
# is left on disk for audit AND its tail is folded into this script's own
|
|
217
|
+
# diagnostic stderr via _emit_vendor_stderr_tail.
|
|
218
|
+
# ---------------------------------------------------------------------------
|
|
219
|
+
call_vendor() {
|
|
220
|
+
local slug="$1" prompt_file="$2" out_file="$3"
|
|
221
|
+
local attempt rc tmp err_file out_dir_path
|
|
222
|
+
tmp=$(mktemp)
|
|
223
|
+
out_dir_path="$(dirname "$out_file")"
|
|
224
|
+
|
|
225
|
+
for attempt in 1 2; do
|
|
226
|
+
rc=0
|
|
227
|
+
err_file="$out_dir_path/$slug.attempt-$attempt.stderr.log"
|
|
228
|
+
invoke_vendor "$slug" "$prompt_file" > "$tmp" 2> "$err_file" || rc=$?
|
|
229
|
+
|
|
230
|
+
if [ "$rc" -eq 124 ]; then
|
|
231
|
+
printf '[agora] %s timeout on attempt %s\n' "$slug" "$attempt" >&2
|
|
232
|
+
_emit_vendor_stderr_tail "$slug" "$err_file"
|
|
233
|
+
elif [ "$rc" -ne 0 ]; then
|
|
234
|
+
printf '[agora] %s exited %s on attempt %s\n' "$slug" "$rc" "$attempt" >&2
|
|
235
|
+
_emit_vendor_stderr_tail "$slug" "$err_file"
|
|
236
|
+
elif ! jq -e . "$tmp" >/dev/null 2>&1; then
|
|
237
|
+
printf '[agora] %s returned unparsable output on attempt %s\n' "$slug" "$attempt" >&2
|
|
238
|
+
_emit_vendor_stderr_tail "$slug" "$err_file"
|
|
239
|
+
rc=65
|
|
240
|
+
else
|
|
241
|
+
# Success is written to the final path ONLY after the response has
|
|
242
|
+
# been confirmed valid JSON — never before the check is settled.
|
|
243
|
+
rm -f "$err_file"
|
|
244
|
+
mv "$tmp" "$out_file"
|
|
245
|
+
return 0
|
|
246
|
+
fi
|
|
247
|
+
|
|
248
|
+
[ "$attempt" -eq 1 ] && printf '[agora] %s retry\n' "$slug" >&2
|
|
249
|
+
done
|
|
250
|
+
|
|
251
|
+
rm -f "$tmp"
|
|
252
|
+
printf '[agora] %s missing after retry\n' "$slug" >&2
|
|
253
|
+
return 1
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
# ---------------------------------------------------------------------------
|
|
257
|
+
# run_reviewers --session-dir <dir> --round <N> --prompt-file <file>
|
|
258
|
+
# Fans out call_vendor to all three vendors in parallel, then aborts the
|
|
259
|
+
# round (exit 3) once two or more are missing (spec §11: a single opinion is
|
|
260
|
+
# not a consensus process).
|
|
261
|
+
# ---------------------------------------------------------------------------
|
|
262
|
+
run_reviewers() {
|
|
263
|
+
local dir='' round='' prompt_file=''
|
|
264
|
+
while [ "$#" -gt 0 ]; do
|
|
265
|
+
case "$1" in
|
|
266
|
+
--session-dir) dir="$2"; shift 2 ;;
|
|
267
|
+
--round) round="$2"; shift 2 ;;
|
|
268
|
+
--prompt-file) prompt_file="$2"; shift 2 ;;
|
|
269
|
+
*) printf 'reviewers.sh: unknown option %s\n' "$1" >&2; return 64 ;;
|
|
270
|
+
esac
|
|
271
|
+
done
|
|
272
|
+
[ -n "$dir" ] && [ -n "$round" ] && [ -n "$prompt_file" ] || {
|
|
273
|
+
printf 'reviewers.sh: --session-dir, --round and --prompt-file are required\n' >&2
|
|
274
|
+
return 64
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
local out_dir="$dir/SEALED/raw/round-$round"
|
|
278
|
+
mkdir -p "$out_dir"
|
|
279
|
+
|
|
280
|
+
local pids=() slugs=(claude omx agy) slug
|
|
281
|
+
for slug in "${slugs[@]}"; do
|
|
282
|
+
call_vendor "$slug" "$prompt_file" "$out_dir/$slug.json" &
|
|
283
|
+
pids+=("$!")
|
|
284
|
+
done
|
|
285
|
+
|
|
286
|
+
local i missing=0
|
|
287
|
+
for i in "${!pids[@]}"; do
|
|
288
|
+
wait "${pids[$i]}" || missing=$(( missing + 1 ))
|
|
289
|
+
done
|
|
290
|
+
|
|
291
|
+
if [ "$missing" -ge 2 ]; then
|
|
292
|
+
printf '[agora] 2 or more reviewers missing (%s) — aborting round %s\n' "$missing" "$round" >&2
|
|
293
|
+
return 3
|
|
294
|
+
fi
|
|
295
|
+
printf '[agora] round %s reviewers: %s responded\n' "$round" "$(( 3 - missing ))" >&2
|
|
296
|
+
return 0
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
main() {
|
|
300
|
+
case "${1:---help}" in
|
|
301
|
+
--run) shift; run_reviewers "$@" ;;
|
|
302
|
+
--help | -h)
|
|
303
|
+
cat <<'USAGE'
|
|
304
|
+
Usage:
|
|
305
|
+
reviewers.sh --run --session-dir <dir> --round <N> --prompt-file <file>
|
|
306
|
+
USAGE
|
|
307
|
+
;;
|
|
308
|
+
*) printf 'reviewers.sh: unknown option %s\n' "$1" >&2; return 64 ;;
|
|
309
|
+
esac
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
main "$@"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "object",
|
|
3
|
+
"required": ["round", "judge", "consensus", "verdict", "resolved", "unresolved", "agenda", "draft", "new_findings", "notes"],
|
|
4
|
+
"properties": {
|
|
5
|
+
"round": { "type": "number" },
|
|
6
|
+
"judge": { "type": "string" },
|
|
7
|
+
"consensus": { "type": "string", "enum": ["UNANIMOUS", "MAJORITY", "SPLIT", "NONE"] },
|
|
8
|
+
"verdict": { "type": "string", "enum": ["BUILD", "BUILD_WITH_CHANGES", "REDESIGN", "ABANDON"] },
|
|
9
|
+
"resolved": {
|
|
10
|
+
"type": "array",
|
|
11
|
+
"items": {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"required": ["id", "resolution"],
|
|
14
|
+
"properties": { "id": { "type": "string" }, "resolution": { "type": "string" } }
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"unresolved": {
|
|
18
|
+
"type": "array",
|
|
19
|
+
"items": {
|
|
20
|
+
"type": "object",
|
|
21
|
+
"required": ["id", "severity", "positions"],
|
|
22
|
+
"properties": {
|
|
23
|
+
"id": { "type": "string" },
|
|
24
|
+
"severity": { "type": "string", "enum": ["CRITICAL", "HIGH", "MEDIUM", "LOW"] },
|
|
25
|
+
"positions": { "type": "string" }
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"agenda": { "type": "array", "items": { "type": "string" } },
|
|
30
|
+
"draft": { "type": "string" },
|
|
31
|
+
"new_findings": { "type": "number" },
|
|
32
|
+
"notes": { "type": "string" }
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -50,7 +50,7 @@ The haiku agent receives the following system prompt:
|
|
|
50
50
|
|
|
51
51
|
```
|
|
52
52
|
You are a relevance filter for the oh-my-customcode project — an AI agent harness/orchestration
|
|
53
|
-
system built on Claude Code CLI with
|
|
53
|
+
system built on Claude Code CLI with 50 agents, 115 skills.
|
|
54
54
|
|
|
55
55
|
Project domains (HIGH relevance):
|
|
56
56
|
- AI agent orchestration, multi-agent systems, agent design patterns
|
|
@@ -5,6 +5,14 @@ version: "2.1.0"
|
|
|
5
5
|
# Design rule: each pipeline run produces ONE bounded release unit (3-7 issues), not all open issues.
|
|
6
6
|
# This pipeline is a project-agnostic template. Project-specific overrides belong in
|
|
7
7
|
# the project's own workflows/auto-dev.yaml (e.g., AgentNav, second-brain).
|
|
8
|
+
#
|
|
9
|
+
# Design rule (R020 「위임 경계를 Phase 개수로 설계」 배선, Origin: #1595 #4):
|
|
10
|
+
# 아래 `skill:` 스텝 중 다중 Phase 스킬(deep-plan = research→plan→verify, deep-verify = 다각 검증)은
|
|
11
|
+
# 스킬을 그대로 spawn하지 않는다. Phase 경계가 곧 종료 유혹 지점이므로, 발주 전에 스킬의 Phase를
|
|
12
|
+
# 읽고 **단일 목표 1개짜리 위임**으로 분할해 순차 발주한다. 실측(v1.1.48): `skill: deep-plan`을
|
|
13
|
+
# 그대로 호출한 결과 tool_uses=0 / 6.9초 / 산출물 0으로 종료했고, 단일 목표 Plan 에이전트로
|
|
14
|
+
# 재설계하니 1/1 완주했다. `skill:` 값은 **분할의 근거가 되는 스킬 정의**를 가리키는 것이지
|
|
15
|
+
# "이 스킬을 1회 호출하라"는 뜻이 아니다.
|
|
8
16
|
|
|
9
17
|
steps:
|
|
10
18
|
- name: pre-triage
|
|
@@ -270,7 +278,7 @@ steps:
|
|
|
270
278
|
|
|
271
279
|
- name: deep-plan
|
|
272
280
|
skill: deep-plan
|
|
273
|
-
description: "Research-validated implementation plan (research → plan → verify) — skipped if docs-only, integrated-analysis allowed if lite"
|
|
281
|
+
description: "Research-validated implementation plan (research → plan → verify) — skipped if docs-only, integrated-analysis allowed if lite. MULTI-PHASE: 스킬을 그대로 spawn하지 말고 R020 「위임 경계를 Phase 개수로 설계」에 따라 단일 목표 위임으로 분할해 순차 발주한다 (#1595 #4)."
|
|
274
282
|
depends_on: plan
|
|
275
283
|
|
|
276
284
|
- name: implement
|
|
@@ -357,7 +365,7 @@ steps:
|
|
|
357
365
|
|
|
358
366
|
- name: deep-verify
|
|
359
367
|
skill: deep-verify
|
|
360
|
-
description: "Multi-angle release quality verification — self-review checklist if docs-only; mgr-sauron R017 + core self-check if lite"
|
|
368
|
+
description: "Multi-angle release quality verification — self-review checklist if docs-only; mgr-sauron R017 + core self-check if lite. MULTI-PHASE: 스킬을 그대로 spawn하지 말고 R020 「위임 경계를 Phase 개수로 설계」에 따라 단일 목표 위임으로 분할해 순차 발주한다 (#1595 #4)."
|
|
361
369
|
depends_on: verify-build
|
|
362
370
|
|
|
363
371
|
- name: release
|
|
@@ -431,7 +439,17 @@ steps:
|
|
|
431
439
|
- No existing tags → v0.1.0
|
|
432
440
|
- Previous tag exists → DEFAULT to patch. When in doubt, patch — do NOT reflexively bump minor for rule/doc/skill edits.
|
|
433
441
|
- patch (DEFAULT): rule/doc/skill/config/wiki/workflow changes, bugfixes, hardening, CC-compat notes — the vast majority of this project's changes
|
|
434
|
-
- minor: ONLY a
|
|
442
|
+
- minor: ONLY a new user-facing capability that changes HOW the harness is used — a new
|
|
443
|
+
workflow axis, a new command surface users must learn, or a contract other components
|
|
444
|
+
depend on. NOT "a file was added under .claude/skills/ or .claude/agents/".
|
|
445
|
+
⚠ Counter-example (Origin: v1.1.49 세션, 사용자 지적): adding one skill + one agent
|
|
446
|
+
(agora: skills 114→115, agents 49→50) was initially scoped as v1.2.0 minor by reading
|
|
447
|
+
the old wording literally. That was WRONG — this repo adds skills routinely, and
|
|
448
|
+
skills reached 115 while the version stayed v1.1.48, so skill/agent addition is
|
|
449
|
+
ESTABLISHED as patch (target was corrected to v1.1.49). Count growth is this repo's
|
|
450
|
+
baseline rate of change, NOT a minor signal. If a version bump would follow
|
|
451
|
+
mechanically from "a new file exists", it is patch. Ask instead: does a user's
|
|
452
|
+
workflow change because of this?
|
|
435
453
|
- major: breaking changes to user-facing contracts (CLI flags, public skill/command names, public API), or a deliberate milestone declaration (e.g., v1.0.0)
|
|
436
454
|
- Previous tag is ahead of source version (e.g., tag v0.136.1, package.json 0.136.0): use next available skip-version (0.136.2)
|
|
437
455
|
|
|
@@ -198,7 +198,7 @@ Starting full R017 verification...
|
|
|
198
198
|
═══════════════════════════════════════════════════════════
|
|
199
199
|
|
|
200
200
|
[Round 1/5] mgr-supplier:audit
|
|
201
|
-
✓
|
|
201
|
+
✓ 50 agents checked, 0 issues
|
|
202
202
|
|
|
203
203
|
[Round 2/5] mgr-updater:docs
|
|
204
204
|
✓ Documentation sync: OK
|
|
@@ -33,10 +33,10 @@ Agents:
|
|
|
33
33
|
Database: 4
|
|
34
34
|
Infra Engineer: 2
|
|
35
35
|
Other: 10 (security, architect, QA, system)
|
|
36
|
-
Total:
|
|
36
|
+
Total: 50 agents
|
|
37
37
|
|
|
38
38
|
Skills:
|
|
39
|
-
Total:
|
|
39
|
+
Total: 115 skills
|
|
40
40
|
|
|
41
41
|
Guides: 56 loaded
|
|
42
42
|
Commands: 60+ available
|
|
@@ -131,7 +131,7 @@ status --health
|
|
|
131
131
|
Health Checks:
|
|
132
132
|
|
|
133
133
|
Agents:
|
|
134
|
-
✓
|
|
134
|
+
✓ 50/50 agents valid
|
|
135
135
|
✓ All agent files exist in .claude/agents/
|
|
136
136
|
|
|
137
137
|
Dependencies:
|
|
@@ -125,7 +125,7 @@ Applies CI/Worker-Only Levers. These disable core oh-my-customcode functionality
|
|
|
125
125
|
|
|
126
126
|
These settings disable core oh-my-customcode functionality:
|
|
127
127
|
• CLAUDE_CODE_DISABLE_CLAUDE_MDS=1 → ALL rules and routing offline (R010 disabled)
|
|
128
|
-
• CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS=1 → All
|
|
128
|
+
• CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS=1 → All 50 agents unavailable
|
|
129
129
|
• ENABLE_CLAUDEAI_MCP_SERVERS=false → MCP-dependent skills unavailable
|
|
130
130
|
• CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 → No persistent memory across sessions
|
|
131
131
|
|
package/templates/CLAUDE.md
CHANGED
|
@@ -117,8 +117,8 @@ oh-my-customcode로 구동됩니다.
|
|
|
117
117
|
project/
|
|
118
118
|
+-- CLAUDE.md # 진입점
|
|
119
119
|
+-- .claude/
|
|
120
|
-
| +-- agents/ # 서브에이전트 정의 (
|
|
121
|
-
| +-- skills/ # 스킬 (
|
|
120
|
+
| +-- agents/ # 서브에이전트 정의 (50 파일)
|
|
121
|
+
| +-- skills/ # 스킬 (115 디렉토리)
|
|
122
122
|
| +-- rules/ # 전역 규칙 (R000-R023)
|
|
123
123
|
| +-- hooks/ # 훅 스크립트 (보안, 검증, HUD)
|
|
124
124
|
| +-- contexts/ # 컨텍스트 파일 (ecomode)
|
|
@@ -180,7 +180,7 @@ oh-my-customcode는 소프트웨어 컴파일과 동일한 구조를 따릅니
|
|
|
180
180
|
| System | 4 | sys-memory-keeper, sys-naggy, tracker-checkpoint, wiki-curator |
|
|
181
181
|
-->
|
|
182
182
|
|
|
183
|
-
총 **
|
|
183
|
+
총 **50개** 에이전트 (타입별 상세는 `/omcustom:lists` 또는 wiki/agents/ 참조)
|
|
184
184
|
|
|
185
185
|
## Agent Teams (MUST when enabled)
|
|
186
186
|
|
package/templates/CLAUDE.md.en
CHANGED
|
@@ -129,8 +129,8 @@ NO EXCEPTIONS. NO EXCUSES.
|
|
|
129
129
|
project/
|
|
130
130
|
+-- CLAUDE.md # Entry point
|
|
131
131
|
+-- .claude/
|
|
132
|
-
| +-- agents/ # Subagent definitions (
|
|
133
|
-
| +-- skills/ # Skills (
|
|
132
|
+
| +-- agents/ # Subagent definitions (50 files)
|
|
133
|
+
| +-- skills/ # Skills (115 directories)
|
|
134
134
|
| +-- rules/ # Global rules (R000-R023)
|
|
135
135
|
| +-- hooks/ # Hook scripts (security, validation, HUD)
|
|
136
136
|
| +-- contexts/ # Context files (ecomode)
|
|
@@ -174,7 +174,7 @@ This is the core oh-my-customcode philosophy: **"No expert? CREATE one, connect
|
|
|
174
174
|
| QA Team | 3 | qa-planner, qa-writer, qa-engineer |
|
|
175
175
|
| Manager | 6 | mgr-creator, mgr-updater, mgr-supplier, mgr-gitnerd, mgr-sauron, mgr-claude-code-bible |
|
|
176
176
|
| System | 4 | sys-memory-keeper, sys-naggy, tracker-checkpoint, wiki-curator |
|
|
177
|
-
| **Total** | **
|
|
177
|
+
| **Total** | **50** | |
|
|
178
178
|
|
|
179
179
|
## Agent Teams (MUST when enabled)
|
|
180
180
|
|
package/templates/CLAUDE.md.ko
CHANGED
|
@@ -129,8 +129,8 @@ oh-my-customcode로 구동됩니다.
|
|
|
129
129
|
project/
|
|
130
130
|
+-- CLAUDE.md # 진입점
|
|
131
131
|
+-- .claude/
|
|
132
|
-
| +-- agents/ # 서브에이전트 정의 (
|
|
133
|
-
| +-- skills/ # 스킬 (
|
|
132
|
+
| +-- agents/ # 서브에이전트 정의 (50 파일)
|
|
133
|
+
| +-- skills/ # 스킬 (115 디렉토리)
|
|
134
134
|
| +-- rules/ # 전역 규칙 (R000-R023)
|
|
135
135
|
| +-- hooks/ # 훅 스크립트 (보안, 검증, HUD)
|
|
136
136
|
| +-- contexts/ # 컨텍스트 파일 (ecomode)
|
|
@@ -174,7 +174,7 @@ project/
|
|
|
174
174
|
| QA Team | 3 | qa-planner, qa-writer, qa-engineer |
|
|
175
175
|
| Manager | 6 | mgr-creator, mgr-updater, mgr-supplier, mgr-gitnerd, mgr-sauron, mgr-claude-code-bible |
|
|
176
176
|
| System | 4 | sys-memory-keeper, sys-naggy, tracker-checkpoint, wiki-curator |
|
|
177
|
-
| **총계** | **
|
|
177
|
+
| **총계** | **50** | |
|
|
178
178
|
|
|
179
179
|
## Agent Teams (MUST when enabled)
|
|
180
180
|
|
package/templates/README.md
CHANGED
|
@@ -47,8 +47,8 @@ templates/
|
|
|
47
47
|
├── CLAUDE.md # 에이전트 시스템 진입점
|
|
48
48
|
├── manifest.json # 배포 컴포넌트 카운트 및 메타데이터
|
|
49
49
|
├── .claude/
|
|
50
|
-
│ ├── agents/ # 에이전트 정의 파일 (*.md,
|
|
51
|
-
│ ├── skills/ # 스킬 모듈 (각 디렉토리에 SKILL.md,
|
|
50
|
+
│ ├── agents/ # 에이전트 정의 파일 (*.md, 50개)
|
|
51
|
+
│ ├── skills/ # 스킬 모듈 (각 디렉토리에 SKILL.md, 115개)
|
|
52
52
|
│ ├── rules/ # 전역 규칙 (R000–R023, 23개)
|
|
53
53
|
│ ├── hooks/
|
|
54
54
|
│ │ ├── hooks.json # 훅 이벤트 설정 (PreToolUse/PostToolUse 등)
|
|
@@ -65,7 +65,7 @@ templates/
|
|
|
65
65
|
아래 카운트는 `templates/manifest.json`과 동기화됩니다.
|
|
66
66
|
CI의 `verify-template-sync.sh`가 소스와 templates/ 간 일치를 검증합니다.
|
|
67
67
|
|
|
68
|
-
### Agents (
|
|
68
|
+
### Agents (50)
|
|
69
69
|
|
|
70
70
|
`.claude/agents/*.md` — 에이전트 정의 파일.
|
|
71
71
|
|
|
@@ -80,13 +80,13 @@ CI의 `verify-template-sync.sh`가 소스와 templates/ 간 일치를 검증합
|
|
|
80
80
|
| DE Engineer | 6 |
|
|
81
81
|
| SW Engineer / Database | 4 |
|
|
82
82
|
| Security | 1 |
|
|
83
|
-
| SW Architect |
|
|
83
|
+
| SW Architect | 3 |
|
|
84
84
|
| Infra Engineer | 2 |
|
|
85
85
|
| QA Team | 3 |
|
|
86
86
|
| Manager | 6 |
|
|
87
87
|
| System | 4 |
|
|
88
88
|
|
|
89
|
-
### Skills (
|
|
89
|
+
### Skills (115)
|
|
90
90
|
|
|
91
91
|
`.claude/skills/*/SKILL.md` — 재사용 가능한 스킬 모듈.
|
|
92
92
|
|
|
@@ -23,7 +23,7 @@ LangChain의 Deep Agents 평가 방법론은 "More evals ≠ better agents" 철
|
|
|
23
23
|
|
|
24
24
|
### oh-my-customcode 맥락
|
|
25
25
|
|
|
26
|
-
oh-my-customcode의 에이전트 시스템은
|
|
26
|
+
oh-my-customcode의 에이전트 시스템은 50개 전문 에이전트와 115개 스킬로 구성된다. 이 방법론은 신규 에이전트 검증(mgr-creator), 릴리즈 품질 검증(deep-verify), 반복 개선 루프(evaluator-optimizer)에 정량 차원을 추가하는 수단으로 내재화된다.
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
package/templates/manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.1.
|
|
2
|
+
"version": "1.1.49",
|
|
3
3
|
"lastUpdated": "2026-07-14T00:00:00.000Z",
|
|
4
4
|
"omcustomMinClaudeCode": "2.1.121",
|
|
5
5
|
"omcustomMinClaudeCodeReason": "Sensitive-path direct Write/Edit on .claude/** under bypassPermissions (R010 deprecation, #1101)",
|
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
"name": "agents",
|
|
15
15
|
"path": ".claude/agents",
|
|
16
16
|
"description": "AI agent definitions (flat .md files with prefixes)",
|
|
17
|
-
"files":
|
|
17
|
+
"files": 50
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
"name": "skills",
|
|
21
21
|
"path": ".claude/skills",
|
|
22
22
|
"description": "Reusable skill modules (includes slash commands)",
|
|
23
|
-
"files":
|
|
23
|
+
"files": 115
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
"name": "guides",
|
|
@@ -5,6 +5,14 @@ version: "2.1.0"
|
|
|
5
5
|
# Design rule: each pipeline run produces ONE bounded release unit (3-7 issues), not all open issues.
|
|
6
6
|
# This pipeline is a project-agnostic template. Project-specific overrides belong in
|
|
7
7
|
# the project's own workflows/auto-dev.yaml (e.g., AgentNav, second-brain).
|
|
8
|
+
#
|
|
9
|
+
# Design rule (R020 「위임 경계를 Phase 개수로 설계」 배선, Origin: #1595 #4):
|
|
10
|
+
# 아래 `skill:` 스텝 중 다중 Phase 스킬(deep-plan = research→plan→verify, deep-verify = 다각 검증)은
|
|
11
|
+
# 스킬을 그대로 spawn하지 않는다. Phase 경계가 곧 종료 유혹 지점이므로, 발주 전에 스킬의 Phase를
|
|
12
|
+
# 읽고 **단일 목표 1개짜리 위임**으로 분할해 순차 발주한다. 실측(v1.1.48): `skill: deep-plan`을
|
|
13
|
+
# 그대로 호출한 결과 tool_uses=0 / 6.9초 / 산출물 0으로 종료했고, 단일 목표 Plan 에이전트로
|
|
14
|
+
# 재설계하니 1/1 완주했다. `skill:` 값은 **분할의 근거가 되는 스킬 정의**를 가리키는 것이지
|
|
15
|
+
# "이 스킬을 1회 호출하라"는 뜻이 아니다.
|
|
8
16
|
|
|
9
17
|
steps:
|
|
10
18
|
- name: pre-triage
|
|
@@ -270,7 +278,7 @@ steps:
|
|
|
270
278
|
|
|
271
279
|
- name: deep-plan
|
|
272
280
|
skill: deep-plan
|
|
273
|
-
description: "Research-validated implementation plan (research → plan → verify) — skipped if docs-only, integrated-analysis allowed if lite"
|
|
281
|
+
description: "Research-validated implementation plan (research → plan → verify) — skipped if docs-only, integrated-analysis allowed if lite. MULTI-PHASE: 스킬을 그대로 spawn하지 말고 R020 「위임 경계를 Phase 개수로 설계」에 따라 단일 목표 위임으로 분할해 순차 발주한다 (#1595 #4)."
|
|
274
282
|
depends_on: plan
|
|
275
283
|
|
|
276
284
|
- name: implement
|
|
@@ -357,7 +365,7 @@ steps:
|
|
|
357
365
|
|
|
358
366
|
- name: deep-verify
|
|
359
367
|
skill: deep-verify
|
|
360
|
-
description: "Multi-angle release quality verification — self-review checklist if docs-only; mgr-sauron R017 + core self-check if lite"
|
|
368
|
+
description: "Multi-angle release quality verification — self-review checklist if docs-only; mgr-sauron R017 + core self-check if lite. MULTI-PHASE: 스킬을 그대로 spawn하지 말고 R020 「위임 경계를 Phase 개수로 설계」에 따라 단일 목표 위임으로 분할해 순차 발주한다 (#1595 #4)."
|
|
361
369
|
depends_on: verify-build
|
|
362
370
|
|
|
363
371
|
- name: release
|
|
@@ -431,7 +439,17 @@ steps:
|
|
|
431
439
|
- No existing tags → v0.1.0
|
|
432
440
|
- Previous tag exists → DEFAULT to patch. When in doubt, patch — do NOT reflexively bump minor for rule/doc/skill edits.
|
|
433
441
|
- patch (DEFAULT): rule/doc/skill/config/wiki/workflow changes, bugfixes, hardening, CC-compat notes — the vast majority of this project's changes
|
|
434
|
-
- minor: ONLY a
|
|
442
|
+
- minor: ONLY a new user-facing capability that changes HOW the harness is used — a new
|
|
443
|
+
workflow axis, a new command surface users must learn, or a contract other components
|
|
444
|
+
depend on. NOT "a file was added under .claude/skills/ or .claude/agents/".
|
|
445
|
+
⚠ Counter-example (Origin: v1.1.49 세션, 사용자 지적): adding one skill + one agent
|
|
446
|
+
(agora: skills 114→115, agents 49→50) was initially scoped as v1.2.0 minor by reading
|
|
447
|
+
the old wording literally. That was WRONG — this repo adds skills routinely, and
|
|
448
|
+
skills reached 115 while the version stayed v1.1.48, so skill/agent addition is
|
|
449
|
+
ESTABLISHED as patch (target was corrected to v1.1.49). Count growth is this repo's
|
|
450
|
+
baseline rate of change, NOT a minor signal. If a version bump would follow
|
|
451
|
+
mechanically from "a new file exists", it is patch. Ask instead: does a user's
|
|
452
|
+
workflow change because of this?
|
|
435
453
|
- major: breaking changes to user-facing contracts (CLI flags, public skill/command names, public API), or a deliberate milestone declaration (e.g., v1.0.0)
|
|
436
454
|
- Previous tag is ahead of source version (e.g., tag v0.136.1, package.json 0.136.0): use next available skip-version (0.136.2)
|
|
437
455
|
|