BuildwellTHREAD: Complete System Specification
Multi-Agent AI System for UK Building Regulations Compliance & Golden Thread Management
Document Version: 1.0
Date: January 2026
Status: Development Specification
Target Platform: Isambard AI Supercomputer (Nvidia GH200 Grace-Hopper)
Project Lead: London Belgravia Surveyors
EXECUTIVE SUMMARY
BuildwellTHREAD is a comprehensive AI-powered system designed to automate UK Building Regulations compliance checking for Gateway 2 and Gateway 3 submissions, with integrated Golden Thread documentation management. The system addresses the critical challenge of high rejection rates at Building Safety Regulator (BSR) gateways while streamlining the compliance verification process.
Key Objectives
- Reduce Gateway Rejection Rates: Target reduction from current 40-67% to below 20%
- Comprehensive Coverage: All Building Regulations Parts A-T with specialized agents
- Golden Thread Integration: Automated generation and maintenance per Building Safety Act requirements
- Professional Standards: Compliance commentary aligned with RBI/Chartered Building Engineer code of conduct
- Processing Efficiency: Automated analysis replacing weeks of manual review with hours of AI-assisted checking
System Capabilities
- Multi-agent architecture with 20+ specialized compliance agents
- Multimodal document processing (text, drawings, specifications)
- Spatial reasoning and measurement from architectural plans
- Regulatory knowledge retrieval from Approved Documents and standards
- Product verification against BBA and KIWA databases
- Gateway 2/3 document organization and validation
- Golden Thread documentation generation and management
1. SYSTEM FUNCTIONS
1.1 Core Processing Functions
Gateway 2 Submission Processing
- Document Ingestion: Accept multi-format submissions (PDF, DWG, specifications)
- Document Classification: Automatically categorize by document type and Building Regulation relevance
- Completeness Validation: Check against Gateway 2 submission requirements per Build UK guidance
- Compliance Analysis: Execute multi-agent compliance checking across all applicable Parts A-T
- Report Generation: Produce comprehensive compliance commentary with evidence trails
- Gap Identification: Flag missing information or non-compliances with specific recommendations
Gateway 3 Support
- Completion Certificate Readiness: Assess documentation completeness for Gateway 3 submission
- As-Built Validation: Compare as-built documentation against approved Gateway 2 submission
- Change Documentation: Track and validate variations from original approval
- Final Compliance Verification: Confirm all conditions satisfied and works completed as approved
Golden Thread Management
- Structured Information Creation: Generate Golden Thread documentation per Building Safety Act requirements
- Version Control: Maintain change history throughout project lifecycle
- Stakeholder Access Management: Provide appropriate access levels for different project participants
- BSR Portal Integration: Format documentation for submission to Building Safety Regulator systems
- Lifecycle Maintenance: Support ongoing updates during construction and post-occupation phases
1.2 Analysis Functions
Spatial Analysis
- Measurement Operations: Calculate lengths, areas, volumes, clearances from submitted drawings
- Spatial Relationship Modeling: Understand topological relationships between building elements
- Path Analysis: Evaluate circulation routes, means of escape, accessible routes
- Visibility Analysis: Assess sightlines, protected views, overlooking considerations
- Proximity Calculations: Measure distances between elements for compliance checking
Compliance Verification
- Rule-Based Checking: Validate explicit requirements (dimensions, ratings, specifications)
- Performance-Based Assessment: Analyze designs against performance objectives
- Cross-Part Validation: Identify conflicts between different Building Regulation requirements
- Scenario Modeling: Simulate occupancy, egress, acoustic performance, energy use
- Product Validation: Verify specified products against approved standards and certifications
Documentation Functions
- Evidence Collection: Link findings to specific submission documents with page/drawing references
- Regulatory Citation: Reference specific Approved Document sections, British Standards, guidance
- Recommendation Generation: Provide actionable suggestions for addressing identified issues
- Confidence Scoring: Assign confidence levels to automated determinations
- Escalation Flagging: Identify cases requiring expert human review
2. DEVELOPMENT APPROACH
2.1 Development Philosophy
Comprehensive Coverage
- All Parts A-T: System addresses entire Building Regulations scope, not selective subset
- No Gaps: Ensure no regulation part can be overlooked in analysis
- Interconnected Requirements: Recognize cross-part dependencies and interactions
- Future-Proof: Architecture supports addition of new requirements as regulations evolve
Realistic Assessment Over Optimism
- Critical Evaluation: Identify genuine challenges and limitations upfront
- Feasibility Focus: Prioritize proven technologies and achievable goals
- Transparent Limitations: Clearly communicate what system can and cannot determine
- Conservative Bias: Err toward stricter interpretation when regulatory ambiguity exists
Detailed Specification Before Implementation
- Thorough Planning: Complete architectural design before coding begins
- Clear Interfaces: Define data structures and APIs between components
- Test Cases: Develop validation scenarios based on real-world submissions
- Iterative Refinement: Plan for learning and improvement from initial deployments
2.2 Processing Methodology
Pipeline Architecture
Submission β Ingestion β Classification β Spatial Extraction β
Storage β Retrieval β Multi-Agent Analysis β Validation β
Report Generation β Golden Thread Update β Output
Sequential Processing Stages
Stage 1: Document Ingestion (5-10 minutes)
- Parse PDF submissions
- Extract text content and metadata
- Segment architectural drawings from specifications
- Initial quality assessment
- Generate document inventory
Stage 2: Spatial Processing (15-30 minutes)
- Run FloorplanTransformation on architectural drawings
- Extract vector representations of building elements
- Classify rooms, walls, doors, stairs, structural elements
- Calculate dimensions and spatial relationships
- Build graph database of building topology
Stage 3: Knowledge Retrieval (Concurrent)
- Query RAG system for relevant regulatory requirements
- Retrieve applicable Approved Document sections
- Identify similar precedent cases
- Pull product certification databases
- Assemble context for each specialist agent
Stage 4: Multi-Agent Analysis (20-40 minutes)
- Dispatch submission to relevant Part-specific agents
- Execute parallel compliance checking across all Parts
- Perform cross-part validation
- Aggregate findings and resolve conflicts
- Generate evidence-based determinations
Stage 5: Report Generation (5-10 minutes)
- Synthesize multi-agent findings
- Structure compliance commentary per Gateway requirements
- Generate Golden Thread documentation
- Package outputs for delivery
- Create audit trail
Total Processing Time: 45-90 minutes per submission
2.3 Deployment Considerations
Platform: Isambard AI Supercomputer
- Hardware: Nvidia GH200 Grace-Hopper superchips
- Operating System: Linux-based (Ubuntu or similar)
- Advantages: Massive parallel processing capability, high-bandwidth memory, ideal for large language models
- Challenges: Windows software compatibility (FloorplanTransformation)
Windows Dependency Resolution
Problem: FloorplanTransformation tool is Windows-only Solution Options:
- Wine/Proton Compatibility Layer: Run Windows executable on Linux via Wine emulator
- Separate Windows Preprocessing Server: Dedicated Windows VM for FloorplanTransformation, feed results to Linux main system
- Alternative Tool Development: Develop Linux-native replacement using computer vision models
- Hybrid Approach: Use FloorplanTransformation for training data generation, deploy alternative for production
Geographic Calibration
- Ensure cost databases reflect UK construction pricing
- Validate dimensional standards against UK practice (metric, UK-specific standards)
- Align terminology with UK Building Regulations language
- Reference UK-specific product certification bodies (BBA, KIWA, BSI)
3. SYSTEM ARCHITECTURE
3.1 High-Level Architecture
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SUBMISSION INTERFACE β
β - Web portal / API for document upload β
β - Authentication and project management β
β - Progress tracking and notifications β
βββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββ
β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DOCUMENT INGESTION & PROCESSING LAYER β
β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββ β
β β PDF Parser β β OCR Engine β β Document β β
β β (PyMuPDF) β β (if needed) β β Classifier β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββ β
β β β β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β FloorplanTransformation Engine β β
β β (Windows compatibility via Wine/separate server) β β
β β β Extracts spatial vector data from drawings β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Spatial Analysis & Graph Building β β
β β β Identifies rooms, walls, doors, stairs β β
β β β Calculates measurements and relationships β β
β β β Constructs building topology graph β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββ
β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β STORAGE LAYER β
β β
β ββββββββββββββββββ ββββββββββββββββββ ββββββββββββββββ β
β β Vector Store β β Graph Database β β Relational DBβ β
β β (Milvus) β β (Neo4j) β β (PostgreSQL) β β
β β β β β β β β
β β β’ Document β β β’ Spatial β β β’ Metadata β β
β β embeddings β β topology β β β’ Projects β β
β β β’ Regulatory β β β’ Compliance β β β’ Users β β
β β text β β chains β β β’ Products β β
β β β’ Precedents β β β’ Golden Threadβ β β’ History β β
β ββββββββββββββββββ ββββββββββββββββββ ββββββββββββββββ β
β β
βββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββ
β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β RAG SYSTEM (Multimodal) β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Text Retrieval System β β
β β β’ Approved Documents A-T (chunked & embedded) β β
β β β’ British Standards (BS, BS EN) β β
β β β’ Guidance documents (BSR, NHBC, etc.) β β
β β β’ Historical precedents and interpretations β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Visual Retrieval System β β
β β β’ Approved Document diagrams (extracted & indexed) β β
β β β’ Reference construction details β β
β β β’ Visual similarity search for diagram comparison β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Product Database β β
β β β’ BBA approved products β β
β β β’ KIWA certifications β β
β β β’ CE marking database β β
β β β’ Manufacturer specifications β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββ
β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MULTI-AGENT COMPLIANCE FRAMEWORK β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Master Orchestrator Agent β β
β β β’ Submission analysis & routing β β
β β β’ Agent coordination β β
β β β’ Conflict resolution β β
β β β’ Report synthesis β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββΌβββββββββββββββββ β
β β β β β
β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ β
β β Part A β β Part B β β Part C β...β Part T β β
β β Agent β β Agent β β Agent β β Agent β β
β β β β β β β β β β
β β Structureβ β Fire β β Site/ β β Broadbandβ β
β β β β Safety β β Moisture β β β β
β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ β
β β
β Each agent has: β
β β’ Specialized knowledge base (RAG-retrieved) β
β β’ Domain-specific tools β
β β’ Compliance checking logic β
β β’ Standardized output format β
β β
βββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββ
β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β TOOL LAYER β
β β
β ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββ β
β β Measurement β β Spatial Reasoningβ β Scenario β β
β β Tools β β Tools β β Planning β β
β β β β β β Tools β β
β β β’ Distances β β β’ Path finding β β β’ Egress β β
β β β’ Areas β β β’ Adjacency β β β’ Acoustic β β
β β β’ Volumes β β β’ Containment β β β’ Energy β β
β β β’ Clearances β β β’ Visibility β β β’ Occupancy β β
β ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββ β
β β
β ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββ β
β β Comparison β β Product Checker β β Calculation β β
β β Tools β β Tools β β Tools β β
β β β β β β β β
β β β’ Design vs β β β’ BBA database β β β’ U-values β β
β β diagrams β β β’ KIWA database β β β’ SAP/SBEM β β
β β β’ As-built vs β β β’ CE marking β β β’ Loads β β
β β approved β β β’ Standards β β β’ Acoustics β β
β ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββ β
β β
βββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββ
β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β OUTPUT GENERATION LAYER β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Compliance Report Generator β β
β β β’ Gateway 2/3 format compliance commentary β β
β β β’ Evidence trails and regulatory citations β β
β β β’ Confidence scores and escalation flags β β
β β β’ Actionable recommendations β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Golden Thread Documentation Generator β β
β β β’ Structured information per Building Safety Act β β
β β β’ Version control and change tracking β β
β β β’ Stakeholder-appropriate views β β
β β β’ BSR portal formatted outputs β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Visualization & Evidence System β β
β β β’ Issue highlighting on drawings β β
β β β’ Interactive compliance dashboard β β
β β β’ Evidence package assembly β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
3.2 Component Details
3.2.1 Document Ingestion Layer
Purpose: Accept and process diverse submission documents into standardized formats
Components:
- PDF Parser (PyMuPDF): Extract text, images, metadata from PDF submissions
- OCR Engine (Tesseract/PaddleOCR): Handle scanned or low-quality documents
- Document Classifier: Categorize documents by type (architectural plans, specifications, calculations, reports)
- Page Segmentation: Separate multi-page documents into logical sections
- Quality Assessment: Flag low-quality or incomplete documents early
Outputs:
- Structured text content
- Extracted images (drawings, photos, diagrams)
- Document metadata (title, author, date, version)
- Document classification labels
- Quality scores
3.2.2 Spatial Processing Layer
Purpose: Convert raster architectural drawings into structured spatial representations
FloorplanTransformation Engine:
- Input: PDF/image format architectural plans
- Process: Computer vision-based element detection and vectorization
- Output: Vector representations of building elements with classifications
Linux Compatibility Solutions:
- Wine Emulator: Run Windows .exe via compatibility layer
- Dedicated Windows Server: Separate preprocessing service
- API Wrapper: Encapsulate Windows tool behind REST API
- Alternative CV Models: Develop replacement using open-source tools
Spatial Analysis Pipeline:
# Pseudo-code example
def process_floorplan(pdf_path: str) -> SpatialData:
# Extract plan images from PDF
images = extract_plan_images(pdf_path)
# Run FloorplanTransformation (via Wine or API)
vector_data = floorplan_transformation(images)
# Classify elements
rooms = classify_rooms(vector_data)
walls = classify_walls(vector_data)
doors = classify_doors(vector_data)
stairs = classify_stairs(vector_data)
# Calculate measurements
measurements = calculate_dimensions(vector_data)
# Build topology
topology = build_spatial_graph(rooms, walls, doors, stairs)
return SpatialData(
rooms=rooms,
walls=walls,
doors=doors,
stairs=stairs,
measurements=measurements,
topology=topology
)
Graph Database Population:
- Create nodes for each spatial element (rooms, doors, stairs, etc.)
- Define relationships (connects, contains, adjacent_to, above, below)
- Store geometric properties (dimensions, coordinates, areas)
- Enable graph queries for compliance checking
3.2.3 Storage Layer
Milvus Vector Database:
- Purpose: Store and retrieve document embeddings for semantic search
- Contents:
- Regulatory text embeddings (Approved Documents, Standards)
- Submission document embeddings
- Historical precedent embeddings
- Visual embeddings (diagram similarity)
- Indexing: HNSW (Hierarchical Navigable Small World) for fast approximate nearest neighbor search
- Partitioning: Separate collections per Building Regulation Part for efficient retrieval
Neo4j Graph Database:
- Purpose: Model spatial relationships and compliance chains
- Node Types:
- Building elements (rooms, walls, doors, stairs)
- Compliance requirements (regulations, sub-clauses)
- Evidence items (document references, measurements)
- Golden Thread information items
- Relationship Types:
- Spatial: connects, contains, adjacent_to, above, below
- Compliance: requires, satisfies, conflicts_with
- Evidence: references, supports, contradicts
- Provenance: derived_from, modified_from, supersedes
- Query Patterns:
- Path finding (shortest egress route)
- Subgraph extraction (all elements in fire compartment)
- Dependency tracking (requirements affected by design change)
PostgreSQL Relational Database:
- Purpose: Store structured metadata and operational data
- Schema:
- Projects (ID, name, address, client, status)
- Submissions (ID, project, gateway, date, status)
- Users (authentication, roles, permissions)
- Products (manufacturer, model, certifications)
- Audit logs (actions, timestamps, users)
- Processing history (submission, agent, runtime, outcome)
3.2.4 RAG System (Retrieval-Augmented Generation)
Text Retrieval System:
Indexing Strategy:
Approved Documents β Chunked by regulation section β Embedded β Indexed in Milvus
β
Each chunk includes:
- Text content
- Regulation reference (e.g., "Part B1, Section 2.5")
- Document source
- Effective date
- Related diagrams/tables
- Keywords
Embedding Model:
- NV-Embed-v2 or similar high-performance model
- 768-dimensional dense vectors
- Trained on technical/regulatory text for domain relevance
Retrieval Process:
- Query Construction: Agent formulates query based on compliance check needed
- Embedding: Query embedded using same model as corpus
- Vector Search: Retrieve top-K most similar chunks from Milvus
- Reranking (optional): Use cross-encoder model to refine results
- Context Assembly: Combine retrieved chunks with query for LLM
Visual Retrieval System:
Diagram Corpus:
- Extract all diagrams from Approved Documents
- Annotate with metadata (Part, section, diagram number, caption)
- Generate visual embeddings (CLIP or similar vision-language model)
- Index in separate Milvus collection
Visual Similarity Search:
- Compare submitted designs against reference diagrams
- Identify similar configurations or details
- Flag deviations from approved construction methods
Product Database Integration:
- BBA Certificates: Regularly updated database of approved products
- KIWA Certifications: European product approvals relevant to UK
- CE Marking Database: Products complying with European standards
- Search Functionality: Query by product name, manufacturer, application, performance criteria
3.2.5 Multi-Agent Framework
Master Orchestrator Agent:
Responsibilities:
- Submission Analysis: Determine which Building Regulation Parts apply
- Agent Dispatching: Route submission to relevant specialist agents
- Parallel Coordination: Manage concurrent agent execution
- Conflict Resolution: Identify and resolve inter-agent conflicts
- Report Synthesis: Aggregate findings into unified output
Process Flow:
def process_submission(submission: Submission) -> ComplianceReport:
# 1. Analyze submission
relevant_parts = identify_applicable_parts(submission)
# 2. Dispatch to agents (parallel execution)
agent_results = {}
with ThreadPoolExecutor() as executor:
futures = {
executor.submit(agent.check_compliance, submission): part
for part, agent in specialist_agents.items()
if part in relevant_parts
}
for future in as_completed(futures):
part = futures[future]
agent_results[part] = future.result()
# 3. Validate cross-part consistency
conflicts = detect_conflicts(agent_results)
# 4. Synthesize report
report = synthesize_report(
agent_results=agent_results,
conflicts=conflicts,
submission=submission
)
return report
Specialist Agents (Parts A-T):
Agent Architecture (consistent across all Parts):
class BuildingRegulationAgent:
"""
Base class for all Part-specific agents.
"""
def __init__(
self,
part_id: str,
rag_system: RAGSystem,
spatial_db: Neo4jClient,
tools: ToolRegistry
):
self.part_id = part_id
self.rag = rag_system
self.spatial_db = spatial_db
self.tools = tools
# Load Part-specific knowledge
self.knowledge_base = self._load_knowledge()
def check_compliance(
self,
submission: Submission
) -> List[ComplianceCheck]:
"""
Main entry point for compliance checking.
Returns list of ComplianceCheck objects with:
- Finding (pass/fail/unclear)
- Evidence (specific references)
- Reasoning (explanation)
- Confidence score
- Recommendations (if non-compliant)
"""
checks = []
# 1. Extract relevant information
relevant_data = self._extract_relevant_data(submission)
# 2. Retrieve regulatory requirements
requirements = self._get_requirements(relevant_data)
# 3. Execute compliance checks
for requirement in requirements:
check = self._evaluate_compliance(
requirement=requirement,
data=relevant_data
)
checks.append(check)
# 4. Cross-validate findings
checks = self._cross_validate(checks)
return checks
def _load_knowledge(self) -> Dict:
"""
Load Part-specific knowledge from RAG system.
"""
# Retrieve relevant Approved Document sections
# Retrieve applicable standards
# Retrieve historical precedents
pass
def _get_requirements(self, data: Dict) -> List[Requirement]:
"""
Identify which specific requirements apply based on data.
"""
# Query RAG system for applicable requirements
# Filter by building type, use, characteristics
pass
def _evaluate_compliance(
self,
requirement: Requirement,
data: Dict
) -> ComplianceCheck:
"""
Evaluate specific requirement against submission data.
"""
# Use tools to measure/calculate as needed
# Compare against requirement criteria
# Generate evidence trail
# Assign confidence score
pass
Agent Specializations:
Each Part agent inherits from base class and adds specialized capabilities:
Part A (Structure) Agent:
- Load calculation tools
- Structural material verification
- Foundation adequacy assessment
- Disproportionate collapse checking (for HRBs)
Part B (Fire Safety) Agent:
- Egress path modeling
- Travel distance calculation
- Compartmentation validation
- Fire resistance verification
- Occupancy load calculation
Part C (Site Preparation) Agent:
- Contamination assessment
- Radon risk evaluation
- Ground gas analysis
- Moisture protection checking
[Parts D-T]: Each with domain-specific tools and knowledge
Agent Communication:
- Shared access to spatial graph database
- Message passing for cross-dependencies
- Conflict notification to orchestrator
- Evidence sharing between related agents
3.2.6 Tool Layer
Measurement Tools:
class MeasurementTools:
"""
Spatial measurement capabilities.
"""
def measure_distance(
self,
point_a: Coordinate,
point_b: Coordinate,
path_type: str = 'straight' # or 'along_route'
) -> float:
"""
Calculate distance between points.
"""
if path_type == 'straight':
return euclidean_distance(point_a, point_b)
elif path_type == 'along_route':
# Query graph DB for path
path = self.spatial_db.shortest_path(point_a, point_b)
return sum_path_length(path)
def calculate_area(
self,
room_id: str
) -> float:
"""
Calculate room floor area from polygon vertices.
"""
vertices = self.spatial_db.get_room_vertices(room_id)
return polygon_area(vertices)
def measure_clearance(
self,
element_id: str,
direction: str
) -> float:
"""
Measure clearance in specified direction.
"""
element_bounds = self.spatial_db.get_element_bounds(element_id)
obstacles = self.spatial_db.find_obstacles(
element_bounds,
direction
)
return calculate_clearance(element_bounds, obstacles, direction)
Spatial Reasoning Tools:
class SpatialReasoningTools:
"""
Higher-level spatial analysis.
"""
def find_egress_routes(
self,
start_room: str,
building_id: str
) -> List[EgressRoute]:
"""
Find all egress routes from room to building exit.
"""
query = """
MATCH path = (start:Room {id: $start_room})-[:CONNECTS*]->(exit:Exit)
WHERE exit.building_id = $building_id
RETURN path
ORDER BY length(path)
"""
paths = self.spatial_db.query(query, start_room=start_room, building_id=building_id)
routes = []
for path in paths:
route = EgressRoute(
path=path,
distance=calculate_path_distance(path),
doors=extract_doors_from_path(path),
stairs=extract_stairs_from_path(path)
)
routes.append(route)
return routes
def check_accessibility(
self,
route: Route,
requirements: AccessibilityRequirements
) -> AccessibilityAssessment:
"""
Evaluate if route meets accessibility requirements.
"""
issues = []
# Check widths
for segment in route.segments:
if segment.width < requirements.min_width:
issues.append(f"Width {segment.width}mm < {requirements.min_width}mm at {segment.location}")
# Check gradients
for ramp in route.ramps:
if ramp.gradient > requirements.max_gradient:
issues.append(f"Gradient {ramp.gradient} > {requirements.max_gradient} at {ramp.location}")
# Check door widths
for door in route.doors:
if door.clear_width < requirements.min_door_width:
issues.append(f"Door width {door.clear_width}mm < {requirements.min_door_width}mm at {door.location}")
return AccessibilityAssessment(
compliant=(len(issues) == 0),
issues=issues
)
Scenario Planning Tools:
class ScenarioPlanningTools:
"""
Simulation and modeling capabilities.
"""
def simulate_egress(
self,
building: Building,
occupancy: int,
fire_location: str
) -> EgressSimulationResult:
"""
Simulate building evacuation scenario.
"""
# Initialize population
occupants = distribute_occupants(building, occupancy)
# Define fire spread
fire_model = create_fire_model(building, fire_location)
# Run evacuation simulation
time_steps = []
current_time = 0
while not all_evacuated(occupants):
# Move occupants toward exits
occupants = move_occupants(occupants, building, fire_model)
# Update fire spread
fire_model = update_fire_model(fire_model, current_time)
# Check for casualties
casualties = check_casualties(occupants, fire_model)
# Record state
time_steps.append(SimulationState(
time=current_time,
occupants=occupants,
fire=fire_model,
casualties=casualties
))
current_time += SIMULATION_TIMESTEP
if current_time > MAX_SIMULATION_TIME:
break
return EgressSimulationResult(
evacuation_time=current_time,
casualties=sum(ts.casualties for ts in time_steps),
bottlenecks=identify_bottlenecks(time_steps),
time_steps=time_steps
)
def model_acoustic_performance(
self,
wall: Wall,
source_room: Room,
receiver_room: Room
) -> AcousticPerformance:
"""
Predict sound insulation performance.
"""
# Calculate direct transmission
direct_loss = calculate_transmission_loss(wall.construction)
# Calculate flanking paths
flanking_loss = calculate_flanking_transmission(
wall=wall,
source_room=source_room,
receiver_room=receiver_room
)
# Combine paths
total_loss = combine_transmission_paths(direct_loss, flanking_loss)
return AcousticPerformance(
sound_reduction_index=total_loss,
meets_requirement=total_loss >= REQUIREMENT_DnTw
)
Comparison Tools:
class ComparisonTools:
"""
Compare designs against reference standards.
"""
def compare_against_approved_diagram(
self,
submitted_design: SpatialData,
reference_diagram_id: str
) -> ComparisonResult:
"""
Compare submitted design against Approved Document diagram.
"""
# Retrieve reference diagram
reference = self.rag.retrieve_diagram(reference_diagram_id)
# Extract comparable features
submitted_features = extract_features(submitted_design)
reference_features = extract_features(reference)
# Compare
differences = []
for feature_name, submitted_value in submitted_features.items():
reference_value = reference_features.get(feature_name)
if reference_value is None:
differences.append(f"{feature_name}: Not in reference diagram")
elif not values_match(submitted_value, reference_value, tolerance=0.05):
differences.append(
f"{feature_name}: Submitted {submitted_value} vs Reference {reference_value}"
)
return ComparisonResult(
matches=(len(differences) == 0),
differences=differences,
similarity_score=calculate_similarity(submitted_features, reference_features)
)
def compare_as_built_to_approved(
self,
as_built: Submission,
approved: Submission
) -> ChangeReport:
"""
Identify changes between approved and as-built submissions.
"""
changes = []
# Compare spatial data
spatial_changes = self._compare_spatial_data(
as_built.spatial_data,
approved.spatial_data
)
changes.extend(spatial_changes)
# Compare specifications
spec_changes = self._compare_specifications(
as_built.specifications,
approved.specifications
)
changes.extend(spec_changes)
# Categorize changes by significance
critical_changes = [c for c in changes if c.affects_compliance]
minor_changes = [c for c in changes if not c.affects_compliance]
return ChangeReport(
critical_changes=critical_changes,
minor_changes=minor_changes,
requires_revised_approval=(len(critical_changes) > 0)
)
Product Verification Tools:
class ProductVerificationTools:
"""
Check specified products against certification databases.
"""
def verify_bba_approval(
self,
product_name: str,
manufacturer: str,
application: str
) -> ApprovalStatus:
"""
Check if product has current BBA approval.
"""
# Query BBA database
results = self.bba_db.search(
product=product_name,
manufacturer=manufacturer,
application=application
)
if not results:
return ApprovalStatus(
approved=False,
message="Product not found in BBA database"
)
# Check approval is current
most_recent = max(results, key=lambda r: r.certificate_date)
if most_recent.expired:
return ApprovalStatus(
approved=False,
message=f"BBA approval expired on {most_recent.expiry_date}",
certificate_number=most_recent.certificate_number
)
return ApprovalStatus(
approved=True,
certificate_number=most_recent.certificate_number,
certificate_date=most_recent.certificate_date,
expiry_date=most_recent.expiry_date
)
def check_ce_marking(
self,
product: Product,
standard: str
) -> CEMarkingStatus:
"""
Verify product has CE marking to specified standard.
"""
# Query CE marking database
marking = self.ce_db.get_marking(
product_code=product.code,
manufacturer_id=product.manufacturer_id
)
if not marking:
return CEMarkingStatus(
marked=False,
message="No CE marking found for product"
)
if standard not in marking.standards:
return CEMarkingStatus(
marked=True,
compliant=False,
message=f"CE marked but not to required standard {standard}",
standards=marking.standards
)
return CEMarkingStatus(
marked=True,
compliant=True,
standards=marking.standards,
notified_body=marking.notified_body
)
3.2.7 Output Generation Layer
Compliance Report Generator:
class ComplianceReportGenerator:
"""
Generate structured compliance reports for Gateway submissions.
"""
def generate_gateway2_report(
self,
submission: Submission,
agent_results: Dict[str, List[ComplianceCheck]],
conflicts: List[Conflict]
) -> GatewayReport:
"""
Create comprehensive Gateway 2 compliance report.
"""
report = GatewayReport(
submission_id=submission.id,
date=datetime.now(),
building=submission.building_details
)
# Executive summary
report.executive_summary = self._generate_executive_summary(
agent_results,
conflicts
)
# Part-by-part findings
for part, checks in agent_results.items():
part_section = self._generate_part_section(
part=part,
checks=checks
)
report.add_section(part_section)
# Cross-part issues
if conflicts:
conflict_section = self._generate_conflict_section(conflicts)
report.add_section(conflict_section)
# Recommendations
report.recommendations = self._prioritize_recommendations(
agent_results,
conflicts
)
# Evidence package
report.evidence = self._compile_evidence(agent_results)
# Confidence assessment
report.overall_confidence = self._calculate_overall_confidence(
agent_results
)
return report
def _generate_executive_summary(
self,
agent_results: Dict,
conflicts: List
) -> str:
"""
Create executive summary of key findings.
"""
total_checks = sum(len(checks) for checks in agent_results.values())
compliant = sum(
1 for checks in agent_results.values()
for check in checks
if check.status == "compliant"
)
non_compliant = sum(
1 for checks in agent_results.values()
for check in checks
if check.status == "non_compliant"
)
requires_clarification = total_checks - compliant - non_compliant
summary = f"""
EXECUTIVE SUMMARY
Total compliance checks performed: {total_checks}
- Compliant: {compliant} ({compliant/total_checks*100:.1f}%)
- Non-compliant: {non_compliant} ({non_compliant/total_checks*100:.1f}%)
- Requires clarification: {requires_clarification} ({requires_clarification/total_checks*100:.1f}%)
Cross-part conflicts identified: {len(conflicts)}
CRITICAL ISSUES REQUIRING IMMEDIATE ATTENTION:
"""
# Add critical issues
critical_issues = [
check for checks in agent_results.values()
for check in checks
if check.status == "non_compliant" and check.priority == "critical"
]
for i, issue in enumerate(critical_issues, 1):
summary += f"\n{i}. {issue.regulation}: {issue.requirement}"
return summary
def _generate_part_section(
self,
part: str,
checks: List[ComplianceCheck]
) -> ReportSection:
"""
Generate detailed section for specific Building Regulation Part.
"""
section = ReportSection(
title=f"Part {part} - {PART_NAMES[part]}",
checks=checks
)
# Group checks by sub-regulation
grouped = self._group_checks_by_regulation(checks)
for regulation, regulation_checks in grouped.items():
subsection = f"\n\n### {regulation}\n\n"
for check in regulation_checks:
subsection += self._format_compliance_check(check)
section.add_content(subsection)
return section
def _format_compliance_check(
self,
check: ComplianceCheck
) -> str:
"""
Format individual compliance check for report.
"""
# Status icon
if check.status == "compliant":
status_icon = "β"
elif check.status == "non_compliant":
status_icon = "β"
else:
status_icon = "?"
# Build formatted text
text = f"""
{status_icon} **{check.requirement}**
Status: {check.status.upper()}
Confidence: {check.confidence:.0%}
Priority: {check.priority.upper()}
**Evidence:**
{self._format_evidence_list(check.evidence)}
**Reasoning:**
{check.reasoning}
"""
if check.recommendations:
text += f"""
**Recommendations:**
{self._format_recommendations(check.recommendations)}
"""
if check.regulatory_references:
text += f"""
**Regulatory References:**
{self._format_references(check.regulatory_references)}
"""
return text
Golden Thread Documentation Generator:
class GoldenThreadGenerator:
"""
Generate and maintain Golden Thread documentation.
"""
def initialize_golden_thread(
self,
project: Project,
gateway2_submission: Submission
) -> GoldenThread:
"""
Create initial Golden Thread structure for project.
"""
golden_thread = GoldenThread(
project_id=project.id,
created_date=datetime.now(),
current_version="1.0"
)
# Building Information
golden_thread.building_info = self._extract_building_info(
gateway2_submission
)
# Design Information
golden_thread.design_info = self._extract_design_info(
gateway2_submission
)
# Safety Case
golden_thread.safety_case = self._generate_safety_case(
gateway2_submission
)
# Compliance Record
golden_thread.compliance_record = self._create_compliance_record(
gateway2_submission
)
# Document Register
golden_thread.document_register = self._create_document_register(
gateway2_submission
)
return golden_thread
def update_golden_thread(
self,
golden_thread: GoldenThread,
change: DesignChange,
authorization: Authorization
) -> GoldenThread:
"""
Update Golden Thread with design change.
"""
# Create new version
new_version = golden_thread.increment_version()
# Record change
new_version.add_change_record(
date=datetime.now(),
change_description=change.description,
affected_elements=change.affected_elements,
justification=change.justification,
authorized_by=authorization.person,
authorization_date=authorization.date
)
# Update affected sections
if change.affects_building_info:
new_version.building_info = self._update_building_info(
golden_thread.building_info,
change
)
if change.affects_design:
new_version.design_info = self._update_design_info(
golden_thread.design_info,
change
)
if change.affects_safety_case:
new_version.safety_case = self._update_safety_case(
golden_thread.safety_case,
change
)
# Re-validate compliance
new_version.compliance_record = self._revalidate_compliance(
new_version,
change
)
# Archive previous version
self._archive_version(golden_thread)
return new_version
def generate_bsr_submission_package(
self,
golden_thread: GoldenThread,
gateway: str # "2" or "3"
) -> BSRSubmissionPackage:
"""
Format Golden Thread for BSR portal submission.
"""
package = BSRSubmissionPackage(
gateway=gateway,
project_id=golden_thread.project_id,
submission_date=datetime.now()
)
# Include required documents per gateway
if gateway == "2":
package.add_document("building_information", golden_thread.building_info)
package.add_document("design_information", golden_thread.design_info)
package.add_document("safety_case", golden_thread.safety_case)
package.add_document("compliance_record", golden_thread.compliance_record)
package.add_document("fire_strategy", golden_thread.fire_strategy)
elif gateway == "3":
package.add_document("completion_certificate_application", ...)
package.add_document("as_built_information", golden_thread.as_built_info)
package.add_document("change_log", golden_thread.change_log)
package.add_document("final_compliance_verification", ...)
package.add_document("operation_and_maintenance_manual", ...)
# Format per BSR requirements
package.format_for_bsr()
return package
4. AGENT DESIGN SPECIFICATIONS
4.1 Standard Agent Design Pattern
All Building Regulation Part agents follow this consistent pattern:
from dataclasses import dataclass
from typing import List, Dict, Optional
from enum import Enum
@dataclass
class ComplianceCheck:
"""
Standard structure for compliance findings.
"""
regulation: str # e.g., "Part B1 - Means of Escape"
requirement: str # What the regulation requires
status: str # "compliant", "non_compliant", "insufficient_info"
evidence: List[str] # Specific evidence from submission
reasoning: str # Explanation of determination
confidence: float # 0.0 to 1.0
priority: str # "critical", "high", "medium", "low"
recommendations: List[str] # Actions if non-compliant
regulatory_references: List[str] # Approved Doc sections, standards
related_checks: List[str] # Links to related findings
class BuildingRegulationPartAgent:
"""
Template for all Part-specific agents.
"""
def __init__(
self,
part_id: str,
rag_system: RAGSystem,
spatial_analyzer: SpatialAnalyzer,
tool_registry: ToolRegistry,
llm_client: LLMClient
):
self.part_id = part_id
self.rag = rag_system
self.spatial = spatial_analyzer
self.tools = tool_registry
self.llm = llm_client
# Load Part-specific knowledge
self.knowledge_base = self._load_regulatory_knowledge()
# Register Part-specific tools
self.specialized_tools = self._register_specialized_tools()
def check_compliance(
self,
submission: Submission,
spatial_data: SpatialData,
specifications: Dict
) -> List[ComplianceCheck]:
"""
Main compliance checking entry point.
Args:
submission: Full Gateway submission
spatial_data: Processed building spatial information
specifications: Extracted technical specifications
Returns:
List of ComplianceCheck objects for all applicable requirements
"""
checks = []
# 1. Identify applicable requirements
requirements = self._identify_applicable_requirements(
submission,
spatial_data,
specifications
)
# 2. Execute checks for each requirement
for requirement in requirements:
check = self._evaluate_requirement(
requirement=requirement,
submission=submission,
spatial_data=spatial_data,
specifications=specifications
)
checks.append(check)
# 3. Cross-validate findings
checks = self._cross_validate_checks(checks)
# 4. Prioritize issues
checks = self._prioritize_checks(checks)
return checks
def _load_regulatory_knowledge(self) -> Dict:
"""
Load Part-specific regulatory knowledge from RAG system.
Returns:
Dictionary containing:
- Approved Document sections
- Relevant British Standards
- Guidance documents
- Historical precedents
- Reference diagrams
"""
# Query RAG for Part-specific content
queries = self._generate_knowledge_queries()
knowledge = {
'approved_doc': [],
'standards': [],
'guidance': [],
'precedents': [],
'diagrams': []
}
for query in queries:
# Text retrieval
text_results = self.rag.retrieve_text(
query=query,
collection=f"part_{self.part_id.lower()}_text",
top_k=20
)
knowledge['approved_doc'].extend(text_results)
# Diagram retrieval
diagram_results = self.rag.retrieve_diagrams(
query=query,
collection=f"part_{self.part_id.lower()}_diagrams",
top_k=5
)
knowledge['diagrams'].extend(diagram_results)
return knowledge
def _identify_applicable_requirements(
self,
submission: Submission,
spatial_data: SpatialData,
specifications: Dict
) -> List[Requirement]:
"""
Determine which specific requirements apply to this building.
Requirements vary based on:
- Building type (dwelling, commercial, HRB, etc.)
- Building use
- Building characteristics (height, occupancy, etc.)
- Design approach (prescriptive vs performance)
"""
# Use LLM with RAG context to determine applicability
building_characteristics = self._extract_characteristics(
submission,
spatial_data,
specifications
)
prompt = f"""
Based on the following building characteristics, identify which
requirements from Part {self.part_id} apply:
Building Characteristics:
{building_characteristics}
Regulatory Context:
{self.knowledge_base['approved_doc']}
List the specific requirements that apply, with justification.
"""
response = self.llm.generate(
prompt=prompt,
temperature=0.1 # Low temperature for consistency
)
requirements = self._parse_requirements(response)
return requirements
def _evaluate_requirement(
self,
requirement: Requirement,
submission: Submission,
spatial_data: SpatialData,
specifications: Dict
) -> ComplianceCheck:
"""
Evaluate a specific requirement against submission.
Process:
1. Extract relevant data using tools
2. Compare against requirement criteria
3. Generate evidence trail
4. Determine compliance status
5. Calculate confidence
6. Generate recommendations if non-compliant
"""
# This is implemented by each specific agent
# with domain-specific logic
raise NotImplementedError
def _cross_validate_checks(
self,
checks: List[ComplianceCheck]
) -> List[ComplianceCheck]:
"""
Cross-validate findings for consistency.
Ensures:
- No contradictory findings
- Related findings are consistent
- Evidence supports conclusions
"""
# Check for contradictions
contradictions = self._find_contradictions(checks)
if contradictions:
# Resolve contradictions (e.g., re-evaluate with more data)
checks = self._resolve_contradictions(checks, contradictions)
# Validate evidence chains
for check in checks:
check = self._validate_evidence(check)
return checks
def _prioritize_checks(
self,
checks: List[ComplianceCheck]
) -> List[ComplianceCheck]:
"""
Assign priority levels to findings.
Priority based on:
- Safety implications
- Likelihood of BSR rejection
- Difficulty of remediation
- Cost implications
"""
for check in checks:
if check.status != "compliant":
check.priority = self._calculate_priority(check)
# Sort by priority
checks.sort(key=lambda c: PRIORITY_ORDER[c.priority])
return checks
4.2 Specific Agent Examples
Part A Agent: Structure
class PartAAgent(BuildingRegulationPartAgent):
"""
Part A: Structure - Checks structural adequacy and safety.
Key areas:
- Loading (dead loads, imposed loads, wind loads, snow loads)
- Structural integrity and stability
- Disproportionate collapse (for HRBs)
- Ground movement
- Foundations
"""
def __init__(self, *args, **kwargs):
super().__init__(part_id="A", *args, **kwargs)
# Part A specific tools
self.load_calculator = LoadCalculator()
self.structural_analyzer = StructuralAnalyzer()
def _evaluate_requirement(
self,
requirement: Requirement,
submission: Submission,
spatial_data: SpatialData,
specifications: Dict
) -> ComplianceCheck:
"""
Evaluate structural requirement.
"""
if requirement.type == "loading":
return self._check_loading(requirement, spatial_data, specifications)
elif requirement.type == "disproportionate_collapse":
return self._check_disproportionate_collapse(requirement, spatial_data, specifications)
elif requirement.type == "foundations":
return self._check_foundations(requirement, specifications)
else:
return self._generic_structural_check(requirement, spatial_data, specifications)
def _check_loading(
self,
requirement: Requirement,
spatial_data: SpatialData,
specifications: Dict
) -> ComplianceCheck:
"""
Check loading assumptions are appropriate.
Requirements:
- Dead loads: weight of structure and fixed equipment
- Imposed loads: occupancy loads per BS EN 1991-1-1
- Wind loads: per BS EN 1991-1-4
- Snow loads: per BS EN 1991-1-3
"""
# Extract loading specifications
loading_spec = specifications.get('structural_calculations', {}).get('loading', {})
# Validate against standards
issues = []
# Check imposed loads
for room in spatial_data.rooms:
room_use = self._determine_room_use(room)
required_imposed_load = IMPOSED_LOADS_BS_EN_1991[room_use]
specified_load = loading_spec.get(room.id, {}).get('imposed_load')
if specified_load is None:
issues.append(f"No imposed load specified for {room.name}")
elif specified_load < required_imposed_load:
issues.append(
f"{room.name}: Imposed load {specified_load} kN/mΒ² "
f"< required {required_imposed_load} kN/mΒ²"
)
if issues:
return ComplianceCheck(
regulation="Part A - Loading",
requirement="Loading assumptions must comply with BS EN 1991",
status="non_compliant" if any("specified" in i for i in issues) else "insufficient_info",
evidence=issues,
reasoning="Loading specifications do not meet BS EN 1991 requirements for all areas.",
confidence=0.90,
priority="high",
recommendations=[
"Review imposed load specifications per BS EN 1991-1-1 Table 6.2",
"Ensure all room types have appropriate loading specified",
"Provide structural engineer's justification for any reduced loads"
],
regulatory_references=["BS EN 1991-1-1", "Approved Document A Section 2"]
)
else:
return ComplianceCheck(
regulation="Part A - Loading",
requirement="Loading assumptions comply with standards",
status="compliant",
evidence=["Loading specifications reviewed", "All loads meet or exceed BS EN 1991 requirements"],
reasoning="Structural loading specifications are adequate per BS EN 1991 series.",
confidence=0.85,
priority="medium",
recommendations=[],
regulatory_references=["BS EN 1991-1-1"]
)
def _check_disproportionate_collapse(
self,
requirement: Requirement,
spatial_data: SpatialData,
specifications: Dict
) -> ComplianceCheck:
"""
Check disproportionate collapse provisions for HRBs.
Requirement (Part A3):
Buildings must be designed so that localized failure doesn't cause
disproportionate collapse.
For HRBs (Class 2B): Specific provisions required:
- Effective horizontal ties
- Effective vertical ties
- Key element design
- Or systematic risk assessment
"""
building_class = self._determine_building_class(spatial_data, specifications)
if building_class != "2B":
# Not HRB, standard provisions sufficient
return ComplianceCheck(
regulation="Part A3 - Disproportionate Collapse",
requirement="Building class determined, Class 2B provisions not required",
status="compliant",
evidence=[f"Building class: {building_class}", "Class 2B requirements not applicable"],
reasoning="Building does not fall into Class 2B (HRB) category requiring enhanced disproportionate collapse provisions.",
confidence=0.95,
priority="low",
recommendations=[],
regulatory_references=["Approved Document A Section 5"]
)
# Class 2B building - check for provisions
structural_strategy = specifications.get('structural_calculations', {}).get('disproportionate_collapse', '')
has_ties = 'ties' in structural_strategy.lower() or 'tying' in structural_strategy.lower()
has_key_elements = 'key element' in structural_strategy.lower()
has_risk_assessment = 'risk assessment' in structural_strategy.lower()
if not (has_ties or has_key_elements or has_risk_assessment):
return ComplianceCheck(
regulation="Part A3 - Disproportionate Collapse (Class 2B)",
requirement="HRBs must have disproportionate collapse provisions",
status="insufficient_info",
evidence=[
"Building is Class 2B (HRB)",
"No disproportionate collapse strategy evident"
],
reasoning="Class 2B buildings require specific provisions per Approved Document A Section 5. No strategy documented.",
confidence=0.95,
priority="critical",
recommendations=[
"Provide structural engineer's disproportionate collapse strategy",
"Options:",
" 1. Effective horizontal and vertical ties (typical approach)",
" 2. Key element design (elements to withstand 34 kN/mΒ²)",
" 3. Systematic risk assessment per BS EN 1991-1-7",
"Submit calculations demonstrating chosen approach"
],
regulatory_references=["Approved Document A Section 5", "BS EN 1992-1-1 Section 9"]
)
# Strategy present - validate it
return ComplianceCheck(
regulation="Part A3 - Disproportionate Collapse (Class 2B)",
requirement="Disproportionate collapse strategy for HRB",
status="compliant",
evidence=[
"Disproportionate collapse strategy provided",
"Ties" if has_ties else "",
"Key elements" if has_key_elements else "",
"Risk assessment" if has_risk_assessment else ""
],
reasoning="Disproportionate collapse provisions documented for Class 2B building.",
confidence=0.80,
priority="high",
recommendations=[
"Verify structural calculations support stated strategy",
"Ensure design reviewed by Building Safety Regulator"
],
regulatory_references=["Approved Document A Section 5"]
)
Part B Agent: Fire Safety
class PartBAgent(BuildingRegulationPartAgent):
"""
Part B: Fire Safety - Most complex and critical agent.
Sections:
- B1: Means of escape
- B2: Internal fire spread (linings)
- B3: Internal fire spread (structure)
- B4: External fire spread
- B5: Access and facilities for fire service
This is often the primary cause of Gateway rejections.
"""
def __init__(self, *args, **kwargs):
super().__init__(part_id="B", *args, **kwargs)
# Part B specific tools
self.egress_simulator = EgressSimulator()
self.compartmentation_checker = CompartmentationChecker()
self.fire_resistance_validator = FireResistanceValidator()
def _evaluate_requirement(
self,
requirement: Requirement,
submission: Submission,
spatial_data: SpatialData,
specifications: Dict
) -> ComplianceCheck:
"""
Evaluate fire safety requirement.
"""
if requirement.section == "B1":
return self._check_means_of_escape(requirement, spatial_data, specifications)
elif requirement.section == "B2":
return self._check_internal_linings(requirement, specifications)
elif requirement.section == "B3":
return self._check_fire_resistance(requirement, spatial_data, specifications)
elif requirement.section == "B4":
return self._check_external_fire_spread(requirement, spatial_data, specifications)
elif requirement.section == "B5":
return self._check_fire_service_access(requirement, spatial_data, specifications)
def _check_means_of_escape(
self,
requirement: Requirement,
spatial_data: SpatialData,
specifications: Dict
) -> ComplianceCheck:
"""
Check means of escape provisions (B1).
Key requirements:
- Travel distances to exits
- Number of escape routes
- Width of escape routes
- Protected stairways
- Emergency lighting
- Signage
For HRBs: Enhanced requirements including 2.5 minute evacuation time.
"""
is_hrb = specifications.get('building_type') == 'HRB'
# Calculate travel distances
travel_distance_issues = []
for room in spatial_data.rooms:
if room.is_habitable:
routes = self.spatial.find_egress_routes(
start_room=room.id,
building_id=spatial_data.building_id
)
shortest_route = min(routes, key=lambda r: r.distance)
# Determine maximum permitted travel distance
if is_hrb:
max_distance = 9.0 if len(routes) < 2 else 18.0 # meters
else:
max_distance = self._get_max_travel_distance(
room.use,
len(routes)
)
if shortest_route.distance > max_distance:
travel_distance_issues.append({
'room': room.name,
'distance': shortest_route.distance,
'max_allowed': max_distance,
'excess': shortest_route.distance - max_distance
})
if travel_distance_issues:
return ComplianceCheck(
regulation="Part B1 - Means of Escape (Travel Distance)",
requirement=f"Travel distance to nearest exit: {'HRB: 9m (one direction) or 18m (two directions)' if is_hrb else 'Per Approved Document B Table 3.1'}",
status="non_compliant",
evidence=[
f"{len(travel_distance_issues)} room(s) exceed travel distance limits",
f"Worst case: {max(travel_distance_issues, key=lambda x: x['excess'])['room']} "
f"({max(travel_distance_issues, key=lambda x: x['excess'])['distance']:.1f}m)"
],
reasoning="Travel distances exceed limits per Approved Document B. This is a critical life safety issue.",
confidence=0.95,
priority="critical",
recommendations=[
"Reduce travel distances by:",
" - Adding additional exits/stairways",
" - Reconfiguring floor layout",
" - Repositioning protected escape routes",
f"Rooms requiring attention: {', '.join(i['room'] for i in travel_distance_issues[:5])}"
],
regulatory_references=["Approved Document B Volume 2 Table 3.1", "BS 9999"]
)
# Check alternative means of escape
alternative_escape_issues = []
for room in spatial_data.rooms:
if room.requires_alternative_escape: # Determined by room characteristics
routes = self.spatial.find_egress_routes(room.id, spatial_data.building_id)
if len(routes) < 2:
alternative_escape_issues.append({
'room': room.name,
'routes_found': len(routes),
'routes_required': 2
})
if alternative_escape_issues:
return ComplianceCheck(
regulation="Part B1 - Alternative Means of Escape",
requirement="Rooms requiring alternative escape must have two independent routes",
status="non_compliant",
evidence=[
f"{len(alternative_escape_issues)} room(s) lack alternative escape routes",
"Rooms affected: " + ", ".join(i['room'] for i in alternative_escape_issues[:10])
],
reasoning="Insufficient alternative means of escape. Some rooms only have single escape route when two required.",
confidence=0.90,
priority="critical",
recommendations=[
"Provide second independent escape route for affected rooms",
"Routes must be truly independent (not converge before final exit)",
"Consider additional external escape stair if necessary"
],
regulatory_references=["Approved Document B Section 2"]
)
# If we reach here, basic egress provisions appear satisfactory
return ComplianceCheck(
regulation="Part B1 - Means of Escape",
requirement="Adequate means of escape provisions",
status="compliant",
evidence=[
f"Travel distances checked for {len(spatial_data.rooms)} rooms",
"All travel distances within limits",
"Alternative escape routes provided where required"
],
reasoning="Means of escape provisions meet Approved Document B requirements.",
confidence=0.85,
priority="high",
recommendations=[
"Verify emergency lighting and signage specifications",
"Ensure protected routes maintained during construction"
],
regulatory_references=["Approved Document B Section 2"]
)
4.3 RAG Strategy Per Agent
Each agent has tailored RAG retrieval strategy:
Part A (Structure) RAG Strategy
class PartARAGStrategy:
"""
RAG strategy optimized for structural requirements.
"""
def generate_queries(self, building_characteristics: Dict) -> List[str]:
"""
Generate queries specific to structural checking.
"""
queries = [
# Loading queries
f"imposed loads for {building_characteristics['use']} buildings BS EN 1991",
f"wind loads {building_characteristics['location']} UK",
f"snow loads {building_characteristics['location']} UK",
# Structural integrity
f"structural stability requirements {building_characteristics['height']}m building",
f"disproportionate collapse class 2B {building_characteristics['storeys']} storey",
# Foundations
f"foundation design {building_characteristics['ground_conditions']}",
f"foundation depth frost heave UK",
# Fire resistance (structural)
f"fire resistance requirements {building_characteristics['use']} {building_characteristics['height']}m",
f"structural fire design {building_characteristics['structural_material']}"
]
return queries
def retrieve_context(
self,
query: str,
rag_system: RAGSystem
) -> Dict:
"""
Retrieve context with emphasis on standards and calculations.
"""
# Text retrieval with focus on BS EN standards
text_results = rag_system.retrieve_text(
query=query,
collection="part_a_text",
top_k=15,
filters={'document_type': ['approved_document', 'bs_en_standard']}
)
# Retrieve calculation examples
precedent_results = rag_system.retrieve_text(
query=f"{query} calculation example",
collection="structural_precedents",
top_k=5
)
# Retrieve diagrams
diagram_results = rag_system.retrieve_diagrams(
query=query,
collection="part_a_diagrams",
top_k=3
)
return {
'regulatory_text': text_results,
'precedents': precedent_results,
'diagrams': diagram_results
}
Part B (Fire Safety) RAG Strategy
class PartBRAGStrategy:
"""
RAG strategy for fire safety - most complex due to broad scope.
"""
def generate_queries(self, building_characteristics: Dict) -> List[str]:
"""
Generate comprehensive fire safety queries.
"""
queries = []
# Means of escape queries
queries.extend([
f"travel distance requirements {building_characteristics['use']}",
f"alternative means of escape {building_characteristics['occupancy']} occupants",
f"protected stairway requirements {building_characteristics['storeys']} storeys",
f"evacuation time requirements HRB" if building_characteristics['is_hrb'] else "",
])
# Compartmentation queries
queries.extend([
f"compartmentation requirements {building_characteristics['use']}",
f"fire resistance periods {building_characteristics['height']}m building",
f"cavity barriers requirements",
])
# External fire spread (post-Grenfell critical)
if building_characteristics['is_hrb']:
queries.extend([
f"external wall systems HRB requirements post-Grenfell",
f"cladding fire performance requirements",
f"combustible materials restrictions HRB"
])
# Fire service access
queries.extend([
f"fire fighting shaft requirements {building_characteristics['height']}m",
f"fire service vehicle access requirements",
f"dry rising mains requirements"
])
return [q for q in queries if q] # Remove empty strings
def retrieve_context(
self,
query: str,
rag_system: RAGSystem,
is_hrb: bool
) -> Dict:
"""
Retrieve fire safety context with HRB emphasis if applicable.
"""
# Base retrieval
text_results = rag_system.retrieve_text(
query=query,
collection="part_b_text",
top_k=20 # More results due to complexity
)
# HRB-specific guidance if applicable
if is_hrb:
hrb_results = rag_system.retrieve_text(
query=f"{query} HRB higher risk building",
collection="hrb_guidance",
top_k=10
)
else:
hrb_results = []
# Rejection precedents (learn from common failures)
rejection_results = rag_system.retrieve_text(
query=f"{query} BSR rejection reasons",
collection="bsr_rejections",
top_k=5
)
# Diagrams (especially for egress layouts)
diagram_results = rag_system.retrieve_diagrams(
query=query,
collection="part_b_diagrams",
top_k=5
)
return {
'regulatory_text': text_results,
'hrb_guidance': hrb_results,
'rejection_precedents': rejection_results,
'diagrams': diagram_results
}
5. REQUIRED OUTCOMES
5.1 Primary Deliverables
Gateway 2 Compliance Package
Contents:
Executive Summary
- Overall compliance status
- Critical issues requiring immediate attention
- Summary statistics (compliant vs non-compliant checks)
- Estimated likelihood of BSR approval
Part-by-Part Compliance Commentary
- Detailed findings for each applicable Building Regulation Part (A-T)
- Evidence-based determinations with regulatory citations
- Confidence scores for each finding
- NOT design advice - commentary only per RBI/Chartered Building Engineer code
Cross-Part Analysis
- Identification of conflicts between different regulation parts
- Recommendations for resolving conflicts
- Dependencies and interactions highlighted
Gap Analysis
- Missing information that prevents full assessment
- Additional documentation required
- Clarifications needed from design team
Prioritized Issue List
- Critical issues (life safety, structural integrity, likely BSR rejection)
- High priority issues (compliance required, moderate remediation difficulty)
- Medium priority issues (compliance preferred, easier remediation)
- Low priority observations (enhancement suggestions, best practice)
Evidence Package
- Document references supporting each finding
- Drawing annotations highlighting issues
- Calculation summaries where applicable
- Product verification results
Recommendations
- Specific, actionable steps to address non-compliances
- Alternative approaches where applicable
- Suggested consultations with specialists
- Timeline implications of changes
Format:
- PDF report for human review
- Structured JSON/XML for system integration
- Interactive dashboard for project team access
- Annotated drawings with issue highlighting
Example Report Structure:
BUILDWELLTHREAD COMPLIANCE REPORT
Gateway 2 Submission Assessment
Project: [Project Name]
Address: [Address]
Submission Date: [Date]
Report Date: [Date]
Reference: [Unique ID]
EXECUTIVE SUMMARY
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
Overall Assessment: NON-COMPLIANT [requires revisions]
Compliance Summary:
β Compliant: 156 checks (64%)
β Non-Compliant: 45 checks (18%)
? Requires Clarification: 44 checks (18%)
Total Checks Performed: 245
CRITICAL ISSUES (IMMEDIATE ATTENTION REQUIRED):
1. Part B1 - Travel Distance: 8 rooms exceed maximum (see Section 2.1)
2. Part B3 - Fire Resistance: Compartmentation incomplete (see Section 2.3)
3. Part A3 - Disproportionate Collapse: Strategy not provided for HRB (see Section 1.3)
LIKELIHOOD OF BSR APPROVAL: LOW (without revisions)
Estimated remediation time: 4-6 weeks
...
PART A: STRUCTURE
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
A1: LOADING
β COMPLIANT: Imposed load specifications
Status: Compliant
Confidence: 85%
Evidence:
- Imposed loads specified per BS EN 1991-1-1 Table 6.2
- All room types have appropriate loading
- Structural calculations signed by Chartered Engineer
β NON-COMPLIANT: Wind load calculations
Status: Non-Compliant
Priority: HIGH
Confidence: 90%
Evidence:
- Wind load calculations use Eurocode but not UK National Annex
- Basic wind speed not adjusted for UK location
- No consideration of terrain category
Reasoning:
Wind load calculations must use UK National Annex to BS EN 1991-1-4.
Current calculations use generic Eurocode values which are not appropriate
for UK sites. This affects sizing of structural elements and connections.
Recommendations:
1. Recalculate wind loads using BS EN 1991-1-4 with UK National Annex
2. Use UK wind map for site-specific basic wind speed
3. Include terrain category and orography factors for site
4. Verify structural adequacy with revised loads
Regulatory References:
- BS EN 1991-1-4:2005+A1:2010
- UK National Annex to BS EN 1991-1-4
- Approved Document A Section 2.1
...
Gateway 3 Support Package
Contents:
Completion Certificate Readiness Assessment
- Verification all Gateway 2 conditions satisfied
- Outstanding items list
- Completion certificate application status
As-Built Validation
- Comparison of as-built to approved drawings
- Material substitutions verification
- Performance testing results review
Change Log
- All variations from approved Gateway 2 submission
- Justification for changes
- Re-validation of compliance where affected
- Authorization trail
Final Compliance Verification
- Confirmation all Building Regulations requirements met
- Testing and commissioning results verification
- Certification package completeness check
Operation and Maintenance Information
- Building manual adequacy assessment
- Safety information compilation
- Handover documentation review
Outcome: Supporting documentation for Gateway 3 submission with confidence that completion certificate will be granted.
Golden Thread Documentation
Structure (per Building Safety Act requirements):
Golden Thread Information Set
βββ Building Information
β βββ Location and address
β βββ Building characteristics (height, storeys, occupancy)
β βββ Use and occupancy information
β βββ Principal contractor details
β βββ Principal designer details
β
βββ Design Information
β βββ Architectural plans (by floor and section)
β βββ Structural design
β βββ Fire safety strategy
β βββ Building services design
β βββ Materials specifications
β βββ Product certifications
β
βββ Safety Case
β βββ Fire safety strategy
β βββ Structural fire protection
β βββ Means of escape provisions
β βββ Fire service access and facilities
β βββ Risk assessments
β βββ Safety management plan
β
βββ Compliance Record
β βββ Gateway 2 approval documentation
β βββ Gateway 3 completion certificate
β βββ Building Regulations compliance certificates
β βββ Fire safety compliance
β βββ Structural approval
β βββ Other regulatory approvals
β
βββ Change Control
β βββ Design change register
β βββ Change authorization records
β βββ Impact assessments
β βββ Re-validation of compliance
β βββ As-built vs approved comparison
β
βββ Construction Phase Information
β βββ Progress updates
β βββ Inspection reports
β βββ Testing and commissioning
β βββ Site safety records
β βββ Handover information
β
βββ Operation and Maintenance
βββ Building user manual
βββ Safety information for residents
βββ Maintenance schedules
βββ Emergency procedures
βββ Contact information
Characteristics:
- Structured: Consistent format following Building Safety Act guidance
- Versioned: Complete change history with dates and authorization
- Accessible: Different views for different stakeholders (residents, facilities management, BSR)
- Persistent: Maintained throughout building lifecycle
- Interoperable: Compatible with BSR digital platform
5.2 Performance Targets
Accuracy Targets
Overall Goal: >90% agreement with expert human reviewers
By Priority Level:
- Critical safety issues: >95% detection rate (minimize false negatives)
- High priority compliance: >90% accuracy
- Medium priority: >85% accuracy
- Low priority observations: >80% accuracy
False Positive Tolerance: <15% (balance between catching issues and not overwhelming with false flags)
Processing Targets
- Time: 45-90 minutes per submission (end-to-end)
- Throughput: Process multiple submissions in parallel
- Availability: 99% uptime (critical for workflow integration)
- Scalability: Support 10-50 concurrent submissions
Quality Targets
- Completeness: 100% of applicable Building Regulations Parts checked
- Evidence Quality: Every finding supported by specific document references
- Clarity: Recommendations actionable without additional interpretation
- Consistency: Same submission produces same results across multiple runs
Business Targets
- BSR Rejection Rate Reduction: Target <20% (from current 40-67%)
- Time Savings: Reduce manual review time by 70-80%
- Cost Reduction: Lower compliance checking costs by 50%+
- Quality Improvement: Catch issues earlier in design process
5.3 Success Metrics
Technical Success Indicators
Validation Against Human Experts
- Blind comparison: AI findings vs expert review
- Agreement rate measured
- Types of discrepancies analyzed
- Continuous improvement based on discrepancies
BSR Gateway Performance
- Track rejection rates of AI-reviewed submissions
- Analyze rejection reasons (were they preventable?)
- Compare to industry baseline
- Measure improvement over time
User Feedback
- Usefulness ratings from design teams
- Accuracy perception from reviewers
- Time savings reported
- Adoption rate within organization
Operational Success Indicators
System Reliability
- Uptime percentage
- Mean time between failures
- Average processing time
- Error rate by component
Golden Thread Utility
- Completeness of generated documentation
- Acceptance by BSR
- Ease of maintenance and updates
- Stakeholder satisfaction
Business Impact
- Cost per submission
- Time to completion
- Number of design iterations reduced
- Overall project timeline improvement
6. ERROR HANDLING AND QUALITY ASSURANCE
6.1 Error Categories and Responses
Input Processing Errors
Corrupt or Unreadable PDFs:
class CorruptPDFHandler:
"""
Handle corrupted or problematic PDF inputs.
"""
def handle(self, pdf_path: str) -> Result:
"""
Attempt recovery or graceful degradation.
"""
try:
# Attempt standard parsing
document = parse_pdf(pdf_path)
return Success(document)
except CorruptPDFError as e:
# Attempt recovery
try:
repaired = repair_pdf(pdf_path)
document = parse_pdf(repaired)
return Success(
document,
warnings=["PDF was repaired - verify content integrity"]
)
except Exception:
# Cannot recover
return Failure(
error="PDF is corrupt and cannot be recovered",
action="manual_review_required",
user_message="This PDF cannot be processed. Please re-export and resubmit.",
file=pdf_path
)
Poor Quality Drawings:
class DrawingQualityAssessor:
"""
Assess and handle low-quality drawings.
"""
def assess_quality(self, image: Image) -> QualityScore:
"""
Score drawing quality on multiple dimensions.
"""
scores = {
'resolution': self._check_resolution(image),
'contrast': self._check_contrast(image),
'clarity': self._check_clarity(image),
'completeness': self._check_completeness(image)
}
overall = np.mean(list(scores.values()))
return QualityScore(
overall=overall,
dimensions=scores
)
def handle(self, image: Image, quality: QualityScore) -> Result:
"""
Decide how to proceed based on quality.
"""
if quality.overall > 0.8:
# High quality - proceed normally
return Success(image)
elif quality.overall > 0.5:
# Acceptable but suboptimal
# Proceed with warnings and reduced confidence
return Success(
image,
warnings=[
f"Drawing quality suboptimal (score: {quality.overall:.2f})",
"Some automated measurements may be less reliable",
"Manual verification recommended for critical dimensions"
],
confidence_penalty=0.15
)
else:
# Unacceptable quality
# Request better quality submission
return Failure(
error="Drawing quality insufficient for automated analysis",
quality_score=quality.overall,
issues=[dim for dim, score in quality.dimensions.items() if score < 0.5],
user_message="Please provide higher quality drawings (minimum 300 DPI, clear lines)",
action="resubmission_required"
)
Missing or Incomplete Submissions:
class CompletenessChecker:
"""
Validate submission completeness before processing.
"""
REQUIRED_DOCUMENTS = {
'gateway_2': [
'site_plan',
'floor_plans',
'elevations',
'sections',
'specifications',
'structural_calculations',
'fire_strategy'
]
}
def check(self, submission: Submission) -> CompletenessResult:
"""
Check if submission is complete.
"""
required = self.REQUIRED_DOCUMENTS['gateway_2']
provided = submission.document_types
missing = [doc for doc in required if doc not in provided]
if missing:
return CompletenessResult(
complete=False,
missing_documents=missing,
can_proceed=len(missing) < 3, # Can partially process if only minor gaps
user_message=self._format_missing_docs_message(missing)
)
return CompletenessResult(
complete=True,
missing_documents=[],
can_proceed=True
)
def _format_missing_docs_message(self, missing: List[str]) -> str:
"""
Create user-friendly message about missing documents.
"""
return f"""
The following required documents are missing from your submission:
{self._format_list(missing)}
Please provide these documents to enable complete compliance checking.
Note: We can perform partial analysis with the documents provided,
but some compliance checks cannot be completed without the missing items.
"""
Spatial Processing Errors
FloorplanTransformation Failures:
class FloorplanTransformationErrorHandler:
"""
Handle failures in spatial processing pipeline.
"""
def handle(
self,
pdf_path: str,
error: Exception
) -> Result:
"""
Attempt fallback strategies when FloorplanTransformation fails.
"""
# Log the error
logger.error(f"FloorplanTransformation failed for {pdf_path}: {error}")
# Attempt fallback strategy 1: Alternative CV model
try:
spatial_data = self.alternative_cv_model.process(pdf_path)
return Success(
spatial_data,
warnings=[
"Used alternative processing method",
"Spatial measurements may be less accurate",
"Manual verification recommended"
],
confidence_penalty=0.20
)
except Exception as e2:
logger.error(f"Alternative CV model also failed: {e2}")
# Attempt fallback strategy 2: Manual annotation interface
try:
# Create manual annotation task
task_id = self.manual_annotation_queue.create_task(
pdf_path=pdf_path,
priority="high",
reason="Automated processing failed"
)
return Pending(
message="Automated processing failed - manual annotation required",
task_id=task_id,
estimated_time="30-60 minutes",
user_message="We're having trouble automatically processing these plans. "
"Our team will manually review and we'll notify you when complete."
)
except Exception as e3:
logger.error(f"Could not create manual task: {e3}")
# Complete failure - cannot proceed
return Failure(
error="Unable to process floorplans",
action="expert_review_required",
user_message="These plans could not be processed automatically. "
"Please contact support for manual review options."
)
Ambiguous Element Detection:
class AmbiguityResolver:
"""
Handle uncertain spatial element identification.
"""
def resolve(
self,
element: SpatialElement,
confidence: float
) -> Resolution:
"""
Decide how to handle ambiguous elements.
"""
if confidence > 0.9:
# High confidence - accept
return Accept(element)
elif confidence > 0.6:
# Medium confidence - flag and proceed with caveats
return AcceptWithCaveats(
element=element,
confidence=confidence,
warnings=[
f"Element '{element.id}' identification uncertain (confidence: {confidence:.0%})",
f"Type: {element.type} (alternative: {element.alternative_types})",
"Recommend manual verification"
]
)
else:
# Low confidence - request clarification
return RequestClarification(
element=element,
confidence=confidence,
question=f"Please clarify: Is element at {element.location} a {element.type}?",
alternatives=element.alternative_types,
impact="Affects: " + ", ".join(element.dependent_checks)
)
RAG System Errors
No Relevant Regulations Retrieved:
class RetrievalFailureHandler:
"""
Handle cases where RAG system returns no relevant results.
"""
def handle(
self,
query: str,
collection: str
) -> Result:
"""
Respond to failed retrieval.
"""
# Log the issue
logger.warning(f"No results for query: {query} in collection: {collection}")
# Attempt query expansion
expanded_queries = self._expand_query(query)
for expanded in expanded_queries:
results = self.rag.retrieve(expanded, collection)
if results:
return Success(
results,
warnings=["Used expanded query for retrieval"]
)
# Still no results - this might be a novel situation
return Failure(
error="No relevant regulatory guidance found",
query=query,
action="flag_for_expert",
user_message="This appears to be a novel or unusual situation. "
"Expert review recommended.",
escalation_priority="medium"
)
def _expand_query(self, query: str) -> List[str]:
"""
Generate alternative queries.
"""
# Use LLM to generate alternative phrasings
prompt = f"""
The following query returned no results:
"{query}"
Generate 3 alternative queries that might retrieve relevant information
from UK Building Regulations documents.
"""
alternatives = self.llm.generate(prompt)
return parse_alternatives(alternatives)
Contradictory Guidance:
class ContradictionResolver:
"""
Handle cases where retrieved regulations appear contradictory.
"""
def resolve(
self,
regulations: List[Regulation]
) -> Resolution:
"""
Identify and resolve contradictions.
"""
# Check for obvious contradictions
contradictions = self._find_contradictions(regulations)
if not contradictions:
return NoContradiction(regulations)
# Attempt resolution by checking:
# 1. Document hierarchy (later supersedes earlier)
# 2. Specificity (specific overrides general)
# 3. Context applicability
resolved = []
for contradiction in contradictions:
resolution = self._resolve_single_contradiction(contradiction)
resolved.append(resolution)
if all(r.confident for r in resolved):
return ResolvedContradiction(
regulations=resolved,
explanations=[r.explanation for r in resolved]
)
# Cannot confidently resolve - escalate
return UnresolvableContradiction(
regulations=regulations,
contradictions=contradictions,
action="escalate_to_expert",
user_message="We've identified potentially conflicting requirements. "
"Expert interpretation needed."
)
Agent-Level Errors
Confidence Below Threshold:
class ConfidenceManager:
"""
Manage low-confidence agent determinations.
"""
CONFIDENCE_THRESHOLDS = {
'critical_safety': 0.90,
'high_priority': 0.80,
'medium_priority': 0.70,
'low_priority': 0.60
}
def handle(
self,
check: ComplianceCheck,
threshold_category: str
) -> HandlingDecision:
"""
Decide how to handle low-confidence findings.
"""
required_confidence = self.CONFIDENCE_THRESHOLDS[threshold_category]
if check.confidence >= required_confidence:
# Acceptable confidence
return Accept(check)
elif check.confidence >= required_confidence - 0.10:
# Slightly below threshold - accept with strong caveats
return AcceptWithReview(
check=check,
warnings=[
f"Confidence ({check.confidence:.0%}) below preferred threshold",
"Recommend expert verification"
],
review_priority="high" if threshold_category == "critical_safety" else "medium"
)
else:
# Significantly below threshold - cannot make determination
return InsufficientConfidence(
check=check,
status="requires_expert_review",
reason=f"Confidence {check.confidence:.0%} insufficient for {threshold_category} finding",
required_action="expert_review_before_proceeding"
)
Inter-Agent Conflicts:
class ConflictResolver:
"""
Resolve conflicts between different agent findings.
"""
def detect_conflicts(
self,
agent_results: Dict[str, List[ComplianceCheck]]
) -> List[Conflict]:
"""
Identify conflicts between agent findings.
"""
conflicts = []
# Check for direct contradictions
# (e.g., Part L wants more insulation, Part O wants less to avoid overheating)
for part_a, checks_a in agent_results.items():
for part_b, checks_b in agent_results.items():
if part_a >= part_b:
continue # Avoid duplicate comparisons
part_conflicts = self._find_conflicts_between_parts(
part_a, checks_a,
part_b, checks_b
)
conflicts.extend(part_conflicts)
return conflicts
def resolve(self, conflict: Conflict) -> Resolution:
"""
Attempt to resolve identified conflict.
"""
# Check if there's established precedence
precedence = self._check_precedence(conflict.part_a, conflict.part_b)
if precedence:
return PrecedenceResolution(
winner=precedence.primary_part,
rationale=precedence.explanation,
recommendation=f"Prioritize {precedence.primary_part} requirement. "
f"Seek alternative solutions for {precedence.secondary_part}."
)
# Check for alternative solutions that satisfy both
alternatives = self._find_alternative_solutions(conflict)
if alternatives:
return AlternativeSolution(
alternatives=alternatives,
recommendation="Consider alternative approaches that satisfy both requirements"
)
# Cannot resolve - escalate
return UnresolvedConflict(
conflict=conflict,
action="expert_judgment_required",
recommendation="This conflict requires design team discussion and expert judgment"
)
Database Errors
Vector Database Unavailable:
class VectorDBFailureHandler:
"""
Handle Milvus vector database failures.
"""
def handle(self, error: Exception) -> Result:
"""
Respond to vector DB unavailability.
"""
logger.critical(f"Vector database unavailable: {error}")
# Attempt reconnection
if self._reconnect_attempt():
return Recovered()
# Use cached results if available
if self.cache.has_recent_data():
return DegradedMode(
message="Using cached regulatory data",
limitations=[
"Cannot retrieve newest regulations",
"Precedent search unavailable",
"Some contextual information may be missing"
],
max_degraded_time="30 minutes"
)
# Cannot proceed
return Failure(
error="Regulatory knowledge base unavailable",
action="system_maintenance_required",
user_message="System temporarily unavailable. Please try again shortly.",
estimated_recovery="15-30 minutes"
)
Graph Database Inconsistencies:
class GraphDBValidation:
"""
Detect and handle Neo4j graph inconsistencies.
"""
def validate_spatial_graph(
self,
spatial_data: SpatialData
) -> ValidationResult:
"""
Check for logical inconsistencies in spatial graph.
"""
issues = []
# Check for orphaned nodes
orphans = self._find_orphaned_nodes(spatial_data)
if orphans:
issues.append(
Issue(
type="orphaned_elements",
elements=orphans,
severity="medium",
message=f"{len(orphans)} elements not connected to building topology"
)
)
# Check for impossible relationships
impossible = self._find_impossible_relationships(spatial_data)
if impossible:
issues.append(
Issue(
type="impossible_topology",
relationships=impossible,
severity="high",
message=f"{len(impossible)} impossible spatial relationships detected"
)
)
# Check for duplicate elements
duplicates = self._find_duplicates(spatial_data)
if duplicates:
issues.append(
Issue(
type="duplicate_elements",
elements=duplicates,
severity="low",
message=f"{len(duplicates)} duplicate elements found"
)
)
if issues:
return ValidationFailure(
issues=issues,
action="repair_or_notify",
can_proceed=all(i.severity != "high" for i in issues)
)
return ValidationSuccess()
def repair(self, issues: List[Issue]) -> RepairResult:
"""
Attempt automatic repair of graph inconsistencies.
"""
repaired = []
failed = []
for issue in issues:
try:
if issue.type == "orphaned_elements":
self._repair_orphans(issue.elements)
repaired.append(issue)
elif issue.type == "duplicate_elements":
self._remove_duplicates(issue.elements)
repaired.append(issue)
else:
# Cannot auto-repair
failed.append(issue)
except Exception as e:
logger.error(f"Repair failed for {issue.type}: {e}")
failed.append(issue)
return RepairResult(
repaired=repaired,
failed=failed,
success=len(failed) == 0
)
6.2 Quality Assurance Mechanisms
Multi-Level Validation
class QualityAssurance:
"""
Multi-level quality assurance for compliance determinations.
"""
def validate_finding(
self,
check: ComplianceCheck
) -> QAResult:
"""
Apply multiple validation checks to finding.
"""
validations = []
# 1. Evidence consistency check
evidence_valid = self._validate_evidence(check)
validations.append(('evidence', evidence_valid))
# 2. Reasoning coherence check
reasoning_valid = self._validate_reasoning(check)
validations.append(('reasoning', reasoning_valid))
# 3. Regulatory citation accuracy
citations_valid = self._validate_citations(check)
validations.append(('citations', citations_valid))
# 4. Confidence calibration
confidence_calibrated = self._calibrate_confidence(check)
validations.append(('confidence', confidence_calibrated))
# 5. Cross-check with similar cases
precedent_consistent = self._check_precedent_consistency(check)
validations.append(('precedent', precedent_consistent))
# Aggregate results
all_valid = all(valid for _, valid in validations)
if all_valid:
return QAPass(check)
else:
failed = [name for name, valid in validations if not valid]
return QAFail(
check=check,
failed_validations=failed,
action="review_and_revise"
)
def _validate_evidence(self, check: ComplianceCheck) -> bool:
"""
Check that evidence actually supports conclusion.
"""
# Use LLM to assess if evidence supports conclusion
prompt = f"""
Does the following evidence support the conclusion?
Conclusion: {check.status} - {check.requirement}
Evidence:
{chr(10).join(check.evidence)}
Answer: yes/no with brief explanation
"""
response = self.llm.generate(prompt, temperature=0.1)
return 'yes' in response.lower()
def _calibrate_confidence(self, check: ComplianceCheck) -> bool:
"""
Ensure confidence score is appropriate.
"""
# Factors that should reduce confidence:
reducing_factors = []
if len(check.evidence) < 2:
reducing_factors.append("insufficient_evidence")
if check.status == "insufficient_info":
# Confidence should be high for "insufficient info" findings
# (high confidence that we don't have enough information)
if check.confidence < 0.80:
reducing_factors.append("confidence_too_low_for_insufficient_info")
if check.regulatory_references == []:
reducing_factors.append("no_regulatory_references")
if reducing_factors and check.confidence > 0.70:
# Confidence should be reduced
check.confidence = max(0.60, check.confidence - 0.15)
check.metadata['confidence_adjusted'] = True
check.metadata['adjustment_reason'] = reducing_factors
return True # Calibration applied
Audit Trail Generation
class AuditTrail:
"""
Comprehensive audit trail for all system decisions.
"""
def log_decision(
self,
decision_type: str,
input_data: Dict,
output: Any,
agent: str,
reasoning: str,
confidence: float,
timestamp: datetime
):
"""
Log a compliance decision with full context.
"""
entry = AuditEntry(
id=generate_uuid(),
timestamp=timestamp,
decision_type=decision_type,
agent=agent,
input_hash=hash_data(input_data),
input_summary=summarize(input_data),
output=output,
reasoning=reasoning,
confidence=confidence,
model_version=self.model_version,
rag_version=self.rag_version,
system_version=self.system_version
)
# Store in database
self.db.store(entry)
# Create human-readable log
self.log_file.write(self._format_entry(entry))
def _format_entry(self, entry: AuditEntry) -> str:
"""
Format audit entry for human review.
"""
return f"""
ββββββββββββββββββββββββββββββββββββββββββ
AUDIT ENTRY: {entry.id}
ββββββββββββββββββββββββββββββββββββββββββ
Timestamp: {entry.timestamp}
Agent: {entry.agent}
Decision Type: {entry.decision_type}
Input Summary:
{entry.input_summary}
Output:
{entry.output}
Reasoning:
{entry.reasoning}
Confidence: {entry.confidence:.0%}
System Versions:
- Model: {entry.model_version}
- RAG: {entry.rag_version}
- System: {entry.system_version}
ββββββββββββββββββββββββββββββββββββββββββ
"""
def generate_audit_report(
self,
submission_id: str
) -> AuditReport:
"""
Generate comprehensive audit report for submission.
"""
entries = self.db.get_entries(submission_id=submission_id)
report = AuditReport(
submission_id=submission_id,
total_decisions=len(entries),
agents_involved=list(set(e.agent for e in entries)),
decision_timeline=self._create_timeline(entries),
confidence_distribution=self._analyze_confidence(entries),
model_versions_used=list(set(e.model_version for e in entries)),
full_trail=entries
)
return report
Continuous Learning and Improvement
class FeedbackLoop:
"""
Collect feedback and improve system over time.
"""
def record_outcome(
self,
submission_id: str,
ai_assessment: ComplianceReport,
actual_outcome: Outcome
):
"""
Record actual BSR decision for learning.
"""
# Compare AI assessment with actual outcome
comparison = self._compare_assessment_to_outcome(
ai_assessment,
actual_outcome
)
# Store for analysis
self.db.store_outcome(
submission_id=submission_id,
ai_assessment=ai_assessment,
actual_outcome=actual_outcome,
comparison=comparison
)
# Update performance metrics
self._update_metrics(comparison)
# Flag cases for review
if comparison.significant_discrepancy:
self._flag_for_review(submission_id, comparison)
def analyze_performance(self) -> PerformanceReport:
"""
Analyze system performance over time.
"""
outcomes = self.db.get_all_outcomes()
metrics = {
'overall_accuracy': self._calculate_accuracy(outcomes),
'accuracy_by_part': self._calculate_accuracy_by_part(outcomes),
'false_positive_rate': self._calculate_false_positive_rate(outcomes),
'false_negative_rate': self._calculate_false_negative_rate(outcomes),
'confidence_calibration': self._assess_confidence_calibration(outcomes)
}
# Identify patterns in errors
error_patterns = self._identify_error_patterns(outcomes)
# Generate recommendations
recommendations = self._generate_improvement_recommendations(
metrics,
error_patterns
)
return PerformanceReport(
metrics=metrics,
error_patterns=error_patterns,
recommendations=recommendations
)
def trigger_retraining(self, criteria: RetrainingCriteria) -> bool:
"""
Determine if model retraining is needed.
"""
performance = self.analyze_performance()
should_retrain = (
performance.accuracy < criteria.min_accuracy or
performance.false_negative_rate > criteria.max_false_negative or
performance.significant_error_patterns
)
if should_retrain:
logger.info("Retraining triggered based on performance analysis")
self._initiate_retraining(performance)
return should_retrain
7. PROFESSIONAL STANDARDS COMPLIANCE
7.1 RBI/Chartered Building Engineer Code Alignment
Key Principle: System provides compliance commentary, not design advice
Distinguishing Commentary from Advice
Commentary (Permitted):
- "The submitted design does not meet Part B1 travel distance requirements (45m max, 60m provided)"
- "Approved Document B Section 2.5 requires alternative means of escape for this occupancy"
- "The specification lacks fire resistance ratings for the separating wall"
- "Similar configurations have been rejected at Gateway 2 for inadequate compartmentation"
Design Advice (Not Provided):
- β "You should relocate the stairway to the northwest corner"
- β "We recommend using 2-hour fire-rated construction"
- β "The optimal approach is to reduce the corridor length"
- β "Install an additional exit here [specific location]"
Implementation in System:
class ProfessionalStandardsValidator:
"""
Ensure all outputs comply with professional standards.
"""
PROHIBITED_PHRASES = [
"you should",
"we recommend",
"you must",
"the best approach",
"optimal design",
"ideal solution"
]
def validate_output(
self,
compliance_check: ComplianceCheck
) -> ValidationResult:
"""
Ensure output is commentary, not advice.
"""
# Check reasoning and recommendations
text_to_check = (
compliance_check.reasoning + " " +
" ".join(compliance_check.recommendations)
).lower()
# Flag prohibited phrases
violations = [
phrase for phrase in self.PROHIBITED_PHRASES
if phrase in text_to_check
]
if violations:
return ValidationFailure(
violations=violations,
suggestion="Rephrase to describe requirements rather than prescribe solutions"
)
# Check for imperative language
if self._contains_imperatives(text_to_check):
return ValidationFailure(
issue="imperative_language",
suggestion="Use 'requirements state' rather than 'you must'"
)
# Ensure regulatory basis cited
if not compliance_check.regulatory_references:
return ValidationFailure(
issue="no_regulatory_basis",
suggestion="Include regulatory references for all findings"
)
return ValidationSuccess()
def reframe_as_commentary(
self,
advice_text: str
) -> str:
"""
Convert advice-style text to commentary-style.
"""
# Use LLM to reframe
prompt = f"""
Reframe the following as regulatory commentary rather than design advice.
Focus on:
- What the regulations require
- Where the submission falls short
- What information is needed
Avoid:
- Prescriptive recommendations
- Specific design solutions
- Imperative language
Original: {advice_text}
Reframed commentary:
"""
reframed = self.llm.generate(prompt, temperature=0.1)
return reframed
Limitation Disclaimers
All outputs include clear disclaimers:
IMPORTANT DISCLAIMER:
This compliance commentary is provided as a guidance tool to assist in
preparing Building Regulations submissions. It does NOT constitute:
- Design advice or recommendations
- Professional engineering or architectural services
- Final determination of compliance (only Building Safety Regulator can make final determinations)
- A substitute for qualified professional review
All findings should be reviewed by appropriately qualified professionals
(Chartered Engineers, Registered Building Inspectors, etc.) before relying
on them for submission or construction purposes.
This system identifies potential compliance issues based on submitted
documentation, but cannot account for all project-specific factors or
replace expert judgment.
The user retains full responsibility for ensuring submissions meet all
applicable regulations and standards.
7.2 Liability and Professional Responsibility
System Positioning:
- Decision Support Tool: Augments human expertise, doesn't replace it
- Early Warning System: Identifies potential issues for expert review
- Documentation Aid: Helps organize and structure compliance evidence
User Responsibility:
- Verification: All AI findings must be verified by qualified professionals
- Interpretation: Regulations require professional judgment in application
- Final Decisions: Human experts make all final compliance determinations
- Documentation: Users responsible for accuracy of submitted information
Recommended Workflow:
1. Submit documents to BuildwellTHREAD
2. Receive AI compliance commentary
3. Review findings with qualified building engineer/RBI
4. Conduct additional analysis as needed
5. Make professional determination
6. Prepare final Gateway submission
7. Maintain audit trail of all review steps
8. DEPLOYMENT AND OPERATIONS
8.1 Deployment on Isambard AI
Resource Allocation
Isambard AI Configuration:
Platform: Nvidia GH200 Grace-Hopper Superchips
Operating System: Ubuntu 22.04 LTS
Container Platform: Docker or Singularity
Compute Resources (Example Allocation):
Development/Training:
- GPUs: 8x GH200 (480GB total GPU memory)
- CPUs: 64 ARM cores
- RAM: 1TB system memory
- Storage: 10TB NVMe
Production Inference:
- GPUs: 4x GH200 (240GB total GPU memory)
- CPUs: 32 ARM cores
- RAM: 512GB system memory
- Storage: 5TB NVMe
Network:
- High-speed interconnect between nodes
- External connectivity for document uploads/downloads
- Firewall rules for security
Software Stack
# Base Image
FROM nvidia/cuda:12.2.0-runtime-ubuntu22.04
# System dependencies
RUN apt-get update && apt-get install -y \
python3.11 \
python3-pip \
git \
wget \
wine64 \ # For FloorplanTransformation
&& rm -rf /var/lib/apt/lists/*
# Python dependencies
COPY requirements.txt /tmp/
RUN pip3 install -r /tmp/requirements.txt
# Key packages
# - transformers (for LLMs)
# - pymilvus (vector DB client)
# - neo4j (graph DB client)
# - fastapi (API server)
# - celery (task queue)
# - pytorch (deep learning framework)
# Application code
COPY buildwellthread /app/buildwellthread
WORKDIR /app
# FloorplanTransformation setup
COPY FloorplanTransformation /app/floorplan_transform
ENV WINEPREFIX=/app/.wine
# Entrypoint
CMD ["uvicorn", "buildwellthread.api:app", "--host", "0.0.0.0", "--port", "8000"]
8.2 Operational Procedures
Submission Processing Workflow
# Orchestration with task queue
from celery import Celery, chain
app = Celery('buildwellthread')
@app.task
def ingest_documents(submission_id: str):
"""
Task 1: Ingest and parse uploaded documents.
"""
submission = load_submission(submission_id)
parsed = document_ingestion.process(submission.files)
save_parsed_documents(submission_id, parsed)
return submission_id
@app.task
def extract_spatial_data(submission_id: str):
"""
Task 2: Process floorplans into spatial data.
"""
parsed = load_parsed_documents(submission_id)
spatial_data = spatial_processor.process(parsed.drawings)
save_spatial_data(submission_id, spatial_data)
return submission_id
@app.task
def build_knowledge_context(submission_id: str):
"""
Task 3: Retrieve relevant regulations from RAG.
"""
submission = load_submission(submission_id)
spatial_data = load_spatial_data(submission_id)
context = rag_system.build_context(submission, spatial_data)
save_context(submission_id, context)
return submission_id
@app.task
def run_compliance_agents(submission_id: str):
"""
Task 4: Execute multi-agent compliance checking.
"""
submission = load_submission(submission_id)
spatial_data = load_spatial_data(submission_id)
context = load_context(submission_id)
agent_results = orchestrator.process(submission, spatial_data, context)
save_agent_results(submission_id, agent_results)
return submission_id
@app.task
def generate_outputs(submission_id: str):
"""
Task 5: Generate reports and Golden Thread docs.
"""
agent_results = load_agent_results(submission_id)
compliance_report = report_generator.generate(agent_results)
golden_thread = golden_thread_generator.generate(agent_results)
save_outputs(submission_id, compliance_report, golden_thread)
# Notify user
notify_user(submission_id, "complete")
return submission_id
# Chain tasks together
def process_submission(submission_id: str):
"""
Orchestrate full processing pipeline.
"""
workflow = chain(
ingest_documents.s(submission_id),
extract_spatial_data.s(),
build_knowledge_context.s(),
run_compliance_agents.s(),
generate_outputs.s()
)
result = workflow.apply_async()
return result
Monitoring and Alerting
class SystemMonitor:
"""
Monitor system health and performance.
"""
def collect_metrics(self):
"""
Collect system metrics for monitoring.
"""
return {
'active_submissions': self.get_active_submission_count(),
'queue_depth': self.get_queue_depth(),
'processing_time_p50': self.get_processing_percentile(0.50),
'processing_time_p95': self.get_processing_percentile(0.95),
'error_rate': self.get_error_rate(),
'gpu_utilization': self.get_gpu_utilization(),
'memory_usage': self.get_memory_usage(),
'storage_usage': self.get_storage_usage(),
'database_latency': self.get_database_latency(),
'confidence_distribution': self.get_confidence_distribution()
}
def check_health(self) -> HealthStatus:
"""
Perform health check on all components.
"""
checks = {
'api': self.ping_api(),
'task_queue': self.check_celery(),
'vector_db': self.ping_milvus(),
'graph_db': self.ping_neo4j(),
'relational_db': self.ping_postgres(),
'storage': self.check_storage_availability(),
'model_server': self.check_model_availability()
}
all_healthy = all(checks.values())
return HealthStatus(
healthy=all_healthy,
component_status=checks,
timestamp=datetime.now()
)
def alert_if_needed(self, metrics: Dict):
"""
Send alerts for concerning metrics.
"""
# High error rate
if metrics['error_rate'] > 0.10: # 10% errors
self.send_alert(
severity='HIGH',
message=f"Error rate elevated: {metrics['error_rate']:.1%}"
)
# Long processing times
if metrics['processing_time_p95'] > 7200: # 2 hours
self.send_alert(
severity='MEDIUM',
message=f"P95 processing time: {metrics['processing_time_p95']/60:.0f} minutes"
)
# Queue backlog
if metrics['queue_depth'] > 100:
self.send_alert(
severity='MEDIUM',
message=f"Queue depth: {metrics['queue_depth']} submissions"
)
# Storage space
if metrics['storage_usage'] > 0.85: # 85% full
self.send_alert(
severity='HIGH',
message=f"Storage {metrics['storage_usage']:.0%} full"
)
9. CONCLUSION AND NEXT STEPS
9.1 Summary
BuildwellTHREAD represents a comprehensive solution for automating UK Building Regulations compliance checking and Golden Thread management. The system addresses critical challenges in the current Gateway submission process:
Problems Solved:
- High Gateway 2/3 rejection rates (40-67% β target <20%)
- Lengthy manual review processes (days β hours)
- Inconsistent compliance checking across projects
- Difficulty maintaining Golden Thread documentation
- Limited early detection of compliance issues
Core Capabilities:
- Multi-agent architecture with specialized compliance checking per Building Regulation Part
- Multimodal document processing (text, drawings, specifications)
- Intelligent spatial reasoning and measurement
- Regulatory knowledge retrieval via RAG system
- Automated Golden Thread generation and maintenance
- Professional standards-compliant commentary (not design advice)
Technical Foundation:
- Deployment on Isambard AI supercomputer (Nvidia GH200)
- Sophisticated error handling and quality assurance
- Comprehensive audit trails for all decisions
- Continuous learning and improvement mechanisms
9.2 Development Roadmap
Phase 1: Foundation (Months 1-3)
- Set up infrastructure on Isambard AI
- Develop document ingestion pipeline
- Implement FloorplanTransformation integration
- Build core RAG system
- Establish databases (Milvus, Neo4j, PostgreSQL)
Phase 2: Core Agents (Months 4-6)
- Implement Part A (Structure) agent
- Implement Part B (Fire Safety) agent
- Implement Part M (Access) agent
- Develop orchestrator framework
- Build tool library (measurement, spatial reasoning)
Phase 3: Comprehensive Coverage (Months 7-9)
- Implement remaining Part agents (C-L, N-T)
- Develop cross-part validation
- Build Golden Thread generator
- Create reporting system
Phase 4: Testing and Validation (Months 10-12)
- Validation against expert human reviews
- Testing with real Gateway submissions
- Performance optimization
- User interface development
- Documentation and training materials
Phase 5: Deployment and Operations (Month 12+)
- Production deployment
- User onboarding
- Continuous monitoring and improvement
- Regular model updates based on outcomes
9.3 Success Factors
Critical for Success:
- High-Quality Training Data: Access to real Gateway submissions and BSR decisions
- Expert Collaboration: Ongoing input from building control professionals
- Iterative Refinement: Continuous improvement based on real-world performance
- Professional Standards: Strict adherence to RBI/Chartered Engineer codes
- Computational Resources: Reliable access to Isambard AI or equivalent infrastructure
Risk Mitigation:
- Technical Risks: Fallback strategies for all critical dependencies
- Regulatory Risks: Clear positioning as decision support, not replacement for professionals
- Operational Risks: Comprehensive monitoring and alert systems
- Quality Risks: Multi-level validation and audit trails
9.4 Expected Impact
For Design Teams:
- Faster identification of compliance issues (days β hours)
- Clearer understanding of regulatory requirements
- Higher quality submissions with fewer iterations
- Reduced risk of costly late-stage redesigns
For Building Control Bodies:
- More consistent compliance checking
- Reduced review burden for complete submissions
- Better-documented decision trails
- Improved communication with applicants
For BSR:
- Higher quality Gateway submissions
- Reduced rejection rates
- Better-maintained Golden Thread documentation
- More efficient review process
For Industry:
- Accelerated project timelines
- Reduced compliance-related costs
- Improved building safety outcomes
- Better regulatory adherence
DOCUMENT CONTROL
Version: 1.0
Date: January 2026
Author: BuildwellTHREAD Development Team
Status: Development Specification
Distribution:
- Isambard AI Development Team
- London Belgravia Surveyors
- Building Safety Regulator (for consultation)
- RBI/Chartered Building Engineers (for professional standards review)
Revision History:
- v1.0 (Jan 2026): Initial comprehensive specification
Contact: For questions or clarifications, please contact the BuildwellTHREAD project team.
APPENDICES
Appendix A: Building Regulation Parts Reference
Quick reference for all UK Building Regulations Parts covered:
- Part A: Structure
- Part B: Fire Safety
- Part C: Site Preparation and Resistance to Contaminants and Moisture
- Part D: Toxic Substances
- Part E: Resistance to the Passage of Sound
- Part F: Ventilation
- Part G: Sanitation, Hot Water Safety and Water Efficiency
- Part H: Drainage and Waste Disposal
- Part J: Combustion Appliances and Fuel Storage
- Part K: Protection from Falling, Collision and Impact
- Part L: Conservation of Fuel and Power
- Part M: Access to and Use of Buildings
- Part N: Glazing (Safety in Relation to Impact, Opening and Cleaning)
- Part O: Overheating
- Part P: Electrical Safety (Dwellings)
- Part Q: Security (Dwellings)
- Part R: Physical Infrastructure for High-Speed Electronic Communications Networks
- Part S: Infrastructure for Charging of Electric Vehicles
- Part T: Infrastructure for Broadband
Appendix B: Glossary
BSR: Building Safety Regulator
HRB: Higher-Risk Building (β₯18m or β₯7 storeys)
Gateway 2: BSR gateway for final design approval before construction
Gateway 3: BSR gateway for completion certificate
Golden Thread: Structured set of information about building throughout lifecycle
RAG: Retrieval-Augmented Generation
RBI: Registered Building Inspector
BBA: British Board of AgrΓ©ment
KIWA: International certification body
Appendix C: Technical Specifications
Model Requirements:
- Base LLM: 7B-72B parameters (depends on deployment resources)
- Embedding Model: NV-Embed-v2 or equivalent (768-dimensional)
- Vision Model: CLIP or similar (if needed for diagram comparison)
Database Requirements:
- Vector DB: Milvus 2.x+ with HNSW indexing
- Graph DB: Neo4j 5.x+ with GDS (Graph Data Science) library
- Relational DB: PostgreSQL 14+ with full-text search capabilities
Storage Requirements:
- Regulatory corpus: ~50GB (Approved Documents, Standards, Guidance)
- Submission documents: ~100GB per 1000 submissions
- Processed spatial data: ~50GB per 1000 submissions
- System logs and audit trails: ~10GB per month
Compute Requirements:
- Development: 8x high-end GPUs with 480GB+ total memory
- Production: 4x GPUs with 240GB+ total memory for concurrent processing
- CPU: 32-64 cores for parallel processing tasks
END OF DOCUMENT