Skip to content
This repository was archived by the owner on Nov 12, 2026. It is now read-only.

Commit 2a9123e

Browse files
techmoreSean Dolbec
andauthored
Add SDK app generation, runtime contracts and native validation (#609)
* fix(msdk): preserve literal names in generated starters * feat(msdk): generate standalone typed GTK applications and qualify the developer path * test(msdk): provision and pin offline generated model dependencies * feat(msdk): package generated native apps and validate install lifecycle * fix(msdk): qualify native lifecycle, schema, keyboard controls and presentation * test(msdk): retain source-matched native qualification receipts and bounded CI provisioning * Add typed service replies, owned processes and storage reference flow * Retain source-matched macOS runtime and reference-flow validation * Add bounded process streaming and owned partial output subscriptions * Retain exact-source bounded streaming qualification on macOS * Validate manifests atomically and publish candidate compatibility policy * Retain version and atomic-manifest core qualification receipts * Stop SDK commands and preview on manifest or activation failures * Retain executable CLI failure-path qualification receipts * Add request context generations and scoped process cancellation * Retain request context and scoped process qualification receipts * Qualify native SDK reference flow and make storage output readable * Retain source-matched native runtime and reference app qualification * Preserve request context through typed GTK reply and error queues * Retain native GTK context-delivery race qualification * Scope SDK qualification without requiring native ports of every app * Add isolated model authoring discovery harness and pinned trial inputs * Pin all model sampling penalties and retain packaged defaults * Retain offline authoring preflight and deferred model admission evidence * Qualify benchmark packaging and clean quit checks * Retain benchmark packaging preflight evidence * Bind streaming process output to request contexts * Test stale buffered streaming output after exit * Expose scenario gates to SDK authoring trials * Keep built-in feeds independent of provider version * Record source-matched ARM SDK validation * Add context-bound GTK feed delivery * Record native context-bound feed validation * Allow fixture injection of extension version mismatch * Record fixture validation and accessibility retry * Retain accessibility failure and report early app exits * Add candidate usage observation semantics * Validate usage observation snapshots * Group usage observations for presentation * Add candidate GTK usage observation rows * Capture synthetic usage component previews * Fix GTK usage orientation spelling * Retain and review candidate usage preview * Refine usage card hierarchy and stale labels * Retain refined usage card review * Add provider marks and scrolling usage fixture * Retain multi-provider usage review * Show usage provider coverage before accounts * Retain provider overview visual review * Add bounded refreshable usage viewport * Retain usage viewport refresh evidence * Decode bounded CodexBar provider snapshots * Record CodexBar decoder validation * Add scoped direct CodexBar snapshot read * Record scoped CodexBar read validation * Apply scoped usage reads safely in GTK * Record scoped usage delivery validation * Manage on-demand CodexBar refresh lifecycle * Fix refresh controller strict lint * Record on-demand usage refresh validation * Add usage refresh control and failure preview * Refine usage failure recovery prompt * Retain usage refresh failure review * Exercise usage refresh with keyboard and AT-SPI * Retain usage accessibility probe failures * Use explicit usage refresh button label * Retain usage keyboard and accessibility evidence * Add candidate usage status anchor * Check mapped state for usage anchor hover * Fix usage anchor pinning and interaction probe * Record usage anchor pointer travel diagnostics * Check pointer containment before closing usage popup * Trace usage popup pointer transitions in isolated probe * Preserve usage reads during popup pin transition * Inspect popup pointer input window * Keep usage popup open while pointer is on its surface * Verify unpinned usage popup closes on pointer exit * Record passing ARM usage anchor validation * Add opt-in SDK usage page to shared desktop status menu * Record desktop SDK host ARM workflow evidence --------- Co-authored-by: Sean Dolbec <sean@example.com>
1 parent a22e319 commit 2a9123e

355 files changed

Lines changed: 26965 additions & 210 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/msdk.yml‎

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
name: M-series SDK developer path
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
paths:
7+
- "rust/msdk/**"
8+
- "rust/msdk-gtk/**"
9+
- "rust/claude-pantheon-rs/sdk/**"
10+
- "rust/mseries-greeter/data/greeter.ui.json"
11+
- "mseries/sdk-tests/**"
12+
- "mseries/sdk-status-host/**"
13+
- "mseries/dock-taskbar/TaskbarT3RPopover.vala"
14+
- "mseries/codexbar-wingpanel/JsonBoundary.vala"
15+
- "mseries/sdk-bench/**"
16+
- ".github/workflows/msdk.yml"
17+
push:
18+
branches: [dev]
19+
paths:
20+
- "rust/msdk/**"
21+
- "rust/msdk-gtk/**"
22+
- "mseries/sdk-tests/**"
23+
- "mseries/sdk-status-host/**"
24+
- "mseries/dock-taskbar/TaskbarT3RPopover.vala"
25+
- "mseries/codexbar-wingpanel/JsonBoundary.vala"
26+
- "mseries/sdk-bench/**"
27+
- ".github/workflows/msdk.yml"
28+
29+
permissions:
30+
contents: read
31+
32+
concurrency:
33+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
34+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
35+
36+
jobs:
37+
qualify:
38+
runs-on: ubuntu-26.04-arm
39+
timeout-minutes: 25
40+
env:
41+
CARGO_TARGET_DIR: ${{ github.workspace }}/work/sdk-target
42+
steps:
43+
- uses: actions/checkout@v7
44+
- name: Provision native SDK test environment
45+
run: |
46+
# The Azure mirror took >25 minutes for two Rust archives in run
47+
# 40355512113. Use official Ubuntu ports with the existing signed trust.
48+
sudo python3 - <<'PYTHON'
49+
from pathlib import Path
50+
import re
51+
path = Path('/etc/apt/sources.list.d/ubuntu.sources')
52+
text = path.read_text()
53+
path.write_text(re.sub(r'(?m)^URIs:.*$', 'URIs: http://ports.ubuntu.com/ubuntu-ports', text))
54+
PYTHON
55+
sudo apt-get -o Acquire::Retries=2 -o Acquire::http::Timeout=20 update
56+
sudo apt-get -o Acquire::Retries=2 -o Acquire::http::Timeout=20 install -y --no-install-recommends cargo rustc rustfmt rust-clippy \
57+
build-essential pkg-config valac libgtk-4-dev libgranite-7-dev libjson-glib-dev libwayland-dev libwayland-bin \
58+
xvfb xauth dbus-x11 at-spi2-core dpkg-dev desktop-file-utils appstream python3-jsonschema python3-pyatspi python3-dbus xdotool x11-utils
59+
- uses: actions/cache@v6
60+
with:
61+
path: |
62+
~/.cargo/registry
63+
work/sdk-target
64+
key: msdk-native-${{ runner.arch }}-${{ hashFiles('rust/Cargo.lock') }}
65+
restore-keys: msdk-native-${{ runner.arch }}-
66+
- name: Prepare isolated SDK workspace
67+
run: python3 mseries/sdk-tests/prepare.py "$RUNNER_TEMP/sdk"
68+
- name: Core tests and strict lint
69+
run: |
70+
python3 -m unittest discover -s mseries/sdk-bench -p 'test_*.py'
71+
cargo fmt --manifest-path "$RUNNER_TEMP/sdk/Cargo.toml" -p msdk --check
72+
cargo test --manifest-path "$RUNNER_TEMP/sdk/Cargo.toml" -p msdk
73+
cargo clippy --manifest-path "$RUNNER_TEMP/sdk/Cargo.toml" -p msdk --all-targets -- -D warnings
74+
- name: Independent schema and checker agreement
75+
run: python3 mseries/sdk-tests/check-schema.py --msdk "$CARGO_TARGET_DIR/debug/msdk" --rust-root "$RUNNER_TEMP/sdk"
76+
- name: Build and test generated native application
77+
run: |
78+
mkdir -p "$RUNNER_TEMP/sdk-evidence"
79+
"$CARGO_TARGET_DIR/debug/msdk" new settings "$RUNNER_TEMP/starter" --name 'SDK Settings' --id io.github.techmore.SdkSettings
80+
"$CARGO_TARGET_DIR/debug/msdk" gen "$RUNNER_TEMP/starter/app.ui.json" "$RUNNER_TEMP/generated" --sdk-root "$RUNNER_TEMP/sdk"
81+
cargo fmt --manifest-path "$RUNNER_TEMP/generated/Cargo.toml"
82+
cargo test --manifest-path "$RUNNER_TEMP/generated/Cargo.toml" --all-targets
83+
cargo clippy --manifest-path "$RUNNER_TEMP/generated/Cargo.toml" --all-targets -- -D warnings
84+
for mode in light dark; do
85+
theme=Adwaita
86+
if [ "$mode" = dark ]; then theme=Adwaita:dark; fi
87+
GTK_THEME="$theme" GSK_RENDERER=cairo xvfb-run -a dbus-run-session -- \
88+
"$CARGO_TARGET_DIR/debug/msdk-sdksettings" --screenshot "$RUNNER_TEMP/sdk-evidence/settings-$mode.png"
89+
done
90+
cp "$RUNNER_TEMP/sdk/Cargo.lock" "$RUNNER_TEMP/sdk-evidence/sdk-Cargo.lock"
91+
cp "$RUNNER_TEMP/generated/Cargo.lock" "$RUNNER_TEMP/sdk-evidence/generated-Cargo.lock"
92+
git rev-parse HEAD > "$RUNNER_TEMP/sdk-evidence/source.txt"
93+
sha256sum "$CARGO_TARGET_DIR/debug/msdk-sdksettings" > "$RUNNER_TEMP/sdk-evidence/binary.sha256"
94+
- name: Actual keyboard and accessibility controls
95+
run: |
96+
MSDK_PRIVATE_TEST_BUS=1 GSK_RENDERER=cairo xvfb-run -a dbus-run-session -- \
97+
python3 mseries/sdk-tests/controls.py --binary "$CARGO_TARGET_DIR/debug/msdk-sdksettings" --output "$RUNNER_TEMP/sdk-evidence/controls.json"
98+
- name: Compact and larger-text render matrix
99+
run: bash mseries/sdk-tests/render-matrix.sh "$CARGO_TARGET_DIR/debug/msdk-sdksettings" "$RUNNER_TEMP/sdk-evidence/matrix"
100+
- name: Native host lifecycle
101+
run: |
102+
cargo clippy --manifest-path "$RUNNER_TEMP/sdk/Cargo.toml" -p msdk-gtk --all-targets -- -D warnings
103+
MSDK_PRIVATE_TEST_BUS=1 XDG_DATA_HOME="$RUNNER_TEMP/sdk-state" GSK_RENDERER=cairo xvfb-run -a dbus-run-session -- \
104+
cargo test --manifest-path "$RUNNER_TEMP/sdk/Cargo.toml" -p msdk-gtk --test lifecycle --test runtime --test cli --test usage --test codexbar -- --test-threads=1
105+
- name: C host SDK usage boundary
106+
run: |
107+
cargo build --manifest-path "$RUNNER_TEMP/sdk/Cargo.toml" -p msdk-gtk --lib
108+
cc -Wall -Wextra -Werror mseries/sdk-tests/usage-host-abi.c \
109+
-I "$RUNNER_TEMP/sdk/msdk-gtk/include" $(pkg-config --cflags --libs gtk4) \
110+
-L "$CARGO_TARGET_DIR/debug" -lmsdk_gtk -Wl,-rpath,"$CARGO_TARGET_DIR/debug" \
111+
-o "$RUNNER_TEMP/usage-host-abi"
112+
printf '#!/bin/sh\nprintf x >> "%s"\necho "{}"\n' "$RUNNER_TEMP/usage-host-read" > "$RUNNER_TEMP/usage-host-fixture"
113+
chmod 700 "$RUNNER_TEMP/usage-host-fixture"
114+
GSK_RENDERER=cairo xvfb-run -a dbus-run-session -- \
115+
"$RUNNER_TEMP/usage-host-abi" "$RUNNER_TEMP/usage-host-fixture" "$RUNNER_TEMP/usage-host-read"
116+
mkdir -p "$RUNNER_TEMP/vala-output"
117+
valac --directory "$RUNNER_TEMP/vala-output" --pkg gtk4 --vapidir mseries/sdk-status-host --pkg msdk-usage \
118+
-X "-I$RUNNER_TEMP/sdk/msdk-gtk/include" -X "-L$CARGO_TARGET_DIR/debug" -X -lmsdk_gtk \
119+
-X "-Wl,-rpath,$CARGO_TARGET_DIR/debug" -o "$RUNNER_TEMP/usage-vala-host" mseries/sdk-status-host/UsagePage.vala mseries/sdk-tests/usage-vala-host.vala
120+
rm -f "$RUNNER_TEMP/usage-host-read"
121+
GSK_RENDERER=cairo xvfb-run -a dbus-run-session -- \
122+
"$RUNNER_TEMP/usage-vala-host" "$RUNNER_TEMP/usage-host-fixture" "$RUNNER_TEMP/usage-host-read"
123+
- name: Shared desktop status menu with SDK usage
124+
run: |
125+
mkdir -p "$RUNNER_TEMP/status-home/.local/bin" "$RUNNER_TEMP/status-home/.config" "$RUNNER_TEMP/status-home/.cache" "$RUNNER_TEMP/vala-output"
126+
cat > "$RUNNER_TEMP/status-home/.local/bin/codexbar-linux" <<'SCRIPT'
127+
#!/bin/sh
128+
printf x >> "$HOME/reads"
129+
now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
130+
printf '{"schemaVersion":1,"entries":[{"provider":"codex","updatedAt":"%s","windows":[{"key":"week","label":"7 day","remaining":75,"resetsAt":""}]}]}\n' "$now"
131+
SCRIPT
132+
chmod 700 "$RUNNER_TEMP/status-home/.local/bin/codexbar-linux"
133+
valac --directory "$RUNNER_TEMP/vala-output" --define MSDK_STATUS_HOST --pkg gtk4 --pkg granite-7 --pkg json-glib-1.0 --pkg gio-unix-2.0 \
134+
--vapidir mseries/sdk-status-host --pkg msdk-usage \
135+
-X "-I$RUNNER_TEMP/sdk/msdk-gtk/include" -X "-L$CARGO_TARGET_DIR/debug" -X -lmsdk_gtk -X "-Wl,-rpath,$CARGO_TARGET_DIR/debug" \
136+
-o "$RUNNER_TEMP/status-host-integration" mseries/sdk-status-host/UsagePage.vala \
137+
mseries/dock-taskbar/TaskbarT3RPopover.vala mseries/codexbar-wingpanel/JsonBoundary.vala \
138+
mseries/sdk-tests/status-host-stubs.vala mseries/sdk-tests/status-host-integration.vala
139+
for mode in wingpanel dock; do
140+
rm -f "$RUNNER_TEMP/status-home/reads"
141+
HOME="$RUNNER_TEMP/status-home" XDG_CONFIG_HOME="$RUNNER_TEMP/status-home/.config" XDG_CACHE_HOME="$RUNNER_TEMP/status-home/.cache" \
142+
GSETTINGS_BACKEND=memory GTK_A11Y=none G_DEBUG=fatal-criticals GSK_RENDERER=cairo \
143+
xvfb-run -a dbus-run-session -- "$RUNNER_TEMP/status-host-integration" "$RUNNER_TEMP/status-home/reads" "$mode"
144+
done
145+
- name: Capture candidate usage rows for review
146+
run: |
147+
cargo build --manifest-path "$RUNNER_TEMP/sdk/Cargo.toml" -p msdk-gtk --examples
148+
printf '#!/bin/sh\nprintf invalid-json\n' > "$RUNNER_TEMP/usage-fixture-failure"
149+
chmod 700 "$RUNNER_TEMP/usage-fixture-failure"
150+
icons="$RUNNER_TEMP/usage-data/icons/hicolor/scalable/apps"
151+
mkdir -p "$icons"
152+
for provider in openai claude grok opencode; do
153+
install -m 644 "mseries/codexbar-wingpanel/icons/$provider.svg" "$icons/mseries-codexbar-$provider-symbolic.svg"
154+
done
155+
for mode in light dark; do
156+
theme=Adwaita
157+
if [ "$mode" = dark ]; then theme=Adwaita:dark; fi
158+
for points in 10 15; do
159+
config="$RUNNER_TEMP/usage-config-$mode-$points"
160+
mkdir -p "$config/gtk-4.0"
161+
printf '[Settings]\ngtk-font-name=Sans %s\n' "$points" > "$config/gtk-4.0/settings.ini"
162+
XDG_DATA_HOME="$RUNNER_TEMP/usage-data" XDG_CONFIG_HOME="$config" GTK_THEME="$theme" GSK_RENDERER=cairo MSDK_MATRIX_POINTS="$points" \
163+
xvfb-run -a dbus-run-session -- bash -eu -c '
164+
python3 mseries/sdk-tests/font-profile.py
165+
"$CARGO_TARGET_DIR/debug/examples/usage_preview" "$RUNNER_TEMP/sdk-evidence/usage-'"$mode"'-'"$points"'.png"
166+
'
167+
XDG_DATA_HOME="$RUNNER_TEMP/usage-data" XDG_CONFIG_HOME="$config" GTK_THEME="$theme" GSK_RENDERER=cairo MSDK_USAGE_SCROLL_END=1 \
168+
xvfb-run -a dbus-run-session -- \
169+
"$CARGO_TARGET_DIR/debug/examples/usage_preview" "$RUNNER_TEMP/sdk-evidence/usage-$mode-$points-end.png"
170+
XDG_DATA_HOME="$RUNNER_TEMP/usage-data" XDG_CONFIG_HOME="$config" GTK_THEME="$theme" GSK_RENDERER=cairo \
171+
xvfb-run -a dbus-run-session -- \
172+
"$CARGO_TARGET_DIR/debug/examples/usage_control_preview" "$RUNNER_TEMP/sdk-evidence/usage-error-$mode-$points.png" "$RUNNER_TEMP/usage-fixture-failure"
173+
done
174+
done
175+
- name: Usage refresh keyboard and accessibility
176+
run: |
177+
MSDK_PRIVATE_TEST_BUS=1 GSK_RENDERER=cairo xvfb-run -a dbus-run-session -- \
178+
python3 mseries/sdk-tests/usage-controls.py \
179+
--binary "$CARGO_TARGET_DIR/debug/examples/usage_control_interactive" \
180+
--output "$RUNNER_TEMP/sdk-evidence/usage-controls.json"
181+
- name: Candidate usage anchor interactions
182+
run: |
183+
MSDK_PRIVATE_TEST_BUS=1 GSK_RENDERER=cairo xvfb-run -a dbus-run-session -- \
184+
python3 mseries/sdk-tests/usage-anchor-controls.py \
185+
--binary "$CARGO_TARGET_DIR/debug/examples/usage_anchor_interactive" \
186+
--output "$RUNNER_TEMP/sdk-evidence/usage-anchor-controls.json"
187+
- name: Package, install, reinstall and remove the generated app
188+
run: |
189+
"$CARGO_TARGET_DIR/debug/msdk" pack "$RUNNER_TEMP/generated" \
190+
--binary "$CARGO_TARGET_DIR/debug/msdk-sdksettings" \
191+
--output "$RUNNER_TEMP/sdk-evidence/settings.deb"
192+
dpkg-deb --info "$RUNNER_TEMP/sdk-evidence/settings.deb" > "$RUNNER_TEMP/sdk-evidence/package-info.txt"
193+
sudo dpkg --install "$RUNNER_TEMP/sdk-evidence/settings.deb"
194+
sudo dpkg --install "$RUNNER_TEMP/sdk-evidence/settings.deb"
195+
cmp "$CARGO_TARGET_DIR/debug/msdk-sdksettings" /usr/bin/io.github.techmore.SdkSettings
196+
GTK_THEME=Adwaita GSK_RENDERER=cairo xvfb-run -a dbus-run-session -- \
197+
/usr/bin/io.github.techmore.SdkSettings --screenshot "$RUNNER_TEMP/sdk-evidence/installed.png"
198+
sha256sum /usr/bin/io.github.techmore.SdkSettings > "$RUNNER_TEMP/sdk-evidence/installed.sha256"
199+
sudo dpkg --remove msdk-io.github.techmore.sdksettings
200+
test ! -e /usr/bin/io.github.techmore.SdkSettings
201+
test ! -e /usr/share/applications/io.github.techmore.SdkSettings.desktop
202+
test ! -e /usr/share/icons/hicolor/scalable/apps/io.github.techmore.SdkSettings.svg
203+
- uses: actions/upload-artifact@v7
204+
if: always()
205+
with:
206+
name: msdk-native-${{ github.run_id }}
207+
path: ${{ runner.temp }}/sdk-evidence/
208+
if-no-files-found: warn

‎mseries/APP-BUILDING-GUIDE.md‎

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ The owner rejected the result. Both apps are incomplete and deferred.
88

99
## First establish what the person will experience
1010

11+
The owner clarified on 2026-10-26 that not every app needs a native experience.
12+
Choose the UI architecture for the actual product journey: existing web UI,
13+
wrapper, webview/hybrid or native controls as appropriate. SDK completion needs
14+
reusable capabilities and representative integration proof, not native rewrites
15+
of every app or full feature parity with every existing client. Do not promise
16+
a WebView vocabulary component or other integration that has not been shipped.
17+
1118
Write a short outcome contract before implementation:
1219

1320
- What opens, which window owns navigation, and what each primary action does.
@@ -37,8 +44,9 @@ necessary. Do not add recurring notifications or timers just to enforce this rul
3744

3845
## Use the implemented SDK authoring path
3946

40-
Descriptions (`.msdk` or JSON), rules and declared services are the primary
41-
authoring path. `msdk new` already generates a description, gates and README
47+
For SDK-rendered native UI, descriptions (`.msdk` or JSON), rules and declared
48+
services are the primary authoring path. This is not a requirement to replace
49+
an appropriate existing frontend. `msdk new` generates a description, gates and README
4250
from six templates; it does not generate a complete Cargo project, backend,
4351
standalone executable or package. Use app-local Rust `Services`/`Logic` only
4452
where the supported vocabulary is insufficient; record each escape hatch and
@@ -51,9 +59,13 @@ transport, account mappings and GitHub services remain app-specific adapters.
5159

5260
Use `cargo run -p msdk -- templates` from `rust/` to discover actual starters,
5361
then the CLI's `describe`, `check` and `gate` commands. Consult
54-
[RUST-PANTHEON-SDK.md](RUST-PANTHEON-SDK.md) for boundaries. Do not present
55-
proposed `msdk gen`, `msdk pack`, `msdk parity` or live introspection commands
56-
as available. Keep native chrome, scaling, accessibility, recoverable states,
62+
[RUST-PANTHEON-SDK.md](RUST-PANTHEON-SDK.md) for boundaries. Use `msdk gen <description> <new-directory> --sdk-root <checkout>/rust`
63+
when a standalone Cargo executable and typed models are needed. It preserves
64+
rules and the GTK host; custom service backends are app-owned extension points.
65+
Use `msdk pack <generated-project> --binary <built-ELF> --output <new.deb>`
66+
on the matching Linux architecture after building the intended artifact; package
67+
creation is separate from install/reinstall/remove and loaded-host qualification.
68+
Do not present proposed `msdk parity` or live introspection commands as available. Keep native chrome, scaling, accessibility, recoverable states,
5769
diagnostics and install/remove behavior in the delivered outcome contract.
5870

5971
## Keep development builds fast

0 commit comments

Comments
 (0)