Skip to content

Rebase rebuild onto main - #172

Closed
nofuturekid wants to merge 27 commits into
mainfrom
rebase/rebuild-onto-main
Closed

nofuturekid wants to merge 27 commits into
mainfrom
rebase/rebuild-onto-main

Conversation

@nofuturekid

Copy link
Copy Markdown
Collaborator

Rebases rebuild onto main (picks up the changelog job from #150); it is landed by a force-with-lease push of this head to rebuild, not merged.

nofuturekid and others added 27 commits November 13, 2026 17:25
Applies the design decisions of 2026-11-12: typed envelopes with a
generic path-keyed payload, four crates, a path-keyed trait Camera with
an id-free daemon, pending values with settle bounds, a sysfs scan,
unsupported devices that receive nothing, per-model send tables, fake
models of two shapes, and a groundwork stage released from main.

Adds the onboarding procedure, the full 0.13.2 parity table with named
exceptions, the Tiny 2 Lite fields without backing and their fate, the
stage plan with acceptance criteria, the camera-only questions, and a
table of every change from revision 1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One row per leaf of spec 4.3 and per action of spec 4.4, with the
paths, values and actions of revision 2. Each row gives the write, the
readback, the evidence as a level with an opaque key, the spec 9.3 row,
the asleep behaviour and settle_ms. References go to spec sections.

Rows for dropped functions are gone (gamma, gimbal.step, image.reset,
device.rename, gimbal.center), as are the review findings of revision 1.
Citations of private notes are replaced by capture keys, measurement
dates and public issues.

A closing section lists where the recorded evidence differs from spec
9.3 and 8.8, for the spec editor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Apply the findings of the two walk-throughs and the coverage check to
the 1.0 design spec and the Tiny 2 Lite field ledger: owner route and
custody, unsupported-device errors and CLI error codes, hand-over
events and rev, hello deadline, identity attempts while asleep, the
restart reply, levels per value and bound, the check script's lag and
asleep rows, the process after 1.0, and the table of fields without
backing brought in line with the ledger. Public text reworded where it
went beyond the evidence policy. New choices are rows 68-81 of the
changes table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Close the seven gaps of the second paper walk-through: the poll rate
for readbacks the vendor app never polls, destructive actions in
onboarding step 7, the end of an identity series, the level of the
on-air probe, reads at wake and slot actions on an unread list, the
worker's end at unplug and after a restart frame, and the rev of a
re-added port: entry. Rows 82-87 of the changes table record them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Eight pull requests into rebuild: guards in the 0.13 layout (byte guard, CLI help guard,
package contents check, test-name list, move check), the cargo workspace, three parallel
moves into family, transport and models/tiny2lite, the camera.rs split, the final module
paths, and one mutation pass. No behaviour change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Task 1 goes to main, so that a later fix re-records the fixtures in the 0.13 layout; the
camera-free fixes of spec 3.2 are listed with their issues, and the camera.rs split waits for
the ones that touch camera.rs. Rebasing rebuild needs a decision on who force-pushes (P4).
The strip check now fails on an unstripped binary and runs on every package in CI; the gate's
shellcheck covers only the new scripts; the split scripts are committed and their output is
reproduced in review (G6b), because the move check cannot see an order change; the mutation
pass skips the byte guard; Task 2 also compares the feature tree. Decision 4 says that
legacy/full_status.rs holds carried read logic that track A ports.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A byte guard records every frame and short command the builders emit for a fixed list of
calls, a CLI guard records the help text of every subcommand, and the release dry run lists
the files of every package. The workspace move must leave all three unchanged.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Taken from the package-contents artifact of the release dry run of this pull request: the
files of the deb, rpm, Arch and tarball packages for both architectures.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The library modules move to crates/obsbot-device, models.rs as registry.rs, and the 0.13 CLI
and daemon to crates/obsbot4linux, which keeps the package name, the binary and the package
metadata. Version, rust-version and licence come from [workspace.package]. No behaviour change.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
frame.rs and streaming.rs move unchanged; lib.rs keeps their old paths as re-exports until
the final path change of the groundwork stage.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The device, its ioctls and the extension-unit access move to transport/uvc.rs; finding the
camera (by-id links, card name) moves to enumeration.rs with its test. Every block is copied
unchanged. lib.rs keeps the old device path as a re-export until the final path change.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
commands.rs, presets.rs and status.rs move unchanged, with their tests; lib.rs keeps their old
paths as re-exports until the final path change of the groundwork stage.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… status

The exchange with the extension unit (short and framed writes, answer polling, the sequence
counter) moves to family/exchange.rs; the Tiny 2 Lite reads and writes stay as
models/tiny2lite/camera.rs; the 0.13 status shape, its capability list and the remembered
pose move to legacy, with state.rs. Every block is copied unchanged by
scripts/groundwork/split-camera.py (anchors matched the file on rebuild as it is); items
another file now uses become pub(crate).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Every use line and the two module paths in code name the modules where they live now;
lib.rs declares only the final modules. No behaviour change.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Section 2 now states the rule once: a request sends the frames of the
setting or action it names, nothing before them and nothing after
them. Two kinds of frames belong to a request: the frames the camera's
protocol defines for that one operation, and the stop of a continuing
action nobody can end any more. Clients chain no second request.

The switch to the static tracking mode that gimbal.move and gimbal.turn
carried over from 0.13 is gone. The moves leave tracking.mode alone,
touch no group, and are not refused while the tracking is on; what the
camera does with a manual move while it tracks is the new camera item
CAM-34. Migration notes, the CLI and the widget say that a client that
wants the tracking off sends tracking.mode=static itself. Section 15.1
records the change after approval (row 88).

The field ledger drops the static short command from both move rows.
The W0 plan follows: fake-a only moves, touches nothing for a move, and
the test that pinned the switch is replaced by one that pins one
operation and an unchanged tracking mode. The plan's code was extracted
and rebuilt (fmt, clippy -D warnings, every test); the regenerated
description files and schema did not change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The daemon no longer stops a turn when the camera falls asleep or a
keep:true turn at shutdown; the only stop it sends is the end the
request set (a turn without keep:true lasts as long as its
connection). Section 2 names that end, the unit-keeping yaw encoding
of gimbal.turn and the preset rewind exception; 3.2 and track A drop
the carried tracking switch; W3 drops the README lines about it;
tracks B, C and D get checks for the one-request rule; CAM-7 no
longer fixes its outcome; 15.1 row 88 lists every touched section and
row 89 records the stops. W0 plan: protocol-2 rule 6 no longer reads
as a camera promise; spec coverage names section 2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
preset.save without a name sends no rename frame and the daemon invents no
"Preset <slot + 1>" (0.13 did). What the camera reports as the name of an
unnamed preset is a camera item, CAM-35. A client may show its own
placeholder for an empty name as display only and never writes it to the
camera. Spec 2, 4.3, 4.4, 6.2, 9.1, 10.3, 12.2, 12.3, 14 and 15.1 (row 90),
the field ledger row of preset.save, and the W0 plan: both fakes store an
empty name for an unnamed preset (their own behaviour), and a new test pins
one act without a rename and the stored name. The plan's code was rebuilt:
fmt, clippy -D warnings and 185 tests pass; the new test fails when the
default name is put back; the generated files did not change.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Camera::answer read the device directly, so no test reached its arms. The poll is now
poll_answer, which takes the selector-2 read as a closure and the gap as an argument;
Camera::answer passes the device read and the same 50 ms gap, so what is sent and read
on the camera is unchanged. Tests script the replies: a rejected answer returns
Error::Rejected(command, code) at the first read, an empty answer returns an empty list,
a stale answer runs through all 20 reads to NoAnswer, and failed reads are polled again
until a value arrives.

Fixes #151

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The test module already gets XU_SIZE through use super::*.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
full_status_with reads the device directly, so no test reached the arm that turns a rejected
or unanswered tracking query (0x0104) into tracking: None. Tests now run it on a scripted
Device (compiled in tests only, answering xu_get, xu_set, get_ctrl and ctrl_range from a
table): a rejected tracking query returns Ok with tracking None and the other fields filled,
an answered one fills tracking, and a failed write still fails the whole read. No status code
and no byte sent to the camera changed.

Fixes #152

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Do not claim how a camera treats an unknown query; the comment now says
what the test double does (type 0x89, code -1) and why.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Camera::gimbal sent the tilt negated inline; no test covered it, so
deleting the minus would have left every test green and made
`gimbal --tilt 20` move the camera down.

The negation (with the + 0.0 that keeps -0.0 off the wire) is now
tilt_to_pitch, which gimbal calls. The bytes sent for any input are
unchanged (byte guard and command-line guard pass unchanged).

Tests: positive tilt up gives the negated value, 0 stays +0.0, None
stays None, and the converted value builds the two pose frames of
capture 18 byte for byte.

Fixes #153

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Quote $pkg in build-arch.sh (SC2086) and $b in the try and chk calls of
check-readback.sh (SC2086); name the unused retry counter `_` (SC2034).
No change in behaviour. The groundwork gate now runs shellcheck over
scripts/*.sh and scripts/groundwork/*.sh.

Fixes #154

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Precondition P5 still said the gate checks only the new scripts and that
an issue is filed on main. Issue #154 fixes the old findings on rebuild,
and the gate line covers every script in scripts/.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
One cargo-mutants 27.1.0 pass over obsbot-device (without the 0.13-only state and pose
modules) left 202 missed mutants. These tests kill the ones that sit in code without I/O or
behind the scripted device: frame length limits and the rejection layout, the pair gap, the
sequence counter, builder limits and the sign of a zero rate, preset and status decoders,
the Camera reads and checks, and how the device handles a refused ioctl.

The scripted device also records set_ctrl calls and can give a control its own range; its doc
comment now describes only what the test double does. The plan names the tilt negation by its
function tilt_to_pitch and says how the run treats cfg(test) code.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The scripted device sits behind five methods since set_ctrl was added; the module
doc said four. The plan now lists the open call-site item of tilt_to_pitch under
"After the tasks".

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@nofuturekid
nofuturekid changed the base branch from rebuild to main November 13, 2026 16:35
@nofuturekid nofuturekid reopened this Nov 13, 2026
@nofuturekid

Copy link
Copy Markdown
Collaborator Author

Landed as 37471a0 by force-with-lease push to rebuild (not merged); PR was retargeted to main only so that CI would run.

@nofuturekid
nofuturekid deleted the rebase/rebuild-onto-main branch November 13, 2026 16:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant