Super Girt Tool (SGT) — Comprehensive Specification
Version: 1.0 (Merged) Date: 2025-11-25 Supersedes: SGT Spec-Lock v13, SGT_Specification_2025-11-9_v6 Status: Normative
This document consolidates all historical guidance, current specifications, and implementation requirements into a single, authoritative Super Girt Tool specification. It merges content from 15 historical documents and 4 current spec files.
Part 1: Core Principles
1.1 Single Strict Path
- Pipeline: Analyze → Configure (UI) → Preview → Plan → Write
- No fallbacks, no silent failures, no vague heuristics
- Fail fast and loud with typed exceptions and overlays
- Catch only typed, expected errors at narrow boundaries; otherwise surface errors and stop
1.2 Preview Purity
- Preview never mutates the document
- Temporary instances for analysis/diagnostics are allowed
- Preview reflects actual placement parameters
1.3 Transactional Commit
- Batch writes, isolate per-girt failures
- Emit precise summary
- Single metadata write at commit
1.4 Spec-Lock Supremacy
- Orientation, rotation, offsets, joins, end-gaps, tolerance gates, and view contracts are judged by the Spec-Lock rules
- When in doubt, enforce the Spec-Lock constraints
1.5 AGENTS.md Compliance
- No fallback routes
- No silent failures
- No stubs/placeholders in production paths
- Delete dead code
- Centralized error handling
Part 2: Wall-Anchored Frame
2.1 Right-Handed Coordinate System
The tool uses a single, unified right-handed wall frame throughout all services. No service may define its own coordinate system.
Frame Definition (matches WallFrame.cs):
- Origin: Location curve start point − (bottom offset × BasisZ)
- BasisX: Along wall (tangent to location curve, typically horizontal)
- BasisY: Exterior normal (perpendicular to wall, pointing outward from interior, from
Wall.Orientation) - BasisZ: Vertical (building up, parallel to Revit world Z-axis)
Right-Hand Verification:
- BasisZ = BasisX × BasisY
Orthonormality Checks:
- |dot(X,Y)|, |dot(X,Z)|, |dot(Y,Z)| ≤ 1e-6
- (BasisX × BasisY) · BasisZ ≥ 0.9999
NO OTHER coordinate systems should exist in SGT codebase. This frame is used for:
- Family calibration (face classification)
- Orientation analysis (placement, seating checks)
- Preview generation (geometry transforms)
- All wall-relative computations
2.2 Linked Wall Handling
For linked walls:
- Read the linked wall's
Orientationproperty and location curve endpoints - Apply
RevitLinkInstance.GetTotalTransform()to transform into host-document coordinate space - The transformed orientation is guaranteed to be the normal vector from the target exterior plane
- Store the transformation in the wall's domain object, including determinant and mirrored (
determinant < 0) metadata - Frame-swap opening T mapping must include mirrored parity so visual elevation left/right remains authoritative for jamb semantics
2.3 Single Frame Enforcement
CRITICAL: The right-handed wall frame computed in §2.1 is the only transformation used throughout the entire tool. Any code that previously used a different coordinate system frame must be refactored to use this single transformation.
Part 3: Services Architecture
3.1 Coordinate System Service
Single Source of Truth for wall coordinate system.
Responsibilities:
- Accept linked or host foundation wall element ID (from user selection or test function)
- Read wall's
Orientationproperty and location curve endpoints - Transform into host-document coordinate space
- Compute and store the right-handed wall frame (Origin + BasisX/Y/Z)
- Provide the Revit
Transformobject for use by all other services
3.2 Wall Layer Service
Responsibilities:
- Examine target wall for compound structure
- Select target layer using fallback logic:
- Primary: Most-exterior core layer with "Structural" checkbox enabled
- Fallback 1: Thickest layer
- Fallback 2: If multiple layers have same thickness, use most-exterior
- Store selected layer in wall domain object
- Compute "target layer offset" — the offset from wall center (location curve) to exterior side of target layer
- Populate UI layer dropdown with all layers, defaulting to selected layer
3.3 Target Exterior Plane Service
Responsibilities:
- Create Revit
Planeobject representing the Final Target Exterior Plane - Construct
Frame()object with:- Origin: Wall frame origin + target layer offset + UI layer offset value (defaults to 0)
- Basis Vectors: From Coordinate System Service
- Keep plane updated when:
- UI target layer combobox changes
- UI layer offset textbox changes
- Create new / delete old plane as needed
3.4 Calibration Service
Single Source of Truth for identifying web and flange faces per family.
High-Level Process:
- Place temporary instance on target plane (arbitrary length/direction)
- Extract geometry using
GetInstanceGeometry()with Medium detail level - Strip end cap faces (faces perpendicular to member length)
- Group remaining faces by area into bins:
- Larger area bin → "likely web faces"
- Smaller area bin → "likely flange faces"
- Within each bin, filter by normal vector orientation:
- Discard faces whose normals aren't multiples of 90° from wall frame
- Select largest area face per orientation bin
- Store face IDs in family domain object
- Delete temp instance and rollback transaction
Notes:
- Calibration runs once per family (not per type)
- Type selection: prefer "middle" type if multiple exist
- Face IDs are stable across instances of the same family
- Geometry traversal must prefer
GetInstanceGeometry()and only fall back toSymbolGeometrywhen instance geometry is unavailable; traversing both in one pass is forbidden because it duplicates candidates and can mix stale/fresh probe geometry.
3.5 Orientation Analysis Service
Single Source of Truth for determining placement settings per family per role.
Process (per family, per role):
- Place temp instance on target plane with role-appropriate direction:
- Girts/Heads/Sills: horizontal
- Jambs: vertical
- Retrieve calibrated faces from Calibration Service
- Find correct rotation by testing web face normal against expected direction
- Horizontal roles probe canonical quarter-turns (
0/90/180/270) directly. - Vertical roles (jambs) probe one azimuth-compensated value per canonical quarter-turn (4 candidates total). The persisted default remains the canonical quarter-turn rotation.
- Horizontal roles probe canonical quarter-turns (
- Identify correct flange face by checking normal matches exterior plane normal
- Test Y justification options against flange gate OR web gate:
- Flange gate: BasisY distance from flange face point to target exterior plane ≈ 0
- Web gate: Uses shape/role mode policy in analyzer:
- Open-section horizontals (
Channelgirt/head/sill,Zgirt,Anglegirt): edge-contact distance (minimum face-vertex distance) - Closed/tube sections (
HSS) and jamb roles: face-coplanar distance (maximum face-vertex distance)
- Open-section horizontals (
- Target/exterior gate (all roles): Uses face-coplanar distance
- Opening-role web-plane origin contract:
Head/Sill/Jambweb seating planes are anchored to the target structural-plane origin (layer-offset/wall-offset applied), not raw wall-frame origin, so opening-role Y/Z gates evaluate in the same plane frame as target seating - Calibrated face-id lookup deduplicates by persistent face id before seating selection
- Square-HSS symmetric candidates are re-resolved inside each Y/Z probe iteration after
doc.Regenerate()(no pre-loop face cache reuse)
- Test Z justification for remaining gate
- For vertical roles, enforce the open-side pointing contract for channels (C/MC):
- For each passing rotation candidate, run the full Y/Z solver and then measure which side of the section is the web side along wall BasisX (using section geometry extents).
- Select the rotation/justification solution where the open side points away from the opening center:
JambLeft: open side points toward−BasisXJambRight: open side points toward+BasisX
- If
CanFlipFacing == true, flip testing may still be evaluated, but the analyzer must not depend on flip support. The primary disambiguator is choosing the correct canonical rotation (often0vs180). - Persist
OrientationResult.IsFlippedonly when the winning solution actually requiresFlipFacing.
- Store solved settings (rotation, Y-just, Z-just) in family domain object
Constraints:
- Z-shapes: Only analyze for Girt role (hard block for opening roles)
- Angle-shapes: Only analyze for Girt role (hard block for opening roles)
- Analysis runs per-family, per-role, but only one type per family
Dual-web-face disambiguation contract (C/MC jambs):
- Calibration can retain both web-side face normals for channels (
+Xand-Xorientation bins), so rotation gate alone can pass bothJambLeftandJambRightat the same rotation. - Vertical role disambiguation must therefore include an open-side pointing check (not rotation-only acceptance).
- If
CanFlipFacing == false, the analyzer must still be able to disambiguate by choosing the canonical rotation (typically0vs180) that satisfies the open-side pointing contract. - If no candidate satisfies pointing, the analyzer must return invalid for that role (explicit failure, no silent fallback).
Source:
src/Tools/Structural/SGT/Features/Orientation/OrientationAnalyzer.cs:340Source:src/Tools/Structural/SGT/Features/Orientation/OrientationAnalyzer.cs:405Source:src/Tools/Structural/SGT/Features/Orientation/OrientationAnalyzer.cs:548Source:src/Tools/Structural/SGT/Features/Orientation/OrientationAnalyzer.cs:893Source:src/Tools/Structural/SGT/Features/Orientation/OrientationAnalyzer.cs:1787Source:src/Tools/Structural/SGT/Features/WallAnalysis/SymbolCalibrationService.cs:544Source:src/Tools/Structural/SGT/Domain/ValueObjects/OrientationResult.cs:9Source:src/Tools/Structural/SGT/Features/WallAnalysis/FaceSelectors.cs:20Source:src/Tools/Structural/SGT/Features/WallAnalysis/FaceSelectors.cs:88Source:src/Tools/Structural/SGT/Features/WallAnalysis/SymbolCalibrationService.cs:356Source:src/Tools/Structural/SGT/Features/Orientation/OrientationAnalyzer.cs:832Source:src/Tools/Structural/SGT/Features/Orientation/OrientationAnalyzer.cs:1369Source:src/Tools/Structural/SGT/Features/Orientation/OrientationAnalyzer.cs:240Source:src/Tools/Structural/SGT/Features/Orientation/OrientationAnalyzer.cs:1046Source:src/Tools/Structural/SGT/Features/Placement/Writers/DomainWriter.Utilities.cs:125Source:src/Tools/Structural/SGT/Features/Placement/Writers/DomainWriter.OpeningPlacement.cs:235
Part 4: Role Contracts
4.1 Role Axis Alignment
| Role | Length (L) | Depth (d) | Width/Flange (bf) | Flange Direction |
|---|---|---|---|---|
| Girt | +BasisX | ±BasisY | +BasisZ | Up |
| Head | +BasisX | ±BasisY | +BasisZ | Up (away from opening) |
| Sill | +BasisX | ±BasisY | −BasisZ | Down (away from opening) |
| Jamb_Left | +BasisZ | ±BasisY | −BasisX | Away from opening |
| Jamb_Right | +BasisZ | ±BasisY | +BasisX | Away from opening |
4.2 Seating Requirements (All Roles)
- Exterior flange: Seats on the exterior wall plane (BasisY direction)
- Web seating by role:
- Girt: Web on assigned elevation plane (horizontal)
- Head: Web on opening top plane (horizontal)
- Sill: Web on opening bottom plane (horizontal)
- Jambs: Web on opening side planes (vertical left/right)
4.3 Corner Alignment
- Corner = intersection of correct flange face and correct web face
- Achieved automatically when both flange gate and web gate pass
- No separate corner gate implementation needed
4.4 Pointing Requirements
- Girts/Heads: Point UP (web face normal points down)
- Sills: Point DOWN (web face normal points up)
- Jambs: Point AWAY from opening center (web face normal points toward opening)
- For open-section jambs (C/MC), pointing is resolved through flip-state role tie-break; left/right jambs should resolve opposite
IsFlippedstates when the same rotation candidate is otherwise valid.
4.5 Special Shape Handling
Z-Shapes:
- Valid only for Girt role
- Exterior flange down, interior side flange up
- Analyzer enforces flange-pair ordering: exterior seated flange must be lower and interior paired flange must be both interior and above
- Hard block for opening roles (heads/sills/jambs)
Angle-Shapes:
- Valid only for Girt role
- Hard block for opening roles (heads/sills/jambs)
- Unequal-leg contract: short leg is web-like (seats assigned elevation), long leg is flange-like (seats target exterior plane)
- Equal-leg fallback: select web/flange by wall-up vs wall-exterior axis alignment score
- Orientation gates still require exterior seating + elevation seating with zero offsets
HSS Rectangles:
- Calibration now captures explicit rectangular-HSS face groups for deep and shallow section dimensions
- Horizontal roles (Girt/Head/Sill):
targetSet=deep,webSet=shallow(deep seats target exterior plane; shallow seats assigned elevation/opening top-bottom plane) - Vertical roles (JambLeft/JambRight):
targetSet=shallow,webSet=deep(deep seats opening-edge plane; shallow seats target exterior plane) - Analyzer no longer relies on ad-hoc web/flange area-swap heuristics to decide rectangular-HSS role mapping
HSS Squares:
- Width == depth degeneracy allowed
- Alignment accepts symmetric case and evaluates all non-endcap section faces for seating/alignment (not only calibrated web/flange bins)
- Symmetric non-endcap faces are re-fetched per Y/Z probe pass after justification regen, preventing stale pre-probe face reuse
- Seating/pointing gates still apply
Finite-Metric Gatekeeping:
- Y/Z candidate and pair scoring now reject non-finite (
NaN/Infinity) metric values before ranking - Failure diagnostics include candidate counts (
candidates,finiteCandidates,rejectedNonFinite) so Step 2 fatal triage shows whether failure is geometric or numeric
Source:
src/Tools/Structural/SGT/Features/WallAnalysis/SymbolCalibrationService.cs:400Source:src/Tools/Structural/SGT/Features/WallAnalysis/SymbolCalibrationService.cs:446Source:src/Tools/Structural/SGT/Features/WallAnalysis/FamilyCalibrationData.cs:68Source:src/Tools/Structural/SGT/Features/Orientation/OrientationAnalyzer.cs:588Source:src/Tools/Structural/SGT/Features/Orientation/OrientationAnalyzer.cs:833
4.6 Solid Geometry Placement
ALL elements must have their solid geometry placed on the interior side of the target exterior wall plane.
Part 5: Rotation & Justification
5.1 Cross-Section Rotation
- Also known as "Structural Bend Dir Angle"
- Angle about member length axis (L)
- Constrained to k×90° within tolerance (mod 90° ≤ 1e-6°)
- Non-multiple-of-90° rotations fail immediately
5.2 Y/Z Justification
- Y Justification: Controls lateral positioning (Left, Center, Right, Origin)
- Z Justification: Controls vertical positioning (Top, Middle, Bottom, Origin)
- Family-dependent labels; validity determined by seating/corner gate outcomes
- Labels are for UI display; actual values are numeric
5.3 Zero Offsets Policy
Hard Gate: Y/Z justification offset values = 0.000 ft
- Any non-zero offset fails with
[SpecFail/Offsets/NonZero] - Clarification: "Wall Offset" (depth plane choice in UI) is independent and allowed
- Wall Offset translates the placement plane along wall depth direction
- Instance Y/Z justification offsets must remain exactly 0.0
5.4 Parameter Update Ordering
Per element, in order:
- Place instance
- Set Disallow Join at both ends
- Apply negative Start/End Extensions for gaps
- Validate spans (> 6")
- Commit
Part 6: UI/UX Flow
6.1 Entry Points
- New Flow: "Super Girt Tool" ribbon button in DB Tools tab
- Edit Flow: Contextual button in "Modify — Structural Framing" tab when SGT metadata detected
6.2 New Flow (Single Basis Wall)
Basis wall is singular. All analysis, seeding, previews, openings, and placement are anchored to one basis wall.
Launch & Prompt:
- Yellow warning banner appears on launch
- Prompt user to select either a linked model wall or a host foundation wall
- Enforce single selection; reject multiple selections and non-wall types
Progress Overlay (4 Steps):
- Step 1: Calibration (0% → 100%)
- Calibrate all structural framing families
- Identify web faces and flange faces
- Step 2: Orientation Analysis (0% → 100%)
- Analyze each family for each role
- Z-shapes and Angle-shapes only for Girt role
- Step 3: 2D Profile Loop Extraction (0% → 100%)
- Extract Medium-detail geometry loops
- Sanitize (ordering, closure, tolerance-clean)
- Step 4: Initial UI Seeding (0% → 100%)
- Default family: "C Shapes" / "C10X15.3"
- Seed girt rows at ≤ 5'-0" spacing
- Seed opening rows from detected openings (Linked) or empty (Foundation)
Auto-Seeding:
- Girts: ≤ 5'-0" spacing with orientation-analyzed defaults
- Openings (Linked): One row per detected opening; default enabled roles are computed from opening bounds vs wall bounds (no fixed "Sill off" default)
- Manual Openings: Available via "Add Opening" action
Plan Validity:
- Plans may be openings-only (0 girts but ≥1 enabled opening role)
- Place/Update are disabled only when the plan would place nothing
Reveal: When analysis and seeding complete, keep the overlay visible until the first Elevation preview frame has painted (so the preview is never blank), then close the overlay to reveal pre-populated grids and live previews.
6.3 Edit Flow (Selection-Aware)
SelectionChanged Observer:
- Monitor Revit selection for Structural Framing with SGT schema
- Show "Edit SGT Wall" button on contextual tab when detected
Launch:
- If multiple SystemIds present, open picker
- Otherwise use single system
Rehydrate:
- Run auto-analysis at open
- Rehydrate UI from existing SGT System
- Initial seeding rules do NOT apply in Edit
Edit-Time Segmentation Invariants (Hard Requirements):
- If girt segments are merged (two
UiKeys removed, one inserted), any opening-role extent targets (TopExtentTarget/BottomExtentTarget) that referenced either removedUiKeymust be rewritten to the insertedUiKeyso snap-to-girt semantics remain stable. - If re-segmentation recomputation produces fewer than 2 segments, the segment group must collapse back to a single standalone row (no stale segmented siblings).
- When deduplicating near bisection points, preserve all source intersecting element keys; bypass filtering may exclude a point only when all contributing sources are bypassed.
Source:
src/Tools/Structural/SGT/Shell/ViewModels/ShellWindowViewModel.DomainIntegration.cs:1908
Source:src/Tools/Structural/SGT/Shell/ViewModels/ShellWindowViewModel.CoreAndEditing.cs:1437
Source:src/Tools/Structural/SGT/Features/Extents/MemberIntersectionService.cs:309
6.4 Foundation Mode
Seeding Window:
- From TOP of basis foundation wall upward 20'-0"
- Standard ≤ 5'-0" spacing within this band
Openings:
- NOT auto-seeded in Foundation Mode
- Manual rows preview and place with full contracts
Height Above Top:
- Acts as vertical reference when enabled
6.5 Window Structure
Left Pane — Scope & Config:
- Exterior Plane & Compound Layers (Linked Mode)
- Wall Offset (depth-plane selection)
- Foundation Mode + Height Above Top
Visibility by Flow:
- New: Place visible; Update/Remove hidden
- Edit: Place hidden; Update/Remove visible
Part 7: Preview System
7.1 Common Contracts
- All three previews (Elevation, Section, 3D) derive from the same canonical, Revit-accurate element data
- Elevation and Section are projections of the canonical data used by 3D
- Previews stay synchronized with grids and UI state at all times
- Preview/placement parity for vertical framing (jambs):
OpeningRoleConfig.RotationDegreesis stored as a wall-relative canonical rotation (typically quarter-turns).- Step 2 may apply azimuth compensation only while probing temporary vertical instances on off-axis walls; the stored rotation remains canonical.
- Preview matches placed geometry by combining the canonical rotation with Step 3's per-rotation vertical calibration payload (section loops, exact Y/Z pair deltas, and wall-direction sign bases).
- Placement applies azimuth compensation only when writing the effective Revit bend-dir angle.
Source:
src/Tools/Structural/SGT/Features/Orientation/JambAzimuthCompensation.cs:34Source:src/Tools/Structural/SGT/Features/Preview/Models/PreviewScene3DBuilder.cs:293Source:src/Tools/Structural/SGT/Shell/UI/Rendering/PreviewRenderer.cs:761
7.2 Elevation Preview
Coordinate System:
- u = +BasisX (along wall)
- v = +BasisZ (vertical)
Rendering:
- Draw bf-thickness bands from loop v-extents along L
- Use trimmed L-span (grids/openings)
- Enforce end gaps via negative extensions after Disallow Join
- Horizontals must not intrude into jamb bf
- Show grid extents overlay
Acceptance Gates:
- bf-thickness bands correct
- Horizontals segmented at openings
- 1/2" end gaps at jamb interfaces
- Disallow Join at both ends
- Zero offsets
7.3 Section Preview
Coordinate System:
- u = +BasisY (depth / exterior normal)
- v = +BasisZ (vertical)
Rendering:
- Render Medium loops with EvenOdd fill
- Anchor at L-axis ∩ section plane (or closest point if parallel)
- No L-extrusion
- Stroke presentation is guidance
Acceptance Gates:
- Medium-detail loops rendered with EvenOdd
- Oriented per (d, bf)
- No L-extrusion
- Strict axis-alignment by role
7.4 3D Preview
Rendering:
- Mesh from canonical 3D element data
- End caps must be tessellated from section loops using EvenOdd across all contours (concave + holes supported; no triangle-fan caps)
- Two directional lights + ambient
- Fixed 6" (0.5 ft) floor plane
- Role palette visible
- Overlay legend
- Interactive orbit/pan/zoom
Acceptance Gates:
- No extra gates; 3D renders exactly the snapshot data
- Issues are visually obvious
- No triangulated/infill artifacts at member ends; concave + hollow sections terminate cleanly (holes remain holes)
Part 8: Endpoint Association System
8.1 EndpointAssociation Value Object
Every segment endpoint must have an association that tracks what it connects to.
Association Types:
| Type | Description | Required Fields |
|---|---|---|
WallStart |
Wall start (t=0) | None |
WallEnd |
Wall end (t=1) | None |
Grid |
Grid intersection | GridName, GridOffset |
OpeningEdge |
Opening edge | OpeningId, EdgeSide, EdgeOffset |
FreeAlong |
Free distance from wall start | AlongDistance |
OpeningEdgeSide Values:
- Left
- Right
- Top
- Bottom
8.2 Association Rules
- All girt segments must have start and end associations defined
- All opening elements must have endpoint associations
- Associations drive:
- Segment trimming calculations
- Preview rendering coordinates
- Placement coordinate determination
Part 9: Elevation Preview Snapping
9.1 ElevationSnapIndex
Spatial index for O(log n) nearest-neighbor queries on snap targets.
Indexed Targets:
- Grids (sorted by t-parameter)
- Opening edges (left/right, sorted by t-parameter)
Rebuild:
- Called once per preview refresh
- Before drag operations
9.2 IElevationSnapService
Service for computing snap targets during drag operations.
SnapInput Parameters:
- Target t-parameter (0.0 to 1.0)
- Pixels per unit t
- Cursor position (X, Y in pixels)
- DPI scale factor
- Note: DPI scale is used for hit-testing and snap thresholds. Preview visual styling (text/lineweights) uses a fixed visual scale (DPI-agnostic).
- Wall length in feet
- Available grids and edges
- Optional girt/wall-top/wall-bottom elevation targets (for vertical endpoint snaps)
SnapResult:
- Snapped (bool): True when cursor is within snap threshold of the resolved valid target
- Kind: "Grid", "Edge", "WallEdge", "Girt", "WallTop", or "WallBottom"
- Name: Grid name or opening key
- Side: Edge side (Left/Right)
- T: Resolved target t-parameter (for vertical-only snaps, cursor T is preserved)
- DxPx: Pixel distance to snap target
9.3 Snapping Behavior
Lock Rule (non-negotiable):
- Drag/snap interactions are locked to valid associations only.
- No free-along / arbitrary drag targets are produced by snapping.
- Valid snap associations are other elements, grids, or wall edges.
Priority:
- Grid snapping (highest priority on ties)
- Wall edge snapping
- Opening edge snapping
- Vertical targets when the edit mode enables elevation snapping (girts, wall top, wall bottom)
Thresholds:
- Hit radius: 10px at 96 DPI baseline (DPI-scaled)
- Snap threshold: 12px to mark a target as "Snapped=true"
- Epsilon for t-value comparisons: 1e-9
When the cursor is outside threshold, the nearest valid target is still returned with Snapped=false (locked association with out-of-threshold feedback).
Tie-Breakers:
- Prefer grids over wall edges over opening edges
- Prefer smaller t on exact ties
Source:
src/Tools/Structural/SGT/Features/Preview/Snapping/ElevationSnapService.cs:46Source:src/Tools/Structural/SGT/Features/Preview/Snapping/ElevationSnapIndex.cs:216Source:src/Tools/Structural/SGT/Features/Preview/PreviewVisualTokens.cs:1Source:src/Tools/Structural/SGT/Shell/UI/Behaviors/PreviewPresenterBehavior.Core.cs:1205
Part 10: Placement System
10.1 Disallow Join
- Must be set at both ends for all members (all roles)
- Set before applying end extensions
10.2 End Extensions
- Along-L edits are via Start/End Extensions only
- Use negative values to shorten (not cutbacks)
- Required 1/2" end gaps at horizontal–jamb interfaces
- Order: Set Disallow Join → Apply −1/2" extensions
10.3 Minimum Segment Length
- Girt segments must be > 6" (0.5 ft)
- Otherwise fail with
[SpecFail/Extents/TooShort]
10.4 Opening Segmentation
- Horizontal members segment at openings
- Compute intervals by subtracting opening spans from row extent
- Gate by vertical intersection (row elevation vs opening height window)
- Apply 1/2" gaps at opening edges
- Exception: rows may declare
BypassedOpeningKeys; matching openings are excluded from subtraction and remain continuous - Interior endpoint drag to the opposite edge of the same opening auto-adds bypass for that opening and clears opening-edge gap overrides for that opening
- Snapping a girt extent endpoint to a specific opening edge removes that opening from bypass for that row
Source:
src/Tools/Structural/SGT/Shell/ViewModels/ShellWindowViewModel.DomainIntegration.cs:1021Source:src/Tools/Structural/SGT/Shell/ViewModels/ShellWindowViewModel.DomainIntegration.cs:1861Source:src/Tools/Structural/SGT/Shell/ViewModels/ShellWindowViewModel.CoreAndEditing.cs:1565Source:src/Tools/Structural/SGT/Features/Extents/SegmentResolutionService.cs:39Source:src/Tools/Structural/SGT/Features/Placement/Orchestrator.cs:155
10.5 Placement Order
Per element:
- Place instance(s)
- Disallow Join at both ends
- Apply negative Start/End Extensions for 1/2" gaps at true intersections only
- Validate minimum segment length
- Commit
10.6 Zero Offsets Enforcement
- Location curve represents logical L-span
- Shortening via negative extensions only
- No cutbacks
- Hand/Face flips allowed if seating/axis outcomes remain valid
10.7 Orientation Parameter Application (Structural Framing)
- Order matters for vertical framing:
- Set
STRUCTURAL_BEND_DIR_ANGLE(rotation) doc.Regenerate()(ensure rotation takes effect)- Apply
flipFacing()if required doc.Regenerate()- Set Y justification
doc.Regenerate()- Set Z justification
doc.Regenerate()
- Set
- Rationale: without regeneration between updates, Revit can apply justifications against stale orientation state, causing flange seating drift (often showing up as a depth-sized exterior shift).
Source:
src/Tools/Structural/SGT/Features/Placement/Writers/DomainWriter.Utilities.cs:125
Part 11: Metadata & Storage
11.1 Extensible Storage Schema
All SGT instances carry schema fields:
| Field | Description |
|---|---|
Tag |
"SGT" |
SystemId |
GUID string |
ConfigJson |
Role, vertical location, along-wall location, depth plane, etc. |
WallCurveHash |
Robust matching (1e-5 ft rounding, includes wall ID) |
WallOffset |
Depth offset value |
Timestamp |
Creation/modification time |
Version |
Schema version ("13") |
11.2 Edit Round-Trip
Metadata enables:
- Selection-based detection
- Edit launch
- Reconciliation when host or openings change
Note: Initial seeding does NOT apply in Edit; system rehydrates from stored configuration.
Openings-only:
- A stored system may have
0girt rows as long as it has ≥1 enabled opening role; Edit/Update must still work end-to-end.
11.3 Remove System Flow
VM Command: RemoveSystemCommand
Implementation:
- Show overlay "Removing…"
- Call writer API to delete only elements tagged with current SystemId
- Delete girts and all opening roles
- Remove stored config from SgtConfigStore (host) and SgtLinkedConfigStore (linked)
- Update overlay with result
- Close window on success
Constraint: Does NOT affect other SGT systems; scoped deletion only.
Part 12: Error Handling
12.1 SpecFail Tags
Recommended for logs/exceptions:
| Tag | Description |
|---|---|
[SpecFail/RoleAxes/Mapping] |
Axis alignment failure |
[SpecFail/Offsets/NonZero] |
Non-zero Y/Z offset detected |
[SpecFail/Extents/TooShort] |
Segment < 6" |
[SpecFail/Writer/Acceptance] |
No valid rotation/justification combination |
[SpecFail/Writer/Basis] |
Cannot determine flange face |
[SpecFail/RightHand] |
Non-right-handed rotation delta |
12.2 Tolerances
| Check | Tolerance |
|---|---|
| Alignment (dot product) | ≥ 0.9999 |
| Seating | ≤ 1e-3 ft |
| Corner | ≤ 1e-4 ft |
| Rotation | k×90° within 1e-6° |
| Minimum girt length | > 6" (0.5 ft) |
| T-parameter epsilon | 1e-9 |
| Distance epsilon (feet) | 1e-6 |
12.3 Logging Requirements
- No silent failures
- All errors surface via banner/overlay
- Centralized error boundaries
- No broad
catch(Exception)unless at narrow per-element boundary with explicit message propagation
Part 13: Window Initialization & Progress Overlay
13.1 Overlay Display
On each window paint, display a 4-step progress overlay that shows completion percentage for each step.
13.2 Step 1: Calibration (0% → 100%)
- Enumerate all structural framing families in document
- For each family (once per run):
- Place temporary instance
- Extract geometry and identify web/flange faces
- Store face IDs in family calibration cache
- Delete temp instance
- The calibration pass is cache-aware and must not re-run temp calibration for a family that is already calibrated in the current run.
- The default girt family guard at the end of Step 1 must check cache presence first and skip recalibration when cache is already populated.
- If a temp calibration fails with family-modification/stretch-forbidden errors, treat it as a symbol-level calibration failure and continue trying other symbols in the same family.
- Temp probes must run inside rollback-only transactions (
TransactionorSubTransaction) with clear-after-rollback enabled. - Transaction-mode temp probes must attach the shared silent failures preprocessor and return failure metadata (
blocking,warnings,lastResult,forbidden) throughTempTransaction.RunWithMetadata(...). - Step 1 calibration, Step 2 orientation probes, and Step 3 profile warm must consume temp-transaction metadata and convert blocking probe failures into deterministic symbol/type-level failures (forbidden and non-forbidden), not silent probe success.
- The temp-transaction utility must capture work exceptions and rollback exceptions independently; it must not throw from a
finallypath that can mask the original failure context. - If rollback fails, raise
[SpecFail/TempTx/RollbackFailed]and preserve both failures when both work and rollback fault. - Emit temp-transaction lifecycle diagnostics for rollback probes (
[SGT.TempTx.Begin],[SGT.TempTx.Rollback.Begin],[SGT.TempTx.Rollback.End],[SGT.TempTx.Failures]) atTracelevel; keep blocking failures atWarning/Error. - Forbidden temp placement failures must short-circuit immediately after temp placement/regenerate (before any face traversal/classification work).
- Emit a single begin/end calibration transaction diagnostic per symbol (
[SGT.Calibration.Tx.Begin]/[SGT.Calibration.Tx.End]) including elapsed milliseconds, document/transaction context, and final outcome (ok|forbidden|failed). - Emit one compact calibration summary per run (
[SGT.PreflightSummary]) with total/calibrated/failed counts. - Post-overlay Analyze completion must force Elevation mode, request a preview refresh, and keep the overlay visible until the Elevation preview has painted at least one frame (paint barrier). After overlay teardown, schedule a Background safety refresh with explicit failure logging (no watchdog/fallback enqueue behavior).
- Progress:
(completed families / total families) × 100%
Source: src/Tools/Structural/SGT/Features/Placement/Steps/PlanBuilder.Step1Calibrate.cs Source: src/Tools/Structural/SGT/Features/Placement/Steps/PlanBuilder.Step3Warm.cs:142 Source: src/Tools/Structural/SGT/Features/WallAnalysis/SymbolCalibrationService.cs:116 Source: src/Tools/Structural/SGT/Features/Orientation/OrientationAnalyzer.cs:337 Source: src/Tools/Structural/SGT/Features/Placement/TempTransaction.cs:38 Source: src/Tools/Structural/SGT/Features/Placement/TempTransaction.cs:123 Source: src/Tools/Structural/SGT/Features/Placement/TempTransaction.cs:279 Source: src/Tools/Structural/SGT/Shell/ViewModels/ShellWindowViewModel.AnalysisAndHydration.cs:210 Source: src/Tools/Structural/SGT/Shell/ViewModels/ShellWindowViewModel.AnalysisAndHydration.cs:228 Source: src/Tools/Structural/SGT/Shell/UI/Behaviors/PreviewPresenterBehavior.CanvasInput.cs:160 Source: src/Tools/Structural/SGT/Features/Placement/Steps/PlanBuilder.Step1Calibrate.cs:151 Source: src/Tools/Structural/SGT/Features/Placement/Steps/PlanBuilder.Step2Analyze.cs:310 Source: src/Tools/Structural/SGT/Features/Placement/Steps/PlanBuilder.Step2Analyze.cs:384 Source: src/Tools/Structural/SGT/Features/Placement/Steps/PlanBuilder.Step3Warm.cs:481 Source: src/Tools/Structural/SGT/Features/Orientation/OrientationAnalyzer.cs:828 Source: src/Tools/Structural/SGT/Features/Placement/TempTransaction.cs:74
13.3 Step 2: Orientation Analysis (0% → 100%)
- For each calibrated family:
- For each applicable role (Girt, Head, Sill, JambLeft, JambRight):
- Skip opening roles for Z-shapes and Angle-shapes
- Place temp instance with role-appropriate direction
- Test rotation/justification combinations
- Vertical roles: use 4 probe candidates (canonical quarter-turns + azimuth compensation), then evaluate both flip states per passing rotation candidate
- Store solved settings
- For each applicable role (Girt, Head, Sill, JambLeft, JambRight):
- Emit compact Step 2 summaries for opening detection and merge (
[SGT.Step2.OpeningsSummary],[SGT.Step2.OpeningMergeSummary]), with only sampled opening detail in Debug logs. - Emit one Debug orientation summary per role (
[SGT.Orientation.Summary]) and keep candidate/probe-level diagnostics atTrace. - Progress:
(completed family-role pairs / total pairs) × 100%
13.4 Step 3: 2D Profile Loop Extraction (0% → 100%)
- For each calibrated family:
- Extract Medium-detail geometry loops
- Sanitize loops (ordering, closure, tolerance)
- Cache for preview rendering
- Emit one compact Step 3 summary (
[SGT.PreflightSummary]) with total/warmed/failed type counts; keep per-type warm success chatter atTrace. - Progress:
(completed families / total families) × 100%
13.5 Step 4: Initial UI Seeding (0% → 100%)
Default Family/Type:
- Family: "C Shapes"
- Type: "C10X15.3"
- (Hardcoded for initial implementation)
Girt Seeding:
- Calculate wall vertical extent
- Seed rows at ≤ 5'-0" spacing
- Apply orientation analysis results for default family
Opening Seeding:
- Linked Mode: One row per detected opening, with default enabled roles computed from opening bounds vs wall bounds:
- Left/Right jambs enabled when the opening is not at the wall ends (tolerance-gated)
- Header enabled when the opening top is below the vertical max (tolerance-gated)
- Sill enabled when the opening bottom is above the base reference (tolerance-gated)
- Left/Right role interpretation is visual elevation-based and must remain stable for rotated and mirrored links
- Role configs seed
FlipFacingfrom analyzedOrientationResult.IsFlipped
- Foundation Mode: Empty (manual add only)
Progress: Based on seeding completion
Part 14: Smart Family Change Updates
14.1 Trigger Condition
When a UI element (girt OR opening element) changes its family selection to a different family.
14.2 Update Behavior
- Look up orientation analysis results for:
- New family ID
- Current role (Girt, Head, Sill, JambLeft, JambRight)
- Auto-populate UI fields:
- Rotation
- Y Justification
- Z Justification
- (HandFlip defaults to false)
- UI controls update in lock-step with domain object
14.3 User Override
- User can manually change rotation/justification after auto-population
- Manual changes are preserved until next family change
- On placement, use currently configured UI settings (not analysis defaults)
14.4 Service Implementation
SgtSmartDefaultsService:
ApplySmartDefaultsForGirt(row, symbolId)
→ Sets rotation, Y-just, Z-just from orientation analysis
TryApplySmartDefaultsForOpeningRole(row, role)
→ Handles LeftJamb, RightJamb, Header, Sill
14.5 Justification Display
- UI displays human-readable labels: "Left", "Center", "Right", "Top", "Bottom", etc.
- Values convert to/from Revit API integers via
JustificationConverter - Rotation displays as degrees (0/90/180/270) but may be stored as radians for API
Part 15: Grid Extents UI
15.1 Detection
Find host and link grid lines intersecting the basis wall; show as Elevation overlay.
15.2 Per-Row UI
Two comboboxes per girt row:
- Left Extent
- Right Extent
Default: "Full Length" (bounded by wall edges)
15.3 Rules
| Grid Count | Behavior |
|---|---|
| 0 grids | Both comboboxes disabled |
| 1 grid | Picking it on one side disables the other (remains "Full Length") |
| 2+ grids | Both enabled; forbid same-grid at both ends; forbid inversions (Right < Left) |
15.4 Endpoint Computation
- Snap to selected grid planes ∩ wall plane
- Set Disallow Join at both ends
- Apply −1/2" Start/End Extensions
- Enforce > 6" minimum length
Part 16: Combination Freedom
Any parameter combination (rotation/flip hand/face/Y-just/Z-just) is valid if and only if all acceptance gates are satisfied:
- k×90° rotation
- Strict axis alignment
- Exterior flange seating + role web seating
- Zero offsets
- Required 1/2" end gaps via negative extensions
- Disallow Join at both ends
- Minimum length > 6"
- Grid ordering rules
- Hybrid axes asserts pass
The spec prescribes outcomes, not a single parameter recipe. No heuristic search is required if the outcome is known.
Part 17: Future Considerations
17.1 SgtMember Role-Agnostic Approach
Current implementation uses "SgtGirt" with separate handling for opening components. Future intent is to consolidate to a unified "SgtMember" class that is role-agnostic:
- Single class handles all roles: Girt, Head, Sill, JambLeft, JambRight
- Role property determines behavior and validation rules
- No axis-specific restrictions
17.2 Z-Shape Opening Role Relaxation
Currently Z-shapes and Angle-shapes are hard-blocked for opening roles. If user demand exists, this could be relaxed to a warning with override capability.
Appendix A: File References
Core Domain
DBTools.Core/Domain/SGT/ValueObjects/EndpointAssociation.csDBTools.Core/Domain/SGT/ValueObjects/GirtSegment.csDBTools.Core/Domain/SGT/Rules/MemberRules.cs
Services
DBTools.UI/Services/Snapping/IElevationSnapService.csDBTools.UI/Services/Snapping/ElevationSnapIndex.csDBTools.UI/Services/Snapping/SnappingConstants.csDBTools.UI/Services/Defaults/SgtSmartDefaultsService.cs
Adapters
DBTools.RevitAdapter/SGT/Analysis/SgtOrientationAnalyzer.csDBTools.RevitAdapter/SGT/Analysis/SgtSymbolCalibrationService.csDBTools.RevitAdapter/SGT/Analysis/SgtFaceSelectors.csDBTools.RevitAdapter/SGT/Analysis/SgtFrameBuilder.csDBTools.RevitAdapter/SGT/Services/SgtDomainWriter.cs
UI
DBTools.UI/ViewModels/SGT/SgtWindowViewModel.*.csDBTools.UI/Views/SGT/SgtWindow.xaml
Appendix B: Change Log
Version 1.0 (2025-11-25)
- Initial merged specification
- Consolidated 15 historical documents + 4 current specs
- Added endpoint association system (Part 8)
- Added elevation snapping specification (Part 9)
- Added 4-step progress overlay specification (Part 13)
- Added smart family change updates (Part 14)
- Adopted strict single wall frame mandate
- Specified Z-shape and Angle-shape hard block for opening roles
- Added future considerations for SgtMember consolidation