@neikyun/ciel 6.11.3 → 6.13.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/assets/.claude/agents/ciel-critic.md +71 -12
- package/assets/.claude/agents/ciel-explorer.md +59 -18
- package/assets/.claude/agents/ciel-improver.md +6 -3
- package/assets/.claude/agents/ciel-researcher.md +85 -25
- package/assets/.claude/hooks/block-destructive.sh +2 -2
- package/assets/.claude/hooks/check-test-first.sh +2 -2
- package/assets/.claude/hooks/memory-bootstrap.sh +0 -0
- package/assets/.claude/hooks/memory-engine.py +82 -15
- package/assets/.claude/hooks/post-tool-write.sh +32 -0
- package/assets/.claude/hooks/pre-agent-gate.sh +11 -6
- package/assets/.claude/hooks/pre-compact.sh +18 -0
- package/assets/.claude/hooks/pre-tool-write.sh +56 -31
- package/assets/.claude/hooks/session-start.sh +22 -1
- package/assets/.claude/hooks/session-version-check.sh +1 -1
- package/assets/.claude/hooks/stop.sh +104 -0
- package/assets/.claude/hooks/subagent-stop.sh +54 -0
- package/assets/.claude/hooks/track-file.sh +2 -2
- package/assets/.claude/hooks/user-prompt-submit.sh +11 -15
- package/assets/.claude/settings.json +18 -4
- package/assets/AGENTS.md +1 -1
- package/assets/CLAUDE.md +103 -175
- package/assets/commands/ciel-audit.md +58 -399
- package/assets/commands/ciel-create-skill.md +24 -38
- package/assets/commands/ciel-eval.md +25 -37
- package/assets/commands/ciel-init.md +36 -126
- package/assets/commands/ciel-status.md +22 -19
- package/assets/commands/ciel-update.md +20 -39
- package/assets/platforms/opencode/.opencode/agents/ciel-researcher.md +71 -895
- package/assets/platforms/opencode/.opencode/commands/ciel-audit.md +58 -296
- package/assets/platforms/opencode/.opencode/commands/ciel-create-skill.md +24 -46
- package/assets/platforms/opencode/.opencode/commands/ciel-eval.md +25 -45
- package/assets/platforms/opencode/.opencode/commands/ciel-init.md +36 -131
- package/assets/platforms/opencode/.opencode/commands/ciel-status.md +22 -24
- package/assets/platforms/opencode/.opencode/commands/ciel-update.md +20 -40
- package/assets/platforms/opencode/AGENTS.md +4 -4
- package/assets/rules/security.md +30 -0
- package/assets/rules/testing.md +23 -0
- package/assets/skills/agile/SKILL.md +42 -0
- package/assets/skills/alerting/SKILL.md +55 -0
- package/assets/skills/api-design/SKILL.md +46 -0
- package/assets/skills/appsec/SKILL.md +43 -0
- package/assets/skills/architecture/SKILL.md +74 -0
- package/assets/skills/backend/SKILL.md +41 -0
- package/assets/skills/backup-recovery/SKILL.md +42 -0
- package/assets/skills/caching/SKILL.md +44 -0
- package/assets/skills/cdn/SKILL.md +42 -0
- package/assets/skills/chaos/SKILL.md +41 -0
- package/assets/skills/cicd-pipeline/SKILL.md +56 -0
- package/assets/skills/cloud/SKILL.md +42 -0
- package/assets/skills/code-quality/SKILL.md +42 -0
- package/assets/skills/code-review/SKILL.md +41 -0
- package/assets/skills/communication/SKILL.md +42 -0
- package/assets/skills/containers/SKILL.md +42 -0
- package/assets/skills/cqrs/SKILL.md +41 -0
- package/assets/skills/crypto/SKILL.md +46 -0
- package/assets/skills/data-engineering/SKILL.md +42 -0
- package/assets/skills/database-design/SKILL.md +46 -0
- package/assets/skills/ddd/SKILL.md +45 -0
- package/assets/skills/deployment-strategies/SKILL.md +51 -0
- package/assets/skills/desktop/SKILL.md +42 -0
- package/assets/skills/devsecops/SKILL.md +43 -0
- package/assets/skills/event-driven/SKILL.md +46 -0
- package/assets/skills/frontend/SKILL.md +41 -0
- package/assets/skills/functional/SKILL.md +42 -0
- package/assets/skills/high-availability/SKILL.md +42 -0
- package/assets/skills/iac/SKILL.md +46 -0
- package/assets/skills/logging/SKILL.md +46 -0
- package/assets/skills/meta/ciel-improve/SKILL.md +127 -0
- package/assets/skills/meta/learnings-capture/SKILL.md +105 -0
- package/assets/skills/meta/patch-spec/patch-spec.md +50 -0
- package/assets/skills/meta/skill-creator/SKILL.md +115 -0
- package/assets/skills/meta/skill-freshness-auditor/SKILL.md +164 -0
- package/assets/skills/meta/skill-variant-evaluator/SKILL.md +100 -0
- package/assets/skills/meta/skills-first-design-auditor/SKILL.md +192 -0
- package/assets/skills/ml-engineering/SKILL.md +42 -0
- package/assets/skills/mobile/SKILL.md +42 -0
- package/assets/skills/monitoring/SKILL.md +54 -0
- package/assets/skills/networking/SKILL.md +42 -0
- package/assets/skills/nosql/SKILL.md +41 -0
- package/assets/skills/oop-solid/SKILL.md +42 -0
- package/assets/skills/performance/SKILL.md +41 -0
- package/assets/skills/reactive/SKILL.md +42 -0
- package/assets/skills/release-management/SKILL.md +51 -0
- package/assets/skills/research/fact-check-claims/SKILL.md +98 -0
- package/assets/skills/research/research-forums/SKILL.md +103 -0
- package/assets/skills/research/research-github-issues/SKILL.md +103 -0
- package/assets/skills/research/research-web-sources/SKILL.md +108 -0
- package/assets/skills/research/synthesize-findings/SKILL.md +112 -0
- package/assets/skills/research/validate-source-credibility/SKILL.md +103 -0
- package/assets/skills/resilience/SKILL.md +41 -0
- package/assets/skills/serverless/SKILL.md +42 -0
- package/assets/skills/servers/SKILL.md +41 -0
- package/assets/skills/sql/SKILL.md +45 -0
- package/assets/skills/supply-chain/SKILL.md +41 -0
- package/assets/skills/system-design/SKILL.md +91 -0
- package/assets/skills/tech-leadership/SKILL.md +46 -0
- package/assets/skills/testing/SKILL.md +41 -0
- package/assets/skills/tracing/SKILL.md +36 -0
- package/assets/skills/utility/branch-cleaner/SKILL.md +195 -0
- package/assets/skills/utility/branch-setup/SKILL.md +144 -0
- package/assets/skills/utility/changelog-updater/SKILL.md +125 -0
- package/assets/skills/utility/commit-writer/SKILL.md +154 -0
- package/assets/skills/utility/issue-closer/SKILL.md +106 -0
- package/assets/skills/utility/issue-creator/SKILL.md +200 -0
- package/assets/skills/utility/pr-merger/SKILL.md +189 -0
- package/assets/skills/utility/pr-opener/SKILL.md +180 -0
- package/assets/skills/utility/release-publisher/SKILL.md +224 -0
- package/assets/skills/workflow/ciel-dev-process/SKILL.md +94 -0
- package/assets/skills/workflow/faire-gatekeeper/SKILL.md +3 -1
- package/assets/skills/workflow/prouver-verifier/SKILL.md +11 -2
- package/dist/cli/check.d.ts.map +1 -1
- package/dist/cli/check.js +11 -2
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/claude.d.ts.map +1 -1
- package/dist/cli/claude.js +0 -2
- package/dist/cli/claude.js.map +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +11 -2
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/opencode.d.ts.map +1 -1
- package/dist/cli/opencode.js +2 -1
- package/dist/cli/opencode.js.map +1 -1
- package/package.json +1 -1
- package/assets/commands/ciel-migrate.md +0 -35
- package/assets/commands/ciel-refresh.md +0 -91
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# Ciel — PreToolUse hook for Write/Edit
|
|
3
3
|
# Trigger: PreToolUse on Write|Edit
|
|
4
|
-
# Purpose:
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# Dispatch
|
|
4
|
+
# Purpose: BLOCK source code writes until dispatch gate passes (v8 — enforcement)
|
|
5
|
+
# Test files and non-code files pass through (always allowed).
|
|
6
|
+
# Escape hatch: [CIEL_GATE_BYPASS] anywhere in the tool input bypasses the gate.
|
|
7
|
+
# Dispatch tracker: /tmp/ciel_dispatched.* (created by SubagentStart hooks)
|
|
8
8
|
|
|
9
|
-
INPUT=$(cat)
|
|
9
|
+
INPUT=$(cat 2>/dev/null || echo "{}")
|
|
10
10
|
|
|
11
11
|
FILE_PATH=$(echo "$INPUT" | python3 -c "
|
|
12
12
|
import sys, json
|
|
@@ -22,14 +22,56 @@ except:
|
|
|
22
22
|
|
|
23
23
|
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-}"
|
|
24
24
|
|
|
25
|
+
# === BYPASS CHECK ===
|
|
26
|
+
# [CIEL_GATE_BYPASS] anywhere in the input is an intentional override
|
|
27
|
+
if echo "$INPUT" | grep -q '\[CIEL_GATE_BYPASS\]'; then
|
|
28
|
+
echo "[CIEL] Gate bypassed via [CIEL_GATE_BYPASS] — allowing write to $(basename "$FILE_PATH")" >&2
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# === FILE CLASSIFICATION ===
|
|
33
|
+
# Source code files that require dispatch before editing
|
|
34
|
+
IS_SOURCE=0
|
|
35
|
+
if echo "$FILE_PATH" | grep -qE '\.(kt|java|ts|tsx|js|jsx|py|go|rs|rb|php|cs|cpp|c|swift|scala|vue|svelte)$'; then
|
|
36
|
+
IS_SOURCE=1
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# Test files always pass (test-first RED)
|
|
40
|
+
IS_TEST=0
|
|
41
|
+
if echo "$FILE_PATH" | grep -qE '\.(test|spec)\.|_test\.|_spec\.|/test/|/tests/|/__tests__/'; then
|
|
42
|
+
IS_TEST=1
|
|
43
|
+
fi
|
|
44
|
+
|
|
25
45
|
# === DISPATCH GATE CHECK ===
|
|
26
|
-
# /tmp/ciel_dispatched
|
|
46
|
+
# /tmp/ciel_dispatched.* files created by SubagentStart hooks when Ciel agents dispatch
|
|
27
47
|
DISPATCHED=0
|
|
28
|
-
|
|
29
|
-
if [ -f "$DISPATCH_FLAG" ]; then
|
|
48
|
+
if ls /tmp/ciel_dispatched.* >/dev/null 2>&1; then
|
|
30
49
|
DISPATCHED=1
|
|
31
50
|
fi
|
|
32
51
|
|
|
52
|
+
# === DEPTH CHECK ===
|
|
53
|
+
# Read depth classification from UserPromptSubmit hook (auto-bypass for Trivial)
|
|
54
|
+
TASK_DEPTH="Standard"
|
|
55
|
+
if [ -n "$PROJECT_DIR" ] && [ -f "$PROJECT_DIR/.ciel/last-depth" ]; then
|
|
56
|
+
TASK_DEPTH=$(cat "$PROJECT_DIR/.ciel/last-depth" 2>/dev/null || echo "Standard")
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
# === DISPATCH GATE — BLOCK (v8 enforcement) ===
|
|
60
|
+
# Block source code edits when no Ciel agent has been dispatched.
|
|
61
|
+
# Auto-bypass for Trivial tasks (depth classified by UserPromptSubmit hook).
|
|
62
|
+
# Skip non-code files (docs, config, JSON, YAML, etc.) — safe to edit inline.
|
|
63
|
+
# Skip test files — test-first RED means tests must be written before source.
|
|
64
|
+
if [ "$IS_SOURCE" -eq 1 ] && [ "$IS_TEST" -eq 0 ] && [ "$DISPATCHED" -eq 0 ] && [ "$TASK_DEPTH" != "Trivial" ]; then
|
|
65
|
+
echo "[CIEL DISPATCH GATE] BLOCKED: Write to $(basename "$FILE_PATH")" >&2
|
|
66
|
+
echo "" >&2
|
|
67
|
+
echo " Depth: $TASK_DEPTH — no Ciel agent dispatched yet." >&2
|
|
68
|
+
echo " Dispatch ciel-researcher + ciel-explorer in parallel (Agent tool)," >&2
|
|
69
|
+
echo " with relevant domain skill names in the dispatch prompt." >&2
|
|
70
|
+
echo "" >&2
|
|
71
|
+
echo " This is actually a Trivial task? Use [CIEL_GATE_BYPASS]." >&2
|
|
72
|
+
exit 2
|
|
73
|
+
fi
|
|
74
|
+
|
|
33
75
|
# === FILE TRACK COUNT (RELIRE GATE) ===
|
|
34
76
|
COUNT=0
|
|
35
77
|
if [ -n "$PROJECT_DIR" ] && [ -f "$PROJECT_DIR/.ciel/tracked-files.json" ]; then
|
|
@@ -40,31 +82,14 @@ except: print(0)
|
|
|
40
82
|
" 2>/dev/null || echo "0")
|
|
41
83
|
fi
|
|
42
84
|
|
|
43
|
-
#
|
|
44
|
-
WARNINGS=""
|
|
45
|
-
|
|
46
|
-
# Dispatch gate warning (no dispatched agents on non-trivial write)
|
|
47
|
-
if [ "$DISPATCHED" -eq 0 ] && [ "$COUNT" -ge 1 ]; then
|
|
48
|
-
WARNINGS="${WARNINGS}[DISPATCH GATE] WARNING: Writing file ${FILE_PATH} without prior Task() dispatch (ciel-researcher + ciel-explorer). Was this classified as Trivial? If Standard+, dispatch subagents BEFORE writing code."
|
|
49
|
-
fi
|
|
50
|
-
|
|
51
|
-
# RELIRE gate warning
|
|
85
|
+
# RELIRE gate warning (3+ files → critic required)
|
|
52
86
|
if [ "${COUNT:-0}" -ge 2 ] 2>/dev/null; then
|
|
53
|
-
|
|
54
|
-
WARNINGS="${WARNINGS}${PIPELINE_WARN}"
|
|
55
|
-
fi
|
|
56
|
-
|
|
57
|
-
# If only dispatch gate fires, prefix to std err
|
|
58
|
-
if [ -n "$WARNINGS" ]; then
|
|
59
|
-
echo "[CIEL PRE-WRITE]" >&2
|
|
60
|
-
echo "$WARNINGS" | while IFS= read -r line; do
|
|
61
|
-
echo " $line" >&2
|
|
62
|
-
done
|
|
87
|
+
echo "[CIEL RELIRE GATE] ${COUNT} file(s) edited — dispatch ciel-critic MODE=RELIRE when done." >&2
|
|
63
88
|
fi
|
|
64
89
|
|
|
65
90
|
# === FAIRE GATE REMINDER ===
|
|
66
|
-
# Skip non-code files
|
|
67
|
-
if
|
|
91
|
+
# Skip non-code files for faire gate
|
|
92
|
+
if [ "$IS_SOURCE" -eq 0 ] && [ "$IS_TEST" -eq 0 ]; then
|
|
68
93
|
exit 0
|
|
69
94
|
fi
|
|
70
95
|
|
|
@@ -75,9 +100,9 @@ if echo "$FILE_PATH" | grep -qiE '(auth|Auth|security|Security|Token|Session|Pas
|
|
|
75
100
|
fi
|
|
76
101
|
|
|
77
102
|
if $CRITICAL; then
|
|
78
|
-
echo " [CIEL] Critical path: invoke faire-gatekeeper, stride-analyzer must have run, test-first (RED)." >&2
|
|
103
|
+
echo " [CIEL] Critical path: invoke faire-gatekeeper, stride-analyzer must have run, test-first (RED). After FAIRE: TESTER (run test suite)." >&2
|
|
79
104
|
else
|
|
80
|
-
echo " [CIEL] Standard path: invoke faire-gatekeeper (alternatives, idiomatic, quality, removal, test-first)." >&2
|
|
105
|
+
echo " [CIEL] Standard path: invoke faire-gatekeeper (alternatives, idiomatic, quality, removal, test-first). After FAIRE: TESTER (run test suite)." >&2
|
|
81
106
|
fi
|
|
82
107
|
|
|
83
108
|
exit 0
|
|
@@ -88,7 +88,14 @@ try:
|
|
|
88
88
|
lines = [f\" [{mid}, {m.get('trigger_count', 0)}x] {m.get('title', '?')}\" for mid, m in top]
|
|
89
89
|
total = len(active)
|
|
90
90
|
more = f' (+{total - len(top)} more)' if total > len(top) else ''
|
|
91
|
-
|
|
91
|
+
promo = [(mid, m) for mid, m in mems.items() if (m.get('trigger_count') or 0) >= 5 and str(m.get('file', '')).startswith('episodes/')]
|
|
92
|
+
promo_hint = ''
|
|
93
|
+
if promo:
|
|
94
|
+
promo.sort(key=lambda x: -(x[1].get('trigger_count') or 0))
|
|
95
|
+
promo_names = ', '.join([m.get('title', '?') for _, m in promo[:3]])
|
|
96
|
+
more_promo = f' +{len(promo) - 3} more' if len(promo) > 3 else ''
|
|
97
|
+
promo_hint = '\\nConsolidation candidates (' + str(len(promo)) + ' episodes >=5 triggers): ' + promo_names + more_promo + '. Run memoire-consolidator.'
|
|
98
|
+
print(f'Cued-recall memory active ({total} memories{more}):\\n' + '\\n'.join(lines) + promo_hint)
|
|
92
99
|
except Exception:
|
|
93
100
|
print('')
|
|
94
101
|
" 2>/dev/null || echo "")
|
|
@@ -103,6 +110,20 @@ elif [[ -d "$CWD/.ciel" ]] || [[ -f "$CWD/.claude/settings.json" ]] || [[ -f "$C
|
|
|
103
110
|
MSG+=$'\n'"No cued-recall memory yet. Run /ciel-memory-bootstrap to scan project for ingestable tribal docs (lessons.md, ciel-overlay.md, .claude/rules/, etc.)."
|
|
104
111
|
fi
|
|
105
112
|
|
|
113
|
+
# ─── Pre-flight checklist — injected into every session ──────────────────────
|
|
114
|
+
MSG+=$'\n'"---"
|
|
115
|
+
MSG+=$'\n'"Checklist pre-vol (verifier avant chaque tache) :"
|
|
116
|
+
MSG+=$'\n'" Logs : structured JSON + correlation ID par requete ?"
|
|
117
|
+
MSG+=$'\n'" Backups : RPO/RTO definis ? Test de restore fait ?"
|
|
118
|
+
MSG+=$'\n'" Cache : TTL + strategie d'invalidation en place ?"
|
|
119
|
+
MSG+=$'\n'" Timeouts : explicites (connect/read/request) — pas d'infini ?"
|
|
120
|
+
MSG+=$'\n'" Securite : auth, injection, CSRF, rate limiting verifies ?"
|
|
121
|
+
MSG+=$'\n'" Metriques : RED (Rate, Errors, Duration) exposees par endpoint ?"
|
|
122
|
+
MSG+=$'\n'" Deploiement : CI/CD automatise, health check, rollback possible ?"
|
|
123
|
+
MSG+=$'\n'" Pagination : cursor-based, limite max definie ?"
|
|
124
|
+
MSG+=$'\n'" Erreurs : structurees (code + message + details) ?"
|
|
125
|
+
MSG+=$'\n'" Angles morts : 3 choses identifiees qui manquent dans la demande ?"
|
|
126
|
+
|
|
106
127
|
# ─── Update check (throttled to once per 24h, never blocks) ──────────────────
|
|
107
128
|
# Fetches GitHub VERSION non-blocking (max 2s). Any failure → silent skip.
|
|
108
129
|
MANIFEST="$HOME/.ciel/manifest.json"
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
set -euo pipefail
|
|
6
6
|
|
|
7
7
|
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(cd "$(dirname "$0")/.." && pwd)}"
|
|
8
|
-
LOCAL_VERSION=$(cat "$PROJECT_DIR/VERSION" 2>/dev/null || echo "0.0.0")
|
|
8
|
+
LOCAL_VERSION=$(cat "$PROJECT_DIR/.ciel/version" 2>/dev/null || cat "$PROJECT_DIR/VERSION" 2>/dev/null || echo "0.0.0" || true)
|
|
9
9
|
|
|
10
10
|
REMOTE_VERSION=$(curl -fsSL --connect-timeout 3 "https://raw.githubusercontent.com/KaosKyun/Ciel/main/VERSION" 2>/dev/null || true)
|
|
11
11
|
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Ciel — Stop hook
|
|
3
|
+
# Trigger: Claude finishes responding (end of task)
|
|
4
|
+
# Purpose: (1) inject meta-critiquer instruction; (2) if on default branch with
|
|
5
|
+
# 3+ unreleased feat/fix commits, prepend a release-gate reminder.
|
|
6
|
+
#
|
|
7
|
+
# Claude Code Stop-hook schema rejects hookSpecificOutput.additionalContext
|
|
8
|
+
# (it is only valid for UserPromptSubmit/PostToolUse). The documented way to
|
|
9
|
+
# steer the model at Stop is {"decision":"block","reason":"..."} — the reason
|
|
10
|
+
# is surfaced as an instruction the model must address.
|
|
11
|
+
#
|
|
12
|
+
# Both meta-critiquer and release-gate are combined into a single `reason`
|
|
13
|
+
# field so only one block event fires per Stop. The existing stop_hook_active
|
|
14
|
+
# loop guard handles re-entry for both.
|
|
15
|
+
|
|
16
|
+
INPUT=$(cat 2>/dev/null || echo "{}")
|
|
17
|
+
|
|
18
|
+
ACTIVE=$(python3 -c "
|
|
19
|
+
import sys, json
|
|
20
|
+
try:
|
|
21
|
+
d = json.loads(sys.argv[1])
|
|
22
|
+
print('true' if d.get('stop_hook_active', False) else 'false')
|
|
23
|
+
except Exception:
|
|
24
|
+
print('false')
|
|
25
|
+
" "$INPUT" 2>/dev/null || echo "false")
|
|
26
|
+
|
|
27
|
+
if [ "$ACTIVE" = "true" ]; then
|
|
28
|
+
exit 0
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Fail-safe: block at most once per 60s window even if stop_hook_active
|
|
32
|
+
# is not set (older Claude Code versions, parsing edge cases, plugin
|
|
33
|
+
# auto-discovery re-invoking the same hook from multiple registrations).
|
|
34
|
+
# Without this, the same Stop event can fire 9 times → CC overrides the
|
|
35
|
+
# hook and emits the "blocked turn 9 times" warning.
|
|
36
|
+
PROJECT_KEY=$(echo "${CLAUDE_PROJECT_DIR:-$PWD}" | (shasum 2>/dev/null || sha1sum 2>/dev/null || md5sum 2>/dev/null || md5 -q 2>/dev/null || cksum 2>/dev/null) | cut -c1-12)
|
|
37
|
+
LAST_BLOCK_FILE="${TMPDIR:-/tmp}/ciel-stop-last-block-${PROJECT_KEY}"
|
|
38
|
+
NOW=$(date +%s)
|
|
39
|
+
LAST=$(cat "$LAST_BLOCK_FILE" 2>/dev/null || echo 0)
|
|
40
|
+
if [ $((NOW - LAST)) -lt 60 ]; then
|
|
41
|
+
exit 0
|
|
42
|
+
fi
|
|
43
|
+
echo "$NOW" > "$LAST_BLOCK_FILE" 2>/dev/null || true
|
|
44
|
+
|
|
45
|
+
CWD=$(python3 -c "
|
|
46
|
+
import sys, json
|
|
47
|
+
try:
|
|
48
|
+
d = json.loads(sys.argv[1])
|
|
49
|
+
print(d.get('cwd', ''))
|
|
50
|
+
except Exception:
|
|
51
|
+
print('')
|
|
52
|
+
" "$INPUT" 2>/dev/null || echo "")
|
|
53
|
+
|
|
54
|
+
# Release-gate check — writes RG_MSG if it should fire
|
|
55
|
+
RG_MSG=""
|
|
56
|
+
check_release_gate() {
|
|
57
|
+
local cwd="$1"
|
|
58
|
+
[ -z "$cwd" ] && return 1
|
|
59
|
+
command -v git >/dev/null 2>&1 || return 1
|
|
60
|
+
git -C "$cwd" rev-parse --git-dir >/dev/null 2>&1 || return 1
|
|
61
|
+
|
|
62
|
+
local current default
|
|
63
|
+
current=$(git -C "$cwd" rev-parse --abbrev-ref HEAD 2>/dev/null)
|
|
64
|
+
default=$(git -C "$cwd" symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')
|
|
65
|
+
[ -z "$default" ] && default="main"
|
|
66
|
+
[ "$current" = "$default" ] || return 1
|
|
67
|
+
|
|
68
|
+
local snooze="$cwd/.ciel-release-snooze"
|
|
69
|
+
if [ -f "$snooze" ] && find "$snooze" -mmin -60 2>/dev/null | grep -q .; then
|
|
70
|
+
return 1
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
local last_tag range pending
|
|
74
|
+
last_tag=$(git -C "$cwd" describe --tags --abbrev=0 2>/dev/null || echo "")
|
|
75
|
+
if [ -z "$last_tag" ]; then
|
|
76
|
+
range="HEAD"
|
|
77
|
+
else
|
|
78
|
+
range="$last_tag..HEAD"
|
|
79
|
+
fi
|
|
80
|
+
pending=$(git -C "$cwd" log "$range" --oneline 2>/dev/null | grep -cE '^[a-f0-9]+ (feat|fix)(\(|:|!)' || echo 0)
|
|
81
|
+
|
|
82
|
+
[ "$pending" -ge 3 ] || return 1
|
|
83
|
+
|
|
84
|
+
local tag_label="${last_tag:-<no previous tag>}"
|
|
85
|
+
RG_MSG="CIEL RELEASE-GATE — $pending feat/fix commit(s) on $default since $tag_label without a release. Actions: (1) bump VERSION per conventional-commit scope (feat=minor, fix=patch, feat!/fix!=major), (2) append CHANGELOG.md entry, (3) git tag -a v<N.N.N>, (4) gh release create v<N.N.N> --generate-notes. Invoke changelog-updater + release-publisher skills. Snooze 60min: touch .ciel-release-snooze."
|
|
86
|
+
return 0
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
META_MSG="CIEL STOP — 30s META-CRITIQUER obligatoire avant de declarer fini: (1) depth match? (2) new failure mode → Guard? (3) user correction → memoire (capture to .ciel/memory/episodes/ via memory-engine.py)? (4) stale branches? (5) uncovered issues? (6) context health? (7) session-progress.md written? (8) dead code sweep (ruff/knip/Detekt)? (9) agent-discovered pattern → memoire capture (if you noticed a reusable pattern, bug, or convention not yet in .ciel/memory/ — call memory-engine.py capture with --captured-from=agent-observed)? (10) 5+ triggers without promotion → invoke memoire-consolidator? Invoke meta-critiquer skill then memoire."
|
|
90
|
+
|
|
91
|
+
if check_release_gate "$CWD"; then
|
|
92
|
+
MSG="$RG_MSG
|
|
93
|
+
|
|
94
|
+
$META_MSG"
|
|
95
|
+
else
|
|
96
|
+
MSG="$META_MSG"
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
python3 -c "
|
|
100
|
+
import json, sys
|
|
101
|
+
print(json.dumps({'decision': 'block', 'reason': sys.argv[1]}))
|
|
102
|
+
" "$MSG"
|
|
103
|
+
|
|
104
|
+
exit 0
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Ciel — SubagentStop hook
|
|
3
|
+
# Trigger: subagent finishes
|
|
4
|
+
# Purpose: log agent report size to eval log; warn if < 200 tokens on Standard/Critical task
|
|
5
|
+
# Passive — does not inject context, just logs
|
|
6
|
+
|
|
7
|
+
INPUT=$(cat 2>/dev/null || echo "{}")
|
|
8
|
+
|
|
9
|
+
# Extract agent name + result size (rough word count)
|
|
10
|
+
AGENT=$(echo "$INPUT" | python3 -c "
|
|
11
|
+
import sys, json
|
|
12
|
+
try:
|
|
13
|
+
d = json.load(sys.stdin)
|
|
14
|
+
print(d.get('agent_type', d.get('subagent_type', 'unknown')))
|
|
15
|
+
except:
|
|
16
|
+
print('unknown')
|
|
17
|
+
" 2>/dev/null || echo "unknown")
|
|
18
|
+
|
|
19
|
+
RESULT=$(echo "$INPUT" | python3 -c "
|
|
20
|
+
import sys, json
|
|
21
|
+
try:
|
|
22
|
+
d = json.load(sys.stdin)
|
|
23
|
+
result = d.get('result', d.get('output', ''))
|
|
24
|
+
print(len(result.split()) if result else 0)
|
|
25
|
+
except:
|
|
26
|
+
print(0)
|
|
27
|
+
" 2>/dev/null || echo "0")
|
|
28
|
+
|
|
29
|
+
# Rough token estimate: 1 word ≈ 1.33 tokens
|
|
30
|
+
TOKENS=$((RESULT * 133 / 100))
|
|
31
|
+
|
|
32
|
+
# Log to evals/results (if CIEL_TRACE_ID set)
|
|
33
|
+
# Uses mkdir-based locking for atomic JSONL appends (portable, no flock dependency)
|
|
34
|
+
if [[ -n "${CIEL_TRACE_ID:-}" ]]; then
|
|
35
|
+
LOG_DIR="$HOME/.ciel/evals/results"
|
|
36
|
+
mkdir -p "$LOG_DIR" 2>/dev/null || true
|
|
37
|
+
LOCK_DIR="$LOG_DIR/.write.lock"
|
|
38
|
+
# Spin-wait with 1s timeout to avoid infinite block
|
|
39
|
+
for _ in $(seq 1 10); do
|
|
40
|
+
if mkdir "$LOCK_DIR" 2>/dev/null; then
|
|
41
|
+
echo "{\"trace_id\":\"$CIEL_TRACE_ID\",\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"agent\":\"$AGENT\",\"tokens\":$TOKENS}" >> "$LOG_DIR/subagent-stops.jsonl" 2>/dev/null || true
|
|
42
|
+
rmdir "$LOCK_DIR" 2>/dev/null || true
|
|
43
|
+
break
|
|
44
|
+
fi
|
|
45
|
+
sleep 0.1
|
|
46
|
+
done
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Warn if truncation suspected
|
|
50
|
+
if [[ $TOKENS -lt 200 && $TOKENS -gt 0 ]]; then
|
|
51
|
+
echo "CIEL WARN — $AGENT agent report is only ${TOKENS} tokens. Suspect truncation on Standard/Critical task. Consider re-dispatching with narrower scope." >&2
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
exit 0
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
# CIEL FILE TRACKING: log modified files for RELIRE trigger
|
|
3
3
|
# exit 0 = allow (always)
|
|
4
4
|
|
|
5
|
-
INPUT=$(cat)
|
|
6
|
-
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.filePath // ""')
|
|
5
|
+
INPUT=$(cat 2>/dev/null || echo "{}")
|
|
6
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.filePath // ""' 2>/dev/null || echo "")
|
|
7
7
|
TRACK_FILE="$CLAUDE_PROJECT_DIR/.ciel/tracked-files.json"
|
|
8
8
|
|
|
9
9
|
if [ -z "$FILE_PATH" ] || [ -z "$CLAUDE_PROJECT_DIR" ]; then
|
|
@@ -17,21 +17,12 @@ except:
|
|
|
17
17
|
|
|
18
18
|
[ -z "$PROMPT" ] && exit 0
|
|
19
19
|
|
|
20
|
-
#
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
DEPTH="Critical"
|
|
27
|
-
REASON="auth/security/payment keyword detected"
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
# Check for Trivial signals (only if not Critical)
|
|
31
|
-
if [[ "$DEPTH" != "Critical" ]] && echo "$PROMPT" | grep -qiE '\b(rename|typo|copyright|comment|readme|1-line|one.line|fix.typo|spelling)\b'; then
|
|
32
|
-
DEPTH="Trivial"
|
|
33
|
-
REASON="rename/typo/docs keyword detected"
|
|
34
|
-
fi
|
|
20
|
+
# Depth classification is model-driven, not regex-driven.
|
|
21
|
+
# Default to Standard — the model reclassifies via depth-classifier skill at DOCS step
|
|
22
|
+
# and writes the result to .ciel/last-depth (read by pre-tool-write gate).
|
|
23
|
+
# No mechanical keyword detection — regex is too imprecise for AI-driven tasks.
|
|
24
|
+
DEPTH="Standard"
|
|
25
|
+
REASON="model reclassifies via depth-classifier at DOCS — write to .ciel/last-depth"
|
|
35
26
|
|
|
36
27
|
DISPATCH_GATE=""
|
|
37
28
|
if [[ "$DEPTH" == "Standard" || "$DEPTH" == "Critical" ]]; then
|
|
@@ -103,6 +94,11 @@ if [[ -n "$ENGINE_PATH" ]] && [[ -n "$PROJECT_DIR" ]] && [[ -f "$PROJECT_DIR/.ci
|
|
|
103
94
|
MEMORY_OUTPUT=$(python3 "$ENGINE_PATH" query --prompt "$PROMPT" --cwd "$PROJECT_DIR" --depth "$DEPTH_LOWER" 2>/dev/null || echo "")
|
|
104
95
|
fi
|
|
105
96
|
|
|
97
|
+
# Persist depth classification for downstream hooks (pre-tool-write gate reads this)
|
|
98
|
+
if [ -n "${CLAUDE_PROJECT_DIR:-}" ]; then
|
|
99
|
+
echo "$DEPTH" > "$CLAUDE_PROJECT_DIR/.ciel/last-depth" 2>/dev/null || true
|
|
100
|
+
fi
|
|
101
|
+
|
|
106
102
|
MSG_BASE="CIEL depth hint: $DEPTH ($REASON).$DISPATCH_GATE$META_GATE$INTERVENTION_GATE Invoke depth-classifier if ambiguous before routing pipeline."
|
|
107
103
|
|
|
108
104
|
# Emit JSON via python to handle newlines and quoting safely
|
|
@@ -15,12 +15,26 @@
|
|
|
15
15
|
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
|
|
16
16
|
},
|
|
17
17
|
"hooks": {
|
|
18
|
+
"UserPromptSubmit": [
|
|
19
|
+
{
|
|
20
|
+
"hooks": [
|
|
21
|
+
{
|
|
22
|
+
"type": "command",
|
|
23
|
+
"command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/user-prompt-submit.sh\""
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
],
|
|
18
28
|
"SessionStart": [
|
|
19
29
|
{
|
|
20
30
|
"hooks": [
|
|
21
31
|
{
|
|
22
32
|
"type": "command",
|
|
23
|
-
"command": "
|
|
33
|
+
"command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/session-start.sh\""
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"type": "command",
|
|
37
|
+
"command": "{ ! [ -x \"$CLAUDE_PROJECT_DIR/.claude/hooks/session-version-check.sh\" ] || \"$CLAUDE_PROJECT_DIR/.claude/hooks/session-version-check.sh\"; }"
|
|
24
38
|
}
|
|
25
39
|
]
|
|
26
40
|
}
|
|
@@ -80,7 +94,7 @@
|
|
|
80
94
|
"hooks": [
|
|
81
95
|
{
|
|
82
96
|
"type": "command",
|
|
83
|
-
"command": "
|
|
97
|
+
"command": "echo \"$(date +%s)\" > \"/tmp/ciel_dispatched.$$\" && echo \"[CIEL] Explorer started: $(date -u +%Y-%m-%dT%H:%M:%SZ)\" >> \"$CLAUDE_PROJECT_DIR/.ciel/exploration-log.md\""
|
|
84
98
|
}
|
|
85
99
|
]
|
|
86
100
|
},
|
|
@@ -89,7 +103,7 @@
|
|
|
89
103
|
"hooks": [
|
|
90
104
|
{
|
|
91
105
|
"type": "command",
|
|
92
|
-
"command": "
|
|
106
|
+
"command": "echo \"$(date +%s)\" > \"/tmp/ciel_dispatched.$$\" && echo \"[CIEL] Researcher started: $(date -u +%Y-%m-%dT%H:%M:%SZ)\" >> \"$CLAUDE_PROJECT_DIR/.ciel/subagent-log.md\""
|
|
93
107
|
}
|
|
94
108
|
]
|
|
95
109
|
},
|
|
@@ -98,7 +112,7 @@
|
|
|
98
112
|
"hooks": [
|
|
99
113
|
{
|
|
100
114
|
"type": "command",
|
|
101
|
-
"command": "echo \"[CIEL] Critic started: $(date -u +%Y-%m-%dT%H:%M:%SZ)\" >> \"$CLAUDE_PROJECT_DIR/.ciel/subagent-log.md\""
|
|
115
|
+
"command": "echo \"$(date +%s)\" > \"/tmp/ciel_dispatched.$$\" && echo \"[CIEL] Critic started: $(date -u +%Y-%m-%dT%H:%M:%SZ)\" >> \"$CLAUDE_PROJECT_DIR/.ciel/subagent-log.md\""
|
|
102
116
|
}
|
|
103
117
|
]
|
|
104
118
|
}
|
package/assets/AGENTS.md
CHANGED
|
@@ -78,7 +78,7 @@ The `ciel.ts` plugin injects depth classification on every user prompt and RELIR
|
|
|
78
78
|
Ciel ships a `.mcp.json` template at the repo root with two opt-in servers: `playwright` (visual critique) and `context7` (live official docs). Register them via:
|
|
79
79
|
|
|
80
80
|
```bash
|
|
81
|
-
bash
|
|
81
|
+
bash <(curl -fsSL https://raw.githubusercontent.com/KaosKyun/Ciel/main/scripts/install.sh) --with-mcp=playwright,context7
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|
**Important** — OpenCode issue #2319: plugin hooks (`tool.execute.before/after`) do NOT fire for MCP tool calls. The `playwright-visual-critic` skill orchestrates the flow explicitly (navigate → snapshot → dispatch `@ciel-critic`) rather than relying on auto-triggered hooks. When you use a visual-critique workflow, dispatch the critic agent yourself after capture.
|