scan inputs and ignore rules
On this page
awa scans the worktree for two purposes: history (checkpoints, changes, diff) and run input (the files a wrapped command could read). Both honor these production defaults:
.awa/and.git/are always protected and never scanned; ordinary config cannot re-include them.- Baseline excludes (build/dependency caches such as
node_modules,target,__pycache__,.venv, and similar) apply to both history and run input. - History-only excludes (
dist,build,coverage) apply to checkpoints/diff but NOT to run input — a build or test must still see them, so they do not affect run cache keys. .awaignoreis ON by default (awa's native ignore source)..gitignoreis OFF by default. It answers "what should not be committed", not "what can affect a command", so a gitignored file is still a real run input.
Because .gitignore is off by default, awa run sees files git ignores unless
an awa rule (protected path, baseline exclude, or .awaignore) excludes them.
Which layer am I looking at
The layers apply in this order, and later ones cannot re-include what an earlier one protects:
- Protected —
.awa/and.git/. A hard boundary; no configuration overrides it. - Baseline excludes — dependency and cache directories, for both history and run input.
- History-only excludes —
dist,build,coverage. Hidden from checkpoints, changes, and diff; never hidden from run input, because a build or test must still see them. - User rules —
.awaignore, plusextra_excludesin the[scope],[history], and[run]config sections, which are additive per family.
An explicitly narrowed scope outranks excludes for the narrowed subtree: if you
ask for a specific path with scope.include or --scope, you get it. The
default scope of the whole project does not have that effect.
The built-in layers are not listed in any config file, because they are product defaults rather than project policy. To see the lists that are actually in force, including the built-ins and which layer each value came from:
awa config effective
Why .gitignore is not the input boundary
The two questions are different. .gitignore answers "what should not be
committed"; awa's run scan must answer "what can affect this command". Generated
files, local fixtures, and secrets are routinely gitignored and routinely change
what a command does, so keying on git's answer would produce false cache hits —
exactly the failure the cache is designed to avoid.
Turning .gitignore on (use_gitignore in [scope] or [run]) is therefore a
deliberate decision to stop keying on those files, not a tidiness setting.
Ignored paths are outside the evidence
An excluded path is not scanned, so it is not observed. Nothing awa records
describes it: it is absent from checkpoints, from changes and diff output, from
run input keys, and from a recorded run's before/after states. awa makes no
claim about it and cannot restore it.
That is the intended trade, but it has a consequence worth stating plainly: a change confined to ignored paths looks like "no changes" in every awa surface. When that matters — reviewing generated output, or checking what a formatter touched — either narrow the scope explicitly to include those paths, or use the project's own tooling instead of a checkpoint delta.
Effect roots vs excludes
The central run-cache decision:
- The command writes or refreshes a generated directory during the run,
and that output is disposable — it may safely be absent after a replay
→
[run].extra_excludesor.awaignore. Otherwise the self-generated output makes every run non-reusable. - The command writes output you actually need on disk afterwards
→
awa run --record. Excluding it would let a replay report success with the output missing. - The command only reads an already-produced generated directory that the
run input scan no longer sees →
[run].extra_effect_roots. Later changes to that generated state should invalidate reuse. - That directory is still visible to the input scan → configure nothing. Its contents already key the run; an effect root would add no coverage.
- The command is a deploy, migration, formatter, live probe, or otherwise
non-reusable →
awa run --record. Keep durable evidence without publishing a reusable hit.
Picking an effect-root selector (literal, never globs):
- The same directory name at any depth, typically repeated across
monorepo packages → a name:
extra_effect_roots = ["bin"]. - Exactly one location → a project-relative path:
extra_effect_roots = ["artifacts/bin"], which watches neitherother/binnorother/artifacts/bin.
Rules:
- Writing to a watched effect root during the run makes the result non-reusable.
- The two lists are separate: the watched set is the built-in effect roots
plus
extra_effect_roots. An exclude you add yourself is NOT watched, so an excluded, unwatched directory is invisible to the cache in both directions. - Excluding a path therefore weakens what
awa runcan observe, so do it intentionally. - awa will not auto-edit config to improve the cache hit rate.
Pattern semantics
.awaignore— gitignore-like: globs, a trailing slash matches a directory, a leading slash anchors to the project root, and later rules override earlier ones. It is on by default;.gitignoreis off by default.[scope].extra_excludesand[run].extra_excludes— gitignore-style patterns, additive on top of the built-in baseline excludes.[run].extra_effect_roots— literal selectors, never globs, in one of two forms. A single segment is a directory NAME matched by basename wherever it appears:"target"watches everytarget/. A slash-separated project-relative PATH matches that one location only:"artifacts/bin"watchesartifacts/binand neitherother/binnorother/artifacts/bin. Matching is case-sensitive and/is the separator on every platform. A backslash, a volume spelling, and a./..component are rejected in either form; a path is also rejected when it begins or ends with a slash, holds an empty component, or names.gitor.awa.
Use awa config effective to see the resolved effective lists and the layer
each value came from.