Skip to content
Open

V4 #39

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
c1cfb3c
particles: add rain template
Kyonru Jul 4, 2026
41689d1
cli: add basic shim fixes
Kyonru Aug 1, 2026
c3b9390
feather: v2 direction
Kyonru Sep 8, 2026
57d08de
ci: split release into per-train tags
Kyonru Sep 8, 2026
cd001b7
feather: negotiate a wire protocol version
Kyonru Sep 8, 2026
1cf8cb8
feather: declare the wire protocol message set once
Kyonru Sep 8, 2026
a4e0396
feather: validate the wire envelope on both sides
Kyonru Sep 8, 2026
2518fef
ci: move to pnpm workspaces and Turborepo
Kyonru Sep 8, 2026
bd0b195
feather: extract ui, host and session-bridge packages
Kyonru Sep 8, 2026
c0ec23b
feather: give the Lua runtime and catalog their own homes
Kyonru Sep 8, 2026
da391ac
docs: record Phase 06 in V2.md
Kyonru Sep 8, 2026
662f432
docs: record the Phase 05 blocker and pickup order
Kyonru Sep 8, 2026
c6af1e2
docs: clarify standalone studio and MCP architecture
Kyonru Sep 8, 2026
8721a7b
docs: rename the re-architecture from v2 to v4
Kyonru Sep 8, 2026
4712956
ci: publish a platform manifest and stop duplicating binaries
Kyonru Sep 8, 2026
f45dc10
ci: attach standalone CLI binaries to the CLI train, and document CI use
Kyonru Sep 8, 2026
b23c33a
studio: extract Studio-owned preferences from the Inspector settings …
Kyonru Sep 8, 2026
8389d8a
studio: scaffold the Studio application and its versioned bridge
Kyonru Sep 8, 2026
d7feec0
studio: move the creative tools into Feather Studio
Kyonru Sep 8, 2026
6c9467e
studio: give Studio its own release train and collapse the showcase
Kyonru Sep 8, 2026
8bcffc5
inspector: move the Inspector into apps/inspector
Kyonru Sep 8, 2026
6da1033
ci: test Inspector, Studio and Showcase as separate products
Kyonru Sep 8, 2026
0a908b3
feather: move cli, vscode-extension and docs under apps
Kyonru Sep 8, 2026
6b1616b
mcp: keep one Feather MCP server and route it to both applications
Kyonru Sep 8, 2026
23e4b5d
ci: drop the stale docs/_site ignore rule
Kyonru Sep 8, 2026
d7a2f8e
studio: complete the preferences handoff, range checks and split docs
Kyonru Sep 8, 2026
663018c
vscode-extension: record and verify the platform snapshot it vendors
Kyonru Sep 8, 2026
b42b303
ci: lint the CLI and the extension
Kyonru Sep 9, 2026
e1680a4
docs: resolve duplicate v4 decision IDs and stale two-MCP spec
Kyonru Sep 9, 2026
42a995d
docs: document the v4 layout and add verify/test/run commands
Kyonru Sep 9, 2026
62ac66a
tauri: make Inspector's before-commands work from its own directory
Kyonru Sep 9, 2026
cf46e05
feather: add `pnpm run up` to bring a dev session online
Kyonru Sep 9, 2026
6de7d17
inspector: remove the creative tool trails left by the v4 split
Kyonru Sep 9, 2026
7e7ebdf
inspector: drop the dead creative MCP surface from the Tauri shell
Kyonru Sep 9, 2026
9e46904
docs: add V4-ENHANCED.md, the feature refinement track for Inspector
Kyonru Sep 9, 2026
8192b3e
docs: add the design direction to V4-ENHANCED, and the C0 it exposed
Kyonru Sep 9, 2026
3323d04
inspector: make color mean something (V4-ENHANCED C0)
Kyonru Sep 9, 2026
997d2de
inspector: keep panel filters across the loop (V4-ENHANCED C1)
Kyonru Sep 9, 2026
2f8a7dc
inspector: say whether panel data is current (V4-ENHANCED C2)
Kyonru Sep 9, 2026
0538bb6
inspector: make warnings actionable and silence deliberate (C3, C4)
Kyonru Sep 9, 2026
76bf446
inspector: fix log search crashing on a log with no message
Kyonru Sep 9, 2026
e00dc29
inspector: stop follow-tail dragging you back to the bottom (6.1)
Kyonru Sep 9, 2026
dd3906c
inspector: make breakpoint problem counts openable (6.4)
Kyonru Sep 9, 2026
286f290
inspector: finish the debugger pass (6.4)
Kyonru Sep 9, 2026
022d575
inspector: reach a breakpoint and its condition from the keyboard (6.4)
Kyonru Sep 9, 2026
7292881
inspector: let a profiler baseline survive a restart (6.3)
Kyonru Sep 9, 2026
24c647a
inspector: stop a plugin manifest breaking the sidebar (C5)
Kyonru Sep 10, 2026
252bd7e
inspector: make the Missing asset filter truthful at scale (6.6)
Kyonru Sep 10, 2026
c03ecc6
inspector: give filtered-empty panels a way out (6.11, C1 follow-up)
Kyonru Sep 10, 2026
9082940
inspector: restore status indicators washed out by the C0 pass (6.9)
Kyonru Sep 10, 2026
0fa1eef
inspector: mark recording the same way everywhere (6.3)
Kyonru Sep 10, 2026
48a6e54
inspector: make settings findable from the palette (6.12, 6.13)
Kyonru Sep 10, 2026
0b836a7
inspector: order session warnings by what to do first (6.2)
Kyonru Sep 10, 2026
f3f4492
docs: design Feather Studio into a usable tool (V4-ENHANCED §9)
Kyonru Sep 10, 2026
2d2a2c1
docs: add V4-STUDIO.md, the specification for making Studio usable
Kyonru Sep 10, 2026
cdf9fc8
docs: normalize spelling in the Studio spec
Kyonru Sep 10, 2026
677bbe2
docs: give Studio its own visual direction — a workbench (V4-STUDIO §5)
Kyonru Sep 10, 2026
c95b272
studio: make Feather Studio usable (V4-STUDIO S1-S3)
Kyonru Sep 10, 2026
a44e7ce
studio: quieter chrome and an overlay tool menu
Kyonru Sep 10, 2026
bcda1c0
studio: give the three tools one visual language
Kyonru Sep 10, 2026
b974e6d
studio: serve the love.js preview target
Kyonru Sep 10, 2026
80bb3a4
docs: add the particles architecture spec
Kyonru Sep 10, 2026
3313d15
docs: measure the particle timeline cost, and bake the curves
Kyonru Sep 10, 2026
6a70cb6
docs: tier the particle cost, and record the authoring redesign
Kyonru Sep 10, 2026
bb8de80
particles: give the timeline one definition (V4-PARTICLES P1)
Kyonru Sep 10, 2026
5e25044
particles: send only what changed (V4-PARTICLES P2)
Kyonru Sep 10, 2026
6690900
particles: warm on start, in every host (V4-PARTICLES P3)
Kyonru Sep 10, 2026
ee38a2d
particles: make atlas variants cheap (V4-PARTICLES P4)
Kyonru Sep 10, 2026
f9f1b2d
particles: the exported file is the same program (V4-PARTICLES P5)
Kyonru Sep 10, 2026
db7bedb
docs: untrack the GPU particle brief
Kyonru Sep 11, 2026
b371ced
studio: give Studio the semantic colour channel (V4-STUDIO S5, C0)
Kyonru Sep 11, 2026
fc7d6cd
studio: name the way out of two dead ends (V4-STUDIO S5, C1 and C3)
Kyonru Sep 11, 2026
97a4dd6
ui: one theme registry, not two copies (V4-STUDIO S5)
Kyonru Sep 11, 2026
2c2a2a5
docs: add V4-PENDING.md, the index of what is left
Kyonru Sep 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
99 changes: 99 additions & 0 deletions .github/workflows/_release-cli.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: "[reusable] CLI release"

# Publishes @kyonru/feather to npm. Called by release-cli.yml, which fires on
# both `cli-v*` (CLI alone) and `v*` (full platform release).

on:
workflow_call:

jobs:
npm-cli-release:
runs-on: ubuntu-latest
name: npm CLI publish
permissions:
contents: write
id-token: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4

- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 24
registry-url: https://registry.npmjs.org
package-manager-cache: false

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Install LÖVE
run: |
sudo apt-get update
sudo apt-get install -y love xvfb

- name: Resolve version from tag
id: get_version
run: |
VERSION="$(bash scripts/release-tag-version.sh "$GITHUB_REF_NAME" --version)"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Verify CLI package version
run: |
CLI_VERSION="$(node -p "require('./apps/cli/package.json').version")"
if [ "$CLI_VERSION" != "${{ steps.get_version.outputs.version }}" ]; then
echo "Tag version ${{ steps.get_version.outputs.version }} does not match cli/package.json version $CLI_VERSION."
echo "Fix with: bash scripts/set-version.sh cli ${{ steps.get_version.outputs.version }}"
exit 1
fi

- name: Fail if CLI package version already exists
run: |
if npm view "@kyonru/feather@${{ steps.get_version.outputs.version }}" version --registry https://registry.npmjs.org >/dev/null 2>&1; then
echo "@kyonru/feather@${{ steps.get_version.outputs.version }} already exists on npm."
exit 1
fi

- name: Build CLI
run: pnpm run cli:build

- name: Run CLI e2e
run: pnpm run test:cli:e2e

- name: Run Lua e2e
run: pnpm run test:lua:e2e

- name: Verify npm package contents
run: pnpm --filter @kyonru/feather pack --dry-run

- name: Publish CLI to npm
run: pnpm --filter @kyonru/feather publish --access public --no-git-checks

# Standalone Bun binaries. These are the hermetic install path: no Node
# toolchain, one download, which is what a lean CI runner wants. They are
# attached to the CLI's own release so a `cli-v*` patch is pinnable on its
# own — publishing them only on platform tags would have made hermetic
# users wait for a full platform release to pin a CLI fix.
- name: Setup Bun
uses: oven-sh/setup-bun@v2

- name: Build standalone binaries
run: |
pnpm --filter @kyonru/feather run bundle:lua
pnpm --filter @kyonru/feather run build:binary
VERSION="${{ steps.get_version.outputs.version }}"
mkdir -p release-assets
cp apps/cli/bin/feather "release-assets/feather-cli-darwin-arm64-${VERSION}.bin"
cp apps/cli/bin/feather-darwin-x64 "release-assets/feather-cli-darwin-x64-${VERSION}.bin"
cp apps/cli/bin/feather-linux-x64 "release-assets/feather-cli-linux-x64-${VERSION}.bin"
cp apps/cli/bin/feather-win-x64.exe "release-assets/feather-cli-windows-x64-${VERSION}.exe"

- name: Attach binaries to the release
uses: ncipollo/release-action@v1
with:
artifacts: release-assets/*
allowUpdates: true
omitBodyDuringUpdate: true
omitNameDuringUpdate: true
139 changes: 35 additions & 104 deletions .github/workflows/release.yml → .github/workflows/_release-desktop.yml
Original file line number Diff line number Diff line change
@@ -1,122 +1,50 @@
name: Feather release
name: "[reusable] Desktop release"

# Builds and publishes the signed Tauri desktop app for macOS (arm64 + x64),
# Linux, and Windows. Called by release-desktop.yml, which fires on both
# `desktop-v*` (desktop alone) and `v*` (full platform release).

on:
push:
tags:
- "*"
workflow_call:

jobs:
npm-cli-release:
verify:
runs-on: ubuntu-latest
name: npm CLI publish
permissions:
contents: read
id-token: write
name: Verify desktop version
outputs:
version: ${{ steps.get_version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 24
registry-url: https://registry.npmjs.org
package-manager-cache: false

- name: Install dependencies
run: npm ci

- name: Install LÖVE
run: |
sudo apt-get update
sudo apt-get install -y love xvfb
- uses: actions/checkout@v4

- name: Get version from tag
- name: Resolve version from tag
id: get_version
run: |
VERSION="${GITHUB_REF_NAME#v}"
VERSION="$(bash scripts/release-tag-version.sh "$GITHUB_REF_NAME" --version)"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Verify CLI package version
run: |
CLI_VERSION="$(node -p "require('./cli/package.json').version")"
if [ "$CLI_VERSION" != "${{ steps.get_version.outputs.version }}" ]; then
echo "Tag version ${{ steps.get_version.outputs.version }} does not match cli/package.json version $CLI_VERSION."
exit 1
fi

- name: Fail if CLI package version already exists
- name: Verify the desktop trio agrees with the tag
run: |
if npm view "@kyonru/feather@${{ steps.get_version.outputs.version }}" version --registry https://registry.npmjs.org >/dev/null 2>&1; then
echo "@kyonru/feather@${{ steps.get_version.outputs.version }} already exists on npm."
VERSION="${{ steps.get_version.outputs.version }}"
PKG="$(node -p "require('./package.json').version")"
TAURI="$(node -p "require('./apps/inspector/src-tauri/tauri.conf.json').version")"
CARGO="$(sed -n '1,/^version = /s/^version = "\(.*\)"/\1/p' apps/inspector/src-tauri/Cargo.toml | head -n 1)"
FAIL=0
for pair in "package.json:$PKG" "apps/inspector/src-tauri/tauri.conf.json:$TAURI" "apps/inspector/src-tauri/Cargo.toml:$CARGO"; do
FILE="${pair%%:*}"
FOUND="${pair#*:}"
if [ "$FOUND" != "$VERSION" ]; then
echo "$FILE is $FOUND, expected $VERSION"
FAIL=1
fi
done
if [ "$FAIL" = "1" ]; then
echo "Fix with: bash scripts/set-version.sh desktop $VERSION"
exit 1
fi

- name: Build CLI
run: npm run cli:build

- name: Run CLI e2e
run: npm run test:cli:e2e

- name: Run Lua e2e
run: npm run test:lua:e2e

- name: Verify npm package contents
run: npm pack --workspace=cli --dry-run

- name: Publish CLI to npm
run: npm publish --workspace=cli --access public

luarocks-release:
runs-on: ubuntu-latest
name: LuaRocks upload
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Fail if changelog entry does not exist
run: grep -q "${{ github.ref_name }}" CHANGELOG.md

- name: Get version from tag
id: get_version
run: |
VERSION="${GITHUB_REF_NAME#v}"
echo "version=$VERSION" >> $GITHUB_OUTPUT

- name: LuaRocks Upload
uses: nvim-neorocks/luarocks-tag-release@v7
with:
license: Feather License
labels: |
love2d
löve
debug
copy_directories: |
src-lua/feather
summary: Debug & Inspect Tool for LÖVE (love2d)
detailed_description: |
Feather is a debugger tool with a plugin system for Love2D projects.
fail_on_duplicate: true
env:
LUAROCKS_API_KEY: ${{ secrets.LUAROCKS_API_KEY }}

- name: Zip feather folder
run: |
cd src-lua
zip -r ../feather-${{ steps.get_version.outputs.version }}.zip feather/

- name: GitHub Release
uses: ncipollo/release-action@v1
with:
artifacts: |
feather-${{ steps.get_version.outputs.version }}-1.rockspec
feather-${{ steps.get_version.outputs.version }}-1.src.rock
feather-${{ steps.get_version.outputs.version }}.zip
allowUpdates: true

tauri-release:
name: Build desktop
needs: verify
permissions:
contents: write
strategy:
Expand All @@ -136,6 +64,8 @@ jobs:

steps:
- uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4

- name: Setup Node
uses: actions/setup-node@v4
Expand All @@ -155,7 +85,7 @@ jobs:
sudo apt-get install -y libwebkit2gtk-4.0-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf

- name: Install frontend dependencies
run: npm install
run: pnpm install --frozen-lockfile

- name: Import Apple Developer Certificate
if: matrix.platform == 'macos-latest'
Expand Down Expand Up @@ -203,5 +133,6 @@ jobs:
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
APPLE_API_KEY_PATH: ${{ env.APPLE_API_KEY_PATH }}
with:
projectPath: apps/inspector
tagName: ${{ github.ref_name }}
args: ${{ matrix.args }}
119 changes: 119 additions & 0 deletions .github/workflows/_release-runtime.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
name: "[reusable] Lua runtime release"

# Publishes the Lua runtime to LuaRocks and attaches a zip to the GitHub release.
# Called by release-runtime.yml, which fires on both `runtime-v*` (runtime alone)
# and `v*` (full platform release).
#
# LuaRocks uploads are permanent and `fail_on_duplicate` is on, so a version
# burned here cannot be reused. The guard job below skips publishing entirely
# when packages/runtime-lua/feather is byte-identical to the previous runtime release, which
# is what makes it safe for a platform tag to fire this workflow unconditionally.

on:
workflow_call:
inputs:
force:
description: "Publish even when the runtime is unchanged"
type: boolean
default: false

jobs:
guard:
runs-on: ubuntu-latest
name: Check whether the runtime actually changed
outputs:
should_publish: ${{ steps.check.outputs.should_publish }}
version: ${{ steps.get_version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Resolve version from tag
id: get_version
run: |
VERSION="$(bash scripts/release-tag-version.sh "$GITHUB_REF_NAME" --version)"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Compare runtime against the previous runtime release
id: check
run: |
if [ "${{ inputs.force }}" = "true" ]; then
echo "Forced publish requested."
echo "should_publish=true" >> "$GITHUB_OUTPUT"
exit 0
fi

PREV="$(git tag --list 'runtime-v*' 'v*' --sort=-creatordate \
| grep -vxF "$GITHUB_REF_NAME" | head -n 1)"

if [ -z "$PREV" ]; then
echo "No previous runtime release found; publishing."
echo "should_publish=true" >> "$GITHUB_OUTPUT"
exit 0
fi

if git diff --quiet "$PREV" HEAD -- packages/runtime-lua/feather; then
echo "packages/runtime-lua/feather is unchanged since $PREV — skipping LuaRocks publish."
echo "should_publish=false" >> "$GITHUB_OUTPUT"
else
echo "packages/runtime-lua/feather changed since $PREV — publishing."
echo "should_publish=true" >> "$GITHUB_OUTPUT"
fi

luarocks-release:
runs-on: ubuntu-latest
name: LuaRocks upload
needs: guard
if: needs.guard.outputs.should_publish == 'true'
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Fail if changelog entry does not exist
run: grep -q "${{ github.ref_name }}" CHANGELOG.md

- name: Verify runtime version
run: |
RUNTIME_VERSION="$(sed -n 's/^local FEATHER_VERSION_NAME = "\([^"]*\)".*/\1/p' packages/runtime-lua/feather/init.lua | head -n 1)"
if [ "$RUNTIME_VERSION" != "${{ needs.guard.outputs.version }}" ]; then
echo "Tag version ${{ needs.guard.outputs.version }} does not match packages/runtime-lua/feather/init.lua version $RUNTIME_VERSION."
echo "Fix with: bash scripts/set-version.sh runtime ${{ needs.guard.outputs.version }}"
exit 1
fi

- name: LuaRocks Upload
uses: nvim-neorocks/luarocks-tag-release@v7
with:
version: ${{ needs.guard.outputs.version }}
license: Feather License
labels: |
love2d
löve
debug
copy_directories: |
packages/runtime-lua/feather
summary: Debug & Inspect Tool for LÖVE (love2d)
detailed_description: |
Feather is a debugger tool with a plugin system for Love2D projects.
fail_on_duplicate: true
env:
LUAROCKS_API_KEY: ${{ secrets.LUAROCKS_API_KEY }}

- name: Zip feather folder
run: |
# Two levels up: the release step below looks for the zip at the repo root.
cd packages/runtime-lua
zip -r ../../feather-${{ needs.guard.outputs.version }}.zip feather/

- name: GitHub Release
uses: ncipollo/release-action@v1
with:
artifacts: |
feather-${{ needs.guard.outputs.version }}-1.rockspec
feather-${{ needs.guard.outputs.version }}-1.src.rock
feather-${{ needs.guard.outputs.version }}.zip
allowUpdates: true
Loading
Loading