Instruction file imported from williamisnotdefined/rubiks-cube-solver (
.cursor/rules/project-core.mdc). Copyright stays with the author.
Generated from ai/registry.json. Do not edit manually.
Canonical skill: ../../ai/skills/project-core.md.
Referenced context:
../../ai/rules/repository-rules.md../../ai/rules/testing-rules.md../../ai/rules/ai-rules.md../../ai/architecture/project-architecture.md../../ai/architecture/ai-knowledge-system.md../../ai/glossary/cube-terms.md
This file is compiled from canonical AI knowledge files. Edit canonical files under ai, then run npm run ai:sync.
Compiled AI Skill: project-core
Canonical Skill: ai/skills/project-core.md
Project Core
Use this skill as the always-on repository baseline for AI-assisted changes anywhere in the Rubik's Cube solver.
Goal
Keep every change aligned with Rust engine boundaries, cube domain language, current project priorities, verification flow, and AI knowledge maintenance rules.
Read First
ai/rules/repository-rules.mdai/rules/testing-rules.mdai/rules/ai-rules.mdai/architecture/project-architecture.mdai/architecture/ai-knowledge-system.mdai/glossary/cube-terms.md
Workflow
- Start from
docs/project-plan.md, nearby code, tests, and source docs before changing behavior. - Create or switch to a dedicated task branch before changing files; never work or commit directly on
main. - Apply a narrower skill when the task touches cube engine, solver search, API boundary, frontend visualization, or AI knowledge.
- Keep solver logic in Rust and keep AI routes generated.
- Run targeted verification first, then broader checks when a change crosses boundaries.
Expected Output
- Code follows the current repository boundaries and documented priorities.
- Generated AI route files are never edited manually.
- Final reporting names verification that was run or explains why it was blocked.
Verification
- Run
npm run ai:checkafter AI knowledge changes. - Run
cargo test -p cube-engineafter engine changes when Rust is installed.
Referenced Context
Reference: ai/rules/repository-rules.md
Repository Rules
Global rules for changes anywhere in this repository.
Always
- Read
docs/project-plan.md, nearby code, and current tests before changing behavior. - Prefer the smallest correct change with the lowest surface area.
- Follow existing naming, file layout, import style, error handling, and command style before introducing a new pattern.
- Keep implementation aligned with the current priorities in
docs/project-plan.mdand the capabilities already present in code. - Keep solver logic in Rust engine code, not in frontend or AI tooling.
- Use cubie representation as the primary engine model.
- For multi-puzzle work, keep state, move models, notation, validation, and solver strategy puzzle-specific unless a shared type is strictly metadata or infrastructure.
- Keep workspace-specific code inside the owning workspace unless there is a current cross-workspace consumer.
- Use repository-root commands such as
npm run ai:check,npm run api:test,npm run build, andcargo testso paths and workspaces resolve consistently. - Before any task that changes files, create or switch to a dedicated branch; never work directly on
mainfor task changes. - For
web, use Biome through workspace scripts for linting and formatting; do not add ESLint or Prettier configs unless explicitly requested. - Run targeted verification for the affected area and report any environment blockers.
- Before any AI-created commit or pull request, run
cargo clippy --all-targets --all-features -- -D warningsfrom the repository root when the Rust toolchain is available. - Keep AI route files generated from canonical files under
ai. - Use
npm run devfor the default Docker development runtime,live:deployfor production Docker deploys aftermainchanges,live:restartonly when the checkout is already current, andlive:startwhen the Cloudflare tunnel should be started after a production deploy.
Never
- Do not add machine learning, reinforcement learning, or Transformers without an explicit current product requirement.
- Do not use sticker/color arrays as the primary solver representation.
- Do not mix UI rendering logic with cube engine logic.
- Do not add a generic puzzle engine, universal state type, universal move type,
BaseMove,BaseState,BasePuzzle, or inheritance-style puzzle abstraction. - Do not commit
.envfiles, raw secrets, API tokens, model artifacts with private data, or local solver output that is not intended for source control. - Do not commit directly on
main; create a task branch first and do not bypass branch-protection hooks with--no-verify. - Do not edit
.agents/skills,.opencode/skills,.cursor/rules, or.github/instructionsAI route files manually. - Do not add compatibility layers or future abstractions without a concrete current consumer.
- Do not add a new formatter, linter, framework, or workspace-wide tool unless explicitly requested.
- Do not use nested ternary expressions; use explicit
if/return, a named helper, or a small lookup table instead. - Do not use
docker restartor start an old production container to deploy code changes; production code changes require a Docker rebuild throughlive:deploy,live:restart,prod:deploy,prod:restart, or the lower-leveldocker:upwrapper.
Runtime Scripts
dev,dev:start,dev:restart,dev:stop,dev:status,dev:logs, anddev:health: default Docker development runtime on ports5173,8788, and8791.dev:local:prepare,dev:local,dev:local:status, anddev:local:stop: non-Docker fallback runtime for development/debugging on ports5173,8788, and8791.live:deploy: preferred production update command after PRs merge; switches tomain, pullsorigin/main, rebuilds/recreates Docker production, waits forhttp://127.0.0.1:8787/health, and prints status.live:restart: rebuilds/recreates Docker production without pulling Git; use when the checkout is already current.live:health,live:status,live:logs, andlive:stop: production health/status/log/stop helpers.live:start: deploys production withlive:deploy, then startscloudflared tunnel run --token "$CLOUDFLARED_TUNNEL_TOKEN"forspeedcube.com.br.live:tunnel: starts only the Cloudflare tunnel and assumes production Docker is already healthy.prod:*,docker:up,docker:down,docker:restart,docker:status, anddocker:logs: lower-levelrubiks-prodCompose wrappers; preferlive:*unless you specifically need raw Compose behavior.docker:devanddocker:dev:down: compatibility wrappers for Docker dev; preferdev:*.docker:trainanddocker:train-gpu: scanner training containers, separate from normal runtime.
Verification
- AI knowledge changes:
npm run ai:check. - Rust engine changes: run the narrowest relevant
cargo testfirst, thencargo test -p cube-engineorcargo testwhen Rust is installed. - API changes:
npm run api:testor the relevantcargo test -p rubiks-cube-solver-apitarget. - Web changes:
npm run buildandnpm run lint -w @rubiks-cube-solver/webwhen dependencies are installed. - Broad repository changes: run affected targeted checks first, then broader checks only when the change crosses boundaries.
- Commit and PR requests: run
cargo clippy --all-targets --all-features -- -D warningsbefore committing, pushing, or opening/updating the PR, or report the environment blocker if it cannot run.
Reference: ai/rules/testing-rules.md
Testing Rules
Testing rules for this repository.
Always
- Add Rust unit tests next to pure functions when behavior is introduced.
- Add integration tests under the owning crate when behavior crosses module boundaries.
- Add regression tests next to changed behavior when fixing bugs.
- Test observable cube behavior: solved state, inverse moves, notation parsing, scramble inversion, validation, and search output.
- Test HTTP/API behavior through request and response contracts when
crates/apibehavior changes. - Test web API-client and UI behavior through public component or request boundaries when frontend behavior changes.
- Test scanner training code with deterministic fixtures or fixed seeds.
- Keep algorithm tests deterministic.
- Run the narrowest test first, then the affected crate test command.
- Use Vitest APIs such as
describe,it,expect,vi.fn, andvi.spyOnforwebunit and component tests. - Keep
webtests in__tests__/folders beside the source area they cover. - Use Testing Library for React component behavior and public accessibility queries.
- Use Playwright accessibility queries for E2E flows and shared E2E helpers for non-native controls such as Radix Select.
- Timer keyboard regressions MUST cover navigation into the timer and closing timer controls that normally restore focus, then prove keyboard timing works without manually focusing the timer display.
- Keep web API request and hook tests in the nearest API-domain
__tests__directory, including the established root, client, and domain-level locations; use shared helpers underapps/web/src/test. - Keep
apps/web/src/coretests underapps/web/src/core/<category>/__tests__/<name>.test.ts. - Keep global
webcoverage thresholds at 90% for statements, branches, functions, and lines.
Never
- Do not rely on random tests without a fixed seed.
- Do not assert implementation details when public cube behavior can be asserted.
- Do not leave focused-only tests such as
.onlyin committed test files. - Do not add duplicate test helpers when nearby crate, web, API, or scanner helpers already cover the setup.
- Do not add tests for future surfaces that do not exist yet.
- Do not use Jest-only APIs or
jest.mockpatterns in Vitest tests. - Do not place
webtests as loose sibling*.test.ts(x)files when a nearby__tests__/folder is available. - Do not add duplicate web test helpers when
apps/web/src/test/render.tsxorapps/web/src/test/api.tsalready covers the setup. - Do not use Playwright
selectOption()orlocator('option')for Radix Select controls; use helpers undertests/e2e/select-helpers.ts.
Verification
- Cube engine tests:
cargo test -p cube-engine. - API tests:
npm run api:testorcargo test -p rubiks-cube-solver-api. - Workspace tests:
cargo test. - Web build/lint:
npm run buildandnpm run lint -w @rubiks-cube-solver/web. - Web unit tests:
npm run test -w @rubiks-cube-solver/web. - Web coverage:
npm run test:coverage -w @rubiks-cube-solver/web. - Web Storybook:
npm run storybook:build -w @rubiks-cube-solver/web. - End-to-end tests:
npm run test:e2eafter the API, web app, and pruning-table prerequisites are available. - E2E split commands:
npm run test:e2e:smokefor product/responsive/timer smoke,npm run test:e2e:scanfor serial manual scan coverage, andnpm run test:e2e:fullfor the complete non-heavy suite. - Product gate:
npm run product:gatefor release-level or cross-boundary validation. - AI routes:
npm run ai:check.
Reference: ai/rules/ai-rules.md
AI Rules
Rules for maintaining the AI knowledge base itself.
Always
- Treat
aias the source of truth for AI guidance. - Keep reusable knowledge in
rules,architecture, andglossary. - Keep
skillstask-oriented: each skill should orchestrate references instead of duplicating them. - Add every routed skill to
ai/registry.json. - Use
referencesinai/registry.jsonfor every rule, architecture, or glossary file a skill depends on. - Keep each skill's
## Read Firstlist identical to itsregistry.jsonreferenceslist. - Apply executable contracts, accepted ADRs, architecture, rules, and skills in that precedence order; skills MUST NOT redefine referenced guidance.
- Use MUST/SHOULD/MAY intentionally and document narrow exceptions to SHOULD or conflicts with higher-precedence contracts.
- Run
npm run ai:syncafter changing canonical skills, registry entries, or referenced knowledge files. - Run
npm run ai:checkbefore finishing AI knowledge changes.
Never
- Do not edit generated route files manually.
- Do not place long architecture explanations inside skills when they belong in
architecture. - Do not place reusable coding rules inside skills when they belong in
rules. - Do not teach generic programming knowledge; document how this project works.
- Do not create a new skill when a new reference document would solve the context gap.
- Do not set Cursor
alwaysApply: trueoutside the explicitly globalproject-coreskill.
Route Generation
- Generated route files are compiled from the canonical skill plus its registry references.
- Manual edits to generated route files are invalid and should be replaced by
npm run ai:sync. - Orphan generated route files should be removed by
npm run ai:sync.
Reference: ai/architecture/project-architecture.md
Project Architecture
The target is a Rubik's Cube solver with a Rust engine, search algorithms, heuristics, pattern databases, a native HTTP API, optional scanner support, and a modern web visualization.
Current Structure
crates/cube-engine: Rust crate for cube representation, moves, notation, scramble handling, search, and heuristics.crates/api: Axum HTTP API around the Rust engine and generated pruning-table artifacts.apps/web: Vite React app built as static HTML for indexable routes, hydrated with React, then operated as an SPA.apps/wca-data: independent NestJS/Fastify workspace with a PostgreSQL-backed public WCA reference API and a separate import worker.packages/rubiks-cube: active private workspace for puzzle-specific Three.js visualization and playback adapters.scanner: Python scanner contracts, FastAPI runtime, and offline scanner training/evaluation tooling.ai: canonical AI knowledge base and route generation system.docs/project-plan.md: current technical direction, implementation rules, and puzzle boundaries.
Generated Artifacts
- Native pruning tables are generated by
cube-enginebinaries and loaded bycrates/api. - Solver quality reports and real-scramble gates are executable verification artifacts, not frontend behavior.
Runtime And Deployment
- Docker dev is the default development runtime. Use
npm run devto build/recreate therubiks-devCompose project, wait for health, and serve web/API/vision on ports5173,8788, and8791. - Local non-Docker fallback uses
dev:local:prepareanddev:localfor development/debugging when Docker is not desired. - Docker production uses the
rubiks-prodCompose project. Uselive:deployafter merges to pullorigin/main, rebuild/recreate containers, wait for app health, and print status. - Use
live:restartonly when the checkout is already current and containers need to be rebuilt/recreated. live:startruns production deploy first and then starts the Cloudflare tunnel forspeedcube.com.brwithcloudflared tunnel run --token "$CLOUDFLARED_TUNNEL_TOKEN".live:tunnelruns only the tunnel command and assumes production Docker is already healthy.- Docker dev, Docker production, and scanner training use separate Compose projects/commands so they do not collide.
Multi-Puzzle Direction
- Additional puzzles must own puzzle-specific state, move models, notation parsers, validators, solvers, heuristics, coordinates, and artifact rules.
- Shared multi-puzzle code is limited to metadata, registries, budgets, results, compatibility checks, API contracts, and visualization adapter selection.
- Do not introduce a generic puzzle engine, universal move type, universal state type,
BaseMove,BaseState,BasePuzzle, or inheritance-style puzzle hierarchy.
Future Or Optional Boundaries
crates/wasm: optional future wasm-bindgen bridge around the Rust engine if browser-local solving becomes a concrete product requirement.- Additional frontend routing, shared component libraries, or state managers should wait for current UI complexity to require them.
Ownership
- Cube state, moves, validation, search, and heuristics belong in Rust.
- The API validates HTTP contracts, applies safety limits, calls Rust solver code, and returns typed solver results.
- Frontend code should only render, collect notation/limits, send solve requests, receive states, and play animations.
- Scanner runtime code may produce visual evidence, but reviewed stickers, cube validation, and solving remain Rust/product boundaries.
- WCA reference data, import lifecycle, and its public
/api/wca-data/v1contract belong toapps/wca-data, not the Rust solver API.
Reference: ai/architecture/ai-knowledge-system.md
AI Knowledge System Architecture
ai is the canonical AI knowledge base for this repository.
Source Layers
rules: reusable constraints, conventions, and anti-patterns.architecture: system boundaries and integration points.glossary: cube and solver vocabulary.skills: task-oriented workflows that reference the other layers.
Authority
Resolve contradictions in this order:
- Executable contracts: checked types and schemas, tests, build output, and runtime behavior.
- Accepted ADRs under
docs/adr, with newer decisions superseding older decisions on the same subject. - Architecture documents in
ai/architecture. - Rules in
ai/rules. - Skills in
ai/skills.
Executable behavior is not permission to preserve an accidental bug. When a task intentionally changes a contract, update the executable contract, affected ADR or architecture, rules, and routes in the same change. Skills only orchestrate references and verification.
Normative terms follow RFC-style strength: MUST is required, SHOULD is the default and needs a documented concrete reason to deviate, and MAY is optional. Exceptions should be narrow, identify the affected boundary, and include verification.
Registry
ai/registry.json defines routed skills.
ai/registry.schema.json documents the registry shape and the sync script enforces the same structural constraints during npm run ai:check.
Each skill entry defines the canonical skill file, its reusable references, generated route paths, and tool-specific matching metadata. The ## Read First list in the canonical skill must match the registry references list exactly and in the same order.
Generated Routes
scripts/ai/sync-routes.mjs compiles each canonical skill and its references into tool routes:
- OpenCode:
.opencode/skills/<skill-name>/SKILL.md. - Codex:
.agents/skills/<skill-name>/SKILL.md. - Cursor:
.cursor/rules/<skill-name>.mdc. - GitHub Copilot:
.github/instructions/<skill-name>.instructions.md.
Generated routes must not be edited manually.
npm run ai:sync writes stale routes and removes orphan generated routes. npm run ai:check verifies registry shape, reference files, generated content, route collisions, Read First parity, and registered canonical skill files.
Reference: ai/glossary/cube-terms.md
Cube Terms
Cubie
A physical movable piece of the cube. The core engine tracks cubies rather than face colors as the primary model.
Corner
A cubie with three stickers. A 3x3 cube has eight corners.
Edge
A cubie with two stickers. A 3x3 cube has twelve edges.
Permutation
Which cubie occupies each position.
Orientation
How a cubie is twisted or flipped in its current position.
Move
A face turn such as R, U, R', or U2.
Scramble
A sequence of moves applied from the solved state to produce a valid cube state.
Heuristic
An estimate of distance from a cube state to the solved state.
Admissible Heuristic
A heuristic that never overestimates the true distance to the solved state.
Pattern Database
A precomputed lookup table mapping partial cube states to minimum solution distances.
Kociemba String
A facelet string format commonly used by two-phase solvers. It can be an adapter format, not the primary engine model.