Commit Graph
9 Commits
Author SHA1 Message Date
huntedbytheirs 1c668c3c1e kernel, patch, doctor, config: fill in the rest of Now and Next
kernel quest reads bugzilla's REST API and picks one bug through a seeded
xorshift, so a pick is reproducible in a test and varied in a person's hands.
kernel test builds under spawn_blocking and boots under qemu with the serial
console streamed line by line, and it reports what qemu did instead of
flattening a failed boot into a success.

patch create writes a whole series when --range is given. git format-patch
does the naming and the numbering because that is already its job, the cover
letter comes from --cover-letter, and a series.toml beside the patches records
the range with both ends as hashes, the revision, the files and the blurb.
patch submit takes a directory or several files and sends them in one
git send-email invocation, and patch update re-rolls a directory through
--reroll-count, deleting the superseded revision only once the new one is
complete.

doctor runs its checks in the order a first run hits them, prints one line and
a fix hint for each, and names the first hard failure in the summary. A missing
qemu or a missing mail route warns and keeps exit 0, because --dry-run is where
the loop actually stops on a machine without an SMTP route.

~/.config/spectral/config.toml holds the tree path, the patch directory,
always-CC addresses and an identity, with the environment winning over the file
and the file over the built-in default. spectral init verifies or clones a tree
and writes it once: a second run with the same tree says so and writes nothing,
and a run that would change an existing answer is refused until --force.

tests/ grew a fixture for each of those. The harness controls PATH and git's
configuration, and its PATH can hold a git that answers send-email either way,
so a host without that support still passes rather than deciding the result.

Two review lanes ran over this work and this commit carries their fixes. A
re-roll regenerated base..HEAD, so a commit that landed after create would have
silently joined the set and been mailed: the range is recorded now and a
re-roll regenerates exactly it. A patch file that was already gone made update
fail forever while the sidecar described a revision that was not on disk: a
missing file is the state the re-roll wanted. An empty blurb aborted after the
files were written: it is checked before anything is generated. A tree that is
not a git repository was reported as a missing revision. init cloned before it
refused. The bugzilla request had no timeout, a signal-ended child printed the
bare word "signal", CommandSpawn dropped the io reason, and the printed
send-email line quoted only arguments with spaces, so --in-reply-to <id@host>
pasted as a redirection.

Checked with cargo fmt --all -- --check, cargo clippy --all-targets --locked --
-D warnings, cargo test --locked (96 passed, 4 ignored) and cargo doc --no-deps.
The four ignored tests want the host's own checkpatch, get_maintainer and
bugzilla, and all four pass when asked for.
2026-09-16 21:52:05 -04:00
huntedbytheirs b74dafb475 deps: swap scraper for serde_json, and take on toml
Quest reads bugzilla's REST API rather than its HTML, so serde_json arrives
and scraper leaves. The buglist page caps at 200 rows and would need
paginating to page through a year of bugs, and its rows are not something a
test can assert on.

toml is for the config file and for the series sidecar, and tokio gains
process and io-util for the qemu path. serde was already in the lock file as
a transitive dependency and is a direct one now.

Dependencies only, on purpose: this is the one commit a swap like this can be
reverted from without dragging code along with it. Checked with
cargo check --locked against this commit's own tree, where nothing imports
the new crates yet.
2026-09-16 21:52:05 -04:00
huntedbytheirs 97664806b7 patch: fill in the loop verbs, and test them
Every patch verb outside the series work is real. check reads the working
tree through checkpatch's stdin, which is the only way it can read one,
since --git with no revision dies; format puts --fix-inplace's output back
into the tree after setting the uncommitted change aside, and restores it
if the fix does not apply; commit and create sit on git; create writes a
mail-formatted patch, because git send-email refuses a bare diff with "No
subject line"; submit splits get_maintainer.pl's roles into To and Cc,
prints the command line it is about to run, and only sends when --dry-run
is off; update re-rolls a patch by renaming it and does nothing at the
revision it is already at.

git.rs grows the plumbing those verbs stand on: diff_unstaged,
format_patch, apply, commit, rev_parse. apply feeds the patch in on stdin,
so a fixed patch stays in memory until it is known to apply.

tests/ holds a fixture kernel tree, so the suite needs no kernel tree, no
network, and no configured git send-email. The two tests that do want the
host's own checkpatch and get_maintainer are ignored unless asked for, and
one of them earned its place immediately: checkpatch's --file means "this
argument is source code", so checking a patch with it reported a dirty
patch as clean, 8004 lines and no errors. Patchfile mode is checkpatch's
default and the path now stands alone.

patch check also takes --rev, which is how a committed range gets checked.

Checked with cargo fmt --check, cargo clippy --all-targets -- -D warnings,
cargo test, and cargo doc --no-deps.
2026-09-16 18:41:51 -04:00
huntedbytheirs 33161f2ae4 docs: add a roadmapped Far section and a ROADMAP.md
ROADMAP.md tracks the work past the scaffold: closing the loop, patch
series with cover letters, doctor, config and init, more quest sources,
more checks, review tracking, and packaging. Its Not planned section
records the refusals, so what spectral will not do is as reviewable as
what it will.

Far specifies two front ends over the same verbs: a TUI session view, and
spectral auto for the mechanical half of the loop. Both need the verbs to
exist first. The TUI's real cost is that the verbs block and a TUI cannot
block its render loop, so it needs the command modules to grow a progress
story they do not have yet.

The Not planned entry that refused a TUI outright is narrowed to a GUI or
web UI, since a TUI is now on the roadmap. Everything the TUI can do
still has to stay reachable as a typed command.

Also links the roadmap from the README's Where to pitch in section.
2026-09-14 20:49:17 -04:00
huntedbytheirs aaae6e3797 readme: update
Rewrite the README and the source comments in a plainer register.

The README had picked up the usual generated-prose tics: seventeen em
dashes, inline bold headers over every work item, signposting lines like
'the two scripts are called out because it matters', and a two-word
'Twenty of them.' dropped in for emphasis. Replaced with commas, real
section headings, and sentences that carry their own subject.

Also fixes the two rustdoc warnings cargo doc was emitting: <NAME> and
<N> in the subcommand doc comments were being parsed as unclosed HTML
tags. cargo doc is clean now.
2026-09-14 20:41:10 -04:00
huntedbytheirs dc708ebb31 docs: README aimed at kernel contributors
States the scaffold status up front, documents what each verb shells out
to and why those tools come from your tree rather than being vendored, and
ends with a map of the 20 stubs grouped by how much they unblock.
2026-09-14 20:38:20 -04:00
huntedbytheirs c25bf94c33 scaffold: CLI surface with stubbed kernel and patch verbs
Add the spectral command tree -- kernel quest/test and patch
check/format/commit/create/submit/update -- with every verb wired through
main to a todo!() body, plus the pieces they will share:

- config: resolve the kernel tree from $SPECTRAL_KERNEL, falling back to
  ~/.spectral/linux, patches under ~/.spectral/patches, and confirm a tree
  really is one before anything uses it
- git: a thin wrapper over the git binary, currently only run
- error: one thiserror enum, converted once in main
- patch/checkpatch and patch/maintainers: seams around the tree's own
  scripts/checkpatch.pl and scripts/get_maintainer.pl, so spectral never
  carries a stale copy of the kernel's rules

20 functions are todo!(); the #[allow(dead_code)] sites mark the items
that are unreachable only until their caller is written. fmt, clippy -D
warnings, and test are all clean.
2026-09-14 20:38:20 -04:00
huntedbytheirs 0ee045c71e scaffold: init project 2026-09-14 20:32:10 -04:00
huntedbytheirs 1f8b468f99 Initial commit 2026-09-14 20:28:01 -04:00