Copy CODING_CONSTITUTION.md from the AgentStore docs/development path and split the seven always-on .mdc files from that exact text.
19 KiB
PERISCOPE — CURSOR ENGINEERING RULES
PURPOSE
This document defines the mandatory engineering rules for the Periscope project.
These rules are not suggestions.
They define:
- repository structure;
- coding standards;
- architectural principles;
- semantic modeling rules;
- Python/Rust language policy;
- testing requirements;
- verification requirements;
- Git workflow;
- commit/push/deployment policy;
- development-phase discipline.
Cursor must treat these rules as mandatory project constraints.
If an implementation conflicts with these rules, the implementation must be changed.
Do not silently relax, bypass, reinterpret, or ignore these rules.
1. CREATE THE PROJECT RULE STRUCTURE
Create and maintain the following structure:
.cursor/
└── rules/
├── 00-coding-constitution.mdc
├── 10-architecture.mdc
├── 20-python.mdc
├── 30-rust.mdc
├── 40-testing.mdc
├── 50-verification.mdc
└── 60-git-workflow.mdc
docs/
└── development/
└── CODING_CONSTITUTION.md
The Markdown document is the human-readable master document.
The .mdc files are the operational Cursor rules.
The rules must be version-controlled with the project.
Do not create contradictory rules in different files.
If a conflict exists, resolve the conflict explicitly before continuing development.
2. CORE PRINCIPLE
CODE THAT FITS IN YOUR HEAD
This is the fundamental Periscope engineering principle.
Code must be locally understandable by an engineer without requiring reconstruction of a large hidden abstraction system.
Prefer:
- small modules;
- small functions;
- one responsibility;
- explicit dependencies;
- explicit data flow;
- simple data structures;
- precise names;
- deterministic behavior;
- minimal public APIs;
- composition over inheritance.
Avoid:
- huge functions;
- god classes;
- deep inheritance;
- speculative abstractions;
- hidden state;
- magic behavior;
- global mutable state;
- unnecessary frameworks;
- premature optimization;
- unnecessary indirection.
A function around 40–60 lines is a warning signal, not an absolute limit.
The actual rule is local comprehensibility.
A 20-line function can violate the rule if it contains too many responsibilities.
A longer function may be acceptable if its structure remains obvious and justified.
3. ONE RESPONSIBILITY
Every function and module must have one primary responsibility.
Prefer:
parse
↓
normalize
↓
build model
↓
analyze
↓
produce finding
↓
report
Avoid a single function that:
- parses input;
- modifies the model;
- performs analysis;
- accesses external services;
- formats output;
- writes files;
- handles errors;
- and generates reports.
Separate responsibilities.
4. EXPLICIT DATA FLOW
Periscope must have explicit data flow.
Prefer:
SOURCE
↓
PARSER
↓
NORMALIZED MODEL
↓
ANALYZER
↓
FINDING
↓
REPORT
Avoid hidden communication through:
- global variables;
- singleton state;
- implicit registries;
- hidden caches;
- ambient configuration;
- side effects;
- undocumented environment state.
If a function needs important information, that information must be visible in its inputs or clearly owned state.
5. NO SPECULATIVE ABSTRACTION
Do not introduce an abstraction merely because it might become useful later.
Do not create unnecessary:
- factories;
- generic managers;
- service layers;
- repository layers;
- plugin systems;
- inheritance hierarchies;
- generic object wrappers;
- framework-like internal infrastructure.
Implement the actual requirement first.
Abstract only when there is a concrete and demonstrated reason.
6. COMPOSITION OVER INHERITANCE
Prefer composition.
Avoid deep class hierarchies.
Inheritance must have a clear semantic reason.
Do not use inheritance merely to share a few methods.
7. DETERMINISTIC CORE
The verification core must be deterministic.
For the same:
input
+
configuration
+
source data
Periscope must produce the same:
model
calculations
findings
Do not make deterministic verification dependent on:
- LLM output;
- prompts;
- randomness;
- execution order;
- hidden state;
- uncontrolled external state.
8. LLM ROLE
LLMs may be used for:
- extraction;
- classification;
- datasheet interpretation;
- explanation;
- hypothesis generation;
- assistance.
LLMs must not be the authoritative deterministic verification engine.
The intended architecture is:
SOURCE
↓
STRUCTURED REQUIREMENT
↓
DETERMINISTIC ANALYZER
↓
FINDING
↓
OPTIONAL LLM EXPLANATION
Not:
SOURCE
↓
LLM
↓
probably wrong
9. EVIDENCE BEFORE CONCLUSION
Every engineering conclusion must be traceable to evidence.
Where applicable, preserve:
observed fact
requirement
source
calculation
assumption
conclusion
confidence
severity
Do not silently transform assumptions into facts.
10. REQUIREMENT STRENGTH
Requirements must preserve their strength.
Use:
MANDATORY
RECOMMENDED
TYPICAL
EXAMPLE
ENGINEERING_INFERENCE
Do not convert:
RECOMMENDED
into:
MANDATORY
Do not convert an example into an absolute rule.
Do not convert an engineering inference into documented manufacturer information.
11. SEVERITY AND CONFIDENCE ARE INDEPENDENT
A finding must be able to represent independent:
severity
confidence
Examples that are valid:
ERROR + LOW confidence
RISK + HIGH confidence
Do not use confidence as a substitute for severity.
12. INSUFFICIENT EVIDENCE
If the available information is insufficient to establish a conclusion:
INSUFFICIENT_EVIDENCE
must be used.
Never invent missing engineering information.
Never invent:
- electrical limits;
- timing values;
- pin functions;
- voltages;
- currents;
- tolerances;
- PCB rules;
- thermal limits;
- datasheet requirements.
Missing evidence is not permission to guess.
13. SEMANTIC MODEL FIRST
Periscope must preserve domain semantics.
At minimum, distinguish concepts such as:
Project
Component
Pin
Footprint
Pad
Net
Via
Track
Zone
PowerRail
SignalGroup
TimingEvent
Requirement
Constraint
DesignIntent
Evidence
Finding
Do not collapse semantically different physical objects into one generic object merely because they share coordinates, nets, or attributes.
14. SEMANTIC IDENTITY MUST SURVIVE TRANSFORMATIONS
A transformation must preserve the semantic identity of objects.
For example:
PCB Via
must never become:
Component Pad
merely because:
- it is close to a footprint;
- it is inside a footprint area;
- it is connected to GND;
- it shares a net;
- it has coordinates similar to a pad.
Similarly:
Pad ≠ Via
Track ≠ Via
Zone ≠ Pad
Component Pin ≠ PCB Via
This is a fundamental Periscope rule.
15. ROOT CAUSE OVER SYMPTOM
When a false positive or incorrect result is discovered:
Do not simply suppress the finding.
Determine where the representation first becomes incorrect.
Example:
PCB
↓
parser
↓
incorrect model
↓
correct analyzer operating on incorrect model
↓
incorrect finding
The fix belongs in the model/parser boundary, not necessarily in the analyzer.
Always investigate the complete chain:
source
→ parser
→ normalized representation
→ semantic model
→ analyzer
→ finding
→ report
16. NO COMPONENT-SPECIFIC HACKS
Do not fix architecture problems with:
if component == U1
or:
if footprint == X
or:
if net == GND
or hard-coded corrections such as:
subtract N
ignore N
force expected count
unless the condition represents a genuine documented engineering rule.
A bug in generic PCB semantics must receive a generic semantic fix.
17. PHYSICAL SEMANTICS
Periscope is an electronic design verification system.
Its internal model must reflect physical reality.
Geometric proximity does not establish semantic identity.
For example:
Via located inside footprint
does not imply:
Via belongs to component as a pad
unless the PCB data model explicitly establishes that relationship.
Do not infer component relationships solely from proximity when stronger source information exists.
18. UNITS MUST BE EXPLICIT
Use explicit units.
Prefer:
width_mm
delay_ns
frequency_hz
voltage_v
current_a
temperature_c
over ambiguous variables such as:
width
delay
value
limit
when unit ambiguity is possible.
Never rely on undocumented implicit units.
19. NAMED CONSTANTS
Avoid magic numbers.
Prefer:
MIN_SUPPLY_V
MAX_TRACE_LENGTH_MM
DEFAULT_SPI_CLOCK_HZ
over unexplained numeric literals.
Engineering constants must have traceable sources where appropriate.
20. ERROR CATEGORIES
Distinguish:
tool failure
data failure
analysis result
insufficient evidence
engineering violation
Do not collapse fundamentally different failure modes into one generic error.
21. TESTING IS MANDATORY
Every meaningful implementation change requires tests.
At minimum test:
normal case
failure case
boundary case
insufficient evidence
For semantic models, also test the boundaries between object types.
For PCB analysis, explicitly test:
Pad
Via
Track
Zone
as distinct semantic entities.
22. TESTS MUST BE STRICT AND ABSOLUTE
Periscope tests are not advisory.
A test must define the exact expected behavior.
Do not use vague assertions such as:
result is reasonable
result is not empty
analysis completed
when an exact result can be established.
Prefer assertions such as:
expected object type == Via
expected pad count == 24
expected finding count == 0
expected finding code == X
expected severity == ERROR
expected confidence == HIGH
Where deterministic exact values are available, test them exactly.
Do not weaken tests merely to make an implementation pass.
Do not modify expected results to accommodate incorrect implementation behavior.
23. REGRESSION TEST FOR EVERY BUG
Every fixed bug must become a regression test.
Required sequence:
BUG
↓
REPRODUCE
↓
TEST FAILS
↓
FIX
↓
TEST PASSES
↓
FULL REGRESSION
A bug fix is not complete until the original failure is permanently represented by a test.
24. TEST THE NEGATIVE CASE
Do not test only:
valid → pass
Also test:
invalid → fail
and ensure that genuine errors remain detectable.
For example, if fixing:
24 datasheet pins
24 footprint pads
N vias
verify that:
24 datasheet pins
23 footprint pads
still produces a real mismatch.
The fix must remove false positives without suppressing true positives.
25. PHASE GATES
Development is divided into macro-phases.
A macro-phase is not complete until:
- implementation is complete;
- all required tests exist;
- all required tests pass;
- full regression passes;
- relevant integration tests pass;
- static/type/lint checks pass where applicable;
- no known blocker remains;
- documentation is updated;
- results have been reviewed;
- the phase acceptance criteria are satisfied.
Only then is the macro-phase considered complete.
26. NO WEAKENING TESTS TO CLOSE A PHASE
Do not:
- delete failing tests;
- weaken assertions;
- skip tests;
- mark tests expected-to-fail;
- suppress failures;
- change expected values without engineering justification;
simply to make a macro-phase pass.
If a test exposes a real implementation problem, fix the implementation.
If the requirement itself is wrong, change the requirement explicitly and document why.
27. PHASE COMMIT AND PUSH POLICY
Do not commit after every small implementation step merely for convenience.
During a phase:
implement
→ test
→ fix
→ test
The repository may contain intermediate working-tree changes.
At the end of each phase, after tests pass:
PHASE TESTS
↓
COMMIT
↓
PUSH
Commit and push belong to the phase boundary, not to every edit.
Do not push broken or half-completed phase work merely to synchronize the repository.
28. MACRO-PHASE DEPLOY POLICY
Deploy happens only after a macro-phase, not after every phase.
A macro-phase may contain several phases (each already committed and pushed after its tests).
Never deploy an incomplete macro-phase.
Required sequence for a macro-phase:
PHASES (each: implement → test → commit → push)
↓
FULL REGRESSION
↓
MACRO-PHASE ACCEPTANCE
↓
DEPLOY
↓
POST-DEPLOY VERIFICATION
If deployment verification fails, stop and investigate.
29. NO DEPLOY AT PHASE BOUNDARY
Commit + push after phase tests: yes.
Deploy after a phase that is not a completed macro-phase: no.
30. NO AUTOMATIC COMMIT/PUSH/DEPLOY DURING DEVELOPMENT
Cursor must not create commits, push, or deploy merely because a small task has finished.
Commit and push are phase-boundary operations (after tests).
Deploy is a macro-phase-boundary operation.
If explicitly instructed to deploy before a macro-phase is complete, Cursor must identify the conflict with this policy rather than silently proceeding.
31. GIT HISTORY IS ENGINEERING EVIDENCE
Do not rewrite Git history casually.
Do not:
- force-push;
- squash history;
- rewrite commits;
- detach repository history;
unless explicitly required by the project phase and explicitly authorized.
Git history may be relevant to provenance and licensing analysis.
Preserve it.
32. PYTHON IS THE DEFAULT LANGUAGE
Python is the default implementation language for Periscope.
Use Python for:
- orchestration;
- datasheet processing;
- document parsing;
- LLM integration;
- requirement extraction;
- evidence management;
- project management;
- CLI;
- API integration;
- reporting;
- test orchestration;
- external tool integration;
- high-level analysis.
Do not rewrite Python into Rust merely because Rust exists in the project.
33. RUST IS NOT A DEFAULT
Rust must not be introduced simply because code is new.
Rust is justified only when there is a demonstrated engineering requirement.
Valid reasons include:
- measured performance bottleneck;
- computationally intensive geometry;
- large-scale spatial processing;
- numerical computation;
- graph processing;
- memory pressure;
- deterministic high-performance computation.
Do not use Rust speculatively.
34. MEASURE BEFORE MOVING TO RUST
Required sequence:
correct implementation
↓
measurement
↓
profiling
↓
identified bottleneck
↓
Rust implementation
↓
benchmark
↓
accept/reject based on evidence
Do not introduce Rust based on assumptions about performance.
35. RUST BOUNDARIES MUST BE COARSE-GRAINED
Prefer:
Python
↓
structured input
↓
Rust engine
↓
structured result
↓
Python
Avoid excessive Python ↔ Rust calls for individual operations.
Rust should encapsulate meaningful computational workloads.
36. DO NOT PREMATURELY FREEZE THE CORE IN RUST
The semantic model should first become correct and well understood.
Prefer:
semantic model
↓
correctness
↓
tests
↓
architecture stabilization
↓
profiling
↓
Rust where justified
Do not rewrite the entire Periscope core in Rust simply to establish a Rust architecture.
37. CORRECTNESS BEFORE PERFORMANCE
Priority order:
1. Correctness
2. Semantic integrity
3. Determinism
4. Testability
5. Readability
6. Maintainability
7. Performance
8. Optimization
Performance optimization must not compromise the first six without explicit justification.
38. MINIMAL PUBLIC APIs
Public APIs must be as small as practical.
Do not expose internal implementation details unnecessarily.
Prefer explicit interfaces.
Avoid API surface growth without a real requirement.
39. NO DEAD CODE
Remove or explicitly document:
- obsolete code;
- commented-out implementations;
- unused imports;
- unused abstractions;
- obsolete APIs;
- temporary workarounds.
Temporary adapters must be clearly identified and have a removal path.
40. COMMENTS
Comments should explain:
WHY
rather than simply:
WHAT
Do not comment obvious code.
Do document:
- non-obvious engineering decisions;
- semantic constraints;
- source-specific behavior;
- intentional limitations;
- reasons for unusual algorithms;
- compatibility constraints.
41. CHANGE MINIMIZATION
For bug fixes:
- reproduce the problem;
- locate root cause;
- change the smallest appropriate architectural layer;
- add regression test;
- run relevant tests;
- run full regression;
- review the resulting design.
Do not combine unrelated refactoring with a bug fix unless necessary.
42. NO SPECULATIVE ENGINEERING
Do not invent engineering rules.
Every rule should be based on one of:
documented requirement
datasheet/source evidence
standard
explicit design intent
validated engineering inference
If evidence is insufficient:
INSUFFICIENT_EVIDENCE
43. DESIGN INTENT IS FIRST-CLASS
Do not assume that every unusual design decision is an error.
Periscope must be able to represent:
INTENTIONAL_DESIGN
when the evidence supports that interpretation.
The system must distinguish:
actual violation
intentional design
engineering observation
insufficient evidence
44. FINDING CATEGORIES
Findings may include:
ERROR
RISK
REFERENCE_DEVIATION
ENGINEERING_OBSERVATION
INTENTIONAL_DESIGN
INSUFFICIENT_EVIDENCE
Do not collapse all deviations into ERROR.
Severity and confidence remain independent.
45. REVIEW QUESTIONS BEFORE COMPLETING ANY CHANGE
Before declaring a change complete, Cursor must verify:
Is the implementation correct?
Is the root cause fixed?
Is the semantic model correct?
Is the data flow explicit?
Can the code fit in my head?
Is any abstraction unnecessary?
Is there hidden state?
Are units explicit?
Are engineering constants named?
Are assumptions distinguished from facts?
Are tests strict?
Are negative cases tested?
Are boundary cases tested?
Is insufficient evidence tested?
Could this change create a false positive?
Could this change suppress a true positive?
Is the full regression passing?
Is documentation updated?
Is the macro-phase actually complete?
46. FINAL ENGINEERING PRINCIPLE
Periscope must not become a clever software system.
It must become a:
CORRECT
DETERMINISTIC
SEMANTICALLY ACCURATE
TESTABLE
TRACEABLE
READABLE
MAINTAINABLE
ENGINEERING SYSTEM
The preferred implementation is the simplest one that satisfies those properties.
When two implementations are technically correct, prefer the one with:
- fewer abstractions;
- fewer dependencies;
- less hidden state;
- clearer data flow;
- smaller modules;
- smaller APIs;
- easier testing;
- easier debugging;
- clearer semantics.
The governing principle is:
CODE THAT FITS IN YOUR HEAD.
And the governing development discipline is:
NO PHASE IS COMPLETE UNTIL ITS TESTS PROVE IT.
And the governing repository discipline is:
COMMIT AND PUSH AT THE PHASE BOUNDARY AFTER TESTS; DEPLOY ONLY AFTER A MACRO-PHASE.