# ADR-0018: Automatic Context Detection for Adaptive AI Prompts

## Status

✅ Accepted

## Context

omni-dev generates and improves commit messages by passing a YAML repository view
to an AI model. The YAML includes diffs, file change lists, and branch metadata,
but the AI prompt treats every commit identically: the same system prompt, the same
level of detail requested, regardless of whether the change is a one-line typo fix
or a breaking API deletion.

This produces uniformly shallow output. A routine documentation tweak receives the
same prompt treatment as a multi-file architectural refactor, so the AI either
over-explains trivial changes or under-explains significant ones.

Three approaches were evaluated:

- **Raw diff only.** Pass the diff to the AI with no additional context. The AI
  must infer the nature of the change from file paths and diff content alone. This
  is the simplest approach and requires no maintenance, but the AI has no structured
  signal about change significance, work type, or project conventions. Output quality
  is uniform and generic regardless of the change.

- **Manual context specification.** Users supply flags or annotations (e.g.,
  `--type=refactor`, `--scope=cli`, `--significance=high`) to tell the system what
  kind of change they are making. This produces accurate context but imposes friction
  on every commit. In practice, users omit the flags and fall back to the generic
  path.

- **Automatic heuristic detection.** The system inspects the repository state —
  branch names, file paths, change types, commit history — and infers structured
  context without user input. This requires maintaining heuristic rules but provides
  context on every invocation with zero user effort.

The config hierarchy that loads project-specific conventions (commit guidelines,
scopes, ecosystem defaults) is documented separately in ADR-0005. Provider-specific
prompt framing — varying how guidelines are presented based on the AI model family
— is documented in ADR-0014. This ADR covers the orthogonal concern of varying
prompt *detail level* based on detected change context.

## Decision

We will automatically detect structured context from the repository and use it to
adapt AI prompt verbosity, using heuristic analyzers organized by concern.

### Analyzer architecture

Four analyzers in `src/claude/context/` each examine one aspect of the change:

- **`BranchAnalyzer`** (`branch.rs`) — Parses the current branch name against
  three regex patterns (standard `type/scope/desc`, ticket-based `PROJ-123-desc`,
  user-based `user/desc`) to extract a `WorkType`, optional scope, ticket
  reference, and human-readable description. Also classifies the project's
  branching strategy (GitFlow, GitHub Flow, Conventional Commits) from the full
  branch list.

- **`ProjectDiscovery`** (`discovery.rs`) — Detects the project ecosystem from
  marker files (`Cargo.toml`, `package.json`, `go.mod`, etc.), loads
  project-specific conventions by parsing `CONTRIBUTING.md` and `README.md`, and
  merges ecosystem-appropriate default scopes. Config file resolution (walk-up
  discovery, local overrides, XDG paths) is delegated to the hierarchy defined in
  ADR-0005.

- **`FileAnalyzer`** (`files.rs`) — Classifies each changed file by purpose
  (Config, Test, Documentation, CoreLogic, Interface, Build, Tooling),
  architectural layer (Presentation, Business, Data, Infrastructure, Cross),
  change impact (Style, Additive, Modification, Breaking, Critical), and project
  significance (Routine, Important, Critical). Classification is keyword-based,
  matching against file path components and extensions.

- **`WorkPatternAnalyzer`** (`patterns.rs`) — Examines a range of commits to
  detect work patterns (Sequential, Refactoring, BugHunt, Documentation,
  Configuration) by counting keyword matches in commit messages and config-file
  touches. Also computes scope consistency (whether commits share a scope) and
  architectural impact (Minimal, Moderate, Significant, Breaking).

### Composition into `CommitContext`

Each analyzer populates one field of `CommitContext` (`src/data/context.rs`):

- `context.project` ← `ProjectDiscovery::discover()`
- `context.branch` ← `BranchAnalyzer::analyze()`
- `context.range` ← `WorkPatternAnalyzer::analyze_commit_range()`
- `context.files` ← `FileAnalyzer::analyze_commits()`

Assembly happens in the `collect_context()` method in `twiddle` and `create_pr`.

### Adaptive verbosity

`CommitContext` exposes two methods that the prompt generator consults:

- **`is_significant_change()`** — Returns `true` if the change significance is
  Major or Critical, the architectural impact is Significant or Breaking, or any
  file has Critical significance or Breaking/Critical impact.

- **`suggested_verbosity()`** — Returns one of three levels:
  - `Concise` — single-line conventional commit (minor changes, single routine file)
  - `Detailed` — subject line plus brief body (moderate changes, multiple files,
    UI/business logic)
  - `Comprehensive` — subject line plus detailed multi-paragraph body with lists
    (significant or breaking changes)

The prompt generation functions in `src/claude/prompts.rs` use the verbosity level
to vary system prompt instructions and user prompt detail expectations.

### Integration scope

All four analyzers are wired into `twiddle` and `create_pr` via
`collect_context()`. `FileAnalyzer::analyze_commits()` deduplicates files across
commits (last status wins when a file appears in multiple commits). The `check`
command does not construct a `CommitContext` and does not call any analyzer.

## Consequences

**Positive:**

- **Output quality scales with change significance.** A breaking API change
  produces a detailed, multi-paragraph commit message while a typo fix produces a
  concise one-liner. The AI receives explicit instructions matching the change's
  actual complexity.

- **Zero user configuration.** Context is detected automatically on every
  invocation. Users do not need to supply flags, annotations, or metadata to get
  context-aware output.

- **Extensible by concern.** Adding a new dimension of context means writing a new
  analyzer that populates a new field on `CommitContext`. Existing analyzers are
  unaffected.

**Negative:**

- **Heuristic classification is approximate.** File classification relies on path
  keywords and extensions, not semantic analysis. A file at `src/data/ui_helpers.rs`
  would be classified as Data layer (matching `data` in path) rather than
  Presentation. Branch name parsing fails silently on unconventional naming
  schemes, defaulting to `WorkType::Feature`.

- **Keyword lists require ongoing maintenance.** Each analyzer contains hardcoded
  keyword and pattern lists (file extensions for config detection, commit message
  keywords for pattern detection, ecosystem marker files). These must be updated as
  new ecosystems, conventions, or file types become relevant.

- **Verbosity control is invisible.** Users see the final commit message but not
  why the system chose Concise vs. Comprehensive. There is no diagnostic output
  explaining the verbosity decision (though `twiddle` prints a context summary
  before each run).

- **`check` command lacks context analysis.** Unlike `twiddle` and `create_pr`,
  the `check` command does not construct a `CommitContext` or call any analyzer,
  so no context-driven verbosity adaptation applies.

**Neutral:**

- **No runtime cost for unused analyzers.** `CommitContext` fields that are not
  populated default to their `Default` values, which map to the least-significant
  classification (Minor, Minimal, Concise). The system degrades gracefully if an
  analyzer is not called.

- **Prompt size increases modestly.** The context-driven prompt additions (work
  type hints, scope consistency notes, verbosity instructions) add a few hundred
  tokens to the system prompt. This is well within the token budgets managed by
  ADR-0009.
