Skip to content

feat(ambient): first-word keyword detection in preamble hook#235

Merged
dean0x merged 7 commits into
mainfrom
feat/ambient-keyword-trigger
Jun 2, 2026
Merged

feat(ambient): first-word keyword detection in preamble hook#235
dean0x merged 7 commits into
mainfrom
feat/ambient-keyword-trigger

Conversation

@dean0x
Copy link
Copy Markdown
Owner

@dean0x dean0x commented Jun 2, 2026

Summary

Implements first-word keyword detection in the preamble hook to enable zero-overhead ambient workflow triggering. When a prompt begins with implement, explore, research, debug, or plan (case-insensitive), the hook automatically invokes the matching devflow:<keyword> skill — eliminating friction for frequent workflows while incurring zero overhead for normal prompts.

Changes

Hook Enhancement

  • First-word keyword detection: Preamble hook detects workflow keywords as the first word of the user prompt
  • Strict guards: Requires a second word and skips prompts ending in ? (questions don't trigger automation)
  • Zero overhead: Hook outputs nothing for non-matching prompts

Test Suite

  • New C7 test (hostile-tail) validates that keyword detection respects the question-mark edge case
  • Const-qualified test variable for immutability alignment
  • Full coverage of 5 keywords (implement, explore, research, debug, plan)

Breaking Changes

None — this is a zero-opt-in enhancement. Existing behavior unchanged for normal prompts.

Testing

  • Unit tests: Full coverage of keyword detection logic and edge cases
  • Manual: Verified keywords trigger workflow invocation; non-matching prompts remain unchanged
  • Edge cases: Prompts ending in ? correctly skip automation

Related Issues

Part of ambient mode enhancement (zero-overhead workflow acceleration)

Dean Sharon added 2 commits June 2, 2026 18:06
Extends the preamble UserPromptSubmit hook with a second detection path
alongside the existing 3-marker plan detection. When a prompt's first
word (case-insensitive) is one of implement/explore/research/debug/plan,
followed by at least one more word and not ending in '?', the hook emits
a directive telling the model to announce then invoke the matching
devflow:<keyword> skill via the Skill tool.

Key implementation properties:
- Pure bash 3.2 (no ${var,,}/tr): uses shopt nocasematch + lowercase case arms
- O(1) keyword scan: HEAD="${PROMPT:0:256}" bounds the hot-path work
- No subprocesses on the keyword path: pure parameter expansion
- Question guard uses "$PROMPT =~ [?][[:space:]]*$" (avoids bash 3.2
  negative-offset-empty-string bug with "${PROMPT: -N}" on short strings)
- Keyword path takes precedence; marker path fires only when keyword path
  does not match; both share the single devflow ambient toggle
- No file I/O on either path; stdout is empty on no-match (zero bytes)

Tests (shell-hooks.test.ts): 4 new suites, 37 new test cases
- Suite 1 (F1–F11): functionality table — match/no-match cases
- Suite 2 (C1–C7): API contract — schema, zero-byte empty, exit codes,
  no file I/O, bash-3.2 guard, injection safety
- Suite 3 (C7): security/fuzz — 8 hostile payloads assert output equals
  the fixed template only (no user text reaches additionalContext)
- Suite 4 (P1–P3): performance — no-subprocess static check + wall-time
  length-independence assertion (delta < 500ms, ratio < 5×)

Docs: CLAUDE.md Ambient Mode paragraph and devflow-ambient README updated
to describe both detection paths and command auto-trigger coverage.
…ualify the out variable in the C7 test to reflect immutable usage. Co-Authored-By: Claude <noreply@anthropic.com>
@dean0x
Copy link
Copy Markdown
Owner Author

dean0x commented Jun 2, 2026

Line 3-5: Stale File Header

The file header still describes plan-detection-only behavior:

# Detects structured implementation plans and injects a directive to execute them.
# Zero overhead for normal prompts — only fires when all three plan markers are present.

After this PR, the hook also fires on first-word keywords (implement/explore/research/debug/plan), so "only fires when all three plan markers are present" is now incorrect.

Suggested fix:

# Devflow Preamble: UserPromptSubmit Hook
# Two coexisting detection paths: (1) first-word workflow keyword (implement/explore/research/debug/plan) 
# → invoke devflow:<keyword>; (2) structured plan (## Goal + ## Steps + ## Files) → devflow:implement.
# Zero overhead for normal prompts — emits nothing when neither path fires.

Confidence: 95% | Flagged by: consistency, documentation, regression reviewers

@dean0x
Copy link
Copy Markdown
Owner Author

dean0x commented Jun 2, 2026

Line 60-62: Inaccurate Comment on Regex Efficiency

The inline comment claims the $ anchor avoids a full scan:

# Guard B: skip prompts ending in '?' (the $ anchor makes this efficient — bash regex
# does not scan the full string for a trailing match; no subprocess required).
if [[ -n "$SKILL" && -n "$REST" ]] && ! [[ "$PROMPT" =~ [?][[:space:]]*$ ]]; then

This is factually incorrect. POSIX ERE matching in bash 3.2 walks the entire string to establish match positions. The $ anchor does not enable a right-to-left or tail-only scan. Measured performance (via performance reviewer): O(n) in prompt length — ~6ms per invocation on a 200KB prompt.

Impact: The comment will mislead future maintainers and contradicts the bounding intent established at line 40 (HEAD="${PROMPT:0:256}").

Suggested fix:

# Guard B: skip prompts ending in '?' (uses full $PROMPT, not $HEAD, because the trailing '?'
# lives at the END of the prompt, beyond the 256-byte keyword window). Regex is O(n) in bash 3.2.
# Only runs when $SKILL matched, so normal prompts are unaffected.

Confidence: 95% | Flagged by: performance reviewer | Risk: HIGH (affects understanding of the hot path)

@dean0x
Copy link
Copy Markdown
Owner Author

dean0x commented Jun 2, 2026

README Line 3: Stale Tagline

The README's one-line summary now contradicts the detailed feature description that immediately follows:

Current tagline:

Ambient mode — plan auto-detection. A UserPromptSubmit hook detects structured implementation plans and invokes the implement workflow automatically.

What the README actually documents (lines 15-58): Two coexisting detection paths — first-word keyword dispatch AND structured plan detection.

A reader skimming the top of the README gets the wrong scope. This is code-doc drift in a file this PR modifies heavily.

Suggested fix:

Ambient mode — first-word keyword dispatch + structured-plan auto-detection. A `UserPromptSubmit` hook routes prompts to the matching devflow workflow.

Confidence: 88% | Flagged by: documentation reviewer

@dean0x
Copy link
Copy Markdown
Owner Author

dean0x commented Jun 2, 2026

Line 64 vs 67: Divergent Directive-Text Style

The two detection paths emit stylistically inconsistent directives for the same purpose (instructing the model to invoke a devflow:<skill>):

Keyword path (line 64): Natural-language announcement:

"The user is invoking the `$SKILL` workflow. Briefly tell the user you are invoking `devflow:$SKILL`, then invoke it..."

Plan path (line 67): Terse marker token:

"EXECUTION_PLAN detected. Invoke `devflow:implement` via the Skill tool to execute this plan."

The keyword path announces to the user first, while the plan path leaks an internal token (EXECUTION_PLAN detected) into model-facing context. Since both paths now live in the same hook and both invoke a devflow skill, consistent phrasing is better.

Suggested fix:
Align the plan-path directive with the keyword-path style. Example:

json_prompt_output "The user supplied a structured implementation plan. Briefly tell the user you are invoking \`devflow:implement\`, then invoke it via the Skill tool to execute this plan."

Low risk: no test asserts the exact plan-path string except :1182 which checks the keyword path does NOT contain EXECUTION_PLAN detected — removing that token from user-facing text is compatible.

Confidence: 85% | Flagged by: consistency reviewer

@dean0x
Copy link
Copy Markdown
Owner Author

dean0x commented Jun 2, 2026

PR Summary: Review Complete

Overall Recommendation: ✅ APPROVED_WITH_CONDITIONS

Inline Comments Created

Four inline comments have been posted above, all at >=80% confidence:

  1. Stale file header (lines 3-5 of preamble) — 95% confidence
  2. Inaccurate regex efficiency comment (lines 60-62 of preamble) — 95% confidence
  3. Stale README tagline (line 3 of README) — 88% confidence
  4. Divergent directive-text style (lines 64 vs 67 of preamble) — 85% confidence

All four are should-fix items requiring minor documentation updates. No blocking issues across any dimension.

Non-Blocking Informational Items (60-79% confidence)

Note 1: ADR-013 is now stale relative to shipped code

  • The decision record documents four keywords (implement/explore/research/debug) but the code ships five (adds plan)
  • ADR-013 says keyword dispatch "replaces" three-marker plan detection, but the code coexists both paths
  • The shipped code and user-facing docs (README, CLAUDE.md) are correct; only the ADR is out of date
  • This is metadata, not executable code — not merge-blocking
  • Consider appending a follow-up ADR clarifying the actual behavior

Note 2: Test coverage gaps (non-blocking)

  • Multi-character trailing punctuation (implement..., debug!!) is untested but correctly handled
  • Leading-whitespace match path (\n\n implement) is indirectly covered but has no positive test case
  • These are existing behaviors the code exercises; tests would lock them in against regression

Scoring Summary

Dimension Score Status
Security 9/10 APPROVED — no injection or command-substitution vulnerabilities
Architecture 9/10 APPROVED — LLM-vs-plumbing boundary preserved, ADR-008 alignment
Performance 7/10 HIGH finding (inaccurate comment) — code is correct, comment must be fixed
Complexity 8/10 APPROVED_WITH_CONDITIONS — one clarifying comment needed
Consistency 8/10 APPROVED_WITH_CONDITIONS — two stale documentation items
Regression 9/10 APPROVED_WITH_CONDITIONS — plan-detection path preserved
Testing 8/10 APPROVED — four-suite plan satisfied, two minor coverage gaps
Reliability 9/10 APPROVED — bounded work, exit-0 discipline, set-e safety confirmed
TypeScript 9/10 APPROVED — no any, explicit return types, resource cleanup correct
Documentation 8/10 APPROVED_WITH_CONDITIONS — two should-fix stale headers

Key Findings: What Works Well

  • Zero overhead for normal prompts — keyword path is genuinely cheap and correctly bounded
  • Security posture is strong: untrusted prompt never interpolated into directive; injection prevented by design
  • All test suites pass (37/37) with behavior-focused assertions mapping cleanly to ADR-014
  • Code follows existing conventions: hook bootstrap, json_prompt_output reuse, set -e discipline

What Needs Fixing Before Merge

  1. Update preamble file header (lines 3-5) — describe both detection paths
  2. Fix inaccurate regex efficiency comment (lines 60-62) — explain O(n) and why full $PROMPT is needed
  3. Update README tagline (line 3) — broaden scope beyond "plan auto-detection"
  4. Align plan-path directive text (line 67) — drop EXECUTION_PLAN detected token, use announcement style

All four fixes are one-liners or small multi-line comments. No architectural changes needed.


Review conducted by: devflow code-review reviewers (security, architecture, performance, complexity, consistency, regression, testing, reliability, typescript, documentation)
Branch: feat/ambient-keyword-trigger → main
PR: #235
Timestamp: 2026-06-02_1826
Claude Code Review Agent

Dean Sharon and others added 5 commits June 2, 2026 22:14
…ne previously only mentioned plan auto-detection. PR #235 added first-word keyword dispatch as a coequal detection path -- tagline now reflects both the keyword -> devflow:<keyword> path and the structured plan -> devflow:implement path.
…ting design

Shipped preamble hook has five keywords (implement/explore/research/debug/plan)
and retains three-marker structured-plan detection as a coexisting elif fallback,
not a replacement. ADR-013 body previously stated four keywords and that the
keyword path "replaces" plan detection — both incorrect. Update prose to match
actual behavior.
- Header: describe both detection paths (keyword dispatch + structured plan)
  instead of the now-stale "only fires when all three plan markers are present"
- Guard B comment: retract the false claim that bash $ anchor enables tail-only
  scan; state plainly that the regex is O(n) over prompt length and runs against
  full $PROMPT (not $HEAD) because the trailing ? lives beyond the 256-byte window
- Plan-path directive: align phrasing with keyword-path style, drop the internal
  EXECUTION_PLAN token from the user-facing text
- plan case arm: add inline note distinguishing plan keyword (devflow:plan)
  from the structured-plan path (devflow:implement)

All 163 shell-hooks tests pass. avoids PF-007 (source hook edited, not installed copy).

Co-Authored-By: Claude <noreply@anthropic.com>
F12: assert that multi-char trailing punct (implement...) is NOT stripped to a
keyword — WORD="${TOKEN%[[:punct:]]}" removes exactly one char, leaving
"implement.." which does not case-match, so output is empty.

F13: assert that prompts with leading newlines/spaces (\\n\\n  implement ...) DO
match — preamble:41 strips HEAD leading whitespace before extracting the first
token, so the keyword is correctly isolated.

Both cases verified against the running hook before asserting (applies ADR-014).
All 165 tests pass.

Co-Authored-By: Claude <noreply@anthropic.com>
preamble:41 pointed at a comment line and would drift on any edit.
Replaced with a description of the behavior the test exercises.
@dean0x dean0x merged commit 4c5fef1 into main Jun 2, 2026
4 checks passed
@dean0x dean0x deleted the feat/ambient-keyword-trigger branch June 2, 2026 19:45
dean0x added a commit that referenced this pull request Jun 2, 2026
…ghten preamble directives (#236)

## Summary

Ambient mode gained first-word keyword detection in #235 (prompts
starting with `implement`, `explore`, `research`, `debug`, or `plan`
invoke the matching `devflow:<keyword>` skill). But the init flow,
`devflow ambient` CLI text, plugin description, and README still
described **plan-only** auto-detection — leaving the docs out of step
with the two-path hook behavior.

This PR aligns all user-facing copy and tightens the directives the
`preamble` hook injects.

## Changes

**Descriptions updated to cover both detection paths (keyword +
structured plan):**
- `src/cli/commands/init.ts` — ambient mode prompt note + `--ambient`
flag help
- `src/cli/commands/ambient.ts` — command description, usage note,
enable-success message, and a stale code comment
- `src/cli/plugins.ts` — ambient plugin description → "Keyword + plan
auto-detection"
- `README.md` — "Ambient intelligence" line now names the keyword start
words and structured plans

**Injected directives tightened (`scripts/hooks/preamble`):**
- Symmetric structure across both paths (announce briefly → invoke via
Skill tool → pass input)
- Explicit input pass-through on **both** paths (the plan path
previously never told the model to pass the plan)
- "Immediately / do not pause to ask whether to proceed" to preserve
ambient's zero-friction intent

## Notes
- The `preamble` hook is copied to `~/.devflow/scripts/` at `devflow
init` time, so the directive change takes effect after a re-init.
- The plugin README and preamble header comments were already accurate —
no change needed there.

## Verification
- `npm run build:cli` — passes
- `bash -n scripts/hooks/preamble` — syntax OK

---------

Co-authored-by: Dean Sharon <deanshrn@gmain.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant