Skip to content

Commit 781b9aa

Browse files
authored
Merge pull request #29 from lorem-dev/develop
release: 0.4.1
2 parents 9938300 + e1d6c0e commit 781b9aa

69 files changed

Lines changed: 2780 additions & 183 deletions

Some content is hidden

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

‎.agents/skills/check-changes/SKILL.md‎

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
name: check-changes
33
description: >
44
Verify that CHANGES.md (Development section) reflects every commit since the
5-
last release. Flag missing entries, stale entries, or commits that have no
6-
corresponding changelog bullet.
5+
last release. Flag missing entries, stale entries, over-long entries, or
6+
commits that have no corresponding changelog bullet.
77
---
88

99
# check-changes
@@ -38,13 +38,22 @@ release.
3838
verbatim -- it only needs to describe the same change at a short summary
3939
level.
4040

41-
5. **Report findings.**
41+
5. **Check each bullet against the length rule.**
42+
Per the "Changelog Entries" section of CONTRIBUTING.md, a bullet is at most
43+
**25 words**, counted as whitespace-separated tokens with a code span
44+
counting as one word. Count every bullet under `## Development` and list the
45+
ones that exceed it, with their count. Do not measure released `## Version`
46+
sections -- a section is frozen once cut and is never rewritten.
47+
48+
6. **Report findings.**
4249
- List commits with NO changelog entry (missing entries -- these must be
4350
added).
4451
- List changelog bullets that appear to describe nothing in the commit
4552
history (stale or speculative entries -- flag for author review).
53+
- List bullets over the 25-word limit, each with its count, and propose a
54+
shorter wording.
4655
- If everything matches, report "CHANGES.md is current."
4756

48-
6. **Do not edit CHANGES.md automatically.**
57+
7. **Do not edit CHANGES.md automatically.**
4958
Propose the missing bullets in your report and let the developer apply them.
5059
The developer owns the changelog wording.

‎.github/workflows/ci.yml‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,22 @@ jobs:
198198
- name: Test workspace
199199
run: cargo test --workspace
200200

201+
# `cargo test` WRITES the generated artifacts (ts-rs bindings, the mcp.yml
202+
# JSON Schema) rather than asserting them, so a commit that changes a Rust
203+
# type but forgets to commit the regenerated file is green here and only
204+
# wrong afterwards. For the schema that is worse than for the bindings: it
205+
# ships as a release asset that editors pin, so a stale one makes every
206+
# user's editor flag correct files until someone notices.
207+
- name: Fail on stale generated artifacts
208+
run: |
209+
git diff --exit-code -- \
210+
schemas/ \
211+
apps/desktop/src/renderer/services/bridge/generated/ \
212+
|| {
213+
echo "::error::A generated artifact is out of date. Run 'cargo test' and commit the result."
214+
exit 1
215+
}
216+
201217
e2e:
202218
name: End-to-end (CLI against the fixture)
203219
runs-on: ubuntu-latest

‎.github/workflows/release.yml‎

Lines changed: 86 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,11 @@ jobs:
6767
run: node scripts/check-version.mjs
6868

6969
# ---------------------------------------------------------------------------
70-
# Build: one matrix leg per (os, target). macOS covers both arches via cross
71-
# targets on the arm64 runner. Linux arm64 and Windows arm64 can be added as
72-
# further legs once cross-toolchains / arm runners are wired (see NOTE below).
70+
# Build: one matrix leg per (os, target), covering x64 and arm64 on all three
71+
# platforms. macOS and Windows reach their second arch by cross-compiling on
72+
# the x64/arm64 runner they already use; Linux gets a native arm64 runner,
73+
# because Tauri links the system WebKitGTK stack and cross-compiling it would
74+
# mean carrying an arm64 sysroot.
7375
# ---------------------------------------------------------------------------
7476
build:
7577
name: Build ${{ matrix.target }}
@@ -104,15 +106,22 @@ jobs:
104106
- os: ubuntu-22.04
105107
target: x86_64-unknown-linux-gnu
106108
args: ""
109+
# Linux arm64, built natively on the arm64 runner (free for public
110+
# repositories). Same 22.04 image as the x64 leg, so both AppImages
111+
# share a glibc floor.
112+
- os: ubuntu-22.04-arm
113+
target: aarch64-unknown-linux-gnu
114+
args: ""
107115
# Windows x64
108116
- os: windows-latest
109117
target: x86_64-pc-windows-msvc
110118
args: ""
111-
# NOTE: per-arch left as documented best-effort:
112-
# - Linux arm64 (aarch64-unknown-linux-gnu) needs a cross toolchain
113-
# or an arm64 runner and the arm64 webkit dev packages.
114-
# - Windows arm64 (aarch64-pc-windows-msvc) needs the arm64 MSVC
115-
# target; MakeAppx would also need ProcessorArchitecture="arm64".
119+
# Windows arm64 (cross-compiled on the x64 runner, as macOS Intel is).
120+
# Only the Rust target changes; Node, pnpm and the frontend build stay
121+
# on the x64 image.
122+
- os: windows-latest
123+
target: aarch64-pc-windows-msvc
124+
args: "--target aarch64-pc-windows-msvc"
116125

117126
steps:
118127
- name: Checkout repository
@@ -135,9 +144,13 @@ jobs:
135144
DEBIAN_FRONTEND: noninteractive
136145
run: |
137146
sudo apt-get update -o DPkg::Lock::Timeout=300
138-
# patchelf is dropped: the AppImage bundler needs it, but it already
139-
# ships in the ubuntu runner image, so installing it is pure download.
147+
# patchelf is installed explicitly: the AppImage bundler needs it,
148+
# and while the x64 runner image ships it, the arm64 images carry a
149+
# documented subset. A missing patchelf fails the arm64 leg, and
150+
# `publish` needs every leg -- so the whole release is blocked to save
151+
# one small download.
140152
sudo apt-get install -y -o DPkg::Lock::Timeout=300 \
153+
patchelf \
141154
libwebkit2gtk-4.1-dev \
142155
libappindicator3-dev \
143156
librsvg2-dev
@@ -249,37 +262,16 @@ jobs:
249262
# with the CHANGES.md-derived notes. Per-arch selection via --target.
250263
args: ${{ matrix.args }}
251264

252-
# -----------------------------------------------------------------------
253-
# Standalone CLI (skillkeeper): build and archive it for this target so it
254-
# can be installed with the one-line install script (scripts/install.*),
255-
# independent of the desktop bundle. The archive holds just the binary at
256-
# its root and is named by target triple, so the script builds the
257-
# download URL straight from the detected platform.
258-
# -----------------------------------------------------------------------
259-
- name: Build the CLI
260-
shell: bash
261-
run: cargo build --release -p skillkeeper-cli --target ${{ matrix.target }}
262-
263-
- name: Archive the CLI (tar.gz)
264-
if: matrix.os != 'windows-latest'
265-
shell: bash
266-
run: |
267-
mkdir -p dist-cli
268-
tar -czf "dist-cli/skillkeeper-cli-${{ matrix.target }}.tar.gz" \
269-
-C "target/${{ matrix.target }}/release" skillkeeper
270-
271-
- name: Archive the CLI (zip)
272-
if: matrix.os == 'windows-latest'
273-
shell: pwsh
274-
run: |
275-
New-Item -ItemType Directory -Force -Path dist-cli | Out-Null
276-
Compress-Archive -Path "target/${{ matrix.target }}/release/skillkeeper.exe" -DestinationPath "dist-cli/skillkeeper-cli-${{ matrix.target }}.zip" -Force
277-
278265
# -----------------------------------------------------------------------
279266
# Windows MSIX (MakeAppx): package the built exe + tile assets into an
280267
# MSIX using the appx identity dev.lorem.SkillKeeper / CN=Lorem Dev.
281268
# Best-effort: authored manifest + MakeAppx pack; unsigned (Store signs
282269
# on ingest). Does not fail the build if MakeAppx/exe are unavailable.
270+
#
271+
# Runs BEFORE the CLI build, and must stay there: the CLI crate's binary
272+
# is also named skillkeeper.exe and lands in target/<triple>/release, the
273+
# very path `tauri build --target` wrote the desktop app to. Build the CLI
274+
# first and the MSIX would ship the CLI instead of the app.
283275
# -----------------------------------------------------------------------
284276
- name: Package Windows MSIX (MakeAppx)
285277
if: matrix.os == 'windows-latest'
@@ -303,19 +295,29 @@ jobs:
303295
}
304296
Write-Host "MSIX version: $msixVersion"
305297
306-
# Locate the built executable (target name = crate name skillkeeper).
307-
$exe = Get-ChildItem -Path "target" -Recurse -Filter "skillkeeper.exe" |
308-
Where-Object { $_.FullName -match "release" -and $_.FullName -notmatch "deps" } |
309-
Select-Object -First 1
310-
if (-not $exe) {
311-
Write-Warning "skillkeeper.exe not found; skipping MSIX packaging."
298+
# Both Windows legs package an MSIX, so the architecture has to reach
299+
# the manifest AND the file name -- the publish job refuses two assets
300+
# sharing a basename, and an arm64 package declaring x64 would install
301+
# on neither.
302+
$arch = if ("${{ matrix.target }}".StartsWith("aarch64")) { "arm64" } else { "x64" }
303+
Write-Host "MSIX architecture: $arch"
304+
305+
# The desktop app crate and the CLI crate BOTH produce a binary named
306+
# skillkeeper.exe, so a recursive search would be a coin toss between
307+
# them. Take the exact path this leg's `tauri build` wrote to:
308+
# target/<triple>/release when --target was passed, target/release
309+
# otherwise.
310+
$releaseDir = if ("${{ matrix.args }}" -match "--target") { "target/${{ matrix.target }}/release" } else { "target/release" }
311+
$exePath = Join-Path $releaseDir "skillkeeper.exe"
312+
if (-not (Test-Path $exePath)) {
313+
Write-Warning "skillkeeper.exe not found at $exePath; skipping MSIX packaging."
312314
exit 0
313315
}
314316
315317
$stage = Join-Path $env:RUNNER_TEMP "msix"
316318
$assets = Join-Path $stage "Assets"
317319
New-Item -ItemType Directory -Force -Path $assets | Out-Null
318-
Copy-Item $exe.FullName (Join-Path $stage "skillkeeper.exe") -Force
320+
Copy-Item $exePath (Join-Path $stage "skillkeeper.exe") -Force
319321
320322
# Tile assets from the Tauri icons dir (Square* + StoreLogo).
321323
$iconDir = "apps/desktop/src-tauri/icons"
@@ -342,7 +344,7 @@ jobs:
342344
' <Identity Name="dev.lorem.SkillKeeper"',
343345
' Publisher="CN=Lorem Dev"',
344346
(' Version="' + $msixVersion + '"'),
345-
' ProcessorArchitecture="x64" />',
347+
(' ProcessorArchitecture="' + $arch + '" />'),
346348
' <Properties>',
347349
' <DisplayName>SkillKeeper</DisplayName>',
348350
' <PublisherDisplayName>Lorem Dev</PublisherDisplayName>',
@@ -378,7 +380,9 @@ jobs:
378380
) -join "`r`n"
379381
Set-Content -Path (Join-Path $stage "AppxManifest.xml") -Value $manifest -Encoding UTF8
380382
381-
# Locate MakeAppx.exe from the installed Windows SDK.
383+
# Locate MakeAppx.exe from the installed Windows SDK. The x64 filter
384+
# picks the HOST tool, which stays x64 on both legs -- the package's
385+
# own architecture is the manifest's ProcessorArchitecture, above.
382386
$makeappx = Get-ChildItem -Path "${env:ProgramFiles(x86)}\Windows Kits\10\bin" -Recurse -Filter "makeappx.exe" -ErrorAction SilentlyContinue |
383387
Where-Object { $_.FullName -match "x64" } |
384388
Sort-Object FullName -Descending | Select-Object -First 1
@@ -389,7 +393,7 @@ jobs:
389393
390394
$outDir = "apps/desktop/dist-msix"
391395
New-Item -ItemType Directory -Force -Path $outDir | Out-Null
392-
$msix = Join-Path $outDir "SkillKeeper-$msixVersion.msix"
396+
$msix = Join-Path $outDir "SkillKeeper-$msixVersion-$arch.msix"
393397
& $makeappx.FullName pack /d $stage /p $msix /o
394398
# Native tools do not trip $ErrorActionPreference; check the exit code
395399
# explicitly so a failed pack is a real (visible) step failure instead
@@ -401,6 +405,32 @@ jobs:
401405
}
402406
Write-Host "Built MSIX: $msix"
403407
408+
# -----------------------------------------------------------------------
409+
# Standalone CLI (skillkeeper): build and archive it for this target so it
410+
# can be installed with the one-line install script (scripts/install.*),
411+
# independent of the desktop bundle. The archive holds just the binary at
412+
# its root and is named by target triple, so the script builds the
413+
# download URL straight from the detected platform.
414+
# -----------------------------------------------------------------------
415+
- name: Build the CLI
416+
shell: bash
417+
run: cargo build --release -p skillkeeper-cli --target ${{ matrix.target }}
418+
419+
- name: Archive the CLI (tar.gz)
420+
if: matrix.os != 'windows-latest'
421+
shell: bash
422+
run: |
423+
mkdir -p dist-cli
424+
tar -czf "dist-cli/skillkeeper-cli-${{ matrix.target }}.tar.gz" \
425+
-C "target/${{ matrix.target }}/release" skillkeeper
426+
427+
- name: Archive the CLI (zip)
428+
if: matrix.os == 'windows-latest'
429+
shell: pwsh
430+
run: |
431+
New-Item -ItemType Directory -Force -Path dist-cli | Out-Null
432+
Compress-Archive -Path "target/${{ matrix.target }}/release/skillkeeper.exe" -DestinationPath "dist-cli/skillkeeper-cli-${{ matrix.target }}.zip" -Force
433+
404434
# -----------------------------------------------------------------------
405435
# Upload per-target bundles + the MSIX. Covers both the default target
406436
# dir (linux/windows) and the cross-target dir (macOS --target).
@@ -481,6 +511,16 @@ jobs:
481511
echo "Staged $(find dist -type f | wc -l) files:"
482512
ls -1 dist
483513
514+
# The mcp.yml JSON Schema is generated from the Rust types by `cargo test`
515+
# and committed, so it ships straight from the checkout -- no build leg
516+
# produces it. It must be attached to EVERY release: the docs tell editors
517+
# to read it from `releases/latest/download/mcp.schema.json`, and that URL
518+
# resolves against whichever release is newest.
519+
- name: Stage the mcp.yml JSON Schema
520+
run: |
521+
test -f schemas/mcp.schema.json
522+
cp schemas/mcp.schema.json dist/mcp.schema.json
523+
484524
# Checksum every staged asset. Written outside dist/ first so the glob
485525
# cannot include the (empty) checksums.txt the redirection would create.
486526
- name: Generate SHA-256 checksums

‎CHANGES.md‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,41 @@
22

33
## Development
44

5+
## Version 0.4.1
6+
7+
### Added
8+
9+
- Prebuilt arm64 builds for Linux and Windows: desktop bundles, CLI archives,
10+
and the one-line installers, alongside the existing x64 and macOS ones.
11+
- A JSON Schema for `mcp.yml`, published with every release: point an editor at
12+
it for completion, hover documentation, and validation as you type.
13+
- Skills may ship binary files. An image, font, or compiled helper is copied,
14+
hashed, and verified like any other file.
15+
16+
### Changed
17+
18+
- A skill with extra or oddly typed frontmatter fields installs instead of
19+
being dropped: only `name` is required.
20+
- A one-line `description:` may hold a second colon, and a header or `env`
21+
value may be a bare `{param}`.
22+
23+
### Fixed
24+
25+
- "Invalid YAML frontmatter" now says what is wrong and on which line of the
26+
file, instead of naming only the file.
27+
- An `mcp.yml` that cannot be read or parsed says so, in the app's
28+
notifications and on the CLI's standard error.
29+
- One unreadable skill no longer takes every skill after it in the repository
30+
with it. It is skipped alone, and named.
31+
- Switching a repository's branch refreshes its skills and MCP servers, instead
32+
of leaving both pages on the previous branch's contents.
33+
- Syncing a repository refreshes the MCP catalog too, which it had left to the
34+
next visit to an MCP page.
35+
- Cloning a repository that needs Git LFS fails when git-lfs is missing,
36+
instead of quietly leaving pointer files in place.
37+
- The Windows MSIX packages the desktop app; it used to pick between two
38+
binaries sharing a file name.
39+
540
## Version 0.4.0
641

742
### Added

‎CONTRIBUTING.md‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,39 @@ docs: document hook consent flow
3636

3737
---
3838

39+
## Changelog Entries
40+
41+
Every user-visible change gets a bullet under `## Development` in
42+
[`CHANGES.md`](CHANGES.md), grouped under `### Added`, `### Changed`, or
43+
`### Fixed`.
44+
45+
**Rules:**
46+
47+
- Keep each bullet to 25 words or fewer, counted as whitespace-separated
48+
tokens; a code span counts as one word whatever it contains. Wrap at the
49+
file's usual width, with continuation lines indented two spaces.
50+
- The cap applies to `### Added`, `### Changed`, and `### Fixed` alike, and
51+
only to `## Development`. A section is frozen once released.
52+
- English, and describe the change, not the code that made it.
53+
- One bullet per change. Two changes that need separate wording are two
54+
bullets, never one longer one.
55+
56+
**Examples:**
57+
58+
```
59+
### Changed
60+
61+
- A skill with extra or oddly typed frontmatter fields installs instead of
62+
being dropped: only `name` is required.
63+
64+
### Fixed
65+
66+
- Switching a repository's branch refreshes its skills and MCP servers,
67+
instead of leaving both pages on the previous branch's contents.
68+
```
69+
70+
---
71+
3972
## Dependency Discipline
4073

4174
Add only packages that are genuinely required for the application to work.

0 commit comments

Comments
 (0)