Skip to content

A05: minimal bolt groups joining two parts - #109

Merged
Blogbotana merged 10 commits into
Apibim-com:masterfrom
axisrow:ao/task-next-fork/promotion/a05-bolts
Oct 20, 2026
Merged

Blogbotana merged 10 commits into
Apibim-com:masterfrom
axisrow:ao/task-next-fork/promotion/a05-bolts

Conversation

@axisrow

@axisrow axisrow commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

What this changes

Mirror of the fork's #25 (axisrow/BeamCraft, A05), rebased onto upstream master
73c3597. The A05 bolt groups feature verbatim: CreateBolt/BoltSpec in the model, the
engine's bolt admission and bounds checks, the layer-engine properties (steel:bolt:*),
create-bolt/bolts CLI commands, the end-to-end suite, and the design note; plus the
fork's review fixes that ride with it (the weld/bolt property-prefix discrimination, the
weld token in the both-property-sets tamper check, and the pre-A05 mapping pin so stores
written before A05 stay readable).

Resolution notes against the upstream base (the fork's branch carried neighbours upstream
does not have — the fork's E03 BOM and A09 marks, which are not part of this PR):

  • only bolt is registered (no bom/marks modules or constants came over);
  • the mapping-pin chain follows 830cabd: every pre-A05 pin is the current descriptor
    without the bolt additions; the upstream pre-A05 pinned digest differs from the fork's
    fork-side value because upstream never added the mark line, and the test pins the
    recomputed upstream value;
  • everything else is the fork's A05 code unchanged.

How you verified it

  • cargo fmt --all, cargo clippy --workspace --all-targets -- -D warnings
  • cargo test -p beamcraft-cli --test bolts (5 tests), cargo test -p beamcraft-model
    and -p beamcraft-layer-engine (170 tests, 0 failed) on macOS — the model and
    layer-engine suites carry the bolt validation, fingerprint and mapping-pin cases
  • CI on this PR for Windows/Linux.

Provenance (clean-room)

  • Verbatim fork material, same MPL-2.0 project; the bolt group is authored data with
    explicit properties (no catalogue); no new assets or dependencies.

🤖 Generated with Claude Code

Issue tracking

Fixes #120

@axisrow axisrow left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: approved

A05 bolt groups promotion, nine commits, net diff reviewed against upstream/master.

  • Model admission (crates/model/src/command.rs): complete and fail-closed — label, two distinct parts (DV-REL-006/007), the group is not its own part, finite diameter in (0, 1000], count 1..512 with the right code split (InvalidArgument for 0, LimitExceeded above), finite pitch under the dimension cap, origin under the coordinate cap, and a unit direction by squared-norm tolerance. The fingerprint is versioned (BeamCraft/A05/CreateBolt/v1), length-prefixed and canonical-f64 encoded.
  • Engine decision (crates/engine/src/bolt.rs): pure and bounded over the weld Parts index; every bolt position origin + direction * (pitch * i) must lie inside both parts and a supported part without bounds refuses (None => false), never guesses; NaN bounds fail the comparisons and refuse. The whole group is refused together, and the tests cover missing/wrong-kind/taken identities, the 13th bolt leaving the plate, the out-of-plane origin and the count-1 outside origin.
  • Connection reading (apps/beamcraft-cli/src/weld.rs): a connection with any steel:bolt: property (whole prefix, not a loose substring) is a bolt group and never a weld; a connection with neither set is refused by the validator before the walk. kinds was widened to pub(crate) for the bolt adapter, nothing else moved.
  • The converge commit is the right surface discipline: the verbatim cherry-picks had carried fork-only neighbours (bom module registrations, A09 mark constants and their tests, the fork dispatch arm); the branch now registers and dispatches bolt alone, after the weld arm.
  • The mapping-pin chain is correctly re-based on the upstream descriptor: pre_a05_descriptor() is the current descriptor minus the bolt-properties line with the connection phrase reverted, the placeholder was replaced by the recomputed upstream pre-A05 digest (the fork value covered a mark line upstream never had), and the D1/D2 pin and the all-pins-still-accepted test chain through it consistently.
  • limits.rs was rewritten to LF: upstream had mixed CRLF/LF there, every other touched file was already LF, so this normalises the one outlier; the real change is the two bolt caps.

No CI checks have reported on the branch yet; this approval rests on the review above and on the same feature having run in the fork since its A05 slice.

axisrow and others added 9 commits October 20, 2026 20:36
A bolt group is the second supported connection, on the A06 weld pattern:
create-bolt authors one connection element per group with explicit diameter,
count, pitch, world origin and unit direction, and one ordered bim:connects
record towards two distinct plates, beams or columns; bolts lists the groups of
the verified head. The engine refuses a group whose bolt positions do not lie
within both parts' conservative world bounds. Like a weld a group has no body
and no volume; its count is the quantity a later bill of materials reads. A
stored connection carries exactly one of the weld or bolt property sets, and
the previous mapping digest stays accepted (experimental slice; see
docs/design/a05-bolts.md).

(cherry picked from commit 9d007ed)
(cherry picked from commit 5186ad7)
The verbatim cherry-picks carried fork-side neighbours the upstream base
lacks: bom module registrations (E03 is not mirrored here), the fork's A09
mark constants and tests, and the fork dispatch arm. Keep the A05 surface
only: register bolt alone, dispatch create-bolt/bolts after the weld arm,
resolve the mapping-pin chain by the 830cabd semantics (every pre-A05 pin is
the current descriptor without the bolt additions), recompute the upstream
pre-A05 pinned digest (the fork's value covered the mark line that upstream
never added), and drop the mark-constant import.

Co-Authored-By: Claude Code <[email protected]>
@axisrow
axisrow force-pushed the ao/task-next-fork/promotion/a05-bolts branch from df46615 to 630a72a Compare October 20, 2026 12:42
@Blogbotana

Copy link
Copy Markdown
Member

Thanks for rebasing onto #103. We tested this head merged into current master (24b4989) locally on Windows, and it fails:

authored::pin_tests::the_pre_a09_mapping_pin_is_accepted_and_is_not_the_current_one ... FAILED
panicked at crates/layer-engine/src/authored.rs:1267

The cause is the order of the mapping-pin chain. pre_a05_descriptor() is built as pre_a09_descriptor() minus the bolt additions, with the comment "A05 predates A09". Upstream it is the other way round: A09 (#103) is already on master, and A05 lands after it. So:

  1. pre_a09_descriptor() (current minus the A09 numbering line and Mark) still contains the bolt line and the reworded connection phrase, and no longer hashes to the pinned pre-A09 digest fdaf8904…, hence the failure.
  2. More importantly, stores written by current master — A09 present, A05 absent — carry a pin that none of the chain's steps produces, so they would be refused after this PR. That is a compatibility regression, not just a test issue.

Suggested fix: make A05 the newest step. pre_a05_descriptor() = SCHEMA_DESCRIPTOR without the bolt line and with the previous connection phrase (this is master 24b4989's descriptor); pre_a09_descriptor() = pre_a05_descriptor() without the A09 numbering line and Mark; the A07.2 step then follows from pre_a09. Please add a pin test for master 24b4989's descriptor digest (accepted, and not the current one), alongside the existing ones.

Also note: cargo test stopped at this first failing binary, so please run cargo test --workspace --no-fail-fast after the fix. Once it is green and CI passes, we will merge.

@axisrow axisrow left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: changes requested (one rebase-introduced pin-chain regression)

The A05 code itself is unchanged from the version I approved; what broke is the mapping-pin chain, which was rebased from the fork history onto a master that already carries the native A09 (#103, merged before #105).

On this branch SCHEMA_DESCRIPTOR = A07.2-era descriptor + native A09 line + A05 bolt line. pre_a05_descriptor() chains through pre_a09_descriptor() (current minus the A09 line), giving:

  • accepted: current; pre_a09 = descriptor-with-A05-without-A09 — a mapping no released master ever shipped; pre_a05 = the A07.2-era fdaf890...; and the older pins;
  • not accepted: the descriptor of the current released master (fdaf890 + the A09 numbering line) — which is exactly the digest every store created upstream since #103 carries.

pin_accepted is load-bearing on the edit path (authored/edit.rs refuses a layer whose saved bimSchemaDigest is not accepted with UnsupportedVersion), so an A05 build refuses to edit any store authored by current upstream master. The test stays green because it pins the same wrong constant (fdaf890, now described as "pre-A05" and duplicated in the all-pins list as "pre-A09"), and the comment "A05 predates A09" describes the fork history, not this one.

The fix is small: define the pre-A05 descriptor as SCHEMA_DESCRIPTOR minus the two A05 edits (that is the live master descriptor and the real pre-A05 mapping), accept the A07.2-era pin by additionally removing the A09 line, and pin the live-master digest in the all-pins test instead of the duplicated fdaf890.

Everything else in the rebase is sound: the descriptor-relevant neighbours from the merged master are handled, the dispatch and help literal are consistent, and the bolt surface is what I approved earlier.

Comment thread crates/layer-engine/src/authored.rs Resolved
The pre-A05 mapping is the current descriptor without the A05 edits - the
numbering mark line of A09 stays, so every store created since A09 keeps
passing edit-path capture. The pre-A09 mapping and the A07.2-era pins are
derived from it by removing the lines A09 added. Pins recomputed.

Co-Authored-By: Claude Code <[email protected]>

@axisrow axisrow left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: approved

The pin-chain fix does exactly what the review asked, and it is minimal:

  • pre_a05_descriptor() is now SCHEMA_DESCRIPTOR minus the two A05 edits (the bolt properties line and the connection rewording), which is precisely the descriptor of the released master — the mapping every store created since the native A09 merged carries. It is checked first in pin_accepted, so edit-path capture accepts those stores again.
  • pre_a09_descriptor() is redefined as the pre-A05 descriptor minus the A09 line and the Mark change item, which yields the A07.2-era descriptor — so the older pins (the A07.2-era fdaf890, the D1/D2 pin derived from it, and the constant list) are all computed from the real historical chain instead of through the phantom never-shipped mapping.
  • The pre-A05 test pins the recomputed live-master digest (085a4f27...), the D1/D2 test derives through the corrected chain with its pinned value unchanged, and the misleading "A05 predates A09" comment is gone.

The recomputed digest is self-validating (the test hashes the constructed descriptor), and by construction the construction equals the released master descriptor given the branch adds only the two A05 edits. The regression surface is closed.

@Blogbotana
Blogbotana merged commit 0c3813a into Apibim-com:master Oct 20, 2026
4 checks passed
@axisrow

axisrow commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator Author

Implements the work tracked in #120 (mirror of axisrow#5, A05: minimal bolt groups joining two elements).

@axisrow
axisrow deleted the ao/task-next-fork/promotion/a05-bolts branch October 24, 2026 06:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bolts: bolt groups joining two elements

2 participants