@fateforge/xpedition-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/.agent/AGENT.md +59 -0
  2. package/.agent/AGENT_zh.md +59 -0
  3. package/.agent/CLI-SPEC.md +1073 -0
  4. package/.agent/CLI-SPEC_zh.md +891 -0
  5. package/.agent/SEC-SPEC.md +158 -0
  6. package/.agent/SEC-SPEC_zh.md +132 -0
  7. package/.agent/SKILL-SPEC.md +266 -0
  8. package/.agent/SKILL-SPEC_zh.md +221 -0
  9. package/.agent/SPEC_VERSION +1 -0
  10. package/AGENTS.md +34 -0
  11. package/AGENTS_zh.md +33 -0
  12. package/CHANGELOG.md +795 -0
  13. package/CODE_OF_CONDUCT.md +35 -0
  14. package/CODE_OF_CONDUCT_zh.md +35 -0
  15. package/CONTRIBUTING.md +50 -0
  16. package/CONTRIBUTING_zh.md +42 -0
  17. package/LICENSE +21 -0
  18. package/NOTICE.md +16 -0
  19. package/NOTICE_zh.md +13 -0
  20. package/README.md +200 -0
  21. package/README_zh.md +178 -0
  22. package/SECURITY.md +108 -0
  23. package/SECURITY_zh.md +83 -0
  24. package/docs/AGENT_HARDENING_EVIDENCE.md +102 -0
  25. package/docs/AGENT_READS.md +74 -0
  26. package/docs/AGENT_READS_METRICS.json +216 -0
  27. package/docs/AGENT_READS_VALIDATION.json +13 -0
  28. package/docs/API_INVENTORY_BINDING_VALIDATION.json +16 -0
  29. package/docs/API_INVENTORY_DESIGN.md +90 -0
  30. package/docs/API_INVENTORY_REVIEW.md +59 -0
  31. package/docs/API_INVENTORY_VALIDATION.json +29 -0
  32. package/docs/API_INVENTORY_WINDOWS_VALIDATION.json +29 -0
  33. package/docs/COMPATIBILITY.md +499 -0
  34. package/docs/CONFIRMATION_CONCURRENCY_VALIDATION.json +33 -0
  35. package/docs/DIAGNOSTIC_BOUNDARIES.md +33 -0
  36. package/docs/DIAGNOSTIC_BOUNDARIES_VALIDATION.json +12 -0
  37. package/docs/E2E.md +445 -0
  38. package/docs/EVALS.md +134 -0
  39. package/docs/MCP.md +20 -0
  40. package/docs/NATIVE_ADAPTER.md +141 -0
  41. package/docs/OPEN_SOURCE_CHECKLIST.md +61 -0
  42. package/docs/OPEN_SOURCE_CHECKLIST_zh.md +61 -0
  43. package/docs/PIN_WORKFLOW_VALIDATION.json +28 -0
  44. package/docs/PLACEMENT_TASKS.md +99 -0
  45. package/docs/PLACEMENT_TASKS_VALIDATION.json +36 -0
  46. package/docs/REFERENCE_ADOPTION.md +67 -0
  47. package/package.json +48 -0
  48. package/scripts/run.js +46 -0
  49. package/skills/xpedition-cli/SKILL.md +300 -0
  50. package/skills/xpedition-cli/reference/agent-hardening.md +58 -0
  51. package/skills/xpedition-cli/reference/api-inventory.md +58 -0
  52. package/skills/xpedition-cli/reference/confirmation-safety.md +55 -0
  53. package/skills/xpedition-cli/test-prompts.json +62 -0
  54. package/skills/xpedition-pcb/SKILL.md +244 -0
  55. package/skills/xpedition-pcb/reference/fabrication.md +26 -0
  56. package/skills/xpedition-pcb/reference/hand-routing.md +33 -0
  57. package/skills/xpedition-pcb/reference/pcb-conventions.md +162 -0
  58. package/skills/xpedition-pcb/reference/placement-tasks.md +28 -0
  59. package/skills/xpedition-pcb/test-prompts.json +62 -0
  60. package/skills/xpedition-schematic/SKILL.md +244 -0
  61. package/skills/xpedition-schematic/reference/pin-assignment.md +61 -0
  62. package/skills/xpedition-schematic/reference/schematic-conventions.md +306 -0
  63. package/skills/xpedition-schematic/reference/schematic-design-format.md +219 -0
  64. package/skills/xpedition-schematic/test-prompts.json +52 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,795 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [1.0.0] - 2026-09-28
11
+
12
+ ### Added
13
+
14
+ - `library kicad-import` converts KiCad footprint libraries into cell partitions of a
15
+ project's central library as a guarded command. Its dry run reads only files -- the
16
+ libraries, their footprint counts, the partitions that exist already -- and binds the
17
+ token to that list; the result reports each library in `items[]` with a `summary`. It
18
+ replaces the earlier module entry point, which wrote with no dry run and is gone.
19
+ - `--dangerous`, the second gate of CLI-SPEC §15.4, on the writes that destroy work:
20
+ `pcb unroute`, `pcb create --replace` (which archives the layout folder first),
21
+ `pcb route --unroute`,
22
+ `pcb annotate --unroute`, and `pcb arrange` on a board with routing (its dry run
23
+ counts it). Without it the confirmed run is refused with `E_CONFIRMATION_REQUIRED`
24
+ and the token stays unspent. `reference` marks them `dangerous` with `dangerous_when`
25
+ in the `dangerous` permission tier, and the tool is now T2. `library kicad-import`
26
+ joins them when it merges into a partition that exists, and `schematic draw` always: every
27
+ sheet it draws is wiped first, hand edits included. SECURITY.md says why `session stop`
28
+ stays outside the tier.
29
+ - `--continue-on-error false` stops `pcb unroute` and `library kicad-import` at the first
30
+ failed item; the rest are listed in `skipped` and `summary` counts the attempted ones. The
31
+ token binds the choice, and other commands refuse the flag.
32
+ - `kb add --name NAME --url URL --about TEXT`, `kb list` and `kb remove --name NAME`
33
+ bind a company's knowledge-base documents -- layout rules, drawing conventions, review
34
+ checklists -- on this machine, and `context` lists them. Binding and unbinding are
35
+ writes, behind the usual dry run and token. The agent reads each document with its own
36
+ tools (for a Feishu wiki, lark-cli), every time, and the Skills say when: before work in
37
+ its area. A company rule replaces a bundled default and settles a TBD; verified facts,
38
+ the write safety rules and STOP CHECKPOINTs stand. The CLI stores http(s) links only;
39
+ it never fetches a document, so no document system is special-cased and no credential
40
+ is held.
41
+ - A failed `schematic draw` can be resumed (#30). Every sheet ends in a save, so the
42
+ failure now names the sheets it completed (`sheets_drawn`) and the rest
43
+ (`sheets_remaining`), with a hint, and `--sheets 3,4` draws only those; the netlist
44
+ check still covers the whole design, and the sheets left alone come back as
45
+ `sheets_kept`. The token binds the chosen sheets. `--pace` slows a draw for someone
46
+ watching Designer, as it does `pcb trace`. On a 4-sheet design interrupted on
47
+ sheet 3, the resume drew 132 of 207 operations and the netlist matched.
48
+ - `--timeout SECONDS` gives a native read -- the snapshot behind review, bom,
49
+ schematic, pcb, library and project reads -- the time a large design needs (#29).
50
+ The default is 120 s, up from a fixed 30 s that a 41-part design with an 8 MB
51
+ central library outran; a timeout names the time it had and the flag to raise.
52
+ - `schematic draw` notes when the partition's parts database does not exist. Designer
53
+ draws a part instance's value itself when the library has no part for it -- twice, the
54
+ horizontal copy landing on the reference designator -- and its own "Text alignment"
55
+ check then fires on every such part, which was the only thing between a generated
56
+ schematic and a clean review. `library build --package` clears both, so the draw says
57
+ so instead of leaving the findings to be chased.
58
+
59
+ - DS-16 reports a top or bottom edge whose pin names are wider than the pin pitch. Those
60
+ names are drawn horizontally inside the body at the pitch, and at `CHAR_WIDTH` per
61
+ character over 10 units about 1.6 characters fit, so a four-ground bottom edge rendered
62
+ as `AGNBPGNBCNE2AD` -- four names written over each other. Shortening them does not
63
+ help. The check names the pins and says where they can go instead; drawing them
64
+ readably needs a rotated name row, which is not done here.
65
+
66
+ - DS-15 checks, when the plan is built, that nothing belonging to one net lands on the
67
+ free end of another net's wire: a ground symbol reaches 40 units past its own end, four
68
+ slots at the 10-unit pin pitch, and a boxed label runs `CHAR_WIDTH` per character
69
+ sideways from a top-edge pin across its neighbours. Designer refuses those draws with
70
+ 6031 and 6035, and a box that lands exactly on an end is worse -- it draws, merging two
71
+ nets, with nothing in the output to say so. DS-07 and DS-08 check symbol extents and
72
+ spacing; none of this was checked, so three draws failed on plans reported clean.
73
+ - A failed draw operation reports the sheet it fell on, the net or symbol it touched,
74
+ and how many operations had already been applied. An index alone was not locatable:
75
+ resolving "operation 269" meant importing the planner, rebuilding the plan and counting
76
+ `open_sheet` records, once per attempt, at several minutes per attempt.
77
+ - `schematic draw --dry-run` publishes the planned `operations`, each carrying its index
78
+ and the sheet it lands on, so a reported index can be looked up and a plan inspected
79
+ without importing the planner. Trim it with `--fields` on a large plan.
80
+ - The native adapter streams draw progress to stderr as it runs, and `--quiet` now does
81
+ what CLI-SPEC §4 says it does and suppresses it. The adapter's stderr was captured, so
82
+ a draw of several hundred operations printed nothing at all until it returned.
83
+ - `doctor` reports a `native_session` check naming which Xpedition application is
84
+ attached right now. `native_xpedition` passes as soon as an adapter is configured,
85
+ which says nothing about what is running, and Layout and Designer are separate
86
+ products with separate COM classes: `pcb *` reaches Layout while `schematic *` and
87
+ `agent snapshot` reach Designer. Nothing surfaced that split, so the first sign of
88
+ it was a task command failing. The probe is skipped when the native backend is not
89
+ ready, and a probe that fails cannot fail `doctor`.
90
+ - Failing to attach to a session now names the application, the commands it serves,
91
+ and the `session start --kind pcb|schematic` that starts it, instead of reporting
92
+ only the ProgIDs that were tried.
93
+ - Selected-origin placement tasks: offline `pcb placement-plan` and guarded native
94
+ `pcb placement` for explicit translate, rotation about an origin, alignment to
95
+ an anchor, and equal-origin-spacing distribution. Input JSON Schemas are exposed
96
+ by reference; native identity, units, side and protection are read, not guessed.
97
+ - One preview/confirmation for a serial batch, per-item and final target read-back,
98
+ native placement DRC enable/restore checks, stop-on-uncertainty results and one
99
+ save after verified completion. No routing deletion or unselected placement is
100
+ requested. This is not route repair, all-or-none rollback or a global write lock.
101
+ - Scoped reference discovery by exact command, top-level domain or existing
102
+ output-schema name. A command slice retains its success and dry-run schemas,
103
+ error tables and permission metadata; the full catalog remains the default.
104
+ Selectors are declared from one source and rejected on unrelated commands.
105
+ - Read-only `schematic pin-plan` and `schematic pin-check` compare exact CSV
106
+ pin/net assignments with supplied snapshots. Plans identify noop/connect/reassign
107
+ and shared-net review needs. Missing or conflicting observations never count as
108
+ verified. No native calls, automatic ChangeSets, write tokens or modifications.
109
+ - Bounded pages and peer samples, full-input assessment before paging, file hashes,
110
+ strict CSV/JSON validation and machine-readable input/observation contracts.
111
+ Source freshness and live electrical correctness are explicitly unverified.
112
+ - `system api-inventory` reads trusted standalone COM type-library metadata on
113
+ Windows without application activation, method invocation or registration.
114
+ Type headers and selected member pages report names, identities and raw type
115
+ descriptors; they do not become callable CLI capabilities or inferred schemas.
116
+ - Exact type selection, bounded pages and descriptor depth, incomplete-read
117
+ reporting, source hashes and safe projection. DLL/EXE/URL/UNC input, backend
118
+ selection and write flags are rejected. Xpedition semantics remain untested.
119
+ - A Windows smoke workflow exercises the real pywin32 loader against Windows'
120
+ standard OLE type library, without Xpedition. It is not a licensed-native test.
121
+ - Hand routing through the CLI — the person's own layout, not the autorouter's:
122
+ `pcb geometry` (the board as data: outline, pads with nets, traces with widths, vias,
123
+ planes, holes, silkscreen, and every part with its origin, extents and pins),
124
+ `pcb trace` (a trace from `--net`, `--layer`, `--width`, `--points "x,y x,y …"`, or a
125
+ whole plan file of traces and vias with `--file`; `Document.PutTrace`), `pcb via`
126
+ (`Document.PutVia`, the board's via padstack or the central library's), `pcb unroute`
127
+ (the routing of `--nets`, of `--all`, or one trace / via at `--at x,y [--layer N]`),
128
+ `pcb move` (one part to a position and rotation with the placement DRC on) and
129
+ `pcb labels` (every silkscreen designator to a free spot beside its part). The
130
+ preview of `pcb trace` names the nearest pin of each trace end; the result gives the
131
+ open count of every touched net before and after, and Layout's online DRC refuses an
132
+ item that violates a clearance while the rest go on.
133
+ - `pcb show --top-view`: a display scheme (`Loc: Top View`, written once into the
134
+ board's `Config` from `All On.dcs`) that shows Layout's own screen the way
135
+ `pcb render` draws the board — plane copper filled, the inner layers off, the
136
+ assembly texts and the drill drawing off. The stock `Loc: All On` draws the
137
+ pours as outlines only and every layer and text at once, which is why a board
138
+ with pours looked bare and crowded on screen. Layout lists a new scheme only
139
+ after the board reopens, so the first use closes and reopens it.
140
+ - `xpedition_cli.routing_plan`: the offline checker for a plan against `pcb geometry`'s
141
+ file (angles, clearances to pads, traces and vias of other nets, a via pad touching
142
+ any pad — Layout refuses those, its own net included), `PlanBuilder` for writing a
143
+ plan pin by pin, and `pcb stitch`, the plan for a ground via beside every
144
+ surface-mount ground pad where the checker finds room. `pcb trace --geometry` runs
145
+ the checker before Layout is touched and refuses a failing plan (`--dangerous` to let
146
+ Layout judge).
147
+
148
+ - Added `pcb rules` (adapter method `net_rules`): a net class with its trace widths on
149
+ every layer, through Constraint Manager's automation server (`ConstraintsAuto`, the
150
+ board loaded in its layout context), which Layout's own automation cannot write.
151
+ `--class POWER --nets VBAT,+3V3 --width 0.5` sets the typical width, `--min` and
152
+ `--expansion` the other two (80 % and 120 % of it by default); Layout re-reads the
153
+ constraints through `ProjectIntegration.SynchCES` and the result says
154
+ `seen_by_layout`. The next `pcb route --unroute` routes the class at that width.
155
+ - Added `pcb render` (adapter method `render_board`, drawing in
156
+ `xpedition_cli.board_render`): a PNG of the board from its geometry — outline with its
157
+ arcs, pads, traces at their widths, vias, generated planes with their cutouts, drills,
158
+ silkscreen graphics and texts — in KiCad's editor colours, top or bottom side. It
159
+ needs no screen, so it works with the desktop locked, where `pcb show --output`
160
+ captures a black window.
161
+ - `pcb arrange` places the parts of a cluster beside the IC pin they connect to: the
162
+ survey now reads every pin's offset, a satellite goes to the side of the IC where its
163
+ pin stands, level with it, turned so its own connecting pad faces the pin (a series
164
+ resistor at its signal pin, a decoupling capacitor at the supply pin, not the ground
165
+ one); a side may overhang the IC by about one designator and continues in a further
166
+ column or row when it fills up, and a row above or below the IC steps past a column
167
+ that reaches the corner.
168
+ - Added `pcb export`: the fabrication package (adapter method `manufacturing_output`,
169
+ pure parts in `xpedition_cli.fab_package`). Layout has no automation call for ODB++,
170
+ Gerber or NC drill, so their Output-menu dialogs (33017, 33016, 33018) are run with
171
+ the helper thread pressing OK. The dialogs keep their settings in memory while the
172
+ board is open and rewrite `Config/ODBSetup.ocf` and `Config/PlotSetup.gpf` on OK, so
173
+ the setups are patched with the board closed and it is opened again: the ODB++ job
174
+ gains its drill spans and board outline (`d_1_4 INCLUDE YES`, `BOARD_OUTLINE YES`),
175
+ the Gerber set gains the cells' silkscreen (`..CellType` / `..CellItemsSide` /
176
+ `...CellItem SilkscreenOutline` + `SilkscreenReferenceDesignator`; a `..BoardItem
177
+ SilkscreenTop` writes an empty file) and the board outline. The outputs are read back
178
+ (draw counts, drill hits, ODB++ layer matrix) and copied into a folder with fab-friendly
179
+ names — empty files and Layout's duplicate outer-copper files stay behind — plus the
180
+ ODB++ job as a zip, a centroid file, a BOM grouped by part number and footprint, a
181
+ README for the board house in Chinese and a manifest with the checks. The dry run is
182
+ offline (it reads the setups only).
183
+
184
+ - `pcb arrange` lays parts out the way a hand layout reads: every part keeps room above
185
+ it for its reference designator (Layout's extents stop at the placement outline, and
186
+ a 1 mm `R302` is wider than an 0603), the parts of one column or row share one pitch
187
+ (the largest of them plus the gap) with the first parts nearest the anchor, centres
188
+ snap to a 0.5 mm grid without ever moving outward past a margin, connectors on the
189
+ left edge turn by 270° and on the right by 90° so their designators face inward, a
190
+ new row keeps room for its sheet label, and once the corners hold mounting holes a
191
+ 7 mm square in each corner stays empty (`corner_keepout`). A plan with parts past the
192
+ outline is refused with `E_VALIDATION` before anything moves (placing them lands on
193
+ the parked parts and Layout stops halfway with a DRC violation).
194
+ - `pcb route --layers 1,4` keeps the traces on the outer layers: `RoutePass.LayerSelect`
195
+ takes the inner layers only (the outer two are always the router's and count as
196
+ invalid parameters), so the list decides which inner layers join. The result reports
197
+ `traces_by_layer`. `--unroute` deletes every trace and via first, because the passes
198
+ only work on open connections.
199
+ - `pcb outline --radius R` rounds the corners: Layout's points array takes each corner
200
+ as the arc's start, its centre with a *negative* radius and its end (a positive
201
+ radius draws the other 270°); the route border is rounded by `R − 0.3` and the
202
+ manufacturing outline like the board. `Geometry.GetRect*` only answers for a plain
203
+ rectangle and calls a rounded outline incorrect geometry, so the board rectangle is
204
+ now read from the outline's extents.
205
+ - `pcb pour` follows the outline: the shape is inset from a rounded outline with the
206
+ corner radius less the margin (the radius is read back from the outline's points
207
+ array, which comes in thousandths of an inch), and `--replace` removes the shape the
208
+ board already has for that net and layer, because after `pcb outline` changed the
209
+ board the old rectangle stuck out past the rounded corners.
210
+ - Added `pcb holes`: a non-plated mounting hole in each corner of the outline (2.2 mm,
211
+ 3.5 mm from both edges by default) through `Document.PutMountingHoleEx` with the
212
+ central library's `MH-C<diameter>-NONPLATED` padstack, which the library build and
213
+ the KiCad import both create (adapter method `mounting_holes`). Corners that already
214
+ hold a hole are left alone; `--replace` removes every existing hole first, for a
215
+ board whose outline grew.
216
+ - Added KiCad's footprint library as a source of real cells. `xpedition_cli.kicad_footprints`
217
+ reads `.kicad_mod` files (pads of every shape, drills and slots, silkscreen / fabrication
218
+ / courtyard graphics, the reference-designator text) into the library model, and the
219
+ adapter method `kicad_import` (run by `library kicad-import`) turns every `.pretty`
220
+ folder into one cell partition of the project's
221
+ central library through the stock converters — 155 libraries, about fifteen thousand
222
+ cells, in a quarter of an hour. A design names a footprint as its package with a
223
+ `kicad:` key (`"packages": {"RES": "kicad:Resistor_SMD:R_0603_1608Metric"}`), and
224
+ `library build` then writes parts that reference the cell and registers its partition in
225
+ the project's `LIST 2dCellLibraries` (`cell_partitions`). The library model gained
226
+ radius-corner rectangles, oblongs, slotted holes, drawn outlines (`Graphic`), mounting
227
+ holes inside package cells and the placed reference designator (`RefDesText`, on the
228
+ silkscreen and on the assembly layer), which is what keeps the refdes at the
229
+ footprint's 1 mm instead of Layout's default. Cell names are
230
+ limited to 64 characters by `HKP2CellDB`, so longer KiCad names are cut and tagged with a
231
+ hash; a partition the converter refuses a cell of is imported again without it.
232
+ `examples/demo-sensor-board-kicad.json` is the example design on KiCad footprints.
233
+
234
+ - Added `pcb create`: the project's board from a layout template through `JobWizard
235
+ -createnew` (adapter method `pcb_create`). The wizard's command line takes the first
236
+ design in the `.prj`'s `LIST Designs` and fails with "failed to get design information"
237
+ when that is a schematic node, so the board design is listed first; the template is
238
+ copied from the installation's stock set into the central library when the library
239
+ lacks it; and `LIST 2dCellLibraries` gains the cell partition of every parts partition
240
+ the project lists, without which Layout's Database Load finds no cells. `library build`
241
+ registers the same list.
242
+ - Added `pcb annotate`: forward annotation through Layout's `Document.ProjectIntegration`
243
+ (adapter method `forward_annotate`), which has no type information, so `ForwardAnnotate`
244
+ runs on attribute access; the counts and verdict come from `PCB/LogFiles/
245
+ ForwardAnnotation.txt`, a board already in synch is reported without running (Layout
246
+ calls that a failure), and the board is saved afterwards.
247
+ - `session open --kind layout` and `pcb info` accept the `.prj`: the board comes from the
248
+ design's `PCBDesignPath`. While a board opens, a helper thread answers Layout's own
249
+ questions through UI Automation (`win_dialogs.answer_prompts`, needs `pywinauto`): a
250
+ stale lock from a killed session is opened, the recovery box loads the database the
251
+ user last saved, the offer to forward-annotate is declined, and every answer is
252
+ reported as `prompts`. A missing Layout is started through its launcher and waited
253
+ for, because an instance that COM activation starts never registers its automation
254
+ object. The adapter loads Layout's type library for its enumerations but keeps the
255
+ objects late-bound, and reads `Components` and `Nets` without filters: both wrappers
256
+ reject the filter arguments.
257
+ - `xpedition_cli.project_file`: pure-text reading and editing of a `.prj` (designs and
258
+ their sections, list entries, list creation, design order).
259
+ - Designer's `OpenProject` is wrapped the same way: switching projects while sheets are
260
+ open asks whether to close them, and the call waits for the answer; the adapter now
261
+ answers Yes.
262
+ - Added `pcb arrange`: a first placement of the board's parts that follows the
263
+ connections (adapter method `arrange_components`, planner `xpedition_cli.board_layout`):
264
+ one cluster per IC with the parts that connect to it around it, filled from the centre
265
+ outward so decoupling capacitors sit nearest, clusters in rows by sheet, connectors
266
+ turned by 90° on the side edge next to their cluster, test points along the bottom
267
+ edge, and a silkscreen zone label per sheet from the design file's `zone`
268
+ (`--design`). Layout has no extents for an unplaced part and drops its pins from
269
+ `Net.Pins`, so the dry run measures each part alone at the board's centre, parks the
270
+ unplaced ones in a grid below the outline, reads the nets, unplaces them again and
271
+ binds the token to the plan's digest; the confirmed run recomputes the plan, refuses a
272
+ changed board, lifts every planned part (Layout calls a part placed onto another one,
273
+ or its own old footprint, a DRC violation), places through `Component.Place`, replaces
274
+ earlier zone labels and saves.
275
+ - Added `pcb outline`: the board outline as a width × height millimetre rectangle from
276
+ the origin (`PutBoardOutline`), with the route border 0.3 mm inside it and the
277
+ manufacturing outline on it, because the template's copies keep their old size
278
+ otherwise (adapter method `board_outline`).
279
+ - Added `pcb pour`: a plane shape for a net on a layer, inset from the outline
280
+ (`PutPlaneShape`; GND on layer 2 by default), refusing a second shape for the same net
281
+ and layer (adapter method `plane_pour`). The optional component argument of these
282
+ calls must be passed as `None`: win32com cannot turn the type library's default `0`
283
+ into an object pointer, and the call fails with "The Python instance can not be
284
+ converted to a COM object".
285
+ - `pcb show` also fits the board outline into the view (`ActiveView.SetExtentsToBoard`,
286
+ once the toolbar's `VIEW_FITBOARD` button), so a resized outline fills the view.
287
+ - Added `pcb route`: Layout's batch autorouter through `Document.NewRoutePass`
288
+ (adapter method `route_board`). `--passes` names the passes and their effort range,
289
+ `route:1-5,viamin:1-3,smooth:1-3` by default (also `fanout`, `novia`, `spread`,
290
+ `expand`, `removehangers`); each pass runs over every net with `Go` and the result
291
+ reports the routed nets, open connections, traces and vias after each one and the
292
+ nets left open. The example board routes completely in three seconds.
293
+ - Added `pcb create --replace`: closes the board in Layout, removes the `PCB` folder,
294
+ clears the board keys in the `.prj` and creates the board again. That is the way to
295
+ pick up a cell that changed in the library: forward annotation never changes the cell
296
+ of a component that already exists on the board, placed or not, and JobWizard's own
297
+ `-deletePCB` fails on these projects.
298
+ - `pcb annotate` is now robust: the board is closed and opened again first (a Layout
299
+ session older than Designer's current project session fails the packaging phase),
300
+ Layout's own "annotate now?" prompt is answered Yes, the explicit call runs with
301
+ Designer's project closed (it fails with it open) and is retried once (the first call
302
+ on a freshly opened board fails, the second succeeds), Designer's project is reopened
303
+ afterwards, and `--unroute` deletes traces and vias first (Layout in its preventive
304
+ DRC mode cannot break traces back).
305
+ - `pcb arrange` deletes the board's traces and vias before re-placing (a part placed
306
+ onto a trace is a DRC violation, and a placement change makes every trace wrong) and
307
+ reports what it removed.
308
+ - Placeholder IC packages are routable under the stock rules: `SOIC` (1.27 mm pitch)
309
+ up to 16 pins and a 0.8 mm pitch `TSSOP` beyond, because a 0.65 mm pitch cannot be
310
+ reached with 0.254 mm traces and clearances (the template's read-only defaults).
311
+ - Board snapshots include traces and vias (net and layer), so `pcb info` counts them.
312
+ - Added `pcb drc`: Layout's Batch DRC (adapter method `batch_drc`). There is no
313
+ automation call and its driver refuses a command line, but the menu command runs
314
+ through `Gui.ProcessCommand(32769)`; its dialog is answered from the helper thread, the
315
+ run is waited out, and every hazard comes back from `Document.GetHazards` with its
316
+ type name, description, position, the objects involved and, for clearance checks, the
317
+ required and actual distance. `--no-run` only reads, `--online` adds the online DRC's
318
+ hazards. The first run found the dual-row placeholder pads overlapping (pad long side
319
+ along the pitch), fixed in `library_hkp`, and the ground vias dangling, fixed below.
320
+ - `pcb pour` switches the net's plane assignment from Draft to Dynamic so Layout
321
+ generates the copper (`PlaneAssignment.PlaneDataState`), and `pcb route` regenerates
322
+ every plane after its passes: vias the router adds only tie in after a regeneration.
323
+ The battery board then passes Batch DRC except for vias under the IC bodies.
324
+ - The prompt answerer thread no longer presses the default button of every `#32770`
325
+ dialog: doing so ended the packager's progress box during forward annotation, which
326
+ was the whole reason `pcb annotate` kept failing "in the packaging phase" while the
327
+ same call from a plain script succeeded. Annotation now succeeds at the first attempt
328
+ on a fresh board; the retry stays, with short waits.
329
+ - Window captures that are all black (a locked desktop) are reported with `blank`.
330
+ - Added `pcb show` (adapter method `show_board`): the board window to the front under a
331
+ display scheme that shows the parts, default `Loc: All On`, with an optional PNG
332
+ capture like `schematic show`. The stock templates open with `Loc: Assembly Bottom`,
333
+ under which a board of top-side parts looks empty. Layout lists the scheme names
334
+ (`Document.DisplaySchemes`); `pcb show` switches them through the view's display
335
+ control (below), with the toolbar combo driven through UI Automation as the fallback,
336
+ whose popup exposes only the rows on screen and is paged with the keyboard.
337
+ - Board component records carry `x`/`y` in millimetres with `unit`, whatever the
338
+ document's current unit (the stock template counts in mils), and `side` from `Side`
339
+ (1 top, 512 bottom) instead of the wrong layer test.
340
+ - Added `library build`: placeholder padstacks, cells and parts for a design, generated as
341
+ HKP text (`xpedition_cli.library_hkp`) and imported into the project's central library
342
+ through the stock `HKP2PadstackDB`, `HKP2CellDB` and `HKP2PartsDB` converters (adapter
343
+ method `library_import`); `--package` then runs the packager, which now replaces its cached
344
+ parts (`-Replace`) so a rebuilt library is seen. Symbols carry pin-label records and default
345
+ to the stock `PartQuest` partition, the one every template library registers.
346
+ - Added `project init --template` on the NativeBackend: a new Xpedition project copied from a
347
+ template project (adapter method `clone_project`), with an ASCII-path guard because Designer
348
+ cannot load new symbol files from a folder whose path has other characters.
349
+ - Added built-in `NTC`, `NMOS`, `PMOS`, `TP` (test point) and `HOLE` (mounting hole) symbol
350
+ kinds to the schematic planner and a four-sheet example design (a
351
+ battery-compartment temperature monitor with pull-ups, series resistors, test points and
352
+ thermal and interface notes).
353
+ - The I2C pull-up review rule now accepts a pull-up one series resistor away, so a host
354
+ connector behind 33 Ω series resistors is not reported.
355
+ - Generated passive, MOSFET and test-point symbols carry `ANALOG` pins, so Designer's
356
+ BI-to-power and BI-to-ground checks stay quiet on a correct design.
357
+ - Added `project tree`, embedded runtime changelog data, and the ExchangeBackend boundary.
358
+ - Added MockBackend read commands for schematic, PCB, constraints, analysis, manufacturing, and library data.
359
+ - Added schematic power-net, interface, and project-model support.
360
+ - Added read-only Agent integration commands and an NDJSON stdio server.
361
+ - Added ChangeSet history and backup rollback with the same dry-run/confirm gate.
362
+ - Added project diff against the latest automatic backup.
363
+ - Added MockBackend session status/log inspection with explicit native lifecycle boundaries.
364
+ - Added JSON/CSV/BOM ExchangeBackend inspection and guarded import.
365
+ - Added IPC-2581 XML component, net and pin-connection inspection/import.
366
+ - Added library validation and review findings/report read aliases.
367
+ - Added `schematic apply` as the unified guarded ChangeSet write entry point.
368
+ - Added guarded MockBackend project initialization.
369
+ - Added MCP JSON-RPC transport for read-only Agent tools.
370
+ - Added MCP protocol version negotiation and tool output schemas.
371
+ - Updated MCP negotiation to prefer protocol version 2025-11-25 while accepting older clients.
372
+ - Added deterministic MockBackend ERC/DRC/DFM analysis runs.
373
+ - Added BOM normalization, grouping, variant/missing/duplicate checks, validation and comparison.
374
+ - Added the optional Windows COM adapter for the public Xpedition automation API, including
375
+ installation discovery, COM-registration probing, structured health errors, session lifecycle,
376
+ PCB and Designer snapshots, and guarded component/net move/place operations.
377
+
378
+ - Added a `package` adapter method that runs forward annotation headless. Designer's
379
+ `Package Design for Layout` launches `packagerui.exe`, a separate GUI process that waits
380
+ for a human; `package.exe` does the same work as a console program. It has to be started
381
+ through the launcher in `common/win64/bin`, because the real binary under `wg/win64/bin`
382
+ cannot initialise its Qt platform plugin on its own and puts up a message box instead.
383
+ Errors and the verdict are read back from `<project>/Integration/PartPkg.log`.
384
+ - Added the Skill's drawing conventions: `reference/schematic-conventions.md` and
385
+ `reference/pcb-conventions.md`, with the non-negotiable subset in `SKILL.md` and a matching
386
+ eval prompt. The sheet unit was measured rather than assumed: one sheet unit is 10 mil, the
387
+ 100 mil grid is 10 units, `V 53` symbol files share the sheet unit and `V 54` files (every
388
+ stock symbol) are in 10 nm. Each rule is marked verified, industry default or pending a
389
+ company decision; the PCB rules are defaults only.
390
+ - Added `schematic export`: renders a Designer project to a new PDF through the stock
391
+ `sch2pdf` console program (adapter method `export_pdf`) and reports the sheets it printed.
392
+ Designer's own `Generate PDF` is a dialog; `sch2pdf` runs headless while the project is
393
+ open and prints only what lies inside each sheet's border. An existing output file is never
394
+ replaced.
395
+ - Added `xpedition_cli.symbols`, a generator for `V 53` Designer symbols: IEC two-terminal
396
+ shapes, pin-grouped boxes and one power symbol per net, all on the 10-unit grid. Power
397
+ symbols are type 4 (`Y 4`) like the stock Globals symbols — a type-1 symbol carrying a
398
+ `NETNAME` attribute names no net — and Designer keeps the definition of a symbol it has
399
+ placed, so a changed symbol needs a new name.
400
+ - Added `schematic draw`: plans a whole schematic from a compact design description
401
+ (`xpedition_cli.schematic_layout`: IC blocks with a treatment per pin, vertical ladders and
402
+ horizontal chains of two-terminal parts between power, ground and labelled nodes, titles,
403
+ notes, overview boxes) and draws it through the adapter method `draw` after the usual
404
+ dry-run/confirm gate. The dry run is pure Python and reports the sheets, parts, netlist and
405
+ convention issues; the confirmed run wipes and redraws the listed sheets, sets them to the
406
+ requested size, writes content-named symbol files, reopens the project and compares every
407
+ net read back with the plan. `examples/demo-sensor-board.json` is the published example.
408
+ - Added `xpedition_cli.win_dialogs`, the modal-dialog dismisser the probes used, so the
409
+ adapter can settle after project and sheet operations without a human.
410
+ - Added `schematic show`: activates a sheet, fits it and brings Designer's window to the
411
+ front so a person can look at what was drawn, with an optional PNG capture of the window
412
+ for the agent's own check (no external imaging library; the PNG is encoded in-process).
413
+ `schematic draw` and `schematic show` were then exercised end to end through the CLI on
414
+ a four-sheet example design: plan, confirm token, 223 operations, netlist match, window
415
+ in front.
416
+ - Added schematic review on live designs. The native snapshot now carries every instance
417
+ attribute (part number, value, package), the sheet a part sits on (from its UID), each
418
+ pin's net through `LogicalNetName` with Designer's `$<sheet>N<id>` id for unlabelled
419
+ nets, and a `no_connect` flag for pins under a no-connect mark. Nets are merged across
420
+ sheets, so multi-sheet designs no longer report every rail as a duplicate, `bom export`
421
+ returns part numbers and values, and `schematic unconnected` no longer lists marked pins
422
+ or bare junctions.
423
+ - Added netlist rules to `review run` (`cli/open-pin`, `single-pin-net`, `unnamed-net`,
424
+ `missing-part-number`, `decoupling`, `i2c-pullup`, `net-name`, `refdes-prefix`) and, on the
425
+ NativeBackend, Designer's own verification: the adapter method `verify` runs `Full
426
+ Verification` (34155) and parses `LogFiles/vdrc.log` and `grc.log` into findings tagged
427
+ `xpedition/verify:<rule>` and `xpedition/grc:<check>`. `RunDesignIntegrityChecks` is only
428
+ a database integrity test and is not used for this.
429
+ - MockBackend project model and normalized design snapshots.
430
+ - Capability registry with explicit NativeBackend and ExchangeBackend boundaries.
431
+ - ChangeSet validation, dry-run previews, operation-bound confirmation tokens, atomic apply, backup, and post-write verification.
432
+ - Deterministic review and normalized BOM commands.
433
+ - JSON-first CLI contract, Skill, FCC guard, CI and npm/PyInstaller packaging seed.
434
+
435
+ ### Changed
436
+
437
+ - Plural flags -- `--nets`, `--sheets`, `--layers`, `--formats`, `--libraries`,
438
+ `--fields` -- repeat as well as take a comma list, and `reference` marks them
439
+ `multiple`. A singular flag given twice with different values is a usage error; it
440
+ used to keep the last one silently.
441
+ - `pcb unroute` reports each net (or the point) in `items[]` with a `summary`, a net
442
+ named twice counts once, and an empty `--nets` is a validation error.
443
+ - A read whose `--project` does not exist is `E_NOT_FOUND`, not an empty design.
444
+ ChangeSet writes and imports still create their target.
445
+ - `doctor` and `session status` only look at a running Layout: they do not switch on its
446
+ dialog suppression and single-threaded mode, which the commands that drive Layout set
447
+ when they attach.
448
+ - `live_smoke_status` uses the spec's values: `missing`, with `reason` saying what the
449
+ recorded runs cover.
450
+ - The release binary's dependencies are locked -- `requirements.txt` (Pillow 12.3.0,
451
+ which fixes the 25 advisories against 12.2.0) and `requirements-build.txt`
452
+ (PyInstaller) -- and CI and the release workflow both audit them; the release also
453
+ runs `npm audit` and the full spec check, as CI does.
454
+ - The install instructions start from the repository with pip, which works before any
455
+ npm release.
456
+ - The bundled conventions keep to general defaults; a company's own practice belongs in
457
+ a bound knowledge-base document. Numbering reference designators per sheet in
458
+ hundreds, and the text-size ladder, are now defaults.
459
+ - The Skill is now three, on spec v1.6.3's rules for several Skills (SKILL-SPEC §7).
460
+ `xpedition-cli` stays the entry Skill: install, sessions, projects and ChangeSets, the
461
+ write recipe, errors and security. `xpedition-schematic` carries the schematic in
462
+ Designer: drawing conventions, design format, packaging after a draw, review, export,
463
+ pin assignment and footprint mapping. `xpedition-pcb` carries the board in Layout,
464
+ from creating it to the fabrication package, with its conventions, placement,
465
+ hand-routing and fabrication references. Both read the entry Skill first. Three writes
466
+ that discard work or cannot be previewed are now STOP CHECKPOINTs: a confirmed
467
+ `pcb arrange` deletes all routing, `schematic draw` wipes the sheets it redraws, and
468
+ `library kicad-import` overwrites the cells of a partition that exists. The same
469
+ `npx skills add fatecannotbealtered/xpedition-cli -y -g` installs all three.
470
+ - The vendored spec is v1.6.3.
471
+ - Runtime readiness is beta. `reference`'s `release_readiness.reason` says what the
472
+ recorded runs cover, the 2026-09-19 placement smoke included, and what keeps the
473
+ level short of stable.
474
+ - Routing-plan checks skip existing-existing segment and via pairs before
475
+ iteration and avoid repeated tail-list copies. The geometric predicates and
476
+ finding order are unchanged. Incremental edits no longer pay a quadratic
477
+ existing-board pair scan; new-new comparisons still require further indexing.
478
+ - Bounded local query pages stop after one matching lookahead record rather than
479
+ filtering every record. Unfiltered sequence reads slice directly; agent and
480
+ library queries no longer re-filter a materialized result. Matching and paging
481
+ semantics remain compatible, including zero limits and clamped offsets.
482
+ This is not native query pushdown or a COM-session optimization.
483
+ - `agent capabilities` no longer loads a project or requires the selected native
484
+ backend to be operational. Capability discovery now matches its streaming
485
+ counterpart and remains available when a design path is absent or malformed.
486
+ - `analysis run --backend native_xpedition` explicitly rejects the unsupported
487
+ combination before native access instead of running Mock checks on a native
488
+ snapshot. Native stored-result reads still run, but the native snapshot holds no
489
+ analysis results, so they return an empty list. This intentionally
490
+ tightens backend selection; it does not implement a native analysis engine.
491
+ - Confirmation consumption now serializes ledger check/update across cooperating
492
+ processes and threads, atomically replaces the ledger and rechecks expiry after
493
+ locking. Concurrent first-use secret creation no longer races; corrupt secrets
494
+ are rejected rather than silently reused or rotated.
495
+ - Reject alternate base64 token representations that could evade a consumed-token
496
+ fingerprint, non-ASCII signatures and nonfinite or malformed signed expiry data.
497
+ - Preserve the pinned spec's storage-failure degradation, with explicit secret-free
498
+ stderr warnings. Failed replacement preserves the old ledger; unavailable lock
499
+ storage never triggers an unlocked ledger rewrite. Lock contention is a conflict,
500
+ not degradation. This is not a project write lock or exactly-once native execution.
501
+ - The published example design is `examples/demo-sensor-board.json` (and its
502
+ `-kicad` variant with a KiCad footprint map): a generic 5 V / 3V3 sensor board that
503
+ exercises every block kind the planner supports. It replaces the two product-shaped
504
+ designs that were here before.
505
+ - `pcb create --replace` archives the design's existing layout folder to
506
+ `PCB-backup-<timestamp>.zip` beside the project before deleting it, and returns the
507
+ archive's path in `backup`. Deleting a board was the one irreversible operation in
508
+ the tool: the folder holds the placement, the routing, the pours and the output
509
+ setups, and none of that lives anywhere else. Its dry-run preview now says so —
510
+ the old `blast_radius` text described only the folder being created, while the
511
+ `changes` list beside it already said `remove_layout_data`.
512
+ - `pcb trace`, `pcb via` and `pcb arrange` take `--pace SECONDS`: a wait between placed
513
+ items (0 to 10 s) so a person at Layout's screen watches the parts land and the
514
+ routing grow one item at a time; 0, the default, is as fast as Layout takes it.
515
+ - `pcb show` switches the display scheme through Layout's automation
516
+ (`ActiveView.DisplayControl.LoadScheme`, read back from `DisplayControl.Name`) and fits
517
+ the board with `ActiveView.SetExtentsToBoard`; the toolbar combo and button through UI
518
+ Automation remain the fallback, which had started to come back empty on a Layout
519
+ started by `pcb annotate`.
520
+ - `pcb rules` also sets the widths of a class that exists, `(Default)` included: the
521
+ stock class allows exactly one width (minimum = typical = expansion = 0.254 mm), so a
522
+ 0.3 mm ground stub was a TraceWidths hazard until its expansion width was raised.
523
+ - A board whose vias were all deleted lists no via padstack; `pcb via` then pulls the
524
+ central library's first via padstack (`Document.PutPadstack`, `026VIA` here).
525
+ - `pcb pour` lays the plane shape with `bRouteObstruct` false: an obstructing shape
526
+ blocks the autorouter on that layer entirely and, laid over traces that are already
527
+ routed, is refused as a DRC violation. The copper flows around the traces when the
528
+ plane data is generated. The board recipe pours the outer layers after routing.
529
+ - `pcb route` routes a second round after regenerating the planes when a net is still
530
+ open: a pin can be cut off once the copper flows around the new traces.
531
+ - `pcb drc` separates `errors` from `warnings` (`ViasUnderParts` — a via under a
532
+ surface-mount body, normal with tented vias) and says `passes` when there are no
533
+ errors; `clean` still means no hazards at all.
534
+ - The placement planner packs parts 0.6 mm apart (courtyards carry their own margin),
535
+ starts a new row of clusters for every sheet so the sheet labels sit over their own
536
+ clusters, and moves a connector to the other edge when one edge cannot hold its
537
+ column.
538
+ - The converter logs are read more carefully: every `HKP2*` log says "checking for file
539
+ format errors… none found", so only a leading or labelled error word, "cannot add" and
540
+ "N errors" count as failures (the old check on the bare word flagged nothing in the
541
+ Chinese logs and would have flagged everything in English ones).
542
+ - `session start`, `attach`, `open` and `stop` are declared by `reference` and pick their
543
+ target application with `--kind pcb|layout|schematic|designer`. Three of them were already
544
+ implemented but undeclared, so no agent reading `reference` could find them, and every one
545
+ of them silently targeted Layout — Designer was unreachable. `session stop` quits the
546
+ application, so it now goes through the dry-run/confirm gate; `native_session_lifecycle` is
547
+ no longer reported as a planned domain.
548
+ - The adapter suppresses Layout's modal dialogs on every attach (`SuppressTrivialDialogs`,
549
+ `SuppressNotepadDialogs`, `SuppressVariantDataOutOfDateDialog`, `SingleThreaded`). An unattended agent cannot answer a
550
+ message box, so a dialog raised mid-operation turns a COM call into a hang. Dialogs raised
551
+ while the application is still starting up happen before automation exists and are out of
552
+ reach — attach to an already-running instance to avoid them.
553
+ - Hardened output redaction, operation-bound confirmation scopes, pagination metadata, and native capability reporting.
554
+ - NativeBackend now discovers the installed adapter, reports the actual COM-registration state,
555
+ and routes verified reads and ChangeSet writes through the adapter.
556
+
557
+ ### Fixed
558
+
559
+ - The plan-time checks for a covered wire end and for unreadable edge pin names reported
560
+ as DS-09 and DS-10, ids the checklist gives to the refdes-prefix and part-number
561
+ checks, so a reviewer looking an issue up found a different rule. They are DS-15 and
562
+ DS-16 now, with a row each in the checklist, and a test holds every id the planner
563
+ emits to a checklist row that names that dry-run issue.
564
+ - `changelog` returned only part of a release's entries: a release that repeats a heading
565
+ kept only its first section, and an entry lost its continuation lines.
566
+ - `manufacturing bom` ignored `--limit`, `agent review` ignored `--limit` and
567
+ `--offset`, and six query commands paged without declaring it in `reference`.
568
+ - Design text holding a double quote or a line break could write records of its own
569
+ into the generated HKP library files; it is refused now. The same holds for symbol
570
+ files, and a KiCad footprint whose text cannot be quoted is skipped with an issue.
571
+ - A symbol name or a symbol partition in a design file named a file path:
572
+ `../../../ESCAPE` would have been written outside the library's `sym` folder, and the
573
+ partition also into the `.prj`. Both are plain names now, and the adapter writes a symbol
574
+ file only inside its folder.
575
+ - `--limit` and `--offset` on a command that does not page were ignored -- `bom validate
576
+ --limit 1` returned every issue -- and are refused now. Review pages carry `count`, and
577
+ every paged command declares its `default_sort`.
578
+ - `doctor` suggested COM registration when the configured adapter file was missing; it
579
+ now names the fix for the reason the backend gives.
580
+ - `pcb trace --dangerous` and `pcb via --dangerous`, which skip the offline clearance
581
+ check, were refused by a global check and could not be used.
582
+ - A pip install that is not editable -- the one the README now leads with -- answered
583
+ `reference` with `E_UNKNOWN` and `changelog` with nothing: the wheel held neither
584
+ contract/contract.json nor CHANGELOG.md. `setup.py` now carries both into the package,
585
+ and neither command falls back to a file in the working directory, which would be
586
+ another project's.
587
+ - The tests run against their own configuration directory; some had been writing audit
588
+ records into the developer's `~/.xpedition-cli`.
589
+ - README said the release level was `stable` (it is `beta`) and listed a
590
+ `schematic plan` command that does not exist.
591
+ - A KiCad footprint that gives one number to several lands keeps them all (#28): each
592
+ becomes a pad of that pin, and forward annotation puts them on its net -- measured
593
+ with a 2x2 mm TDFN MOSFET whose drain owns four leads and the paddle. Only a pad
594
+ inside a larger one of its number (a thermal via) is dropped, now reported as
595
+ `inside_same_number`; two overlapping rectangles make an L-shaped land.
596
+ - A running Designer read as absent after a temp cleaner emptied win32com's
597
+ generated-wrapper cache (`has no attribute 'CLSIDToClassMap'`). The adapter
598
+ removes such entries before it attaches, and an attach failure now says what
599
+ failed instead of only "not found". Designer is bound through its generated
600
+ wrapper, created if missing: late-bound, `project init` failed on
601
+ `Documents.Open` ("parameter not optional"), which a fresh machine would hit too.
602
+ - `session stop` reported the application closed while a dialog a timed-out call had
603
+ left up held its `Quit`. Known questions are answered while it quits, and an
604
+ application still running afterwards is an `E_CONFLICT` naming the dialog.
605
+ - A draw that failed inside the adapter itself -- a sheet it could not make active --
606
+ reported no sheet or index; every draw failure now carries them.
607
+ - The `schematic_draw` output schema declares `sheets_drawn`, `sheets_not_drawn` and
608
+ `sheets_kept`, and the dry run's declares `operations`.
609
+ - Every confirm example in `reference` repeats the arguments of a dry-run example. The
610
+ token is bound to them, so the `pcb route`, `outline`, `rules`, `export`, `holes`,
611
+ `labels`, `create`, `trace`, `unroute` and `library build` examples failed with
612
+ `E_CONFLICT` when copied; a test now holds every command to it. `pcb arrange` declares
613
+ in its blast radius that it deletes every trace and via on the board first.
614
+ - `library build --dry-run` reports a cell pad that no symbol pin reaches. The pin check
615
+ ran one way only -- every symbol pin needed a cell pin -- so a cell with *more* pads
616
+ than the symbol has pins passed clean. A power MOSFET in DFN or PowerPAK carries
617
+ several pads per electrode and a drain paddle, so its converted cell had seven pads
618
+ against a three-pin symbol and the preview reported `issues: []`: a library that looks
619
+ built and is not. The unmapped pads and both counts are named.
620
+
621
+ - DS-07 checks the area a design may draw in rather than only the border. The sheet
622
+ title strip and the notes band are placed by the planner itself, so those are computed
623
+ from `MARGIN` and the note count; the border symbol's own frame and title block are
624
+ measured per sheet size (A4 and A3 recorded, others fall back to the computed area).
625
+ A sheet used to pass with `issues: []` while a whole stage was drawn through the notes
626
+ and two capacitors sat on the title block. The plan publishes the rectangle per sheet,
627
+ so a caller can lay out against it instead of measuring a rendered export.
628
+
629
+ - `--dry-run` and `--confirm` are refused on a command that is not a guarded write,
630
+ instead of being accepted and ignored. `schematic export` renders a PDF and has no
631
+ gate, so a dry run wrote the file and the next one failed because it already existed.
632
+ The reference already declared which commands the gate applies to; now it is enforced,
633
+ and probing a command that has no gate says so rather than performing the write.
634
+
635
+ - A design collection that cannot be read names the state that caused it. Two ordinary
636
+ mid-design states both surfaced as a bare `DesignComponents` type mismatch, stopping
637
+ `review run`, `bom export` and `schematic components` at once: a schematic changed
638
+ since the last `library build --package`, and a sheet added or removed, which needs the
639
+ project reopened instead. `GetActiveDesign` reporting the schematic rather than the
640
+ block separates them, so the error now carries the likely cause and the one command
641
+ that clears it. Being unpackaged is a normal state to be in, not a failure.
642
+
643
+ - A part's reference designator and value start where the plan puts them. Designer's
644
+ attributes carry a `VdOrigin` saying which corner of the text sits at the location, and
645
+ a symbol leaves its refdes at `VDALIGN_MR` -- middle *right* -- so setting a location
646
+ put the text's right edge there and the string ran back its own width. A 17-unit refdes
647
+ against the planner's +12 offset landed on the part's own centreline, on every part of
648
+ every drawn sheet. The planner now states the left-anchored origin it means.
649
+ - `project init --template` gives every user symbol partition a parts database instead of
650
+ leaving Designer to raise a modal dialog at draw time, which blocks the draw until a
651
+ human clicks. A missing one is filled by copying an unused stock database out of the
652
+ project's own library, and only when at least two unused databases are byte-identical --
653
+ enough to tell an empty database from a populated one rather than guess. A library where
654
+ that does not hold is reported in `parts_databases.missing` and left alone.
655
+ - `schematic draw` reports `sheets_drawn` and `sheets_not_drawn`. A draw wipes and redraws
656
+ the sheets its design names; any other sheet keeps what was on it, which for a cloned
657
+ project is the template's content and used to ship unremarked.
658
+ - A timed-out native call marks the session stale, and the next task command reports that
659
+ instead of failing somewhere unrelated. After a read timed out, `IsProjectOpened()`
660
+ reported false with the project still open, so the next command asked Designer to open a
661
+ project it already had and was refused with a message about scripts and GUIs. Recovery
662
+ commands (`session status`, `start`, `stop`) still run against a stale session.
663
+ - `_ensure_project` reads the open project's path whatever `IsProjectOpened()` claims, so
664
+ a project that is already open is not reopened, and product code 64185 maps to a
665
+ conflict naming the state that refused the request rather than a retryable server fault.
666
+ - A symbol that displays the same pin name twice is refused when the plan is built,
667
+ naming the repeated names and the pins that share them. Designer names a net after
668
+ the pin a wire meets, so repeated pin names put two wires on one auto-named net and
669
+ the second explicit label made the draw stop with 6035 "Net already labeled" minutes
670
+ in and partway through. Renaming automatically is not available: the pin's `L` record
671
+ is what the parts database maps to cell pin numbers. Give each pin a distinct name and
672
+ keep the shared net on the wire's label, which is what the netlist already uses.
673
+ - `session stop` quits the application that is attached rather than defaulting to pcb.
674
+ Quitting discards unsaved design work, and with only Designer running the old default
675
+ reported success against an application that was not there while leaving the one the
676
+ caller meant still running. The domain is resolved from the live session; both attached
677
+ is a `E_USAGE` asking for `--kind`, an explicitly named application that is not running
678
+ is `E_NOT_FOUND`, and the preview's blast radius now names the application instead of
679
+ saying "the running Xpedition application". Machines with no adapter to probe keep the
680
+ previous behaviour.
681
+ - `session start --kind schematic` starts Designer through `common\win64\bin\viewdraw.exe`
682
+ rather than the product under `wv`. The common launcher sets up the release environment
683
+ before starting the product; naming the product directly skipped that and the process
684
+ exited immediately with STATUS_DLL_NOT_FOUND (0xC0000135), so every native schematic
685
+ command was unusable unless someone had already started Designer by hand. The pcb domain
686
+ always went through the launcher and the comment above the code already stated the rule.
687
+ - A missing Xpedition automation-licensing call is classified from its EXCEPINFO
688
+ numbers (product code 10279, scode `0x8004022D`) instead of by searching the COM
689
+ description for "license". On a localised installation the description carries
690
+ neither that word nor "token" — a Chinese session reports 自动化代码不包含身份验证
691
+ 所需的许可调用 — so the fault was reported as a retryable `E_SERVER` and an agent
692
+ would retry it indefinitely. It is now the non-retryable `E_AUTH` it always was.
693
+ Observed on XPED2604; ordinary faults such as `DISP_E_TYPEMISMATCH` arrive without
694
+ this EXCEPINFO and keep their existing classification.
695
+ - The reference-query test reads `contract/contract.json` as UTF-8 rather than with
696
+ the locale codec, so the suite no longer fails on a GBK Windows machine. The
697
+ hosted runners default to UTF-8, so CI could not observe this.
698
+ - Explicit NativeBackend project initialization without a template fails before
699
+ preview, token consumption or file creation; it never creates a mock project.
700
+ - Native ChangeSet results verify the requested final coordinates, properties,
701
+ part identities and connectivity against read-back instead of hardcoding
702
+ verification success. Missing observations or unsupported verification fail
703
+ closed; post-write read-back failures are non-retryable and report the stage.
704
+ Read-back is not a durability or electrical-correctness claim.
705
+ - `--fields` projects records inside arrays without changing their order or
706
+ cardinality. Paging controls and `_untrusted` annotations survive projection;
707
+ parent/child selectors are order-independent. Missing fields retain legacy
708
+ omission semantics; no post-write selector error is introduced.
709
+ - `reference` derives confirm/dry-run applicability from write-command metadata.
710
+ - Three things the first CI run found, none of which a Windows workstation could
711
+ show: `_layout_board_path` could not resolve a board off Windows, because a `.prj`
712
+ stores its relative board path with backslashes and those are ordinary filename
713
+ characters elsewhere; `pcb render`'s tests were skipped-by-crash wherever Pillow
714
+ was absent, since Pillow sat only in the `native` extra while the renderer is pure
715
+ Python (it is now in `dev` too); and a test encoded its fixture with `mbcs`, which
716
+ does not exist off Windows and cannot represent Chinese on a Windows runner whose
717
+ code page differs.
718
+ - The contract tests no longer depend on what is installed on the machine that runs
719
+ them. NativeBackend finds its adapter through `XPEDITION_NATIVE_COMMAND` or through
720
+ `xpedition-native-adapter` on PATH, so on a workstation with the native extra the
721
+ backend really is available and the write-gate test saw a successful snapshot where
722
+ it asserts `E_BACKEND_UNAVAILABLE`. The suite now points the variable at a path that
723
+ does not exist.
724
+ - `session start|attach|open|stop --backend native_xpedition --kind bogus` reports
725
+ `E_VALIDATION` again instead of `E_BACKEND_UNAVAILABLE`: the kind is validated before
726
+ the adapter is asked for, because a malformed flag is a usage error whether or not an
727
+ adapter is installed.
728
+ - Grid snapping rounded half-way values to the even side (Python's `round`), so a
729
+ column on a 2.5 mm step landed alternately high and low; they now always go up.
730
+ - `pcb create --replace` could not remove the old layout folder after an NC drill run:
731
+ Layout keeps `LogFiles/DrillPrefs.txt` open after the document closes, and
732
+ `Application.Quit` leaves it on its start page still holding the file. A Layout
733
+ with no document open is now ended by its process when the folder stays locked,
734
+ and the next step starts it again.
735
+ - `pcb export` runs the output dialogs a second time when one of them wrote its own
736
+ settings back over the patched setup file (the ODB++ job came out without its
737
+ drill layer once); the result says `rounds`.
738
+ - Fixed shared ground bars for several bottom-edge ground pins: the ground symbol now sits on
739
+ the bar's free end, where Designer connects it, instead of on the corner where it did not.
740
+ - The board ChangeSet operations called `Component.Place` and `Component.Move` with the
741
+ wrong arguments: `Place(x, y, orientation, bTop, eFixType, eUnit, eAngleUnit)` takes
742
+ "top side" where a mirror flag was passed, and `Move(x, y, eUnit)` was given no `y`.
743
+ Both now take an optional `unit` (`mm`, `mils`, `inch`, `um`; the document's unit by
744
+ default).
745
+ - `pcb arrange` measures a placed part unturned: Layout reports the extents of a part as
746
+ it stands, so a connector standing at 90° from the previous arrangement came back
747
+ 5.5 mm wide and 10.9 mm tall and the next plan turned it again, onto its neighbour.
748
+ - `pcb route` regenerates a plane it finds in Draft instead of skipping it: the GND
749
+ plane of the board on KiCad footprints was back in Draft after its pour had been
750
+ saved, and Batch DRC reported the ground net partial with its vias dangling.
751
+ - The CLI and the native adapter now exchange UTF-8 on their pipes regardless of the console
752
+ code page. On a Chinese Windows the parent decoded the adapter's output as GBK and crashed in
753
+ its reader thread, so every native error surfaced as `E_UNKNOWN`/`TypeError` instead of the
754
+ adapter's structured error.
755
+ - Session liveness no longer probes with `os.kill(pid, 0)` on Windows. `signal.CTRL_C_EVENT`
756
+ is 0 there, so CPython routed signal 0 to `GenerateConsoleCtrlEvent`, which takes a process
757
+ *group* id: it reported every running Xpedition process as dead and made `doctor` warn
758
+ "recorded native process is no longer running" against a live session. The probe now uses
759
+ `OpenProcess` plus `WaitForSingleObject`.
760
+ - Native Designer snapshots return component coordinates again. `GetLocation` is a property
761
+ on current Xpedition Standard, not a method, so calling it yielded the point's default
762
+ member and every `x`/`y` came back as null.
763
+ - A native schematic placement whose reference-designator assignment fails now reports the
764
+ symbol it left on the sheet — `orphan_placed` with library, device, symbol and coordinates —
765
+ instead of failing silently with the instance still present. The API exposes no delete
766
+ entry point, so the orphan has to be removed in Designer.
767
+ - `doctor` reads `release_readiness` from its single source instead of restating it. The
768
+ hardcoded copy went stale the moment the smoke evidence changed, and `doctor` is what an
769
+ agent checks first.
770
+ - Native schematic reads resolve net names and connections. A Designer net carries no
771
+ `Name`; the name lives on the label attached to one of its segments
772
+ (`net.GetLabel(segment).TextString`), so reading `Name` reported every net on a live
773
+ sheet as unnamed and left `connections` empty.
774
+ - Native schematic placement no longer defaults the library to `MISC`. No such library
775
+ exists in a stock installation, so a missing parameter surfaced only as Designer error
776
+ 2005 in the message window; the adapter now names the missing parameter instead.
777
+ - Native Designer reads return component pins again, and a schematic net can be labelled.
778
+ `GetConnections` and `GetSegments` are properties on current Xpedition Standard, not
779
+ methods; calling them raised DISP_E_PARAMNOTOPTIONAL inside a bare `except`, so every
780
+ snapshot reported `pins: []` and `connect` failed to find a pin by number. A shared
781
+ `_com_member` helper now reads either form, and a net that cannot carry its label fails
782
+ loudly instead of silently.
783
+ - `CO_E_SERVER_EXEC_FAILURE` from COM activation is reported as `E_BACKEND_UNAVAILABLE` with
784
+ a launcher hint. Xpedition `LocalServer32` entries point at binaries that need the release
785
+ environment established by the launcher in `common/win64/bin`, which COM activation skips.
786
+ - Native schematic reads no longer fail on every real design. `normalise_project` required a
787
+ reference designator on every component and a name on every net, which is right for an
788
+ authored project file but wrong for observed data: a live schematic always carries ground,
789
+ power, port and border symbols that have none, and a single one of them made `design
790
+ snapshot` and all nine `schematic *` commands return `E_PROJECT_INVALID`. Observed data now
791
+ separates those out and records a count under `metadata.unnamed`; authored files stay
792
+ strict.
793
+
794
+ [Unreleased]: https://github.com/fatecannotbealtered/xpedition-cli/compare/v1.0.0...HEAD
795
+ [1.0.0]: https://github.com/fatecannotbealtered/xpedition-cli/releases/tag/v1.0.0