Skip to content

Latest commit

 

History

History
168 lines (140 loc) · 15.5 KB

AGENTS.md

File metadata and controls

168 lines (140 loc) · 15.5 KB

Repository Guidelines

Project Structure & Module Organization

src/main.rs defines the CLI entrypoint and Clap command tree. Command implementations live in src/commands/; larger generators use submodules such as src/commands/generate_constraint/ and src/commands/generate_domain/. Shared support code sits in src/app_spec.rs, src/countable_range.rs, src/error.rs, src/list_variable_metadata.rs, src/managed_block.rs, src/model_contract.rs, src/model_id.rs, src/output.rs, src/rc.rs, src/scaffold_target.rs, src/scalar_variable_hooks.rs, src/solver_config.rs, and src/template.rs. Integration tests live in tests/; their reusable generated-app harness lives in tests/support/, browser scenarios live in tests/e2e/, and scaffold/template assets live in templates/. The portable agent skill lives in skills/ and is installed by scripts/install-skill; csemver.toml configures csemver for releases.

Current Product Direction

solverforge-cli is the default entry point for new SolverForge applications. Treat the CLI as its own versioned product, distinct from the runtime crates and UI assets that generated projects target.

Current scaffold policy:

  • current CLI package version is 3.6.0
  • minimum supported Rust version is 1.95, matching the current SolverForge runtime crates
  • generated projects currently target solverforge 0.22.0; the default web shell additionally targets solverforge-ui 0.9.0 and solverforge-maps 2.1.4; the MCP shell additionally targets rmcp 3.5.1
  • solverforge new <name> is the only public scaffold path and produces a neutral app shell
  • --shell web|api|cli|mcp is the current public shell selector; web is the default, api omits frontend assets, cli omits Axum/SSE routes and frontend assets, and mcp delivers the solver as an MCP server over stdio and stateless Streamable HTTP
  • API/CLI/MCP app specs omit ui_source, and subsequent CLI mutations must preserve that absence
  • the MCP shell keeps the shared core (domain/, constraints/, solver/, data/, DTOs) and adds src/mcp/; solve is task-backed with retained jobId metadata for task-capable clients, tasks have no TTL and remain for the server process lifetime, failed/cancelled solves map to corresponding MCP task states, stdio is the default transport, concrete --host IPs preserve rmcp Host validation but the HTTP transport is unauthenticated with a single shared solver/task store so a non-loopback bind is a documented trusted-network-only limitation, and the runtime console feature stays off so the banner never corrupts the stdio channel
  • solverforge connect prints MCP client configuration and writes in-project config for the harness target (--write opencode|claude|cursor|vscode; each merges instead of clobbering)
  • Tauri scaffolding is deferred; do not document or implement a public Tauri shell unless that work is explicitly reopened
  • users shape the app afterward through facts, entities, solution/score metadata, variables, constraints, and generated data
  • generated docs and CLI version output must distinguish CLI version from scaffold runtime/UI target
  • scalar and list are the only planning variable kinds accepted by the public CLI and app-spec projection
  • scalar variables accept either a fact-collection range or a validated non-negative half-open countable range and expose current candidate/nearby/construction hook metadata; list variables expose current domain, distance, route/savings, ownership, construction-order, precedence, and solution-trait metadata
  • ordered sequences and routes use list variables; do not model sequence topology as a scalar predecessor field
  • standard is a demo size label only; do not reintroduce it as a variable kind or scaffold family
  • templates/scalar/generic is the embedded neutral scaffold used by solverforge new; templates/list/generic is not a public new selector
  • generated Cargo.toml files must carry rust-version = "1.95" plus the current explicit dependency baselines for the selected shell from the template/materialization code
  • the repository ships portable agent skills at skills/solverforge-modeling/ and skills/solverforge-ui/ with an agent-centric installer at scripts/install-skill; keep their documented shell set, scaffold targets, and command surface aligned with the live CLI

When changing templates or scaffold behavior, follow the current repo reality over older starter-template assumptions. Do not add legacy aliases, compatibility shims, migration fallbacks, or automatic rewrites for unmanaged pre-refactor file shapes unless that is explicitly requested.

Build, Test, and Development Commands

  • cargo build: compile the solverforge binary.
  • cargo run -- --help: run the CLI locally and inspect commands.
  • cargo test: run Rust unit tests, scaffold contract tests, and generated-app runtime pipeline tests.
  • cargo test --test runtime_pipeline_test -- --nocapture --test-threads=1: run the phase-marked runtime pipeline suite directly.
  • cargo test --test runtime_mcp_pipeline_test -- --nocapture --test-threads=1: run the MCP-shell runtime pipeline suite directly.
  • make test-runtime: run only the generated-app runtime pipeline tests.
  • make install-e2e: install Playwright Chromium locally.
  • make test-e2e: run Playwright browser tests against ephemeral generated apps.
  • make test-full: run binary/unit tests, installer and skill-integrity tests, scaffold contract tests, runtime pipeline tests, and Playwright tests in order.
  • make test-support: run only the installer behavior and skill reference-integrity tests.
  • cargo fmt --all: apply Rust formatting.
  • cargo clippy --all-targets -- -D warnings: enforce lint-clean code.
  • pre-commit run --all-files: run the repository hooks, including YAML checks, gitleaks, fmt, and clippy.
  • ./scripts/install-skill --agent <harness> (or make install-skill ARGS='--agent <harness>'): install the bundled agent skills into the selected harness's own skills directory.

Coding Style & Naming Conventions

Use standard Rust style with 4-space indentation and rustfmt output as the source of truth. Prefer snake_case for modules, files, functions, and test names; use PascalCase for types and enums. Keep CLI flags, generated file names, and module names descriptive and consistent with existing commands such as generate_constraint and sf_config.

Testing Guidelines

Add narrow unit tests close to the code in sibling test files or #[cfg(test)] child modules when validating parsing, rewriting, or template helpers. Put end-to-end CLI behavior in tests/, following existing names like *_test.rs and test_* functions. When changing scaffolding or generated code, cover both file creation and key output content assertions.

Prefer a small number of readable, high-signal end-to-end phases over a large number of narrow tests. The main generated-app suites are:

  • tests/scaffold_test.rs: scaffold contract and generated cargo check
  • tests/runtime_pipeline_test.rs: phase-marked generated-app runtime pipelines
  • tests/runtime_mcp_pipeline_test.rs: phase-marked MCP-shell pipelines driven by the real rmcp client
  • tests/e2e/*.spec.js: Playwright browser pipelines against ephemeral generated apps

Both runtime and browser suites must:

  • scaffold fresh temp apps through the real CLI
  • mutate them through the real CLI
  • boot generated servers on random ports
  • preserve failure artifacts under target/test-artifacts/
  • keep phase boundaries explicit in code and logs

Current end-to-end scenario policy:

  • neutral shell is covered as a bootable empty app
  • mixed is covered as a seeded generated solve in both runtime and browser scenarios, with required scalar assignment and complete list placement
  • the scalar-only scenario covers the full pause/resume/cancel/delete lifecycle
  • the scalar-only runtime scenario covers full compact telemetry, bounded candidate detail, and qualified trace provenance
  • the MCP scenario models a mixed scalar-plus-list problem, generates the sample data, and drives both stdio and stateless Streamable HTTP through the real rmcp client: annotated tool surface, task-backed solve to a terminal snapshot with scalar assignment and complete list placement, retained lifecycle via a legacy client, and byte-level stdio stdout purity during a solve

SolverForge 0.22.0 uses list variables as the sequence and route model. The generated-app runtime and browser scenarios must continue to start and observe a real mixed scalar/list solve.

For scaffold changes, prefer assertions that check the generated contract directly:

  • dependency wiring for the selected shell: solverforge everywhere, solverforge-ui and solverforge-maps only for web-shell projects, rmcp only for the mcp shell, and the optional schemars/schema feature enabled only for the mcp shell
  • CLI version vs runtime target messaging
  • generated README version/runtime source disclosure
  • typed solver SSE payload shape and typed frontend hooks
  • full compact SolverTelemetry projection plus the separate retained candidate-trace diagnostics route and qualified-run entry point
  • solverforge generate data ownership boundaries: src/data/mod.rs is the stable wrapper and src/data/data_seed.rs is compiler-owned generated sample data
  • managed block ownership boundaries: domain exports, solution collections, entity variables, constraint modules, and constraint calls require their @solverforge:begin ... / @solverforge:end ... markers
  • solverforge.app.toml projection: facts, entities, scalar/list variable metadata, constraints, demo sizes, solution/score metadata, runtime target metadata, and web-shell static/generated/ui-model.json
  • scaffolded cargo check must preserve generated registry declarations; before a coordinated target is published, sibling-checkout validation must be explicit via SF_USE_LOCAL_PATCHES=1, which writes a temporary .cargo/config.toml patch file without rewriting generated Cargo.toml; repeat the registry-only gate after publication

Commit & Pull Request Guidelines

Follow the commit style already used in history: fix: ..., refactor: ..., style: ..., chore: .... Keep commits scoped to one behavior change. PRs should explain user-visible CLI impact, list verification commands run, and link the relevant issue. Include concrete examples when flags, generated files, or template output change.

Releases

Releases are cut with csemver, configured by the checked-in csemver.toml. Never hand-edit CHANGELOG.md or a version surface the config owns (Cargo.toml, Cargo.lock, package.json, package-lock.json) or the prose version lines in README.md, AGENTS.md, WIREFRAME.md, and skills/solverforge-modeling/SKILL.md. Run csemver --release-as vX.Y.Z (or let conventional commits pick the bump) instead of bumping by hand; the tool owns the release commit, the tag, and the changelog.

Security & Configuration Tips

Do not commit generated projects, secrets, or credentials. The pre-commit config runs gitleaks; keep it enabled. When tests or generated scaffolds touch published SolverForge crate versions, verify Cargo.toml template changes and corresponding integration tests together.

Agent Skill Package

skills/solverforge-modeling/ is a portable Agent Skill (SKILL.md plus references/ and scripts/) that teaches an agent to model planning problems with this CLI. Keep it aligned with the live CLI surface:

  • SKILL.md frontmatter name/description drive discovery; keep the shell set, scaffold targets, and command surface documented in the body current.
  • scripts/install-skill copies the skill into each selected harness's own skills directory (opencode, Claude Code, the cross-harness Agent Skills standard), at user or project scope. It never symlinks or shares a location, and it writes a .solverforge-skill marker into each installed copy so --list and --uninstall never touch an entry it did not install.
  • skills/solverforge-modeling/scripts/solve-smoke-test.sh verifies a generated app per shell (MCP covers transport health only; protocol proof lives in runtime_mcp_pipeline_test); update it when a shell's runtime surface changes.
  • make install-skill ARGS='--agent <harness>' wraps the installer.

Keep SKILL.md harness-agnostic; do not encode assumptions about one client.

Scaffold Contract Notes

Generated apps should behave like production references, not toy demos.

Keep these rules aligned across the single neutral scaffold and all generated domain shapes that users create afterward:

  • backend services track best solution separately from live status telemetry
  • compact status/snapshot/SSE telemetry projects every current SolverTelemetry aggregate and phase/selector/move/applied-move breakdown
  • bounded candidate pulls are retained separately and exposed only through /jobs/{id}/telemetry; do not copy them into ordinary lifecycle traffic
  • qualified candidate-trace jobs use additive /jobs/qualified input with all five externally attested SHA-256 digests and a non-empty producer
  • status endpoints return currentScore, bestScore, solver status, and latest snapshot revision
  • SSE payloads carry typed lifecycle metadata including eventType, eventSequence, lifecycleState, and snapshotRevision
  • retained lifecycle events include progress, best_solution, pause_requested, paused, resumed, completed, cancelled, and failed
  • frontends use lifecycle-aware hooks including onProgress(meta), onSolution(snapshot, meta), onPaused(snapshot, meta), onResumed(meta), onCancelled(snapshot, meta), onComplete(snapshot, meta), and onFailure(message, meta, snapshot, analysis)
  • snapshot-bound analysis and retained /jobs/{id}/snapshot flows stay aligned with the shared UI backend contract
  • reconnect bootstrap is derived from SolverManager status plus the latest retained snapshot revision; do not cache or replay last SSE text locally
  • Pause resumes from the runtime-retained checkpoint, Stop maps to /jobs/{id}/cancel, and Delete is terminal cleanup only
  • progress-only events update status, not the rendered board
  • generated demo data flows expose /demo-data as the catalog and /demo-data/{id} for selected data; frontends derive the default ID from the catalog and must not hard-code /demo-data/STANDARD
  • generated web-shell UI composition should use shipped solverforge-ui primitives before adding template-owned JavaScript
  • src/data/data_seed.rs and web-shell static/generated/ui-model.json are compiler-owned; user-facing seams are the solverforge generate data command, stable src/data/mod.rs wrapper, and web-shell static/sf-config.json
  • generated domain and constraint mutation is canonical-only: current managed block shapes are required, not inferred from old layouts

Do not reintroduce:

  • raw top-level score-only progress payloads
  • starter-specific solve/render lifecycles
  • docs that blur CLI version with runtime/UI target
  • standard as a planning variable kind
  • scalar predecessor topology; ordered sequences belong to list variables
  • hidden scaffold/template aliases
  • shell selectors beyond the canonical web, api, cli, and mcp
  • Tauri or other shell aliases before a real scaffold implementation exists
  • fallback migration code for legacy generated files

Test harness notes:

  • ephemeral generated apps should be the default validation path; do not rely on manually scaffolded directories for routine testing
  • runtime/browser failures should leave actionable logs and artifacts under target/test-artifacts/
  • phase output should remain human-readable and ordered, even when tests grow