feat: simplify ambient mode to plan detection + command awareness#227
Conversation
Replace 4-layer classification pipeline (~950 lines removed) with: - preamble hook: deterministic plan detection (## Goal/Steps/Files markers) - shared/rules/commands.md: passive command awareness for all sessions Removes router skill, 7 triage skills, 7 guided skills, and session-start-classification hook. addAmbientHook/removeAmbientHook are now async (write/delete commands rule to disk). Updates all callers (init.ts, uninstall.ts), registries (plugin.json, plugins.ts), tests, and reference documentation. applies ADR-001
… LEGACY_HOOK_FILES for disk cleanup - Update skill count 66->51, rule count 12->13 in CLAUDE.md and file-organization.md - Include unstaged Coder simplifications (hasAmbientHook, dead helpers removal)
src/cli/commands/ambient.ts:26 — Dual-ownership of commands rule content (90% confidence)The Fix: Read the rule content from the shared source at build time instead of embedding as a constant, OR remove |
src/cli/commands/ambient.ts:95 — addAmbientHook mixes I/O with JSON transformation (85% confidence)This function now performs filesystem operations ( Fix: Extract rule file management into a separate function that callers invoke explicitly: const updated = addAmbientHook(settingsJson, devflowDir); // pure JSON
await writeCommandsRule(); // explicit side effect |
src/cli/commands/ambient.ts:141 — removeAmbientHook drops stale hook cleanup (92% confidence - BLOCKING)Line 145 calls Fix: Capture and check both: const removedClassification = filterHookEntries(settings, 'SessionStart', isClassification);
if (!removedPrompt && !removedClassification) return settingsJson; |
src/cli/commands/ambient.ts:148 — Error swallowing in removeAmbientHook (82% confidence)The catch block swallows ALL fs.unlink errors, not just ENOENT. Permission errors are hidden, leaving stale rule files active while the user believes ambient mode is disabled. Fix: Only swallow ENOENT: try {
await fs.unlink(COMMANDS_RULE_PATH);
} catch (err: unknown) {
if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {
throw err;
}
} |
src/cli/plugins.ts — LEGACY_SKILL_NAMES missing namespaced entries (95% confidence - BLOCKING)17 skill directories were deleted, including 15 with Add to LEGACY_SKILL_NAMES: // v2.x ambient simplification: deleted router, triage, and guided skills
'devflow:router',
'devflow:implement:triage', 'devflow:implement:guided',
'devflow:debug:triage', 'devflow:debug:guided',
'devflow:explore:triage', 'devflow:explore:guided',
'devflow:plan:triage', 'devflow:plan:guided',
'devflow:review:triage', 'devflow:review:guided',
'devflow:research:triage', 'devflow:research:guided',
'devflow:release:triage', 'devflow:release:guided', |
shared/rules/commands.md:24 — False documentation claim (92% confidence)The file claims detection fires only on "the first message in a session", but Fix: Change "When the first message in a session is..." to "When a prompt is..." |
tests/ambient.test.ts:17-140 — Unit tests write real files (90% confidence - BLOCKING)
Fix: Mock filesystem operations: beforeEach(() => {
vi.spyOn(fs, 'mkdir').mockResolvedValue(undefined);
vi.spyOn(fs, 'writeFile').mockResolvedValue();
vi.spyOn(fs, 'unlink').mockResolvedValue();
});
afterEach(() => {
vi.restoreAllMocks();
}); |
PR #227 Review SummaryReview Timestamp: 2026-05-25_2233 Lower-Confidence Issues (60-79%) — Summary Only
RecommendationCHANGES_REQUESTED — Fix the 7 blocking issues (marked above) before merge. The PR achieves a significant and well-motivated architectural simplification, but the dual-source rule content, function side-effect mixing, stale hook cleanup bug, and missing legacy cleanup entries must be resolved for production quality. Review conducted by devflow:git agent with 90% minimum inline comment confidence threshold. See .devflow/docs/reviews/feat-ambient-mode/2026-05-25_2233/ for full detail. |
…arification - commands.md / ambient.ts: "first message in a session" was wrong — the preamble hook fires on every prompt, not just the first. Changed to "When a prompt is a structured implementation plan" to match CLAUDE.md and actual hook behavior. - README.md: update rule count from 12 to 13 to reflect the addition of commands.md. - plugins/devflow-ambient/README.md: plan detection wording aligned with the above; Skills section now clarifies that only implement:orch is auto-triggered by plan detection — the other 8 orch skills are invoked via explicit slash commands. Co-Authored-By: Claude <noreply@anthropic.com>
…narrow ENOENT catch, add legacy prefixed skill names - Extract installCommandsRule() and removeCommandsRule() as standalone exported async functions, keeping addAmbientHook/removeAmbientHook as the public API (SRP: rule file I/O isolated and independently testable) - Fix removeAmbientHook discarding filterHookEntries return value for SessionStart classification cleanup — stale-only configs now serialize correctly and the idempotency guard checks both removals - Narrow catch block in removeCommandsRule to ENOENT only; EACCES and other permission errors now propagate instead of being silently eaten - Add 15 devflow:-prefixed triage/guided/router skill names to LEGACY_SKILL_NAMES so existing user installs are cleaned up on next devflow init Co-Authored-By: Claude <noreply@anthropic.com>
- Stub fs.mkdir/writeFile/unlink in addAmbientHook, removeAmbientHook, and hasAmbientHook describe blocks so unit tests no longer write to or delete ~/.claude/rules/devflow/commands.md during test runs - Add 'removes stale classification hook when no UserPromptSubmit hooks exist' to cover the removedClassification-only return path in removeAmbientHook - Add 'matches shared/rules/commands.md source file' sync guard to the COMMANDS_RULE_CONTENT block to catch drift between the two sources Co-Authored-By: Claude <noreply@anthropic.com>
Simplify the guard condition in filterHookEntries — settings.hooks is guaranteed to exist at that point in the function (checked in line 60). Remove unused COMMANDS_RULE_PATH export from test imports. Co-Authored-By: Claude <noreply@anthropic.com>
Code Review — High-Confidence Findings (≥80%)Inline Comments Posted BelowSummary: 4 high-confidence issues identified:
All findings are detailed as inline comments on the affected lines. Pre-existing issues are marked as such; the testing gap is a blocking issue for this PR. |
Inline Comments: High-Confidence Findings (≥80%)Below are the high-confidence blocking and should-fix issues identified in the review: 1. Testing Gap (BLOCKING) - src/cli/commands/ambient.ts:93-109Missing direct tests for extracted helper functions (Confidence: 82%) The new exported functions
Suggestion: Add describe blocks with direct mocks for each helper. 2. Security (Should-Fix) - src/cli/commands/ambient.ts:217Broad catch swallows all errors in settings.json read (Confidence: 82%, Pre-existing) The This mirrors the issue you correctly fixed in 3. Security (Should-Fix) - src/cli/commands/ambient.ts:244Broad catch at JSON.parse (Confidence: 80%, Pre-existing) The Suggestion: Add a comment explaining the fallback is safe, or narrow to specific error types. 4. Architecture (Should-Fix) - src/cli/commands/ambient.ts:26-52Dual-source content duplication (Confidence: 82%) The The sync test is a good stopgap, but architectural direction should be single-source. Consider a build-time approach or runtime file read. Summary
Recommendation: Address the test gap before merge. The others improve the codebase. Review completed by devflow:git — High-confidence findings (≥80%) only |
…er tests - Narrow settings.json read catch to ENOENT only (was silently swallowing EACCES and other errors, risking config overwrite on permission failure) - Use getDevFlowDirectory() as primary devflowDir source instead of Stop hook path heuristic; keep hook-path inference as fallback for legacy installs only; log unexpected JSON.parse errors instead of swallowing them silently - Add direct unit tests for installCommandsRule (mkdir+writeFile path) and removeCommandsRule (ENOENT swallowed, non-ENOENT re-thrown) Co-Authored-By: Claude <noreply@anthropic.com>
…LL_NAMES by era - Replace sequential fs.rm() loop with Promise.allSettled() so all 224+ legacy skill deletions run concurrently rather than serially; reduces cleanup latency on slow/network filesystems - Split flat LEGACY_SKILL_NAMES array into three era-scoped sub-arrays (LEGACY_SKILLS_PRE_V1, LEGACY_SKILLS_V2, LEGACY_SKILLS_V2X) composed via spread; makes it easy to scan for duplicates and understand the evolution of the list without changing observable behaviour Co-Authored-By: Claude <noreply@anthropic.com>
…all 9 :orch variant skills (debug, explore, implement, pipeline, plan, release, research, resolve, review) as part of simplifying ambient mode to plan detection + command awareness. These orchestration skills duplicated logic already present in commands. - Delete shared/skills/*:orch/ (9 skills, ~1775 lines removed) - Remove :orch refs from plugin manifests (ambient, release, research) - Add devflow:-prefixed orch names to LEGACY_SKILL_NAMES for cleanup - Remove SHADOW_RENAMES entries for deleted orch skills - Update skill count 51->42 in CLAUDE.md and file-organization.md - Update skill-catalog.md: orch->command terminology - Update skills-architecture.md: remove orchestration tier - Update commands (debug, implement, release) with enhancements - Update tests: remove orch-dependent assertions, fix test data - Fix stale comment in decisions-citation.test.ts
…ion Remove stale orch skill references and old QUICK/GUIDED/ORCHESTRATED terminology from docs that were missed in the main refactor commit.
Summary
Implements ambient mode for Devflow — a zero-overhead session enhancement system with plan auto-detection and command awareness. Ambient mode consists of two independent, toggleable components:
## Goal,## Steps,## Files) and emits a directive to invokedevflow:implementvia the Skill tool.~/.claude/rules/devflow/commands.mddocuments available/devflow:<name>commands and the auto-execution trigger.Key Features
devflow ambient --enable/--disableordevflow initImplementation Details
features.ambient: booleanpreamblehook for plan detectionambient.tscommand (not through rules plugin system)Testing
Added comprehensive tests covering:
Closes #220
Co-Authored-By: Claude noreply@anthropic.com