Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
d09f91c
feat(models): define shared model and configuration data
thunderock Sep 22, 2026
4339511
fix(config): unify model-class validation and migration previews
thunderock Sep 22, 2026
3fb7a3b
test(skills): enforce the portable frontmatter contract
thunderock Sep 22, 2026
fdebb04
feat(dependencies): declare supported native workflow peers
thunderock Sep 22, 2026
c43b13f
feat(routing): resolve workflow capabilities without silent fallback
thunderock Sep 22, 2026
9140425
feat(cli): describe native dependencies and propagate installer failures
thunderock Sep 22, 2026
5f59c9b
fix(models): align catalog and configuration contract
thunderock Sep 23, 2026
d020470
fix(config): reject ambiguous configuration inputs
thunderock Sep 23, 2026
cb41e3b
fix(config): reject ASCII controls in frozen paths
thunderock Sep 23, 2026
3f3f7e4
fix(frontmatter): enforce compatibility bounds with fixed fixtures
thunderock Sep 23, 2026
5a25d74
test(frontmatter): keep contract checks type-safe
thunderock Sep 23, 2026
5609c18
feat(dependencies): pin deployed provenance for native peer targets
thunderock Sep 23, 2026
01c5106
refactor(tests): separate dependency contract validation
thunderock Sep 23, 2026
0505478
fix(dependencies): enforce provenance and native role contracts
thunderock Sep 23, 2026
cc8970b
docs(delegation): clarify native binding and decision records
thunderock Sep 23, 2026
e1c0f81
test(routing): construct real native peer fixtures
thunderock Sep 23, 2026
c4ea616
fix(routing): qualify native bytes models and task homes
thunderock Sep 23, 2026
995c015
test(routing): cover portable CLI decisions and input safety
thunderock Sep 23, 2026
7b70926
fix(routing): reject whitespace-only native descriptors
thunderock Sep 23, 2026
959d5d0
fix(packaging): make individual skill payloads self-contained
thunderock Sep 23, 2026
74d072a
test(fixtures): define explicit host binding recipes
thunderock Sep 23, 2026
b24d922
test(skills): evaluate contracts with real peer fixtures
thunderock Sep 23, 2026
f58835c
docs(tests): show structural scenario expectations
thunderock Sep 23, 2026
086786a
test(preflight): characterize CLI selections and process outcomes
thunderock Sep 24, 2026
09677f3
fix(preflight): validate safe CLI completion evidence
thunderock Sep 24, 2026
297d47f
fix(preflight): enforce catalog selections and verified family gates
thunderock Sep 24, 2026
1c2504d
refactor(ask): keep closed answers independent of advisor workflows
thunderock Sep 24, 2026
e049755
fix(router): keep chosen models across backends and gate execution on…
thunderock Sep 24, 2026
cf2c1ac
refactor(intake): reuse compatible interview capabilities
thunderock Sep 24, 2026
2a52266
fix(intake): stop on blocked routes and unbound planners
thunderock Sep 24, 2026
a10fb7a
docs(preflight): define verified fleet consumer contract
thunderock Sep 24, 2026
d1269f0
refactor(spec): keep clarification requirements-only across interview…
thunderock Sep 24, 2026
5003539
fix(spec): require planner binding and separate invocation failures
thunderock Sep 24, 2026
2182906
refactor(mapping): reuse read-only reconnaissance with explicit limits
thunderock Sep 24, 2026
ae72673
refactor(decisions): preserve owner choices through interview delegation
thunderock Sep 24, 2026
3aa0a32
refactor(research): reuse native research with source-qualified routing
thunderock Sep 24, 2026
4e7159d
refactor(learning): reuse knowledge workflows before drafting new skills
thunderock Sep 24, 2026
31f3697
refactor(planning): hand off to native planners without duplicating o…
thunderock Sep 24, 2026
8afd298
fix(planning): distinguish required and optional inputs
thunderock Sep 24, 2026
7ce7c3b
refactor(execution): enforce single ownership and selected-model disp…
thunderock Sep 24, 2026
e7fb394
refactor(review): preserve independent cross-family gates
thunderock Sep 25, 2026
b22aea1
fix(review): stop requiring untracked review reports
thunderock Sep 25, 2026
7934764
refactor(uat): preserve read-only surface checks across backends
thunderock Sep 25, 2026
0c00367
refactor(debugging): reuse investigations without fabricating fix evi…
thunderock Sep 25, 2026
0605367
chore: keep repository working records local
thunderock Sep 25, 2026
00e26e9
chore(packaging): exclude local tool state
thunderock Sep 25, 2026
e15fa52
feat(release): validate canonical versions and channels
thunderock Sep 24, 2026
3096d0b
feat(release): validate trusted workflow requests
thunderock Sep 24, 2026
4e786dd
feat(release): bind records to immutable artifacts
thunderock Sep 24, 2026
2681cd7
feat(release): select and reconcile immutable releases
thunderock Sep 24, 2026
385188f
refactor(delivery): preserve explicit release authority and clean sum…
thunderock Sep 25, 2026
4ec378d
refactor(docs): retain source-verified project documentation semantics
thunderock Sep 25, 2026
29bf51e
refactor(audit): retain complete requirements coverage across delegates
thunderock Sep 25, 2026
4bb246a
refactor(memory): unify portable project selections and decision records
thunderock Sep 25, 2026
5515ff0
refactor(handoff): preserve provenance and validate resume targets
thunderock Sep 25, 2026
27b5221
docs: explain native workflow dependencies
thunderock Sep 25, 2026
9427788
docs(config): align project guidance with model classes
thunderock Sep 25, 2026
a35dd0e
ci(release): publish immutable releases from gated artifacts
thunderock Sep 25, 2026
9ef47a1
docs(release): describe automatic and manual releases
thunderock Sep 25, 2026
6427709
docs(changelog): point release history to GitHub Releases
thunderock Sep 25, 2026
e14eba8
fix(release): initialize runner paths in supported step scope
thunderock Sep 25, 2026
0fe6177
fix(site): render skill contracts and detect content drift
thunderock Sep 25, 2026
53cef8f
fix(site): resolve linked public root documents
thunderock Sep 25, 2026
fe99128
chore: ignore local package artifacts
thunderock Sep 25, 2026
bd5882d
build: integrate offline contract and package checks
thunderock Sep 25, 2026
c639a8b
ci: use matching offline verification runtimes
thunderock Sep 25, 2026
55e8d27
fix(site): link the canonical root README
thunderock Sep 25, 2026
617d15b
docs(site): refresh public guides and shared references
thunderock Sep 25, 2026
f02a667
feat(release): inspect and extract archives safely
thunderock Sep 25, 2026
0439e83
feat(release): bound git, registry and gh transports
thunderock Sep 25, 2026
f4e7a06
feat(release): stamp, pack and verify the publishable artifact
thunderock Sep 25, 2026
ff7f5fb
feat(release): plan a source-bound release without remote writes
thunderock Sep 25, 2026
14a8683
feat(release): publish through a finite tag, npm and GitHub lifecycle
thunderock Sep 25, 2026
42315d6
fix(release): isolate fixtures from development state
thunderock Sep 25, 2026
103c290
test(release): preserve public documents in fixture copies
thunderock Sep 25, 2026
8198603
fix(release): verify the selected public dependency document
thunderock Sep 25, 2026
1e964a9
test(release): cover lock and shrinkwrap version consistency
thunderock Sep 25, 2026
bdb31a8
fix(release): reject overlapping workspaces before writes
thunderock Sep 25, 2026
c8ebe44
fix(release): reject malformed registry redirects safely
thunderock Sep 25, 2026
6d854e9
test(release): declare explicit payload policies in fixtures
thunderock Sep 25, 2026
44790ff
test(release): declare shrinkwrap selection in fixtures
thunderock Sep 25, 2026
15f7c8c
fix(release): verify public guide selected by root allowlist
thunderock Sep 25, 2026
4ea997e
fix(build): enforce exact full-suite runtime versions
thunderock Sep 25, 2026
88b6d32
fix(build): isolate temporary Node test executables
thunderock Sep 25, 2026
8795a66
test(frontmatter): allocate adapter scratch under the supplied privat…
thunderock Sep 27, 2026
a1181ba
test(model-config): split the configuration suite into cohesive modules
thunderock Sep 27, 2026
14069d6
feat(dependencies): resolve host-required peers through a machine-loc…
thunderock Sep 27, 2026
c2af238
feat(config): allow the gsd ecosystem and enable it by default
thunderock Sep 27, 2026
4d30e9d
feat(routing): delegate project-free work to GSD on other hosts
thunderock Sep 27, 2026
09dfbe7
docs(dependencies): describe host-required peers and keep GSD project…
thunderock Sep 27, 2026
59ec88a
feat(cli): resolve and print the host-required peer install without r…
thunderock Sep 27, 2026
49c5be2
feat(skills): add tk-fast and tk-quick for small changes
thunderock Sep 27, 2026
199c645
ci(peers): report each host peer channel weekly without write access
thunderock Sep 27, 2026
98c379d
feat(tools): report wrapped and unwrapped upstream peer skills offline
thunderock Sep 27, 2026
8db8f01
feat(skills): ask users through host choice tools with a numbered fal…
thunderock Sep 27, 2026
dc378b4
fix(site): keep wide tables and code readable on narrow screens
thunderock Sep 27, 2026
929dbf1
test(package): put the pinned npm ahead of the Node-bundled npm on PATH
thunderock Sep 27, 2026
f8fce0b
test(release): hide runner provenance variables when checking the for…
thunderock Sep 27, 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
  •  
  •  
  •  
31 changes: 26 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,43 @@ name: ci
push:
branches: ["**"]
pull_request:
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97
with:
python-version: "3.12"
- name: Run tests (frontmatter + roster + drift)
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
with:
node-version: "24"
package-manager-cache: false
- name: Prepare isolated npm CLI
run: |
umask 077
prefix="$(mktemp -d "$RUNNER_TEMP/npm-cli.XXXXXX")"
cd "$RUNNER_TEMP"
npm install --prefix "$prefix" --ignore-scripts --no-audit --no-fund --package-lock=false npm@11.19.1
printf '%s\n' "$prefix/node_modules/.bin" >> "$GITHUB_PATH"
- name: Run all offline tests
env:
npm_config_offline: "true"
npm_config_ignore_scripts: "true"
npm_config_audit: "false"
npm_config_fund: "false"
run: make run_tests
- name: Lint
run: make lint
- name: Leakage gate (no secrets / proprietary strings)
run: |
if grep -rniE 'adobe|astiwari|sensei-fs|AWS_BEARER|\.internal\b|\bcorp\.|firefly|\borion\b' \
skills site README.md NORTH_STAR.md .thunderkit; then
skills site bin README.md NORTH_STAR.md DEPENDENCIES.md .thunderkit; then
echo "::error::leakage denylist hit"; exit 1
fi
echo "leakage gate clean"
Expand Down
28 changes: 28 additions & 0 deletions .github/workflows/peers-watch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: peers-watch
"on":
schedule:
- cron: "17 6 * * 1"
workflow_dispatch:
permissions:
contents: read
jobs:
watch:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
with:
node-version: "24"
package-manager-cache: false
- name: Resolve each host's required peer channel
run: |
set -eu
{
echo "## Peer channels"
for host in hermes opencode claude codex copilot; do
node bin/thunderkit.js peers --host "$host"
done
} >> "$GITHUB_STEP_SUMMARY"
29 changes: 0 additions & 29 deletions .github/workflows/publish.yml

This file was deleted.

236 changes: 202 additions & 34 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
@@ -1,49 +1,217 @@
name: release-please
name: Release
"on":
push:
branches: ["master"]
branches: [master]
workflow_dispatch:
inputs:
version:
description: Exact version; leave empty for automatic stable versioning
required: false
type: string
npm_tag:
description: Optional channel for an exact version
required: false
type: string

permissions:
contents: write
pull-requests: write
id-token: write # for the publish job (npm OIDC trusted publishing)
permissions: {}
concurrency:
group: npm-release
cancel-in-progress: false
defaults:
run:
shell: bash
env:
RELEASE_VERSION_INPUT: ${{ inputs.version }}
RELEASE_NPM_TAG_INPUT: ${{ inputs.npm_tag }}
npm_config_registry: https://registry.npmjs.org
GIT_CONFIG_GLOBAL: /dev/null
GIT_CONFIG_NOSYSTEM: "1"

jobs:
release-please:
runs-on: ubuntu-latest
gate:
if: ${{ github.repository == 'thunderock/thunderkit' && github.ref == 'refs/heads/master' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
runs-on: ubuntu-24.04
timeout-minutes: 30
permissions:
contents: read
outputs:
release_created: ${{ steps.rp.outputs.release_created }}
tag_name: ${{ steps.rp.outputs.tag_name }}
action: ${{ steps.plan.outputs.action }}
record_sha256: ${{ steps.plan.outputs.record_sha256 }}
artifact_id: ${{ steps.upload.outputs.artifact-id }}
steps:
- id: rp
uses: googleapis/release-please-action@v4
with:
release-type: node
# Config + manifest live in the repo so the next version is computed
# from Conventional Commits since the last tag — no manual bump.
config-file: .release-please-config.json
manifest-file: .release-please-manifest.json
- id: environment
name: Initialize isolated configuration paths
run: |
printf '%s\n' \
"npm_config_userconfig=$RUNNER_TEMP/npm-userconfig" \
"npm_config_globalconfig=$RUNNER_TEMP/npm-globalconfig" \
"npm_config_cache=$RUNNER_TEMP/npm-cache" \
"GH_CONFIG_DIR=$RUNNER_TEMP/gh-config" \
>> "$GITHUB_ENV"
- id: checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.sha }}
fetch-depth: 0
fetch-tags: true
persist-credentials: false
set-safe-directory: false
- id: node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "24"
package-manager-cache: false
- id: python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- id: npm
name: Prepare isolated npm CLI
run: |
umask 077
: > "$npm_config_userconfig"
: > "$npm_config_globalconfig"
prefix="$(mktemp -d "$RUNNER_TEMP/npm-cli.XXXXXX")"
cd "$RUNNER_TEMP"
npm install --prefix "$prefix" --ignore-scripts --no-audit --no-fund --package-lock=false npm@11.19.1
printf '%s\n' "$prefix/node_modules/.bin" >> "$GITHUB_PATH"
- id: tools
name: Verify tools and source
run: |
node -e 'if (process.versions.node.split(".")[0] !== "24") process.exit(1)'
test "$(npm --version)" = '11.19.1'
python3 -c 'import sys; assert sys.version_info[:2] == (3, 12)'
for tool in git gh make; do command -v "$tool" > /dev/null; done
api_help="$(gh api --help)"
for flag in --include --method; do [[ "$api_help" == *"$flag"* ]]; done
release_help="$(gh release create --help)"
for flag in --repo --verify-tag --target --title --generate-notes --prerelease --latest; do [[ "$release_help" == *"$flag"* ]]; done
test "$(git rev-parse HEAD)" = "$GITHUB_SHA"
- id: plan
name: Validate and prepare release
env:
GH_TOKEN: ${{ github.token }}
run: node tools/release/plan.mjs --workspace "$RUNNER_TEMP/release"
- id: tests
name: Test the stamped source
if: ${{ success() && steps.plan.outputs.action == 'publish' }}
run: |
cd "$RUNNER_TEMP/release/source"
make run_tests && make lint && npm test
node --test tests/release_*.test.mjs
make site
- id: verify
name: Verify unchanged bundle after tests
if: ${{ success() && steps.plan.outputs.action == 'publish' }}
env:
RELEASE_RECORD_SHA256: ${{ steps.plan.outputs.record_sha256 }}
run: |
node --input-type=module <<'NODE'
import assert from 'node:assert/strict';
import { createHash } from 'node:crypto';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
const bundle = join(process.env.RUNNER_TEMP, 'release', 'bundle');
const bytes = readFileSync(join(bundle, 'release-plan.json'));
assert.match(process.env.RELEASE_RECORD_SHA256, /^[a-f0-9]{64}$/);
assert.equal(createHash('sha256').update(bytes).digest('hex'), process.env.RELEASE_RECORD_SHA256);
const record = JSON.parse(bytes);
assert.equal(record.action, 'publish');
assert.equal(record.release.tarball.file, 'package.tgz');
const tarball = readFileSync(join(bundle, 'package.tgz'));
assert.equal(tarball.length, record.release.tarball.size);
assert.equal('sha512-' + createHash('sha512').update(tarball).digest('base64'), record.release.tarball.integrity);
NODE
- id: upload
if: ${{ success() && steps.plan.outputs.action == 'publish' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: release-${{ github.run_id }}-${{ github.run_attempt }}
path: |
${{ runner.temp }}/release/bundle/release-plan.json
${{ runner.temp }}/release/bundle/package.tgz
if-no-files-found: error
overwrite: false
archive: true

# Publish in the SAME run. A GitHub Release created with GITHUB_TOKEN never
# triggers other workflows (`on: release` stays silent), so publishing must be
# chained here rather than listening for the release event.
publish:
needs: release-please
if: ${{ needs.release-please.outputs.release_created == 'true' }}
runs-on: ubuntu-latest
needs: gate
if: ${{ github.repository == 'thunderock/thunderkit' && github.ref == 'refs/heads/master' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && needs.gate.result == 'success' && needs.gate.outputs.action == 'publish' }}
runs-on: ubuntu-24.04
timeout-minutes: 15
permissions:
contents: read
contents: write
id-token: write
steps:
- uses: actions/checkout@v4
- id: environment
name: Initialize isolated configuration paths
run: |
printf '%s\n' \
"npm_config_userconfig=$RUNNER_TEMP/npm-userconfig" \
"npm_config_globalconfig=$RUNNER_TEMP/npm-globalconfig" \
"npm_config_cache=$RUNNER_TEMP/npm-cache" \
"GH_CONFIG_DIR=$RUNNER_TEMP/gh-config" \
>> "$GITHUB_ENV"
- id: checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ needs.release-please.outputs.tag_name }}
- uses: actions/setup-node@v4
ref: ${{ github.sha }}
fetch-depth: 0
fetch-tags: true
persist-credentials: false
set-safe-directory: false
- id: node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "24"
registry-url: "https://registry.npmjs.org"
- run: npm install -g npm@latest
- name: Verify the pack contents (skills + bin, no repo noise)
run: npm pack --dry-run
- name: Publish to npm (OIDC trusted publishing, public)
run: npm publish --provenance --access public
package-manager-cache: false
- id: python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- id: npm
name: Prepare isolated npm CLI
run: |
umask 077
: > "$npm_config_userconfig"
: > "$npm_config_globalconfig"
prefix="$(mktemp -d "$RUNNER_TEMP/npm-cli.XXXXXX")"
cd "$RUNNER_TEMP"
npm install --prefix "$prefix" --ignore-scripts --no-audit --no-fund --package-lock=false npm@11.19.1
printf '%s\n' "$prefix/node_modules/.bin" >> "$GITHUB_PATH"
- id: tools
name: Verify tools and source
run: |
node -e 'if (process.versions.node.split(".")[0] !== "24") process.exit(1)'
test "$(npm --version)" = '11.19.1'
python3 -c 'import sys; assert sys.version_info[:2] == (3, 12)'
for tool in git gh make; do command -v "$tool" > /dev/null; done
api_help="$(gh api --help)"
for flag in --include --method; do [[ "$api_help" == *"$flag"* ]]; done
release_help="$(gh release create --help)"
for flag in --repo --verify-tag --target --title --generate-notes --prerelease --latest; do [[ "$release_help" == *"$flag"* ]]; done
test "$(git rev-parse HEAD)" = "$GITHUB_SHA"
- id: handoff
name: Require exact artifact identity
env:
RELEASE_ARTIFACT_ID: ${{ needs.gate.outputs.artifact_id }}
RELEASE_RECORD_SHA256: ${{ needs.gate.outputs.record_sha256 }}
run: |
node --input-type=module <<'NODE'
import assert from 'node:assert/strict';
assert.match(process.env.RELEASE_ARTIFACT_ID, /^[1-9][0-9]*$/);
assert.match(process.env.RELEASE_RECORD_SHA256, /^[a-f0-9]{64}$/);
NODE
- id: download
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
artifact-ids: ${{ needs.gate.outputs.artifact_id }}
path: ${{ runner.temp }}/release-bundle
merge-multiple: true
digest-mismatch: error
- id: publish
name: Publish the verified tarball
env:
GH_TOKEN: ${{ github.token }}
RELEASE_RECORD_SHA256: ${{ needs.gate.outputs.record_sha256 }}
run: node tools/release/publish.mjs --bundle "$RUNNER_TEMP/release-bundle"
17 changes: 13 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,24 @@
__pycache__/
*.pyc

# thunderkit lane execution is machine-local (worktrees + dispatch run records)
.thunderkit/runs/
# Repository-local context
.thunderkit/*
!.thunderkit/NORTH_STAR.md
!.thunderkit/PHILOSOPHY.md
!.thunderkit/config.json
wt-*/

# macOS
.DS_Store

# oh-my-claudecode / harness state written by tk-test CLI probes — never ours to commit
# Local tool state
.omo/
.omo-tmp/
.omh/
.omc/
.planning/
node_modules/
*.tgz

# Note: site/_site IS committed (GitHub Pages serves it, and tests/site_drift.py
# gates the committed skills.json against skills/ on disk).
# checks the complete public file set, contents and local links).
Loading