Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
d332ad0
chore(deps): bump the actions-minor-and-patch group across 1 director…
dependabot[bot] Oct 12, 2026
908b033
chore(deps): bump motion from 13.5.1 to 14.0.0 in /Tools/Controller/web
dependabot[bot] Oct 12, 2026
a37e2b8
feat(virtual): support isolated Pealayer development and mapped host …
DRSDavidSoft Oct 12, 2026
9435492
test(virtual): verify live host sensor source and honor shared enviro…
DRSDavidSoft Oct 12, 2026
710b2d6
fix(virtual): make development profile ownership and seeding descript…
DRSDavidSoft Oct 12, 2026
dffba35
fix(virtual): use explicit exclusive ownership-marker creation
DRSDavidSoft Oct 12, 2026
1967669
Merge remote-tracking branch 'origin/main' into feat/virtual-development
DRSDavidSoft Oct 12, 2026
bd378ae
fix(virtual): retain one ownership descriptor throughout development …
DRSDavidSoft Oct 12, 2026
9f9c37b
feat(mobile): add live channel state, telemetry charts and authentica…
DRSDavidSoft Oct 12, 2026
26a0604
feat(mobile): polish unified controls, preferences and native beep mi…
DRSDavidSoft Oct 12, 2026
2afac32
docs(mobile): retain launcher artwork provenance and current peer con…
DRSDavidSoft Oct 12, 2026
b36af2c
test(mobile): await branding decode in settings capture
DRSDavidSoft Oct 12, 2026
3697520
feat: add binary UDP RPC, discovery and leased events [skip ci]
DRSDavidSoft Oct 12, 2026
f39cde1
fix: guard UDP peer routing against recursive pivots [skip ci]
DRSDavidSoft Oct 12, 2026
1543802
feat(mobile): add interactive sequence and native cue timing editors
DRSDavidSoft Oct 12, 2026
4bfe948
feat: verified app discovery and consented peer APK upgrades [skip ci]
DRSDavidSoft Oct 12, 2026
a0d796e
fix: bound APK staging and cancel disposed progress notifications [sk…
DRSDavidSoft Oct 12, 2026
a83b52b
feat(mobile): unify expert workspace, preferences and peer activities…
DRSDavidSoft Oct 12, 2026
4827645
fix: refresh APK peer discovery interfaces on link changes [skip ci]
DRSDavidSoft Oct 12, 2026
1e220d1
fix: fence stale PWM reads and reconcile typed write receipts [skip ci]
DRSDavidSoft Oct 12, 2026
9b2cc9e
docs: record PWM reconciliation and relay layout contract [skip ci]
DRSDavidSoft Oct 13, 2026
826cd66
fix: preserve fractional PWM automation percentages [skip ci]
DRSDavidSoft Oct 13, 2026
7200fe3
fix(mobile): retain PWM edits and configure relay card layout [skip ci]
DRSDavidSoft Oct 13, 2026
4557cb2
docs(mobile): record bug-fix APK delivery and remaining Android gates…
DRSDavidSoft Oct 13, 2026
94ef33a
fix: preserve panel edges and fresh short mirrored notes [skip ci]
DRSDavidSoft Oct 13, 2026
6b4692e
fix: retain short notes across fresh scheduler handoff [skip ci]
DRSDavidSoft Oct 13, 2026
7c067ba
fix: keep short note durations after timer wakeup [skip ci]
DRSDavidSoft Oct 13, 2026
564791b
fix: retain cross-source ordering after playout recovery [skip ci]
DRSDavidSoft Oct 13, 2026
d7ed73a
docs: record Linux mirrored-note delivery and remaining visual gate […
DRSDavidSoft Oct 13, 2026
0db4765
feat(mobile): restore roomy charts and configurable muted styling [sk…
DRSDavidSoft Oct 13, 2026
ddbb95c
docs(mobile): record appearance APK and exact Android delivery [skip ci]
DRSDavidSoft Oct 13, 2026
177f4c2
fix(mobile): preserve scroll geometry during front-panel loading [ski…
DRSDavidSoft Oct 13, 2026
3fcdd5c
fix(mobile): color relay power semantically and center card text [ski…
DRSDavidSoft Oct 13, 2026
0920b98
style(mobile): format semantic relay style regression [skip ci]
DRSDavidSoft Oct 13, 2026
03925e4
fix(mobile): maintain readable semantic relay fill contrast [skip ci]
DRSDavidSoft Oct 13, 2026
884f1a8
feat(mobile): reorder outputs and rename captions inline [skip ci]
DRSDavidSoft Oct 13, 2026
20d50a0
docs(mobile): record outputs APK deployment and acceptance gates [ski…
DRSDavidSoft Oct 13, 2026
19672cf
fix(mobile): stabilize PWM readback freshness and stale presentation …
DRSDavidSoft Oct 13, 2026
fddb33d
docs(mobile): record PWM stability diagnosis and tablet fix delivery …
DRSDavidSoft Oct 13, 2026
db8bcb7
fix(mobile): preserve buzzer cadence and native PCM playback [skip ci]
DRSDavidSoft Oct 13, 2026
b84fe9d
docs(mobile): record buzzer package and tablet delivery [skip ci]
DRSDavidSoft Oct 13, 2026
0d978d6
feat(mobile): add stable read-only pull to refresh [skip ci]
DRSDavidSoft Oct 13, 2026
a35509a
docs(mobile): record pull refresh checks and tablet delivery [skip ci]
DRSDavidSoft Oct 13, 2026
fe02a1e
fix(web): resolve channel names and preserve PWM gestures [skip ci]
DRSDavidSoft Oct 13, 2026
9838d92
fix(web): resolve channel names and preserve PWM gestures [skip ci]
DRSDavidSoft Oct 13, 2026
c561c20
feat(mobile): adapt PU850 endpoint and dialog experience [skip ci]
DRSDavidSoft Oct 13, 2026
915708c
docs(mobile): record PU850 import and Android delivery [skip ci]
DRSDavidSoft Oct 13, 2026
37ef730
docs: record Cafe Web channel controls delivery and gates [skip ci]
DRSDavidSoft Oct 13, 2026
78b79f2
docs: record Cafe Web channel controls delivery and gates [skip ci]
DRSDavidSoft Oct 13, 2026
0eef88b
feat(mobile): make hardware workspace contextual and event driven [sk…
DRSDavidSoft Oct 13, 2026
e05ebc9
fix: preserve terminal startup and hide owned background consoles [sk…
DRSDavidSoft Oct 13, 2026
7ebf4a5
fix: hide owned background consoles and show immediate TUI startup [s…
DRSDavidSoft Oct 13, 2026
c2b4d0b
docs(mobile): record contextual utility tablet delivery [skip ci]
DRSDavidSoft Oct 13, 2026
b4c847a
docs: record verified Cafe console startup delivery [skip ci]
DRSDavidSoft Oct 13, 2026
b3d108a
docs: record Cafe startup console delivery and acceptance boundaries …
DRSDavidSoft Oct 13, 2026
db407fc
fix: bound strip serial occupancy and PWM acknowledgement replies [sk…
DRSDavidSoft Oct 13, 2026
969969c
fix: bound strip serial occupancy and PWM acknowledgement replies [sk…
DRSDavidSoft Oct 13, 2026
4c5230b
docs: record Cafe serial response delivery and native draft hold [ski…
DRSDavidSoft Oct 13, 2026
3e5f63e
docs: record Cafe serial response delivery and native draft hold [ski…
DRSDavidSoft Oct 13, 2026
49484dc
fix(deps): reconcile Motion update and canonical Web lock on current …
DRSDavidSoft Oct 13, 2026
1f9f2b2
feat(mobile): port Go controller tools and validated settings workflo…
DRSDavidSoft Oct 13, 2026
e0f9e71
docs(mobile): record Go tools tablet delivery and remaining gates [sk…
DRSDavidSoft Oct 13, 2026
b07b9ca
fix: deliver final live values to controller clients
DRSDavidSoft Oct 13, 2026
dec929f
docs: record verified Android 0.1.13 delivery and phone gate
DRSDavidSoft Oct 13, 2026
fe214f6
feat: refine unified controller UI and contextual authoring
DRSDavidSoft Oct 13, 2026
55c747d
fix: disable numeric editing while technical changes are pending
DRSDavidSoft Oct 13, 2026
73d8014
docs: record Android UI update delivery and remaining acceptance
DRSDavidSoft Oct 13, 2026
6fb2609
fix: show terminal UI for interactive Web hosts [skip ci]
DRSDavidSoft Oct 13, 2026
35cfef2
docs: record Web terminal package provenance [skip ci]
DRSDavidSoft Oct 13, 2026
121a71d
Integrate Web controls while retaining native sensor names and calibr…
DRSDavidSoft Oct 13, 2026
94fcf3d
Integrate owned console hiding without disabling the Web-host TUI
DRSDavidSoft Oct 13, 2026
9be6b29
Integrate bounded serial/PWM deadlines for the rollout
DRSDavidSoft Oct 13, 2026
5c66abd
Integrate locked Motion dependency update
DRSDavidSoft Oct 13, 2026
3054562
Integrate pinned GitHub Actions updates
DRSDavidSoft Oct 13, 2026
3fcb769
Constrain native sensor sources to owned adapters and Linux sysfs
DRSDavidSoft Oct 13, 2026
352e637
Repair integrated deadlines and current profile/API merge checks
DRSDavidSoft Oct 13, 2026
282232d
Restore full AVR footprint and verify responsive integration contracts
DRSDavidSoft Oct 13, 2026
755d0d5
Reduce live PWM projection work and fit optional AVR labels
DRSDavidSoft Oct 13, 2026
62998fc
Fail closed when development metadata creation races
DRSDavidSoft Oct 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/scripts/repository-policy.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ const policyDefinitionPaths = new Set([

// Current-product links are permitted only in maintained public entry points.
const repositoryIdentityPaths = new Set([
"docs/WEB-HOST-TERMINAL.md",
"docs/verification/serial-response-deadlines.md",
"docs/verification/web-channel-controls.md",
"README.md",
"docs/Alpha-Delivery-Ledger.md",
"docs/CI-CD-and-Releases.md",
Expand All @@ -36,6 +39,7 @@ const repositoryIdentityPaths = new Set([
// repository; private paths, stale-origin language and unrelated URLs remain
// forbidden.
const reviewedExternalRepositories = new Map([
["docs/verification/serial-response-deadlines.md", new Set(["toghroltp/pealayer"])],
["mobile/assets/fonts/Vazirmatn-OFL.txt", new Set(["rastikerdar/vazirmatn"])],
["mobile/PAKAR-README.md", new Set(["atomicdeploy/pakarcontroller"])],
["docs/Shared-Production-Firmware.md", new Set(["mcudude/megacore"])],
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- name: "🟢 Install Node.js"
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: "24"

Expand All @@ -66,7 +66,7 @@ jobs:
> build-downloads/artifact-index.json

- name: "⬇️ Download build artifacts"
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
with:
pattern: PCController-*
path: build-downloads
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ jobs:

- name: "🟢 Install Node.js"
if: matrix.key == 'cpp-avr-linux'
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: "24"

Expand Down Expand Up @@ -132,7 +132,7 @@ jobs:
node -e 'const { execFileSync } = require("node:child_process"); for (const library of JSON.parse(process.env.ARDUINO_LIBRARIES_JSON)) execFileSync("arduino-cli", ["lib", "install", library], { stdio: "inherit" });'

- name: "🛡️ Initialize CodeQL"
uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
uses: github/codeql-action/init@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build_mode }}
Expand Down Expand Up @@ -200,7 +200,7 @@ jobs:
if errorlevel 1 exit /b 1

- name: "🔬 Analyze and upload CodeQL results"
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
uses: github/codeql-action/analyze@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
with:
category: ${{ matrix.category }}

Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/deploy-avr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ jobs:
persist-credentials: false

- name: "🟢 Install Node.js"
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: "24"

Expand Down Expand Up @@ -145,7 +145,7 @@ jobs:

- name: "⬆️ Upload immutable programming bundle"
id: upload
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
with:
name: PCController-Verified-Deployment-Bundle
path: deployment-bundle
Expand Down Expand Up @@ -213,7 +213,7 @@ jobs:
cache-dependency-path: Tools/Controller/go.sum

- name: "🟢 Install Node.js"
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: "24"

Expand Down Expand Up @@ -253,7 +253,7 @@ jobs:
printf 'Verified AVRDUDE backend: %s\n' "$avrdude"

- name: "⬇️ Download verified programming bundle"
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
with:
name: PCController-Verified-Deployment-Bundle
path: deployment-bundle
Expand Down Expand Up @@ -317,7 +317,7 @@ jobs:
- name: "⬆️ Preserve physical deployment evidence"
if: always()
id: evidence
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
with:
name: PCController-Deployment-Evidence-${{ github.run_id }}
path: deployment-evidence
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/firmware.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- name: "🟢 Install Node.js"
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: "24"

Expand Down Expand Up @@ -150,7 +150,7 @@ jobs:

- name: "⬆️ Upload firmware artifact"
id: upload
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
with:
name: ${{ steps.pins.outputs.product_slug }}-Firmware-ATmega328P
path: .build/actions-artifact/*
Expand Down Expand Up @@ -207,7 +207,7 @@ jobs:
node Tools/Firmware/targets.mjs build mega2560 expanded-autonomous

- name: "⬆️ Preserve build-only ATmega2560 evidence (not a commissioned release)"
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
with:
name: BuildOnly-ATmega2560-Targets
path: .build/firmware/mega2560
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/host.yml
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ jobs:
ctest --test-dir .build/controller-cabi --output-on-failure

- name: "🟢 Install Node.js"
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: ${{ steps.host-dependencies.outputs.node_version }}

Expand All @@ -148,7 +148,7 @@ jobs:

- name: "⬇️ Download the exact validated firmware defaults"
if: inputs.firmware_artifact_name != ''
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
with:
name: ${{ inputs.firmware_artifact_name }}
path: .build/firmware
Expand Down Expand Up @@ -236,7 +236,7 @@ jobs:

- name: "⬆️ Upload Host artifact"
id: upload
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
with:
name: PCController-Host-${{ matrix.target }}
path: |
Expand All @@ -263,7 +263,7 @@ jobs:
run: node Tools/Dependencies/export-lock.mjs export-host --output "$GITHUB_OUTPUT"

- name: "🟢 Install Node.js"
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: ${{ steps.summary-host-dependencies.outputs.node_version }}

Expand All @@ -288,7 +288,7 @@ jobs:
- name: "⬇️ Download available Host artifacts"
if: ${{ always() }}
continue-on-error: true
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
with:
pattern: PCController-Host-*
path: build-summary/packages
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,12 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- name: "🟢 Install Node.js"
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: "24"

- name: "⬇️ Download build artifacts"
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
with:
pattern: PCController-*
path: release-downloads
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/repository-health.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
run: node Tools/Dependencies/export-lock.mjs export-host --output "$GITHUB_OUTPUT"

- name: "🟢 Install Node.js"
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: ${{ steps.host-dependencies.outputs.node_version }}

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/update-dependencies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
cache-dependency-path: Tools/Controller/go.sum

- name: Install current Node.js LTS
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: lts/*
cache: npm
Expand Down Expand Up @@ -79,7 +79,7 @@ jobs:

- name: Upload resolution, hash, and validation evidence
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
with:
name: dependency-resolution-${{ github.run_id }}
path: |
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/virtual-board.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- name: "🟢 Install Node.js"
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: "24"

Expand Down Expand Up @@ -108,7 +108,7 @@ jobs:

- name: "⬆️ Upload Virtual Board artifact"
id: upload
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
with:
name: PCController-VirtualBoard-${{ matrix.target }}
path: |
Expand All @@ -130,7 +130,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- name: "🟢 Install Node.js"
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: "24"

Expand All @@ -155,7 +155,7 @@ jobs:
- name: "⬇️ Download available Virtual Board artifacts"
if: ${{ always() }}
continue-on-error: true
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
with:
pattern: PCController-VirtualBoard-*
path: build-summary/packages
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ yarn-error.log*
pnpm-debug.log*

# MCU/virtual-board runtime state and backups
/build-programs/
virtual-mcu-eeprom.bin
*.eeprom
*.backup
Expand Down
18 changes: 18 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,21 @@
## Digitalogic interface design

Before implementing or reviewing any user-facing interface, read and follow [Contextual UI and no narration](docs/CONTEXTUAL-UI.md). This standing ecosystem contract covers state-driven rendering, progressive disclosure, semantic actions, conditional affordances and stable layout. Apply it across related controls, preserving existing safety and authorization requirements.

## Unified controller application - mandatory acceptance

- The current basic Flutter design is rejected. Build one expert utility workspace, not separate PCController/Pealayer product tabs. Organize by useful activities and current capabilities; peers and branding are contextual identities, not duplicate navigation hierarchies.
- Use one contextual connection action per peer. Connect/cancel may be first-class while disconnected/connecting; The latest direct request uses one compact lifecycle toggle: Connect, Cancel while connecting, or Disconnect when connected. Never show competing connection verbs together. Preserve explicit disconnect discovery opt-out. Hide dormant access-token inputs while the current products do not require authentication. Defer a complete multi-step authentication/authorization flow; do not introduce token placeholders or a partial login design.
- Omit unavailable-only cards and irrelevant controls. Never publish unknown measurements as zero. Remove filler narration such as "last values unavailable" and boilerplate explanations of ordinary behavior. Preserve concise, actionable failures, stale-state/safety indicators and outcome-unknown errors.
- Use compact, professionally composed phone/tablet layouts: aligned headers, meaningful cards, contextual dialogs, square accessible icon actions, semantic colors/pills, real live charts and efficient space. Rich styling must remain coherent, legible and useful; neither oversized generic buttons nor a plain basic navigation shell is accepted.
- Refresh from authoritative events, coalesce unchanged work and retain last good state. Do not add per-frame network probes, persistence, synthetic telemetry or automatic mutation retries.
- Preferences own appearance, density, branding, palettes (including the original PakarController schemes), activity/task icon and one or both launcher identities. Both launcher entries must open the same unified application. Check actual Android icon/alias behavior rather than claiming a Dart preference changed OS state.
- DNS-SD/mDNS, SSDP and MNDP must be implemented/coordinated across PCController, Pealayer and Flutter, with real service identity and endpoint verification. Auto-connect valid discovered peers according to saved user intent, but never treat a raw advertisement as proof, silently replace a live selected peer, take board authority or actuate outputs.
- Android peers must support bounded, verified app-package upload/download and upgrades through the existing IPC/RPC transport. Preserve package identity/signature checks, unknown-outcome handling and Android user-consent/install permissions; no silent install or arbitrary path/URL proxy.
- Source/build/device screenshots are separate from live transport, physical/audio acceptance and David's design acceptance. Keep rejected/incomplete gates open, preserve concurrent authoring work and record source provenance before deployment.

- The latest contextual-utility rejection remains authoritative: no idle effect Cancel/Stop actions, empty live-only cards, unavailable-only fact cards or static "last values unavailable" narration. Keep actionable exceptions and useful offline editors. Hardware controls use balanced equal-width action rows within compact cards, semantic ON/OFF colors and directly clickable observed relay indicators with the same current-owner/lock/E-STOP gates. Folder assignment is a catalog-driven dropdown scoped to output kind and preserving raw folder identity, not a plain text field. Refresh is explicit and event-driven; only failed/stale/unsupported WebSocket transport uses bounded fallback reads. Preserve acknowledged PWM drafts, current profile-resolved names, and owner/revision fences. Native network discovery, auto-connect intent, branding/task icons and dual launcher aliases, all existing color schemes and integrity-checked peer IPC/RPC app transfers remain acceptance requirements. Defer remote multi-step authentication until supported; hide unused remote token fields without weakening protected local automation. Every new surface follows this contract without another user reminder.

- Live continuous values retain a quiet final update per domain; do not drop it through throttling or collapse RGB/PWM into one shared latest slot. Complete calibrated push observations carry selected host, board generation, monotonic revision and time. Buffer bounded notifications until subscription ACK; fence replaced owners and older reads, and preserve active edits/acknowledged setpoints. Healthy complete pushes must not trigger per-client HTTP/PWM polling. Audio/segments/lifecycle stay immediate. Typed request/response relay must retain honest bounded fallback rather than treating player WS as a controller subscription. Record Android installed identity per reachable device separately from source, physical, audio and human acceptance.

- Apply the folder-dropdown contract to effect/Studio authoring as well as hardware assignments. Preserve current raw category identity; creating a new folder is a separate explicit action. Effect/cue/settings dialogs share bounded keyboard-aware chrome, explicit Close/Cancel and fixed busy progress space. Invalid numeric edits survive selection changes and block saving; never silently retain the old number behind invalid input. Unapplied technical JSON must not be overwritten by typed controls. Pending saves disable editable fields; failures preserve drafts and unchanged Save sends no mutation. Resource URL normalization changes authority characters only, retaining native paths, query and Unicode filename semantics. Keep mobile/UI-REQUIREMENT-LEDGER.md current and never mark all UI/hardware accepted from source fixtures or delivery.
2 changes: 1 addition & 1 deletion LocalLib/DallasTemperatureBus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void DallasTemperatureBus::begin() {
// Optional explicit device fixtures; runtime owns discovery and conversion.
addressCount_ = 0;
for (uint8_t index = 0; index < 2; ++index) {
if (NativeHal::temperature[index] == DisconnectedCentiC) continue;
if (!NativeHal::temperatureConfigured[index] && NativeHal::temperature[index] == DisconnectedCentiC) continue;
uint8_t *rom = addresses_[addressCount_++];
memset(rom, 0, 8); rom[0] = Ds18b20Family; rom[1] = index + 1;
rom[7] = crc8(rom, 7);
Expand Down
7 changes: 2 additions & 5 deletions Project/IlluminationController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ void IlluminationController::begin(PwmController &pwm, bool doorOpen,
pwm_ = &pwm;
currentBrightness_ =
mode_ == IlluminationMode::On ? onBrightness_ : offBrightness_;
pwm_->setEnclosureIllumination(
static_cast<uint16_t>(currentBrightness_) * 16U +
currentBrightness_ / 16U);
pwm_->setEnclosureIllumination(TransitionMath::expandByte12(currentBrightness_));
lastFadeAt_ = now;
initialized_ = true;

Expand Down Expand Up @@ -56,8 +54,7 @@ void IlluminationController::service(bool doorOpen, bool allowLedUpdate,
// jitter while preserving the responsive 20 ms control cadence.
lastFadeAt_ = now;
const uint8_t next = TransitionMath::easedByte(currentBrightness_, target);
if (pwm_->setEnclosureIllumination(
static_cast<uint16_t>(next) * 16U + next / 16U)) {
if (pwm_->setEnclosureIllumination(TransitionMath::expandByte12(next))) {
currentBrightness_ = next;
}
}
Expand Down
11 changes: 11 additions & 0 deletions Project/Ina219Sensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,25 @@ constexpr uint16_t Calibration32V2A = 4096;
} // namespace

bool Ina219Sensor::begin() {
#if defined(PCCONTROLLER_NATIVE)
return NativeHal::powerAvailable;
#else
i2cBus.beginTransmission(address_);
if (i2cBus.endTransmission() != 0) {
return false;
}
return write16(CalibrationRegister, Calibration32V2A) &&
write16(ConfigRegister, Config32V2A);
#endif
}

bool Ina219Sensor::read(Ina219Reading &reading) {
#if defined(PCCONTROLLER_NATIVE)
if (!NativeHal::powerAvailable) return false;
reading = {NativeHal::supplyMilliVolts, NativeHal::supplyMilliVolts,
NativeHal::currentMilliAmps, NativeHal::powerMilliWatts};
return true;
#else
// Some compatible devices clear calibration after reset; refreshing it also
// matches the established Adafruit 32V/2A measurement sequence.
if (!write16(CalibrationRegister, Calibration32V2A)) {
Expand Down Expand Up @@ -61,6 +71,7 @@ bool Ina219Sensor::read(Ina219Reading &reading) {
: (signedCurrent - 5L) / 10L;
reading.powerMilliWatts = static_cast<uint32_t>(powerRaw) * 2UL;
return true;
#endif
}

bool Ina219Sensor::write16(uint8_t reg, uint16_t value) {
Expand Down
Loading
Loading