v0.3: Kconfig-aware configurator + downloadable defconfig fragment#2
Open
widgetii wants to merge 1 commit into
Open
v0.3: Kconfig-aware configurator + downloadable defconfig fragment#2widgetii wants to merge 1 commit into
widgetii wants to merge 1 commit into
Conversation
Builds on the build-time aggregator from v0.2 — same architecture (browser
fetches same-origin only), no new infra, no new on-firmware-gh-pages files.
Adds a real "Configure" tab that lets users tick packages to remove,
computes the cascade closure with Kconfig semantics, and exports a
defconfig fragment the user appends to their board defconfig.
Pairs with the firmware-side PR that ships kconfig-graph.<plat>.json +
kconfig-help.<plat>.json as release assets next to sizes.<plat>.json
(OpenIPC/firmware PR for the emitter). Until that lands and one nightly
cycle attaches the assets, the Configure tab stays disabled with a
tooltip — `kconfig_available_for` ends up empty and the gate at
App.tsx blocks click. By design, not a bug.
Data path
scripts/prebuild.mts now also downloads kconfig-*.json from the most
recent nightly tag once per source (graph evolves slowly; per-build
storage isn't worth the ~3 GB raw it would cost across the retention
window). Files land at:
public/data/<source>/kconfig/kconfig-graph.<platform>.json
public/data/<source>/kconfig/kconfig-help.<platform>.json
IndexFile gains a forward-compatible `kconfig_available_for?: string[]`
at the source level. Empty/absent means no graph data shipped yet;
populated means "the Configure tab works for these platforms".
IndexFile schema stays at 1 — older v0.2-era files (no field) keep
parsing without error (covered by tests/types-compat.test.ts).
Dep closure semantics
src/lib/kconfig.ts is pure. The closeDisable function:
1. Iterates to fixed point: each pass extends the disabled set with
symbols newly disable-able given the current state.
2. A symbol can be disabled only if no surviving (still-set ∧ not
in our disable set) symbol hard-selects it. If something still
selects it, the disable is "blocked" and the UI explains which
symbol is still pinning it on.
3. After the initial sweep, re-checks blocked entries: a symbol
previously blocked may unblock as its selectors fall in the
cascade.
This matches what Kconfig actually does at .config save time — telling
Kconfig "drop X" when something still selects X is a silent no-op. The
configurator surfaces the blocker so the user can choose to drop the
selector instead.
defconfigFragment renders a deterministic, sorted, known-symbol-only
set of `# BR2_PACKAGE_FOO is not set` lines — URL-injected ghost
symbols are filtered out at output time.
WhatIfPanel
Per-symbol checkbox. Status column shows kept / would-disable /
blocked badges. Pinned-by column shows the symbol chips for blocked
entries (clickable in a future iteration to jump to the blocker).
KPI summary: disabled count, blocked count, estimated rootfs savings
(real, via sizes.json's per-package bytes against the disabled
closure's package set — not the naive sum disclaimer the v0.1 stub
carried), new-headroom projection. "Download defconfig fragment"
triggers a Blob → <a download="..."> click, no server round-trip.
Help text loads lazily — the per-symbol popover opens on row label
click; missing help is non-fatal (the column just isn't expandable).
Bundle invariant extended
tests/bundle.test.ts gains the assertion that JS chunks never embed
`releases/download/...kconfig...` URLs. Same regression guard pattern
the original CORS bug catches.
Numbers
- 46 active tests (was 38): +10 kconfig.test.ts (cascade / block /
unblock / determinism), +3 types-compat.test.ts
- JS bundle: 172 KB raw / 55 KB gzipped (+6 KB vs v0.2, under the
250 KB perf budget)
- Initial launch byte budget unchanged: ~60 KB gzipped
- Per-platform kconfig graph: ~14 KB raw / ~1.8 KB gzipped
- Per-platform kconfig help: ~9 KB raw / ~3.8 KB gzipped
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Builds on v0.2's build-time aggregator — same architecture (browser fetches
same-origin only), no new infra, no new files on `OpenIPC/firmware`'s or
`OpenIPC/builder`'s gh-pages. Adds a real "Configure" tab that lets users
tick packages to remove, computes the cascade closure with Kconfig
semantics, and exports a defconfig fragment to append to a board defconfig.
Pairs with OpenIPC/firmware PR for the kconfig-graph emitter. Until
that PR lands and one nightly cycle attaches the assets to release tags,
this PR's prebuild logs "no kconfig assets found in any retained tag"
and the Configure tab stays disabled with a tooltip — `kconfig_available_for`
ends up empty and the gate at `App.tsx` blocks click. By design, not
a bug.
Data path
`scripts/prebuild.mts` now also downloads `kconfig-*.json` from the
most recent nightly tag once per source (graph evolves slowly; per-build
storage isn't worth ~3 GB raw across the retention window). Files land
at:
```/kconfig/kconfig-graph..json/kconfig/kconfig-help..json
public/data/
public/data/
```
`IndexFile` gains a forward-compatible `kconfig_available_for?: string[]`
field at the source level. Empty / absent → no graph data shipped yet;
populated → the Configure tab works for these platforms. `IndexFile.schema`
stays at 1 — older v0.2-era files (no field) keep parsing without error.
`tests/types-compat.test.ts` covers this.
Dep closure semantics
`src/lib/kconfig.ts` is pure. `closeDisable` iterates to fixed point:
symbol hard-`select`s it. If something still selects it, the disable
is blocked and the UI explains which symbol is pinning it on.
blocked may unblock as its selectors fall in the cascade.
This matches Kconfig's actual save behaviour — telling Kconfig "drop X"
when something still selects X is a silent no-op. The configurator surfaces
the blocker so the user can choose to drop the selector instead.
`defconfigFragment` renders a deterministic, sorted, known-symbol-only
set of `# BR2_PACKAGE_FOO is not set` lines. URL-injected ghost symbols
are filtered at output time.
WhatIfPanel
Bundle invariant extended
`tests/bundle.test.ts` gains the assertion that JS chunks never embed
`releases/download/...kconfig...` URLs. Same regression-guard pattern
that catches the original CORS bug class.
Numbers
Bundle still under the 250 KB perf budget.
Test plan
🤖 Generated with Claude Code