| Upstream `main` | `upstream/main` = `b26ad3509f4a19878fb7050aad3da9eacba8d914` (fetched locally for comparison only; **GitHub remotes of the fork were not changed**) |
| Merge-base (all three tips) | `b26ad35` — upstream HEAD *is* the fork point |
| This document | `docs/development/PINSCOPE_AUDIT.md` (only file this phase is allowed to add) |
---
## 1. Executive summary
Periscope is a **live GitHub fork** of Faradworks/Pinscope (AGPL-3.0). Upstream has **five** commits and has not moved since 2026-07-17. GitHub `main` on the fork is only **three** commits ahead (Docker / OSS / README). The **product** (DeepSeek, rebrand, PCB exam, finding engine, v2.32.1) lives on `cursor/pcb-review-plan-44dd`: **92** commits ahead of upstream, **89** ahead of `origin/main`, **not merged** to the default branch. GitHub lists **no pull requests**.
On the product snapshot (`facbaa2`, 404 files, 123544 text lines):
**PinScope-lineage share (UPSTREAM + DERIVED + REPLACEMENT):** 63.4% of files, 79.4% of lines.
**New / vendored share (NEW + THIRD_PARTY):** 36.6% of files, 20.7% of lines.
Architectural independence is **not** blocked by leftover strings. It **is** blocked by: (1) the still-PinScope pipeline (`periscopex` ← `pinscopex`: graph, parsers, `validate.py`, extraction, Next.js report shell); (2) Faradworks legal/metadata identity still shipping in the UI; (3) GitHub `main` not carrying the product; (4) Clerk / Anthropic seams still in the runtime graph; (5) vendored ImpedenceFinder with **no license file and GitHub `license: null`**.
Most important to replace **first** (identity and branch topology), not the finding engine or PCB job: Faradworks terms/privacy/contact/metadata; then isolate Clerk and Anthropic; keep parsers/graph as KEEP until a later phase.
---
## 2. Method and non-goals
**Compared trees**
- Upstream: `git fetch` of `https://github.com/Faradworks/Pinscope.git` into a **local** remote named `upstream` on a disposable clone. This audit did not `git remote set-url`, force-push, rewrite history, or detach the GitHub fork.
- Product: `origin/cursor/pcb-review-plan-44dd` (also compared `origin/main` and `origin/cursor/deepseek-71c5`).
- File identity: `git ls-tree` blob SHAs.
- Text overlap: line-**set** Jaccard on `git show` text. Thresholds (fixed, not guessed): identical SHA → UPSTREAM; same path and Jaccard ≥ 0.20 **or** ≥ 20 shared lines → DERIVED; same path and below that → REPLACEMENT; path only in HEAD with identical SHA to an unmatched upstream blob, or Jaccard ≥ 0.15 against a basename / `pinscopex`→`periscopex` map → DERIVED/REPLACEMENT with `renamed_from`; `vendor/` → THIRD_PARTY; else NEW.
- Licenses: root `LICENSE` blob vs upstream; npm `license` field on **every**`frontend/package-lock.json``packages` entry (827 entries, 0 missing); PyPI JSON `info.license` / `license_expression` / License classifiers for each `backend/requirements.txt` name; ImpedenceFinder GitHub API + tree + `pyproject.toml` + `LICENSE` URL. **No license was inferred from a package name.**
- Strings: ripgrep for `Pinscope`, `PinScope`, `pinscope`, `Faradworks`, `faradworks`, `SPDX`, `copyright` (lockfile excluded from hit lists). Matches were classified, not deleted.
**Classifier caveat (empty blobs):** git empty-file SHA `e69de29` is shared by `backend/__init__.py` (UPSTREAM) and three HEAD empty files. The rename heuristic tagged `backend/periscopex/__init__.py`, `tests/impedancefinder/__init__.py`, and `vendor/impedancefinder/__init__.py` as DERIVED-from-`backend/__init__.py`. That is **not** a meaningful derivation. Corrected intent: package markers NEW / THIRD_PARTY. Counts in §1 are the **raw** classifier (reproducible). Adjusted: DERIVED 124, NEW 141, THIRD_PARTY 10.
**Non-goals:** no refactors, no PCB/finding-engine edits, no license changes, no history rewrite, no “delete every PinScope line.”
---
## 3. Git history map
### 3.1 Exact upstream and remotes (GitHub, not this clone)
From `GET https://api.github.com/repos/manvalan/periscope` (2026-09-20):
`upstream/main`**is**`b26ad35`. Fork `origin/main` contains those five plus three fork-only commits. **0** upstream commits are missing from the fork (ahead/behind `upstream/main...origin/main` = `0 3`).
### 3.3 Divergence
```
6672d2b Pinscope OSS root (Faradworks)
…
b26ad35 upstream/main = merge-base
├─ origin/main (+3)
│ 4888092 Docker, remove Clerk, OSS mode
│ 2c5d9d3 Document fork changes in README
│ ab1c5b0 Fix Anthropic skill references and backend git support
└─ origin/cursor/pcb-review-plan-44dd (+92 from upstream, +89 from origin/main)
48246f3 Adapt Pinscope to DeepSeek, auto datasheets, shared library
Rules: see §2. Full per-file table: **Appendix A**. Snapshot: 404 HEAD files vs 254 upstream files.
**Unmatched upstream path still absent from HEAD:**`backend/pinscopex/__init__.py` (package renamed; other `pinscopex/*` files matched as `periscopex/*`).
**DERIVED core:**`backend/periscopex/{graph,models,parsers,parsers_edif,validate,validation_tools,resolve_passives,derating,bom_summary,taxonomy,pin_mux_check,led_current_check}.py` with Jaccard typically 0.63–0.98 vs `backend/pinscopex/*`. `parsers_edif.py`, `pin_function_tokens.py`, `taxonomy.py` are **identical blobs** after rename.
**UPSTREAM clusters:**`LICENSE` (identical AGPL-3.0 text), most `frontend/src` primitives / marketing assets, `frontend/public`, `skills/extract-pattern` + `extract-specs` trees, most `taxonomy/*.json`, `simple_project` netlist/BOM/PDF/design_graph, several `backend/services` and routers unchanged.
Strengths: **DIRECT** = still the same module/control flow; **INDIRECT** = new code that imports DIRECT modules; **WEAK** = naming, docs, compatibility aliases, unused seams; **NONE** = no PinScope type/control coupling observed.
└─ CLAUDE.md still describing Console Skills while README forbids Anthropic
│
NONE (new engines, still may import geometry types)
├─ antenna_geometry / antenna_rf
└─ vendor ImpedenceFinder (third party) via vendor_path
```
| Subsystem | Strength | Evidence |
| --- | --- | --- |
| `periscopex.graph` / `parsers*` / `models` / `taxonomy` | DIRECT | Rename + high Jaccard; `pipeline.py` still `build_graph` / `parse_bom` / `parse_netlist_any` |
| `periscopex.validate` / `validation_tools` / `services/validation.py` | DIRECT | Same per-IC datasheet review; `complete_findings` grafted at end of validate |
| `services/pipeline.py` + `pipeline_worker.py` | DIRECT | Same stage machine; provider swapped |
| `finding_engine.py` | INDIRECT | NEW; imports `models.Finding`; seeds `PE-*`; used by `validate.py` and `pcb_checks.py` |
PCB/finding-engine **code was not modified** for this audit. Observation only: PCB is already a second job, but it is not architecturally independent of PinScope’s graph, pintable cache, or review parser.
---
## 6. Package and lockfile licenses
Root project license: **GNU AGPL v3** text, blob-identical to upstream (`LICENSE` = UPSTREAM). README on the product branch: “AGPL-3.0, same as upstream Pinscope (Faradworks). For commercial licensing of the original, write to dev@faradworks.com.” GitHub API also reports `AGPL-3.0` on both repos. No `SPDX-License-Identifier` headers in the tree (0 files).
There is **no** Python lockfile (`poetry.lock` / `uv.lock` / `requirements.lock`). Versions below are **declared ranges** plus **PyPI’s current JSON license field** (fetched 2026-09-20), not the exact installed wheel in a given deploy.
MIT 684; ISC 44; Apache-2.0 43; MPL-2.0 13 (e.g. `axe-core`, `lightningcss*`); BSD-2-Clause 11; LGPL-3.0-or-later 10 (`@img/sharp-libvips-*`); BSD-3-Clause 9; BlueOak-1.0.0 3; Apache-2.0 AND LGPL-3.0-or-later 3; 0BSD 2; plus one each of Apache-2.0 AND LGPL-3.0-or-later AND MIT, Python-2.0 (`argparse`), CC-BY-4.0 (`caniuse-lite`), CC0-1.0, (MIT OR CC0-1.0).
**Copyleft transitive (frontend):** LGPL-3.0-or-later via sharp/libvips optional platform packages; MPL-2.0 via lightningcss/axe-core. Not removed; recorded.
### 6.4 Vendored ImpedenceFinder
| Probe | Result |
| --- | --- |
| GitHub `license` on `manvalan/ImpedenceFinder` | JSON `license: null` |
| `LICENSE` at vendored commit `a0c8d0ec…` | HTTP 404 |
| `pyproject.toml` on default `main` | **no**`[project].license` / license-files |
`terms.md` still defines the operator as Faradworks while `SITE_URL` defaults to `https://periscope.michelebigi.it`. That is a **product-identity coupling**, not a parser coupling.
FSF copyright on the AGPL **license document** itself (2007). That is expected and KEEP. No per-file `Copyright (C) Faradworks` headers were found in `.py`/`.ts` (search limited as in §2). Absence of headers ≠ absence of copyright; the fork inherits AGPL obligations from the parent work.
---
## 8. Duplicated concepts and partial migrations
| Concept | PinScope side (still present) | Periscope side | Migration state |
| --- | --- | --- | --- |
| Package name | `backend/pinscopex` gone; empty `__init__` only unmatched | `backend/periscopex` | **Done** (rename); imports updated |
| Finding IDs | changelog `PS-*` | `PE-*` in finding_engine | **Done** for new IDs; old reports not in repo |
| App version field | `pinscope_version` alias | `periscope_version` | **Partial** — dual read |
| Open-core seams | `billing_hook`, proxy.ts, clerk-theme | OSS no-op + local auth | Stubs KEEP for API shape; identity REPLACE |
---
## 9. Technical quality observations (no rewrite proposals)
These are facts about the snapshot, not a license to rip out PinScope.
1.**Default branch is not the product.** Anyone cloning `manvalan/periscope` without a branch flag gets pre-DeepSeek Pinscope + Docker (`ab1c5b0`). Live notes refer to 2.32.1 on the PCB branch.
2.**Docs disagree:**`CLAUDE.md` (DERIVED, Jaccard 0.67) still titles Periscope but describes Claude Console Skills as required. Product `README.md` (REPLACEMENT) says skills are local and Anthropic must not be used.
3.**Finding engine is a clamp, not a new IR.**`validate.py` still produces `Finding` objects; `complete_findings` fills FACT/REQUIREMENT/INFERENCE. Replacing PinScope review in one shot would discard the working schematic loop.
4.**PCB job correctly refuses auto-place** (comments in `pcb_pipeline.py`) but **depends** on schematic graph + pintable cache (“run schematic review first”). That is coupling, not a bug by itself.
6.**`frontend/package-lock.json` is almost identical to upstream** (Jaccard 0.999) while app version moved to 2.26.3/2.32.1 — lock **name-version** stale; dependency licenses still readable from the lock.
7.**PyMuPDF dual AGPL/commercial** on PyPI is a distribution constraint for binaries/SaaS (AGPL network clause already applies via root LICENSE). Recorded, not changed.
8.**ImpedenceFinder** has no license metadata. KiCad formula comments are provenance of **math**, not a license grant.
9.**xlsx@0.18.5** lock field is Apache-2.0 (not guessed from “SheetJS”).
10.**Auth production guard** still mentions Clerk (`backend/main.py`, `update-periscope.sh` dies if `ENVIRONMENT=production` without Clerk). Local JWT exists but deploy script language is mixed.
11.**No per-source-file copyright/SPDX** — harder provenance later; AGPL still applies to the combined work.
12. Tests for NEW modules are substantial (`tests/test_pcb_review.py`, `test_finding_engine.py`, etc.) — quality of *additions* is high relative to unmerged `main`.
Independence means Periscope can evolve its product, legal identity, and review contract without pretending to be Faradworks/Pinscope. It does **not** mean deleting `graph.py`.
| Area | Action | Why |
| --- | --- | --- |
| AGPL `LICENSE` blob | **KEEP** | Identical upstream license; changing it is out of scope and would not create independence |
| Parsers, graph, taxonomy, BOM, derating, EDIF | **KEEP** | DIRECT lineage; this *is* the schematic core; replacing is a later engineering program |
| `models.Finding` + normalize/dedupe | **KEEP** + **ISOLATE** | Keep types; route new semantics through `finding_engine` |
| `validate.py` LLM loop | **KEEP** for now; **ISOLATE** provider/skills | Working product; independence = provider + finding contract, not a greenfield reviewer |
**REMOVE** is empty for Phase 0. Nothing should be deleted on the basis of this audit alone.
---
## 11. Phase 1 sequence (recommended order; not this change)
Phase 1 should increase **independence**, not maximize diff against PinScope.
1.**Land this audit** on a branch that does not rewrite engines (`docs/development/PINSCOPE_AUDIT.md` only).
2.**Branch topology:** decide how GitHub `main` relates to `cursor/pcb-review-plan-44dd` without detaching the fork (merge/PR of product onto `main`, or document that `main` is archival). Until then, every clone is the wrong tree.
3.**Operator identity:** replace Faradworks TOS/privacy/contact/metadata/Twitter/footers with Periscope operator documents; keep AGPL and a factual “derived from Faradworks/Pinscope” attribution (README already has a form of this).
4.**Compatibility fence:** one module/doc for legacy `pinscope_*` keys, JWT issuer, CORS, Docker network names; stop writing new `pinscopex:` storage keys.
5.**Auth ISOLATE:** make the self-host path (local JWT) the documented default; keep Clerk behind a named seam so admin/email do not assume Clerk.
6.**LLM ISOLATE:** document DeepSeek as the supported provider; treat Anthropic SDK + `upload_skills.py` as optional/legacy so CLAUDE.md matches README.
7.**Finding contract:** keep using `finding_engine` as the independence layer on top of `Finding`; do not rewrite `validate.py` in Phase 1.
8.**Vendor license:** obtain an explicit license for ImpedenceFinder (or stop distributing the vendor tree until known).
9.**Python lock:** add a lockfile so transitive licenses can be audited like npm.
10.**Only then** consider isolating parsers/graph behind a narrower Periscope API — a large KEEP surface, not a Phase 1 delete.
---
## 12. Unresolved questions and evidence gaps
1.**Intent of GitHub `main`:** accidental staleness vs deliberate “OSS mirror of upstream + Docker”? No PRs exist to explain it.
2.**Legal operator of periscope.michelebigi.it** vs documents that still say Faradworks, Inc. — this audit cannot assign a legal entity.
3.**ImpedenceFinder license** (author, KiCad cpp port implications). GitHub API `license` is null.
4.**PyMuPDF** AGPL vs Artifex commercial: which grant is used in the VPS deploy?
5.**Python transitive licenses** without a lockfile.
6.**Whether Anthropic is still reachable** if env keys exist despite README (code path exists; runtime not executed here).
7.**Private Faradworks gateway** files mentioned in upstream CLAUDE.md — not in this repo; cannot audit what the parent still replaces in cloud builds.
8.**Trademark** “Pinscope” / “Periscope” / “Faradworks”: search found **use**, not a registration database. No legal conclusion.
9.**Empty-file DERIVED tags** — see §2; raw vs adjusted counts.
10.**`origin` on the analyst clone** included a local `upstream` remote for fetch-only comparison. GitHub fork remotes were not edited; confirm live GitHub still has `parent: Faradworks/Pinscope` after this docs-only PR.
11.**mbparks/pinscope** (Arduino) is a **different project**; zero code overlap observed; ignored.
12.**Exact installed npm/pip versions on production** (`/root/periscope`) were not inspected; licenses are from lock + PyPI JSON as of 2026-09-20.
---
## Appendix A — Per-file classification
Evidence strings are mechanical (SHA / Jaccard / path). Empty-blob rename caveat applies to three `__init__.py` files listed as DERIVED.
**Do not rename** live Docker networks `pinscope_pinscope` / `pinscope_periscope` in Fase A (VPS Caddy).
## Identity
Operator of https://periscope.michelebigi.it is **Michele Bigi**. UI, TOS, privacy, metadata, and contact must not say the operator is Faradworks, Inc. Attribution to Faradworks/Pinscope remains for AGPL lineage only.
## Out of scope here (later phases)
Clerk/Anthropic runtime isolation (B). Rewrite of `validate.py` / finding engine (C). UI FindingCard (D). Parsers/graph (E). Fork detach (legal, not this plan).
# Piano — indipendenza architettonica e di licenza da PinScope
**Stato:** solo piano. Nessuna modifica a source di prodotto, remotes, `LICENSE`, né git history.
**Base:** [PINSCOPE_AUDIT.md](./PINSCOPE_AUDIT.md) (snapshot prodotto `facbaa2` / `cursor/pcb-review-plan-44dd`).
**Intento di Michele:***lasciare* il codice PinScope e le sue licenze; **isolare** l’albero ereditato; disegnare dipendenze; marcare cosa **deve** essere riscritto. Non cancellare ogni riga ereditata.
Questo piano **non** stacca il fork GitHub (`manvalan/periscope` ← `Faradworks/Pinscope`). Lo stacco è un passo legale successivo, fuori da queste fasi di lavoro, salvo decisione esplicita.
---
## 1. Obiettivo
Due indipendenze distinte, nello stesso prodotto:
| Asse | Cosa significa | Cosa *non* significa |
| --- | --- | --- |
| **Architetturale** | Periscope evolve identity, auth, LLM, contratto finding, job PCB/placement **senza** fingere di essere Faradworks/Pinscope e senza che il nuovo codice importi il loop PinScope come se fosse “nostro” | Cancellare `graph.py`, i parser, o il 79% di linee lineage |
| **Licenza / identità** | Operatore, TOS, privacy, metadata, vendor terzi con licenza **nota**; AGPL del fork **resta visibile** e attribuita | Relicenziare l’albero PinScope, togliere AGPL, o chiedere a Faradworks una licenza commerciale come se fossimo noi l’upstream |
**Criterio di fatto:** un modulo è “nativo Periscope” se può cambiare contratto (finding, PCB, auth locale, DeepSeek) senza patchare il recinto PinScope. Un modulo è “ereditato” se un `git blame`/Jaccard da audit lo lega a `pinscopex` / UI OSS Faradworks.
L’audit già dice: l’indipendenza **non** è bloccata dalle stringhe `pinscope`; è bloccata da pipeline, identità legale, `main` stantio, seam Clerk/Anthropic, ImpedenceFinder senza licenza.
---
## 2. Confine di isolamento (fence)
### 2.1 Recinto — albero ereditato (resta, non si “ripulisce”)
Trattare come **una dipendenza in-tree**, non come prodotto Periscope:
- Il recinto **conserva**`LICENSE` AGPL e l’attribuzione “derived from Faradworks/Pinscope”.
Implementazione fisica futura (non in fase identità): directory tipo `vendor/pinscope/`**oppure** package `backend/pinscope_legacy/` con shim `periscopex` — solo dopo che i consumer nativi non importano più path sparsi. Non è un rename cosmetico (`pinscopex` → `periscopex` è già successo e **non** è un recinto).
| LLM DeepSeek | `deepseek_provider.py`, `local_skill.py`, `pdf_ingest.py` | NEW |
| Deploy | `scripts/update-periscope.sh`, `docker-compose.yml` | NEW (nomi `pinscope_*` ancora WEAK) |
| Plugin KiCad | `plugins/kicad/` | NEW |
| Check deterministici fork | `dnp_check`, `sequencing_check`, `layout_rules`, … | NEW ma **INDIRECT**: usano `models` / graph |
### 2.3 Terzi (né PinScope né “nostro motore”)
`vendor/impedancefinder/` — commit `a0c8d0ec`, licenza **UNKNOWN** (audit §6.4). Resta dietro `impedance.py` + `vendor_path.py`. Non mescolare con AGPL PinScope né con il finding engine.
---
## 3. Albero delle dipendenze
Forza: **DIRECT** = stesso control flow / blob lineage PinScope; **INDIRECT** = codice nativo che importa DIRECT; **WEAK** = alias, brand, reti Docker.
```
Faradworks/Pinscope (AGPL-3.0)
│
├─ DIRECT periscopex.graph / parsers* / taxonomy / models
| Sottosistema PinScope | Consumer Periscope | Forza | Se si riscrive il PinScope… |
| --- | --- | --- | --- |
| Graph + parsers BOM/netlist | `pipeline.py`, PCB, placement, tutti i check | DIRECT / INDIRECT | Cade tutto il prodotto |
| `validate.py` review loop | report schema, PCB AI | DIRECT | Serve un reviewer nativo **prima** di spegnere PinScope |
| `Finding` Pydantic | `finding_engine`, UI card, cad-bridge | DIRECT | Mappare al contratto `motore-finding.md` |
| Skills pintable/pattern/specs | extraction, library | DIRECT | Già in parte sostituiti da `local_skill.py` |
| UI shell | ogni pagina | DIRECT | Identità e finding card prima; wizard dopo |
| Clerk/billing | `main.py`, admin, email | DIRECT + WEAK | Auth locale già c’è |
| Legal Faradworks | `/terms``/privacy` layout | DIRECT contenuto | Non è codice motore |
**Cosa deve essere riscritto** (per indipendenza vera, fasi tarde — non per “pulizia”):
1.**Identità legale/UI** — obbligatorio e **primo**; non è il motore.
2.**Seam Clerk + Anthropic** — obbligatorio per non dipendere dal cloud Faradworks.
3.**Loop `validate.py` / `_parse_review` / tool graph** — obbligatorio per un motore *Periscope*, **dopo** identità; oggi `finding_engine` è solo un clamp.
4.**IR `Finding`** — allineare il tipo Pydantic al contratto FACT/REQUIREMENT/INFERENCE (oggi campi doppi `finding`/`why`).
5.**UI report/wizard** — quando il contratto finding è nativo; non nella fase identità.
6.**Parsers/graph** — *non* obbligatori per identità; rewrite solo se si vuole un CAD layer Periscope senza AGPL PinScope (programma XL, ultimo).
---
## 4. Mappa licenze — cosa blocca una licenza Periscope “pulita”
“Pulita” = *Periscope come opera dell’operatore Michele, con dipendenze dichiarate*, **non** “Periscope senza AGPL”. L’albero PinScope **resta AGPL**; toglierlo richiederebbe rewrite totale del recinto (fase ultima) **e** comunque rispetto dei diritti sul codice già pubblicato.
| C4 | Spegnere import da `validate.py` nel PCB (`_parse_review` → parser finding nativo) | Toglie INDIRECT PCB→PinScope reviewer |
| C5 | Test golden `simple_project` + Emmaforo: parity FACT/REQUIREMENT, non parity prose | |
**Non in C:** riscrivere `graph.py` / parser KiCad.
**Done quando:**`validate.py` PinScope può restare nel recinto **non chiamato** dal job schema/PCB, oppure ridotto a wrapper deprecato.
### Fase D — UI
FindingCard, filtri Layout, wizard, admin senza Clerk copy, `package-lock` version drift. Dopo C1 almeno (stesso oggetto finding).
### Fase E — Parsers / graph (opzionale, XL)
Solo se l’obiettivo diventa *opera senza codice AGPL PinScope*. Sostituire BOM/netlist/graph/taxonomy è un secondo prodotto. PCB nativo resta INDIRECT finché `ensure_graph` chiama PinScope.
**Stacco fork GitHub:** solo dopo consiglio legale, **non** in A–D.
---
## 7. Rischi e sconosciuti
| Rischio | Impatto |
| --- | --- |
| Clone di default `main` ≠ prodotto 2.32.1 | Ogni PR “solo docs” su `main` descrive un altro tree |
| Rewrite `validate.py` in A | Rompe schema+PCB; l’audit lo vieta come primo passo |
| Recinto solo rename di cartella | Falso recinto (già successo con `periscopex`) |
| TOS Periscope scritti male | Resta il testo Faradworks *o* si perde AGPL attribution |
| ImpedenceFinder | Distribuzione RF senza grant |
| PyMuPDF grant in VPS | Dual license; non verificato a runtime |
| Clerk rimasto in `ENVIRONMENT=production` | Deploy script vs JWT locale |
| Anthropic ancora importabile se c’è la key | README ≠ runtime |
| Trademark Pinscope/Periscope/Faradworks | Audit: solo *use*, nessuna registrazione |
| Relicenza “Periscope MIT” | Impossibile finché il recinto è servito (AGPL §13 network) |
| Gateway privato Faradworks | Non è nel repo; non auditabile |
---
## 8. Non-obiettivi (espliciti)
- Non modificare source prodotto, remotes, `LICENSE`, git history **in questa consegna** (piano only).
- Non staccare il fork GitHub in queste fasi (**passo legale successivo**, se mai).
- Non cancellare il codice PinScope “perché è PinScope”.
- Non riscrivere `finding_engine` / `validate.py` / PCB nella **fase A**.
- Non auto-placer, non write-back pcbnew (già fuori da `piano-pcb-review.md`).
- Non promettere una licenza Periscope non-AGPL.
- Non mescolare mbparks/pinscope (Arduino) — progetto altro.
- Non usare questo piano come licenza a refactor su `cursor/pcb-review-plan-44dd` oltre un eventuale **solo** file docs su **nuovo** branch.
@@ -115,4 +115,6 @@ Geometria board: width/thickness, via, pour courtyard, placement mm, return/stit
**Fase B close-out:** BOM↔PCB↔datasheet (package/pinout/V/T/I); SPOF REVIEW; EMI solo con FACT in `layout_rules`; Tj da θJA+rame+via quando tutti i parametri ci sono.
**Fase B leftovers:** thermal FEM / OpenEMS; ImpedenceFinder LICENSE UNKNOWN; auto-place pcbnew; PinScope identity.
**Fase B leftovers:** thermal FEM / OpenEMS; ImpedenceFinder LICENSE UNKNOWN; auto-place pcbnew; GitHub fork detach.
**Fase A identity (shipped on product HEAD):** operator TOS/privacy/fence; not a `validate.py` rewrite.
@@ -109,10 +109,12 @@ Emmaforo USB verdict: if library has e.g. 90 Ω ±10% (81–99), Zavg ~88 Ω **P
| CPWG / OpenEMS | Field-solver export excluded from the ImpedenceFinder vendor snapshot |
| ImpedenceFinder license | Upstream has **no LICENSE** (UNKNOWN). Not invented in-tree. See `vendor/impedancefinder/SOURCE.md` |
| Auto-place / pcbnew write-back | Fase C |
| PinScope identity / TOS | Other worker |
| Fork detach | GitHub parent Faradworks/Pinscope stays; identity Fase A does not unfork |
Shipped this close-out: BOM↔PCB↔datasheet (`PE-BOM-010`…`014`); SPOF REVIEW; EMI with datasheet FACT; gated θJA Tj; SI re-extract when library `layout_rules` lack SI kinds (`model_version` 1.12.0, `si_extract_needed.json`).
Shipped PCB close-out (2.35.0): BOM↔PCB↔datasheet (`PE-BOM-010`…`014`); SPOF REVIEW; EMI with datasheet FACT; gated θJA Tj; SI re-extract when library `layout_rules` lack SI kinds (`model_version` 1.12.0, `si_extract_needed.json`). Shared `library/extracted` + one PDF exam.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.