Owner decree of 2026-08-01 (AM msg 348, point 7) binds all Gemini use to
2.5, never 3.x. That message was unread in my inbox when I ran the gate
on gemini-3.1-pro-preview. Re-run on gemini-2.5-pro; section 10.1 is now
the binding review and the 3.x run is marked superseded.
The 2.5 run found a real gap the 3.x run missed entirely: cross-repo
clone credentials were never addressed. A CI job in offband-site cloning
docs/ out of two other repos needs either a deploy key rotated in three
places or a machine-user PAT with repo scope. SAFELANE section 5
prohibits reaching for a new PAT before auditing existing inventory,
after the 2026-04-25 proliferation incident, so this is governed rather
than free. Added to #491 as a blocking design item.
It also pushed harder on two owner-level decisions, surfaced rather than
silently re-prioritised: whether deferring offline in-app help is right
for a product built for no-connectivity, and whether localization should
be planned now given 18 shipped locales.
Agent: DustyRiver (session f6f6e512)
Adversarial review run per standards#145 before opening the PR. The
reviewer endorsed the wiki disqualification and did not overturn the
recommendation, but found real defects, all landing on the build phase
(#491) rather than on this decision.
Accepted:
- A central nav: block would force a second PR per page. MkDocs docs
confirm nav is optional and auto-generates from directory structure,
so the build must not use a central nav. Most valuable finding.
- Tag-versus-branch was self-contradictory: a post-merge dispatch that
rebuilds a pinned tag is a no-op.
- No pre-merge docs build, so broken links surface only after merge.
- Cross-repo relative links between app and firmware sections.
- Language URL segment must be decided before launch, or adding locales
later breaks every inbound link. This contradicted my own argument
about URL permanence.
- Clone-versus-plugin was pre-committed on thin reasoning; now decided
on evidence at build time.
- Read the Docs was genuinely unassessed. Assessed now, still not
recommended: another vendor where Cloudflare Pages already works.
Rejected, with reasons recorded:
- "RTD natively handles multirepo" is unverified; their MkDocs page does
not say it. Not propagated.
- "Flutter asset bundling unassessed" is inaccurate; it is option E and
epic #492.
- "A plain clone breaks the firmware config" overstates it.
Agent: DustyRiver (session f6f6e512)
Owner asked what happens to meshcore-firmware if the docs build runs in
meshcore-client. The original recommendation had the client repo owning
docs.offband.org, which was wrong: the hostname is org-level, and the
firmware has the stronger claim today since it has ~30 doc files and a
configured mkdocs.yml while the client has none.
Revised (new section 4.1): sources stay beside their code in each repo,
so docs still change in the same PR as the behavior they describe. One
MkDocs build aggregates both, owned by offband-site, which is neutral
and already has Cloudflare Pages working. Published as /app and
/firmware sections under one nav and one search index.
Consequence worth noting: the unified site launches with real content on
day one from the firmware docs, instead of sitting empty until client
docs are written.
Agent: DustyRiver (session f6f6e512)
Two corrections to the assessment.
1. docs.offband.org does not exist. nslookup returns NXDOMAIN and curl
cannot connect. I had recorded it as "already attached to the
offband-site Pages project" by trusting that repo's own CLAUDE.md,
CLAUDE.local.md and KNOWLEDGE-TRANSFER.md rather than testing it.
Those three files are wrong and should be fixed in offband-site.
Consequence: there is no migration conflict. The hostname is unused,
so it gets created, not moved. The plan gets simpler.
2. Option G resolved by the owner: the BookStack is OKIMesh's. A second
Offband-owned instance is rejected on cost, since BookStack supports
only MySQL 8.0+ or MariaDB 10.6+ with no SQLite or Postgres path,
plus PHP 8.2+, a webserver and Composer. Cited to BookStack's docs.
Agent: DustyRiver (session f6f6e512)
Research deliverable for the docs-home epic. Inventories every existing
Offband documentation surface, scores seven candidate homes against the
eleven criteria, and recommends in-repo markdown published as a MkDocs
Material site.
Key findings:
- GitHub Wikis are not indexed by search engines below 500 stars; this
repo has 3. Cited to GitHub's own docs. Effectively disqualifying for
end-user documentation.
- meshcore-firmware already contains a complete, never-deployed MkDocs
Material config whose exclude_docs block already solves the client's
internal-artifact problem.
- A BookStack instance already holds Offband-adjacent content; ownership
is unverified and is an open question for the owner.
No infrastructure was built or changed. Decision requested on five points
before plan/build/test children are scoped.
Agent: DustyRiver (session f6f6e512)
Replace the DM composer with an "Unblock to message" notice bar when
the contact is blocked, so a block also stops outgoing DMs (previously
only incoming DMs/adverts were suppressed). Inline unblock restores the
composer. Adds block_composerNotice l10n string and documents the
outgoing-DM rule in block-contract-as-built.md §4.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Offband rebrand renamed the Windows executable meshcore_open.exe ->
offband_meshcore.exe (verified: the #244 build produced offband_meshcore.exe).
Only the Windows distribution doc was stale; the Android package/namespace,
MethodChannel names, and macOS/iOS bundle names are deliberately still
meshcore_open (those renames are deferred per the rebrand plan).
Remove the invented whole-channel-mute (never specified; already exists in
notification settings). Repurpose §6 to the real spec: blocking a channel sender
who can't be resolved to a pubkey adds a GLOBAL name-fallback (hides them in every
channel, not one at a time), which promotes to a pubkey block once the identity is
learned via advert OR DM (§7). Single/invisible-char rename evasion explicitly out
of scope. A4/#171 closed not-planned; behavior lives in A3/#170 + A5/#172 + A7/#174.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ben's UX call: do NOT hide blocked contacts to a settings-only list. Keep them
in Contacts/Discovery with a red block icon + muted styling + inline unblock.
A 'hide blocked entirely' toggle is a post-implementation follow-on.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reply-shape [0xC2][sub][ok] (result byte, not ack/err frame); generic error
frame [0x01][0x06] is NOT 0xC2-prefixed. Overflow at MAX_BLOCKED_KEYS=32 returns
ok=0 (not error) + already-stored returns ok=1 (dedup short-circuit). BLOCK_LIST
truncation detect via START count vs key-frames -> re-request on APP_START
early-END; never derive removals from LIST. DM-drop is silent (no notif/frame) ->
no firmware block counts for UX. No unsolicited pushes. Design confirmed by
PearlMeadow; app half locked to shipped firmware, no open discrepancies.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Align to firmware PR #247 (merged): cap OFFBAND_CAP_BLOCK=0x02, FIRMWARE_VER_CODE
15, 0xC2 CMD_OFFBAND_BLOCK (ADD/REMOVE/LIST/CLEAR), MAX_BLOCKED_KEYS=32, BLOCK_LIST
streamed-dump framing (0xFF count / index / 0xFE end) + APP_START early-END.
Switch sync model to union / always-retain-local (app-local never wiped; portable
across Offband clients, local-only on non-Offband). Global (by-pubkey) app store.
Fold in channel all-matching-pubkeys rule, dual name-key index sourcing (0x8A vs
0x80), promote-and-prune age-out, gaps G1/L1/L2/L3, interop invariant.
Feature #164 / Epic A #165 / Epic B #166; firmware doc #244.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sweep user-facing docs from "MeshCore Open" to "Offband Meshcore":
README, docs/PRIVACY_POLICY, documentation/*, CONTRIBUTING, TESTFLIGHT_GUIDE.
- Prominent README attribution (fork of MeshCore Open by zjs81, MIT) + a
Credits section. LICENSE left untouched (zjs81 copyright retained).
- Removed the upstream donation block (Solana/Monero/BTC) per owner.
- Removed upstream-only pointers that would misdirect (zjs81 Obtainium badge,
meshcoreopen.org); pointed clone/issues at Strycher/meshcore-open; fixed the
stale iOS bundle id -> app.offband.meshcore.
CLAUDE.md (dev-facing instructions) intentionally left as-is.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>