michele 6b751522b7 Keep rust-criteri and conformita-coding in the local docs tree.
Absolute paths in the headings so the files open from
~/Development/periscope/docs. PCB 2.62.1 check list unchanged.
2026-09-21 22:40:12 +02:00
2026-07-16 21:29:45 -07:00

Periscope

Periscope is full PCB analysis for a board you intend to send to fab with confidence. Schematic review is a stage, not the deliverable.

Give it a netlist, a BOM, datasheet PDFs, and a KiCad PCB. It builds a queryable graph of the design, extracts manufacturer constraints once into a shared library, then checks both the circuit and the copper: pads, tracks, vias, zones, measured geometry, and the interfaces that are actually on this board.

Live instance: https://periscope.michelebigi.it

This tree is the Periscope product (operator: Michele Bigi). It is derived from Faradworks/Pinscope; Faradworks does not operate this instance.

What it checks — and what it will not invent

USB pair impedance, Ethernet class, and trace current versus width are examples of gated checks. They run when that bus, connector, or datasheet number exists on the board. They are not a catalog of every interface in electronics.

Semantic objects stay distinct. A via is not a pad. A track is not a via. A zone is not a pad. Sharing a net, sitting inside a courtyard, or having nearby coordinates does not change the object type.

Evidence before conclusion. If the datasheet, netlist, BOM, or .kicad_pcb does not supply the number, Periscope records INSUFFICIENT (or skips the check). It does not invent current, impedance, copper weight, geometry, IEC creepage, or “typical USB 500 mA”.

Trace current uses datasheet current only. Width versus load (PE-PWR) runs when the datasheet reports I_load / Imax / I_abs. Missing that current is a skip — not a guessed ampacity table, not via-IPC folklore.

Interface class certifiers are gated on parts that are present. USB-C, RJ45/Ethernet, PoE, and DDR-style certifiers fire only if that connector or device is on the graph. No USB-C receptacle → no USB-C findings (silence, not N/A). A bare RJ45 is Ethernet, not PoE. No DDR device → no DDR findings.

Periscope does not claim FEM, thermal spreading, OpenEMS, or a field solver. Closed-form Z0 comes from vendored ImpedenceFinder (vendor/impedancefinder/; upstream license UNKNOWN).

Findings keep FACT, REQUIREMENT, and INFERENCE apart. Recommended datasheet notes are not errors. The same finding object is used for schematic (MODE=run) and PCB (MODE=pcb).

Repository layout

Path Role
periscope/src/ Native Periscope (finding engine, PCB/placement, DeepSeek, Dockerfiles, KiCad plugin)
periscope/dependency/ Inherited PinScope (in-tree AGPL dependency — do not delete)
backend/__init__.py Merges the two backend packages for local imports
scripts/ update-periscope.sh, materialize-frontend.sh, smoke wrapper
vendor/impedancefinder/ Third-party Z0 core (not FEM)
LICENSE GNU AGPL v3

See periscope/README.md for the physical split.

Run locally

Python 3.12+, Node 20+, and a DeepSeek API key for live extraction and review. Offline graph/smoke does not need the key.

python3 -m venv .venv
source .venv/bin/activate
pip install -r periscope/src/backend/requirements.txt
cp periscope/src/backend/.env.example .env   # set DEEPSEEK_API_KEY

python3 -m uvicorn backend.main:app --reload --host 127.0.0.1 --port 18741

Frontend — overlay native UI onto the inherited shell, then start Next.js (this is what CI runs):

./scripts/materialize-frontend.sh
cd .merge/frontend && npm install
NEXT_PUBLIC_API_URL=http://127.0.0.1:18741 npm run dev -- --port 18742 --hostname 127.0.0.1

Open the frontend URL, create a project, and upload a netlist plus BOM. A .kicad_pcb is required for the PCB job; without it the project can complete schematic review only. periscope/dependency/simple_project/ is a small bundled schematic fixture (MSPM0G3507 + CH340E + SPX3819).

Projects and the extraction library live in data/ (gitignored). Extraction skills are local periscope/src/skills/*/SKILL.md. Do not run an Anthropic Console uploader.

Tests from the repo root:

pip install pytest pytest-asyncio
pytest tests/ -q
python3 scripts/smoke_simple_project.py          # offline

Docker

cp periscope/src/backend/.env.example .env   # set DEEPSEEK_API_KEY
docker compose up --build

Backend listens on port 8080, frontend on port 3000 (docker-compose.yml).

Live host

The public site is rebuilt from /root/periscope with the script that actually ships:

cd /root/periscope
./scripts/update-periscope.sh

--no-pull skips git. SITE=https://other.host ./scripts/update-periscope.sh overrides the public URL. The script refuses to run unless the checkout is /root/periscope (override with CANONICAL_ROOT only if the host layout differs). It does not touch data/.

Source

Remote URL
GitHub https://github.com/manvalan/pinscope (git@github.com:manvalan/pinscope.git)
Gitea http://192.168.1.71:3000/michele/periscope.git

Push both: git push github && git push gitea (no force).

License

AGPL-3.0 — GNU Affero General Public License v3.0.

This tree is derived from Faradworks/Pinscope. For a commercial license of upstream Pinscope, contact Faradworks as they publish it. For this Periscope instance, contact Michele Bigi (mikbigi@gmail.com).

S
Description
No description provided
Readme AGPL-3.0
9.4 MiB
Languages
Python 71.2%
TypeScript 28.3%
CSS 0.2%
Shell 0.2%
JavaScript 0.1%