Ship the batch: undo, parallel subagents, lazy MCP, hot-reloaded skills; docs and CI/CD

Loop and ergonomics batch across Now/Next and Maintenance:
- /undo and /redo via pre-prompt file snapshots (snapshot.ts)
- task takes a tasks[] array and runs investigations concurrently (subagent.ts)
- lazy MCP tools: mcp_list/mcp_inspect/mcp_call meta-tools, eager opt-in (mcp.ts, config.ts)
- skill tool reads its list live so a mid-session install is callable next turn (skills.ts)
- tool-name lists (tool-kinds.ts) derived from a mutating() marker; gates previously ungated writes
- prune/session recovery path summarized, and step-back doom-loop primitive (step-back.ts)
- @file completion re-walks on a slow cooldown; estimateTokens and pricing labeled as estimates

Docs: README, CHANGELOG, docs/{mcp,architecture,development} updated to match.
CI/CD: bun install-store cache and concurrency gates on both workflows; release.yml now
composes file-based release notes via scripts/make-release-notes.ts and verifies every binary.
This commit is contained in:
Muhammad Zakir Ramadhan
2026-09-17 17:49:19 +07:00
parent ffa9a02c26
commit f8c3cc2d8e
57 changed files with 3808 additions and 573 deletions
+17
View File
@@ -5,6 +5,10 @@ on:
branches: [main]
pull_request:
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
check:
runs-on: ${{ matrix.os }}
@@ -16,9 +20,22 @@ jobs:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.14
# bun install --frozen-lockfile re-resolves nothing but still pays the network
# cost of a cold store; cache the store so a no-change run skips it. Key is per
# OS and lockfile, so a dependency bump or a new OS each gets a fresh cache.
- name: Cache the bun install store
uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
restore-keys: |
bun-${{ runner.os }}-
- run: bun install --frozen-lockfile
- run: bun run typecheck
- run: bun test
+38 -4
View File
@@ -10,9 +10,16 @@ on:
type: boolean
default: true
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
permissions:
contents: write
env:
BUN_VERSION: 1.3.14
jobs:
verify:
runs-on: ubuntu-latest
@@ -20,7 +27,14 @@ jobs:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.14
bun-version: ${{ env.BUN_VERSION }}
- name: Cache the bun install store
uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
restore-keys: |
bun-${{ runner.os }}-
- run: bun install --frozen-lockfile
- run: bun run typecheck
- run: bun test
@@ -32,15 +46,26 @@ jobs:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.14
bun-version: ${{ env.BUN_VERSION }}
- name: Cache the bun install store
uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
restore-keys: |
bun-${{ runner.os }}-
- run: bun install --frozen-lockfile
# Bun cross-compiles every target from one host, so no build matrix is needed.
# release.ts also fails the build when the tag and src/version.ts disagree.
- run: bun run release
- name: Check the binary reports the right version
- name: Check the binaries report the right version and are non-empty
run: |
for f in dist/release/shiro-linux-x64 dist/release/shiro-linux-arm64 \
dist/release/shiro-darwin-x64 dist/release/shiro-darwin-arm64; do
[ -s "$f" ] || { echo "$f is missing or empty"; exit 1; }
done
chmod +x dist/release/shiro-linux-x64
./dist/release/shiro-linux-x64 --version
./dist/release/shiro-linux-x64 --version | grep -q "$(bun -e 'console.log((await import("./src/version.ts")).VERSION)')"
@@ -66,12 +91,21 @@ jobs:
name: shiro-binaries
path: dist/release
# Release body: a short summary plus the artifact inventory, so the release
# page reads like a hand-written one instead of the raw PR list. The changelog
# is the prose; scripts/make-release-notes.ts extracts the section for this tag
# and fails if the heading is missing, rather than publishing an empty body.
- name: Compose release notes
env:
RELEASE_TAG: ${{ github.ref_name }}
run: bun run scripts/make-release-notes.ts
- name: Publish the release
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "${{ github.ref_name }}" \
--title "shiro-neko ${{ github.ref_name }}" \
--generate-notes \
--notes-file release_notes.md \
$([[ "${{ github.ref_name }}" == *-* ]] && echo --prerelease) \
dist/release/*