| name | project-core |
| description | Always-on repository baseline for boundaries, precedence, verification, and AI knowledge maintenance. |
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.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
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:check after AI knowledge changes.
- Run
cargo test -p cube-engine after 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.md and 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, and cargo test so paths and workspaces resolve consistently.
- Before any task that changes files, create or switch to a dedicated branch; never work directly on
main for 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 warnings from the repository root when the Rust toolchain is available.
- Keep AI route files generated from canonical files under
ai.
- Use
npm run dev for the default Docker development runtime, live:deploy for production Docker deploys after main changes, live:restart only when the checkout is already current, and live:start when 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
.env files, 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/instructions AI 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 restart or start an old production container to deploy code changes; production code changes require a Docker rebuild through live:deploy, live:restart, prod:deploy, prod:restart, or the lower-level docker:up wrapper.
Runtime Scripts
dev, dev:start, dev:restart, dev:stop, dev:status, dev:logs, and dev:health: default Docker development runtime on ports 5173, 8788, and 8791.
dev:local:prepare, dev:local, dev:local:status, and dev:local:stop: non-Docker fallback runtime for development/debugging on ports 5173, 8788, and 8791.
live:deploy: preferred production update command after PRs merge; switches to main, pulls origin/main, rebuilds/recreates Docker production, waits for http://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, and live:stop: production health/status/log/stop helpers.
live:start: deploys production with live:deploy, then starts cloudflared tunnel run --token "$CLOUDFLARED_TUNNEL_TOKEN" for speedcube.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, and docker:logs: lower-level rubiks-prod Compose wrappers; prefer live:* unless you specifically need raw Compose behavior.
docker:dev and docker:dev:down: compatibility wrappers for Docker dev; prefer dev:*.
docker:train and docker: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 test first, then cargo test -p cube-engine or cargo test when Rust is installed.
- API changes:
npm run api:test or the relevant cargo test -p rubiks-cube-solver-api target.
- Web changes:
npm run build and npm run lint -w @rubiks-cube-solver/web when 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 warnings before 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/api behavior 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, and vi.spyOn for web unit and component tests.
- Keep
web tests 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 under apps/web/src/test.
- Keep
apps/web/src/core tests under apps/web/src/core/<category>/__tests__/<name>.test.ts.
- Keep global
web coverage 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
.only in 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.mock patterns in Vitest tests.
- Do not place
web tests 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.tsx or apps/web/src/test/api.ts already covers the setup.
- Do not use Playwright
selectOption() or locator('option') for Radix Select controls; use helpers under tests/e2e/select-helpers.ts.
Verification
- Cube engine tests:
cargo test -p cube-engine.
- API tests:
npm run api:test or cargo test -p rubiks-cube-solver-api.
- Workspace tests:
cargo test.
- Web build/lint:
npm run build and npm 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:e2e after the API, web app, and pruning-table prerequisites are available.
- E2E split commands:
npm run test:e2e:smoke for product/responsive/timer smoke, npm run test:e2e:scan for serial manual scan coverage, and npm run test:e2e:full for the complete non-heavy suite.
- Product gate:
npm run product:gate for 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
ai as the source of truth for AI guidance.
- Keep reusable knowledge in
rules, architecture, and glossary.
- Keep
skills task-oriented: each skill should orchestrate references instead of duplicating them.
- Add every routed skill to
ai/registry.json.
- Use
references in ai/registry.json for every rule, architecture, or glossary file a skill depends on.
- Keep each skill's
## Read First list identical to its registry.json references list.
- 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:sync after changing canonical skills, registry entries, or referenced knowledge files.
- Run
npm run ai:check before 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: true outside the explicitly global project-core skill.
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-engine binaries and loaded by crates/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 dev to build/recreate the rubiks-dev Compose project, wait for health, and serve web/API/vision on ports 5173, 8788, and 8791.
- Local non-Docker fallback uses
dev:local:prepare and dev:local for development/debugging when Docker is not desired.
- Docker production uses the
rubiks-prod Compose project. Use live:deploy after merges to pull origin/main, rebuild/recreate containers, wait for app health, and print status.
- Use
live:restart only when the checkout is already current and containers need to be rebuilt/recreated.
live:start runs production deploy first and then starts the Cloudflare tunnel for speedcube.com.br with cloudflared tunnel run --token "$CLOUDFLARED_TUNNEL_TOKEN". live:tunnel runs 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/v1 contract belong to apps/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.