Rewatch: feature-gated source directories (#8379)
* Rewatch: feature-gated source directories
Add a `feature` tag on source entries so a package can ship optional
slices of its source tree that consumers opt into. The new top-level
`features` map declares transitive implications, and `dependencies` /
`dev-dependencies` accept an object form `{name, features}` so a
consumer can restrict which features of a dep get built.
On the CLI, `rewatch build --features=a,b` (and the same on `watch`)
restricts the current package; dependencies inherit from consumer
declarations in rescript.json (union across consumers). Omitting the
flag keeps all features active.
Filtering runs inside `packages::make` before source files are
discovered, so the watcher automatically skips disabled directories and
the existing diff-based cleanup removes orphan artifacts when a feature
is toggled off. `clean` intentionally ignores `--features` so it
always wipes the full tree.
Cycles in the `features` map are rejected at load time with a message
naming the participants. Empty `--features=` is rejected with guidance
to omit the flag instead.
Includes unit tests for parsing, closure resolution, cycle detection,
and per-package active-set computation; six bash integration tests
covering CLI restriction, transitive expansion, artifact cleanup on
toggle, cycle errors, and empty-flag rejection. Documentation in
rewatch/Features.md and a row added to
rewatch/CompilerConfigurationSpec.md.
Signed-off-by: Jaap Frolich <jaap@tella.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Jaap Frolich <jfrolich@gmail.com>
* Rewatch: skip dev-dependency feature requests in --prod
compute_active_features scanned both dependencies and dev-dependencies
on every consumer regardless of the active build mode. In --prod, a
dep reached via dependencies with a restricted feature list could still
have a shorthand dev-dependencies entry on the same consumer flip
any_all_request = true and force all features active — pulling in
feature-gated code that --prod is supposed to exclude.
Match read_dependencies's rule: dev-dependency edges only contribute
to a dep's active feature set when the consumer is local and we're not
in --prod. Regression test covers both modes.
Signed-off-by: Jaap Frolich <jaap@tella.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Jaap Frolich <jfrolich@gmail.com>
* Rewatch: honour explicit empty features list on dependencies
compute_active_features conflated "no consumer edge found" with
"consumer requested empty". A qualified dependency with
`"features": []` would land in the same state as an unreached dep
(requested set empty, no `any_all_request`) and trip the fallback that
forced all features active. That made it impossible to express an
untagged-only dependency build.
Track `saw_consumer_entry` explicitly. The all-features fallback now
fires only when no consumer edge was observed; an empty requested set
from an explicit `"features": []` is honoured as "no feature-gated
dirs". Regression test covers the explicit-empty case. Docs updated.
Signed-off-by: Jaap Frolich <jaap@tella.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Jaap Frolich <jfrolich@gmail.com>
---------
Signed-off-by: Jaap Frolich <jfrolich@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> J
Jaap Frolich committed
4f652366b16452d9d31f0ff534017bb93b161e69
Parent: 49a7238
Committed by GitHub <noreply@github.com>
on 4/22/2026, 2:03:20 PM