CLI
What a change touches, and branch review
What a change reaches, and what a branch means, without a model.
Problem. A change that looks local is not. Someone edits a shared component and three other features break. A pull request shows a pile of changed lines, not what they mean. Asking a model "what does this touch?" costs tokens and gives a different answer each time.
It already knows which feature and part every file belongs to and who imports whom. research impact computes the what it touches from that graph, and review compares two git refs against your own rules. Both are read-only, offline and repeatable.
This page is CLI only. The Git screen is in the Cockpit examples.
Do this#
1. What does changing this file touch?#
The repository ships a small fixture with a shared component used by three features:
construct research impact features/shared/components/CurrencyLabel.tsx \
--dir fixtures/impact-shared --format markdown
Trimmed output (the full report also lists every file with the reason it is included):
Impact of component:features/shared/components/CurrencyLabel.tsx: 4 feature(s) (shared, billing, checkout, reporting), 6 file(s) across 1 layer(s), depth 2; 4 warning(s); 1 rule error(s), 0 rule warning(s); every entry derived deterministically.
## Warnings
- **CROSS-FEATURE** (warning, derived): The seeds live in 1 feature(s) (shared) but the impact reaches 3 more: billing, checkout, reporting.
- **PUBLIC-API** (warning, derived): 1 implicated file(s) are re-exported from features/shared/index.ts: changing them changes feature "shared"'s public API.
- **SHARED-COMPONENT** (warning, derived): features/shared/components/CurrencyLabel.tsx is used by 3 other feature(s): billing, checkout, reporting. A change here is not feature-local.
- **SHARED-COMPONENT** (warning, derived): features/shared/index.ts is used by 3 other feature(s): billing, checkout, reporting. A change here is not feature-local.
Same input, same tree, same bytes. Running the JSON form twice and hashing it:
$ construct research impact features/shared/components/CurrencyLabel.tsx --dir fixtures/impact-shared --format json | sha256sum
d45a9f2d4cf5bb555bb19d6156475aafbec6f2747012dcfba95fb28daeed26dd -
$ construct research impact features/shared/components/CurrencyLabel.tsx --dir fixtures/impact-shared --format json | sha256sum
d45a9f2d4cf5bb555bb19d6156475aafbec6f2747012dcfba95fb28daeed26dd -
Other ways to seed the same report: a git range (--since main), a list of files (--files a,b), or the change described in English (--ticket "..."). Anything guessed from note text is marked inferred; anything reached from a unit you named is derived.
2. What does this branch actually change?#
On a branch where a page gained a fetch() call (here the shop project from the scaffold example, committed on main, with the fetch() line from that page's step 2 committed on feature/invoice-fetch):
construct review main feature/invoice-fetch --format markdown
Trimmed output (each section also carries a short "Where this comes from" note):
# PR health
1 file changed across 1 feature (billing): 1 finding (0 mechanical, 1 for a conversation).
## Declared vs actual scope (not measured)
Scope is not measured for this change.
No plan is linked. That is normal for hand-written work and outside contributions. Every other check still runs.
## Unexplained changes
Nothing to compare: the changed files form no connected group, so none can be singled out.
## Rule regressions
1 new rule violation on this change (5 already there, not counted).
- **conversation** [error] PAGE-004 is newly violated in features/billing/pages/InvoicePage.tsx — Page calls fetch().
## Public surface
No public exports changed.
## What the flow now does
No workflow files changed, so the flows behave as before.
Rule regressions counts only violations that are new on the head branch: the 5 that were already there are a number, never blamed on this change. Findings are split into those a Construct block can fix mechanically and those that need a human decision; the two are never mixed. Pass --plan <file> and the scope check compares what the plan declared with what the branch touched.
Nothing is written. Refs are validated, git runs from temporary detached checkouts that are removed afterwards, and your working tree, index and branches are unchanged after the run.
You get#
| You get | Evidence above |
|---|---|
| A what it touches without asking a model | every entry derived deterministically |
| The same answer every time | identical sha256 on two runs |
| Review that knows your rules | 1 new rule violation ... (5 already there, not counted) |
| No side effects | read-only by construction |
Why it matters#
You know what a change reaches, and what a branch means, before you approve it, and the answer is the same every time.
Checked against commit a33b5fa on 2026-09-24.