cleargate 0.14.0 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/MANIFEST.json +72 -16
- package/dist/admin-api/index.cjs +0 -1
- package/dist/admin-api/index.js +1 -2
- package/dist/auth/factory.cjs +0 -1
- package/dist/auth/factory.js +2 -3
- package/dist/auth/require-token.cjs +0 -1
- package/dist/auth/require-token.js +1 -2
- package/dist/auth/token-store.cjs +0 -1
- package/dist/auth/token-store.js +1 -2
- package/dist/{bootstrap-root-QKSA5V75.js → bootstrap-root-2H5HVTCC.js} +1 -2
- package/dist/{chunk-PDE37WFQ.js → chunk-A7MSQUU7.js} +2 -3
- package/dist/{chunk-BTSZOEWC.js → chunk-P6KEDAK2.js} +0 -1
- package/dist/{chunk-E3X7IE5E.js → chunk-PY6FHGV5.js} +1 -2
- package/dist/{chunk-5DI2Z3C2.js → chunk-Y53ZZYYU.js} +1 -2
- package/dist/cli.cjs +1564 -1414
- package/dist/cli.js +1514 -1364
- package/dist/lib/ledger.cjs +0 -1
- package/dist/lib/ledger.js +1 -2
- package/dist/lib/lifecycle-reconcile.cjs +0 -1
- package/dist/lib/lifecycle-reconcile.js +2 -3
- package/dist/{whoami-EANGN46Z.js → whoami-JKQQPABQ.js} +3 -4
- package/package.json +4 -3
- package/templates/cleargate-planning/.claude/agents/architect-synth.md +2 -0
- package/templates/cleargate-planning/.claude/agents/architect.md +4 -2
- package/templates/cleargate-planning/.claude/agents/developer.md +4 -11
- package/templates/cleargate-planning/.claude/agents/qa.md +14 -6
- package/templates/cleargate-planning/.claude/hooks/pending-task-sentinel.sh +2 -2
- package/templates/cleargate-planning/.claude/skills/sprint-execution/SKILL.md +19 -1
- package/templates/cleargate-planning/.cleargate/config.example.yml +16 -0
- package/templates/cleargate-planning/.cleargate/scripts/close_sprint.deferred-verify.red.node.test.ts +245 -0
- package/templates/cleargate-planning/.cleargate/scripts/close_sprint.mjs +227 -0
- package/templates/cleargate-planning/.cleargate/scripts/gate-checks.json +5 -4
- package/templates/cleargate-planning/.cleargate/scripts/init_sprint.mjs +75 -2
- package/templates/cleargate-planning/.cleargate/scripts/pre_gate_common.sh +48 -0
- package/templates/cleargate-planning/.cleargate/scripts/pre_gate_runner.sh +57 -1
- package/templates/cleargate-planning/.cleargate/scripts/provision_worktree_config.sh +155 -0
- package/templates/cleargate-planning/.cleargate/scripts/qa_red_lint.mjs +380 -0
- package/templates/cleargate-planning/.cleargate/scripts/run_script.sh +34 -1
- package/templates/cleargate-planning/.cleargate/scripts/test/cr077_eviction.red.sh +113 -0
- package/templates/cleargate-planning/.cleargate/scripts/test/cr078_init.test.sh +309 -0
- package/templates/cleargate-planning/.cleargate/scripts/test/cr079_provision.red.sh +262 -0
- package/templates/cleargate-planning/.cleargate/scripts/test/cr080_wrapper.test.sh +177 -0
- package/templates/cleargate-planning/.cleargate/scripts/test/cr081_qa_red_lint.red.sh +348 -0
- package/templates/cleargate-planning/.cleargate/sprint-runs/_off-sprint/.session-totals.json +1 -0
- package/templates/cleargate-planning/.cleargate/sprint-runs/_off-sprint/token-ledger.jsonl +222 -0
- package/templates/cleargate-planning/.cleargate/templates/sprint_context.md +17 -0
- package/templates/cleargate-planning/.cleargate/templates/story.md +1 -0
- package/templates/cleargate-planning/MANIFEST.json +72 -16
- package/dist/admin-api/index.cjs.map +0 -1
- package/dist/admin-api/index.js.map +0 -1
- package/dist/auth/factory.cjs.map +0 -1
- package/dist/auth/factory.js.map +0 -1
- package/dist/auth/require-token.cjs.map +0 -1
- package/dist/auth/require-token.js.map +0 -1
- package/dist/auth/token-store.cjs.map +0 -1
- package/dist/auth/token-store.js.map +0 -1
- package/dist/bootstrap-root-QKSA5V75.js.map +0 -1
- package/dist/chunk-5DI2Z3C2.js.map +0 -1
- package/dist/chunk-BTSZOEWC.js.map +0 -1
- package/dist/chunk-E3X7IE5E.js.map +0 -1
- package/dist/chunk-PDE37WFQ.js.map +0 -1
- package/dist/cli.cjs.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/lib/ledger.cjs.map +0 -1
- package/dist/lib/ledger.js.map +0 -1
- package/dist/lib/lifecycle-reconcile.cjs.map +0 -1
- package/dist/lib/lifecycle-reconcile.js.map +0 -1
- package/dist/templates/cleargate-planning/.claude/agents/architect-reader.md +0 -61
- package/dist/templates/cleargate-planning/.claude/agents/architect-synth.md +0 -124
- package/dist/templates/cleargate-planning/.claude/agents/architect.md +0 -230
- package/dist/templates/cleargate-planning/.claude/agents/cleargate-wiki-contradict.md +0 -108
- package/dist/templates/cleargate-planning/.claude/agents/cleargate-wiki-ingest.md +0 -194
- package/dist/templates/cleargate-planning/.claude/agents/cleargate-wiki-lint.md +0 -261
- package/dist/templates/cleargate-planning/.claude/agents/cleargate-wiki-query.md +0 -143
- package/dist/templates/cleargate-planning/.claude/agents/developer.md +0 -185
- package/dist/templates/cleargate-planning/.claude/agents/devops.md +0 -257
- package/dist/templates/cleargate-planning/.claude/agents/qa.md +0 -171
- package/dist/templates/cleargate-planning/.claude/agents/reporter.md +0 -274
- package/dist/templates/cleargate-planning/.claude/hooks/pending-task-sentinel.sh +0 -209
- package/dist/templates/cleargate-planning/.claude/hooks/pre-commit-surface-gate.sh +0 -33
- package/dist/templates/cleargate-planning/.claude/hooks/pre-commit-test-ratchet.sh +0 -58
- package/dist/templates/cleargate-planning/.claude/hooks/pre-commit.sh +0 -19
- package/dist/templates/cleargate-planning/.claude/hooks/pre-edit-gate.sh +0 -162
- package/dist/templates/cleargate-planning/.claude/hooks/pre-tool-use-autonomy.sh +0 -58
- package/dist/templates/cleargate-planning/.claude/hooks/pre-tool-use-task.sh +0 -148
- package/dist/templates/cleargate-planning/.claude/hooks/session-start.sh +0 -75
- package/dist/templates/cleargate-planning/.claude/hooks/stamp-and-gate.sh +0 -43
- package/dist/templates/cleargate-planning/.claude/hooks/token-ledger.sh +0 -590
- package/dist/templates/cleargate-planning/.claude/settings.json +0 -68
- package/dist/templates/cleargate-planning/.claude/skills/flashcard/SKILL.md +0 -102
- package/dist/templates/cleargate-planning/.claude/skills/sprint-execution/SKILL.md +0 -742
- package/dist/templates/cleargate-planning/.cleargate/FLASHCARD.md +0 -7
- package/dist/templates/cleargate-planning/.cleargate/config.example.yml +0 -67
- package/dist/templates/cleargate-planning/.cleargate/config.yml +0 -18
- package/dist/templates/cleargate-planning/.cleargate/delivery/archive/.gitkeep +0 -0
- package/dist/templates/cleargate-planning/.cleargate/delivery/pending-sync/.gitkeep +0 -0
- package/dist/templates/cleargate-planning/.cleargate/knowledge/cleargate-enforcement.md +0 -551
- package/dist/templates/cleargate-planning/.cleargate/knowledge/cleargate-protocol.md +0 -878
- package/dist/templates/cleargate-planning/.cleargate/knowledge/mid-sprint-triage-rubric.md +0 -160
- package/dist/templates/cleargate-planning/.cleargate/knowledge/readiness-gates.md +0 -213
- package/dist/templates/cleargate-planning/.cleargate/knowledge/sprint-closeout-checklist.md +0 -71
- package/dist/templates/cleargate-planning/.cleargate/scripts/_migrate-schema-v3.mjs +0 -120
- package/dist/templates/cleargate-planning/.cleargate/scripts/assert_story_files.mjs +0 -265
- package/dist/templates/cleargate-planning/.cleargate/scripts/close_sprint.mjs +0 -1012
- package/dist/templates/cleargate-planning/.cleargate/scripts/collision_surface.sh +0 -114
- package/dist/templates/cleargate-planning/.cleargate/scripts/constants.mjs +0 -62
- package/dist/templates/cleargate-planning/.cleargate/scripts/dedupe_frontmatter.mjs +0 -219
- package/dist/templates/cleargate-planning/.cleargate/scripts/file_surface_diff.sh +0 -320
- package/dist/templates/cleargate-planning/.cleargate/scripts/gate-checks.json +0 -15
- package/dist/templates/cleargate-planning/.cleargate/scripts/init_gate_config.sh +0 -38
- package/dist/templates/cleargate-planning/.cleargate/scripts/init_sprint.mjs +0 -240
- package/dist/templates/cleargate-planning/.cleargate/scripts/launch_wave.mjs +0 -341
- package/dist/templates/cleargate-planning/.cleargate/scripts/lib/report-filename.mjs +0 -54
- package/dist/templates/cleargate-planning/.cleargate/scripts/pre_gate_common.sh +0 -206
- package/dist/templates/cleargate-planning/.cleargate/scripts/pre_gate_runner.sh +0 -371
- package/dist/templates/cleargate-planning/.cleargate/scripts/prefill_report.mjs +0 -280
- package/dist/templates/cleargate-planning/.cleargate/scripts/prep_doc_refresh.mjs +0 -378
- package/dist/templates/cleargate-planning/.cleargate/scripts/prep_qa_context.mjs +0 -888
- package/dist/templates/cleargate-planning/.cleargate/scripts/run_script.sh +0 -209
- package/dist/templates/cleargate-planning/.cleargate/scripts/sprint_trends.mjs +0 -71
- package/dist/templates/cleargate-planning/.cleargate/scripts/state.schema.json +0 -127
- package/dist/templates/cleargate-planning/.cleargate/scripts/suggest_improvements.mjs +0 -717
- package/dist/templates/cleargate-planning/.cleargate/scripts/surface-whitelist.txt +0 -27
- package/dist/templates/cleargate-planning/.cleargate/scripts/test/test_assert_story_files.sh +0 -261
- package/dist/templates/cleargate-planning/.cleargate/scripts/test/test_file_surface.sh +0 -210
- package/dist/templates/cleargate-planning/.cleargate/scripts/test/test_flashcard_gate.sh +0 -190
- package/dist/templates/cleargate-planning/.cleargate/scripts/test/test_prep_qa_context.sh +0 -482
- package/dist/templates/cleargate-planning/.cleargate/scripts/test/test_test_ratchet.sh +0 -327
- package/dist/templates/cleargate-planning/.cleargate/scripts/test_ratchet.mjs +0 -261
- package/dist/templates/cleargate-planning/.cleargate/scripts/update_state.mjs +0 -246
- package/dist/templates/cleargate-planning/.cleargate/scripts/validate_bounce_readiness.mjs +0 -111
- package/dist/templates/cleargate-planning/.cleargate/scripts/validate_state.mjs +0 -184
- package/dist/templates/cleargate-planning/.cleargate/scripts/write_dispatch.sh +0 -172
- package/dist/templates/cleargate-planning/.cleargate/templates/Bug.md +0 -126
- package/dist/templates/cleargate-planning/.cleargate/templates/CR.md +0 -130
- package/dist/templates/cleargate-planning/.cleargate/templates/Sprint Plan Template.md +0 -137
- package/dist/templates/cleargate-planning/.cleargate/templates/epic.md +0 -166
- package/dist/templates/cleargate-planning/.cleargate/templates/hotfix.md +0 -111
- package/dist/templates/cleargate-planning/.cleargate/templates/initiative.md +0 -122
- package/dist/templates/cleargate-planning/.cleargate/templates/sprint_context.md +0 -50
- package/dist/templates/cleargate-planning/.cleargate/templates/sprint_report.md +0 -224
- package/dist/templates/cleargate-planning/.cleargate/templates/story.md +0 -213
- package/dist/templates/cleargate-planning/CLAUDE.md +0 -66
- package/dist/templates/cleargate-planning/MANIFEST.json +0 -503
- package/dist/templates/synthesis/active-sprint.md +0 -30
- package/dist/templates/synthesis/open-gates.md +0 -38
- package/dist/templates/synthesis/product-state.md +0 -31
- package/dist/templates/synthesis/roadmap.md +0 -63
- package/dist/whoami-EANGN46Z.js.map +0 -1
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# pre-edit-gate.sh — CR-008 Phase B: planning-first PreToolUse gate
|
|
3
|
-
#
|
|
4
|
-
# Registered as a PreToolUse hook for Edit|Write tool calls.
|
|
5
|
-
# In warn mode (default), logs would-block decisions but always exits 0.
|
|
6
|
-
# In enforce mode, exits 1 to block the tool call when planning is missing.
|
|
7
|
-
#
|
|
8
|
-
# Mode controlled by CLEARGATE_PLANNING_GATE_MODE (warn|enforce|off). Default: warn.
|
|
9
|
-
# Bypass: CLEARGATE_PLANNING_BYPASS=1 → skip check, log bypass=true, exit 0.
|
|
10
|
-
|
|
11
|
-
set -u
|
|
12
|
-
|
|
13
|
-
REPO_ROOT="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
14
|
-
MODE="${CLEARGATE_PLANNING_GATE_MODE:-warn}"
|
|
15
|
-
LOG_FILE="${REPO_ROOT}/.cleargate/hook-log/pre-edit-gate-warn.log"
|
|
16
|
-
|
|
17
|
-
# ── 0. Off mode — do nothing ──────────────────────────────────────────────────
|
|
18
|
-
if [ "${MODE}" = "off" ]; then
|
|
19
|
-
exit 0
|
|
20
|
-
fi
|
|
21
|
-
|
|
22
|
-
# ── 1. Read file path from stdin (PreToolUse JSON payload) ────────────────────
|
|
23
|
-
# Claude Code sends JSON on stdin: {"tool_name":"Edit","tool_input":{"file_path":"..."}}
|
|
24
|
-
INPUT=$(cat)
|
|
25
|
-
FILE=$(printf '%s' "${INPUT}" | node -e "
|
|
26
|
-
try {
|
|
27
|
-
var d = require('fs').readFileSync('/dev/stdin','utf8');
|
|
28
|
-
var o = JSON.parse(d);
|
|
29
|
-
var fp = (o.tool_input && o.tool_input.file_path) ? o.tool_input.file_path : '';
|
|
30
|
-
process.stdout.write(fp);
|
|
31
|
-
} catch(e) {
|
|
32
|
-
process.stdout.write('');
|
|
33
|
-
}
|
|
34
|
-
" 2>/dev/null || true)
|
|
35
|
-
|
|
36
|
-
TOOL_NAME=$(printf '%s' "${INPUT}" | node -e "
|
|
37
|
-
try {
|
|
38
|
-
var d = require('fs').readFileSync('/dev/stdin','utf8');
|
|
39
|
-
var o = JSON.parse(d);
|
|
40
|
-
process.stdout.write(o.tool_name || '');
|
|
41
|
-
} catch(e) {
|
|
42
|
-
process.stdout.write('');
|
|
43
|
-
}
|
|
44
|
-
" 2>/dev/null || true)
|
|
45
|
-
|
|
46
|
-
# ── Guard: if we couldn't parse the file path, fail-open ──────────────────────
|
|
47
|
-
if [ -z "${FILE}" ]; then
|
|
48
|
-
exit 0
|
|
49
|
-
fi
|
|
50
|
-
|
|
51
|
-
# ── 2. Bypass env var ─────────────────────────────────────────────────────────
|
|
52
|
-
if [ "${CLEARGATE_PLANNING_BYPASS:-0}" = "1" ]; then
|
|
53
|
-
ISO_TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
54
|
-
mkdir -p "$(dirname "${LOG_FILE}")"
|
|
55
|
-
printf '[%s] mode=%s bypass=true file=%s\n' "${ISO_TS}" "${MODE}" "${FILE}" >> "${LOG_FILE}"
|
|
56
|
-
exit 0
|
|
57
|
-
fi
|
|
58
|
-
|
|
59
|
-
# ── 3. Whitelist: always allow these paths ────────────────────────────────────
|
|
60
|
-
# Normalise: strip leading REPO_ROOT prefix for matching
|
|
61
|
-
REL_FILE="${FILE}"
|
|
62
|
-
if [[ "${FILE}" == "${REPO_ROOT}/"* ]]; then
|
|
63
|
-
REL_FILE="${FILE#${REPO_ROOT}/}"
|
|
64
|
-
fi
|
|
65
|
-
|
|
66
|
-
is_whitelisted() {
|
|
67
|
-
local f="$1"
|
|
68
|
-
# Exact or prefix matches for whitelisted directories/files
|
|
69
|
-
case "${f}" in
|
|
70
|
-
.cleargate/*|.claude/*|cleargate-planning/*) return 0 ;;
|
|
71
|
-
CLAUDE.md|MANIFEST.json|README.md|.gitignore|.gitkeep) return 0 ;;
|
|
72
|
-
package.json|package-lock.json) return 0 ;;
|
|
73
|
-
.env|.env.*|.npmrc|.editorconfig) return 0 ;;
|
|
74
|
-
# Also allow absolute paths that fall under the repo's cleargate dirs
|
|
75
|
-
esac
|
|
76
|
-
# Check absolute path variants
|
|
77
|
-
case "${FILE}" in
|
|
78
|
-
"${REPO_ROOT}/.cleargate/"*|"${REPO_ROOT}/.claude/"*|"${REPO_ROOT}/cleargate-planning/"*) return 0 ;;
|
|
79
|
-
esac
|
|
80
|
-
return 1
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if is_whitelisted "${REL_FILE}"; then
|
|
84
|
-
exit 0
|
|
85
|
-
fi
|
|
86
|
-
|
|
87
|
-
# ── 3.5 Sprint-active sentinel bypass ────────────────────────────────────────
|
|
88
|
-
# If a sprint is actively running, all in-sprint edits bypass the gate.
|
|
89
|
-
if [ -f "${REPO_ROOT}/.cleargate/sprint-runs/.active" ]; then
|
|
90
|
-
exit 0
|
|
91
|
-
fi
|
|
92
|
-
|
|
93
|
-
# ── 4. Resolve cleargate CLI (three-branch resolver — CR-009) ────────────────
|
|
94
|
-
if [ -f "${REPO_ROOT}/cleargate-cli/dist/cli.js" ]; then
|
|
95
|
-
CG=(node "${REPO_ROOT}/cleargate-cli/dist/cli.js")
|
|
96
|
-
elif command -v cleargate >/dev/null 2>&1; then
|
|
97
|
-
CG=(cleargate)
|
|
98
|
-
else
|
|
99
|
-
# Read pinned version from stamp-and-gate.sh
|
|
100
|
-
HOOK_PIN=""
|
|
101
|
-
HOOK_SH="${REPO_ROOT}/.claude/hooks/stamp-and-gate.sh"
|
|
102
|
-
if [ -f "${HOOK_SH}" ]; then
|
|
103
|
-
HOOK_PIN=$(grep -oP '(?<=# cleargate-pin: )[\S]+' "${HOOK_SH}" 2>/dev/null || \
|
|
104
|
-
grep -oE 'cleargate@[^"]+' "${HOOK_SH}" 2>/dev/null | head -1 | sed 's/.*@//' || true)
|
|
105
|
-
fi
|
|
106
|
-
if [ -z "${HOOK_PIN}" ]; then
|
|
107
|
-
HOOK_PIN="__CLEARGATE_VERSION__"
|
|
108
|
-
fi
|
|
109
|
-
CG=(npx -y "cleargate@${HOOK_PIN}")
|
|
110
|
-
fi
|
|
111
|
-
|
|
112
|
-
# ── 5. Read user prompt snippet for log context (optional; best-effort) ───────
|
|
113
|
-
PROMPT_SNIPPET=$(printf '%s' "${INPUT}" | node -e "
|
|
114
|
-
try {
|
|
115
|
-
var d = require('fs').readFileSync('/dev/stdin','utf8');
|
|
116
|
-
var o = JSON.parse(d);
|
|
117
|
-
var p = (o.user_prompt || '').slice(0, 200);
|
|
118
|
-
process.stdout.write(p);
|
|
119
|
-
} catch(e) {
|
|
120
|
-
process.stdout.write('');
|
|
121
|
-
}
|
|
122
|
-
" 2>/dev/null || true)
|
|
123
|
-
|
|
124
|
-
# ── 6. Ask doctor --can-edit ──────────────────────────────────────────────────
|
|
125
|
-
# Capture both stdout AND exit code without || true swallowing the exit code.
|
|
126
|
-
_DOCTOR_TMPFILE=$(mktemp)
|
|
127
|
-
"${CG[@]}" doctor --can-edit "${FILE}" --cwd "${REPO_ROOT}" > "${_DOCTOR_TMPFILE}" 2>/dev/null
|
|
128
|
-
DOCTOR_EXIT=$?
|
|
129
|
-
DOCTOR_OUT=$(cat "${_DOCTOR_TMPFILE}")
|
|
130
|
-
rm -f "${_DOCTOR_TMPFILE}"
|
|
131
|
-
|
|
132
|
-
# Parse reason from doctor output
|
|
133
|
-
REASON=$(printf '%s' "${DOCTOR_OUT}" | grep -oP '(?<=blocked: )\S+' 2>/dev/null || \
|
|
134
|
-
printf '%s' "${DOCTOR_OUT}" | sed -n 's/blocked: //p' 2>/dev/null || \
|
|
135
|
-
echo "unknown")
|
|
136
|
-
|
|
137
|
-
# Count approved stories in pending-sync (for log entry)
|
|
138
|
-
PENDING_DIR="${REPO_ROOT}/.cleargate/delivery/pending-sync"
|
|
139
|
-
PENDING_MATCH_COUNT=0
|
|
140
|
-
if [ -d "${PENDING_DIR}" ]; then
|
|
141
|
-
PENDING_MATCH_COUNT=$(grep -rl 'approved: true' "${PENDING_DIR}" 2>/dev/null | wc -l | tr -d ' ' || echo "0")
|
|
142
|
-
fi
|
|
143
|
-
|
|
144
|
-
# ── 7. Gate decision ──────────────────────────────────────────────────────────
|
|
145
|
-
if [ "${DOCTOR_EXIT}" -ne 0 ]; then
|
|
146
|
-
# Would block
|
|
147
|
-
ISO_TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
148
|
-
mkdir -p "$(dirname "${LOG_FILE}")"
|
|
149
|
-
printf '[%s] mode=%s would_block file=%s reason=%s tool=%s pending_match_count=%d prompt_snippet=%s\n' \
|
|
150
|
-
"${ISO_TS}" "${MODE}" "${FILE}" "${REASON}" "${TOOL_NAME}" "${PENDING_MATCH_COUNT}" "${PROMPT_SNIPPET}" \
|
|
151
|
-
>> "${LOG_FILE}"
|
|
152
|
-
|
|
153
|
-
if [ "${MODE}" = "enforce" ]; then
|
|
154
|
-
printf 'ClearGate: planning-first gate — no approved story covers %s (%s). Draft a work item first.\n' \
|
|
155
|
-
"${FILE}" "${REASON}" >&2
|
|
156
|
-
exit 1
|
|
157
|
-
fi
|
|
158
|
-
|
|
159
|
-
# warn mode: log written above, exit 0 (do not block)
|
|
160
|
-
fi
|
|
161
|
-
|
|
162
|
-
exit 0
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# pre-tool-use-autonomy.sh — PreToolUse:AskUserQuestion soft-warning hook (STORY-071-01)
|
|
3
|
-
#
|
|
4
|
-
# CR-071: Logs a warning when an agent issues AskUserQuestion during an active sprint.
|
|
5
|
-
# Soft mode — ALWAYS exits 0 (never blocks the call). Observability only.
|
|
6
|
-
#
|
|
7
|
-
# Inputs:
|
|
8
|
-
# stdin: Claude Code PreToolUse JSON payload with tool_name, tool_input, etc.
|
|
9
|
-
# env: CLAUDE_PROJECT_DIR (project root; fallback to current dir)
|
|
10
|
-
#
|
|
11
|
-
# Output:
|
|
12
|
-
# Appends to .cleargate/hook-log/autonomy-warnings.log when conditions are met.
|
|
13
|
-
# Tab-separated columns: <iso-timestamp>\tAskUserQuestion\t<agent>\t<question-summary>
|
|
14
|
-
#
|
|
15
|
-
# Conditions for logging:
|
|
16
|
-
# 1. tool_name == "AskUserQuestion"
|
|
17
|
-
# 2. .cleargate/sprint-runs/.active exists and is non-empty
|
|
18
|
-
# 3. corresponding state.json sprint_status == "Active"
|
|
19
|
-
#
|
|
20
|
-
# Exit code: 0 always (soft mode — never blocks).
|
|
21
|
-
|
|
22
|
-
set -u
|
|
23
|
-
|
|
24
|
-
PAYLOAD="$(cat 2>/dev/null || true)"
|
|
25
|
-
|
|
26
|
-
# If jq is absent, degrade gracefully (exit 0, no log).
|
|
27
|
-
if ! command -v jq >/dev/null 2>&1; then
|
|
28
|
-
exit 0
|
|
29
|
-
fi
|
|
30
|
-
|
|
31
|
-
TOOL=$(printf '%s' "$PAYLOAD" | jq -r '.tool_name // empty' 2>/dev/null || true)
|
|
32
|
-
[ "$TOOL" = "AskUserQuestion" ] || exit 0
|
|
33
|
-
|
|
34
|
-
ACTIVE_FILE="${CLAUDE_PROJECT_DIR:-.}/.cleargate/sprint-runs/.active"
|
|
35
|
-
[ -s "$ACTIVE_FILE" ] || exit 0
|
|
36
|
-
|
|
37
|
-
SPRINT_ID="$(cat "$ACTIVE_FILE" 2>/dev/null || true)"
|
|
38
|
-
[ -n "$SPRINT_ID" ] || exit 0
|
|
39
|
-
|
|
40
|
-
STATE_FILE="${CLAUDE_PROJECT_DIR:-.}/.cleargate/sprint-runs/$SPRINT_ID/state.json"
|
|
41
|
-
[ -f "$STATE_FILE" ] || exit 0
|
|
42
|
-
|
|
43
|
-
STATUS=$(jq -r '.sprint_status // empty' "$STATE_FILE" 2>/dev/null || true)
|
|
44
|
-
[ "$STATUS" = "Active" ] || exit 0
|
|
45
|
-
|
|
46
|
-
LOG="${CLAUDE_PROJECT_DIR:-.}/.cleargate/hook-log/autonomy-warnings.log"
|
|
47
|
-
mkdir -p "$(dirname "$LOG")" 2>/dev/null || true
|
|
48
|
-
|
|
49
|
-
QUESTION_SUMMARY=$(printf '%s' "$PAYLOAD" | jq -r '.tool_input.question // ""' 2>/dev/null | head -c 200 || true)
|
|
50
|
-
|
|
51
|
-
DISPATCH_DIR="${CLAUDE_PROJECT_DIR:-.}/.cleargate/sprint-runs/$SPRINT_ID"
|
|
52
|
-
AGENT=$(ls -t "$DISPATCH_DIR"/.dispatch-*.json 2>/dev/null | head -1 | \
|
|
53
|
-
xargs -I {} jq -r '.agent // "unknown"' {} 2>/dev/null || echo "unknown")
|
|
54
|
-
[ -n "$AGENT" ] || AGENT="unknown"
|
|
55
|
-
|
|
56
|
-
printf '%s\tAskUserQuestion\t%s\t%s\n' "$(date -u +%FT%TZ)" "$AGENT" "$QUESTION_SUMMARY" >> "$LOG" 2>/dev/null || true
|
|
57
|
-
|
|
58
|
-
exit 0
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# pre-tool-use-task.sh — PreToolUse:Task hook.
|
|
3
|
-
#
|
|
4
|
-
# CR-026: Auto-write a dispatch marker on every Task() spawn so the
|
|
5
|
-
# SubagentStop hook (token-ledger.sh) can attribute tokens to the correct
|
|
6
|
-
# work item and agent without relying on transcript-grep heuristics.
|
|
7
|
-
#
|
|
8
|
-
# This hook addresses BUG-024 §3.1 Defect 3: manual write_dispatch.sh calls
|
|
9
|
-
# were unreliable (~5 calls vs ~19 spawns in SPRINT-18). The hook fires
|
|
10
|
-
# automatically on every Task() spawn inside the orchestrator session.
|
|
11
|
-
#
|
|
12
|
-
# Input: JSON on stdin from Claude Code with fields:
|
|
13
|
-
# session_id, transcript_path, cwd, hook_event_name, tool_name, tool_input
|
|
14
|
-
# For tool_name == "Task", tool_input has: subagent_type, description, prompt.
|
|
15
|
-
#
|
|
16
|
-
# Output: writes .cleargate/sprint-runs/<sprint>/.dispatch-<ts>-<pid>-<rand>.json
|
|
17
|
-
# with { work_item_id, agent_type, spawned_at, session_id, writer }
|
|
18
|
-
# Uniquified filename prevents collision under parallel Task() spawns.
|
|
19
|
-
# SubagentStop hook uses newest-file lookup (ls -t) to consume it.
|
|
20
|
-
#
|
|
21
|
-
# Log: .cleargate/hook-log/pre-tool-use-task.log
|
|
22
|
-
#
|
|
23
|
-
# Exit code: 0 always. Never blocks a Task spawn.
|
|
24
|
-
#
|
|
25
|
-
# Banner-immunity: reads tool_input.prompt directly from the JSON payload —
|
|
26
|
-
# no transcript involvement, so the SessionStart blocked-items banner cannot
|
|
27
|
-
# poison this path (contrast with token-ledger.sh's transcript-grep fallback).
|
|
28
|
-
|
|
29
|
-
set -u
|
|
30
|
-
|
|
31
|
-
# ─── Resolve repo root (matches token-ledger.sh:59 + write_dispatch.sh:30) ───
|
|
32
|
-
REPO_ROOT="${ORCHESTRATOR_PROJECT_DIR:-${CLAUDE_PROJECT_DIR}}"
|
|
33
|
-
LOG_DIR="${REPO_ROOT}/.cleargate/hook-log"
|
|
34
|
-
mkdir -p "${LOG_DIR}"
|
|
35
|
-
HOOK_LOG="${LOG_DIR}/pre-tool-use-task.log"
|
|
36
|
-
ACTIVE_SENTINEL="${REPO_ROOT}/.cleargate/sprint-runs/.active"
|
|
37
|
-
|
|
38
|
-
TS="$(date -u +%FT%TZ)"
|
|
39
|
-
|
|
40
|
-
# Read stdin once
|
|
41
|
-
INPUT="$(cat)"
|
|
42
|
-
|
|
43
|
-
# ─── Extract tool_name to confirm this is a Task spawn ────────────────────────
|
|
44
|
-
TOOL_NAME="$(printf '%s' "${INPUT}" | jq -r '.tool_name // empty' 2>/dev/null)"
|
|
45
|
-
if [[ "${TOOL_NAME}" != "Task" ]]; then
|
|
46
|
-
# Not a Task spawn — nothing to do; exit silently.
|
|
47
|
-
exit 0
|
|
48
|
-
fi
|
|
49
|
-
|
|
50
|
-
# ─── Resolve active sprint via sentinel ───────────────────────────────────────
|
|
51
|
-
if [[ ! -f "${ACTIVE_SENTINEL}" ]]; then
|
|
52
|
-
printf '[%s] no .active sentinel — dispatch marker skipped (off-sprint)\n' "${TS}" >> "${HOOK_LOG}"
|
|
53
|
-
exit 0
|
|
54
|
-
fi
|
|
55
|
-
|
|
56
|
-
SPRINT_ID="$(tr -d '[:space:]' < "${ACTIVE_SENTINEL}")"
|
|
57
|
-
if [[ -z "${SPRINT_ID}" ]]; then
|
|
58
|
-
printf '[%s] .active sentinel is empty — dispatch marker skipped\n' "${TS}" >> "${HOOK_LOG}"
|
|
59
|
-
exit 0
|
|
60
|
-
fi
|
|
61
|
-
|
|
62
|
-
SPRINT_DIR="${REPO_ROOT}/.cleargate/sprint-runs/${SPRINT_ID}"
|
|
63
|
-
mkdir -p "${SPRINT_DIR}"
|
|
64
|
-
|
|
65
|
-
# ─── Extract subagent_type ────────────────────────────────────────────────────
|
|
66
|
-
AGENT_TYPE="$(printf '%s' "${INPUT}" | jq -r '.tool_input.subagent_type // empty' 2>/dev/null)"
|
|
67
|
-
ALLOW_LIST="architect developer qa reporter cleargate-wiki-contradict"
|
|
68
|
-
if [[ -z "${AGENT_TYPE}" ]] || ! printf '%s\n' ${ALLOW_LIST} | grep -qxF "${AGENT_TYPE}"; then
|
|
69
|
-
printf '[%s] no marker: agent_type absent or not in allow-list (%s)\n' "${TS}" "${AGENT_TYPE:-<empty>}" >> "${HOOK_LOG}"
|
|
70
|
-
exit 0
|
|
71
|
-
fi
|
|
72
|
-
|
|
73
|
-
# ─── Extract work_item_id from first 5 lines of tool_input.prompt ─────────────
|
|
74
|
-
# Regex: (STORY=?NNN-NN | BUG-NNN | EPIC-NNN | CR-NNN | PROPOSAL-NNN | HOTFIX-NNN)
|
|
75
|
-
PROMPT_HEAD="$(printf '%s' "${INPUT}" | jq -r '.tool_input.prompt // ""' 2>/dev/null | head -5)"
|
|
76
|
-
if [[ -z "${PROMPT_HEAD}" ]]; then
|
|
77
|
-
printf '[%s] no marker: prompt empty or unreadable\n' "${TS}" >> "${HOOK_LOG}"
|
|
78
|
-
exit 0
|
|
79
|
-
fi
|
|
80
|
-
|
|
81
|
-
WORK_ITEM_RAW="$(printf '%s' "${PROMPT_HEAD}" \
|
|
82
|
-
| grep -oE '(STORY=?[0-9]{3}-[0-9]{2}|BUG-[0-9]+|EPIC-[0-9]+|CR-[0-9]+|PROPOSAL-[0-9]+|HOTFIX-[0-9]+)' \
|
|
83
|
-
| head -1)"
|
|
84
|
-
|
|
85
|
-
if [[ -z "${WORK_ITEM_RAW}" ]]; then
|
|
86
|
-
printf '[%s] no marker: regex miss (agent=%s prompt_head=%s)\n' \
|
|
87
|
-
"${TS}" "${AGENT_TYPE}" "$(printf '%s' "${PROMPT_HEAD}" | head -1 | cut -c1-60)" >> "${HOOK_LOG}"
|
|
88
|
-
exit 0
|
|
89
|
-
fi
|
|
90
|
-
|
|
91
|
-
# Normalize STORY=NNN-NN → STORY-NNN-NN
|
|
92
|
-
WORK_ITEM_ID="$(printf '%s' "${WORK_ITEM_RAW}" | sed 's/=/\-/')"
|
|
93
|
-
|
|
94
|
-
# ─── Resolve orchestrator session ID ─────────────────────────────────────────
|
|
95
|
-
# Path-B: uniquified filename makes session ID irrelevant for lookup.
|
|
96
|
-
# We embed it in the JSON body for forensic value only.
|
|
97
|
-
# GOTCHA-5: CLAUDE_SESSION_ID may be unset on nested spawns; fall back to stdin payload.
|
|
98
|
-
SESSION_ID="${CLAUDE_SESSION_ID:-}"
|
|
99
|
-
if [[ -z "${SESSION_ID}" ]]; then
|
|
100
|
-
SESSION_ID="$(printf '%s' "${INPUT}" | jq -r '.session_id // empty' 2>/dev/null)"
|
|
101
|
-
fi
|
|
102
|
-
[[ -z "${SESSION_ID}" ]] && SESSION_ID="unknown"
|
|
103
|
-
|
|
104
|
-
# ─── Resolve cleargate version ────────────────────────────────────────────────
|
|
105
|
-
PKG_JSON="${REPO_ROOT}/cleargate-cli/package.json"
|
|
106
|
-
CG_VERSION="unknown"
|
|
107
|
-
if [[ -f "${PKG_JSON}" ]]; then
|
|
108
|
-
CG_VERSION="$(jq -r '.version // "unknown"' "${PKG_JSON}" 2>/dev/null || echo "unknown")"
|
|
109
|
-
fi
|
|
110
|
-
|
|
111
|
-
# ─── Write dispatch file atomically (mktemp + mv, matches write_dispatch.sh:110-112) ──
|
|
112
|
-
# Uniquified filename: .dispatch-<ts-epoch>-<pid>-<random>.json
|
|
113
|
-
# Prevents collision under parallel Task() spawns; newest-file lookup at SubagentStop.
|
|
114
|
-
SPAWNED_AT="${TS}"
|
|
115
|
-
DISPATCH_FILENAME=".dispatch-$(date -u +%s)-$$-${RANDOM}.json"
|
|
116
|
-
DISPATCH_TARGET="${SPRINT_DIR}/${DISPATCH_FILENAME}"
|
|
117
|
-
|
|
118
|
-
DISPATCH_JSON="$(jq -cn \
|
|
119
|
-
--arg work_item_id "${WORK_ITEM_ID}" \
|
|
120
|
-
--arg agent_type "${AGENT_TYPE}" \
|
|
121
|
-
--arg spawned_at "${SPAWNED_AT}" \
|
|
122
|
-
--arg session_id "${SESSION_ID}" \
|
|
123
|
-
--arg writer "pre-tool-use-task.sh@cleargate-${CG_VERSION}" \
|
|
124
|
-
'{
|
|
125
|
-
work_item_id: $work_item_id,
|
|
126
|
-
agent_type: $agent_type,
|
|
127
|
-
spawned_at: $spawned_at,
|
|
128
|
-
session_id: $session_id,
|
|
129
|
-
writer: $writer
|
|
130
|
-
}' 2>/dev/null)"
|
|
131
|
-
|
|
132
|
-
if [[ -z "${DISPATCH_JSON}" ]]; then
|
|
133
|
-
printf '[%s] error: jq failed to build dispatch JSON\n' "${TS}" >> "${HOOK_LOG}"
|
|
134
|
-
exit 0
|
|
135
|
-
fi
|
|
136
|
-
|
|
137
|
-
TMP="$(mktemp "${SPRINT_DIR}/.dispatch-tmp-XXXXXX" 2>/dev/null)"
|
|
138
|
-
if [[ -z "${TMP}" ]]; then
|
|
139
|
-
printf '[%s] error: mktemp failed for dispatch file\n' "${TS}" >> "${HOOK_LOG}"
|
|
140
|
-
exit 0
|
|
141
|
-
fi
|
|
142
|
-
printf '%s\n' "${DISPATCH_JSON}" > "${TMP}"
|
|
143
|
-
mv "${TMP}" "${DISPATCH_TARGET}"
|
|
144
|
-
|
|
145
|
-
printf '[%s] wrote dispatch: sprint=%s work_item=%s agent=%s file=%s\n' \
|
|
146
|
-
"${TS}" "${SPRINT_ID}" "${WORK_ITEM_ID}" "${AGENT_TYPE}" "${DISPATCH_FILENAME}" >> "${HOOK_LOG}"
|
|
147
|
-
|
|
148
|
-
exit 0
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -u
|
|
3
|
-
REPO_ROOT="${CLAUDE_PROJECT_DIR}"
|
|
4
|
-
|
|
5
|
-
# cleargate-pin: __CLEARGATE_VERSION__
|
|
6
|
-
# Resolve cleargate CLI (three-branch resolver — CR-009):
|
|
7
|
-
# 1. meta-repo dogfood dist (fastest; only present in ClearGate's own repo)
|
|
8
|
-
# 2. on-PATH binary (global install or shim)
|
|
9
|
-
# 3. pinned npx invocation (always works wherever Node is present)
|
|
10
|
-
if [ -f "${REPO_ROOT}/cleargate-cli/dist/cli.js" ]; then
|
|
11
|
-
CG=(node "${REPO_ROOT}/cleargate-cli/dist/cli.js")
|
|
12
|
-
elif command -v cleargate >/dev/null 2>&1; then
|
|
13
|
-
CG=(cleargate)
|
|
14
|
-
else
|
|
15
|
-
CG=(npx -y "cleargate@__CLEARGATE_VERSION__")
|
|
16
|
-
fi
|
|
17
|
-
|
|
18
|
-
"${CG[@]}" doctor --session-start || true
|
|
19
|
-
|
|
20
|
-
# --- Sprint-active skill auto-load directive (STORY-026-01) ---
|
|
21
|
-
ACTIVE_FILE="${REPO_ROOT}/.cleargate/sprint-runs/.active"
|
|
22
|
-
if [ -s "${ACTIVE_FILE}" ] && [ -n "$(tr -d '[:space:]' < "${ACTIVE_FILE}")" ]; then
|
|
23
|
-
printf '→ Active sprint detected. Load skill: sprint-execution\n'
|
|
24
|
-
fi
|
|
25
|
-
|
|
26
|
-
# ── §14.9 SessionStart sync nudge (STORY-010-08) ─────────────────────────────
|
|
27
|
-
# Daily-throttled: probe remote for updates at most once per 24h.
|
|
28
|
-
# Never auto-pulls or auto-pushes. Exits 0 regardless of outcome.
|
|
29
|
-
MARKER="${REPO_ROOT}/.cleargate/.sync-marker.json"
|
|
30
|
-
NOW_ISO=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
31
|
-
NOW_EPOCH=$(date +%s)
|
|
32
|
-
|
|
33
|
-
if [ ! -f "${MARKER}" ]; then
|
|
34
|
-
# First run — write marker with current timestamp and skip MCP call (24h grace).
|
|
35
|
-
mkdir -p "$(dirname "${MARKER}")"
|
|
36
|
-
printf '{"last_check":"%s"}' "${NOW_ISO}" > "${MARKER}"
|
|
37
|
-
else
|
|
38
|
-
# Parse last_check epoch from marker using node (portable, avoids jq dep)
|
|
39
|
-
LAST_CHECK_ISO=$(node -e "try{const m=JSON.parse(require('fs').readFileSync('${MARKER}','utf8'));process.stdout.write(m.last_check||'1970-01-01T00:00:00Z')}catch{process.stdout.write('1970-01-01T00:00:00Z')}" 2>/dev/null || echo "1970-01-01T00:00:00Z")
|
|
40
|
-
LAST_EPOCH=$(node -e "process.stdout.write(String(Math.floor(new Date('${LAST_CHECK_ISO}').getTime()/1000)))" 2>/dev/null || echo "0")
|
|
41
|
-
ELAPSED=$(( NOW_EPOCH - LAST_EPOCH ))
|
|
42
|
-
|
|
43
|
-
if [ "${ELAPSED}" -ge 86400 ]; then
|
|
44
|
-
# ≥24h since last check — run probe (3s timeout, R7 mitigation)
|
|
45
|
-
RESULT_FILE=$(mktemp)
|
|
46
|
-
# Cross-platform 3-second timeout: prefer `timeout` (Linux); fall back to
|
|
47
|
-
# background-process kill (macOS where GNU coreutils may be absent).
|
|
48
|
-
if command -v timeout > /dev/null 2>&1; then
|
|
49
|
-
timeout 3 "${CG[@]}" sync --check > "${RESULT_FILE}" 2>/dev/null || true
|
|
50
|
-
else
|
|
51
|
-
"${CG[@]}" sync --check > "${RESULT_FILE}" 2>/dev/null &
|
|
52
|
-
_PROBE_PID=$!
|
|
53
|
-
(sleep 3 && kill "${_PROBE_PID}" 2>/dev/null) &
|
|
54
|
-
_KILL_PID=$!
|
|
55
|
-
wait "${_PROBE_PID}" 2>/dev/null || true
|
|
56
|
-
kill "${_KILL_PID}" 2>/dev/null || true
|
|
57
|
-
wait "${_KILL_PID}" 2>/dev/null || true
|
|
58
|
-
fi
|
|
59
|
-
UPDATES=$(node -e "
|
|
60
|
-
try {
|
|
61
|
-
var data = require('fs').readFileSync(process.argv[1], 'utf8').trim();
|
|
62
|
-
var obj = JSON.parse(data);
|
|
63
|
-
process.stdout.write(String(obj.updates || 0));
|
|
64
|
-
} catch(e) {
|
|
65
|
-
process.stdout.write('0');
|
|
66
|
-
}
|
|
67
|
-
" "${RESULT_FILE}" 2>/dev/null || echo "0")
|
|
68
|
-
rm -f "${RESULT_FILE}"
|
|
69
|
-
if [ "${UPDATES}" -gt 0 ] 2>/dev/null; then
|
|
70
|
-
printf '📡 ClearGate: %s remote updates since yesterday — run `cleargate sync` to reconcile.\n' "${UPDATES}"
|
|
71
|
-
fi
|
|
72
|
-
# Marker is updated by sync --check itself; no re-write needed here.
|
|
73
|
-
fi
|
|
74
|
-
fi
|
|
75
|
-
exit 0
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -u
|
|
3
|
-
REPO_ROOT="${CLAUDE_PROJECT_DIR}"
|
|
4
|
-
LOG="${REPO_ROOT}/.cleargate/hook-log/gate-check.log"
|
|
5
|
-
mkdir -p "$(dirname "$LOG")"
|
|
6
|
-
|
|
7
|
-
# cleargate-pin: __CLEARGATE_VERSION__
|
|
8
|
-
# Resolve cleargate CLI (three-branch resolver — CR-009):
|
|
9
|
-
# 1. meta-repo dogfood dist (fastest; only present in ClearGate's own repo)
|
|
10
|
-
# 2. on-PATH binary (global install or shim)
|
|
11
|
-
# 3. pinned npx invocation (always works wherever Node is present)
|
|
12
|
-
if [ -f "${REPO_ROOT}/cleargate-cli/dist/cli.js" ]; then
|
|
13
|
-
CG=(node "${REPO_ROOT}/cleargate-cli/dist/cli.js")
|
|
14
|
-
elif command -v cleargate >/dev/null 2>&1; then
|
|
15
|
-
CG=(cleargate)
|
|
16
|
-
else
|
|
17
|
-
CG=(npx -y "cleargate@__CLEARGATE_VERSION__")
|
|
18
|
-
fi
|
|
19
|
-
|
|
20
|
-
FILE=$(jq -r '.tool_input.file_path' 2>/dev/null || echo "")
|
|
21
|
-
[ -z "$FILE" ] && exit 0
|
|
22
|
-
case "$FILE" in *.cleargate/delivery/*) : ;; *) exit 0 ;; esac
|
|
23
|
-
TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
24
|
-
# Ordered chain — stamp MUST precede gate (gate may read draft_tokens)
|
|
25
|
-
"${CG[@]}" stamp-tokens "$FILE" >>"$LOG" 2>&1
|
|
26
|
-
SR1=$?
|
|
27
|
-
# CR-032: capture gate check stdout to tmpfile so we can re-emit ⚠️ lines to
|
|
28
|
-
# hook stdout (→ Claude Code system-reminder). gate.ts emits ❌ lines to
|
|
29
|
-
# stdout (gate.ts:259), not stderr; the tmpfile captures them separately.
|
|
30
|
-
GATE_OUT=$(mktemp)
|
|
31
|
-
"${CG[@]}" gate check "$FILE" >"$GATE_OUT" 2>>"$LOG"
|
|
32
|
-
SR2=$?
|
|
33
|
-
cat "$GATE_OUT" >>"$LOG"
|
|
34
|
-
if [ "$SR2" -ne 0 ]; then
|
|
35
|
-
WORK_ITEM_ID=$(grep -m1 -oE '(EPIC|STORY|CR|BUG|HOTFIX|PROPOSAL|INITIATIVE|SPRINT)-[0-9]+(-[0-9]+)?' "$FILE" | head -1)
|
|
36
|
-
: "${WORK_ITEM_ID:=<work-item>}"
|
|
37
|
-
grep '^❌' "$GATE_OUT" 2>/dev/null | sed -E "s/^❌ /⚠️ gate failed: ${WORK_ITEM_ID} — /"
|
|
38
|
-
fi
|
|
39
|
-
rm -f "$GATE_OUT"
|
|
40
|
-
"${CG[@]}" wiki ingest "$FILE" >>"$LOG" 2>&1
|
|
41
|
-
SR3=$?
|
|
42
|
-
echo "[$TS] stamp=$SR1 gate=$SR2 ingest=$SR3 file=$FILE" >>"$LOG"
|
|
43
|
-
exit 0 # ALWAYS 0 — severity enforcement is at wiki lint, not hook
|