Files
periscope/docs/development/CODING_CONSTITUTION.md
T
michele 0533d4ebd2 Add Periscope Cursor engineering constitution and always-on rules.
Docs-only: master CODING_CONSTITUTION plus seven .mdc splits. Git policy is
phase = test then commit+push; deploy only after a macro-phase.
2026-09-20 18:06:00 +02:00

6.9 KiB
Raw Blame History

Periscope Cursor Engineering Rules

Mandatory for every Cursor agent working on Periscope. Do not invent a weaker local policy. This file is the master; .cursor/rules/*.mdc split the same text by section and must not contradict it.

0. Coding constitution

  • You are implementing Periscope (schematic/PCB validation), not a generic scaffold and not Faradworks/PinScope under a new name.
  • Prefer original Periscope source in periscope/src over copying PinScope. Overlay stamps, cp of periscope/dependency/**, and near-identical pastes do not create architectural or AGPL independence.
  • Keep periscope/dependency/ until a rewritten slice is proven. Never empty-delete inherited files to “look native.”
  • Auto-place / pcbnew write-back is out of scope unless Michele explicitly asks.
  • Never touch live auth users, password hashes, or AUTH_JWT_SECRET unless Michele explicitly orders a credential change in that turn.
  • Never swallow exceptions with bare except: continue. Log or re-raise.
  • Match existing public contracts (Pydantic models, REST shapes, finding engine). Frontend types stay in sync with backend models.
  • AGPL-3.0 of the fork stays visible. Do not relicense. Do not detach the GitHub fork unless Michele and counsel say so.
  • Gateway-owned seams stay stub-shaped (billing_hook.get_billing(), frontend auth/billing pass-throughs). Do not import Clerk/Stripe SDKs outside those seams.
  • Skills stay local (skills/*/SKILL.md + validate.py on DeepSeek). Do not run scripts/upload_skills.py.
  • Default LLM path is DeepSeek. Do not route live stages to Anthropic Console.

1. Architecture

Three layers:

Layer Location Purpose
Core backend/periscopex/ (native under periscope/src when split) Models, parsers, graph, validator, passives, taxonomy, derating
Backend backend/ FastAPI, pipeline, SSE, storage
Frontend frontend/ Next.js app: dashboard, progress, report, derating, admin

Physical split (when present): periscope/src = Periscope; periscope/dependency = inherited PinScope in-tree. Docker copies dependency then src so native files win only when they are real replacements, not stamped copies.

Import switch rule: keep calling dependency/ until pytest + deploy smoke pass for that slice, then switch imports. Fail-soft: if verification fails, leave the inherited path.

Netlist is a queryable bipartite graph (components + nets). Deterministic checks beat heuristics. Finding normalization is downgrade-only. Cross-IC excerpt budget is global plus per-neighbor.

Content-addressed datasheets live under library/datasheets/. DigiKey matches exact MPN only. Value-string passives stay per-project, never the shared library.

Do not add auth, billing, or extra services unless the task needs them. Do not add a second frontend component library.

2. Python

  • Python 3.12+, Pydantic 2.x, FastAPI on the backend.
  • Parsers and graph builders are pure functions without hidden I/O, except documented loaders (build_graph from paths).
  • All shared data structures are Pydantic models in backend/periscopex/models.py (or the native successor once rewritten).
  • Tests live under tests/ against simple_project/ as ground truth. Emmaforo behavior is a live spec, not a license to skip unit tests.
  • Extraction prompts live in skills/ and run in-process. Bump default_model_version in skills_manifest.json when skill prompts change; never call Anthropic Console.
  • Use stdlib hashing (hashlib.scrypt in local_users.hash_password) for local passwords. Do not invent a homemade hash.
  • repo_paths.py locates taxonomy, skills, vendor, changelog. Do not hard-code /app without the Docker heuristic that also requires vendor/.
  • Format and lint with the repos existing tools. Do not drive-by reformat unrelated files.

3. Rust

  • Periscopes product code is Python/TypeScript today. If a Rust crate is added, it is original Periscope code, not a paste of an AGPL PinScope module.
  • Rust slices follow the same verify-then-switch rule: tests first, then wire into the Python/TS surface.
  • Use rustfmt + clippy on that crate. No unsafe without a comment that names the invariant.
  • Do not introduce Rust to dodge AGPL or to empty-delete Python in dependency/.

4. Testing

  • Write tests before considering a slice done. Prefer tests that lock behavior (graph topology, finding codes, via≠pad, review isolation) over tests that assert overlay stamps or file provenance comments.
  • pytest from the worktree with the project venv. Do not claim green from a system Python missing deps.
  • One malformed IC must not kill the whole review; keep per-IC isolation tests.
  • Do not add tests whose only job is to require Native Periscope overlay in a copied file.
  • UI changes: exercise the flow (not a single screenshot). If no browser tools, say what was not verified.
  • Installing docs/rules is a docs phase: existence and internal consistency of the seven .mdc files plus this master is the check. There is no product pytest gate for markdown-only.

5. Verification

  • Verify-then-switch: pytest (or the docs check above) then import/path switch, then commit+push at phase end.
  • Live smoke after a macro-phase deploy: version from changelog, health of /api/auth/mode, overlay/rewrite modules that should load, users untouched.
  • Deploy script: /root/periscope ./scripts/update-periscope.sh. Prefer --no-pull after the host checkout is already on the intended SHA. Do not let the script generate a new AUTH_JWT_SECRET if one exists.
  • Do not treat Docker COPY of src over dependency as proof of a rewrite.

6. Git workflow

Worktree for this product line: ~/Development/pinscope-tree-split unless Michele names another. Do not start a second clone to dodge the worktree.

Phase vs macro-phase

  • Phase (one verified slice: e.g. rules install, one rewritten module with tests): when tests (or the docs check) pass → commit and push. That is the end of the phase.
  • Macro-phase (a named batch of phases Michele treats as one shippable increment): deploy only after a macro-phase, not after every phase, and not at a mere phase boundary.
  • No commit, push, or deploy on every small edit. Edit, keep working, commit when the phase is actually done.
  • No deploy at a mere phase boundary. Passing tests + push is not a deploy order.

Other git rules

  • Feature branches cursor/<descriptive-name>-0d9d (lowercase). Do not force-push unless Michele explicitly orders it.
  • Do not create pull requests unless Michele asks.
  • Push origin and github when this worktree has both remotes.
  • Do not commit secrets, data/auth/users, or .env password material.
  • Changelog version is the latest ## x.y.z in frontend/content/changelog.md (dependency copy is the Docker source of truth today). Bump only when the phase is a product change, not for docs-only rules unless Michele wants a version bump.