Files
periscope/docs/development/CODING_CONSTITUTION.md
T
michele 2f2e35e802 Replace paraphrased constitution with the 1224-line master.
Copy CODING_CONSTITUTION.md from the AgentStore docs/development path and split
the seven always-on .mdc files from that exact text.
2026-09-20 18:24:29 +02:00

1225 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:
```text
.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 4060 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:
```text
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:
```text
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:
```text
input
+
configuration
+
source data
```
Periscope must produce the same:
```text
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:
```text
SOURCE
STRUCTURED REQUIREMENT
DETERMINISTIC ANALYZER
FINDING
OPTIONAL LLM EXPLANATION
```
Not:
```text
SOURCE
LLM
probably wrong
```
---
# 9. EVIDENCE BEFORE CONCLUSION
Every engineering conclusion must be traceable to evidence.
Where applicable, preserve:
```text
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:
```text
MANDATORY
RECOMMENDED
TYPICAL
EXAMPLE
ENGINEERING_INFERENCE
```
Do not convert:
```text
RECOMMENDED
```
into:
```text
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:
```text
severity
confidence
```
Examples that are valid:
```text
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:
```text
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:
```text
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:
```text
PCB Via
```
must never become:
```text
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:
```text
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:
```text
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:
```text
source
→ parser
→ normalized representation
→ semantic model
→ analyzer
→ finding
→ report
```
---
# 16. NO COMPONENT-SPECIFIC HACKS
Do not fix architecture problems with:
```text
if component == U1
```
or:
```text
if footprint == X
```
or:
```text
if net == GND
```
or hard-coded corrections such as:
```text
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:
```text
Via located inside footprint
```
does not imply:
```text
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:
```text
width_mm
delay_ns
frequency_hz
voltage_v
current_a
temperature_c
```
over ambiguous variables such as:
```text
width
delay
value
limit
```
when unit ambiguity is possible.
Never rely on undocumented implicit units.
---
# 19. NAMED CONSTANTS
Avoid magic numbers.
Prefer:
```text
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:
```text
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:
```text
normal case
failure case
boundary case
insufficient evidence
```
For semantic models, also test the boundaries between object types.
For PCB analysis, explicitly test:
```text
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:
```text
result is reasonable
result is not empty
analysis completed
```
when an exact result can be established.
Prefer assertions such as:
```text
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:
```text
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:
```text
valid → pass
```
Also test:
```text
invalid → fail
```
and ensure that genuine errors remain detectable.
For example, if fixing:
```text
24 datasheet pins
24 footprint pads
N vias
```
verify that:
```text
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:
1. implementation is complete;
2. all required tests exist;
3. all required tests pass;
4. full regression passes;
5. relevant integration tests pass;
6. static/type/lint checks pass where applicable;
7. no known blocker remains;
8. documentation is updated;
9. results have been reviewed;
10. 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**:
```text
implement
→ test
→ fix
→ test
```
The repository may contain intermediate working-tree changes.
At the **end of each phase**, after tests pass:
```text
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:
```text
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:
```text
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:
```text
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:
```text
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:
```text
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:
```text
WHY
```
rather than simply:
```text
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:
1. reproduce the problem;
2. locate root cause;
3. change the smallest appropriate architectural layer;
4. add regression test;
5. run relevant tests;
6. run full regression;
7. 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:
```text
documented requirement
datasheet/source evidence
standard
explicit design intent
validated engineering inference
```
If evidence is insufficient:
```text
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:
```text
INTENTIONAL_DESIGN
```
when the evidence supports that interpretation.
The system must distinguish:
```text
actual violation
intentional design
engineering observation
insufficient evidence
```
---
# 44. FINDING CATEGORIES
Findings may include:
```text
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:
```text
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:
```text
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.**