@@ -17,7 +17,8 @@ bos_build/
1717 batch-apply, features.yaml IO (interactive apply/sync
1818 lives in the Go tool: tools/patch, `bpatch`)
1919 products/ one package per product: define() call + server bundles
20- profiles/ saved switch sets for CI (flat yaml, no module lists)
20+ profiles/ saved switch sets (flat yaml; a local profile may opt into
21+ an explicit modules: list — shipped profiles never do)
2122 config/ data: gn flags, resource yamls, appcast templates, offset
2223```
2324
@@ -52,6 +53,53 @@ browseros build --profile nightly-ci --arch x64
5253browseros build --modules clean,compile,sign_macos --product browseros
5354```
5455
56+ ### Seeing and tweaking a plan
57+
58+ The composed plan is always a projection of ` plan() ` — generated, never
59+ hand-copied, so it can't drift:
60+
61+ ``` bash
62+ # Print the composed steps + required env vars and exit
63+ # (works without a chromium checkout)
64+ browseros build --preset release --show-plan
65+
66+ # Comment out steps, as an operation: subtract from the composed plan
67+ browseros build --preset release --skip upload,series_patches
68+
69+ # Resume the tail after a failure without recompiling
70+ browseros build --preset release --from sign_macos
71+ ```
72+
73+ - ` --skip ` (and a ` skip: ` list in profiles) subtracts ** after**
74+ composition — it never re-triggers composition rules. CLI ` --skip `
75+ and profile ` skip: ` union. Unknown step names fail loudly; a valid
76+ step absent from this plan is a no-op, so a saved ` skip: ` keeps
77+ working as presets evolve — subtraction from the canonical plan,
78+ never a copy of it.
79+ - ` --from ` resumes the composed (post-skip) run timeline at a step:
80+ earlier runs are dropped, the first run containing the step is
81+ sliced, later runs stay whole. A failed universal merge resumes with
82+ just ` --arch universal --from merge_universal ` — no recompiles.
83+ CLI-only: resume is a one-off, so there is no ` from: ` profile key.
84+
85+ ### Modules profiles — "you own this list now"
86+
87+ For the rare run that genuinely wants an arbitrary sequence, a profile
88+ may carry ` modules: ` as an explicit opt-in — a local, commentable file
89+ that bypasses the planner entirely:
90+
91+ ``` yaml
92+ # my-tail.yaml (local only — never shipped)
93+ modules : [compile, sign_macos, package_macos]
94+ build_type : release # only valid with modules:; defaults to debug
95+ arch : arm64 # single arch only
96+ ` ` `
97+
98+ Planner-owned keys (` preset`, `clean`, `provision`, `download`, `sign`,
99+ ` upload` , `skip`) and the `--skip`/`--from` flags are rejected alongside
100+ ` modules:` — you own the list, edit it directly. Shipped profiles stay
101+ switch-based (drift-tested).
102+
55103# # Remote / ephemeral runners
56104
57105A fresh machine needs nothing outside this package :
0 commit comments