Known rough edges
Small defects and unfinished corners that are worth knowing about before working near them, and that are too minor to have their own page. Each was checked against the code, not inherited from an older list. Design-level limitations of the parameter system are in parameterSystem.md instead.
Delete an entry when it is fixed. A list that keeps its history stops being read.
Parameters
-
*
ParameterAnalysis.chainActionsOnSheetpicks the wrong declarer.*Set.minElement declarersis the alphabetically first sheet that declares the parameter, not the outermost one. The default value and the description copied onto the intermediate sheets of a materialised bind-to-top chain therefore come from an arbitrary sheet. Worse,BindOffer.BindsToprefers the top sheet where it declares the name, so the button can say "connect this to TOP.width" while copying the default and description from a different sheet entirely. -
Deleting a parameter checks slots but not other parameters.
ParameterView.deleteParameterBoxlists theParamSlotsthat use the parameter and refuses while any remain, but does not look inDefaultBindings, so a parameter defined in terms of another can be orphaned. Only reachable through a hand-edited file today, since the UI writes onlyPIntdefaults — buteditParameterBoxhandles expression-valued defaults, so the system claims to support them. -
*
ReloadSelectedComponentis fed the wrong number.* For aBusSelectionLSB or aBusComparevalue it receives that number as "most recent bus width", which is what the properties pane then offers as the default width for the next component.
Wire routing and separation
How these two passes are meant to work is in wireRouting.md.
-
*
stringon an[<Erase>]id means two different things.*InputPortId,OutputPortIdand friends are erased by Fable, sostring portIdis the bare id in the app andInputPortId "…"under .NET.BusWireRouteused it for fivemodel.Symbol.Portslookups, which therefore threw in any .NET test that routed a wire; those are nowinputPortStr/outputPortStr. Nothing checks for the pattern, and the same trap is open wherever an erased id meetsstring,sprintfor an interpolation. -
*
removeWireSpikesandremoveModelSpikeshave no callers.* Spike removal is written, exported and never run:separateAndOrderModelSegmentsends withremoveModelCornersand nothing calls the spike pass. Either the artifact it removes no longer occurs, in which case delete it, or it does and the pass was dropped by accident. -
*
hasOverlapandhasNearOverlapeach have a clause that can only fire on exact equality.* Both writeb1.MinBwhere the third argument should beb1.MaxB. Harmless — the other two clauses already decide overlap in every case — but it reads as if it were load-bearing. -
*
makeClusterscalls the head of a descending-sorted listlowestLoc2Index.* It is the highest index, so the test that follows it is not the "did the downward search fail to reach the starting segment" check it appears to be. It errs towards the branch that splits off a second cluster, which is the safe one. -
Zero-length segments turn up in the middle of wires. They belong beside a nub, where they
make the first visible segment draggable, and nowhere else: a zero segment mid-wire is two
coincident vertices - a vertex that is not a vertex - and a separation move which crosses one
draws the wire back over itself. Redrawing
reg16x8from the3cpufixture leaves 3 of them and one such spike, with or without same-net branching, so ordinary routing and separation produce them too.removeWireSpikeswas written to clean up after this and is called from nowhere; removing the cause is better than calling it. -
Dead code kept alive.
snapToNet(andcopySegments,generateEndSegments, which serve only it) was the first attempt at whatsameNetRoutesnow does, and is still there and still unreachable — it only ever handled 5 or 7 segment unrotated wires and copied from whichever wire of the net came first out of aMap. It should go.expandClustercomputeslowestDownwardsIndexfor a guard that is commented out.adjustSegmentsInModelbindsOption.get line.Seg1and never uses it. The doc comment onConstants.separateCaptureOverlapdescribesmaxCornerSize.
Component libraries
-
A typed library name becomes a directory name unchecked.
MiscMenuView.saveAsLibraryComponentjoins the user's text onto the libraries directory with no validation beyond non-empty, so a name containing a path separator or..writes outside the intended directory. Sheet names are validated bymaybeWarning; library names are not. -
Name collisions have no rule.
CustomComponentType.Namerefers to sheets by name, so a libraryAdderand a userAddercannot coexist in one project. Namespacing or rename-on-import is the missing piece. -
Sweeping a library sheet leaves its backups.
MenuHelpers.sweepUnusedLibrarySheetsremoves the.dgmwhen the last instance goes, but the sheet's files underbackup/stay. - A copied-in library sheet does not track the library. Once materialised it is an ordinary project sheet and never sees a later version of the library component. This is probably what is wanted, but it is nowhere stated to the user.
Refactoring worth doing
-
SheetLayout.saveSheetandsheetBodyare the same function twice, differing only insaveStateToFileversusstateToJsonString; both also evaluateparamDefsOfa second time aftertoCanvasStatehas already done it. -
"The custom components named in a canvas" is written three times:
ComponentLibraries.customSheetsUsedBy, the sameList.chooseinline inComponentLibraries.unusedLibrarySheets, andSheetLayout.saveLibraryComponent'srequiredBy. -
LibraryHeaderis built field by field in bothMiscMenuView.saveAsLibraryComponentandSheetLayout.saveLibraryComponent. The format is versioned, so the two writers drifting matters. -
MiscMenuView.maybeWarningcallsComponentLibraries.reservedPrefixOftwice and then uses.IsSome/.Value, against theOption-throughout convention. -
FilesIO.modifiedTimeMshas no callers. It was written for a library-index scheme that was dropped in favour of lazy reading. -
VerilogComponent/TestParser.fs(937 lines) is a hand-driven test runner that compiles into the shipped renderer, reads paths that exist only in a dev checkout, and keepsprintfon theSourceHygieneallowlist. It should go once its corpus runner is in Expecto — see verilogTesting.md.
Documentation
-
The screenshots on the documentation site are a version behind.
docs/img/homePage/*anddocs/img/userGuide/*show a Sheets menu and an Electron application menu bar that no longer exist — the bar is nowProject | Sheet | Edit | View, drawn inside the app. The workflows are unchanged, so they are still usable.scripts/inspect-canvas.jscan screenshot the running app, so a refresh can be scripted rather than done by hand.