-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsession-start.sh
More file actions
173 lines (156 loc) · 7.19 KB
/
Copy pathsession-start.sh
File metadata and controls
173 lines (156 loc) · 7.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#!/bin/bash
# 8-Habit AI Dev — Session Start Reminder (≤300 tokens)
#
# TOKEN BUDGET (F16, #368): worst-case output measures ~281 tokens by chars/4
# (the enforced estimator in tests/test-verbosity-hook.sh uses words×1.3 and passes
# with headroom). Treat ~300 as a hard ceiling with little slack: any NEW feature/skill
# line here MUST trim an existing line to stay under budget — do not just append.
#
# Opt out: export HABIT_QUIET=1 (silences this reminder entirely)
# Honor opt-out before any work
[[ "${HABIT_QUIET:-}" == "1" ]] && exit 0
is_codex_hook_runtime() {
[ "${HABIT_HOOK_OUTPUT:-}" = "markdown" ] && return 1
[ "${HABIT_HOOK_OUTPUT:-}" = "codex-json" ] ||
[ -n "${CODEX_THREAD_ID:-}" ] ||
[ -n "${CODEX_CI:-}" ] ||
[ -n "${CODEX_MANAGED_PACKAGE_ROOT:-}" ]
}
json_escape() {
local line
local first=1
while IFS= read -r line; do
line=${line//\\/\\\\}
line=${line//\"/\\\"}
line=${line//$'\t'/\\t}
line=${line//$'\r'/\\r}
if [ "$first" -eq 1 ]; then
printf '%s' "$line"
first=0
else
printf '\\n%s' "$line"
fi
done
}
# Read version from the installed package manifest for the session banner.
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-.}"
VERSION=""
for MANIFEST in "$PLUGIN_ROOT/.claude-plugin/plugin.json" "$PLUGIN_ROOT/.codex-plugin/plugin.json"; do
[ -n "$VERSION" ] && break
VERSION=$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' \
"$MANIFEST" 2>/dev/null | head -1)
done
VERSION="${VERSION:-unknown}"
# Check for workflow artifacts to show progress
PRD="" ; ADR="" ; TASKS=""
[ -f PRD.md ] || [ -f docs/PRD.md ] && PRD="✓"
[ -d ADR ] || [ -d docs/ADR ] && ADR="✓"
[ -f TASKS.md ] || [ -f docs/TASKS.md ] && TASKS="✓"
# Habit profile state — emits level-specific adaptation directive (v2.7.0, Issue #96).
# When ~/.claude/habit-profile.md exists with a valid level, outputs a one-sentence
# directive that shapes how skills should adapt their verbosity in the session.
# When the profile is missing, falls back to the v2.6.0 /calibrate nudge.
#
# Override precedence: preferences.verbosity-override (verbose|concise) > level field.
# Unknown/missing level → Dependence fallback (safest for uncalibrated users).
#
# awk patterns use the pipe-safe "read until exit" technique from
# tests/validate-structure.sh:27 and validate-content.sh:614 to avoid the
# sed|head SIGPIPE flake fixed in v2.6.1.
PROFILE_MSG=""
PROFILE_FILE="${HOME}/.claude/habit-profile.md"
if [ -f "$PROFILE_FILE" ] && [ -r "$PROFILE_FILE" ]; then
# Extract level from frontmatter (between --- markers)
LEVEL=$(awk '/^---$/{c++; if(c==2) exit; next} c==1 && /^level:/{sub(/^level:[[:space:]]*/, ""); print; exit}' "$PROFILE_FILE" 2>/dev/null)
# Extract verbosity-override (nested under preferences:)
OVERRIDE=$(awk '/^preferences:/{f=1; next} /^[^[:space:]]/{if(f) exit; next} f && /verbosity-override:/{sub(/^[[:space:]]*verbosity-override:[[:space:]]*/, ""); print; exit}' "$PROFILE_FILE" 2>/dev/null)
# Apply override precedence: explicit verbose/concise wins over level
case "$OVERRIDE" in
verbose) EFFECTIVE_LEVEL="Dependence (verbose override)"; DIRECTIVE_LEVEL="Dependence" ;;
concise) EFFECTIVE_LEVEL="Significance (concise override)"; DIRECTIVE_LEVEL="Significance" ;;
""|none) EFFECTIVE_LEVEL="$LEVEL"; DIRECTIVE_LEVEL="$LEVEL" ;;
*) EFFECTIVE_LEVEL="$LEVEL"; DIRECTIVE_LEVEL="$LEVEL" ;;
esac
# Emit level-specific one-sentence directive
case "$DIRECTIVE_LEVEL" in
Dependence)
PROFILE_MSG="
📖 **Profile active: ${EFFECTIVE_LEVEL}** — skills should show full guidance, all checkpoints, and beginner examples inline."
;;
Independence)
PROFILE_MSG="
📖 **Profile active: ${EFFECTIVE_LEVEL}** — skills should show key checkpoints only and skip beginner examples."
;;
Interdependence)
PROFILE_MSG="
📖 **Profile active: ${EFFECTIVE_LEVEL}** — skills should focus on delegation, review, and synergy patterns over individual ceremony."
;;
Significance)
PROFILE_MSG="
📖 **Profile active: ${EFFECTIVE_LEVEL}** — skills should show minimal prompts, trust user judgment, and surface only non-obvious checkpoints."
;;
*)
# Unknown or missing level → Dependence fallback with visible note
PROFILE_MSG="
⚠️ **Profile exists but level is unknown** (got: \"${LEVEL:-<missing>}\") — using Dependence (full guidance) as fallback. Run \`/calibrate\` to refresh."
;;
esac
else
# No profile file → v2.6.0 nudge (backwards compatible)
PROFILE_MSG="
💡 **No habit profile detected** — run \`/calibrate\` to personalize guidance to your maturity level (H8)."
fi
# Workflow step awareness — detect highest completed step and suggest next skill
WORKFLOW_HINT=""
if [ "${HABIT_QUIET:-0}" != "1" ]; then
HIGHEST_STEP=0
# Check each step — use compgen (bash builtin) to test globs without ls exit-code issues
has_glob() { compgen -G "$1" >/dev/null 2>&1; }
# Check for Step 4 artifacts (build brief) — highest priority
if has_glob "*-brief.md" || has_glob "*build-brief*"; then
HIGHEST_STEP=4
# Check for Step 3 artifacts (breakdown/tasks)
elif has_glob "*-tasks.md" || has_glob "*-breakdown.md" || has_glob "*task-list*"; then
HIGHEST_STEP=3
# Check for Step 2 artifacts (design/architecture)
elif has_glob "*-design.md" || has_glob "*-architecture.md" || has_glob "*ADR*"; then
HIGHEST_STEP=2
# Check for Step 1 artifacts (PRD/requirements)
elif has_glob "*-prd.md" || has_glob "*-requirements.md" || has_glob "*PRD*"; then
HIGHEST_STEP=1
fi
if [ "$HIGHEST_STEP" -gt 0 ]; then
case $HIGHEST_STEP in
1) NEXT_SKILL="/design" ;;
2) NEXT_SKILL="/breakdown" ;;
3) NEXT_SKILL="/build-brief" ;;
4) NEXT_SKILL="/review-ai" ;;
esac
WORKFLOW_HINT="
📍 Workflow: artifacts suggest Step ${HIGHEST_STEP} done — next: \`${NEXT_SKILL}\`"
fi
fi
REMINDER=$(cat <<EOF
## 8-Habit AI Dev Active (v${VERSION})
**7-Step Workflow reference** — use what fits the task:
0. \`/research\` — Investigate before specifying (H5)
1. \`/requirements\` — Define what, why, who + EARS criteria (H2)${PRD:+ ✓}
2. \`/design\` — Architecture decisions + Art. 14 checkpoint (H8)${ADR:+ ✓}
3. \`/breakdown\` — Atomic tasks (H3)${TASKS:+ ✓}
4. \`/build-brief\` — Context before coding (H5)
5. \`/review-ai\` — Audit before commit (H4)
6. \`/deploy-guide\` — Staging first (H1)
7. \`/monitor-setup\` — Observe after deploy (H7)
**Core 5** (80% of daily work): \`/requirements\` · \`/review-ai\` · \`/cross-verify\` · \`/research\` · \`/reflect\`
**Assessment**: \`/workflow\` · \`/whole-person-check\` · \`/security-check\` · \`/ai-dev-log\`
**Onboarding**: \`/using-8-habits\` (decision tree) · \`/calibrate\` (maturity profile)
**Compliance**: \`/eu-ai-act-check\` (redirect stub — install \`pitimon/claude-governance\` v3.1.0+ for the canonical skill, migrated 2026-05-02 per ADR-012)${WORKFLOW_HINT}${PROFILE_MSG}
_Silence this reminder: \`export HABIT_QUIET=1\`_
EOF
)
if is_codex_hook_runtime; then
ESCAPED_REMINDER=$(printf '%s' "$REMINDER" | json_escape)
printf '{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"%s"}}\n' "$ESCAPED_REMINDER"
else
printf '%s\n' "$REMINDER"
fi