Skip to content

Commit b23194b

Browse files
authored
Merge pull request #76 from managedcode/codex/issue-14-toolchain-center
Implement toolchain center vertical slice
2 parents 3fdeb0e + 0fcab7f commit b23194b

File tree

88 files changed

+6092
-601
lines changed

Some content is hidden

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

88 files changed

+6092
-601
lines changed

.github/workflows/build-validation.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636

3737
- name: Build
3838
shell: pwsh
39-
run: dotnet build DotPilot.slnx -warnaserror
39+
run: dotnet build DotPilot.slnx -warnaserror -m:1 -p:BuildInParallel=false
4040

4141
unit_tests:
4242
name: Unit Test Suite

.github/workflows/release-publish.yml

Lines changed: 179 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -74,30 +74,12 @@ jobs:
7474
echo "release_tag=v${display_version}"
7575
} >> "$GITHUB_OUTPUT"
7676
77-
publish_desktop:
78-
name: Publish Desktop (${{ matrix.name }})
79-
runs-on: ${{ matrix.runner }}
77+
publish_macos:
78+
name: Publish macOS Release Asset
79+
runs-on: macos-latest
80+
timeout-minutes: 60
8081
needs:
8182
- prepare_release
82-
strategy:
83-
fail-fast: false
84-
matrix:
85-
include:
86-
- name: macOS
87-
runner: macos-latest
88-
artifact_name: dotpilot-release-macos
89-
archive_name: dotpilot-desktop-macos.zip
90-
output_path: artifacts/publish/macos
91-
- name: Windows
92-
runner: windows-latest
93-
artifact_name: dotpilot-release-windows
94-
archive_name: dotpilot-desktop-windows.zip
95-
output_path: artifacts/publish/windows
96-
- name: Linux
97-
runner: ubuntu-latest
98-
artifact_name: dotpilot-release-linux
99-
archive_name: dotpilot-desktop-linux.zip
100-
output_path: artifacts/publish/linux
10183
steps:
10284
- uses: actions/checkout@v6
10385
with:
@@ -108,30 +90,189 @@ jobs:
10890
timeout-minutes: 60
10991
uses: "./.github/steps/install_dependencies"
11092

111-
- name: Publish Desktop App
93+
- name: Resolve macOS RID
94+
id: macos_rid
95+
shell: bash
96+
run: |
97+
architecture="$(uname -m)"
98+
case "${architecture}" in
99+
arm64)
100+
rid="osx-arm64"
101+
asset_suffix="macos-arm64"
102+
;;
103+
x86_64)
104+
rid="osx-x64"
105+
asset_suffix="macos-x64"
106+
;;
107+
*)
108+
echo "Unsupported macOS runner architecture: ${architecture}" >&2
109+
exit 1
110+
;;
111+
esac
112+
113+
echo "rid=${rid}" >> "$GITHUB_OUTPUT"
114+
echo "asset_suffix=${asset_suffix}" >> "$GITHUB_OUTPUT"
115+
116+
- name: Publish macOS Disk Image
117+
shell: bash
118+
working-directory: ./DotPilot
119+
run: |
120+
dotnet publish DotPilot.csproj \
121+
-c Release \
122+
-f net10.0-desktop \
123+
-r "${{ steps.macos_rid.outputs.rid }}" \
124+
-warnaserror \
125+
-m:1 \
126+
-p:BuildInParallel=false \
127+
-p:SelfContained=true \
128+
-p:PackageFormat=dmg \
129+
-p:CodesignKey=- \
130+
-p:DiskImageSigningKey=- \
131+
-p:ApplicationDisplayVersion=${{ needs.prepare_release.outputs.release_version }} \
132+
-p:ApplicationVersion=${{ needs.prepare_release.outputs.application_version }}
133+
134+
- name: Stage macOS Release Asset
135+
shell: bash
136+
run: |
137+
mkdir -p ./artifacts/releases
138+
source_path="./DotPilot/bin/Release/net10.0-desktop/${{ steps.macos_rid.outputs.rid }}/publish/DotPilot.dmg"
139+
target_path="./artifacts/releases/dotpilot-${{ needs.prepare_release.outputs.release_version }}-${{ steps.macos_rid.outputs.asset_suffix }}.dmg"
140+
141+
if [[ ! -f "${source_path}" ]]; then
142+
echo "Expected macOS release asset was not produced: ${source_path}" >&2
143+
exit 1
144+
fi
145+
146+
cp "${source_path}" "${target_path}"
147+
148+
- name: Upload macOS Release Artifact
149+
uses: actions/upload-artifact@v4
150+
with:
151+
name: dotpilot-release-macos
152+
path: ./artifacts/releases/*.dmg
153+
if-no-files-found: error
154+
retention-days: 14
155+
156+
publish_windows:
157+
name: Publish Windows Release Asset
158+
runs-on: windows-latest
159+
timeout-minutes: 60
160+
needs:
161+
- prepare_release
162+
steps:
163+
- uses: actions/checkout@v6
164+
with:
165+
fetch-depth: 0
166+
ref: ${{ github.sha }}
167+
168+
- name: Install Dependencies
169+
timeout-minutes: 60
170+
uses: "./.github/steps/install_dependencies"
171+
172+
- name: Publish Windows Single-File Executable
112173
shell: pwsh
174+
working-directory: .\DotPilot
113175
run: >
114-
dotnet publish ./DotPilot/DotPilot.csproj -c Release -f net10.0-desktop
115-
-o ./${{ matrix.output_path }}
176+
dotnet publish DotPilot.csproj
177+
-c Release
178+
-f net10.0-desktop
179+
-r win-x64
180+
-warnaserror
181+
-m:1
182+
-p:BuildInParallel=false
183+
-p:SelfContained=true
184+
-p:PublishSingleFile=true
185+
-p:IncludeNativeLibrariesForSelfExtract=true
186+
-p:IncludeAllContentForSelfExtract=true
116187
-p:ApplicationDisplayVersion=${{ needs.prepare_release.outputs.release_version }}
117188
-p:ApplicationVersion=${{ needs.prepare_release.outputs.application_version }}
118189
119-
- name: Archive Desktop Publish Output
190+
- name: Stage Windows Release Asset
120191
shell: pwsh
121192
run: |
122-
New-Item -ItemType Directory -Force -Path ./artifacts/releases | Out-Null
123-
$archivePath = "./artifacts/releases/${{ matrix.archive_name }}"
124-
if (Test-Path $archivePath) {
125-
Remove-Item $archivePath -Force
193+
New-Item -ItemType Directory -Force -Path .\artifacts\releases | Out-Null
194+
$sourcePath = ".\DotPilot\bin\Release\net10.0-desktop\win-x64\publish\DotPilot.exe"
195+
$targetPath = ".\artifacts\releases\dotpilot-${{ needs.prepare_release.outputs.release_version }}-windows-x64.exe"
196+
197+
if (-not (Test-Path $sourcePath)) {
198+
throw "Expected Windows release asset was not produced: $sourcePath"
126199
}
127200
128-
Compress-Archive -Path "./${{ matrix.output_path }}/*" -DestinationPath $archivePath
201+
Copy-Item $sourcePath $targetPath -Force
202+
203+
- name: Upload Windows Release Artifact
204+
uses: actions/upload-artifact@v4
205+
with:
206+
name: dotpilot-release-windows
207+
path: ./artifacts/releases/*.exe
208+
if-no-files-found: error
209+
retention-days: 14
210+
211+
publish_linux:
212+
name: Publish Linux Snap Release Asset
213+
runs-on: ubuntu-24.04
214+
timeout-minutes: 60
215+
needs:
216+
- prepare_release
217+
steps:
218+
- uses: actions/checkout@v6
219+
with:
220+
fetch-depth: 0
221+
ref: ${{ github.sha }}
222+
223+
- name: Install Dependencies
224+
timeout-minutes: 60
225+
uses: "./.github/steps/install_dependencies"
226+
227+
- name: Install Linux Snap Packaging Prerequisites
228+
shell: bash
229+
run: |
230+
sudo apt-get update
231+
sudo apt-get install -y snapd
232+
sudo systemctl start snapd.socket
233+
sudo snap wait system seed.loaded
234+
sudo snap install core24
235+
sudo snap install multipass
236+
sudo snap install lxd
237+
sudo snap install snapcraft --classic
238+
sudo lxd init --minimal
239+
240+
- name: Publish Linux Snap Package
241+
shell: bash
242+
working-directory: ./DotPilot
243+
run: |
244+
dotnet publish DotPilot.csproj \
245+
-c Release \
246+
-f net10.0-desktop \
247+
-r linux-x64 \
248+
-warnaserror \
249+
-m:1 \
250+
-p:BuildInParallel=false \
251+
-p:SelfContained=true \
252+
-p:PackageFormat=snap \
253+
-p:UnoSnapcraftAdditionalParameters=--destructive-mode \
254+
-p:ApplicationDisplayVersion=${{ needs.prepare_release.outputs.release_version }} \
255+
-p:ApplicationVersion=${{ needs.prepare_release.outputs.application_version }}
256+
257+
- name: Stage Linux Release Asset
258+
shell: bash
259+
run: |
260+
mkdir -p ./artifacts/releases
261+
source_path="$(find ./DotPilot/bin/Release/net10.0-desktop/linux-x64/publish -maxdepth 1 -type f -name '*.snap' | sort | head -n 1)"
262+
target_path="./artifacts/releases/dotpilot-${{ needs.prepare_release.outputs.release_version }}-linux-x64.snap"
263+
264+
if [[ -z "${source_path}" || ! -f "${source_path}" ]]; then
265+
echo "Expected Linux snap release asset was not produced." >&2
266+
exit 1
267+
fi
268+
269+
cp "${source_path}" "${target_path}"
129270
130-
- name: Upload Release Artifact
271+
- name: Upload Linux Release Artifact
131272
uses: actions/upload-artifact@v4
132273
with:
133-
name: ${{ matrix.artifact_name }}
134-
path: ./artifacts/releases/${{ matrix.archive_name }}
274+
name: dotpilot-release-linux
275+
path: ./artifacts/releases/*.snap
135276
if-no-files-found: error
136277
retention-days: 14
137278

@@ -140,7 +281,9 @@ jobs:
140281
runs-on: ubuntu-latest
141282
needs:
142283
- prepare_release
143-
- publish_desktop
284+
- publish_macos
285+
- publish_windows
286+
- publish_linux
144287
steps:
145288
- uses: actions/checkout@v6
146289
with:
@@ -226,7 +369,7 @@ jobs:
226369
RELEASE_VERSION: ${{ needs.prepare_release.outputs.release_version }}
227370
REPOSITORY: ${{ github.repository }}
228371
run: |
229-
mapfile -t release_assets < <(find ./artifacts/release-assets -type f -name '*.zip' | sort)
372+
mapfile -t release_assets < <(find ./artifacts/release-assets -type f | sort)
230373
if [[ ${#release_assets[@]} -eq 0 ]]; then
231374
echo "No release assets were downloaded." >&2
232375
exit 1

AGENTS.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,10 @@ Skill-management rules for this `.NET` solution:
122122

123123
### Commands
124124

125-
- `build`: `dotnet build DotPilot.slnx -warnaserror`
125+
- `build`: `dotnet build DotPilot.slnx -warnaserror -m:1 -p:BuildInParallel=false`
126126
- `test`: `dotnet test DotPilot.slnx`
127127
- `format`: `dotnet format DotPilot.slnx --verify-no-changes`
128-
- `analyze`: `dotnet build DotPilot.slnx -warnaserror`
128+
- `analyze`: `dotnet build DotPilot.slnx -warnaserror -m:1 -p:BuildInParallel=false`
129129
- `coverage`: `dotnet test DotPilot.Tests/DotPilot.Tests.csproj --settings DotPilot.Tests/coverlet.runsettings --collect:"XPlat Code Coverage"`
130130
- `publish-desktop`: `dotnet publish DotPilot/DotPilot.csproj -c Release -f net10.0-desktop`
131131

@@ -134,13 +134,15 @@ For this app:
134134
- unit tests currently use `NUnit` through the default `VSTest` runner
135135
- UI tests live in `DotPilot.UITests` and are a mandatory part of normal verification; the harness must provision or resolve browser-driver prerequisites automatically instead of skipping when local setup is missing
136136
- a canceled, timed-out, or hanging `DotPilot.UITests` run is a harness failure to fix, not an acceptable substitute for a real pass or fail result in CI
137+
- when debugging or validating the browser UI path, do not launch the app manually outside `DotPilot.UITests`; reproduce and diagnose only through the real UI-test harness so failures match the enforced verification path
137138
- `format` uses `dotnet format --verify-no-changes` as a local pre-push check; GitHub Actions validation should not spend CI time rechecking formatting drift that must already be fixed before push
138139
- coverage uses the `coverlet.collector` integration on `DotPilot.Tests` with the repo runsettings file to keep generated Uno artifacts out of the coverage path
139140
- desktop release publishing uses `dotnet publish DotPilot/DotPilot.csproj -c Release -f net10.0-desktop`; the validation workflow stays focused on build and automated tests, while the release workflow owns desktop publish outputs for macOS, Windows, and Linux
140-
- `LangVersion` is pinned to `latest` at the root
141+
- `LangVersion` is pinned to `14` at the root
141142
- prefer the newest stable `.NET 10` and `C#` language features that are supported by the pinned SDK and do not weaken readability, determinism, or analyzability
142143
- the repo-root lowercase `.editorconfig` is the source of truth for formatting, naming, style, and analyzer severity
143144
- local and CI build commands must pass `-warnaserror`; warnings are not an acceptable "green" build state in this repository
145+
- do not run parallel `dotnet` or `MSBuild` work that shares the same checkout, target outputs, or NuGet package cache; the multi-target Uno app must build serially in CI to avoid `Uno.Resizetizer` file-lock failures
144146
- quality gates should prefer analyzer-backed build failures over separate one-off CI tools; for overloaded methods and maintainability drift, enable build-time analyzers such as `CA1502` instead of adding a formatting-only gate
145147
- `Directory.Build.props` owns the shared analyzer and warning policy for future projects
146148
- `Directory.Packages.props` owns centrally managed package versions
@@ -150,8 +152,11 @@ For this app:
150152
- keep the Uno app project presentation-only; domain, runtime host, orchestration, integrations, and persistence code must live in separate class-library projects so UI composition does not mix with feature implementation
151153
- GitHub Actions workflows must use descriptive names and filenames that reflect their purpose; do not use a generic `ci.yml` catch-all because build validation and release automation are separate operator flows
152154
- GitHub Actions must be split into at least one validation workflow for normal builds/tests and one release workflow for CI-driven version resolution, release-note generation, desktop publishing, and GitHub Release publication
155+
- meaningful GitHub review comments must be evaluated and fixed when they still apply even if the original PR was closed; closed review threads are not a reason to ignore valid engineering feedback
156+
- PR bodies for issue-backed work must use GitHub closing references such as `Closes #14` so merged work closes the tracked issue automatically
153157
- the release workflow must run automatically on pushes to `main`, build desktop apps, and publish the GitHub Release without requiring a manual dispatch
154158
- desktop app build or publish jobs must use native runners for their target OS: macOS artifacts on macOS runners, Windows artifacts on Windows runners, and Linux artifacts on Linux runners
159+
- desktop release assets must be native installable or directly executable outputs for each OS, not archives of raw publish folders; package the real `.exe`, `.snap`, `.dmg`, `.pkg`, `Setup.exe`, or equivalent runnable installer/app artifact instead of zipping intermediate publish directories
155160
- desktop release versions must use the `ApplicationDisplayVersion` value in `DotPilot/DotPilot.csproj` as a manually maintained two-segment prefix, with CI appending the final segment from the build number (for example `0.0.<build-number>`)
156161
- the release workflow must not take ownership of the first two version segments; those remain manually edited in source, while CI supplies only the last numeric segment and matching release tag/application version values
157162
- for CI and release automation in this solution, prefer existing `dotnet` and `MSBuild` capabilities plus small workflow-native steps over Python or adding a separate helper project for simple versioning and release-note tasks
@@ -278,6 +283,8 @@ Local `AGENTS.md` files may tighten these values, but they must not loosen them
278283
- The task is not done until the full relevant test suite is green, not only the newly added tests.
279284
- UI tests are mandatory for this repository and must run in normal agent verification; missing local browser-driver setup is a harness bug to fix, not a reason to skip the suite.
280285
- UI coverage must validate complete end-to-end operator flows and also assert the presence and behavior of each interactive element introduced by a feature.
286+
- For `Uno` UI-test changes, use the official `Uno` MCP documentation as the source of truth and align browser assertions with the documented WebAssembly automation mapping before changing the harness shape.
287+
- When debugging local product behavior on this machine, prefer the real desktop `Uno` app head plus local `Uno` app tooling or MCP over ad hoc `browserwasm` runs; keep `browserwasm` for the dedicated `DotPilot.UITests` verification path.
281288
- GitHub Actions PR validation is mandatory for every PR and must enforce the real repo verification path so test failures are caught in CI, not only locally.
282289
- GitHub Actions PR validation must run full automated test verification, especially the real UI suite; build-only or smoke-only checks are not an acceptable substitute for pull-request gating.
283290
- GitHub Actions validation must also produce downloadable app artifacts for macOS, Windows, and Linux so every PR and mainline run has test results plus installable build outputs.
@@ -332,6 +339,7 @@ Ask first:
332339
- Follow the canonical MCAF tutorial when bootstrapping or upgrading the agent workflow.
333340
- Commit cohesive code-change batches promptly while debugging, especially before switching focus or starting long verification runs, so the branch state stays inspectable and pushable.
334341
- After opening or updating a PR, create a fresh working branch before continuing with the next slice of work so follow-up changes do not pile onto the already-reviewed branch.
342+
- Keep `DotPilot` feeling like a fast desktop control plane: startup, navigation, and visible UI reactions should be prompt, and agents should remove unnecessary waits instead of normalizing slow web-style loading behavior.
335343
- Keep the root `AGENTS.md` at the repository root.
336344
- Keep the repo-local agent skill directory limited to current `mcaf-*` skills.
337345
- Keep the solution file name cased as `DotPilot.slnx`.
@@ -352,6 +360,7 @@ Ask first:
352360
- Installing stale, non-canonical, or non-`mcaf-*` skills into the repo-local agent skill directory.
353361
- Moving root governance out of the repository root.
354362
- Mixing multiple `.NET` test frameworks in the active solution without a documented migration plan.
363+
- Adding fallback paths or alternate harnesses that only make failures disappear in tests while the primary product path remains broken.
355364
- Switching desktop Uno pages into stacked or mobile-style responsive layouts during resize work unless the user explicitly asks for a different composition; desktop pages must stay desktop-first and protect geometry through sizing constraints instead.
356365
- Adding extra UI-test orchestration complexity when the actual goal is simply to run the tests and get an honest pass or fail result.
357366
- Planning `MLXSharp` into the first product wave before it is ready for real use.

DotPilot.Core/DotPilot.Core.csproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,4 @@
66
<NoWarn>$(NoWarn);CS1591</NoWarn>
77
</PropertyGroup>
88

9-
<ItemGroup>
10-
<PackageReference Include="ManagedCode.Communication" />
11-
</ItemGroup>
12-
139
</Project>

0 commit comments

Comments
 (0)