Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/bake-tables.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Bake pattern databases

# Manually triggered: bakes the optimal solver's tables on a CI runner
# and uploads the LZFSE seeds as a downloadable artifact. Drop the
# downloaded files into the repo's Seeds/ folder to have local builds
# bundle them automatically.
#
# The 7-edge tier takes minutes; the 8-edge tier several hours on a
# standard runner (it is ~75 min on a 10-core M5).

on:
workflow_dispatch:
inputs:
tier:
description: "Pattern database tier"
required: true
default: "7"
type: choice
options: ["7", "8"]

jobs:
bake:
name: Bake ${{ inputs.tier }}-edge tier
runs-on: macos-26
timeout-minutes: 350
steps:
- uses: actions/checkout@v4
- name: Runner resources
run: |
sysctl -n hw.ncpu hw.memsize
df -h "$RUNNER_TEMP"
- name: Bake
run: >
swift run -c release --package-path CubeKit cubekit-bake
${{ inputs.tier }} "$RUNNER_TEMP/pdb"
- name: Upload seeds
uses: actions/upload-artifact@v4
with:
name: pdb-seeds-${{ inputs.tier }}-edge
path: ${{ runner.temp }}/pdb/seeds
retention-days: 30
# The seeds are already LZFSE-compressed.
compression-level: 0
35 changes: 35 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: CI

on:
push:
branches: [main]
pull_request:

jobs:
engine-tests:
name: CubeKit tests (release)
runs-on: macos-26
timeout-minutes: 120
steps:
- uses: actions/checkout@v4
- name: Swift version
run: swift --version
- name: Run tests
run: swift test -c release --package-path CubeKit

app-build:
name: App builds
runs-on: macos-26
timeout-minutes: 40
steps:
- uses: actions/checkout@v4
- name: Build macOS app
run: >
xcodebuild -project cubeone.xcodeproj -scheme cubeone
-destination 'platform=macOS'
CODE_SIGNING_ALLOWED=NO build
- name: Build iOS app
run: >
xcodebuild -project cubeone.xcodeproj -scheme cubeone
-destination 'generic/platform=iOS Simulator'
CODE_SIGNING_ALLOWED=NO build
6 changes: 5 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ swift test --filter SolverTests # one suite (also: BeginnerSolverTests,
xcodebuild -project cubeone.xcodeproj -scheme cubeone -destination 'platform=macOS' build
xcodebuild -project cubeone.xcodeproj -scheme cubeone -destination 'generic/platform=iOS Simulator' build

# Headless table bake (CI or scripted local use)
swift run -c release --package-path CubeKit cubekit-bake 7 /tmp/pdb

# Run on iPhone simulator
xcrun simctl boot <device-udid>
xcrun simctl install <device-udid> <DerivedData>/Build/Products/Debug-iphonesimulator/cubeone.app
Expand Down Expand Up @@ -53,5 +56,6 @@ Key mechanisms to understand before touching play/scene code:
## Project decisions

- `ENABLE_ENHANCED_SECURITY = NO` is deliberate (user-approved): with it on, Xcode 26 builds the app arm64e but Swift packages arm64, breaking every build that uses CubeKit. Re-evaluate at release time.
- Workflow: each work chunk on a branch → PR → merge immediately. PR descriptions carry the design record (see #2–#15 for the full history).
- Workflow: each work chunk on a branch → PR → merge immediately. PR descriptions carry the design record (see #2 onward for the full history).
- CI (GitHub Actions, `macos-26` runners): every push/PR runs the release test suite and both app builds (unsigned). `bake-tables.yml` is a manual workflow that bakes PDB seeds on a runner for download into `Seeds/`. The repo is public under GPLv3 — keep license headers/notices intact.
- Verification habit: beyond unit tests, changes to play/scene behavior are verified interactively (launch the macOS app and drive it; `simctl` screenshots for iOS layout). macOS swallows the first click on an unfocused window — click once to focus before clicking buttons.
2 changes: 2 additions & 0 deletions CubeKit/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ let package = Package(
],
products: [
.library(name: "CubeKit", targets: ["CubeKit"]),
.executable(name: "cubekit-bake", targets: ["CubeKitBake"]),
],
targets: [
.target(name: "CubeKit"),
.executableTarget(name: "CubeKitBake", dependencies: ["CubeKit"]),
.testTarget(name: "CubeKitTests", dependencies: ["CubeKit"]),
]
)
42 changes: 42 additions & 0 deletions CubeKit/Sources/CubeKitBake/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import CubeKit
import Foundation

// Headless pattern-database baking, for CI or scripted local use.
// Usage: cubekit-bake <7|8> <output-directory>
// Writes tables to <out>/tables and compressed seeds to <out>/seeds.

let arguments = CommandLine.arguments
guard arguments.count == 3,
let tierValue = Int(arguments[1]),
let tier = OptimalTableTier(rawValue: tierValue)
else {
print("usage: cubekit-bake <7|8> <output-directory>")
exit(64)
}

let output = URL(fileURLWithPath: arguments[2], isDirectory: true)
let tables = output.appendingPathComponent("tables", isDirectory: true)
let seeds = output.appendingPathComponent("seeds", isDirectory: true)

let clock = ContinuousClock()
let started = clock.now
print("Baking \(tier.rawValue)-edge tier into \(tables.path)")

do {
try PatternDatabaseSet.generate(
tier: tier, in: tables, seedsDirectory: seeds,
progress: { progress in
let percent = Int(progress.filledFraction * 100)
print("[\(progress.tableIndex + 1)/\(progress.tableCount)] "
+ "\(progress.tableName) depth \(progress.depth) — \(percent)% "
+ "(\(clock.now - started) elapsed)")
fflush(stdout)
},
isCancelled: { false }
)
} catch {
print("Bake failed: \(error)")
exit(1)
}

print("Done in \(clock.now - started). Seeds in \(seeds.path)")
Loading
Loading