Skip to content

modem-stack: Phase-B adoption docs sweep + POLICY amendment + v1.0.0 version bump - #10

Merged
andrescera merged 12 commits into
mainfrom
feat/phase-b-adoption
Aug 17, 2026
Merged

modem-stack: Phase-B adoption docs sweep + POLICY amendment + v1.0.0 version bump#10
andrescera merged 12 commits into
mainfrom
feat/phase-b-adoption

Conversation

@andrescera

@andrescera andrescera commented Aug 16, 2026

Copy link
Copy Markdown
Member

What

Closes out modem-stack's Wave 0+1 (todos 1-10, already merged onto this branch) with the integration housekeeping: doc sweep, the POLICY.md Phase-A→Phase-B scope amendment, and the 1.0.0 version bump for both workspace packages. No source/behavior changes — this PR is docs + one version-bump commit.

  • AGENTS.md / README.md: document the uhubctl PowerHook (recovery-ladder rung 4, control/src/backend/uhubctl-power-hook.ts), the hil-cycle HIL harness (bench runbook RB-10), the full RB-9..RB-17 bench-runbook ladder, and add the docs/ESIM-DECISION.md pointer (eSIM is investigate-only, implementation deferred).
  • POLICY.md §4: amended from a blanket "Phase A only, no CeraUI/image/apt integration" statement to an adoption-versioned one — integration is authorized starting at the v1.0.0 tag, not before, while §1-3 (no-fork gate, upstream-first) remain permanently binding. The historical fact that every release through v0.2.0 was Phase-A-only is preserved, not scrubbed. README.md and packaging/README.md carry the same amendment so no stale "Phase A: no integration" claim survives outside POLICY.md's own record of it.
  • control/package.json (@ceralive/modem-control) and cli/package.json (modem-control-cli): 0.2.01.0.0, the version POLICY.md §4 and docs/VERSIONING.md reserve for Phase-B adoption.

No tag is cut in this PR. v1.0.0 is released later (a separate workflow_dispatch on release.yml), once CeraUI's and image-building-pipeline's own Phase-B waves are also ready to consume it.

Why

This is the last modem-stack todo in the current effort. The repo's docs/VERSIONING.md already reserved 1.0.0 for "Phase-B adoption"; this PR is what actually enacts that reservation in the version files and in the policy text that currently forbids any downstream integration outright. Bumping now (rather than at tag time) means the tag, when cut, releases exactly what this PR's gates already proved green — no second PR, no last-minute version-file diff at release time.

How to verify

  • Pre-check (done before touching any version file): read .github/workflows/{ci-bun.yml,ci-packaging.yml,release.yml} and packaging/ci/*.sh. Confirmed no lane asserts control/package.json's version against an existing tag/npm/deb state on a non-tag (PR/push) build — ci-bun.yml only lints/typechecks/tests; ci-packaging.yml's contract.sh never reads control/package.json (only the four packaging debian/changelog files); the one version-vs-tag assertion (release.yml's publish-npm job) only runs on manual workflow_dispatch with an explicit tag input, unreachable from this PR.
  • bun install --frozen-lockfile → exit 0.
  • git diff --exit-code -- bun.lock → exit 0 (zero drift; workspace members are referenced by name, not version, in the lockfile's resolution table).
  • bunx tsc --noEmit → exit 0.
  • bunx biome check . → exit 0 (171 files).
  • dbus-run-session -- bun test → 396 pass / 0 fail across 50 files.
  • bash packaging/ci/contract.sh → PASS (scaffold, tag-guard contract, dpkg tilde-ordering proofs all green; dch absent in this sandbox, which the script itself detects and documents rather than failing).
  • Stale-version sweep: no surviving bare 0.2.0 self-reference in cli/. The 0.2.0 mentions remaining in docs/BENCH.md/docs/VERSIONING.md are accurate as-is — v0.2.0 really is the latest released tag until v1.0.0 is actually cut (a later step), so those are correctly-retained current-state text, not stale claims.

Risks

  • Not run in this PR: packaging/ci/{build-bookworm.sh,test-package-contract.sh,daemon-smoke.sh} — these build real .debs in a debian:bookworm container and need a working Docker daemon; this sandbox's Docker context is Docker Desktop, which this stack's own tooling refuses as a runner daemon (same known limitation recorded for image-building-pipeline). This is not a gap in this PR's own gate: those three scripts are release.yml-only (tag-triggered), not part of ci-packaging.yml's PR lane, so nothing in this diff exercises them.
  • bun.lock has no diff to commit — bumping a workspace member's own version doesn't touch its resolution-table entry (verified, not assumed).
  • The POLICY.md amendment lifts a standing prohibition but authorizes nothing on its own: every actual integration (CeraUI, image-building-pipeline, apt-worker) still needs its own reviewed PR in the receiving repo, gated on this repo's v1.0.0 tag existing.

Update — three further commits on this branch

The branch advanced past the version bump before merge. The PR now carries real source
changes in addition to the docs/policy/version work described above, so the "docs +
one version-bump commit" framing at the top applies only to the original three commits.

  • 9b9184b feat(usage): setUsagePolicy write surface — the WRITE half of the
    data-usage surface (control/src/backend/usage/policy-write.ts + policy-store.ts).
    It persists a slot's cycle day and advisory threshold to a local 0600 policy file
    and, when a live UsageSampler is supplied, applies them in the same call. It writes a
    local file and never the modem, because ModemManager exposes no data-usage API at all:
    verified against a live MM 1.24.2 that the only Setup/threshold surface on the object
    is Modem.Signal.Setup (rssi-threshold / error-rate-threshold — radio quality, not
    bytes), and the only byte counters are the per-bearer read-only Stats, which reset on
    every connection and so cannot carry a monthly cycle. Typed results rather than throws
    (called from an RPC boundary), tri-state fields (undefined leaves alone, null
    clears), order is load → validate → persist → apply, and an applied policy outranks a
    later observation carrying the old one for the process lifetime.
  • 4d53b09, eb71039 docs(fm350) — record the real FM350-GL observed on USB
    (Citation 6) and close the adapter-mediated decision stop in docs/FM350-DECISION.md.
    Documentation only; the modem stays documented-deferred, not supported.

Verification on the merged head (eb71039)

  • bun install --frozen-lockfile → exit 0, bun run lint (Biome, 175 files) → exit 0,
    bun run typecheck (tsc --noEmit, strict + exactOptionalPropertyTypes) → exit 0.
  • bun test448 pass / 0 fail, 9274 expect() calls across 52 files.
  • Both PR checks green pinned to this SHA: Lint, typecheck, test (control + cli) and
    Packaging contract (bookworm).
  • npm pack ./control --dry-run@ceralive/modem-control@1.0.0, 121 files — the
    exact tarball CeraUI's consumer-side skew test was proven against before publish.

The .deb-building lanes remain release.yml-only (tag-triggered) and are unchanged by
these commits; they run for real when v1.0.0 is dispatched.

PR #6 (actions/setup-qemu v3->v4) squash-merged and rebased in. PR #9's npm group (Biome 2.5.4->2.5.5 + TypeScript 5.9.3->7.0.2) closed: the TS major bump is forbidden by policy, so only the Biome patch bump is taken here; Dependabot re-raises TypeScript standalone if it clears the existing major-version ignore rule in .github/dependabot.yml (already present, verified unchanged).
…th, transfer impossibility, validation checklist)
Document the uhubctl PowerHook (recovery-ladder rung 4), the hil-cycle HIL harness, the full RB-9..RB-17 bench-runbook ladder, and the eSIM investigate-only decision doc in AGENTS.md/README.md. Amend POLICY.md §4 so the Phase-A scope boundary reads as adoption-versioned: integration into CeraUI/device-image/apt is authorized starting at the v1.0.0 tag rather than blanket-forbidden, while preserving the accurate historical record that every release through v0.2.0 was Phase-A-only. Mirror the same amendment in README.md and packaging/README.md so no stale 'Phase A: no integration' claim survives outside POLICY.md's historical section.
… gate)

Bumps @ceralive/modem-control (control/package.json) and modem-control-cli (cli/package.json) from 0.2.0 to 1.0.0, the version POLICY.md §4 and docs/VERSIONING.md reserve for Phase-B adoption. This is the version bump only — no tag is cut here (release is a separate, later step: workflow_dispatch on release.yml with tag v1.0.0).

Pre-checked that no CI lane couples control/package.json's version to an existing tag/npm state on a non-tag build: ci-bun.yml only lints/typechecks/tests; ci-packaging.yml's contract.sh never reads control/package.json (it only handles the four packaging/ debian/changelog files via read-pin.sh); release.yml's version-vs-tag assertion lives in publish-npm, which only runs on workflow_dispatch with an explicit tag input and is not reachable from a PR or a push to this branch. bun install produced zero bun.lock drift (workspace members are referenced by name, not by version, in the lockfile's resolution table) — bun install --frozen-lockfile and git diff --exit-code -- bun.lock both exit 0.
…h-A HARD STOP

An RB-16 re-run on bench ceralive2 found a physically connected Fibocom
FM350-GL enumerating over USB as 0e8d:7127, bound by rndis_host + option
(not the cdc_mbim the Branch-A template predicted, and not the documented
PCIe mtk_t7xx path — the PCI bus still shows nothing). ModemManager 1.24.2
claims it via the generic fallback plugin as Modem/4, state failed /
sim-missing.

This is the decision record's own branch-1 contrary-evidence HARD STOP, so
this change records evidence and nothing else: Branch-A steps 1-3 only. No
classifier entry, branch, type, or fixture is added; the three-gate ledger
table is left verbatim; the support matrix is untouched. 0e8d matches none
of the previously considered identities (PCI 14c3, fibocom-USB 2cb7/1782/
1508) — hwdb resolves it to MediaTek's USB vendor id.

Also noted: RB-16's literal candidate list (0e8d:7126|14c3:4d75) reports
"not connected" against this board. Widening it is deferred to the same
human decision that governs the classifier question.
@andrescera
andrescera merged commit 9af48e8 into main Aug 17, 2026
2 checks passed
@andrescera
andrescera deleted the feat/phase-b-adoption branch August 19, 2026 13:13
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