@neikyun/ciel 6.11.3 → 6.13.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.
Files changed (128) hide show
  1. package/assets/.claude/agents/ciel-critic.md +71 -12
  2. package/assets/.claude/agents/ciel-explorer.md +59 -18
  3. package/assets/.claude/agents/ciel-improver.md +6 -3
  4. package/assets/.claude/agents/ciel-researcher.md +85 -25
  5. package/assets/.claude/hooks/block-destructive.sh +2 -2
  6. package/assets/.claude/hooks/check-test-first.sh +2 -2
  7. package/assets/.claude/hooks/memory-bootstrap.sh +0 -0
  8. package/assets/.claude/hooks/memory-engine.py +82 -15
  9. package/assets/.claude/hooks/post-tool-write.sh +32 -0
  10. package/assets/.claude/hooks/pre-agent-gate.sh +11 -6
  11. package/assets/.claude/hooks/pre-compact.sh +18 -0
  12. package/assets/.claude/hooks/pre-tool-write.sh +56 -31
  13. package/assets/.claude/hooks/session-start.sh +22 -1
  14. package/assets/.claude/hooks/session-version-check.sh +1 -1
  15. package/assets/.claude/hooks/stop.sh +104 -0
  16. package/assets/.claude/hooks/subagent-stop.sh +54 -0
  17. package/assets/.claude/hooks/track-file.sh +2 -2
  18. package/assets/.claude/hooks/user-prompt-submit.sh +11 -15
  19. package/assets/.claude/settings.json +18 -4
  20. package/assets/AGENTS.md +1 -1
  21. package/assets/CLAUDE.md +103 -175
  22. package/assets/commands/ciel-audit.md +58 -399
  23. package/assets/commands/ciel-create-skill.md +24 -38
  24. package/assets/commands/ciel-eval.md +25 -37
  25. package/assets/commands/ciel-init.md +36 -126
  26. package/assets/commands/ciel-status.md +22 -19
  27. package/assets/commands/ciel-update.md +20 -39
  28. package/assets/platforms/opencode/.opencode/agents/ciel-researcher.md +71 -895
  29. package/assets/platforms/opencode/.opencode/commands/ciel-audit.md +58 -296
  30. package/assets/platforms/opencode/.opencode/commands/ciel-create-skill.md +24 -46
  31. package/assets/platforms/opencode/.opencode/commands/ciel-eval.md +25 -45
  32. package/assets/platforms/opencode/.opencode/commands/ciel-init.md +36 -131
  33. package/assets/platforms/opencode/.opencode/commands/ciel-status.md +22 -24
  34. package/assets/platforms/opencode/.opencode/commands/ciel-update.md +20 -40
  35. package/assets/platforms/opencode/AGENTS.md +4 -4
  36. package/assets/rules/security.md +30 -0
  37. package/assets/rules/testing.md +23 -0
  38. package/assets/skills/agile/SKILL.md +42 -0
  39. package/assets/skills/alerting/SKILL.md +55 -0
  40. package/assets/skills/api-design/SKILL.md +46 -0
  41. package/assets/skills/appsec/SKILL.md +43 -0
  42. package/assets/skills/architecture/SKILL.md +74 -0
  43. package/assets/skills/backend/SKILL.md +41 -0
  44. package/assets/skills/backup-recovery/SKILL.md +42 -0
  45. package/assets/skills/caching/SKILL.md +44 -0
  46. package/assets/skills/cdn/SKILL.md +42 -0
  47. package/assets/skills/chaos/SKILL.md +41 -0
  48. package/assets/skills/cicd-pipeline/SKILL.md +56 -0
  49. package/assets/skills/cloud/SKILL.md +42 -0
  50. package/assets/skills/code-quality/SKILL.md +42 -0
  51. package/assets/skills/code-review/SKILL.md +41 -0
  52. package/assets/skills/communication/SKILL.md +42 -0
  53. package/assets/skills/containers/SKILL.md +42 -0
  54. package/assets/skills/cqrs/SKILL.md +41 -0
  55. package/assets/skills/crypto/SKILL.md +46 -0
  56. package/assets/skills/data-engineering/SKILL.md +42 -0
  57. package/assets/skills/database-design/SKILL.md +46 -0
  58. package/assets/skills/ddd/SKILL.md +45 -0
  59. package/assets/skills/deployment-strategies/SKILL.md +51 -0
  60. package/assets/skills/desktop/SKILL.md +42 -0
  61. package/assets/skills/devsecops/SKILL.md +43 -0
  62. package/assets/skills/event-driven/SKILL.md +46 -0
  63. package/assets/skills/frontend/SKILL.md +41 -0
  64. package/assets/skills/functional/SKILL.md +42 -0
  65. package/assets/skills/high-availability/SKILL.md +42 -0
  66. package/assets/skills/iac/SKILL.md +46 -0
  67. package/assets/skills/logging/SKILL.md +46 -0
  68. package/assets/skills/meta/ciel-improve/SKILL.md +127 -0
  69. package/assets/skills/meta/learnings-capture/SKILL.md +105 -0
  70. package/assets/skills/meta/patch-spec/patch-spec.md +50 -0
  71. package/assets/skills/meta/skill-creator/SKILL.md +115 -0
  72. package/assets/skills/meta/skill-freshness-auditor/SKILL.md +164 -0
  73. package/assets/skills/meta/skill-variant-evaluator/SKILL.md +100 -0
  74. package/assets/skills/meta/skills-first-design-auditor/SKILL.md +192 -0
  75. package/assets/skills/ml-engineering/SKILL.md +42 -0
  76. package/assets/skills/mobile/SKILL.md +42 -0
  77. package/assets/skills/monitoring/SKILL.md +54 -0
  78. package/assets/skills/networking/SKILL.md +42 -0
  79. package/assets/skills/nosql/SKILL.md +41 -0
  80. package/assets/skills/oop-solid/SKILL.md +42 -0
  81. package/assets/skills/performance/SKILL.md +41 -0
  82. package/assets/skills/reactive/SKILL.md +42 -0
  83. package/assets/skills/release-management/SKILL.md +51 -0
  84. package/assets/skills/research/fact-check-claims/SKILL.md +98 -0
  85. package/assets/skills/research/research-forums/SKILL.md +103 -0
  86. package/assets/skills/research/research-github-issues/SKILL.md +103 -0
  87. package/assets/skills/research/research-web-sources/SKILL.md +108 -0
  88. package/assets/skills/research/synthesize-findings/SKILL.md +112 -0
  89. package/assets/skills/research/validate-source-credibility/SKILL.md +103 -0
  90. package/assets/skills/resilience/SKILL.md +41 -0
  91. package/assets/skills/serverless/SKILL.md +42 -0
  92. package/assets/skills/servers/SKILL.md +41 -0
  93. package/assets/skills/sql/SKILL.md +45 -0
  94. package/assets/skills/supply-chain/SKILL.md +41 -0
  95. package/assets/skills/system-design/SKILL.md +91 -0
  96. package/assets/skills/tech-leadership/SKILL.md +46 -0
  97. package/assets/skills/testing/SKILL.md +41 -0
  98. package/assets/skills/tracing/SKILL.md +36 -0
  99. package/assets/skills/utility/branch-cleaner/SKILL.md +195 -0
  100. package/assets/skills/utility/branch-setup/SKILL.md +144 -0
  101. package/assets/skills/utility/changelog-updater/SKILL.md +125 -0
  102. package/assets/skills/utility/commit-writer/SKILL.md +154 -0
  103. package/assets/skills/utility/issue-closer/SKILL.md +106 -0
  104. package/assets/skills/utility/issue-creator/SKILL.md +200 -0
  105. package/assets/skills/utility/pr-merger/SKILL.md +189 -0
  106. package/assets/skills/utility/pr-opener/SKILL.md +180 -0
  107. package/assets/skills/utility/release-publisher/SKILL.md +224 -0
  108. package/assets/skills/workflow/ciel-dev-process/SKILL.md +94 -0
  109. package/assets/skills/workflow/faire-gatekeeper/SKILL.md +3 -1
  110. package/assets/skills/workflow/prouver-verifier/SKILL.md +11 -2
  111. package/dist/cli/check.d.ts +1 -0
  112. package/dist/cli/check.d.ts.map +1 -1
  113. package/dist/cli/check.js +15 -2
  114. package/dist/cli/check.js.map +1 -1
  115. package/dist/cli/claude.d.ts.map +1 -1
  116. package/dist/cli/claude.js +0 -2
  117. package/dist/cli/claude.js.map +1 -1
  118. package/dist/cli/index.js +6 -0
  119. package/dist/cli/index.js.map +1 -1
  120. package/dist/cli/init.d.ts.map +1 -1
  121. package/dist/cli/init.js +11 -2
  122. package/dist/cli/init.js.map +1 -1
  123. package/dist/cli/opencode.d.ts.map +1 -1
  124. package/dist/cli/opencode.js +2 -1
  125. package/dist/cli/opencode.js.map +1 -1
  126. package/package.json +1 -1
  127. package/assets/commands/ciel-migrate.md +0 -35
  128. 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: inject faire-gatekeeper + dispatch gate + pipeline reminders before code write
5
- # Critical files get additional stride-analyzer hint
6
- # Always exits 0 (never blocks), outputs reminders via stderr (reliable channel)
7
- # Dispatch counter: /tmp/ciel_dispatched set by SubagentStart hooks (ciel-researcher/explorer)
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 is created by SubagentStart hooks when ciel-researcher/explorer dispatch
46
+ # /tmp/ciel_dispatched.* files created by SubagentStart hooks when Ciel agents dispatch
27
47
  DISPATCHED=0
28
- DISPATCH_FLAG="/tmp/ciel_dispatched"
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
- # Build warnings
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
- PIPELINE_WARN=" | CIEL PIPELINE: ${COUNT} file(s) edited. Have researcher+explorer been dispatched? If 3+ files: ciel-critic MODE=RELIRE required before merge."
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 ! echo "$FILE_PATH" | grep -qE '\.(kt|java|ts|tsx|js|jsx|py|go|rs|rb|php|cs|cpp|c|swift|scala|vue|svelte|sql|sh|json|yaml|yml|toml)$'; then
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
- print(f'Cued-recall memory active ({total} memories{more}):\\n' + '\\n'.join(lines))
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
- # Mechanical depth signals
21
- DEPTH="Standard" # default
22
- REASON=""
23
-
24
- # Check for Critical signals
25
- if echo "$PROMPT" | grep -qiE '\b(auth|authenti|author|jwt|oauth|password|secret|token|session|payment|credit.card|migration.*schema|2fa|mfa|encryption|credential|cookie.*security)\b'; then
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": "echo \"[CIEL v6] Session started — Pipeline: DOCS → QUOI → ASK → AVEC QUOI → DIVERGE → RECHERCHE → CODEBASE → EVALUER → ASK2 → FAIRE → RELIRE → PROUVER → MEMOIRE → META\" && { ! [ -x \"$CLAUDE_PROJECT_DIR/.claude/hooks/session-version-check.sh\" ] || \"$CLAUDE_PROJECT_DIR/.claude/hooks/session-version-check.sh\"; }"
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": "touch /tmp/ciel_dispatched && echo \"[CIEL] Explorer started: $(date -u +%Y-%m-%dT%H:%M:%SZ)\" >> \"$CLAUDE_PROJECT_DIR/.ciel/exploration-log.md\""
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": "touch /tmp/ciel_dispatched && echo \"[CIEL] Researcher started: $(date -u +%Y-%m-%dT%H:%M:%SZ)\" >> \"$CLAUDE_PROJECT_DIR/.ciel/subagent-log.md\""
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 ~/.claude/plugins/ciel/scripts/install.sh --with-mcp=playwright,context7
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.