mirror of
https://github.com/bybrooklyn/openbitdo.git
synced 2026-03-19 04:12:56 -04:00
Compare commits
2 Commits
v0.0.1-rc.
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 900563addc | |||
| da09094d3e |
2
.github/ISSUE_TEMPLATE/release-blocker.yml
vendored
2
.github/ISSUE_TEMPLATE/release-blocker.yml
vendored
@@ -36,7 +36,7 @@ body:
|
||||
id: openbitdo_version
|
||||
attributes:
|
||||
label: OpenBitdo version
|
||||
placeholder: v0.0.1-rc.1
|
||||
placeholder: v0.0.1-rc.4
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
||||
4
.github/workflows/aur-publish.yml
vendored
4
.github/workflows/aur-publish.yml
vendored
@@ -4,13 +4,13 @@ on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Release tag to publish (for example: v0.0.1-rc.2)"
|
||||
description: "Release tag to publish (for example: v0.0.1-rc.4)"
|
||||
required: true
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Release tag to publish (for example: v0.0.1-rc.2)"
|
||||
description: "Release tag to publish (for example: v0.0.1-rc.4)"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
|
||||
22
.github/workflows/ci.yml
vendored
22
.github/workflows/ci.yml
vendored
@@ -30,21 +30,21 @@ jobs:
|
||||
container: archlinux:base
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install AUR packaging toolchain
|
||||
- name: Install packaging validation toolchain
|
||||
run: |
|
||||
pacman -Sy --noconfirm --needed base-devel git
|
||||
- name: Ensure package metadata has pinned checksum fields
|
||||
pacman -Sy --noconfirm --needed base-devel git jq
|
||||
- name: Validate release metadata rendering
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if grep -nE 'SKIP|:no_check' \
|
||||
packaging/aur/openbitdo-bin/PKGBUILD \
|
||||
packaging/homebrew/Formula/openbitdo.rb; then
|
||||
echo "Found placeholder checksum markers; release metadata must be pinned." >&2
|
||||
exit 1
|
||||
fi
|
||||
test -f packaging/scripts/render_release_metadata.sh
|
||||
test -f packaging/aur/openbitdo-bin/PKGBUILD.tmpl
|
||||
test -f packaging/homebrew/Formula/openbitdo.rb.tmpl
|
||||
test ! -f packaging/homebrew/Formula/openbitdo.rb
|
||||
bash packaging/scripts/test_render_release_metadata.sh
|
||||
- name: Validate Homebrew tap sync helper
|
||||
run: |
|
||||
set -euo pipefail
|
||||
bash packaging/homebrew/test_sync_tap.sh
|
||||
- name: Validate PKGBUILD and .SRCINFO
|
||||
run: |
|
||||
useradd -m builder
|
||||
@@ -53,6 +53,10 @@ jobs:
|
||||
cd '$GITHUB_WORKSPACE/packaging/aur/openbitdo-bin'; \
|
||||
makepkg --printsrcinfo > /tmp/openbitdo-bin.srcinfo; \
|
||||
diff -u .SRCINFO /tmp/openbitdo-bin.srcinfo"
|
||||
- name: Check docs consistency
|
||||
run: |
|
||||
set -euo pipefail
|
||||
bash sdk/scripts/check_docs_consistency.sh
|
||||
|
||||
tui-smoke-test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
82
.github/workflows/homebrew-publish.yml
vendored
Normal file
82
.github/workflows/homebrew-publish.yml
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
name: Homebrew Publish
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Release tag to publish (for example: v0.0.1-rc.4)"
|
||||
required: true
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Release tag to publish (for example: v0.0.1-rc.4)"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
publish-homebrew:
|
||||
if: vars.HOMEBREW_PUBLISH_ENABLED == '1'
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAG: ${{ inputs.tag }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Wait for release assets
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for attempt in $(seq 1 30); do
|
||||
if gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
|
||||
echo "release ${TAG} is available"
|
||||
exit 0
|
||||
fi
|
||||
sleep 10
|
||||
done
|
||||
echo "release ${TAG} was not found after waiting" >&2
|
||||
exit 1
|
||||
|
||||
- name: Render Homebrew formula from released assets
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p /tmp/release-input /tmp/release-metadata
|
||||
gh release download "$TAG" --repo "$GITHUB_REPOSITORY" \
|
||||
--pattern "openbitdo-${TAG}-linux-x86_64.tar.gz" \
|
||||
--pattern "openbitdo-${TAG}-linux-aarch64.tar.gz" \
|
||||
--pattern "openbitdo-${TAG}-macos-arm64.tar.gz" \
|
||||
--dir /tmp/release-input
|
||||
bash packaging/scripts/render_release_metadata.sh \
|
||||
"$TAG" \
|
||||
"$GITHUB_REPOSITORY" \
|
||||
/tmp/release-input \
|
||||
/tmp/release-metadata
|
||||
|
||||
- name: Upload rendered Homebrew formula (audit)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: homebrew-rendered-formula-${{ inputs.tag }}
|
||||
path: |
|
||||
/tmp/release-metadata/homebrew/Formula/openbitdo.rb
|
||||
/tmp/release-metadata/checksums.env
|
||||
|
||||
- name: Sync Homebrew tap
|
||||
env:
|
||||
HOMEBREW_PUBLISH_ENABLED: "1"
|
||||
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
|
||||
HOMEBREW_TAP_REPO: ${{ vars.HOMEBREW_TAP_REPO }}
|
||||
FORMULA_SOURCE: /tmp/release-metadata/homebrew/Formula/openbitdo.rb
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ -z "${HOMEBREW_TAP_TOKEN:-}" ]]; then
|
||||
echo "missing required secret: HOMEBREW_TAP_TOKEN" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z "${HOMEBREW_TAP_REPO:-}" ]]; then
|
||||
echo "missing required variable: HOMEBREW_TAP_REPO" >&2
|
||||
exit 1
|
||||
fi
|
||||
bash packaging/homebrew/sync_tap.sh
|
||||
58
.github/workflows/release.yml
vendored
58
.github/workflows/release.yml
vendored
@@ -269,61 +269,11 @@ jobs:
|
||||
|
||||
publish-homebrew:
|
||||
if: vars.HOMEBREW_PUBLISH_ENABLED == '1'
|
||||
runs-on: ubuntu-latest
|
||||
needs: publish
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Wait for release assets
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for attempt in $(seq 1 30); do
|
||||
if gh release view "${GITHUB_REF_NAME}" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
|
||||
exit 0
|
||||
fi
|
||||
sleep 10
|
||||
done
|
||||
echo "release ${GITHUB_REF_NAME} was not found after waiting" >&2
|
||||
exit 1
|
||||
|
||||
- name: Render Homebrew formula with release checksums
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p /tmp/release-input /tmp/release-metadata
|
||||
gh release download "${GITHUB_REF_NAME}" --repo "$GITHUB_REPOSITORY" \
|
||||
--pattern "openbitdo-${GITHUB_REF_NAME}-linux-x86_64.tar.gz" \
|
||||
--pattern "openbitdo-${GITHUB_REF_NAME}-linux-aarch64.tar.gz" \
|
||||
--pattern "openbitdo-${GITHUB_REF_NAME}-macos-arm64.tar.gz" \
|
||||
--dir /tmp/release-input
|
||||
bash packaging/scripts/render_release_metadata.sh \
|
||||
"${GITHUB_REF_NAME}" \
|
||||
"$GITHUB_REPOSITORY" \
|
||||
/tmp/release-input \
|
||||
/tmp/release-metadata
|
||||
|
||||
- name: Upload rendered Homebrew formula (audit)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: homebrew-rendered-formula-${{ github.ref_name }}
|
||||
path: |
|
||||
/tmp/release-metadata/homebrew/Formula/openbitdo.rb
|
||||
/tmp/release-metadata/checksums.env
|
||||
|
||||
- name: Sync Homebrew tap
|
||||
env:
|
||||
HOMEBREW_PUBLISH_ENABLED: "1"
|
||||
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
|
||||
HOMEBREW_TAP_REPO: ${{ vars.HOMEBREW_TAP_REPO }}
|
||||
FORMULA_SOURCE: /tmp/release-metadata/homebrew/Formula/openbitdo.rb
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ -z "${HOMEBREW_TAP_TOKEN:-}" ]]; then
|
||||
echo "missing required secret: HOMEBREW_TAP_TOKEN" >&2
|
||||
exit 1
|
||||
fi
|
||||
bash packaging/homebrew/sync_tap.sh
|
||||
uses: ./.github/workflows/homebrew-publish.yml
|
||||
with:
|
||||
tag: ${{ github.ref_name }}
|
||||
secrets: inherit
|
||||
|
||||
publish-aur:
|
||||
if: vars.AUR_PUBLISH_ENABLED == '1'
|
||||
|
||||
55
CHANGELOG.md
55
CHANGELOG.md
@@ -1,40 +1,41 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
All notable changes to OpenBitdo are tracked here.
|
||||
|
||||
## Unreleased
|
||||
|
||||
## v0.0.1-rc.4
|
||||
|
||||
### Changed
|
||||
- CLI contract reverted to single-command interactive launch:
|
||||
- `openbitdo [--mock]`
|
||||
- subcommand forms `openbitdo ui ...` and `openbitdo run ...` are rejected.
|
||||
- Headless automation output remains available in the `bitdo_tui` Rust API (human and line-delimited JSON records).
|
||||
- AUR packaging/publish flow now targets `openbitdo-bin` only.
|
||||
- Settings schema is now documented as v2:
|
||||
- `schema_version`
|
||||
- `advanced_mode`
|
||||
- `report_save_mode`
|
||||
- `device_filter_text`
|
||||
- `dashboard_layout_mode`
|
||||
- `last_panel_focus`
|
||||
|
||||
- Release docs are being rewritten around the `v0.0.1-rc.4` flow.
|
||||
- Homebrew publishing is being moved to a reusable workflow with the separate tap repo kept as the canonical Homebrew destination.
|
||||
- TUI copy is being expanded so first-run guidance is clearer and blocked-action reasons are easier to understand.
|
||||
- The checked-in Homebrew formula output is being removed; the template and rendered release metadata remain the source of truth.
|
||||
|
||||
## v0.0.1-rc.3
|
||||
|
||||
### Added
|
||||
|
||||
- Tag-driven GitHub prerelease assets for Linux `x86_64`, Linux `aarch64`, and macOS arm64.
|
||||
- AUR publication for `openbitdo-bin` with release-derived checksums.
|
||||
- Diagnostics screen with richer per-check detail and saved-report flow.
|
||||
|
||||
### Changed
|
||||
|
||||
- Firmware update defaults remain safe until the user explicitly acknowledges risk.
|
||||
- Temporary recommended-firmware downloads are cleaned up after success, failure, or cancellation.
|
||||
- Invalid persisted settings are surfaced as warnings instead of being silently discarded.
|
||||
|
||||
## v0.0.1-rc.1
|
||||
|
||||
### Added
|
||||
- Beginner-first `openbitdo` TUI flow with device-specific JP108 and Ultimate2 guided mapping paths.
|
||||
- About screen showing app version, git commit, build date, and runtime/target platform.
|
||||
- Release packaging scripts for Linux (`x86_64`, `aarch64`) and macOS arm64 outputs.
|
||||
- macOS arm64 unsigned/ad-hoc `.pkg` packaging to `/opt/homebrew/bin/openbitdo`.
|
||||
- AUR packaging sources for `openbitdo` and `openbitdo-bin`.
|
||||
- Homebrew formula scaffolding and deferred tap sync script.
|
||||
- Release workflow for tag-triggered GitHub pre-releases using changelog content.
|
||||
- Release metadata rendering that computes authoritative checksums from published assets for AUR/Homebrew updates.
|
||||
|
||||
### Changed
|
||||
- Project license transitioned to BSD 3-Clause.
|
||||
- CI expanded to include macOS arm64 package build validation and AUR package metadata validation.
|
||||
- Release process documentation updated for clean-tree requirements and RC gating policy.
|
||||
- Beginner-first `openbitdo` launcher and terminal dashboard.
|
||||
- Release packaging scripts for Linux and macOS artifacts.
|
||||
- Unsigned, non-notarized macOS `.pkg` output for RC distribution.
|
||||
- AUR and Homebrew release metadata rendering.
|
||||
|
||||
### Notes
|
||||
- Homebrew and AUR publication paths are automated and remain controlled by repo variables (`HOMEBREW_PUBLISH_ENABLED`, `AUR_PUBLISH_ENABLED`).
|
||||
- Hardware CI gates remain required as configured in `ci.yml`.
|
||||
|
||||
- Historical RC notes are preserved here for audit continuity.
|
||||
|
||||
69
MIGRATION.md
69
MIGRATION.md
@@ -1,46 +1,24 @@
|
||||
# OpenBitdo Migration Notes
|
||||
|
||||
## Scope
|
||||
This migration restores the single-command `openbitdo` CLI contract and removes the `ui`/`run` subcommand surface from user-facing usage.
|
||||
This file explains the current user and contributor surface after the CLI and packaging cleanup.
|
||||
|
||||
## What changed
|
||||
- `bitdoctl` was removed.
|
||||
- `openbitdo cmd ...` was removed.
|
||||
- `openbitdo` now launches interactive TUI directly (with optional `--mock`).
|
||||
- subcommand forms `openbitdo ui ...` and `openbitdo run ...` are rejected (historical).
|
||||
- headless output modes remain available through the Rust API, not the CLI.
|
||||
- Settings schema moved to v2 fields while keeping compatibility defaults for v1 files.
|
||||
## Current CLI Contract
|
||||
|
||||
## Command mapping
|
||||
| Prior command form | Current command |
|
||||
| --- | --- |
|
||||
| `cargo run -p openbitdo --` | `cargo run -p openbitdo --` |
|
||||
| `cargo run -p openbitdo -- --mock` | `cargo run -p openbitdo -- --mock` |
|
||||
| `openbitdo ui --mock` (historical) | `openbitdo --mock` |
|
||||
| `openbitdo run ...` (historical) | Not supported in CLI |
|
||||
- `openbitdo` launches the interactive dashboard.
|
||||
- `openbitdo --mock` launches the dashboard without real hardware.
|
||||
- Historical subcommand-style entry points are no longer part of the supported CLI.
|
||||
|
||||
## New usage
|
||||
From `/Users/brooklyn/data/8bitdo/cleanroom/sdk`:
|
||||
## Current Packaging Contract
|
||||
|
||||
Interactive dashboard:
|
||||
- GitHub prereleases are the canonical release source.
|
||||
- AUR publishes `openbitdo-bin`.
|
||||
- Homebrew publishes through the separate tap repo `bybrooklyn/homebrew-openbitdo`.
|
||||
- macOS artifacts remain unsigned and non-notarized until Apple credentials exist.
|
||||
|
||||
```bash
|
||||
cargo run -p openbitdo --
|
||||
cargo run -p openbitdo -- --mock
|
||||
```
|
||||
## Current Settings Contract
|
||||
|
||||
## Historical note
|
||||
The temporary subcommand surface (`openbitdo ui` / `openbitdo run`) is historical (historical) and should not be used for current workflows.
|
||||
Persisted UI state uses `schema_version = 2` with these fields:
|
||||
|
||||
## Headless library API
|
||||
Headless automation remains available to Rust callers through `bitdo_tui`:
|
||||
|
||||
```bash
|
||||
run_headless(core, RunLaunchOptions { output_mode: HeadlessOutputMode::Json, ..Default::default() })
|
||||
```
|
||||
|
||||
## Settings schema migration
|
||||
Current schema is `schema_version = 2` with fields:
|
||||
- `advanced_mode`
|
||||
- `report_save_mode`
|
||||
- `device_filter_text`
|
||||
@@ -48,10 +26,21 @@ Current schema is `schema_version = 2` with fields:
|
||||
- `last_panel_focus`
|
||||
|
||||
Compatibility behavior:
|
||||
- v1 settings files load with defaults for missing v2 fields.
|
||||
- if `advanced_mode = false`, `report_save_mode = off` is normalized to `failure_only`.
|
||||
|
||||
## CI note
|
||||
The CLI smoke coverage now validates:
|
||||
- `openbitdo --help` exposes single-command option usage.
|
||||
- `openbitdo ui ...` and `openbitdo run ...` fail as unsupported forms (historical).
|
||||
- v1 settings still load with defaults for new fields.
|
||||
- invalid settings files now raise a warning and fall back to defaults instead of being silently accepted.
|
||||
|
||||
## Current Library Contract
|
||||
|
||||
OpenBitdo keeps headless automation as a Rust API, not a public CLI surface.
|
||||
The supported entry points remain:
|
||||
|
||||
- `bitdo_tui::run_headless`
|
||||
- `bitdo_tui::RunLaunchOptions`
|
||||
- `bitdo_tui::HeadlessOutputMode`
|
||||
|
||||
## Practical Migration Guidance
|
||||
|
||||
- If you used the historical CLI subcommands, switch to `openbitdo` or `openbitdo --mock`.
|
||||
- If you need automation, call the Rust API instead of expecting a supported headless CLI.
|
||||
- If you document install paths, prefer Homebrew tap, AUR, tarball, or source build rather than old ad hoc command forms.
|
||||
|
||||
171
RC_CHECKLIST.md
171
RC_CHECKLIST.md
@@ -1,44 +1,26 @@
|
||||
# OpenBitdo RC Checklist (`v0.0.1-rc.2`)
|
||||
# OpenBitdo RC Checklist (`v0.0.1-rc.4`)
|
||||
|
||||
This checklist defines release-candidate readiness for the `v0.0.1-rc.2` public RC tag.
|
||||
This checklist defines the release-candidate gate for the current public RC tag.
|
||||
|
||||
## Candidate Policy
|
||||
- Tag format: `v*` (for this RC: `v0.0.1-rc.2`)
|
||||
## Release Policy
|
||||
|
||||
- Tag format: `v*`
|
||||
- Current RC tag: `v0.0.1-rc.4`
|
||||
- Tag source: `main` only
|
||||
- Release trigger: tag push
|
||||
- RC gate: all required CI checks + manual smoke validation
|
||||
- Public RC rule: zero open issues labeled `release-blocker`
|
||||
|
||||
## Release-Blocker Policy
|
||||
Use GitHub issue labels:
|
||||
- `release-blocker`
|
||||
- `severity:p0`
|
||||
- `severity:p1`
|
||||
- `severity:p2`
|
||||
## Required CI Checks
|
||||
|
||||
Public RC gate rule:
|
||||
- zero open issues labeled `release-blocker`
|
||||
- `guard`
|
||||
- `aur-validate`
|
||||
- `tui-smoke-test`
|
||||
- `build-macos-arm64`
|
||||
- `test`
|
||||
|
||||
Daily review cadence:
|
||||
- run once per day until RC tag:
|
||||
- `gh issue list -R bybrooklyn/openbitdo --label release-blocker --state open --limit 200`
|
||||
- release remains blocked while this list is non-empty.
|
||||
- AUR auth troubleshooting runbook:
|
||||
- [aur_publish_troubleshooting.md](/Users/brooklyn/data/8bitdo/cleanroom/process/aur_publish_troubleshooting.md)
|
||||
## Clean Tree Gate
|
||||
|
||||
## Scope-Completeness Gate ("Good Point")
|
||||
Before tagging `v0.0.1-rc.2`, RC scope must match the locked contract:
|
||||
- JP108 mapping supports dedicated keys only (`A/B/K1-K8`) for RC.
|
||||
- Ultimate2 expanded mapping supports RC-required fields only:
|
||||
- remappable slots `A/B/K1-K8`
|
||||
- known controller-button targets
|
||||
- profile slot read/write/readback
|
||||
- firmware version in diagnostics/reports
|
||||
- L2/R2 analog read (and write where capability allows)
|
||||
|
||||
Release gate is checklist-driven for RC (no separate scorecard artifact).
|
||||
|
||||
## Clean-Tree Requirement (Before Tagging)
|
||||
Run from `/Users/brooklyn/data/8bitdo/cleanroom`:
|
||||
From `cleanroom/`:
|
||||
|
||||
```bash
|
||||
git status --porcelain
|
||||
@@ -46,108 +28,53 @@ git clean -ndX
|
||||
```
|
||||
|
||||
Expected:
|
||||
- `git status --porcelain` prints nothing (no modified, staged, or untracked files)
|
||||
- `git clean -ndX` output reviewed for ignored-build artifacts only
|
||||
|
||||
Tracked-path audit:
|
||||
|
||||
```bash
|
||||
git ls-files | rg '(^sdk/dist/|^sdk/target/|^harness/reports/)'
|
||||
```
|
||||
|
||||
Expected:
|
||||
- no tracked artifact/build-output paths matched
|
||||
|
||||
## Required CI Checks
|
||||
- `guard`
|
||||
- `aur-validate`
|
||||
- `tui-smoke-test`
|
||||
- `build-macos-arm64`
|
||||
- `test`
|
||||
|
||||
## Release Secret Preflight (Tag Workflow)
|
||||
Tag preflight must fail early if any required secret is missing:
|
||||
- `AUR_USERNAME`
|
||||
- `AUR_SSH_PRIVATE_KEY`
|
||||
- `HOMEBREW_TAP_TOKEN`
|
||||
- no tracked modifications or staged changes
|
||||
- ignored-output review only from `git clean -ndX`
|
||||
|
||||
## Artifact Expectations
|
||||
|
||||
Release assets must include:
|
||||
- `openbitdo-v0.0.1-rc.2-linux-x86_64.tar.gz`
|
||||
- `openbitdo-v0.0.1-rc.2-linux-x86_64`
|
||||
- `openbitdo-v0.0.1-rc.2-linux-aarch64.tar.gz`
|
||||
- `openbitdo-v0.0.1-rc.2-linux-aarch64`
|
||||
- `openbitdo-v0.0.1-rc.2-macos-arm64.tar.gz`
|
||||
- `openbitdo-v0.0.1-rc.2-macos-arm64`
|
||||
- `openbitdo-v0.0.1-rc.2-macos-arm64.pkg`
|
||||
- corresponding `.sha256` files for every artifact above
|
||||
|
||||
## Verify Checksums
|
||||
Run from release asset directory:
|
||||
- `openbitdo-v0.0.1-rc.4-linux-x86_64.tar.gz`
|
||||
- `openbitdo-v0.0.1-rc.4-linux-x86_64`
|
||||
- `openbitdo-v0.0.1-rc.4-linux-aarch64.tar.gz`
|
||||
- `openbitdo-v0.0.1-rc.4-linux-aarch64`
|
||||
- `openbitdo-v0.0.1-rc.4-macos-arm64.tar.gz`
|
||||
- `openbitdo-v0.0.1-rc.4-macos-arm64`
|
||||
- `openbitdo-v0.0.1-rc.4-macos-arm64.pkg`
|
||||
- `.sha256` files for every artifact above
|
||||
|
||||
```bash
|
||||
shasum -a 256 -c openbitdo-v0.0.1-rc.2-linux-x86_64.tar.gz.sha256
|
||||
shasum -a 256 -c openbitdo-v0.0.1-rc.2-linux-x86_64.sha256
|
||||
shasum -a 256 -c openbitdo-v0.0.1-rc.2-linux-aarch64.tar.gz.sha256
|
||||
shasum -a 256 -c openbitdo-v0.0.1-rc.2-linux-aarch64.sha256
|
||||
shasum -a 256 -c openbitdo-v0.0.1-rc.2-macos-arm64.tar.gz.sha256
|
||||
shasum -a 256 -c openbitdo-v0.0.1-rc.2-macos-arm64.sha256
|
||||
shasum -a 256 -c openbitdo-v0.0.1-rc.2-macos-arm64.pkg.sha256
|
||||
```
|
||||
## Distribution Gate
|
||||
|
||||
## Manual Smoke Matrix
|
||||
1. Linux `x86_64`
|
||||
- Extract tarball, run `./bin/openbitdo --mock`
|
||||
- Confirm dashboard renders (device list, quick actions, event panel)
|
||||
- Confirm settings screen opens and returns to dashboard
|
||||
- GitHub prerelease assets must be published successfully.
|
||||
- AUR publish must render checksum-pinned metadata and update `openbitdo-bin`.
|
||||
- Homebrew publish must render a checksum-pinned formula and update `bybrooklyn/homebrew-openbitdo`.
|
||||
|
||||
2. Linux `aarch64`
|
||||
- Extract tarball, run `./bin/openbitdo --mock`
|
||||
- Confirm dashboard navigation and preflight/task render
|
||||
## macOS Packaging Gate
|
||||
|
||||
3. macOS arm64
|
||||
- Run standalone binary `openbitdo --mock`
|
||||
- Install `.pkg`, then run `/opt/homebrew/bin/openbitdo --mock`
|
||||
- Confirm launch and settings view behavior
|
||||
- `.pkg` remains unsigned and non-notarized for this RC.
|
||||
- Gatekeeper friction is expected and must be documented.
|
||||
- Tarball and standalone binary remain the fallback paths.
|
||||
|
||||
## Help Surface Verification
|
||||
- `openbitdo --help` shows single-command usage with `--mock`.
|
||||
## Manual Smoke Expectations
|
||||
|
||||
## Distribution Readiness Notes
|
||||
- Homebrew publication runs after release asset publish when `HOMEBREW_PUBLISH_ENABLED=1`.
|
||||
- AUR publication runs after release asset publish when `AUR_PUBLISH_ENABLED=1`.
|
||||
- Both package paths use release-derived SHA256 values (no `SKIP`, no `:no_check` in published metadata).
|
||||
1. Linux `x86_64`: launch `openbitdo --mock`
|
||||
2. Linux `aarch64`: launch `openbitdo --mock`
|
||||
3. macOS arm64 standalone binary: launch `openbitdo --mock`
|
||||
4. macOS arm64 `.pkg`: confirm payload installation path and launch behavior where possible
|
||||
|
||||
## Current Status Snapshot
|
||||
|
||||
## RC Gate Snapshot (Local)
|
||||
| Gate | Status | Notes |
|
||||
| --- | --- | --- |
|
||||
| Clean tree | Pass | Verified empty on `c3115da` before final checklist update (`git status --porcelain`). |
|
||||
| Secrets present | Pass | `AUR_USERNAME`, `AUR_SSH_PRIVATE_KEY`, `HOMEBREW_TAP_TOKEN` exist in repo secrets. |
|
||||
| Required checks configured | Pass | `guard`, `test`, `tui-smoke-test`, `aur-validate`, `build-macos-arm64`. |
|
||||
| Open release-blocker issues | Pass | `0` open (`gh issue list --label release-blocker --state open`). |
|
||||
| RC release allowed | Fail | `No` yet: AUR SSH auth still returns `Permission denied (publickey)`. |
|
||||
| Required CI checks | Pass | Current required checks are configured in GitHub branch protection. |
|
||||
| GitHub prerelease assets | Pending | Verify `v0.0.1-rc.4` assets after the tag workflow completes. |
|
||||
| AUR publication | Pending | Verify `openbitdo-bin` updates to `v0.0.1-rc.4` after release publication. |
|
||||
| Homebrew publication | Pending | Verify `bybrooklyn/homebrew-openbitdo` updates to `v0.0.1-rc.4` after release publication. |
|
||||
| macOS notarization | Deferred | Explicitly out of scope until Apple credentials exist. |
|
||||
|
||||
## RC Execution Log
|
||||
Historical note: entries below may mention older command forms from prior milestones and are preserved as-is for audit history.
|
||||
## Historical Notes
|
||||
|
||||
- 2026-03-02T20:54:31Z: governance preflight complete; release blocker remains open by policy.
|
||||
- 2026-03-02T21:38:17Z: set `HOMEBREW_TAP_REPO=bybrooklyn/homebrew-openbitdo`; repository and tap visibility switched to public.
|
||||
- 2026-03-02T21:40:00Z: bootstrapped tap repo `bybrooklyn/homebrew-openbitdo` with initial `Formula/openbitdo.rb`.
|
||||
- 2026-03-02T21:45:27Z to 2026-03-02T21:48:55Z: CI run `22597105846` on commit `c3115da` passed `guard`, `test`, `tui-smoke-test`, `aur-validate`, `build-macos-arm64`, `build-linux-x86_64`, and `build-linux-aarch64`.
|
||||
- 2026-03-02T21:49:00Z to 2026-03-02T21:55:00Z: downloaded CI artifacts and manually verified each artifact hash against `.sha256` content (all matched) for:
|
||||
- `openbitdo-v0.0.0-ci-linux-x86_64.tar.gz`
|
||||
- `openbitdo-v0.0.0-ci-linux-x86_64`
|
||||
- `openbitdo-v0.0.0-ci-linux-aarch64.tar.gz`
|
||||
- `openbitdo-v0.0.0-ci-linux-aarch64`
|
||||
- `openbitdo-v0.0.0-ci-macos-arm64.tar.gz`
|
||||
- `openbitdo-v0.0.0-ci-macos-arm64`
|
||||
- `openbitdo-v0.0.0-ci-macos-arm64.pkg`
|
||||
- 2026-03-02T21:56:00Z to 2026-03-02T22:00:00Z: Linux artifact smoke completed in containers for `linux/amd64` and `linux/arm64` by launching `openbitdo --mock` and observing successful TUI startup.
|
||||
- 2026-03-02T21:57:00Z: local macOS packaging smoke completed via `./sdk/scripts/package-macos.sh v0.0.0-local arm64` (tarball, standalone binary, pkg generated).
|
||||
- 2026-03-02T21:58:00Z: local standalone macOS smoke completed (`openbitdo-v0.0.0-local-macos-arm64 --mock`) with TUI startup and clean exit via scripted key input.
|
||||
- 2026-03-02T21:59:00Z: pkg payload path validated by expansion (`Payload/opt/homebrew/bin/openbitdo`); direct installer invocation requires root (`installer: Must be run as root to install this package`).
|
||||
- 2026-03-02T21:59:30Z: About behavior validated by test run `cargo test -p bitdo_tui about_state_roundtrip_returns_home`.
|
||||
- 2026-03-02T22:02:00Z: Wave 2 issues `#2` through `#13` closed with per-issue evidence comments.
|
||||
- 2026-03-02T22:03:00Z: epic issue `#1` closed and `release-blocker` label removed after child closure summary.
|
||||
- 2026-03-02T22:04:00Z: clean-tree gate confirmed on baseline commit `c3115da` (`git status --porcelain` empty).
|
||||
- 2026-03-02T22:10:00Z: removed hardware self-hosted checks from branch protection and CI/release gate policy.
|
||||
- Historical RC activity for earlier candidates is preserved in commit history and the changelog.
|
||||
- Troubleshooting for AUR SSH publication lives in `process/aur_publish_troubleshooting.md`.
|
||||
|
||||
211
README.md
211
README.md
@@ -1,185 +1,62 @@
|
||||
# OpenBitdo
|
||||
|
||||
OpenBitdo is a clean-room implementation workspace for beginner-friendly 8BitDo tooling.
|
||||
OpenBitDo is an unofficial tool and should be used at your own risk. The authors are not responsible for device damage, firmware corruption, or data loss. This project is not affiliated with or endorsed by 8BitDo. See the [LICENSE](/Users/brooklyn/data/8bitdo/cleanroom/LICENSE) file for details.
|
||||
OpenBitdo is a clean-room, beginner-first 8BitDo utility built around a modern terminal UI.
|
||||
It focuses on safe diagnostics first, guided firmware/update flows for confirmed devices, and clear blocked-action messaging for devices that are still under investigation.
|
||||
|
||||
## Beginner Quickstart
|
||||
From `/Users/brooklyn/data/8bitdo/cleanroom/sdk`:
|
||||
OpenBitdo is unofficial and not affiliated with 8BitDo. Firmware updates and device changes always carry risk. Read the prompts carefully and keep backups or recovery plans where available.
|
||||
|
||||
```bash
|
||||
cargo run -p openbitdo --
|
||||
```
|
||||
## What OpenBitdo Does Today
|
||||
|
||||
Optional mock mode:
|
||||
- Detect connected 8BitDo devices and explain their current support level.
|
||||
- Run diagnostics and save support reports.
|
||||
- Stage verified firmware updates on full-support devices.
|
||||
- Edit supported mappings for the currently confirmed JP108 and Ultimate 2 flows.
|
||||
- Keep unconfirmed devices in safe read-only or detect-only paths.
|
||||
|
||||
```bash
|
||||
cargo run -p openbitdo -- --mock
|
||||
```
|
||||
## Install
|
||||
|
||||
`openbitdo` launches the interactive dashboard directly.
|
||||
|
||||
## Install (Public RC)
|
||||
|
||||
Homebrew tap install path for RC:
|
||||
|
||||
```bash
|
||||
brew tap bybrooklyn/openbitdo
|
||||
brew install openbitdo
|
||||
```
|
||||
|
||||
Homebrew Core inclusion (`brew install openbitdo` without tapping) is not an RC blocker and may land later.
|
||||
|
||||
AUR package names:
|
||||
- `openbitdo-bin` (prebuilt binary)
|
||||
|
||||
macOS RC caveat:
|
||||
- `.pkg` installers are unsigned/ad-hoc for `v0.0.1-rc.2`.
|
||||
- notarization is required starting with `v0.1.0`.
|
||||
|
||||
## UI Language Support
|
||||
|
||||
| Language | Status | Notes |
|
||||
| Path | Command | Best for |
|
||||
| --- | --- | --- |
|
||||
| English | Supported | Default and primary beginner flow language. |
|
||||
| Spanish | In Progress | Roadmap item for core wizard screens. |
|
||||
| Japanese | Planned | Planned after Spanish stabilization. |
|
||||
| German | Planned | Planned after Spanish stabilization. |
|
||||
| French | Planned | Planned after Spanish stabilization. |
|
||||
| Homebrew | `brew tap bybrooklyn/openbitdo && brew install openbitdo` | macOS or Linux users who want the standard tap flow |
|
||||
| AUR | `paru -S openbitdo-bin` | Arch Linux users who want a prebuilt package |
|
||||
| GitHub Releases | Download a release tarball and run `bin/openbitdo` | Users who want a standalone binary without a package manager |
|
||||
| From source | `cargo run -p openbitdo --` from `sdk/` | Contributors and local development |
|
||||
|
||||
## Support Status Model
|
||||
## First Run
|
||||
|
||||
| Runtime Tier | README Status | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `full` | Supported | Mapping/update paths allowed when safety gates are satisfied. |
|
||||
| `candidate-readonly` | In Progress | Detect/identify/diagnostics enabled, writes and firmware transfer blocked. |
|
||||
| `detect-only` | Planned | Detect/identify baseline now, broader functionality planned. |
|
||||
1. Launch `openbitdo`.
|
||||
2. If you do not have hardware attached yet, launch `openbitdo --mock` to preview the interface.
|
||||
3. Pick a controller from the dashboard.
|
||||
4. Use `Diagnose` first if you are unsure what is safe for that device.
|
||||
5. Follow the support-tier guidance shown in the UI before attempting update or mapping work.
|
||||
|
||||
Beginner UI note: candidate devices are shown with blocked-action messaging in the TUI so new users always see the safe path first.
|
||||
## Support Tiers
|
||||
|
||||
## Protocol Family Overview
|
||||
| Tier | What it means |
|
||||
| --- | --- |
|
||||
| `supported` | Diagnostics, update, and any confirmed mapping flows are available when safety gates are satisfied. |
|
||||
| `read-only candidate` | Diagnostics are available, but update and mapping stay blocked until runtime and hardware confirmation are complete. |
|
||||
| `detect-only` | OpenBitdo can identify the device, but deeper workflows are intentionally unavailable. |
|
||||
|
||||
| Family | PID Rows | Notes |
|
||||
| --- | --- | --- |
|
||||
| Standard64 | 36 | Largest family, mixed status from Planned to Supported. |
|
||||
| DInput | 11 | Includes current full-support Ultimate2 and Pro3 lines. |
|
||||
| JpHandshake | 9 | Includes JP108 full support and keyboard-related candidate lines. |
|
||||
| DS4Boot | 0 | No standalone canonical PID rows in current catalog. |
|
||||
| Unknown | 1 | Sentinel/internal row only. |
|
||||
## macOS Packaging Caveat
|
||||
|
||||
DS4Boot explicit note: there are currently no active canonical PID rows in this catalog.
|
||||
Current macOS release artifacts are unsigned and non-notarized.
|
||||
That means Gatekeeper friction is expected for the `.pkg`, tarball, and standalone binary.
|
||||
If the installer path is inconvenient, use the extracted tarball or Homebrew tap as the fallback path.
|
||||
Apple Developer signing and notarization are deferred until credentials are available.
|
||||
|
||||
## Compatibility Verification Dates (Manual, ISO)
|
||||
| Family | Last verified date | Notes |
|
||||
| --- | --- | --- |
|
||||
| Standard64 | 2026-03-02 | Manual RC verification date. |
|
||||
| DInput | 2026-03-02 | Manual RC verification date. |
|
||||
| JpHandshake | 2026-03-02 | Manual RC verification date. |
|
||||
| DS4Boot | 2026-03-02 | No active canonical rows. |
|
||||
| Unknown | 2026-03-02 | Sentinel/internal row only. |
|
||||
## Release And Package Map
|
||||
|
||||
## Device Compatibility (Canonical, No Duplicate PIDs)
|
||||
Device naming references are documented in [device_name_catalog.md](/Users/brooklyn/data/8bitdo/cleanroom/spec/device_name_catalog.md) and [device_name_sources.md](/Users/brooklyn/data/8bitdo/cleanroom/process/device_name_sources.md).
|
||||
- GitHub prereleases publish the canonical release assets.
|
||||
- AUR publishes `openbitdo-bin` from the Linux tarballs and release-derived checksums.
|
||||
- Homebrew publishes through the separate tap repo `bybrooklyn/homebrew-openbitdo`.
|
||||
- Package-manager metadata is rendered from published assets so release checksums stay authoritative.
|
||||
|
||||
### Unknown
|
||||
## Where To Go Next
|
||||
|
||||
| Canonical ID | Display Name | PID (hex) | Family | Status | Current User Actions | Firmware Path | Notes |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| `PID_None` | No Device (Sentinel) | `0x0000` | Unknown | Planned | None | N/A | Internal sentinel row only. |
|
||||
|
||||
### Standard64
|
||||
|
||||
| Canonical ID | Display Name | PID (hex) | Family | Status | Current User Actions | Firmware Path | Notes |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| `PID_IDLE` | Unconfirmed Internal Device (PID_IDLE) | `0x3109` | Standard64 | Planned | Detect, identify | Blocked | Internal interface row. |
|
||||
| `PID_SN30Plus` | SN30 Pro+ | `0x6002` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_USB_Ultimate` | Unconfirmed Internal Device (PID_USB_Ultimate) | `0x3100` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_USB_Ultimate2` | Unconfirmed Internal Device (PID_USB_Ultimate2) | `0x3105` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_USB_UltimateClasses` | Unconfirmed Internal Device (PID_USB_UltimateClasses) | `0x3104` | Standard64 | Planned | Detect, identify | Blocked | Planned support only. |
|
||||
| `PID_Xcloud` | Unconfirmed Internal Device (PID_Xcloud) | `0x2100` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_Xcloud2` | Unconfirmed Internal Device (PID_Xcloud2) | `0x2101` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_ArcadeStick` | Arcade Stick | `0x901a` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_Pro2` | Pro 2 Bluetooth Controller | `0x6003` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_Pro2_CY` | Unconfirmed Variant Name (PID_Pro2_CY) | `0x6006` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_Pro2_Wired` | Pro 2 Wired Controller | `0x3010` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_Ultimate_PC` | Ultimate PC Controller | `0x3011` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_Ultimate2_4` | Ultimate 2.4G Controller | `0x3012` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_Ultimate2_4RR` | Ultimate 2.4G Adapter | `0x3013` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_UltimateBT` | Ultimate Wireless Controller | `0x6007` | Standard64 | Supported | Detect, diagnose, recommended update | Stable download + local fallback | Full-support runtime. |
|
||||
| `PID_UltimateBTRR` | Ultimate Wireless Adapter | `0x3106` | Standard64 | Supported | Detect, diagnose, recommended update | Stable download + local fallback | Full-support runtime. |
|
||||
| `PID_NUMPAD` | Retro 18 Mechanical Numpad | `0x5203` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_NUMPADRR` | Retro 18 Adapter | `0x5204` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_Pro3DOCK` | Charging Dock for Pro 3S Gamepad | `0x600d` | Standard64 | Planned | Detect, identify | Blocked | Planned support only. |
|
||||
| `PID_NGCDIY` | Mod Kit for NGC Controller | `0x5750` | Standard64 | Planned | Detect, identify | Blocked | Planned support only. |
|
||||
| `PID_NGCRR` | Retro Receiver for NGC | `0x902a` | Standard64 | Planned | Detect, identify | Blocked | Planned support only. |
|
||||
| `PID_Mouse` | Retro R8 Mouse | `0x5205` | Standard64 | Planned | Detect, identify | Blocked | Canonical row for `0x5205`. |
|
||||
| `PID_MouseRR` | Retro R8 Adapter | `0x5206` | Standard64 | Planned | Detect, identify | Blocked | Planned support only. |
|
||||
| `PID_SaturnRR` | Retro Receiver for Saturn | `0x902b` | Standard64 | Planned | Detect, identify | Blocked | Planned support only. |
|
||||
| `PID_UltimateBT2C` | Ultimate 2C Bluetooth Controller | `0x301a` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_Lashen` | Ultimate Mobile Gaming Controller | `0x301e` | Standard64 | Planned | Detect, identify | Blocked | Planned support only. |
|
||||
| `PID_N64BT` | 64 Bluetooth Controller | `0x3019` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_N64` | 64 2.4G Wireless Controller | `0x3004` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_N64RR` | Retro Receiver for N64 | `0x9028` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_XBOXUK` | Retro 87 Mechanical Keyboard - Xbox (UK) | `0x3026` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_XBOXUKUSB` | Retro 87 Mechanical Keyboard Adapter - Xbox (UK) | `0x3027` | Standard64 | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_LashenX` | Ultimate Mobile Gaming Controller For Xbox | `0x200b` | Standard64 | Planned | Detect, identify | Blocked | Planned support only. |
|
||||
| `PID_N64JoySticks` | Joystick v2 for N64 Controller | `0x3021` | Standard64 | Planned | Detect, identify | Blocked | Planned support only. |
|
||||
| `PID_DoubleSuper` | Wireless Dual Super Button | `0x203e` | Standard64 | Planned | Detect, identify | Blocked | Planned support only. |
|
||||
| `PID_Cube2RR` | Retro Cube 2 Adapter - N Edition | `0x2056` | Standard64 | Planned | Detect, identify | Blocked | Planned support only. |
|
||||
| `PID_Cube2` | Retro Cube 2 Speaker - N Edition | `0x2039` | Standard64 | Planned | Detect, identify | Blocked | Planned support only. |
|
||||
|
||||
### JpHandshake
|
||||
|
||||
| Canonical ID | Display Name | PID (hex) | Family | Status | Current User Actions | Firmware Path | Notes |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| `PID_JP` | Retro Mechanical Keyboard | `0x5200` | JpHandshake | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_JPUSB` | Retro Mechanical Keyboard Receiver | `0x5201` | JpHandshake | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_108JP` | Retro 108 Mechanical Keyboard | `0x5209` | JpHandshake | Supported | Detect, diagnose, dedicated mapping (`A/B/K1-K8`), recommended update | Stable download + local fallback | Full-support JP108 flow. |
|
||||
| `PID_108JPUSB` | Retro 108 Mechanical Adapter | `0x520a` | JpHandshake | Supported | Detect, diagnose, dedicated mapping (`A/B/K1-K8`), recommended update | Stable download + local fallback | Full-support JP108 receiver flow. |
|
||||
| `PID_XBOXJP` | Retro 87 Mechanical Keyboard - Xbox Edition | `0x2028` | JpHandshake | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_XBOXJPUSB` | Retro 87 Mechanical Keyboard Adapter - Xbox Edition | `0x202e` | JpHandshake | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_68JP` | Retro 68 Keyboard - N40 | `0x203a` | JpHandshake | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_68JPUSB` | Retro 68 Keyboard Adapter - N40 | `0x2049` | JpHandshake | In Progress | Detect, identify, diagnose | Blocked (`NotHardwareConfirmed`) | Candidate read-only. |
|
||||
| `PID_ASLGJP` | Riviera Keyboard | `0x205a` | JpHandshake | Planned | Detect, identify | Blocked | Planned support only. |
|
||||
|
||||
### DInput
|
||||
|
||||
| Canonical ID | Display Name | PID (hex) | Family | Status | Current User Actions | Firmware Path | Notes |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| `PID_QINGCHUN2` | Ultimate 2C Controller | `0x310a` | DInput | Supported | Detect, diagnose, recommended update | Stable download + local fallback | Full-support runtime. |
|
||||
| `PID_QINGCHUN2RR` | Ultimate 2C Wireless Adapter | `0x301c` | DInput | Supported | Detect, diagnose, recommended update | Stable download + local fallback | Full-support runtime. |
|
||||
| `PID_Xinput` | Unconfirmed Interface Name (PID_Xinput) | `0x310b` | DInput | Planned | Detect, identify | Blocked | Planned support only. |
|
||||
| `PID_Pro3` | Pro 3 Bluetooth Gamepad | `0x6009` | DInput | Supported | Detect, diagnose, recommended update | Stable download + local fallback | Full-support runtime. |
|
||||
| `PID_Pro3USB` | Pro 3 Bluetooth Adapter | `0x600a` | DInput | Supported | Detect, diagnose, recommended update | Stable download + local fallback | Full-support runtime. |
|
||||
| `PID_Ultimate2` | Ultimate 2 Wireless Controller | `0x6012` | DInput | Supported | Detect, diagnose, slot mapping (`A/B/K1-K8`), analog L2/R2, recommended update | Stable download + local fallback | Full-support Ultimate2 RC scope (known controller-button targets). |
|
||||
| `PID_Ultimate2RR` | Ultimate 2 Wireless Adapter | `0x6013` | DInput | Supported | Detect, diagnose, slot mapping (`A/B/K1-K8`), analog L2/R2, recommended update | Stable download + local fallback | Full-support Ultimate2 receiver RC scope (known controller-button targets). |
|
||||
| `PID_UltimateBT2` | Ultimate 2 Bluetooth Controller | `0x600f` | DInput | Supported | Detect, diagnose, recommended update | Stable download + local fallback | Full-support runtime. |
|
||||
| `PID_UltimateBT2RR` | Ultimate 2 Bluetooth Adapter | `0x6011` | DInput | Supported | Detect, diagnose, recommended update | Stable download + local fallback | Full-support runtime. |
|
||||
| `PID_HitBox` | Arcade Controller | `0x600b` | DInput | Supported | Detect, diagnose, recommended update | Stable download + local fallback | Full-support runtime. |
|
||||
| `PID_HitBoxRR` | Arcade Controller Adapter | `0x600c` | DInput | Supported | Detect, diagnose, recommended update | Stable download + local fallback | Full-support runtime. |
|
||||
|
||||
## Alias Appendix (Non-Canonical Names)
|
||||
These aliases are intentionally excluded from canonical PID rows to guarantee uniqueness.
|
||||
|
||||
| Alias PID Name | Canonical PID Name | PID (hex) |
|
||||
| --- | --- | --- |
|
||||
| `PID_Pro2_OLD` | `PID_Pro2` | `0x6003` |
|
||||
| `PID_ASLGMouse` | `PID_Mouse` | `0x5205` |
|
||||
|
||||
See [alias_index.md](/Users/brooklyn/data/8bitdo/cleanroom/spec/alias_index.md) for details.
|
||||
|
||||
## Hardware Support Confidence
|
||||
Support is implemented to our best current knowledge. Coverage and confidence are expanded and confirmed over time through community testing and hardware reports.
|
||||
|
||||
## Dirty-Room Evidence Backlog
|
||||
- [dirtyroom_evidence_backlog.md](/Users/brooklyn/data/8bitdo/cleanroom/process/dirtyroom_evidence_backlog.md)
|
||||
- [dirtyroom_collection_playbook.md](/Users/brooklyn/data/8bitdo/cleanroom/process/dirtyroom_collection_playbook.md)
|
||||
- [dirtyroom_dossier_schema.md](/Users/brooklyn/data/8bitdo/cleanroom/process/dirtyroom_dossier_schema.md)
|
||||
- [community_evidence_intake.md](/Users/brooklyn/data/8bitdo/cleanroom/process/community_evidence_intake.md)
|
||||
|
||||
## Source Notes
|
||||
- Canonical clean-room naming catalog: [device_name_catalog.md](/Users/brooklyn/data/8bitdo/cleanroom/spec/device_name_catalog.md)
|
||||
- Dirty-room source index + official web cross-check URLs: [device_name_sources.md](/Users/brooklyn/data/8bitdo/cleanroom/process/device_name_sources.md)
|
||||
|
||||
## Public RC Gate
|
||||
The next RC remains blocked until release-blocker issues are zero and all required checks are green.
|
||||
RC gating is checklist-based (see [RC_CHECKLIST.md](/Users/brooklyn/data/8bitdo/cleanroom/RC_CHECKLIST.md)).
|
||||
- Developer and release-engineering details: [sdk/README.md](sdk/README.md)
|
||||
- Current RC release gate: [RC_CHECKLIST.md](RC_CHECKLIST.md)
|
||||
- Changelog and release notes: [CHANGELOG.md](CHANGELOG.md)
|
||||
- CLI and packaging migration notes: [MIGRATION.md](MIGRATION.md)
|
||||
- Device catalog: [spec/device_name_catalog.md](spec/device_name_catalog.md)
|
||||
- Protocol overview: [spec/protocol_spec.md](spec/protocol_spec.md)
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
# AUR Packaging
|
||||
|
||||
This directory contains AUR package sources for:
|
||||
- `openbitdo-bin` (prebuilt release assets)
|
||||
This directory holds the tracked AUR source for `openbitdo-bin`.
|
||||
|
||||
Publishing is automated by `.github/workflows/aur-publish.yml` and remains gated:
|
||||
- requires repository variable `AUR_PUBLISH_ENABLED=1`
|
||||
- requires secrets `AUR_SSH_PRIVATE_KEY` and `AUR_USERNAME`
|
||||
## Source Of Truth
|
||||
|
||||
Publish flow:
|
||||
1. wait for release assets from a `v*` tag
|
||||
2. compute authoritative SHA256 values from released artifacts
|
||||
3. render `PKGBUILD`/`.SRCINFO` with pinned hashes
|
||||
4. push updates to AUR repo
|
||||
- tracked metadata: `packaging/aur/openbitdo-bin/PKGBUILD` and `.SRCINFO`
|
||||
- template: `packaging/aur/openbitdo-bin/PKGBUILD.tmpl`
|
||||
- renderer: `packaging/scripts/render_release_metadata.sh`
|
||||
|
||||
Template files used for release rendering:
|
||||
- `openbitdo-bin/PKGBUILD.tmpl`
|
||||
## Publish Flow
|
||||
|
||||
1. Publish GitHub release assets for a `v*` tag.
|
||||
2. Render `PKGBUILD` and `.SRCINFO` from those assets.
|
||||
3. Upload rendered metadata as a workflow artifact for audit.
|
||||
4. Push the updated metadata to the AUR repo for `openbitdo-bin`.
|
||||
|
||||
## Required Controls
|
||||
|
||||
- repo variable `AUR_PUBLISH_ENABLED=1`
|
||||
- secrets `AUR_USERNAME` and `AUR_SSH_PRIVATE_KEY`
|
||||
- no placeholder checksums in published metadata
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
pkgbase = openbitdo-bin
|
||||
pkgdesc = Prebuilt beginner-first clean-room 8BitDo utility
|
||||
pkgver = 0.0.1rc1
|
||||
pkgver = 0.0.1rc3
|
||||
pkgrel = 1
|
||||
url = https://github.com/bybrooklyn/openbitdo
|
||||
arch = x86_64
|
||||
arch = aarch64
|
||||
license = BSD-3-Clause
|
||||
depends = hidapi
|
||||
source_x86_64 = openbitdo-v0.0.1-rc.1-linux-x86_64.tar.gz::https://github.com/bybrooklyn/openbitdo/releases/download/v0.0.1-rc.1/openbitdo-v0.0.1-rc.1-linux-x86_64.tar.gz
|
||||
sha256sums_x86_64 = 0000000000000000000000000000000000000000000000000000000000000000
|
||||
source_aarch64 = openbitdo-v0.0.1-rc.1-linux-aarch64.tar.gz::https://github.com/bybrooklyn/openbitdo/releases/download/v0.0.1-rc.1/openbitdo-v0.0.1-rc.1-linux-aarch64.tar.gz
|
||||
sha256sums_aarch64 = 0000000000000000000000000000000000000000000000000000000000000000
|
||||
source_x86_64 = openbitdo-v0.0.1-rc.3-linux-x86_64.tar.gz::https://github.com/bybrooklyn/openbitdo/releases/download/v0.0.1-rc.3/openbitdo-v0.0.1-rc.3-linux-x86_64.tar.gz
|
||||
sha256sums_x86_64 = fa7ae583796dc979a64eaeb670a06fc7c10fd51bbb12fce5815d66629e18c9a0
|
||||
source_aarch64 = openbitdo-v0.0.1-rc.3-linux-aarch64.tar.gz::https://github.com/bybrooklyn/openbitdo/releases/download/v0.0.1-rc.3/openbitdo-v0.0.1-rc.3-linux-aarch64.tar.gz
|
||||
sha256sums_aarch64 = 992586ff89da6dfdb137fd424f651ccedb4a65de0f43d615cda682e31e222dd0
|
||||
|
||||
pkgname = openbitdo-bin
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
pkgname=openbitdo-bin
|
||||
pkgver=0.0.1rc1
|
||||
_upstream_tag=v0.0.1-rc.1
|
||||
pkgver=0.0.1rc3
|
||||
_upstream_tag=v0.0.1-rc.3
|
||||
pkgrel=1
|
||||
pkgdesc="Prebuilt beginner-first clean-room 8BitDo utility"
|
||||
arch=('x86_64' 'aarch64')
|
||||
@@ -9,8 +9,8 @@ license=('BSD-3-Clause')
|
||||
depends=('hidapi')
|
||||
source_x86_64=("openbitdo-${_upstream_tag}-linux-x86_64.tar.gz::${url}/releases/download/${_upstream_tag}/openbitdo-${_upstream_tag}-linux-x86_64.tar.gz")
|
||||
source_aarch64=("openbitdo-${_upstream_tag}-linux-aarch64.tar.gz::${url}/releases/download/${_upstream_tag}/openbitdo-${_upstream_tag}-linux-aarch64.tar.gz")
|
||||
sha256sums_x86_64=('0000000000000000000000000000000000000000000000000000000000000000')
|
||||
sha256sums_aarch64=('0000000000000000000000000000000000000000000000000000000000000000')
|
||||
sha256sums_x86_64=('fa7ae583796dc979a64eaeb670a06fc7c10fd51bbb12fce5815d66629e18c9a0')
|
||||
sha256sums_aarch64=('992586ff89da6dfdb137fd424f651ccedb4a65de0f43d615cda682e31e222dd0')
|
||||
|
||||
package() {
|
||||
local extracted_dir
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
class Openbitdo < Formula
|
||||
desc "Beginner-first clean-room 8BitDo TUI utility"
|
||||
homepage "https://github.com/bybrooklyn/openbitdo"
|
||||
license "BSD-3-Clause"
|
||||
version "0.0.1-rc.1"
|
||||
|
||||
on_macos do
|
||||
if Hardware::CPU.arm?
|
||||
url "https://github.com/bybrooklyn/openbitdo/releases/download/v0.0.1-rc.1/openbitdo-v0.0.1-rc.1-macos-arm64.tar.gz"
|
||||
sha256 "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
end
|
||||
end
|
||||
|
||||
on_linux do
|
||||
if Hardware::CPU.intel?
|
||||
url "https://github.com/bybrooklyn/openbitdo/releases/download/v0.0.1-rc.1/openbitdo-v0.0.1-rc.1-linux-x86_64.tar.gz"
|
||||
sha256 "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
elsif Hardware::CPU.arm?
|
||||
url "https://github.com/bybrooklyn/openbitdo/releases/download/v0.0.1-rc.1/openbitdo-v0.0.1-rc.1-linux-aarch64.tar.gz"
|
||||
sha256 "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
end
|
||||
end
|
||||
|
||||
# Release automation rewrites checksums in the tap with authoritative values
|
||||
# from published assets.
|
||||
def install
|
||||
bin.install "bin/openbitdo"
|
||||
end
|
||||
|
||||
test do
|
||||
assert_match "openbitdo", shell_output("#{bin}/openbitdo --help")
|
||||
end
|
||||
end
|
||||
@@ -1,14 +1,24 @@
|
||||
# Homebrew Packaging
|
||||
|
||||
Formula source lives in `Formula/openbitdo.rb`.
|
||||
Template source used for release rendering: `Formula/openbitdo.rb.tmpl`.
|
||||
Homebrew publishing uses the separate tap repo `bybrooklyn/homebrew-openbitdo`.
|
||||
|
||||
Planned tap:
|
||||
- `bybrooklyn/homebrew-openbitdo`
|
||||
## Source Of Truth
|
||||
|
||||
Current status:
|
||||
- release workflow computes checksum-pinned formula values from published assets
|
||||
- tap sync remains gated by `HOMEBREW_PUBLISH_ENABLED=1`
|
||||
- template: `packaging/homebrew/Formula/openbitdo.rb.tmpl`
|
||||
- renderer: `packaging/scripts/render_release_metadata.sh`
|
||||
- sync helper: `packaging/homebrew/sync_tap.sh`
|
||||
|
||||
Optional sync helper:
|
||||
- `sync_tap.sh` (disabled by default unless `HOMEBREW_PUBLISH_ENABLED=1`)
|
||||
The main repo does not keep a checked-in rendered formula. Release rendering produces the formula from published assets, and the tap repo is the canonical published destination.
|
||||
|
||||
## Publish Flow
|
||||
|
||||
1. Publish GitHub release assets for a `v*` tag.
|
||||
2. Render a checksum-pinned formula from those assets.
|
||||
3. Upload the rendered formula as a workflow artifact for audit.
|
||||
4. Sync the rendered formula to `bybrooklyn/homebrew-openbitdo`.
|
||||
|
||||
## Required Controls
|
||||
|
||||
- repo variable `HOMEBREW_PUBLISH_ENABLED=1`
|
||||
- repo variable `HOMEBREW_TAP_REPO=bybrooklyn/homebrew-openbitdo`
|
||||
- secret `HOMEBREW_TAP_TOKEN`
|
||||
|
||||
@@ -23,9 +23,22 @@ HOMEBREW_TAP_TOKEN="$(
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
TAP_REPO="${HOMEBREW_TAP_REPO:-bybrooklyn/homebrew-openbitdo}"
|
||||
FORMULA_SOURCE="${FORMULA_SOURCE:-$ROOT/packaging/homebrew/Formula/openbitdo.rb}"
|
||||
FORMULA_SOURCE="${FORMULA_SOURCE:-}"
|
||||
TMP="$(mktemp -d)"
|
||||
|
||||
decode_base64() {
|
||||
if base64 --help 2>/dev/null | grep -q -- "--decode"; then
|
||||
base64 --decode
|
||||
else
|
||||
base64 -D
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ -z "$FORMULA_SOURCE" ]]; then
|
||||
echo "FORMULA_SOURCE must point to a rendered formula; run render_release_metadata.sh first" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$FORMULA_SOURCE" ]]; then
|
||||
echo "formula source not found: $FORMULA_SOURCE" >&2
|
||||
exit 1
|
||||
@@ -69,7 +82,7 @@ remote_content_file="$TMP/remote_formula.rb"
|
||||
|
||||
if api_with_fallback "repos/${TAP_REPO}/contents/${formula_path}?ref=main" >"$TMP/remote.json" 2>/dev/null; then
|
||||
remote_sha="$(jq -r '.sha // ""' "$TMP/remote.json")"
|
||||
jq -r '.content // ""' "$TMP/remote.json" | tr -d '\n' | base64 --decode >"$remote_content_file"
|
||||
jq -r '.content // ""' "$TMP/remote.json" | tr -d '\n' | decode_base64 >"$remote_content_file"
|
||||
if cmp -s "$FORMULA_SOURCE" "$remote_content_file"; then
|
||||
echo "no formula changes to push"
|
||||
exit 0
|
||||
|
||||
98
packaging/homebrew/test_sync_tap.sh
Executable file
98
packaging/homebrew/test_sync_tap.sh
Executable file
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
TMP="$(mktemp -d)"
|
||||
trap 'rm -rf "$TMP"' EXIT
|
||||
|
||||
MOCK_BIN="$TMP/bin"
|
||||
mkdir -p "$MOCK_BIN"
|
||||
|
||||
cat >"$MOCK_BIN/gh" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
STATE_DIR="${MOCK_GH_STATE_DIR:?}"
|
||||
|
||||
if [[ "${1:-}" != "api" ]]; then
|
||||
echo "mock gh only supports api" >&2
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
|
||||
method="GET"
|
||||
if [[ "${1:-}" == "--method" ]]; then
|
||||
method="$2"
|
||||
shift 2
|
||||
fi
|
||||
|
||||
endpoint="$1"
|
||||
shift
|
||||
|
||||
case "${method}:${endpoint}" in
|
||||
GET:repos/*/contents/Formula/openbitdo.rb\?ref=main)
|
||||
if [[ -f "$STATE_DIR/remote_formula.rb" ]]; then
|
||||
content="$(base64 < "$STATE_DIR/remote_formula.rb" | tr -d '\n')"
|
||||
printf '{"sha":"remote-sha","content":"%s"}\n' "$content"
|
||||
exit 0
|
||||
fi
|
||||
exit 1
|
||||
;;
|
||||
PUT:repos/*/contents/Formula/openbitdo.rb)
|
||||
content=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
if [[ "$1" == "-f" ]]; then
|
||||
case "$2" in
|
||||
content=*)
|
||||
content="${2#content=}"
|
||||
;;
|
||||
esac
|
||||
shift 2
|
||||
else
|
||||
shift
|
||||
fi
|
||||
done
|
||||
printf '%s' "$content" | base64 --decode >"$STATE_DIR/updated_formula.rb"
|
||||
echo "put" >>"$STATE_DIR/requests.log"
|
||||
printf '{"content":{"sha":"new-sha"}}\n'
|
||||
;;
|
||||
*)
|
||||
echo "unexpected mock gh call: ${method} ${endpoint}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
EOF
|
||||
chmod +x "$MOCK_BIN/gh"
|
||||
|
||||
FORMULA_SOURCE="$TMP/openbitdo.rb"
|
||||
cat >"$FORMULA_SOURCE" <<'EOF'
|
||||
class Openbitdo < Formula
|
||||
desc "OpenBitdo"
|
||||
end
|
||||
EOF
|
||||
|
||||
run_sync() {
|
||||
PATH="$MOCK_BIN:$PATH" \
|
||||
MOCK_GH_STATE_DIR="$TMP/mock-state" \
|
||||
GH_TOKEN="job-token" \
|
||||
HOMEBREW_TAP_TOKEN="tap-token" \
|
||||
HOMEBREW_TAP_REPO="bybrooklyn/homebrew-openbitdo" \
|
||||
HOMEBREW_PUBLISH_ENABLED="1" \
|
||||
FORMULA_SOURCE="$FORMULA_SOURCE" \
|
||||
bash "$ROOT/packaging/homebrew/sync_tap.sh"
|
||||
}
|
||||
|
||||
mkdir -p "$TMP/mock-state"
|
||||
cp "$FORMULA_SOURCE" "$TMP/mock-state/remote_formula.rb"
|
||||
run_sync >"$TMP/noop.out"
|
||||
grep -Fq "no formula changes to push" "$TMP/noop.out"
|
||||
test ! -f "$TMP/mock-state/updated_formula.rb"
|
||||
|
||||
cat >"$TMP/mock-state/remote_formula.rb" <<'EOF'
|
||||
class Openbitdo < Formula
|
||||
desc "Old formula"
|
||||
end
|
||||
EOF
|
||||
run_sync >"$TMP/update.out"
|
||||
grep -Fq "updated bybrooklyn/homebrew-openbitdo:Formula/openbitdo.rb" "$TMP/update.out"
|
||||
cmp -s "$FORMULA_SOURCE" "$TMP/mock-state/updated_formula.rb"
|
||||
63
packaging/scripts/test_render_release_metadata.sh
Executable file
63
packaging/scripts/test_render_release_metadata.sh
Executable file
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
TMP="$(mktemp -d)"
|
||||
trap 'rm -rf "$TMP"' EXIT
|
||||
|
||||
sha256() {
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
sha256sum "$1" | awk '{print $1}'
|
||||
else
|
||||
shasum -a 256 "$1" | awk '{print $1}'
|
||||
fi
|
||||
}
|
||||
|
||||
INPUT_DIR="$TMP/input"
|
||||
OUTPUT_DIR="$TMP/output"
|
||||
mkdir -p "$INPUT_DIR"
|
||||
|
||||
printf 'x86_64 archive payload\n' >"$INPUT_DIR/openbitdo-v0.0.1-rc.4-linux-x86_64.tar.gz"
|
||||
printf 'aarch64 archive payload\n' >"$INPUT_DIR/openbitdo-v0.0.1-rc.4-linux-aarch64.tar.gz"
|
||||
printf 'macos archive payload\n' >"$INPUT_DIR/openbitdo-v0.0.1-rc.4-macos-arm64.tar.gz"
|
||||
|
||||
bash "$ROOT/packaging/scripts/render_release_metadata.sh" \
|
||||
"v0.0.1-rc.4" \
|
||||
"bybrooklyn/openbitdo" \
|
||||
"$INPUT_DIR" \
|
||||
"$OUTPUT_DIR"
|
||||
|
||||
PKGBUILD="$OUTPUT_DIR/aur/openbitdo-bin/PKGBUILD"
|
||||
FORMULA="$OUTPUT_DIR/homebrew/Formula/openbitdo.rb"
|
||||
CHECKSUMS="$OUTPUT_DIR/checksums.env"
|
||||
|
||||
test -f "$PKGBUILD"
|
||||
test -f "$FORMULA"
|
||||
test -f "$CHECKSUMS"
|
||||
|
||||
expected_x86="$(sha256 "$INPUT_DIR/openbitdo-v0.0.1-rc.4-linux-x86_64.tar.gz")"
|
||||
expected_aarch64="$(sha256 "$INPUT_DIR/openbitdo-v0.0.1-rc.4-linux-aarch64.tar.gz")"
|
||||
expected_macos="$(sha256 "$INPUT_DIR/openbitdo-v0.0.1-rc.4-macos-arm64.tar.gz")"
|
||||
|
||||
grep -Fq "pkgver=0.0.1rc4" "$PKGBUILD"
|
||||
grep -Fq "_upstream_tag=v0.0.1-rc.4" "$PKGBUILD"
|
||||
grep -Fq "sha256sums_x86_64=('${expected_x86}')" "$PKGBUILD"
|
||||
grep -Fq "sha256sums_aarch64=('${expected_aarch64}')" "$PKGBUILD"
|
||||
|
||||
grep -Fq 'version "0.0.1-rc.4"' "$FORMULA"
|
||||
grep -Fq "sha256 \"${expected_x86}\"" "$FORMULA"
|
||||
grep -Fq "sha256 \"${expected_aarch64}\"" "$FORMULA"
|
||||
grep -Fq "sha256 \"${expected_macos}\"" "$FORMULA"
|
||||
grep -Fq 'https://github.com/bybrooklyn/openbitdo/releases/download/v0.0.1-rc.4/openbitdo-v0.0.1-rc.4-linux-x86_64.tar.gz' "$FORMULA"
|
||||
|
||||
if grep -nE '@[A-Z0-9_]+@' "$PKGBUILD" "$FORMULA"; then
|
||||
echo "rendered metadata still contains template placeholders" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
grep -Fq "TAG=v0.0.1-rc.4" "$CHECKSUMS"
|
||||
grep -Fq "VERSION=0.0.1-rc.4" "$CHECKSUMS"
|
||||
grep -Fq "AUR_PKGVER=0.0.1rc4" "$CHECKSUMS"
|
||||
grep -Fq "LINUX_X86_64_SHA256=${expected_x86}" "$CHECKSUMS"
|
||||
grep -Fq "LINUX_AARCH64_SHA256=${expected_aarch64}" "$CHECKSUMS"
|
||||
grep -Fq "MACOS_ARM64_SHA256=${expected_macos}" "$CHECKSUMS"
|
||||
@@ -1,68 +1,37 @@
|
||||
# Add Device Support (Hardcoded Path)
|
||||
# Add Device Support
|
||||
|
||||
This guide keeps device support simple and explicit: everything is added directly in Rust code.
|
||||
This guide describes the clean-room path for adding or promoting a device.
|
||||
|
||||
## 1) Add/verify PID in hardcoded registry
|
||||
File:
|
||||
- `/Users/brooklyn/data/8bitdo/cleanroom/sdk/crates/bitdo_proto/src/pid_registry_table.rs`
|
||||
## Update The Runtime Catalog
|
||||
|
||||
Add a `PidRegistryRow` with:
|
||||
- `name`
|
||||
- `pid`
|
||||
- `support_level`
|
||||
- `support_tier`
|
||||
- `protocol_family`
|
||||
1. Add or verify the PID row in `sdk/crates/bitdo_proto/src/pid_registry_table.rs`.
|
||||
2. Update capability defaults and support-tier policy in `sdk/crates/bitdo_proto/src/registry.rs`.
|
||||
3. Add or verify command rows in `sdk/crates/bitdo_proto/src/command_registry_table.rs`.
|
||||
4. Update candidate-readonly gating in `sdk/crates/bitdo_proto/src/session.rs` when the new PID needs safe-read diagnostics.
|
||||
|
||||
## 2) Update capability policy
|
||||
File:
|
||||
- `/Users/brooklyn/data/8bitdo/cleanroom/sdk/crates/bitdo_proto/src/registry.rs`
|
||||
## Update The Sanitized Evidence
|
||||
|
||||
Update `default_capability_for(...)` and support-tier PID lists so capability flags match evidence.
|
||||
Keep the spec and evidence artifacts aligned:
|
||||
|
||||
## 3) Add/verify command declarations
|
||||
File:
|
||||
- `/Users/brooklyn/data/8bitdo/cleanroom/sdk/crates/bitdo_proto/src/command_registry_table.rs`
|
||||
- `spec/device_name_catalog.md`
|
||||
- `spec/protocol_spec.md`
|
||||
- `process/device_name_sources.md`
|
||||
- dossier and matrix artifacts where applicable
|
||||
|
||||
Add/verify command rows:
|
||||
- `id`
|
||||
- `safety_class`
|
||||
- `confidence`
|
||||
- `experimental_default`
|
||||
- `report_id`
|
||||
- `request`
|
||||
- `expected_response`
|
||||
- `applies_to`
|
||||
- `operation_group`
|
||||
## Update Tests
|
||||
|
||||
## 4) Confirm runtime policy
|
||||
Runtime policy is derived in code (not scripts):
|
||||
- `confirmed` -> enabled by default
|
||||
- inferred `SafeRead` -> experimental-gated
|
||||
- inferred `SafeWrite`/unsafe -> blocked until confirmed
|
||||
At minimum, touch the tests that prove:
|
||||
|
||||
File:
|
||||
- `/Users/brooklyn/data/8bitdo/cleanroom/sdk/crates/bitdo_proto/src/registry.rs`
|
||||
- support-tier gating is correct
|
||||
- command/runtime policy is correct
|
||||
- diagnostics or mapping behavior is correct for the new device family
|
||||
|
||||
## 5) Update candidate gating allowlists
|
||||
File:
|
||||
- `/Users/brooklyn/data/8bitdo/cleanroom/sdk/crates/bitdo_proto/src/session.rs`
|
||||
## Validation
|
||||
|
||||
Update `is_command_allowed_for_candidate_pid(...)` so detect/diag behavior for the new PID is explicit.
|
||||
From `cleanroom/sdk`:
|
||||
|
||||
## 6) Keep spec artifacts in sync
|
||||
Files:
|
||||
- `/Users/brooklyn/data/8bitdo/cleanroom/spec/pid_matrix.csv`
|
||||
- `/Users/brooklyn/data/8bitdo/cleanroom/spec/command_matrix.csv`
|
||||
- `/Users/brooklyn/data/8bitdo/cleanroom/spec/evidence_index.csv`
|
||||
- `/Users/brooklyn/data/8bitdo/cleanroom/spec/dossiers/...`
|
||||
|
||||
## 7) Add tests
|
||||
- Extend candidate gating tests:
|
||||
- `/Users/brooklyn/data/8bitdo/cleanroom/sdk/tests/candidate_readonly_gating.rs`
|
||||
- Extend runtime policy tests:
|
||||
- `/Users/brooklyn/data/8bitdo/cleanroom/sdk/tests/runtime_policy.rs`
|
||||
|
||||
## 8) Validation
|
||||
From `/Users/brooklyn/data/8bitdo/cleanroom/sdk`:
|
||||
- `cargo test --workspace --all-targets`
|
||||
- `./scripts/cleanroom_guard.sh`
|
||||
```bash
|
||||
./scripts/cleanroom_guard.sh
|
||||
cargo clippy --workspace --all-targets -- -D warnings
|
||||
cargo test --workspace --all-targets
|
||||
```
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
# AUR Publish SSH Troubleshooting
|
||||
# AUR Publish Troubleshooting
|
||||
|
||||
This runbook focuses on resolving AUR publish failures such as `Permission denied (publickey)` in release workflows.
|
||||
Use this runbook when the AUR release path fails, especially on SSH authentication.
|
||||
|
||||
## Preconditions
|
||||
- `AUR_USERNAME` secret exists.
|
||||
- `AUR_SSH_PRIVATE_KEY` secret exists and contains the full private key block.
|
||||
- Runner can reach `aur.archlinux.org:22`.
|
||||
## Typical Failure Signatures
|
||||
|
||||
## 1) Key format and permissions checks
|
||||
Run on a secure local shell before updating secrets:
|
||||
- `Permission denied (publickey)`
|
||||
- `Host key verification failed`
|
||||
- missing `AUR_USERNAME`
|
||||
- missing `AUR_SSH_PRIVATE_KEY`
|
||||
|
||||
## Local SSH Sanity Check
|
||||
|
||||
```bash
|
||||
mkdir -p /tmp/aur-debug && cd /tmp/aur-debug
|
||||
@@ -20,10 +21,11 @@ ssh-keygen -y -f aur_key >/tmp/aur_key.pub
|
||||
```
|
||||
|
||||
Expected:
|
||||
- `ssh-keygen -y` succeeds.
|
||||
- no passphrase prompt for CI use.
|
||||
|
||||
## 2) Known hosts and host verification
|
||||
- the key parses successfully
|
||||
- no CI-incompatible passphrase prompt
|
||||
|
||||
## Known Hosts Check
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.ssh && chmod 700 ~/.ssh
|
||||
@@ -31,40 +33,27 @@ ssh-keyscan -H aur.archlinux.org >> ~/.ssh/known_hosts
|
||||
chmod 600 ~/.ssh/known_hosts
|
||||
```
|
||||
|
||||
Expected:
|
||||
- `aur.archlinux.org` host key is present in `known_hosts`.
|
||||
|
||||
## 3) SSH dry-run authentication
|
||||
## Remote Auth Check
|
||||
|
||||
```bash
|
||||
ssh -i /tmp/aur-debug/aur_key \
|
||||
-o IdentitiesOnly=yes \
|
||||
-o StrictHostKeyChecking=yes \
|
||||
${AUR_USERNAME}@aur.archlinux.org
|
||||
"${AUR_USERNAME}@aur.archlinux.org"
|
||||
```
|
||||
|
||||
Expected success signature:
|
||||
- authentication accepted (AUR may close session after auth; that still proves key acceptance).
|
||||
An immediate disconnect after auth is still acceptable. It proves the key is valid.
|
||||
|
||||
Expected failure signatures:
|
||||
- `Permission denied (publickey)` means wrong key/user pairing.
|
||||
- `Host key verification failed` means known_hosts mismatch/missing.
|
||||
|
||||
## 4) Repo-level publish dry run
|
||||
For package repo:
|
||||
## Repo Check
|
||||
|
||||
```bash
|
||||
git ls-remote ssh://${AUR_USERNAME}@aur.archlinux.org/openbitdo-bin.git
|
||||
git ls-remote "ssh://${AUR_USERNAME}@aur.archlinux.org/openbitdo-bin.git"
|
||||
```
|
||||
|
||||
Expected:
|
||||
- command returns refs without auth failures.
|
||||
If this fails, the AUR account or key pairing is still wrong.
|
||||
|
||||
## 5) CI secret update checklist
|
||||
- Store private key in `AUR_SSH_PRIVATE_KEY` exactly as multiline PEM/OpenSSH block.
|
||||
- Store account name in `AUR_USERNAME`.
|
||||
- Re-run release workflow preflight job.
|
||||
## After The Fix
|
||||
|
||||
## 6) Post-fix validation
|
||||
- Confirm release preflight no longer fails on SSH auth.
|
||||
- Confirm `publish-aur` job pushes `openbitdo-bin` metadata repo.
|
||||
- rerun the release workflow
|
||||
- confirm `publish-aur` succeeds
|
||||
- confirm `openbitdo-bin` points at the new release tag
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
# Branch and Merge Policy
|
||||
# Branch Policy
|
||||
|
||||
Because this workspace currently has no active Git repository metadata, this policy is documented for use when repository control is re-enabled.
|
||||
## Defaults
|
||||
|
||||
## Branches
|
||||
- `codex/dirtyroom-spec`: sanitize findings into `cleanroom/spec` and `cleanroom/process`
|
||||
- `codex/cleanroom-sdk`: implement SDK and CLI from sanitized artifacts only
|
||||
- default branch: `main`
|
||||
- automation/worktree branches: `codex/*`
|
||||
- release tags: `v*`
|
||||
|
||||
## Merge Strategy
|
||||
- Cherry-pick sanitized spec commits from dirtyroom branch into cleanroom branch.
|
||||
- Never merge dirty-room evidence paths into cleanroom implementation branch.
|
||||
## Merge Expectations
|
||||
|
||||
- clean-room implementation stays in `cleanroom/`
|
||||
- dirty-room or decompiler material never lands in runtime, tests, docs, or workflows inside this tree
|
||||
- release tags are created from commits that are already on `main`
|
||||
|
||||
## Review Checklist
|
||||
- Guard script passes.
|
||||
- No forbidden path references in code/tests.
|
||||
- Requirement IDs are traceable from implementation and tests.
|
||||
|
||||
- clean-room guard passes
|
||||
- no forbidden path references were introduced
|
||||
- docs and release metadata are consistent with the current RC
|
||||
- required CI checks stay green
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
# Clean-Room Rules
|
||||
|
||||
## Allowed Inputs During Clean Implementation
|
||||
- `cleanroom/spec/**`
|
||||
- `cleanroom/process/cleanroom_rules.md`
|
||||
- `cleanroom/harness/golden/**`
|
||||
## Allowed Inputs
|
||||
|
||||
## Forbidden Inputs During Clean Implementation
|
||||
- `decompiled/**`
|
||||
- `decompiled_*/*`
|
||||
- `bundle_extract/**`
|
||||
- `extracted/**`
|
||||
- `extracted_net/**`
|
||||
- `session-ses_35e4.md`
|
||||
- `cleanroom/spec/**`
|
||||
- `cleanroom/process/**`
|
||||
- approved harness fixtures and generated release artifacts
|
||||
|
||||
## Forbidden Inputs
|
||||
|
||||
- decompiled vendor code
|
||||
- copied proprietary snippets
|
||||
- direct references to dirty-room paths from clean implementation or user-facing docs
|
||||
|
||||
## Enforcement
|
||||
- `cleanroom/sdk/scripts/cleanroom_guard.sh` checks for forbidden path and token references.
|
||||
- CI runs the guard before test jobs.
|
||||
|
||||
- `cleanroom/sdk/scripts/cleanroom_guard.sh` scans for forbidden references
|
||||
- CI runs the guard before packaging and test jobs
|
||||
|
||||
## Commit Hygiene
|
||||
- No copied decompiled code snippets.
|
||||
- No direct references to dirty-room files in SDK implementation/tests.
|
||||
- Any new protocol fact must be added to sanitized spec artifacts first.
|
||||
|
||||
- no copied decompiled code
|
||||
- no raw vendor-source excerpts
|
||||
- new protocol facts must arrive through sanitized spec or evidence updates first
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
# OpenBitdo Commenting Standard
|
||||
# Commenting Standard
|
||||
|
||||
This project prefers concise, high-context comments.
|
||||
OpenBitdo prefers sparse, high-value comments.
|
||||
|
||||
## Required Comment Zones
|
||||
- Command gating order and rationale (`bitdo_proto::session`).
|
||||
- Support-tier decisions and promotion boundaries (`candidate-readonly` vs `full`).
|
||||
- Unsafe/firmware blocking rules and brick-risk protections.
|
||||
- Retry/fallback behavior where multiple command paths exist.
|
||||
- State-machine transitions in TUI/app-core flows when transitions are non-obvious.
|
||||
## Add Comments When
|
||||
|
||||
## Avoid
|
||||
- Trivial comments that restate code syntax.
|
||||
- Comment blocks that drift from behavior and are not maintained.
|
||||
- safety or brick-risk behavior is non-obvious
|
||||
- support-tier gating would be easy to misread
|
||||
- retries, fallbacks, or validator behavior need rationale
|
||||
- a state transition matters more than the literal code line
|
||||
|
||||
## Rule of Thumb
|
||||
If someone adding a new device could misread a policy or safety boundary, comment it.
|
||||
## Avoid Comments When
|
||||
|
||||
- the code already says the same thing clearly
|
||||
- the comment would become stale as soon as names or branches change
|
||||
- the comment explains syntax instead of intent
|
||||
|
||||
## Rule Of Thumb
|
||||
|
||||
If a future contributor could accidentally weaken a safety boundary, the surrounding code deserves a short comment.
|
||||
|
||||
@@ -1,30 +1,25 @@
|
||||
# Community Evidence Intake
|
||||
|
||||
## Purpose
|
||||
Collect hardware and protocol evidence from the community in a clean-room-safe format.
|
||||
This process collects safe, sanitized device evidence from users and testers.
|
||||
|
||||
## Submission Requirements
|
||||
Every report must include:
|
||||
- Device name
|
||||
- VID/PID (`0xVVVV:0xPPPP`)
|
||||
- Firmware version shown by official software/device
|
||||
- Operation attempted
|
||||
- Sanitized request/response shape description
|
||||
- Reproducibility notes (steps, OS, transport mode)
|
||||
## Required Submission Data
|
||||
|
||||
- device name
|
||||
- VID/PID in `0xVVVV:0xPPPP` form
|
||||
- firmware version
|
||||
- operation attempted
|
||||
- sanitized request or response description
|
||||
- OS, transport mode, and reproducibility notes
|
||||
|
||||
## Prohibited Content
|
||||
- Raw copied decompiled code.
|
||||
- Vendor source snippets.
|
||||
- Binary dumps with proprietary content not required for protocol structure.
|
||||
|
||||
## Acceptance Levels
|
||||
- `intake`: report received, unverified.
|
||||
- `triaged`: mapped to a PID/operation group and requirement IDs.
|
||||
- `accepted`: converted into sanitized dossier/spec updates.
|
||||
- raw decompiled code
|
||||
- copied vendor source snippets
|
||||
- proprietary dumps that are not sanitized into structure-level notes
|
||||
|
||||
## Maintainer Processing
|
||||
1. Validate report format.
|
||||
2. Cross-reference PID with `spec/pid_matrix.csv`.
|
||||
3. Create/update `spec/dossiers/<pid_hex>/*.toml`.
|
||||
4. Update `spec/evidence_index.csv` and command/pid matrices.
|
||||
5. Keep device as `candidate-readonly` until full 3-signal promotion gate is met.
|
||||
## Maintainer Flow
|
||||
|
||||
1. validate the report format
|
||||
2. map it to a known PID or create a new sanitized record
|
||||
3. update the relevant spec or dossier artifacts
|
||||
4. keep the device read-only until runtime and hardware confirmation justify promotion
|
||||
|
||||
@@ -1,33 +1,38 @@
|
||||
# Device Name Sources
|
||||
|
||||
This index lists sanitized naming sources used to build `/Users/brooklyn/data/8bitdo/cleanroom/spec/device_name_catalog.md`.
|
||||
This index explains where canonical device names came from and how confident the project is in them.
|
||||
|
||||
## Primary dirty-room references
|
||||
- `DR-1`: Decompiled PID constants table (`VIDPID`) in `/Users/brooklyn/data/8bitdo/decompiled_dll/8BitDo_Ultimate_Software_V2.decompiled.cs` around line 194289.
|
||||
- `DR-2`: Decompiled device name resolver (`getName()`) in `/Users/brooklyn/data/8bitdo/decompiled_dll/8BitDo_Ultimate_Software_V2.decompiled.cs` around line 12249.
|
||||
- `DR-3`: Decompiled language map (`LanguageTools`) in `/Users/brooklyn/data/8bitdo/decompiled_dll/8BitDo_Ultimate_Software_V2.decompiled.cs` around line 206277.
|
||||
## Source Classes
|
||||
|
||||
## Official 8BitDo web cross-check references
|
||||
- `WEB-1`: [8BitDo product catalog](https://www.8bitdo.com/#Products)
|
||||
- `WEB-2`: [Ultimate 2 Wireless Controller](https://www.8bitdo.com/ultimate-2-wireless-controller/)
|
||||
- `WEB-3`: [Ultimate 2 Bluetooth Controller](https://www.8bitdo.com/ultimate-2-bluetooth-controller/)
|
||||
- `WEB-4`: [Ultimate 2C Wireless Controller](https://www.8bitdo.com/ultimate-2c-wireless-controller/)
|
||||
- `WEB-5`: [Ultimate 2C Bluetooth Controller](https://www.8bitdo.com/ultimate-2c-bluetooth-controller/)
|
||||
- `WEB-6`: [Pro 2 Bluetooth Controller](https://www.8bitdo.com/pro2/)
|
||||
- `WEB-7`: [Retro 108 Mechanical Keyboard](https://www.8bitdo.com/retro-108-mechanical-keyboard/)
|
||||
- `WEB-8`: [Retro 87 Mechanical Keyboard - Xbox Edition](https://www.8bitdo.com/retro-87-mechanical-keyboard-xbox/)
|
||||
- `WEB-9`: [Retro R8 Mouse - Xbox Edition](https://www.8bitdo.com/retro-r8-mouse-xbox/)
|
||||
- `WEB-10`: [Arcade Controller](https://www.8bitdo.com/arcade-controller/)
|
||||
- `WEB-11`: [64 Bluetooth Controller](https://www.8bitdo.com/64-controller/)
|
||||
- `WEB-12`: [Retro Mechanical Keyboard N Edition](https://www.8bitdo.com/retro-mechanical-keyboard/)
|
||||
- sanitized dirty-room references from internal naming tables
|
||||
- official 8BitDo product pages
|
||||
- project-maintained fallback names when neither source is strong enough for a public label
|
||||
|
||||
## Confidence policy
|
||||
- `high`: direct match in `DR-2/DR-3` and/or product page exact-name match.
|
||||
- `medium`: strong inferred match from product family naming with at least one source anchor.
|
||||
- `low`: internal fallback name because no confident public marketing name was found.
|
||||
## Confidence Policy
|
||||
|
||||
## Low-confidence naming convention
|
||||
- Canonical wording for low-confidence rows is:
|
||||
- `Unconfirmed Internal Device (PID_*)`
|
||||
- `Unconfirmed Variant Name (PID_*)`
|
||||
- `Unconfirmed Interface Name (PID_*)`
|
||||
- `high`: exact or near-exact public confirmation
|
||||
- `medium`: strong inferred match from family and naming context
|
||||
- `low`: fallback wording kept intentionally conservative
|
||||
|
||||
## Low-Confidence Naming Convention
|
||||
|
||||
Use conservative labels such as:
|
||||
|
||||
- `Unconfirmed Internal Device (...)`
|
||||
- `Unconfirmed Variant Name (...)`
|
||||
- `Unconfirmed Interface Name (...)`
|
||||
|
||||
## Current Official Cross-Checks
|
||||
|
||||
- [8BitDo product catalog](https://www.8bitdo.com/#Products)
|
||||
- [Ultimate 2 Wireless Controller](https://www.8bitdo.com/ultimate-2-wireless-controller/)
|
||||
- [Ultimate 2 Bluetooth Controller](https://www.8bitdo.com/ultimate-2-bluetooth-controller/)
|
||||
- [Ultimate 2C Wireless Controller](https://www.8bitdo.com/ultimate-2c-wireless-controller/)
|
||||
- [Ultimate 2C Bluetooth Controller](https://www.8bitdo.com/ultimate-2c-bluetooth-controller/)
|
||||
- [Pro 2 Bluetooth Controller](https://www.8bitdo.com/pro2/)
|
||||
- [Retro 108 Mechanical Keyboard](https://www.8bitdo.com/retro-108-mechanical-keyboard/)
|
||||
- [Retro 87 Mechanical Keyboard - Xbox Edition](https://www.8bitdo.com/retro-87-mechanical-keyboard-xbox/)
|
||||
- [Retro R8 Mouse - Xbox Edition](https://www.8bitdo.com/retro-r8-mouse-xbox/)
|
||||
- [Arcade Controller](https://www.8bitdo.com/arcade-controller/)
|
||||
- [64 Bluetooth Controller](https://www.8bitdo.com/64-controller/)
|
||||
- [Retro Mechanical Keyboard N Edition](https://www.8bitdo.com/retro-mechanical-keyboard/)
|
||||
|
||||
@@ -1,60 +1,40 @@
|
||||
# Dirty-Room Collection Playbook (Decompiler-First Expansion)
|
||||
# Dirty-Room Collection Playbook
|
||||
|
||||
This playbook describes how dirty-room evidence is gathered and sanitized before the clean-room implementation consumes it.
|
||||
|
||||
## Goal
|
||||
Create sanitized, requirement-linked evidence that expands device detect/diagnostics support without contaminating clean-room implementation.
|
||||
|
||||
## Scope of This Wave
|
||||
- Evidence source: decompiler/static-only.
|
||||
- Target: Wave 2 +12 popularity cohort (plus previously tracked candidate-readonly set).
|
||||
- Promotion policy: no new `full` promotions in this wave.
|
||||
- Output artifacts: `spec/dossiers/**`, `spec/evidence_index.csv`, updated `spec/*.csv`, updated `requirements.yaml`.
|
||||
Produce sanitized, requirement-linked evidence that can expand detect, diagnostics, mapping, or firmware understanding without copying vendor material into the runtime.
|
||||
|
||||
## Allowed Dirty-Room Inputs
|
||||
- `/Users/brooklyn/data/8bitdo/decompiled_dll/8BitDo_Ultimate_Software_V2.decompiled.cs`
|
||||
- `/Users/brooklyn/data/8bitdo/decompiled/*.cs`
|
||||
- `/Users/brooklyn/data/8bitdo/decompiled_autoupdate/*.cs`
|
||||
- Existing dirty-room transcript files under `/Users/brooklyn/data/8bitdo/`
|
||||
## Allowed Inputs
|
||||
|
||||
## Required Sanitization Rules
|
||||
- Do not copy raw vendor/decompiled code snippets into clean artifacts.
|
||||
- Record only sanitized structure-level findings:
|
||||
- command intent
|
||||
- request/response byte-shape
|
||||
- validator expectations
|
||||
- gating/policy notes
|
||||
- Use requirement IDs only (`REQ-DR-*`, `REQ-PROM-*`, `REQ-COMM-*`, `REQ-GH-*`).
|
||||
- approved decompiler outputs and existing dirty-room transcripts
|
||||
- official public web pages used for naming or marketing confirmation
|
||||
|
||||
## Required Sanitization
|
||||
|
||||
Record only structure-level findings:
|
||||
|
||||
- command intent
|
||||
- request and response shape
|
||||
- validator expectations
|
||||
- retry or failure behavior
|
||||
- promotion or safety notes
|
||||
|
||||
Do not copy vendor code or raw proprietary snippets.
|
||||
|
||||
## Dossier Workflow
|
||||
1. Pick PID and operation group.
|
||||
2. Collect static evidence anchors (class/function names and behavior summaries).
|
||||
3. Derive sanitized command mapping and validation expectations.
|
||||
4. Write TOML dossier in `spec/dossiers/<pid_hex>/<operation_group>.toml`.
|
||||
5. Link dossier ID into `spec/command_matrix.csv` (`dossier_id` column).
|
||||
6. Update `spec/evidence_index.csv`.
|
||||
7. Ensure each Wave 2 PID has all three required dossier files:
|
||||
- `core_diag.toml`
|
||||
- `mode_or_profile_read.toml`
|
||||
- `firmware_preflight.toml`
|
||||
|
||||
## Authoring Approach (No Helper Scripts)
|
||||
- Dossiers and matrix updates are maintained directly in repository source files.
|
||||
- `spec/evidence_index.csv` is updated manually with deterministic ordering.
|
||||
- Validation is performed through normal repository review plus workspace tests.
|
||||
1. choose a PID and operation group
|
||||
2. collect anchors and summarize them
|
||||
3. create or update the sanitized dossier
|
||||
4. link the dossier from the relevant matrix rows
|
||||
5. update evidence indexes and notes
|
||||
|
||||
## Confidence Rules
|
||||
- `confirmed`: requires static + runtime + hardware confirmation (not achievable in this wave).
|
||||
- `inferred`: static-only or partial confidence.
|
||||
- For this wave, new entries should remain `inferred` unless already confirmed historically.
|
||||
## Promotion Rule
|
||||
|
||||
## Promotion Gate
|
||||
A device can move from `candidate-readonly` to `full` only when all three are true:
|
||||
1. static evidence complete
|
||||
2. runtime trace evidence complete
|
||||
3. hardware read/write/readback complete
|
||||
Moving from `read-only candidate` to `supported` requires:
|
||||
|
||||
## Review Checklist
|
||||
- Dossier contains required fields from schema.
|
||||
- Requirement linkage is explicit.
|
||||
- No raw decompiled text/snippets are present.
|
||||
- `support_tier` remains `candidate-readonly` for new no-hardware devices.
|
||||
- Runtime and hardware placeholders are populated with concrete promotion evidence tasks.
|
||||
1. static evidence
|
||||
2. runtime traces
|
||||
3. hardware confirmation
|
||||
|
||||
@@ -1,56 +1,30 @@
|
||||
# Dirty-Room Dossier Schema
|
||||
|
||||
Each dossier file is TOML and must include these fields.
|
||||
Each dossier is a TOML file that captures sanitized protocol evidence for one PID and one operation group.
|
||||
|
||||
## Required Fields
|
||||
- `dossier_id`: stable identifier, e.g. `DOS-5200-CORE`.
|
||||
- `pid_hex`: target PID in hex (`0xNNNN`).
|
||||
- `operation_group`: logical grouping (`CoreDiag`, `ModeProfileRead`, `FirmwarePreflight`, etc).
|
||||
- `command_id`: array of command IDs scoped by this dossier.
|
||||
- `request_shape`: sanitized request structure summary.
|
||||
- `response_shape`: sanitized response structure summary.
|
||||
- `validator_rules`: array of response validation constraints.
|
||||
- `retry_behavior`: retry and timeout behavior summary.
|
||||
- `failure_signatures`: array of known failure signatures.
|
||||
- `evidence_source`: `static` for this wave.
|
||||
- `confidence`: `inferred` or `confirmed`.
|
||||
- `requirement_ids`: array of linked requirement IDs.
|
||||
- `state_machine`: table with `pre_state`, `action`, `post_state`, and `invalid_transitions`.
|
||||
- `runtime_placeholder`: table with `required` and `evidence_needed`.
|
||||
- `hardware_placeholder`: table with `required` and `evidence_needed`.
|
||||
|
||||
- `dossier_id`
|
||||
- `pid_hex`
|
||||
- `operation_group`
|
||||
- `command_id`
|
||||
- `request_shape`
|
||||
- `response_shape`
|
||||
- `validator_rules`
|
||||
- `retry_behavior`
|
||||
- `failure_signatures`
|
||||
- `evidence_source`
|
||||
- `confidence`
|
||||
- `requirement_ids`
|
||||
- `state_machine`
|
||||
- `runtime_placeholder`
|
||||
- `hardware_placeholder`
|
||||
|
||||
## Optional Fields
|
||||
- `class_family`: static class-family grouping hints.
|
||||
- `notes`: additional sanitized context.
|
||||
|
||||
## Example
|
||||
```toml
|
||||
dossier_id = "DOS-5200-CORE"
|
||||
pid_hex = "0x5200"
|
||||
operation_group = "CoreDiag"
|
||||
command_id = ["GetPid", "GetReportRevision", "GetControllerVersion", "Version", "Idle"]
|
||||
request_shape = "64-byte HID report, command byte in report[1], PID-specific gating outside payload"
|
||||
response_shape = "short status header plus optional payload bytes"
|
||||
validator_rules = ["byte0 == 0x02", "response length >= 4"]
|
||||
retry_behavior = "retry up to configured max attempts on timeout/malformed response"
|
||||
failure_signatures = ["timeout", "malformed response", "unsupported command for pid"]
|
||||
evidence_source = "static"
|
||||
confidence = "inferred"
|
||||
requirement_ids = ["REQ-DR-001", "REQ-PROM-001", "REQ-PID-002"]
|
||||
class_family = "JP/Handshake path"
|
||||
notes = "candidate-readonly in this wave"
|
||||
- `class_family`
|
||||
- `notes`
|
||||
|
||||
[state_machine]
|
||||
pre_state = "DeviceConnected"
|
||||
action = "Run core diagnostics reads"
|
||||
post_state = "DeviceIdentified"
|
||||
invalid_transitions = ["NoDevice", "TransportClosed", "BootloaderOnly"]
|
||||
## Authoring Rule
|
||||
|
||||
[runtime_placeholder]
|
||||
required = true
|
||||
evidence_needed = ["runtime request/response captures", "error signature examples"]
|
||||
|
||||
[hardware_placeholder]
|
||||
required = true
|
||||
evidence_needed = ["physical read validation", "repeatability checks"]
|
||||
```
|
||||
Prefer short, structure-level descriptions over long prose. The dossier should be good enough to guide clean implementation and testing without embedding dirty-room source text.
|
||||
|
||||
@@ -1,50 +1,18 @@
|
||||
# Dirty-Room Evidence Backlog
|
||||
|
||||
## Purpose
|
||||
This backlog tracks the next protocol-evidence areas that would most improve runtime confidence.
|
||||
|
||||
Track future dirty-room evidence work for protocol expansion in a structured way, so new functionality can be translated into sanitized clean-room specs without contaminating implementation code.
|
||||
## Priority Areas
|
||||
|
||||
## Clean-Room Boundaries
|
||||
1. read-only candidate expansion for additional controller families
|
||||
2. deeper JP108 mapping confirmation
|
||||
3. deeper Ultimate 2 profile and slot behavior confirmation
|
||||
4. firmware trace and recovery evidence across supported devices
|
||||
5. runtime and hardware evidence needed to promote candidate devices
|
||||
|
||||
- Dirty-room analysis may use approved evidence sources.
|
||||
- Clean implementation must consume only sanitized artifacts in `spec/` and approved harness data.
|
||||
- No raw dirty-room snippets, copied code, or direct decompiled fragments may be carried into clean implementation files.
|
||||
## Expected Outputs
|
||||
|
||||
## Prioritized Backlog
|
||||
|
||||
1. Wave-2 candidate-readonly expansion (decompiler-first):
|
||||
- Popularity +12 PIDs:
|
||||
- `0x3100`, `0x3105`, `0x2100`, `0x2101`, `0x901a`, `0x6006`
|
||||
- `0x5203`, `0x5204`, `0x301a`, `0x9028`, `0x3026`, `0x3027`
|
||||
- Deliverable posture: detect/diag-only (`candidate-readonly`), no firmware transfer/write promotion.
|
||||
2. Wave-1 candidate-readonly follow-through:
|
||||
- Primary 14 PIDs:
|
||||
- `0x6002`, `0x6003`, `0x3010`, `0x3011`, `0x3012`, `0x3013`
|
||||
- `0x5200`, `0x5201`, `0x203a`, `0x2049`, `0x2028`, `0x202e`
|
||||
- `0x3004`, `0x3019`
|
||||
- Stretch PIDs:
|
||||
- `0x3021`, `0x2039`, `0x2056`, `0x5205`, `0x5206`
|
||||
- Deliverable posture: stay candidate-readonly until runtime and hardware evidence is accepted.
|
||||
3. JP108 deeper mapping coverage:
|
||||
- Expand dedicated key mapping confirmation beyond the current A/B/K1-K8 baseline.
|
||||
- Confirm feature and voice command behavior with stronger request/response confidence.
|
||||
4. Ultimate2 advanced paths:
|
||||
- Expand confidence for advanced slot/config interactions and additional profile behaviors.
|
||||
- Confirm edge cases for mode transitions and per-slot persistence.
|
||||
5. Firmware trace confidence:
|
||||
- Increase confidence for bootloader enter/chunk/commit/exit behavior across supported target variants.
|
||||
- Capture and sanitize additional failure and recovery traces.
|
||||
|
||||
## Required Sanitized Outputs
|
||||
|
||||
- Update `spec/protocol_spec.md` for any newly confirmed operation groups or behavior rules.
|
||||
- Update `spec/requirements.yaml` with new stable requirement IDs.
|
||||
- Update `spec/command_matrix.csv` and `spec/pid_matrix.csv` as evidence confidence changes.
|
||||
- Add or refresh sanitized harness fixtures under `harness/golden/` for replay and regression tests.
|
||||
|
||||
## Review Checklist Before Clean Implementation
|
||||
|
||||
- Sanitized evidence is traceable to requirement IDs.
|
||||
- Command confidence levels are explicit (`confirmed` vs `inferred`).
|
||||
- PID capability changes are reflected in matrices.
|
||||
- No raw-source text is present in clean implementation artifacts.
|
||||
- updated spec and requirement references
|
||||
- refreshed command and PID matrices
|
||||
- sanitized dossier updates
|
||||
- optional harness fixtures where they improve regression coverage
|
||||
|
||||
@@ -1,23 +1,15 @@
|
||||
# Wave 1 Baseline Snapshot
|
||||
|
||||
Generated: 2026-02-28
|
||||
Generated on 2026-02-28.
|
||||
|
||||
## Hardware Access Baseline
|
||||
- Available hardware lines: JP108 + Ultimate2.
|
||||
- Exact attached PID variants: pending local identify run on connected hardware.
|
||||
- Temporary lab fixture defaults remain:
|
||||
- JP108: `0x5209`
|
||||
- Ultimate2: `0x6012`
|
||||
## Baseline
|
||||
|
||||
## Required Next Verification Step
|
||||
Run identify flow with connected hardware and confirm fixture PIDs:
|
||||
1. `cargo test --workspace --test hardware_smoke -- --ignored --exact hardware_smoke_detect_devices`
|
||||
2. `./scripts/run_hardware_smoke.sh` with `BITDO_REQUIRED_SUITE=108jp`
|
||||
3. `./scripts/run_hardware_smoke.sh` with `BITDO_REQUIRED_SUITE=ultimate2`
|
||||
- owned fixture families: JP108 and Ultimate 2
|
||||
- existing supported paths were limited to hardware-confirmed devices
|
||||
- newly expanded devices were intentionally kept read-only
|
||||
|
||||
If detected variants differ, update `harness/lab/device_lab.yaml` fixture PIDs immediately.
|
||||
## Expected Follow-Up
|
||||
|
||||
## Support Baseline
|
||||
- Existing `full` paths: JP108/Ultimate2 and previously confirmed families.
|
||||
- New expansion wave devices remain `candidate-readonly` (detect/diag only).
|
||||
- No new firmware/write enablement for no-hardware targets.
|
||||
- capture runtime traces
|
||||
- confirm real hardware behavior
|
||||
- promote devices only after static, runtime, and hardware evidence align
|
||||
|
||||
@@ -1,23 +1,9 @@
|
||||
# Wave 1 Results (Template)
|
||||
# Wave 1 Results
|
||||
|
||||
Generated: 2026-02-28
|
||||
Generated on 2026-02-28.
|
||||
|
||||
## Summary
|
||||
- Primary target PIDs processed: 14
|
||||
- Stretch target PIDs processed: TBD
|
||||
- New `full` promotions: 0 (expected in decompiler-only wave)
|
||||
## Outcome
|
||||
|
||||
## Deliverables
|
||||
- Dossiers created: `spec/dossiers/**`
|
||||
- Evidence index updated: `spec/evidence_index.csv`
|
||||
- Matrices updated: `spec/pid_matrix.csv`, `spec/command_matrix.csv`
|
||||
- Requirements updated: `spec/requirements.yaml`
|
||||
|
||||
## Validation
|
||||
- `cargo test --workspace --all-targets`: pending
|
||||
- `./scripts/cleanroom_guard.sh`: pending
|
||||
- Detect/diag targeted tests: pending
|
||||
|
||||
## Follow-Up
|
||||
- Collect runtime traces for candidate-readonly devices.
|
||||
- Run hardware confirmation on each candidate before promotion to `full`.
|
||||
- Wave 1 produced sanitized evidence and candidate-readonly expansion work.
|
||||
- No new device families were promoted directly to full support.
|
||||
- Follow-up work remained runtime traces and hardware confirmation.
|
||||
|
||||
@@ -1,32 +1,17 @@
|
||||
# Wave 2 Baseline (Frozen)
|
||||
# Wave 2 Baseline
|
||||
|
||||
## Snapshot Date
|
||||
- 2026-03-01
|
||||
Snapshot date: 2026-03-01.
|
||||
|
||||
## Pre-Wave Counts (Frozen)
|
||||
- `spec/pid_matrix.csv` rows: 59
|
||||
- Support tier counts (pre-wave):
|
||||
- `full`: 14
|
||||
- `candidate-readonly`: 15
|
||||
- `detect-only`: 30
|
||||
- `spec/command_matrix.csv` rows (pre-wave): 37
|
||||
## Baseline Assumptions
|
||||
|
||||
## Hardware Reality (Current)
|
||||
- Available fixtures: JP108 line and Ultimate2 line only.
|
||||
- Non-owned devices must remain `candidate-readonly` until strict promotion signals are complete.
|
||||
|
||||
## Required Checks Baseline
|
||||
Branch protection for `main` must require:
|
||||
- `guard`
|
||||
- `aur-validate`
|
||||
- `tui-smoke-test`
|
||||
- `build-macos-arm64`
|
||||
- `test`
|
||||
- `hardware-108jp`
|
||||
- `hardware-ultimate2`
|
||||
- hardware ownership still covered only the JP108 and Ultimate 2 lines
|
||||
- newly researched PIDs had to remain read-only until confirmation improved
|
||||
- release gates stayed anchored on `guard`, `aur-validate`, `tui-smoke-test`, `build-macos-arm64`, and `test`
|
||||
|
||||
## Promotion Policy
|
||||
Promotion from `candidate-readonly` to `full` requires all 3 signals:
|
||||
1. static dossier evidence,
|
||||
2. runtime sanitized traces,
|
||||
3. hardware read/write/readback confirmation.
|
||||
|
||||
Promotion from `read-only candidate` to `supported` requires:
|
||||
|
||||
1. static evidence
|
||||
2. runtime evidence
|
||||
3. hardware evidence
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
# Wave 2 PID Scorecard
|
||||
|
||||
Legend:
|
||||
- Static: dossier + matrix linkage complete.
|
||||
- Runtime: sanitized runtime traces accepted.
|
||||
- Hardware: read/write/readback confirmed on owned fixture.
|
||||
- Gate: promotion blocker status.
|
||||
|
||||
- `Static`: dossier and matrix linkage complete
|
||||
- `Runtime`: sanitized runtime traces accepted
|
||||
- `Hardware`: real-device confirmation accepted
|
||||
- `Gate`: reason promotion remains blocked
|
||||
|
||||
| PID | Device | Tier | Static | Runtime | Hardware | Gate |
|
||||
|---|---|---|---|---|---|---|
|
||||
| `0x3100` | PID_USB_Ultimate | candidate-readonly | yes | no | no | blocked/no_runtime |
|
||||
| `0x3105` | PID_USB_Ultimate2 | candidate-readonly | yes | no | no | blocked/no_runtime |
|
||||
| `0x2100` | PID_Xcloud | candidate-readonly | yes | no | no | blocked/no_runtime |
|
||||
| `0x2101` | PID_Xcloud2 | candidate-readonly | yes | no | no | blocked/no_runtime |
|
||||
| `0x901a` | PID_ArcadeStick | candidate-readonly | yes | no | no | blocked/no_runtime |
|
||||
| `0x6006` | PID_Pro2_CY | candidate-readonly | yes | no | no | blocked/no_runtime |
|
||||
| `0x5203` | PID_NUMPAD | candidate-readonly | yes | no | no | blocked/no_runtime |
|
||||
| `0x5204` | PID_NUMPADRR | candidate-readonly | yes | no | no | blocked/no_runtime |
|
||||
| `0x301a` | PID_UltimateBT2C | candidate-readonly | yes | no | no | blocked/no_runtime |
|
||||
| `0x9028` | PID_N64RR | candidate-readonly | yes | no | no | blocked/no_runtime |
|
||||
| `0x3026` | PID_XBOXUK | candidate-readonly | yes | no | no | blocked/no_runtime |
|
||||
| `0x3027` | PID_XBOXUKUSB | candidate-readonly | yes | no | no | blocked/no_runtime |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| `0x3100` | `PID_USB_Ultimate` | read-only candidate | yes | no | no | blocked/no_runtime |
|
||||
| `0x3105` | `PID_USB_Ultimate2` | read-only candidate | yes | no | no | blocked/no_runtime |
|
||||
| `0x2100` | `PID_Xcloud` | read-only candidate | yes | no | no | blocked/no_runtime |
|
||||
| `0x2101` | `PID_Xcloud2` | read-only candidate | yes | no | no | blocked/no_runtime |
|
||||
| `0x901a` | `PID_ArcadeStick` | read-only candidate | yes | no | no | blocked/no_runtime |
|
||||
| `0x6006` | `PID_Pro2_CY` | read-only candidate | yes | no | no | blocked/no_runtime |
|
||||
| `0x5203` | `PID_NUMPAD` | read-only candidate | yes | no | no | blocked/no_runtime |
|
||||
| `0x5204` | `PID_NUMPADRR` | read-only candidate | yes | no | no | blocked/no_runtime |
|
||||
| `0x301a` | `PID_UltimateBT2C` | read-only candidate | yes | no | no | blocked/no_runtime |
|
||||
| `0x9028` | `PID_N64RR` | read-only candidate | yes | no | no | blocked/no_runtime |
|
||||
| `0x3026` | `PID_XBOXUK` | read-only candidate | yes | no | no | blocked/no_runtime |
|
||||
| `0x3027` | `PID_XBOXUKUSB` | read-only candidate | yes | no | no | blocked/no_runtime |
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
# Wave 2 Results
|
||||
|
||||
## Scope
|
||||
- Expansion cohort: 12 additional popularity-first PIDs.
|
||||
- Evidence mode: static/decompiler-only.
|
||||
- Support result: all 12 moved to `candidate-readonly` with detect/diag-only behavior.
|
||||
## Outcome
|
||||
|
||||
## Delivered
|
||||
1. Manual, source-controlled dossier and matrix updates (no script-generated artifacts).
|
||||
2. Wave 2 dossier set (`core_diag`, `mode_or_profile_read`, `firmware_preflight`) for each of 12 PIDs.
|
||||
3. `pid_matrix.csv` updated with Wave 2 candidate-readonly tiering.
|
||||
4. `command_matrix.csv` updated with Wave 2 dossier-linked rows and explicit promotion gates.
|
||||
5. `evidence_index.csv` updated from current candidate-readonly set.
|
||||
6. Governance verification completed for variables, labels, and required checks.
|
||||
- twelve additional PIDs were expanded through sanitized static evidence
|
||||
- all twelve remained read-only candidates
|
||||
- no new family was promoted without runtime and hardware confirmation
|
||||
|
||||
## Deferred
|
||||
- Runtime trace evidence for Wave 2 cohort.
|
||||
- Hardware read/write/readback confirmation for Wave 2 cohort.
|
||||
- Any promotion to `full` for Wave 2 cohort.
|
||||
## Deliverables
|
||||
|
||||
## Exit Status
|
||||
- Wave 2 static-only deliverables: complete.
|
||||
- Promotion status: blocked pending runtime + hardware signals.
|
||||
- updated dossiers and matrices
|
||||
- refreshed evidence index
|
||||
- governance and release-gate verification
|
||||
|
||||
## Deferred Work
|
||||
|
||||
- runtime traces
|
||||
- hardware confirmation
|
||||
- any promotion to full support
|
||||
|
||||
@@ -1,38 +1,22 @@
|
||||
# Wave 2 Runtime/Hardware Intake (Prepared, Deferred)
|
||||
# Wave 2 Runtime Intake
|
||||
|
||||
## Purpose
|
||||
Define exactly what sanitized runtime/hardware evidence is needed to move Wave 2 devices beyond static-only dossiers.
|
||||
This note describes the evidence still needed to move Wave 2 devices beyond static-only confidence.
|
||||
|
||||
## Required Submission Data
|
||||
Every submission must include:
|
||||
1. VID/PID in hex.
|
||||
2. Firmware version.
|
||||
3. Operation attempted.
|
||||
4. Sanitized request structure.
|
||||
5. Sanitized response structure.
|
||||
6. Reproducibility notes (OS, transport, retries, success/failure rate).
|
||||
|
||||
## Sanitization Rules
|
||||
Allowed content:
|
||||
- byte-layout summaries,
|
||||
- command/response shape descriptions,
|
||||
- validation predicates,
|
||||
- timing/retry observations.
|
||||
1. VID/PID
|
||||
2. firmware version
|
||||
3. operation attempted
|
||||
4. sanitized request structure
|
||||
5. sanitized response structure
|
||||
6. reproducibility notes
|
||||
|
||||
Forbidden content:
|
||||
- raw decompiled code snippets,
|
||||
- copied vendor constants blocks,
|
||||
- copied source fragments from official binaries/tools.
|
||||
## Acceptance Rules
|
||||
|
||||
## Evidence Acceptance Checklist
|
||||
1. VID/PID and firmware fields are present.
|
||||
2. Request/response structure is sanitized and technically complete.
|
||||
3. Failure signatures are mapped to stable categories (`timeout`, `malformed`, `unsupported`, `invalid_signature`).
|
||||
4. Repro steps are clear enough for independent rerun.
|
||||
5. No forbidden raw-source content appears.
|
||||
- no copied vendor code or decompiled snippets
|
||||
- failure signatures must map to stable categories
|
||||
- the report must be repeatable enough for an independent rerun
|
||||
|
||||
## Promotion Readiness Mapping
|
||||
A PID is promotion-eligible only when all are true:
|
||||
1. Static dossiers complete.
|
||||
2. Runtime traces accepted from at least 2 independent runs.
|
||||
3. Hardware read/write/readback validation passes on owned fixture(s).
|
||||
## Promotion Readiness
|
||||
|
||||
A PID is promotion-ready only when static, runtime, and hardware evidence all exist together.
|
||||
|
||||
@@ -9,7 +9,7 @@ resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
edition = "2021"
|
||||
version = "0.0.1-rc.2"
|
||||
version = "0.0.1-rc.4"
|
||||
license = "BSD-3-Clause"
|
||||
|
||||
[workspace.dependencies]
|
||||
|
||||
179
sdk/README.md
179
sdk/README.md
@@ -1,135 +1,90 @@
|
||||
# OpenBitdo SDK
|
||||
|
||||
OpenBitdo SDK includes:
|
||||
- `bitdo_proto`: protocol/transport/session library
|
||||
- `bitdo_app_core`: shared firmware-first workflow and policy layer
|
||||
- `bitdo_tui`: Ratatui/Crossterm terminal app
|
||||
- `openbitdo`: beginner-first launcher (`openbitdo` starts guided TUI)
|
||||
This workspace contains the OpenBitdo runtime, protocol layer, and release packaging scripts.
|
||||
|
||||
## Crates
|
||||
|
||||
- `bitdo_proto`: command registry, transport, session, and diagnostics behavior
|
||||
- `bitdo_app_core`: firmware policy, device workflows, and support-tier gating
|
||||
- `bitdo_tui`: terminal UI, app state, runtime loop, persistence, and headless API
|
||||
- `openbitdo`: beginner-first launcher binary
|
||||
|
||||
## Build And Test
|
||||
|
||||
From `cleanroom/sdk`:
|
||||
|
||||
## Build
|
||||
```bash
|
||||
cargo build --workspace
|
||||
```
|
||||
|
||||
## Test
|
||||
```bash
|
||||
cargo clippy --workspace --all-targets -- -D warnings
|
||||
cargo test --workspace --all-targets
|
||||
```
|
||||
|
||||
## Guard
|
||||
```bash
|
||||
./scripts/cleanroom_guard.sh
|
||||
```
|
||||
|
||||
## Hardware smoke report
|
||||
```bash
|
||||
./scripts/run_hardware_smoke.sh
|
||||
```
|
||||
## Local Run
|
||||
|
||||
## TUI app examples (`openbitdo`)
|
||||
```bash
|
||||
cargo run -p openbitdo --
|
||||
cargo run -p openbitdo -- --mock
|
||||
```
|
||||
|
||||
## CLI surface
|
||||
- `openbitdo [--mock]`: interactive dashboard flow (mouse-primary, minimal keyboard).
|
||||
|
||||
## Interactive behavior (`openbitdo`)
|
||||
- dashboard starts with:
|
||||
- searchable device list (left)
|
||||
- quick actions (center)
|
||||
- persistent event panel (right)
|
||||
- primary quick actions:
|
||||
- `Refresh`
|
||||
- `Diagnose`
|
||||
- `Recommended Update`
|
||||
- `Edit Mapping` (capability-gated)
|
||||
- `Settings`
|
||||
- `Quit`
|
||||
- firmware transfer path:
|
||||
- preflight generation
|
||||
- explicit confirm/cancel action
|
||||
- updating progress and final result screen
|
||||
- mapping editors are draft-first with:
|
||||
- apply
|
||||
- undo
|
||||
- reset
|
||||
- restore backup
|
||||
- recovery lock behavior is preserved when rollback fails.
|
||||
|
||||
## Headless library API
|
||||
- headless automation remains available as a Rust API in `bitdo_tui`:
|
||||
- `run_headless`
|
||||
- `RunLaunchOptions`
|
||||
- `HeadlessOutputMode`
|
||||
- `openbitdo` CLI does not expose a headless command surface.
|
||||
|
||||
## Config schema (v2)
|
||||
- persisted fields:
|
||||
- `schema_version`
|
||||
- `advanced_mode`
|
||||
- `report_save_mode`
|
||||
- `device_filter_text`
|
||||
- `dashboard_layout_mode`
|
||||
- `last_panel_focus`
|
||||
- v1 files are read with compatibility defaults and normalized to v2 fields at load time.
|
||||
`openbitdo` intentionally exposes a single interactive CLI surface.
|
||||
Headless automation remains available through the Rust API in `bitdo_tui`.
|
||||
|
||||
## Packaging
|
||||
|
||||
```bash
|
||||
./scripts/package-linux.sh v0.0.1-rc.2 x86_64
|
||||
./scripts/package-linux.sh v0.0.1-rc.2 aarch64
|
||||
./scripts/package-macos.sh v0.0.1-rc.2 arm64 aarch64-apple-darwin
|
||||
./scripts/package-linux.sh v0.0.0-local x86_64
|
||||
./scripts/package-linux.sh v0.0.0-local aarch64
|
||||
./scripts/package-macos.sh v0.0.0-local arm64 aarch64-apple-darwin
|
||||
```
|
||||
|
||||
Packaging outputs use:
|
||||
- `openbitdo-<version>-<os>-<arch>.tar.gz`
|
||||
- `openbitdo-<version>-<os>-<arch>` standalone binary
|
||||
- `.sha256` checksum file for each artifact
|
||||
- macOS arm64 additionally emits `.pkg` (unsigned/ad-hoc for RC)
|
||||
Outputs:
|
||||
|
||||
## Release Workflow
|
||||
- CI checks remain in `.github/workflows/ci.yml`.
|
||||
- Tag-based release workflow is in `.github/workflows/release.yml`.
|
||||
- Release tags must originate from `main`.
|
||||
- `v0.0.1-rc.2` style tags publish GitHub pre-releases.
|
||||
- Release notes are sourced from `/Users/brooklyn/data/8bitdo/cleanroom/CHANGELOG.md`.
|
||||
- Package-manager publish runs only after release assets are published.
|
||||
- `openbitdo-<version>-linux-x86_64.tar.gz`
|
||||
- `openbitdo-<version>-linux-aarch64.tar.gz`
|
||||
- `openbitdo-<version>-macos-arm64.tar.gz`
|
||||
- standalone binaries for each packaged target
|
||||
- `.sha256` files for every artifact
|
||||
- macOS `.pkg` from `pkgbuild`
|
||||
|
||||
## Public RC Gate
|
||||
- No open GitHub issues with label `release-blocker`.
|
||||
- Scope-completeness gate:
|
||||
- JP108 RC scope is dedicated mapping only (`A/B/K1-K8`).
|
||||
- Ultimate2 RC scope is expanded mapping for required fields only.
|
||||
- Clean-tree requirement from `/Users/brooklyn/data/8bitdo/cleanroom/RC_CHECKLIST.md` must be satisfied before tagging.
|
||||
Current macOS packaging remains unsigned and non-notarized by design.
|
||||
|
||||
## Distribution Prep
|
||||
- Homebrew install path for public RC:
|
||||
- `brew tap bybrooklyn/openbitdo`
|
||||
- `brew install openbitdo`
|
||||
- Homebrew Core inclusion is not required for `v0.0.1-rc.2`.
|
||||
- Homebrew formula scaffold: `/Users/brooklyn/data/8bitdo/cleanroom/packaging/homebrew/Formula/openbitdo.rb`
|
||||
- Homebrew tap sync script (disabled by default): `/Users/brooklyn/data/8bitdo/cleanroom/packaging/homebrew/sync_tap.sh`
|
||||
- Tap repository: `bybrooklyn/homebrew-openbitdo`
|
||||
- AUR package sources:
|
||||
- `/Users/brooklyn/data/8bitdo/cleanroom/packaging/aur/openbitdo-bin`
|
||||
- AUR package names:
|
||||
- `openbitdo-bin`
|
||||
- Release metadata renderer:
|
||||
- `/Users/brooklyn/data/8bitdo/cleanroom/packaging/scripts/render_release_metadata.sh`
|
||||
- AUR publish workflow:
|
||||
- `/Users/brooklyn/data/8bitdo/cleanroom/.github/workflows/aur-publish.yml`
|
||||
- gated by `AUR_PUBLISH_ENABLED=1`
|
||||
- Homebrew publish path:
|
||||
- `release.yml` renders checksum-pinned formula and runs `sync_tap.sh`
|
||||
- gated by `HOMEBREW_PUBLISH_ENABLED=1`
|
||||
- macOS `.pkg` caveat:
|
||||
- unsigned/ad-hoc is accepted for `v0.0.1-rc.2`
|
||||
- notarization required for `v0.1.0`
|
||||
## Release Flow
|
||||
|
||||
## CI Gates
|
||||
- required:
|
||||
- `guard`
|
||||
- `test`
|
||||
- `tui-smoke-test`
|
||||
- `aur-validate`
|
||||
- `build-macos-arm64`
|
||||
1. Tag from `main` using a `v*` tag.
|
||||
2. `release.yml` verifies CI, secrets, and release blockers.
|
||||
3. Linux and macOS artifacts are built and uploaded.
|
||||
4. GitHub prerelease assets are published from those artifacts.
|
||||
5. AUR and Homebrew metadata are rendered from published release assets.
|
||||
6. AUR and Homebrew publication run only when their repo-variable gates are enabled.
|
||||
|
||||
## Package Manager Publishing
|
||||
|
||||
- AUR workflow: `.github/workflows/aur-publish.yml`
|
||||
- Homebrew workflow: `.github/workflows/homebrew-publish.yml`
|
||||
- Release metadata renderer: `packaging/scripts/render_release_metadata.sh`
|
||||
- AUR source of truth:
|
||||
- tracked package metadata in `packaging/aur/openbitdo-bin`
|
||||
- template in `packaging/aur/openbitdo-bin/PKGBUILD.tmpl`
|
||||
- Homebrew source of truth:
|
||||
- template in `packaging/homebrew/Formula/openbitdo.rb.tmpl`
|
||||
- published tap repo `bybrooklyn/homebrew-openbitdo`
|
||||
|
||||
Current repo-variable contract:
|
||||
|
||||
- `AUR_PUBLISH_ENABLED=1`
|
||||
- `HOMEBREW_PUBLISH_ENABLED=1` when Homebrew publication is enabled
|
||||
- `HOMEBREW_TAP_REPO=bybrooklyn/homebrew-openbitdo`
|
||||
|
||||
Required secrets:
|
||||
|
||||
- `AUR_USERNAME`
|
||||
- `AUR_SSH_PRIVATE_KEY`
|
||||
- `HOMEBREW_TAP_TOKEN`
|
||||
|
||||
## Docs Map
|
||||
|
||||
- Public project overview: [`../README.md`](../README.md)
|
||||
- RC checklist: [`../RC_CHECKLIST.md`](../RC_CHECKLIST.md)
|
||||
- Process docs: [`../process`](../process)
|
||||
- Spec docs: [`../spec`](../spec)
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
---
|
||||
source: crates/bitdo_tui/src/tests.rs
|
||||
assertion_line: 196
|
||||
expression: rendered
|
||||
---
|
||||
╭Session───────────────────────────────────────────────────────────────────────╮
|
||||
│OpenBitDo Dashboard • 3 devices • reports fail-only • safe │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯
|
||||
╭Search filter────────────────╮╭Device full──────────╮╭Actions Enter/click──╮
|
||||
│Search active ││Ultimate2 2dc8:5209 ││› Refresh • scan │
|
||||
╰──────────────────────────────╯│Support: supported ││ Diagnose • probe │
|
||||
╭Search filter────────────────╮╭Device supported─────╮╭Actions Enter/click──╮
|
||||
│Search active ││Ultimate2 2dc8:5209 ││› Refresh • look for│
|
||||
╰──────────────────────────────╯│Support: Supported ││ Diagnose • run saf│
|
||||
╭Controllers detected─────────╮│Protocol: Standard64 ││ Recommended Update │
|
||||
│› 2dc8:5209 Ultimate2 ││Evidence: Confirmed ││ Edit Mapping • map│
|
||||
│full • S64 • conf ││ ││ Settings • prefs │
|
||||
│ 2dc8:6009 Ultimate ││Capabilities ││ Quit • exit │
|
||||
│ro • S64 • infer ││• firmware ││ │
|
||||
│ 2dc8:901a Candidate ││• profile rw │╰──────────────────────╯
|
||||
│ro • unknown • untest ││• mode switch │╭Activity events──────╮
|
||||
│ ││• JP108 mapping ││ │
|
||||
│ ││• U2 slot + map ││ │
|
||||
│› 2dc8:5209 Ultimate2 ││Evidence: Confirmed ││ Edit Mapping • cha│
|
||||
│supported • standard64 • confi││ ││ Settings • report │
|
||||
│ 2dc8:6009 Ultimate ││Capabilities ││ Quit • close OpenB│
|
||||
│read-only • standard64 • infer││• firmware updates ││ │
|
||||
│ 2dc8:901a Candidate ││• profile read and wri│╰──────────────────────╯
|
||||
│read-only • unknown • untested││• mode switching │╭Activity events──────╮
|
||||
│ ││• JP108 dedicated mapp││ │
|
||||
│ ││• Ultimate 2 slot and ││ │
|
||||
│ ││ ││ │
|
||||
│ ││ ││ │
|
||||
│ ││ ││ │
|
||||
@@ -25,5 +24,5 @@ expression: rendered
|
||||
╰──────────────────────────────╯╰──────────────────────╯╰──────────────────────╯
|
||||
╭Status────────────────────────────────────────────────────────────────────────╮
|
||||
│Ready │
|
||||
│Ultimate2 • click • arrows • Enter • Esc/q │
|
||||
│Ultimate2 • click a device or action • arrows, Enter, Esc, and q still work │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
source: crates/bitdo_tui/src/tests.rs
|
||||
assertion_line: 317
|
||||
expression: rendered
|
||||
---
|
||||
╭Session───────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
@@ -8,7 +7,7 @@ expression: rendered
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭Diagnostics summary──────────────────────────────────────────────────────────────────────────────╮
|
||||
│3/5 passed • 2 issues • 2 experimental │
|
||||
│Tier: full • Family: Standard64 • Transport: ready │
|
||||
│Tier: supported • Family: Standard64 • Transport: ready │
|
||||
│ │
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭Filter All──╮╭Filter Issu╮╭Filter Exper╮╭Selected Check detail────────────────────────────────╮
|
||||
@@ -22,7 +21,7 @@ expression: rendered
|
||||
│ ATTN Version invalid response… ││Validator: test:GetPid │
|
||||
│ │╰──────────────────────────────────────────────────────╯
|
||||
│ │╭Next Steps guidance──────────────────────────────────╮
|
||||
│ ││Action: Return to the dashboard and choose Recomme… │
|
||||
│ ││Action: Return to the dashboard for update or mapp… │
|
||||
│ ││Summary: 3/5 checks passed. Experimental checks: 1… │
|
||||
│ ││Saved report: not yet saved in this screen │
|
||||
│ ││ │
|
||||
@@ -31,5 +30,5 @@ expression: rendered
|
||||
╰──────────────────────────────────────────╯╰──────────────────────────────────────────────────────╯
|
||||
╭Run Again──────────────────────╮╭Save Report────────────────────╮╭Back───────────────────────────╮
|
||||
│Run Again ││Save Report ││Back │
|
||||
│rerun safe-read probe ││write support report ││return to dashboard │
|
||||
│run the safe checks again ││save a shareable support re… ││return to dashboard │
|
||||
╰───────────────────────────────╯╰───────────────────────────────╯╰───────────────────────────────╯
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
source: crates/bitdo_tui/src/tests.rs
|
||||
assertion_line: 327
|
||||
expression: rendered
|
||||
---
|
||||
╭Session───────────────────────────────────────────────────────────────────────╮
|
||||
@@ -8,7 +7,7 @@ expression: rendered
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯
|
||||
╭Diagnostics summary──────────────────────────────────────────────────────────╮
|
||||
│3/5 passed • 2 issues • 2 experimental │
|
||||
│Tier: full • Family: Standard64 • Transport: ready │
|
||||
│Tier: supported • Family: Standard64 • Transport: ready │
|
||||
│ │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯
|
||||
╭Checks tab cycles filter─────────────────────────────────────────────────────╮
|
||||
@@ -21,9 +20,9 @@ expression: rendered
|
||||
│Severity: Ok │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯
|
||||
╭Next Steps guidance──────────────────────────────────────────────────────────╮
|
||||
│Action: Return to the dashboard and choose Recommended Update or Edit Mapp… │
|
||||
│Action: Return to the dashboard for update or mapping if this device still… │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯
|
||||
╭Run Again───────────────╮╭Save Report──────────────╮╭Back────────────────────╮
|
||||
│Run Again ││Save Report ││Back │
|
||||
│rerun safe-read probe ││write support report ││return to dashboard │
|
||||
│run the safe checks … ││save a shareable supp… ││return to dashboard │
|
||||
╰────────────────────────╯╰─────────────────────────╯╰────────────────────────╯
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
source: crates/bitdo_tui/src/tests.rs
|
||||
assertion_line: 343
|
||||
expression: rendered
|
||||
---
|
||||
╭Session───────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
@@ -8,7 +7,7 @@ expression: rendered
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭Diagnostics summary──────────────────────────────────────────────────────────────────────────────╮
|
||||
│3/5 passed • 2 issues • 2 experimental │
|
||||
│Tier: full • Family: Standard64 • Transport: ready │
|
||||
│Tier: supported • Family: Standard64 • Transport: ready │
|
||||
│ │
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭Filter All──╮╭Filter Issu╮╭Filter Exper╮╭Selected Check detail────────────────────────────────╮
|
||||
@@ -22,7 +21,7 @@ expression: rendered
|
||||
│ ││Validator: test:Version │
|
||||
│ │╰──────────────────────────────────────────────────────╯
|
||||
│ │╭Next Steps guidance──────────────────────────────────╮
|
||||
│ ││Action: Return to the dashboard and choose Recomme… │
|
||||
│ ││Action: Return to the dashboard for update or mapp… │
|
||||
│ ││Summary: 3/5 checks passed. Experimental checks: 1… │
|
||||
│ ││Saved report: /tmp/openbitdo-diag-report.toml │
|
||||
│ ││ │
|
||||
@@ -31,5 +30,5 @@ expression: rendered
|
||||
╰──────────────────────────────────────────╯╰──────────────────────────────────────────────────────╯
|
||||
╭Run Again──────────────────────╮╭Save Report────────────────────╮╭Back───────────────────────────╮
|
||||
│Run Again ││Save Report ││Back │
|
||||
│rerun safe-read probe ││write support report ││return to dashboard │
|
||||
│run the safe checks again ││save a shareable support re… ││return to dashboard │
|
||||
╰───────────────────────────────╯╰───────────────────────────────╯╰───────────────────────────────╯
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
---
|
||||
source: crates/bitdo_tui/src/tests.rs
|
||||
assertion_line: 212
|
||||
expression: rendered
|
||||
---
|
||||
╭Session───────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│OpenBitDo Workflow • Ready • reports fail-only • safe │
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭Preflight status and intent──────────────────────────────────────────────────────────────────────╮
|
||||
│Preflight Workflow preflight safety check │
|
||||
╭Safety Check status and intent───────────────────────────────────────────────────────────────────╮
|
||||
│Safety Check Workflow reviewing update safety │
|
||||
│ │
|
||||
│Ready to confirm transfer │
|
||||
│ │
|
||||
@@ -17,9 +16,9 @@ expression: rendered
|
||||
│ ││█████ 12% │
|
||||
│ │╰────────────────────────────────────────╯
|
||||
│ │╭Context current session────────────────╮
|
||||
│ ││Stage: preflight safety check │
|
||||
│ ││Current stage: reviewing update safety │
|
||||
│ ││Progress: 12% │
|
||||
│ ││Reports: failure_only │
|
||||
│ ││Report policy: failure_only │
|
||||
│ ││Ready │
|
||||
│ ││ │
|
||||
│ ││ │
|
||||
@@ -31,5 +30,5 @@ expression: rendered
|
||||
╰────────────────────────────────────────────────────────╯╰────────────────────────────────────────╯
|
||||
╭Confirm────────────────────────╮╭Cancel─────────────────────────╮╭Back───────────────────────────╮
|
||||
│Confirm ││Cancel ││Back │
|
||||
│acknowledge risk + start ││stop this workflow ││return to dashboard │
|
||||
│acknowledge risk and start … ││stop and discard this step ││leave this screen │
|
||||
╰───────────────────────────────╯╰───────────────────────────────╯╰───────────────────────────────╯
|
||||
|
||||
@@ -15,8 +15,12 @@ pub fn render(frame: &mut Frame<'_>, state: &AppState, area: Rect) -> HitMap {
|
||||
.split(area);
|
||||
|
||||
let status_hint = match state.dashboard_layout_mode {
|
||||
DashboardLayoutMode::Compact => "compact layout • resize for full three-panel view",
|
||||
DashboardLayoutMode::Wide => "click • arrows • Enter • Esc/q",
|
||||
DashboardLayoutMode::Compact => {
|
||||
"compact layout • resize for three panels or keep using click, arrows, and Enter"
|
||||
}
|
||||
DashboardLayoutMode::Wide => {
|
||||
"click a device or action • arrows, Enter, Esc, and q still work"
|
||||
}
|
||||
};
|
||||
let selected_summary = state
|
||||
.selected_device()
|
||||
@@ -94,7 +98,7 @@ fn render_devices(frame: &mut Frame<'_>, state: &AppState, area: Rect, map: &mut
|
||||
let filter = Paragraph::new(Line::from(vec![
|
||||
Span::styled("Search ", crate::ui::theme::title_style()),
|
||||
Span::raw(if filter_label.is_empty() {
|
||||
"type a model, VID, or PID".to_owned()
|
||||
"type a model name or USB ID".to_owned()
|
||||
} else {
|
||||
filter_label
|
||||
}),
|
||||
@@ -194,7 +198,7 @@ fn render_selected_device(frame: &mut Frame<'_>, state: &AppState, area: Rect) {
|
||||
if device.support_tier != bitdo_proto::SupportTier::Full {
|
||||
details.push(Line::from(""));
|
||||
details.push(Line::from(Span::styled(
|
||||
"Write actions stay blocked until hardware confirmation lands.",
|
||||
"This device is still read-only here. Safe diagnostics work, but mapping and update stay blocked until hardware confirmation lands.",
|
||||
crate::ui::theme::warning_style(),
|
||||
)));
|
||||
}
|
||||
@@ -333,17 +337,31 @@ fn truncate_reason(reason: &str) -> String {
|
||||
|
||||
fn action_caption(action: crate::app::action::QuickAction) -> &'static str {
|
||||
match action {
|
||||
crate::app::action::QuickAction::Refresh => "scan",
|
||||
crate::app::action::QuickAction::Diagnose => "probe",
|
||||
crate::app::action::QuickAction::RecommendedUpdate => "safe update",
|
||||
crate::app::action::QuickAction::EditMappings => "mapping",
|
||||
crate::app::action::QuickAction::Settings => "prefs",
|
||||
crate::app::action::QuickAction::Quit => "exit",
|
||||
crate::app::action::QuickAction::Refresh => "look for connected controllers",
|
||||
crate::app::action::QuickAction::Diagnose => {
|
||||
"run safe diagnostics and build a support summary"
|
||||
}
|
||||
crate::app::action::QuickAction::RecommendedUpdate => {
|
||||
"download and stage a verified firmware update"
|
||||
}
|
||||
crate::app::action::QuickAction::EditMappings => {
|
||||
"change supported buttons on supported devices"
|
||||
}
|
||||
crate::app::action::QuickAction::Settings => "report saving and interface preferences",
|
||||
crate::app::action::QuickAction::Quit => "close OpenBitdo",
|
||||
_ => "available",
|
||||
}
|
||||
}
|
||||
|
||||
fn support_tier_label(tier: bitdo_proto::SupportTier) -> &'static str {
|
||||
match tier {
|
||||
bitdo_proto::SupportTier::Full => "Supported",
|
||||
bitdo_proto::SupportTier::CandidateReadOnly => "Read-only candidate",
|
||||
bitdo_proto::SupportTier::DetectOnly => "Detection only",
|
||||
}
|
||||
}
|
||||
|
||||
fn support_tier_short(tier: bitdo_proto::SupportTier) -> &'static str {
|
||||
match tier {
|
||||
bitdo_proto::SupportTier::Full => "supported",
|
||||
bitdo_proto::SupportTier::CandidateReadOnly => "read-only",
|
||||
@@ -351,34 +369,26 @@ fn support_tier_label(tier: bitdo_proto::SupportTier) -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
fn support_tier_short(tier: bitdo_proto::SupportTier) -> &'static str {
|
||||
match tier {
|
||||
bitdo_proto::SupportTier::Full => "full",
|
||||
bitdo_proto::SupportTier::CandidateReadOnly => "ro",
|
||||
bitdo_proto::SupportTier::DetectOnly => "detect",
|
||||
}
|
||||
}
|
||||
|
||||
fn capability_lines(device: &bitdo_app_core::AppDevice) -> Vec<String> {
|
||||
let mut lines = Vec::new();
|
||||
|
||||
if device.capability.supports_firmware {
|
||||
lines.push("• firmware".to_owned());
|
||||
lines.push("• firmware updates".to_owned());
|
||||
}
|
||||
if device.capability.supports_profile_rw {
|
||||
lines.push("• profile rw".to_owned());
|
||||
lines.push("• profile read and write".to_owned());
|
||||
}
|
||||
if device.capability.supports_mode {
|
||||
lines.push("• mode switch".to_owned());
|
||||
lines.push("• mode switching".to_owned());
|
||||
}
|
||||
if device.capability.supports_jp108_dedicated_map {
|
||||
lines.push("• JP108 mapping".to_owned());
|
||||
lines.push("• JP108 dedicated mapping".to_owned());
|
||||
}
|
||||
if device.capability.supports_u2_button_map || device.capability.supports_u2_slot_config {
|
||||
lines.push("• U2 slot + map".to_owned());
|
||||
lines.push("• Ultimate 2 slot and mapping".to_owned());
|
||||
}
|
||||
if lines.is_empty() {
|
||||
lines.push("• detect only".to_owned());
|
||||
lines.push("• detection only".to_owned());
|
||||
}
|
||||
|
||||
lines
|
||||
@@ -396,7 +406,9 @@ fn compact_reason(reason: &str) -> String {
|
||||
|
||||
fn protocol_short(protocol: bitdo_proto::ProtocolFamily) -> &'static str {
|
||||
match protocol {
|
||||
bitdo_proto::ProtocolFamily::Standard64 => "S64",
|
||||
bitdo_proto::ProtocolFamily::Standard64 => "standard64",
|
||||
bitdo_proto::ProtocolFamily::DInput => "dinput",
|
||||
bitdo_proto::ProtocolFamily::JpHandshake => "jp",
|
||||
bitdo_proto::ProtocolFamily::Unknown => "unknown",
|
||||
_ => "other",
|
||||
}
|
||||
@@ -404,8 +416,8 @@ fn protocol_short(protocol: bitdo_proto::ProtocolFamily) -> &'static str {
|
||||
|
||||
fn evidence_short(evidence: bitdo_proto::SupportEvidence) -> &'static str {
|
||||
match evidence {
|
||||
bitdo_proto::SupportEvidence::Confirmed => "conf",
|
||||
bitdo_proto::SupportEvidence::Inferred => "infer",
|
||||
bitdo_proto::SupportEvidence::Untested => "untest",
|
||||
bitdo_proto::SupportEvidence::Confirmed => "confirmed",
|
||||
bitdo_proto::SupportEvidence::Inferred => "inferred",
|
||||
bitdo_proto::SupportEvidence::Untested => "untested",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,8 +467,8 @@ fn render_next_steps(frame: &mut Frame<'_>, state: &AppState, area: Rect) {
|
||||
|
||||
fn diagnostics_action_caption(action: QuickAction) -> &'static str {
|
||||
match action {
|
||||
QuickAction::RunAgain => "rerun safe-read probe",
|
||||
QuickAction::SaveReport => "write support report",
|
||||
QuickAction::RunAgain => "run the safe checks again",
|
||||
QuickAction::SaveReport => "save a shareable support report",
|
||||
QuickAction::Back => "return to dashboard",
|
||||
_ => "available",
|
||||
}
|
||||
@@ -477,13 +477,13 @@ fn diagnostics_action_caption(action: QuickAction) -> &'static str {
|
||||
fn recommended_next_action(diagnostics: &crate::app::state::DiagnosticsState) -> &'static str {
|
||||
match diagnostics.result.support_tier {
|
||||
bitdo_proto::SupportTier::Full => {
|
||||
"Return to the dashboard and choose Recommended Update or Edit Mapping if needed."
|
||||
"Return to the dashboard for update or mapping if this device still needs work."
|
||||
}
|
||||
bitdo_proto::SupportTier::CandidateReadOnly => {
|
||||
"Save or share the report. Update and mapping remain blocked until confirmation lands."
|
||||
"Save or share the report. Update and mapping stay blocked until this device family is hardware-confirmed."
|
||||
}
|
||||
bitdo_proto::SupportTier::DetectOnly => {
|
||||
"Diagnostics only. Do not attempt update or mapping for this device."
|
||||
"Use diagnostics only. This device is not ready for update or mapping flows."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -514,8 +514,8 @@ fn severity_style(has_issues: bool) -> Style {
|
||||
|
||||
fn support_tier_label(tier: bitdo_proto::SupportTier) -> &'static str {
|
||||
match tier {
|
||||
bitdo_proto::SupportTier::Full => "full",
|
||||
bitdo_proto::SupportTier::CandidateReadOnly => "candidate-readonly",
|
||||
bitdo_proto::SupportTier::Full => "supported",
|
||||
bitdo_proto::SupportTier::CandidateReadOnly => "read-only candidate",
|
||||
bitdo_proto::SupportTier::DetectOnly => "detect-only",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,18 +24,18 @@ pub fn render(frame: &mut Frame<'_>, state: &AppState, area: Rect) -> HitMap {
|
||||
let adv = Paragraph::new(vec![
|
||||
Line::from(Span::styled(
|
||||
if state.advanced_mode {
|
||||
"Advanced mode is on"
|
||||
"Advanced controls are on"
|
||||
} else {
|
||||
"Advanced mode is off"
|
||||
"Advanced controls are off"
|
||||
},
|
||||
crate::ui::theme::screen_title_style(),
|
||||
)),
|
||||
Line::from(Span::styled(
|
||||
"Toggle to expose expert-only report and workflow options.",
|
||||
"Turn this on only if you want expert labels and extra workflow options.",
|
||||
crate::ui::theme::subtle_style(),
|
||||
)),
|
||||
])
|
||||
.block(panel_block("Advanced", Some("press t or click"), true));
|
||||
.block(panel_block("Advanced", Some("toggle"), true));
|
||||
frame.render_widget(adv, rows[0]);
|
||||
|
||||
let report = Paragraph::new(vec![
|
||||
@@ -44,11 +44,11 @@ pub fn render(frame: &mut Frame<'_>, state: &AppState, area: Rect) -> HitMap {
|
||||
crate::ui::theme::screen_title_style(),
|
||||
)),
|
||||
Line::from(Span::styled(
|
||||
"Cycle report persistence policy with r or mouse.",
|
||||
"Choose whether support reports save automatically after diagnostics or firmware work.",
|
||||
crate::ui::theme::subtle_style(),
|
||||
)),
|
||||
])
|
||||
.block(panel_block("Reports", Some("press r or click"), true));
|
||||
.block(panel_block("Reports", Some("save policy"), true));
|
||||
frame.render_widget(report, rows[1]);
|
||||
|
||||
let settings_path = state
|
||||
@@ -61,11 +61,11 @@ pub fn render(frame: &mut Frame<'_>, state: &AppState, area: Rect) -> HitMap {
|
||||
Line::from(""),
|
||||
Line::from(format!("Config path: {settings_path}")),
|
||||
Line::from(Span::styled(
|
||||
"Dashboard layout and filter state persist when a settings path is configured.",
|
||||
"Dashboard layout, filters, and report preferences persist when this path is available.",
|
||||
crate::ui::theme::subtle_style(),
|
||||
)),
|
||||
])
|
||||
.block(panel_block("Status", Some("saved preferences"), true));
|
||||
.block(panel_block("Status", Some("persistence"), true));
|
||||
frame.render_widget(status, rows[2]);
|
||||
|
||||
let actions = state
|
||||
@@ -95,7 +95,7 @@ fn inner_click_rect(rect: Rect) -> Rect {
|
||||
fn settings_action_caption(action: crate::app::action::QuickAction) -> &'static str {
|
||||
match action {
|
||||
crate::app::action::QuickAction::Back => "return to dashboard",
|
||||
crate::app::action::QuickAction::Quit => "exit openbitdo",
|
||||
crate::app::action::QuickAction::Quit => "close OpenBitdo",
|
||||
_ => "available",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ pub fn render(frame: &mut Frame<'_>, state: &AppState, area: Rect) -> HitMap {
|
||||
let task = state.task_state.as_ref();
|
||||
let title = match task.map(|t| t.mode) {
|
||||
Some(TaskMode::Diagnostics) => "Diagnostics",
|
||||
Some(TaskMode::Preflight) => "Preflight",
|
||||
Some(TaskMode::Updating) => "Updating",
|
||||
Some(TaskMode::Preflight) => "Safety Check",
|
||||
Some(TaskMode::Updating) => "Update In Progress",
|
||||
Some(TaskMode::Final) => "Result",
|
||||
None => "Task",
|
||||
};
|
||||
@@ -51,7 +51,7 @@ pub fn render(frame: &mut Frame<'_>, state: &AppState, area: Rect) -> HitMap {
|
||||
crate::ui::theme::screen_title_style(),
|
||||
)),
|
||||
Line::from(""),
|
||||
Line::from("Select a device action from the dashboard to begin."),
|
||||
Line::from("Choose a controller action from the dashboard to begin."),
|
||||
]
|
||||
};
|
||||
|
||||
@@ -96,14 +96,20 @@ fn render_task_details(frame: &mut Frame<'_>, state: &AppState, area: Rect) {
|
||||
let mut lines = vec![Line::from(task.status.clone())];
|
||||
if let Some(plan) = task.plan.as_ref() {
|
||||
lines.push(Line::from(""));
|
||||
lines.push(Line::from(format!("Session: {:?}", plan.session_id)));
|
||||
lines.push(Line::from(format!(
|
||||
"Transfer session: {:?}",
|
||||
plan.session_id
|
||||
)));
|
||||
lines.push(Line::from(format!("Chunk size: {} bytes", plan.chunk_size)));
|
||||
lines.push(Line::from(format!("Chunks: {}", plan.chunks_total)));
|
||||
lines.push(Line::from(format!("Estimated: {}s", plan.expected_seconds)));
|
||||
lines.push(Line::from(format!("Total chunks: {}", plan.chunks_total)));
|
||||
lines.push(Line::from(format!(
|
||||
"Estimated transfer time: {}s",
|
||||
plan.expected_seconds
|
||||
)));
|
||||
if !plan.warnings.is_empty() {
|
||||
lines.push(Line::from(""));
|
||||
lines.push(Line::from(Span::styled(
|
||||
"Warnings",
|
||||
"Safety notes",
|
||||
crate::ui::theme::warning_style(),
|
||||
)));
|
||||
for warning in &plan.warnings {
|
||||
@@ -145,16 +151,19 @@ fn render_task_details(frame: &mut Frame<'_>, state: &AppState, area: Rect) {
|
||||
|
||||
let summary_lines = if let Some(task) = task {
|
||||
vec![
|
||||
Line::from(format!("Stage: {}", task_mode_caption(task.mode))),
|
||||
Line::from(format!("Current stage: {}", task_mode_caption(task.mode))),
|
||||
Line::from(format!("Progress: {progress}%")),
|
||||
Line::from(format!("Reports: {}", state.report_save_mode.as_str())),
|
||||
Line::from(format!(
|
||||
"Report policy: {}",
|
||||
state.report_save_mode.as_str()
|
||||
)),
|
||||
Line::from(Span::styled(
|
||||
state.status_line.clone(),
|
||||
crate::ui::theme::subtle_style(),
|
||||
)),
|
||||
]
|
||||
} else {
|
||||
vec![Line::from("Select an action to see task details.")]
|
||||
vec![Line::from("Choose an action to see its workflow details.")]
|
||||
};
|
||||
let summary =
|
||||
Paragraph::new(summary_lines).block(panel_block("Context", Some("current session"), true));
|
||||
@@ -163,18 +172,18 @@ fn render_task_details(frame: &mut Frame<'_>, state: &AppState, area: Rect) {
|
||||
|
||||
fn task_mode_caption(mode: TaskMode) -> &'static str {
|
||||
match mode {
|
||||
TaskMode::Diagnostics => "diagnostic probe",
|
||||
TaskMode::Preflight => "preflight safety check",
|
||||
TaskMode::Updating => "firmware transfer",
|
||||
TaskMode::Final => "final outcome",
|
||||
TaskMode::Diagnostics => "running safe diagnostics",
|
||||
TaskMode::Preflight => "reviewing update safety",
|
||||
TaskMode::Updating => "sending verified firmware",
|
||||
TaskMode::Final => "showing the final result",
|
||||
}
|
||||
}
|
||||
|
||||
fn task_action_caption(action: crate::app::action::QuickAction) -> &'static str {
|
||||
match action {
|
||||
crate::app::action::QuickAction::Confirm => "acknowledge risk + start",
|
||||
crate::app::action::QuickAction::Cancel => "stop this workflow",
|
||||
crate::app::action::QuickAction::Back => "return to dashboard",
|
||||
crate::app::action::QuickAction::Confirm => "acknowledge risk and start the update",
|
||||
crate::app::action::QuickAction::Cancel => "stop and discard this step",
|
||||
crate::app::action::QuickAction::Back => "leave this screen",
|
||||
_ => "available",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,25 @@ use bitdo_tui::{run_ui, UiLaunchOptions};
|
||||
use clap::Parser;
|
||||
use openbitdo::{load_user_settings, user_settings_path, BuildInfo, UserSettings};
|
||||
|
||||
const CLI_AFTER_HELP: &str = "\
|
||||
Examples:
|
||||
openbitdo
|
||||
openbitdo --mock
|
||||
|
||||
Install:
|
||||
Homebrew: brew tap bybrooklyn/openbitdo && brew install openbitdo
|
||||
AUR: paru -S openbitdo-bin
|
||||
Releases: download a tarball, then run bin/openbitdo
|
||||
|
||||
Notes:
|
||||
--mock starts the app without real hardware.
|
||||
macOS packages are currently unsigned and non-notarized.
|
||||
";
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(name = "openbitdo")]
|
||||
#[command(about = "OpenBitdo beginner-first launcher")]
|
||||
#[command(about = "Beginner-first 8BitDo controller utility")]
|
||||
#[command(after_help = CLI_AFTER_HELP)]
|
||||
struct Cli {
|
||||
#[arg(long, help = "Use mock transport/devices")]
|
||||
mock: bool,
|
||||
|
||||
@@ -9,8 +9,16 @@ fn help_mentions_single_command_surface() {
|
||||
.success()
|
||||
.stdout(predicate::str::contains("Usage: openbitdo [OPTIONS]"))
|
||||
.stdout(predicate::str::contains("--mock"))
|
||||
.stdout(predicate::str::contains("Examples:"))
|
||||
.stdout(predicate::str::contains(
|
||||
"Homebrew: brew tap bybrooklyn/openbitdo && brew install openbitdo",
|
||||
))
|
||||
.stdout(predicate::str::contains(
|
||||
"macOS packages are currently unsigned and non-notarized.",
|
||||
))
|
||||
.stdout(predicate::str::contains("Commands:").not())
|
||||
.stdout(predicate::str::contains("ui").not())
|
||||
.stdout(predicate::str::contains("run").not());
|
||||
.stdout(predicate::str::contains("run [OPTIONS]").not());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
26
sdk/scripts/check_docs_consistency.sh
Executable file
26
sdk/scripts/check_docs_consistency.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
cd "$ROOT"
|
||||
|
||||
if rg -n \
|
||||
--glob '*.md' \
|
||||
--glob '*.yml' \
|
||||
--glob '*.sh' \
|
||||
--glob '*.rb' \
|
||||
--glob 'PKGBUILD' \
|
||||
--glob '.SRCINFO' \
|
||||
-g '!CHANGELOG.md' \
|
||||
'v0\.0\.1-rc\.1|v0\.0\.1-rc\.2|0\.0\.1-rc\.1|0\.0\.1-rc\.2|0\.0\.1rc1|0\.0\.1rc2' \
|
||||
.github \
|
||||
README.md \
|
||||
MIGRATION.md \
|
||||
RC_CHECKLIST.md \
|
||||
packaging \
|
||||
process \
|
||||
sdk \
|
||||
spec; then
|
||||
echo "stale rc.1/rc.2 references remain outside CHANGELOG.md" >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -3,7 +3,7 @@ set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
REPO_ROOT="$(cd "$ROOT/.." && pwd)"
|
||||
VERSION="${1:-v0.0.1-rc.1}"
|
||||
VERSION="${1:-v0.0.0-local}"
|
||||
ARCH_LABEL="${2:-$(uname -m)}"
|
||||
TARGET_TRIPLE="${3:-}"
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
REPO_ROOT="$(cd "$ROOT/.." && pwd)"
|
||||
VERSION="${1:-v0.0.1-rc.1}"
|
||||
VERSION="${1:-v0.0.0-local}"
|
||||
ARCH_LABEL="${2:-arm64}"
|
||||
TARGET_TRIPLE="${3:-aarch64-apple-darwin}"
|
||||
INSTALL_PREFIX="${4:-/opt/homebrew/bin}"
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# Alias Index
|
||||
|
||||
OpenBitdo uses a strict no-duplicate PID model in runtime and canonical spec tables.
|
||||
These legacy names are preserved here as aliases only.
|
||||
OpenBitdo keeps one canonical row per PID. Historical duplicate names are tracked here as aliases only.
|
||||
|
||||
| Alias PID Name | Canonical PID Name | PID (hex) | Note |
|
||||
| --- | --- | --- | --- |
|
||||
| `PID_Pro2_OLD` | `PID_Pro2` | `0x6003` | Legacy constant alias in 8BitDo source; runtime/spec use only `PID_Pro2`. |
|
||||
| `PID_ASLGMouse` | `PID_Mouse` | `0x5205` | Alias constant maps to the same PID as `PID_Mouse`; runtime/spec use only `PID_Mouse`. |
|
||||
| `PID_Pro2_OLD` | `PID_Pro2` | `0x6003` | Historical constant alias; runtime and specs use `PID_Pro2`. |
|
||||
| `PID_ASLGMouse` | `PID_Mouse` | `0x5205` | Historical alias for the same canonical mouse PID. |
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
# Device Name Catalog
|
||||
|
||||
This catalog is the sanitized naming source of truth for OpenBitdo runtime/docs.
|
||||
Canonical rows are unique by PID (no duplicates in this table).
|
||||
This catalog is the canonical PID-to-name reference for OpenBitdo.
|
||||
Use it when you need a stable display name for runtime UI, docs, packaging copy, or evidence review.
|
||||
|
||||
## How To Use This Catalog
|
||||
|
||||
- Match devices by `pid_hex` first.
|
||||
- Treat `display_name_en` as the preferred user-facing label.
|
||||
- Keep aliases out of new canonical rows; add them to the `aliases` column and the alias index instead.
|
||||
- When confidence is low or the source is `internal-fallback`, treat the name as provisional until better evidence is collected.
|
||||
|
||||
| canonical_pid_name | pid_hex | display_name_en | protocol_family | name_source | source_confidence | aliases |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
@@ -64,5 +71,7 @@ Canonical rows are unique by PID (no duplicates in this table).
|
||||
| PID_ASLGJP | 0x205a | Riviera Keyboard | JpHandshake | vendor-language-map | high | |
|
||||
|
||||
## Notes
|
||||
- Name-source references are indexed in `/Users/brooklyn/data/8bitdo/cleanroom/process/device_name_sources.md`.
|
||||
- Alias names are documented in `/Users/brooklyn/data/8bitdo/cleanroom/spec/alias_index.md` and intentionally excluded from canonical PID rows.
|
||||
|
||||
- Canonical rows are unique by PID. Do not duplicate a PID to reflect a marketing alias.
|
||||
- Name-source evidence is indexed in `/Users/brooklyn/data/8bitdo/cleanroom/process/device_name_sources.md`.
|
||||
- Alias names live in `/Users/brooklyn/data/8bitdo/cleanroom/spec/alias_index.md` and stay out of the primary PID rows unless they become the canonical public name.
|
||||
|
||||
@@ -1,98 +1,93 @@
|
||||
# 8BitDo Clean-Room Protocol Specification (Sanitized)
|
||||
# OpenBitdo Protocol Overview
|
||||
|
||||
## Scope
|
||||
This document defines a sanitized command and transport contract for a clean-room Rust implementation.
|
||||
It is intentionally independent from reverse-engineered source code details and uses stable requirement IDs.
|
||||
This document summarizes the sanitized protocol model used by the clean-room runtime.
|
||||
|
||||
## Wire Model
|
||||
- Transport: HID-like reports
|
||||
- Primary report width: 64 bytes (`Standard64`, `DInput`, `JpHandshake` families)
|
||||
- Variable-length reports: allowed for boot/firmware phases
|
||||
- Byte order: little-endian for multi-byte numeric fields
|
||||
|
||||
- HID-like command transport
|
||||
- primary 64-byte reports for `Standard64`, `DInput`, and `JpHandshake`
|
||||
- variable-length reports only where firmware or boot phases require them
|
||||
- little-endian multi-byte numbers
|
||||
|
||||
## Protocol Families
|
||||
- `Standard64`: standard 64-byte command and response flow
|
||||
- `JpHandshake`: alternate handshake and version probing workflow
|
||||
- `DInput`: command family used for mode and runtime profile operations
|
||||
- `DS4Boot`: reserved boot mode for DS4-style update path
|
||||
- `Unknown`: fallback for unknown devices
|
||||
|
||||
- `Standard64`
|
||||
- `JpHandshake`
|
||||
- `DInput`
|
||||
- `DS4Boot`
|
||||
- `Unknown`
|
||||
|
||||
## Safety Classes
|
||||
- `SafeRead`: read-only operations
|
||||
- `SafeWrite`: runtime settings/profile writes
|
||||
- `UnsafeBoot`: bootloader transitions with brick risk
|
||||
- `UnsafeFirmware`: firmware transfer/commit operations with brick risk
|
||||
|
||||
## Response Validation Contract
|
||||
- Responses are validated per command against byte-pattern expectations from `command_matrix.csv`
|
||||
- Validation outcomes: `Ok`, `Invalid`, `Malformed`
|
||||
- Retry policy applies on `Malformed` or timeout responses
|
||||
- `SafeRead`: diagnostics and metadata reads
|
||||
- `SafeWrite`: profile, setting, or mapping writes
|
||||
- `UnsafeBoot`: bootloader transitions
|
||||
- `UnsafeFirmware`: firmware transfer and commit operations
|
||||
|
||||
## Response Validation
|
||||
|
||||
- every command validates against the registry table
|
||||
- outcomes are `Ok`, `Invalid`, or `Malformed`
|
||||
- retry logic applies on timeout or malformed data according to session policy
|
||||
|
||||
## Operation Groups
|
||||
- `Core`: generic identify/mode/profile/boot/fallback commands
|
||||
- `JP108Dedicated`: 108-key dedicated-button mapping + feature/voice operations
|
||||
- `Ultimate2Core`: Ultimate2 mode/slot/core-map operations
|
||||
- `Firmware`: device-scoped firmware enter/chunk/commit/exit operations
|
||||
- `CoreDiag`: decompiler-first detect/diagnostic command subset for candidate-readonly PIDs
|
||||
- `ModeProfileRead`: decompiler-first read-only mode/profile snapshot group for candidate-readonly PIDs
|
||||
- `FirmwarePreflight`: decompiler-first firmware readiness metadata reads (no transfer enablement)
|
||||
|
||||
## JP108 Dedicated Support
|
||||
- Supported targets: `0x5209` (`PID_108JP`), `0x520a` (`PID_108JPUSB`)
|
||||
- First milestone mapping scope: `A`, `B`, `K1`-`K8`
|
||||
- Additional controls in this group:
|
||||
- feature flags read/write
|
||||
- voice setting read/write
|
||||
- Full 111-key matrix remap is explicitly out of scope for this milestone.
|
||||
- `Core`
|
||||
- `JP108Dedicated`
|
||||
- `Ultimate2Core`
|
||||
- `Firmware`
|
||||
- `CoreDiag`
|
||||
- `ModeProfileRead`
|
||||
- `FirmwarePreflight`
|
||||
|
||||
## Ultimate2 Core Support
|
||||
- Supported targets: `0x6012` (`PID_Ultimate2`), `0x6013` (`PID_Ultimate2RR`)
|
||||
- First milestone editable scope:
|
||||
- current mode read/set
|
||||
- current slot read
|
||||
- slot config read/write
|
||||
- core button map read/write
|
||||
- Advanced subsystems (theme/sixaxis/deep macro editing) are intentionally hidden in this milestone.
|
||||
## Support Model
|
||||
|
||||
## PID-Aware Command Gating
|
||||
- Command availability is gated by:
|
||||
1. safety class and runtime unsafe acknowledgements
|
||||
2. capability flags
|
||||
3. explicit PID allowlist from `command_matrix.csv:applies_to`
|
||||
- `applies_to="*"` means globally available within existing safety/capability constraints.
|
||||
### Support Levels
|
||||
|
||||
## Device Support Levels
|
||||
- `full`: command execution permitted for safe and unsafe operations (with user gates)
|
||||
- `detect-only`: identification allowed; unsupported operations return `UnsupportedForPid`
|
||||
- `full`
|
||||
- `detect-only`
|
||||
|
||||
## Support Tiers
|
||||
- `full`: read/write/unsafe operations available according to existing safety gates.
|
||||
- `candidate-readonly`: detect/diag safe reads are allowed per PID allowlist; safe writes and unsafe flows are blocked.
|
||||
- `detect-only`: identify-only posture for unsupported or unknown PIDs.
|
||||
### Support Tiers
|
||||
|
||||
## Candidate Read-Only Wave Policy
|
||||
- Wave-1 and Wave-2 expansion PIDs are classified as `candidate-readonly`.
|
||||
- Command policy for this tier:
|
||||
- allow: detect/diag safe-read subset.
|
||||
- allow: read-only mode/profile snapshot reads when family-appropriate.
|
||||
- allow: firmware metadata/preflight reads only.
|
||||
- deny: all safe-write operations.
|
||||
- deny: all unsafe boot/firmware operations.
|
||||
- Promotion from `candidate-readonly` to `full` requires 3-signal evidence:
|
||||
1. static dossier coverage
|
||||
2. runtime trace evidence
|
||||
3. hardware read/write/readback confirmation
|
||||
- `full`: normal read, write, and gated unsafe paths
|
||||
- `candidate-readonly`: safe-read diagnostics only
|
||||
- `detect-only`: identify-only posture
|
||||
|
||||
## Dossier Linkage
|
||||
- Per-PID operation evidence is tracked in `spec/dossiers/**`.
|
||||
- `command_matrix.csv:dossier_id` links command rows to sanitized dossier artifacts.
|
||||
- `evidence_index.csv` maps PID to class-family anchors and operation groups.
|
||||
## Candidate Read-Only Policy
|
||||
|
||||
## Required Runtime Gating
|
||||
Unsafe commands execute only when both conditions are true:
|
||||
1. `--unsafe`
|
||||
2. `--i-understand-brick-risk`
|
||||
Read-only candidates may:
|
||||
|
||||
## Clean-Room Requirements Linkage
|
||||
Implementation and tests must trace to IDs in `requirements.yaml`.
|
||||
All public APIs and behavior are governed by `REQ-PROT-*`, `REQ-PID-*`, `REQ-SAFE-*`, and `REQ-TEST-*` IDs.
|
||||
- identify themselves
|
||||
- run allowed safe-read diagnostics
|
||||
- perform family-appropriate read-only metadata checks
|
||||
|
||||
Read-only candidates may not:
|
||||
|
||||
- write mappings or profiles
|
||||
- enter unsafe boot paths
|
||||
- transfer firmware
|
||||
|
||||
Promotion to full support requires:
|
||||
|
||||
1. static evidence
|
||||
2. runtime evidence
|
||||
3. hardware evidence
|
||||
|
||||
## Feature Scopes
|
||||
|
||||
### JP108
|
||||
|
||||
- supported targets: `0x5209`, `0x520a`
|
||||
- current mapping scope: `A`, `B`, `K1`-`K8`
|
||||
|
||||
### Ultimate 2
|
||||
|
||||
- supported targets: `0x6012`, `0x6013`
|
||||
- current scope: mode, slot, slot config, core button map, and required analog handling
|
||||
|
||||
## Runtime Safety Rule
|
||||
|
||||
Unsafe commands are only allowed when the runtime has both:
|
||||
|
||||
1. unsafe mode enabled
|
||||
2. explicit brick-risk acknowledgment
|
||||
|
||||
Reference in New Issue
Block a user