Repository navigation
Generated fasteners for FRC and FTC, part sets, and the Onshape workflow - #24
Merged
Merged
Conversation
…for FRCDesign quickFastener/quickFastenerTables.py is the one source of FRCDesign's Quick fastener catalog: FRC (#6-32 to 1/4-20) and FTC (M3, M4) screws in socket, button and flat heads, flat and wide washers, and nylock and hex nuts. fs gen writes the features' enums and dimensions, and quickFastener.gen.json, the manifest FRCDesign pins to a tag and reads its catalog, configurations and hole scan from. Each part is a Part Studio exposing its feature through a List input per parameter, Length showing only the lengths the chosen size comes in. fs configure-studio writes that configuration and configures the feature by it (fs_cli/configured_studios.py), so the FeatureScript and the configuration can't drift. A screw's and nut's Washer input moves only its one mate connector onto the washer it sits on, so FRCDesign fastens every part to the hole's own edge without mate offsets. quickFastenerHoleScan.fs is the lambda FRCDesign evaluates in a Part Studio to find its parts' holes and the selected circles; its body is copied into the manifest, so it keeps to std's common.fs. Definitions can now set EXPORTS, files fs gen writes beside them. Untried in Onshape: the features' geometry, the configuration payloads, and the hole scan's evaluation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
FRCDesign fastens a nut, or a screw into a blind hole, to the edge at that end of the hole, so it needs the edges' ids. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
The screws, nuts and washers are now the ones FRCDesign's FRC library already offers (vendor/frcdesign-fasteners.json, a snapshot of its configurations), with their part numbers: McMaster-Carr, REV and WCP black oxide screws from #4-40 to 1/4-20, McMaster-Carr's nuts, and black washers, plus Generic, which offers every length anyone makes. Each studio has a Vendor input. Length is an enum of the 49 standard lengths, offered only where the chosen vendor makes that size and head; the feature errors on anything else. Washer is a checkbox, which moves the mate connector onto the vendor's seat washer. Configured studios can now have checkbox inputs, and show a List's options by combinations of several earlier inputs. FTC comes out until its list is decided. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
…est, library releases The screw and nut studios lose their Washer input and the seat washers behind it: FRCDesign fastens a screw or nut to the top edge of the washer it inserts under it, so any washer fits and the mate connector stays at the origin. The manifest carries each studio's configuration as Onshape answers it, so FRCDesign parses it with the parser it uses on any configuration. List visibility conditions are factored by input, which takes the screw studio's from 192 KB to 61 KB. `[tool.fs.libraries]` names library documents: the FeatureScripts in their folders are released to the library's default workspace instead of the frontend document, may define several features, have no betas, and are left out of `fs sync-versions`. Quick fastener releases to FRCDesign's Fasteners library. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Run in Onshape, the hole scan failed whenever a face or circle was selected: `transientQueriesToStrings` names only transient queries, and `qOwnerBody(edge)` isn't one, so it came back as a map where a string was declared. The scan now evaluates the owner body first. Also tried in Onshape: every kind of screw, washer and nut regenerates with its mate connector at the origin, and the scan reports through and blind holes as the planner expects. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
FRCDesign's Fasteners group has only #10-32 screws from WCP, one of them under a part number WCP no longer lists (its 3/4 in. button head is now WCP-0135). WCP's and AndyMark's screws now come from their Shopify stores' product lists, snapshotted in vendor/stores.json and refreshed by `python quickFastenerTables.py fetch`, replacing the group's for those vendors: WCP's #8-32, #6-32 and #4-40 screws, and AndyMark's #4-40 to 1/4-20 socket, button and flat heads, each with its part number and page. A store screw without a thread lock patch is preferred where both are sold. AndyMark is a new vendor; 2-1/8 in. a new length. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
…eners They're the library's new fastener, which Quick fastener inserts too, not Quick fastener's own: the folder is `fasteners/` (`fasteners.fs`, `fastenerTables.py`, `fasteners.gen.json`), the features `fastenerScrew`, `fastenerWasher` and `fastenerNut`, named Screw, Washer and Nut. The hole scan keeps its Quick fastener name, since only Quick fastener evaluates it. The writeup now says what the dialogs already are: flat enums with no conditions, wired one for one to configuration inputs whose visibility conditions show only what's made. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
The fasteners are generated for FRCDesignApp, which inserts them from the library and into assemblies; nothing here belongs to Quick fastener. The hole scan is `fastenerHoleScan`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
…xing `fastenerTables.py` now names each screw, washer and nut, with its vendor, part number and link, as a `Record` per configuration. The tables carry them, so the features set exactly these properties (now with Vendor too), and the manifest lists them per studio, so FRCDesignApp indexes the generated records rather than asking Onshape about each configuration. `ConfiguredStudio.combinations()` enumerates what a configuration offers, and each studio's records are tested against it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
…dor sells them A screw's Variant chooses among what its vendor sells beyond the standard: zinc plated (McMaster-Carr, REV), aluminum (WCP), or fully threaded (McMaster-Carr's long socket heads, whose standard is partly threaded). A washer's Finish chooses plain stainless steel over black where McMaster-Carr sells both. Each input is hidden wherever only the standard is made, Generic included, and a hidden input is left out of the records, as FRCDesignApp enumerates it. Parts take their material and their finish's appearance from the records. ConfiguredStudio inputs can now be shown for some combinations of earlier inputs (Onshape's visibilityCondition), as their options already could. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
`fs build-studios <definition>` builds each of a definition's configured Part Studios in the backend document, to try them: it finds the tab by name or creates it, writes its configuration, and inserts its feature from the pushed Feature Studio beside the definition (or points the one it has at it), configured by it. A feature failing to regenerate in its default configuration stops the build. A library release builds them the same way in the library document, from the studio it just pushed there, then always versions the library and records where each Part Studio is in `<definition>.studios.json`, writing the definition's exports again. The fasteners' manifest takes its locations from there, in place of LOCATIONS. `fs configure-studio` is gone: nothing is made by hand. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
…g Onshape The fasteners go straight to their library document, so the backend-document `fs build-studios` is gone; `fs release` builds them there. AGENTS.md now says to ask before every call to Onshape: the FeatureScript MCP's tools and every fs command that talks to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
The screw's Variant is split in two. Finish is an enum between Head and Length, always shown and offering what's made in the size and head (Generic's only black), so Length shows the lengths made in it. Fully threaded is a checkbox at the end, shown only where a length is sold both ways. A screw's table entry holds its standard part and, there, its fullThread one. Length's conditions are factored by Finish first (ConfiguredStudio factor_first), which keeps the screw's configuration at 170 KB rather than 221 KB. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
The stores snapshot now holds only products that are catalog screws, which fetch keeps by the same parse the catalog uses: no listings shipped from Sydney, metric or self-piercing screws, or WCP's Kraken spares, whose IP8 drive isn't a hex socket. AndyMark's am-1754, zinc plated by its url, is now the zinc plated 1/4-20 x 3/4 in. button head. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
FeatureScript-backed parts are now part sets ([tool.fs.parts.<set>]: a title, its folder, and the FRCDesignLib document it's released into), in place of library documents. Their FeatureScript stays in the backend document, so pushing, checking and core imports work as before, but they have their own commands and versions: - `fs parts test <set>` builds each Part Studio in the backend document as `<Part> (TEST)`, from the FeatureScript as pushed, to try a change. - `fs parts release <set>` versions the backend (`Fasteners - v1.2.0`), points the main document's Feature Studio at it, builds the Part Studios there, versions the main document, records where they are, writes the definition's exports again, and tags the release. `fs release` refuses a part set's FeatureScript, and `fs sync-versions` leaves its versions out. docs/parts.md describes the flow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Pushed fasteners/fastenerHoleScan.fs Pushed fasteners/fastenerTables.gen.fs Pushed fasteners/fasteners.fs Pushed gear/gearCommon.fs Pushed gear/robotGear.fs
…ape refused
Inserting a fastener's feature answered 409 ("the feature list becoming
invalid"). Its enum values (FastenerVendor, ScrewHead, ...) are defined in
its FeatureScript, but were sent with no namespace; they now name the
feature's. A build that Onshape refuses now says which step it refused
(creating the tab, writing the configuration, or inserting or updating the
feature) and in which Part Studio.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
…nto claude/zealous-shannon-e0iklk
…ape kept the inputs' ids A refusal now names which of the two feature writes Onshape refused, and a configuration whose input ids or enum names Onshape changed fails before anything names them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
…cosmetic threads with hole attributes Screws get a 45 degree tip chamfer, socket heads a top chamfer, flat heads their band, and button heads a short side, a dome and a flat top, in McMaster-Carr's proportions. Each screw's shank carries std's external thread attribute and a cosmetic thread, 2D + 1/2 in on a standard socket head and to the head otherwise; each nut's bore is the tap drill, tapped through as std's Hole does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Writes each studio's configuration in stages to a scratch (DIAGNOSE) Part Studio, stopping at the first Onshape refuses, and lists the features in its (TEST) tab. Onshape refuses the screw's whole configuration with a 409, and its message doesn't say why. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
…-length variables FRCDesign's bolt Part Studios give each screw's threaded length as configured variables (BO_ThreadedLength and so on), which its group snapshot doesn't carry. This saves them, from the versions the snapshot names, for the tables to read offline. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
… threaded is a switch
Onshape refuses any visibility condition but an AND of inputs, each one of
some values, with a 409 ("The change would result in the feature list
becoming invalid"), which fs parts diagnose found on the screw's first option
rule. Each option's combinations are now factored into such conditions, one
rule per condition, several of which may control an option; a List's own
visibility is folded into its options', since a List with none shown is
hidden. A checkbox shows by one condition, which the studio checks, so the
screw's Fully threaded, which needs five, is a switch: a List of false and
true setting the same boolean parameter.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
FRCDesign's threaded lengths will be copied in from its tables instead of read from Onshape. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
…e stores it Onshape still refuses the screw's first option rule, now in the shape its UI makes; one made in its UI shows what differs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
… rest always A configuration made in Onshape's UI ends its option rules with one showing every option always: Onshape hides an option no rule controls, so the screw's first rule, which left its default #10-32 to none, made the feature list invalid. Each List's options no condition controls now get that rule, and each equality says inArray, as Onshape writes them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Alone, an input's first rule can hide its default in the default configuration, which Onshape refuses: finish's did, with Black shown only for AndyMark. Size and head show the rules themselves are accepted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Names and options spell inches "in", as Onshape does. The screw and the washer took one FastenerFinish, so the screw's own dialog offered Stainless steel, which no screw comes in; ScrewFinish and WasherFinish keep the same option ids. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Onshape refused the screw's configured parameters: "Parameter with parameterId vendor ... has configured values using parameters that are assigned parameterId values". Only the configured parameter names it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
It's on main (ca8ee75), against main's reworked custom frames; this branch's version was written against the frames before them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
goBILDA's M4 screws, nuts, and washers and REV's M3 ones, with each part's dimensions read from the vendor's STEP model, what the fastener features need to offer them, and the few models still missing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
FRCDesign renamed ftc-design-lib to config-lib, so `-l ftc` was refused as an invalid library. It's `-l config` now. The FTC fastener catalog gains what ConfigLib's teams insert, which sets its defaults. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
AndyMark's metric screws, nuts, and lock washers from its store's product list, and McMaster-Carr's series, whose part numbers have to come from its pages by hand. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Where usage doesn't pick, a part's vendor and finish default to the lowest price per piece: goBILDA for M4, AndyMark for M3 so far. Records the prices behind that, how McMaster-Carr's supplies are chosen between, and that its metric tables and REV's per-length prices are still needed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
…f 250 or fewer McMaster-Carr's zinc-plated Class 8 nylocks are the cheapest M3 and M4 ones per piece, so they're the defaults. Packs over 250 don't count toward the cheapest, since a team doesn't buy 2,000 nuts to save a fraction of a cent each. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Price orders only the finishes within a vendor, by the piece in its smallest pack. Vendors go Generic, McMaster-Carr, goBILDA, REV, AndyMark; goBILDA stays behind McMaster-Carr, whose nuts cost less. Generic covers screws and washers, not nuts, as for FRC. Adds McMaster-Carr's hex nuts and stainless M4 nylocks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Its socket heads in zinc-plated and black-oxide alloy steel and 18-8 stainless, every length and supply, and its nylocks and hex nuts in the three finishes, go in vendor/mcmaster-metric.json for the generator, in place of the doc's tables. 18-8 is McMaster-Carr's cheapest socket head, or within two cents, and sold in the most lengths, so it's the screws' default finish. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Its button heads in the three finishes join the snapshot, with the head dimensions measured from the models it publishes, which agree with its tables. Stainless goes first for them, as for its socket heads. Low profile socket heads are left out: under 1% of ConfigLib's M4 inserts, and a button head is lower on the same hex key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Its hex-drive flat heads in the three finishes join the snapshot, with the M4's head measured from its model. Black oxide is the cheapest flat head at every common length, so it goes first. A metric flat head sits in a 90 degree countersink, where the FRC features assume 82. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Its general purpose M4 washers in the three finishes join the snapshot, and its models of an M4 hex nut, nylock and washer give their shapes: the nylock's hex height and insert bore replace the proportions FRC's nylocks are drawn from. McMaster-Carr's washers cost less than goBILDA's too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Lock washers are left out, a nylock or thread locker doing the job. REV's M3 washer, which it publishes no dimensions for, is taken as a standard ISO 7089 one. Prices only order finishes and pick McMaster-Carr's supply, and go into no part's records, so REV's per-length prices aren't needed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Its general purpose M3 washers in the three finishes join the snapshot, taken as ISO 7089's 0.5 mm thick. Stainless is the cheapest M3 washer, and a black one black-oxide 18-8, which costs less than its black-oxide steel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Both are DIN 934 M3 nuts of the same size, so nothing is still needed from a vendor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
… own FTC's M3 and M4 parts from McMaster-Carr, goBILDA, REV and AndyMark are FRC's Screw, Nut and Washer features and tables, offered by Part Studios of their own: ftcFastenerTables.py configures them from fastenerTables.py's FTC catalog and writes their manifest, ftcFasteners.gen.json. Each set's studios offer its own sizes, so FRC's manifest is unchanged. The catalog takes metric sizes and lengths, hex heads and REV's T-slot, a 90 degree countersink for metric flat heads, ISO 4762's 2D + 12 mm socket head thread, and a vendor's word that a part is threaded its whole length. Nuts come in finishes: FRC's in zinc plating alone, which their configuration doesn't ask. FTC's studios list finishes cheapest first, and vendors Generic, McMaster-Carr, goBILDA, REV, AndyMark. fs: a part set may name its definition, so two can share a folder, and a definition configuring studios from another's tables needs no CONTENTS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
ConfigLib has no T-slot screw, and nobody inserts one, so REV's REV-41-1907 and the T-slot head shape it alone needed are gone; its hex cap screws stay. FRCDesign's analytics count a part's uses now (`useCount`), which `fs cots` failed on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
…ument Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Pushed fasteners/fastenerTables.gen.fs Pushed fasteners/fasteners.fs
Pushed gear/gearCommon.fs Pushed gear/robotGear.fs
# Conflicts: # featurescripts/core/linearStock.fs # featurescripts/released/frame/frameTables.gen.fs # featurescripts/released/frame/robotFrame.fs # featurescripts/released/nutStrip/robotNutStrip.fs # featurescripts/released/shaft/robotShaft.fs # featurescripts/released/shaft/robotShaftTables.gen.fs # featurescripts/released/spacer/robotSpacer.fs
The screw was every solid the feature made, which took in the socket's cutter once it was extruded, and Onshape refused to subtract a part from itself. It's the revolve, or a hex head's joined body, again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Pushed core/cutStock.fs Pushed core/linearStock.fs Pushed fasteners/fasteners.fs Pushed gear/gearCommon.fs Pushed gear/robotGear.fs Pushed released/frame/frameTables.gen.fs Pushed released/frame/robotFrame.fs Pushed released/nutStrip/robotNutStrip.fs Pushed released/shaft/robotShaft.fs Pushed released/shaft/robotShaftTables.gen.fs
… from them The feature's tables hold both sets' parts, so a vendor in both, such as REV (#10-32 for FRC, M3 for FTC), had two sizes: a hidden Size holding the studio's default resolved to neither, and the screw failed with "does not make this screw in this finish". A hidden size now resolves among its own set's sizes (FASTENER_SIZES' new `metric`), the only ones its studio offers. The features also built from the inputs' raw values, so a hidden size, head or length that held something else made the wrong geometry. resolveChoices replaces made: it resolves each choice to the option it stands for, and the screw and nut build from those. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
…y in sync
Pushed together, a file could land before a tab it imports, and Onshape then
rewrote its import to the tab's new version, leaving the local file behind
until `fs pull`. fs parts built from that state, and Onshape refused to
configure the screw ("Feature not found"). Files are now pushed in waves, each
after the tabs it imports among those pushed, naming their new versions.
fs parts also refuses to build while Onshape has import versions the local
files lack, and says to run fs pull.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
M3 and M4, as McMaster-Carr's are, in one finish with no vendor or part number, as Generic's screws and washers are. Generic comes first among the vendors, so it's FTC's default nut, as it is its default screw and washer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Each a major release, their first: v1.0.0 into FRCDesignLib's fasteners document and ConfigLib's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
A release builds the Part Studios and writes the manifest in the main document, and leaves versioning it to its owner, who checks the studios first; FRCDesignApp then loads that version or holds it for approval. A release is numbered by the backend's versions, and its recorded locations name the document and tabs, with no version. A target is still versioned, for a local FRCDesignApp to load. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
Rather than refusing until `fs pull`, fs parts writes them into the local files itself, as fs pull does, with no API calls. After fs sync-main merges into the main workspace, Onshape can change them there, and refusing would stop fs run-releases in the Onshape workflow; it commits them with the release instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this adds
[tool.fs.parts.*],fs parts SET --test|--release|--diagnose): FeatureScript-backed Part Studios, each configured by a definition. A release builds them in FRCDesignLib's documents, with a manifest (<set>.parts.json) that FRCDesignApp reads. Seedocs/parts.md.featurescripts/fasteners/): screw, nut and washer features, with tables generated fromfastenerTables.py.fasteners, goes into FRCDesignLib.ftcFasteners, goes into ConfigLib. It covers Generic, McMaster-Carr, goBILDA, REV and AndyMark, in M3 and M4.resolveChoices).fs sync-main: each branch pushes to its own Onshape workspace, and main is landed in the main workspace by merge.fs push: files are now pushed after the files they import, so their import versions stay in sync.fs partsrefuses to build while Onshape holds import versions the local files lack.checks.ymlruns on pull requests.onshape.ymlruns on each push to main:fs sync-main, thenfs run-releases, then a push of what they commit.releases/fasteners.tomlreleases v1.0.0 offasteners.releases/ftc-fasteners.tomlreleases v1.0.0 offtcFasteners.Merging this runs Onshape
This PR brings
onshape.ymlto main, so merging it starts the workflow. The run spends the API allocation of the account inONSHAPE_ACCESS_KEY/ONSHAPE_SECRET_KEY.Each release:
Before merging:
github-actions[bot]must be allowed to push past main's branch protection.Tests
uv run pytest -q: 942 passed.fs checkandfs releasesare clean.🤖 Generated with Claude Code
https://claude.ai/code/session_01T4daFKz4qvNwCEYcg38VKS