fabro/lib/crates/fabro-cli/tests/it/cmd
Scott Werner accd91a0a6
Some checks are pending
Rust / Test (Linux) (push) Waiting to run
Rust / Format (push) Waiting to run
Rust / Clippy (push) Waiting to run
Rust / Generated Docs (push) Waiting to run
Rust / Test (macOS) (push) Waiting to run
Demote non-interpolating config fields to plain String (#492)
# Demote non-category leak fields to plain `String`

Second slice of the interpolation unification — the first **reducing**
PR
stacked on the foundation (#472), per the reduce-first sequencing:
narrowing
changes land before capability additions. (The other reducing slice, the
DOT
de-templating, already landed independently as #474.)

## Why

The target model gives `InterpString` to fields in five categories —
`command` / `script` / `headers` / `env` / `url` — wherever they appear.
A
handful of fields were typed `InterpString` but are *identifiers or
commit
content*, not in any category:

- `run.model.provider` / `run.model.name`
- `cli.exec.model.provider` / `cli.exec.model.name`
- `run.git.author.name` / `run.git.author.email`
- `run.scm.owner` / `run.scm.repository`

Their consumers never resolved them — they leaked raw source text via
`as_source()`. This PR demotes them to plain `String` (layer and
resolved
structs) with **no interpolation**.

## The principle: only `InterpString` fields access variables

These fields are dropped from the variable substitute pass entirely, so
both
`{{ vars.* }}` and `{{ env.* }}` are now literal text. This **removes an
incidental behavior**: run-scoped plain-`String` fields used to get
`{{ vars.* }}` substituted via the String pass (a lucky accident), while
`env` always leaked literally. Variable access becomes deliberate and
typed
rather than accidental; if any of these fields should support variables
later, that's a controlled promotion back to `InterpString`.

## Behavior changes (honest list)

- **The incidental run-scoped `{{ vars.* }}` substitution on these eight
fields stops working.** To keep the removal visible rather than silent,
a
`tracing::warn!` fires at resolve time when a demoted field still
contains
claimed template tokens (`warn_if_demoted_template`). Unclaimed `{{ ...
}}`
  text (jq programs, Go templates) never interpolated and does not warn.
- `{{ env.* }}` / `{{ secrets.* }}` / `{{ inputs.* }}` never resolved on
  these fields, so nothing else changes.

## Added in review: D11 demotions (separate commit, revertable)

The rule got refined during review: a field is `InterpString` iff it is
in one
of the five categories **and resolved at the run boundary** (the only
point
where `vars`/`secrets`/`inputs` exist — they're server state, so
connect-time
and startup-time fields can't reach them even in principle). A separate
commit
applies the clean subset so it can be cherry-picked out if we change
course:

- `cli.target.http.url` / `cli.target.unix.path` — consumed at CLI
connect
time; consumers only ever leaked raw source, so nothing working is
removed.
- `run.working_dir` — **the outlier; see the PR comment.** Its `{{
vars.* }}`
  substitution worked; demoted on the category test alone.

## What's deliberately NOT here

- The **control-plane fields** (`server.storage.root` /
`listen.unix.path` /
  S3 fields / `github.app_id/client_id/slug` / `server.api.url` /
  `server.web.url`) — untouched here, demoted in a follow-up PR.
**Resolved during review** (see the resolution comment): `InterpString`
was
  conflating the user-facing workflow language with the internal control
plane. Control-plane fields never interpolate; the few deployment knobs
that need late binding (e.g. `FABRO_WEB_URL`, whose only real usage is
the
  split-web PoC ferrying a compose env var across a file mount) become
explicit native `EnvVars` reads, and `fabro-server/src/interp.rs`
shrinks
to deletion. `slack.default_channel` stays `InterpString` (consumed with
  run context).

## Implementation notes

- Consumers move from `as_source()` to direct `String` access; the
  foundation's `#[expect(disallowed_methods, ... demotion pending ...)]`
  annotations for these fields are removed (no longer `InterpString`).
- `fabro-checkpoint`'s author plumbing and `fabro-manifest`'s scm fields
  simplify accordingly.

## Verification

- `cargo build --workspace`
- `cargo nextest run --workspace` → 6684 passed, 181 skipped
- `cargo +nightly fmt --check --all`
- `cargo +nightly clippy --workspace --all-targets -- -D warnings` →
clean

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 13:16:31 -04:00
..
approve.rs feat: Add approve/deny run controls to MCP and CLI (#400) 2026-05-25 15:49:57 -04:00
archive.rs feat: Add approve/deny run controls to MCP and CLI (#400) 2026-05-25 15:49:57 -04:00
artifact_cp.rs test(cli): trim slow integration fixture setup 2026-04-28 19:14:56 -07:00
artifact_list.rs test(cli): trim slow integration fixture setup 2026-04-28 19:14:56 -07:00
attach.rs feat(web): add server-managed Environments CRUD settings UI (#462) 2026-06-13 08:44:38 -04:00
auth.rs test(cli): tighten env-dev-token-ignore tests 2026-05-01 16:25:13 -04:00
cli_reference.rs refactor(dev): decouple CLI reference generation 2026-05-06 12:31:02 -04:00
config.rs feat: add server-owned environment store (Task 1 & 2 foundation) (#446) 2026-05-28 17:10:59 -04:00
create.rs Demote non-interpolating config fields to plain String (#492) 2026-06-16 13:16:31 -04:00
deny.rs feat: Add approve/deny run controls to MCP and CLI (#400) 2026-05-25 15:49:57 -04:00
diff.rs test(cli): prune slow integration outliers 2026-04-28 19:26:27 -07:00
discord.rs refactor(cli): deglobalize server and storage target flags 2026-04-05 16:06:42 -04:00
docs.rs refactor(cli): deglobalize server and storage target flags 2026-04-05 16:06:42 -04:00
doctor.rs refactor(auth): split credential sources and vault schemas (#306) 2026-05-18 11:07:42 -04:00
dump.rs feat: add server-owned environment store (Task 1 & 2 foundation) (#446) 2026-05-28 17:10:59 -04:00
events.rs fix: stabilize attach JSON timing snapshot (#385) 2026-05-24 13:09:09 -04:00
exec.rs feat(llm): Amazon Bedrock provider — Converse codec, SigV4 + API-key auth (#459) 2026-06-16 11:46:49 -04:00
fabro.rs Add fabro variable CLI namespace for server-managed variables (#434) 2026-05-27 13:57:25 -04:00
fork.rs refactor(runs): simplify run projection shape 2026-05-09 23:31:43 -04:00
graph.rs feat(cli): allow rendering invalid graphs 2026-05-25 10:19:32 -04:00
inspect.rs feat(web): add server-managed Environments CRUD settings UI (#462) 2026-06-13 08:44:38 -04:00
install.rs refactor: rationalize server secret scopes (vault-only for optional int… (#401) 2026-05-25 17:26:01 -04:00
json_global.rs Add fabro variable CLI namespace for server-managed variables (#434) 2026-05-27 13:57:25 -04:00
logs.rs fix(cli): preserve API error details 2026-05-06 14:03:12 -04:00
mcp.rs feat: Add approve/deny run controls to MCP and CLI (#400) 2026-05-25 15:49:57 -04:00
mod.rs Add fabro variable CLI namespace for server-managed variables (#434) 2026-05-27 13:57:25 -04:00
model.rs test(cli): stabilize model list snapshots 2026-05-25 10:20:47 -04:00
model_list.rs refactor(cli): separate local socket and storage defaults 2026-04-06 11:57:14 -04:00
model_test.rs refactor(llm): split provider identity from adapters (#280) 2026-05-16 13:13:41 -04:00
parent.rs feat(cli): wire run parent commands (#288) 2026-05-16 15:15:28 -04:00
parse.rs feat(cli): render fatal errors with miette 2026-04-24 15:35:57 -04:00
pr.rs feat(pr): support GitHub pull request associations (#270) 2026-05-16 12:47:27 -04:00
pr_close.rs refactor(pr): simplify server-side PR plumbing 2026-04-24 11:17:01 -04:00
pr_create.rs feat(pr): support GitHub pull request associations (#270) 2026-05-16 12:47:27 -04:00
pr_link.rs feat(pr): support GitHub pull request associations (#270) 2026-05-16 12:47:27 -04:00
pr_merge.rs refactor(pr): simplify server-side PR plumbing 2026-04-24 11:17:01 -04:00
pr_unlink.rs feat(pr): support GitHub pull request associations (#270) 2026-05-16 12:47:27 -04:00
pr_view.rs feat(pr): support GitHub pull request associations (#270) 2026-05-16 12:47:27 -04:00
preflight.rs Replace run-scoped sandbox config with named environments (#360) 2026-05-23 13:03:21 -04:00
provider.rs refactor(cli): deglobalize server and storage target flags 2026-04-05 16:06:42 -04:00
provider_login.rs Complete provider credential auth and scripted install 2026-04-13 09:15:45 -04:00
ps.rs fix(server): persist manifest metadata names (#302) 2026-05-18 08:31:23 -04:00
render_graph.rs fix(graph): support dotted Fabro graph attributes (#324) 2026-05-20 09:31:08 -04:00
repo.rs feat(cli): render fatal errors with miette 2026-04-24 15:35:57 -04:00
repo_deinit.rs refactor(config): move project state under .fabro 2026-04-11 12:55:46 -04:00
repo_init.rs Replace run-scoped sandbox config with named environments (#360) 2026-05-23 13:03:21 -04:00
resume.rs test(cli): prune slow integration outliers 2026-04-28 19:26:27 -07:00
rewind.rs feat(api): unify public run shape 2026-05-10 20:48:55 -04:00
rm.rs fix(cli): print full run id on rm (#315) 2026-05-20 08:24:31 -04:00
run.rs feat: add server-owned environment store (Task 1 & 2 foundation) (#446) 2026-05-28 17:10:59 -04:00
runner.rs Replace stdin JSONL control pipe with WebSocket worker control bus (#440) 2026-05-27 20:24:25 -04:00
sandbox_cp.rs Model run sandbox lifecycle explicitly (#431) 2026-05-27 12:48:56 -04:00
sandbox_preview.rs refactor(types): remove legacy run summary shape 2026-05-10 23:29:41 -04:00
sandbox_ssh.rs fix(cli): repair verification failures 2026-05-09 18:07:24 -04:00
secret.rs refactor(auth): split credential sources and vault schemas (#306) 2026-05-18 11:07:42 -04:00
secret_list.rs refactor(auth): split credential sources and vault schemas (#306) 2026-05-18 11:07:42 -04:00
secret_rm.rs refactor(cli): deglobalize server and storage target flags 2026-04-05 16:06:42 -04:00
secret_set.rs refactor(auth): split credential sources and vault schemas (#306) 2026-05-18 11:07:42 -04:00
send_analytics.rs refactor(cli): deglobalize server and storage target flags 2026-04-05 16:06:42 -04:00
send_panic.rs refactor(cli): deglobalize server and storage target flags 2026-04-05 16:06:42 -04:00
server_start.rs refactor: rationalize server secret scopes (vault-only for optional int… (#401) 2026-05-25 17:26:01 -04:00
server_status.rs refactor(server): unify daemon runtime metadata 2026-04-22 16:07:52 -04:00
server_stop.rs refactor(test): promote shared server-lifecycle test helpers into fabro-test 2026-04-19 16:43:26 -04:00
start.rs Replace run-scoped sandbox config with named environments (#360) 2026-05-23 13:03:21 -04:00
support.rs feat(web): add server-managed Environments CRUD settings UI (#462) 2026-06-13 08:44:38 -04:00
system.rs fix(system): expose unreadable run repair flow 2026-05-06 07:15:18 -04:00
system_df.rs fix(server): count whole storage tree in Fabro-managed bytes 2026-05-21 11:28:39 -04:00
system_events.rs refactor(cli): finish command context cleanup 2026-04-23 07:14:32 -04:00
system_info.rs refactor(cli): finish command context cleanup 2026-04-23 07:14:32 -04:00
system_prune.rs test(cli): trim slow integration fixture setup 2026-04-28 19:14:56 -07:00
system_repair.rs fix(runs): repair deletion of unreadable runs 2026-05-09 17:45:55 -04:00
test_panic.rs test: speed up slow default-profile tests and tighten nextest thresholds 2026-04-05 13:15:59 -04:00
top_level.rs feat(cli): show curated landing output for bare fabro 2026-04-17 08:59:03 -04:00
unarchive.rs feat: Add approve/deny run controls to MCP and CLI (#400) 2026-05-25 15:49:57 -04:00
uninstall.rs refactor(server): unify daemon runtime metadata 2026-04-22 16:07:52 -04:00
upgrade.rs feat(cli): render fatal errors with miette 2026-04-24 15:35:57 -04:00
validate.rs feat(template): resolve template error locations (#333) 2026-05-20 20:15:04 -04:00
variable.rs Add fabro variable CLI namespace for server-managed variables (#434) 2026-05-27 13:57:25 -04:00
variable_get.rs Add fabro variable CLI namespace for server-managed variables (#434) 2026-05-27 13:57:25 -04:00
variable_list.rs Add fabro variable CLI namespace for server-managed variables (#434) 2026-05-27 13:57:25 -04:00
variable_rm.rs Add fabro variable CLI namespace for server-managed variables (#434) 2026-05-27 13:57:25 -04:00
variable_set.rs Add fabro variable CLI namespace for server-managed variables (#434) 2026-05-27 13:57:25 -04:00
version.rs feat(cli): add fabro version command 2026-04-14 16:30:53 -04:00
wait.rs fix: stabilize attach JSON timing snapshot (#385) 2026-05-24 13:09:09 -04:00
worker_auth.rs refactor: rationalize server secret scopes (vault-only for optional int… (#401) 2026-05-25 17:26:01 -04:00
workflow.rs fix(workflow): ignore deprecated project directory 2026-05-09 10:55:56 -04:00
workflow_create.rs fix(workflow): ignore deprecated project directory 2026-05-09 10:55:56 -04:00
workflow_list.rs feat(cli): render fatal errors with miette 2026-04-24 15:35:57 -04:00