diff --git a/CLAUDE.md b/CLAUDE.md index 365ac0b..e4c809d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,7 +12,7 @@ plugins/ llm-security/ v6.0.0 — Security scanning, auditing, threat modeling ms-ai-architect/ v1.8.0 — Microsoft AI architecture (Cosmo Skyberg persona) okr/ v1.0.0 — OKR guidance for Norwegian public sector - ultraplan-local/ v2.3.0 — Brief, research, architect, plan, execute (five-command pipeline + skill-factory Fase 1) + ultraplan-local/ v2.3.1 — Brief, research, architect, plan, execute (five-command pipeline + skill-factory Fase 1) ``` Hvert plugin er selvstendig med egen CLAUDE.md, README, hooks, agents og commands. diff --git a/README.md b/README.md index 63aa276..d6572be 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ Key commands: `/config-audit posture`, `/config-audit feature-gap`, `/config-aud --- -### [Ultra {brief | research | architect | plan | execute} - local](plugins/ultraplan-local/) `v2.3.0` +### [Ultra {brief | research | architect | plan | execute} - local](plugins/ultraplan-local/) `v2.3.1` Deep requirements gathering, research, Claude Code feature matching, implementation planning, self-verifying execution, and skill-factory authoring with specialized agent swarms, adversarial review, IP-hygiene scoring, and failure recovery. @@ -76,7 +76,7 @@ Five core commands plus an authoring command, one pipeline with clear division o All artifacts land in one project directory: `.claude/projects/{YYYY-MM-DD}-{slug}/` contains `brief.md`, `research/NN-*.md`, `architecture/` *(v2.2)*, `plan.md`, `sessions/`, and `progress.json`. `--project ` works across `/ultraresearch-local`, `/ultra-cc-architect-local`, `/ultraplan-local`, and `/ultraexecute-local`. -v2.3 (non-breaking) ships the skill-factory Fase 1 MVP: `/ultra-skill-author-local` plus four supporting agents (1 opus orchestrator + 3 sonnet workers) and `scripts/ngram-overlap.mjs` (pure Node stdlib, word-5-gram containment + longest-run secondary signal, calibrated against three source/draft fixture pairs). Catalog growth is now tractable without touching the architect's hallucination gate. Non-goals stay explicit: no automation, no batch, no decision-layer skills, no remote sources — manual `mv` from `.drafts/` to catalog root is the promotion mechanism. +v2.3 (non-breaking) ships the skill-factory Fase 1 MVP: `/ultra-skill-author-local` plus four supporting agents (1 opus orchestrator + 3 sonnet workers) and `scripts/ngram-overlap.mjs` (pure Node stdlib, word-5-gram containment + longest-run secondary signal, calibrated against three source/draft fixture pairs). Catalog growth is now tractable without touching the architect's hallucination gate. Non-goals stay explicit: no automation, no batch, no decision-layer skills, no remote sources — manual `mv` from `.drafts/` to catalog root is the promotion mechanism. v2.3.1 adds a qualified-slug convention (`[-]-.md`) so one feature can host multiple named patterns at different abstraction levels without displacing the baseline — resolved a collision surfaced in v2.3.0 dogfood. v2.2 (non-breaking) adds the optional `/ultra-cc-architect-local` step between research and planning. The architect phase is backed by a versioned catalog skill (`cc-architect-catalog`) with 10 seed entries across three layers (reference, pattern, decision). Gaps are captured as issue-ready drafts so the catalog grows from real usage rather than speculation. `/ultraplan-local` auto-discovers the architecture note — existing pipelines keep working unchanged. diff --git a/plugins/ultraplan-local/.claude-plugin/plugin.json b/plugins/ultraplan-local/.claude-plugin/plugin.json index 1f2cb11..d22502b 100644 --- a/plugins/ultraplan-local/.claude-plugin/plugin.json +++ b/plugins/ultraplan-local/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "ultraplan-local", "description": "Five-command context-engineering pipeline (brief → research → architect → plan → execute) with project folders, CC-feature matching, specialized agent swarms, external research triangulation, adversarial review, session decomposition, and headless execution.", - "version": "2.3.0", + "version": "2.3.1", "author": { "name": "Kjell Tore Guttormsen" }, diff --git a/plugins/ultraplan-local/CHANGELOG.md b/plugins/ultraplan-local/CHANGELOG.md index f573ae3..f357a4d 100644 --- a/plugins/ultraplan-local/CHANGELOG.md +++ b/plugins/ultraplan-local/CHANGELOG.md @@ -4,6 +4,47 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +## [2.3.1] - 2026-04-18 + +### Added — Qualified slug convention for cc-architect-catalog + +Catalog files now follow `[-]-.md`. The +unqualified slug (e.g., `hooks-pattern.md`) remains the canonical +baseline for a `(feature, layer)` pair. Qualified slugs (e.g., +`hooks-observability-pattern.md`) cover specific sub-patterns without +displacing the baseline. + +**Why.** v2.3.0 dogfood surfaced a design gap: the skill-factory +produced a draft `hooks-pattern.md` from a specialized source (progressive- +alert observability) that collided with the existing generic `hooks-pattern.md` +seed. Promoting would have replaced the general pattern with a narrow +one; discarding would have lost real catalog growth. Qualified slugs +resolve this by letting one feature host multiple named patterns at +different abstraction levels. + +**Changes.** + +- `skills/cc-architect-catalog/SKILL.md` — slug convention section added; + coverage table gains "qualified patterns" column; matcher logic + documented for N patterns per feature; modification rules cover + qualified-vs-canonical choice and slug-collision handling. +- `agents/feature-matcher.md` — catalog map is now + `cc_feature → {layer → [skills]}`; new "Selecting among multiple + patterns per feature" section (baseline by default, qualified when + justified, multiple when non-overlapping, never purely cosmetic); + `supporting_skill` accepts one-or-more skill names. +- `agents/gap-identifier.md` — adds `pattern_count[cc_feature]` signal + to the catalog coverage audit. +- `agents/architecture-critic.md` — adds supporting-skill verification: + every cited skill name must exist in the catalog; blocker severity. +- First qualified skill: `hooks-observability-pattern.md` (promoted from + `.drafts/`, sourced from `ai-psychosis/README.md`, ngram-overlap 0.01, + review_status approved). + +**Non-breaking.** Existing unqualified slugs keep working. No changes to +`cc_feature` taxonomy. Hallucination gate unchanged (still validates +against `cc_feature` values, not slugs). + ## [2.3.0] - 2026-04-18 ### Added — Skill-factory Fase 1 MVP (`/ultra-skill-author-local`) diff --git a/plugins/ultraplan-local/CLAUDE.md b/plugins/ultraplan-local/CLAUDE.md index 388af85..5a829ce 100644 --- a/plugins/ultraplan-local/CLAUDE.md +++ b/plugins/ultraplan-local/CLAUDE.md @@ -123,6 +123,16 @@ Architect sits between `/ultraresearch-local` and `/ultraplan-local`. It matches **CC-feature catalog skill:** The architect phase loads the `cc-architect-catalog` skill, which indexes Claude Code primitives (hooks, subagents, skills, output styles, MCP, plan mode, worktrees, background agents) across three layers: `reference` (how a feature works), `pattern` (when to reach for it), `decision` (adoption heuristics). The `feature-matcher` agent only proposes features covered by the catalog *or* an explicit fallback list — a hallucination gate that `architecture-critic` enforces as BLOCKER severity. The `gap-identifier` agent emits issue-ready drafts for missing catalog entries so the catalog grows with real usage rather than speculation. The catalog lives at `skills/cc-architect-catalog/`. +**Slug convention (v2.3.1):** catalog files follow `[-]-.md`. + +- **Unqualified slugs** (e.g., `hooks-pattern.md`) are the canonical baseline — one per `(feature, layer)` pair, covering generic shapes and decision-heuristics for the feature. +- **Qualified slugs** (e.g., `hooks-observability-pattern.md`) cover specific named sub-patterns. Zero-or-more per `(feature, layer)` pair. The qualifier MUST be kebab-case and descriptive (`observability`, `migration`, `multi-tenant`). +- **Matcher logic:** `feature-matcher` builds `cc_feature → {layer → [skills]}` and prefers the unqualified baseline when the brief does not specifically justify a variant. Multiple skills can be proposed together when they cover non-overlapping aspects of the same feature. +- **Critic enforcement:** `architecture-critic` verifies every cited `supporting_skill` name exists as a real file in the catalog (blocker severity). The `cc_feature` hallucination gate is unchanged — still validates against the taxonomy, not slugs. +- **Collision handling:** skill-factory drafts that would overwrite an approved slug are a hard error. Resolution is either to qualify the new slug or revise the existing baseline. + +Seeds v2.3.1: 11 skills across 8 features — one qualified pattern (`hooks-observability-pattern.md`, promoted from `ai-psychosis/README.md`, ngram-overlap 0.01, approved). Decision-layer intentionally empty pending skill-factory Fase 2. + ## State All artifacts in one project directory (default): diff --git a/plugins/ultraplan-local/README.md b/plugins/ultraplan-local/README.md index b93f905..b7ddea2 100644 --- a/plugins/ultraplan-local/README.md +++ b/plugins/ultraplan-local/README.md @@ -1,6 +1,6 @@ # ultraplan-local — Brief, Research, Architect, Plan, Execute -![Version](https://img.shields.io/badge/version-2.3.0-blue) +![Version](https://img.shields.io/badge/version-2.3.1-blue) ![License](https://img.shields.io/badge/license-MIT-green) ![Platform](https://img.shields.io/badge/platform-Claude%20Code-purple) @@ -224,7 +224,9 @@ Downstream: `/ultraplan-local` auto-discovers `architecture/overview.md` in proj ### CC-feature catalog -The architect command reads from `skills/cc-architect-catalog/`, a plugin-internal catalog of hand-written skills covering each CC feature at one or more layers (`reference`, `pattern`, `decision`). v2.2 ships 10 seeds covering all 8 features at the reference layer (plus pattern layer for hooks and subagents). The catalog is designed for later expansion via a separate skill-factory process — gaps surfaced by the architect command are the backlog for that work. +The architect command reads from `skills/cc-architect-catalog/`, a plugin-internal catalog of hand-written skills covering each CC feature at one or more layers (`reference`, `pattern`, `decision`). v2.2 shipped 10 seeds covering all 8 features at the reference layer (plus pattern layer for hooks and subagents). The catalog is designed for expansion via the skill-factory process (v2.3) — gaps surfaced by the architect command are the backlog for that work. + +**Slug convention (v2.3):** files follow `[-]-.md`. Unqualified slugs (e.g., `hooks-pattern.md`) are the baseline/canonical entry for a `(feature, layer)` pair. Qualified slugs (e.g., `hooks-observability-pattern.md`) cover specific sub-patterns without displacing the baseline. `feature-matcher` prefers the baseline when the brief does not specifically justify a qualified variant; it may propose multiple supporting skills when they cover non-overlapping aspects. Slug collisions with approved skills are a hard error — skill-factory drafts must qualify or revise instead. ### Hallucination gate diff --git a/plugins/ultraplan-local/agents/architecture-critic.md b/plugins/ultraplan-local/agents/architecture-critic.md index 4baa8cf..b63bd5f 100644 --- a/plugins/ultraplan-local/agents/architecture-critic.md +++ b/plugins/ultraplan-local/agents/architecture-critic.md @@ -66,6 +66,14 @@ the catalog or fallback list. catalog, this is a **major** finding (REVISE — the feature is real but the catalog has a coverage gap worth surfacing), not a blocker. +**Supporting-skill verification:** `supporting_skill` entries (one or +more skill names per feature, following the +`[-]-.md` convention) must match real files +in the catalog. A cited skill that does not exist is a **blocker**. +Multiple supporting skills for one feature are allowed when they cover +non-overlapping aspects — but the `integration_note` must justify +having more than one. + ### 3. Contradiction detection Scan for internal contradictions: diff --git a/plugins/ultraplan-local/agents/feature-matcher.md b/plugins/ultraplan-local/agents/feature-matcher.md index 95e2403..7296e1c 100644 --- a/plugins/ultraplan-local/agents/feature-matcher.md +++ b/plugins/ultraplan-local/agents/feature-matcher.md @@ -47,14 +47,16 @@ enough. ### 2. Consult the catalog -Read `{catalog_root}/SKILL.md` to learn the `cc_feature` taxonomy and -layer model. +Read `{catalog_root}/SKILL.md` to learn the `cc_feature` taxonomy, the +layer model, and the slug convention (`[-]-.md`). Glob `{catalog_root}/*.md` excluding `SKILL.md`. Parse each skill's frontmatter: - `name`, `description`, `layer`, `cc_feature`, `source`, `concept`. -Build an in-memory map: `cc_feature → [skill_names]`. +Build an in-memory map: `cc_feature → {layer → [skills]}`. One feature +can have multiple pattern-layer skills (one baseline plus zero-or-more +qualified variants). **Fallback when the catalog is empty or unreadable:** use this hardcoded minimum list. Mark `fallback_used: true` in your output. @@ -79,14 +81,37 @@ For each feature you propose, produce: Goal / Constraint / NFR / Success Criterion) that motivates this feature. Prefer verbatim quotes; paraphrase only when length forces it. -- **supporting_skill** — a skill name from the catalog that supports - this choice, or `null` if only the fallback hint was used. +- **supporting_skill** — one or more skill names from the catalog that + support this choice, or `null` if only the fallback hint was used. + When multiple pattern skills exist for the feature, apply the + selection rules below. - **confidence** — `high` (direct brief anchor + skill), `medium` (brief anchor without strong skill support, or skill match without a strong anchor), `low` (inferred need with no explicit anchor). - **integration_note** — one sentence on how this feature integrates with the task at hand. +#### Selecting among multiple patterns per feature + +A feature can have a baseline pattern (`-pattern.md`) plus +zero-or-more qualified patterns (`--pattern.md`). +When the feature is relevant to the brief: + +1. **Baseline by default.** If the brief's anchor is generic + ("need hooks for policy"), pick the unqualified `-pattern`. +2. **Qualified when justified.** If the brief explicitly calls for the + qualified variant's concept (e.g., observability, migration, + multi-tenant), pick the qualified pattern and name it in + `supporting_skill`. The anchor must reference the specific aspect, + not just the feature. +3. **Propose both when they cover non-overlapping aspects.** Example: + the brief needs both generic hook shapes *and* observability-style + cadence tracking — list `supporting_skill: [hooks-pattern, hooks-observability-pattern]` + and explain the split in `integration_note`. +4. **Never pick a qualified pattern just because it looks fancier.** + If the brief does not justify the qualifier, the baseline is the + honest answer. + ### 4. Propose feature composition After the per-feature list, write a short (3–5 bullet) note on how the @@ -112,7 +137,7 @@ Return your response as markdown, with this structure: 1. **** (confidence: ) - Brief anchor: "" - - Supporting skill: + - Supporting skill: - Integration: 2. ... @@ -140,7 +165,8 @@ Return your response as markdown, with this structure: fallback list.** That is a hallucination; `architecture-critic` will block it. - **Never invent skill names.** If you don't see a skill for a - feature, say "none — fallback hint". + feature, say "none — fallback hint". Every skill name in + `supporting_skill` must match a real file in the catalog. - **Quote the brief; don't paraphrase silently.** Reviewers need to verify the anchor matches. - **Rationale must trace to the brief.** "We should have hooks because diff --git a/plugins/ultraplan-local/agents/gap-identifier.md b/plugins/ultraplan-local/agents/gap-identifier.md index 76a994d..0411da8 100644 --- a/plugins/ultraplan-local/agents/gap-identifier.md +++ b/plugins/ultraplan-local/agents/gap-identifier.md @@ -38,12 +38,16 @@ enough" notes. You do not propose architecture — only gaps. ### 1. Catalog audit -Read `{catalog_root}/SKILL.md` to learn the taxonomy + coverage table. -Glob `{catalog_root}/*.md` (excluding `SKILL.md`) and parse -frontmatter. Build: +Read `{catalog_root}/SKILL.md` to learn the taxonomy, slug convention +(`[-]-.md`), and coverage table. Glob +`{catalog_root}/*.md` (excluding `SKILL.md`) and parse frontmatter. +Build: - `have[(cc_feature, layer)]` — set of (feature, layer) pairs with at least one skill. +- `pattern_count[cc_feature]` — number of pattern-layer skills per + feature (useful signal for the audit; one baseline plus zero-or-more + qualified variants). ### 2. Read the brief + research @@ -111,7 +115,7 @@ They are not issues; they are informational. ### Catalog coverage audit - Skills in catalog: N - Features with reference: [list] -- Features with pattern: [list] +- Features with pattern: [list with (feature, pattern_count) when >1] - Features with decision: [list] - Features with no coverage: [list] diff --git a/plugins/ultraplan-local/skills/cc-architect-catalog/SKILL.md b/plugins/ultraplan-local/skills/cc-architect-catalog/SKILL.md index e73518d..ba4948b 100644 --- a/plugins/ultraplan-local/skills/cc-architect-catalog/SKILL.md +++ b/plugins/ultraplan-local/skills/cc-architect-catalog/SKILL.md @@ -83,32 +83,70 @@ skill-factory output will start as `pending` (channel 2) or If a future skill covers a feature not in this list, add the row above and surface the extension in the relevant CHANGELOG entry. +## Slug convention + +Skill filenames follow this pattern: + +``` +[-]-.md +``` + +- **Unqualified slug** (`-.md`) — the baseline/canonical + entry for that (feature, layer) pair. One per pair. Example: + `hooks-pattern.md` = generic hook shapes and pitfalls. +- **Qualified slug** (`--.md`) — a + specialized variant covering one specific sub-pattern or use-case. + Zero-or-more per pair. Example: `hooks-observability-pattern.md` = + progressive-alert observability pattern specifically. + +Qualifiers exist because one CC feature can support multiple +non-overlapping patterns at different abstraction levels. Forcing +everything into a single `-.md` either bloats the +canonical entry or loses useful specialization. Qualified slugs let the +catalog grow with concrete, named patterns without displacing the +baseline. + +`feature-matcher` treats all skills with the same `cc_feature` + `layer` +as candidates and picks the most relevant to the brief (or proposes +several if they cover different aspects). See "How `feature-matcher` +uses this file" below. + ## Current seed coverage (v2.3.0 — see .drafts/ for skill-factory output) -| Feature | reference | pattern | decision | -|---------|-----------|---------|----------| -| hooks | hooks-reference | hooks-pattern | — | -| subagents | subagents-reference | subagents-pattern | — | -| skills | skills-reference | — | — | -| output-styles | output-styles-reference | — | — | -| mcp | mcp-reference | — | — | -| plan-mode | plan-mode-reference | — | — | -| worktrees | worktrees-reference | — | — | -| background-agents | background-agents-reference | — | — | +| Feature | reference | pattern | qualified patterns | decision | +|---------|-----------|---------|--------------------|----------| +| hooks | hooks-reference | hooks-pattern | hooks-observability-pattern | — | +| subagents | subagents-reference | subagents-pattern | — | — | +| skills | skills-reference | — | — | — | +| output-styles | output-styles-reference | — | — | — | +| mcp | mcp-reference | — | — | — | +| plan-mode | plan-mode-reference | — | — | — | +| worktrees | worktrees-reference | — | — | — | +| background-agents | background-agents-reference | — | — | — | -Total: 10 seed skills, 8 features, 2 layers. Decision-layer is +Total: 11 seed skills, 8 features, 2 layers. Decision-layer is intentionally empty — decisions cross features and require broader synthesis than a single seed pass can provide. Skill-factory populates decision-layer later. ## How `feature-matcher` uses this file -1. Read this file to learn the `cc_feature` taxonomy. +1. Read this file to learn the `cc_feature` taxonomy and slug convention. 2. Glob the directory for `*.md` files (excluding SKILL.md). 3. Parse each skill's frontmatter. 4. For each feature mentioned in the brief or research, match against - `cc_feature` field. Prefer `pattern` over `reference` when both exist - (pattern is richer). + `cc_feature` field. Build the candidate set per feature, grouped by + layer. Selection rules: + - **Layer preference:** prefer `pattern` over `reference` when both + exist (pattern is richer). + - **Multiple patterns per feature:** when two or more pattern-layer + skills share the same `cc_feature`, read each `description` and + pick the one(s) most relevant to the brief. If two cover + non-overlapping aspects that both apply, propose both with clear + rationale. Prefer the unqualified baseline (`-pattern.md`) + when the brief does not specifically justify a qualified variant. + - **Be explicit:** name the chosen skill in `supporting_skill` so + `architecture-critic` can verify the match. 5. When no skill exists for a mentioned feature, fall back to the hardcoded minimum-list inside the `feature-matcher` prompt and mark the gap in stats (`fallback_used: true`). @@ -132,9 +170,24 @@ decision-layer later. ## Modification rules -- Adding a new skill: create `-.md` with the frontmatter - above and bump the coverage table in this file. -- Renaming `cc_feature` values: update both this file AND every skill - using the old value in the same commit. -- Removing a skill: document in CHANGELOG under the version that drops - it. +- **Adding a canonical skill:** create `-.md` with the + frontmatter contract above. Bump the coverage table in this file. +- **Adding a qualified pattern skill:** create + `--.md` when the new pattern covers a + distinct sub-case that does not belong in the unqualified baseline. + The qualifier MUST be kebab-case and descriptive (e.g., + `observability`, `migration`, `multi-tenant`). Add it to the + "qualified patterns" column in the coverage table. +- **Choosing qualified vs. canonical:** if no unqualified skill exists + yet for a `(feature, layer)` pair, the new skill SHOULD be the + unqualified baseline — don't ship a qualified skill without a + canonical one, because `feature-matcher` prefers baseline when the + brief has no specific justification for a variant. +- **Renaming `cc_feature` values:** update both this file AND every + skill using the old value in the same commit. +- **Removing a skill:** document in CHANGELOG under the version that + drops it. +- **Slug collision:** two skills with the same slug are a hard error. + Skill-factory (`/ultra-skill-author-local`) must refuse to promote a + draft that would overwrite an approved skill. Collision is resolved + either by qualifying the new slug or by revising the baseline. diff --git a/plugins/ultraplan-local/skills/cc-architect-catalog/hooks-observability-pattern.md b/plugins/ultraplan-local/skills/cc-architect-catalog/hooks-observability-pattern.md new file mode 100644 index 0000000..6f2ce04 --- /dev/null +++ b/plugins/ultraplan-local/skills/cc-architect-catalog/hooks-observability-pattern.md @@ -0,0 +1,50 @@ +--- +name: hooks-observability-pattern +description: Observe user-interaction patterns across session lifecycle hooks and emit cooldown-gated nudges +layer: pattern +cc_feature: hooks +source: ../../../../ai-psychosis/README.md +concept: progressive alerts via lifecycle hooks +last_verified: 2026-04-18 +ngram_overlap_score: 0.01 +review_status: approved +--- + +# Hooks — Progressive-Alert Observability Pattern + +## Use this when + +- Measure behaviour the model itself cannot see: cadence, duration, repetition, time-of-day. +- Surface soft nudges rather than hard blocks — the operator keeps the final call. +- Separate "what happened" (metrics) from "what was said" (prompt text) so no conversation content touches disk. + +## Shape + +- Wire four lifecycle events: a start handler for baseline counters, a prompt handler for language-category flags, a tool handler for cadence and burst detection, and an end handler for totals and state cleanup. +- Keep per-session counters in a tiny JSON file under the plugin data dir; keep aggregate events in an append-only JSONL log for later reporting. +- Gate every nudge behind two things: a threshold (hard or soft) and a cooldown window, so repeat alerts do not spam the transcript. +- Deliver alerts as `additionalContext` injection, never as a tool block — the goal is awareness, not control. + +## Forces + +- **Privacy vs. signal.** Richer signal wants more content logged; the user wants none. Resolve by computing boolean flags in-memory and discarding the raw text before the handler returns. +- **Latency budget.** Handlers fire on every prompt and every tool call. Stay well under 100 ms per invocation; append-only JSONL is sub-millisecond and safe. +- **Portability.** Hooks that assume a shell, `jq`, or npm dependencies break on half the operator fleet. Stick to Node stdlib so the same script runs on macOS, Linux, and Windows. +- **Instruction layer alone is not enough.** Behavioural rules in a skill file shape tone but cannot measure duration or frequency. Layer the hook observability on top of the skill — each compensates for the other. + +## Gotchas + +- A handler that crashes blocks the turn. Catch everything, log, and exit zero by default. +- Cooldowns must be per-category, not global, or the most-triggered alert silences the rarer, more informative ones. +- Late-night and rapid-fire thresholds are legitimate signals but also easy to over-tune; start with generous bands and tighten only with data. +- `additionalContext` from an end-of-session handler is discarded — inject alerts on start, prompt, or tool events where the model will actually see them. + +## Anti-patterns + +- Storing prompt text or tool arguments "just for debugging" — once it is on disk, the privacy guarantee is gone. +- Treating every elevated metric as an intervention. If the hook starts blocking, the operator works around it and loses the awareness benefit. +- Hardcoding thresholds into the handler. Pull them from a single config so future tuning does not require a rewrite of four scripts. + +## Decision quick-check + +Reach for this pattern when you need visibility into *how* the user is interacting, not *what* they are saying, and when the response should be a gentle nudge rather than a gate. Otherwise use a PreToolUse denylist (hard limit) or a skill-only instruction layer (style, not cadence).