# The New Engineer — HVAC

> IFC models: duct networks, circuits, pressure drop. EN 12828 vessels, EN 378, Swiss refrigerants.

- name: com.thenewengineer/hvac
- version: 1.3.0
- connection class: R0 (autonomous)
- trust: 83/100 flags: no-repository
- quality: 84/100 (good)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/com.thenewengineer%2Fhvac
- tools: https://api.protogrid.dev/v1/servers/com.thenewengineer%2Fhvac/tools

**An agent can connect right now, no human step.** Remote endpoint, no authentication, reachable on the last probe.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "hvac": {
      "type": "http",
      "url": "https://thenewengineer.com/mcp"
    }
  }
}
```


## Trust

- hygiene: 80
- liveness: 100
- freshness: 100
- provenance: 55
- drivers: +dns-namespace +website +reachable +uptime-100% +updated-10d-ago -no-repository
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 84/100 (good)

### protocol: 88 (weight 25)

- pass `protocol.modern`: supports 2026-07-28 (server/discover)
- pass `protocol.stateless`: answers without a session
- pass `protocol.transport`: streamable HTTP
- warn `protocol.list_ttl`: tools/list declares ttlMs 0, so clients re-fetch it on every use

### authorization: n/a (weight 15)

- n/a `auth.prm`, `auth.as_metadata`, `auth.cimd`: no remote uses OAuth
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 86 (weight 30)

- pass `tools.descriptions`: every tool has a description
- warn `tools.description_length`: 8 tools have descriptions over 1,024 characters, which crowds the context
- pass `tools.schemas`: every tool has an object input schema
- pass `tools.annotations`: 11 of 11 tools declare readOnlyHint or destructiveHint
- pass `tools.directory_hints`: every tool declares readOnlyHint, destructiveHint, idempotentHint and openWorldHint
- warn `tools.token_cost`: about 14,587 tokens to load every tool
- pass `tools.api_dump`: tools are not a one-to-one API dump

### stability: 75 (weight 15)

- warn `stability.changes`: 33 tool changes in 30 days
- pass `stability.rug_pull`: no tool changed its meaning under the same name

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: no npm or PyPI package

- tools: 11, about 14,587 tokens to load them all
- tool set hash: 52e92dd6a7f038f8ca9c3303130f9d7a
- tools last changed: 2026-10-19T20:24:29.212Z
- badge: [![protogrid quality](https://protogrid.dev/badge/com.thenewengineer/hvac.svg)](https://protogrid.dev/servers/com.thenewengineer/hvac)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

- 2026-10-19 `trace_duct_circuits` changed (description, inputSchema)
  - before: THE CIRCUITS THE FANS OF A MODEL ARE SIZED ON, found without anyone clicking and computed on the pressure-drop page, where the user confirms types and flows and reads the pressure drops. ONLY UNITS AND FANS ARE EXCHANGED. The tool never sends you system names: it sends the air handling units and fans your rules found, each with what the network walk finds connected to it - geometry, not names. A unit is equipment with a FAN - air handling unit, monobloc, ventilation casing, fan. Coils, heat exchangers, filters, silencers, dampers are network pieces: if one shows up in the list (often as 'dans_le_reseau_de' another unit), your rules are too wide - fix them with apply_ifc_rules before choosing. FIRST THE CHECK AND THE LIST, THEN THE CALCULATION. Called with only the token, once your rules are posted with apply_ifc_rules, it computes NOTHING and bills nothing. It walks the networks from every unit and fan and measures the share of the model's air pieces they reach ('raccordement'). Two answers: - CONNECTED (half of the air pieces or more): the COMPLETE list of units and fans ('centrales_et_ventilateurs', each with its number of connected networks) and 'lien_centrales', a VIEW-ONLY page - every unit in a light colour with its name floating above it, each of its networks in the same colour. Give the user that link and say nothing is computed yet. Then: * the user named units, even loosely: map their words onto the EXACT names of the list, say which you picked, and call again with units; * the user asked for the whole model and the list says 'tous_possible' (50 air networks or fewer): call again with all_networks=true; * otherwise show the user the WHOLE list to tick - every unit and fan, however long; never only the main ones. 'Tous' first when it is offered, then one numbered line per unit with its number of connected networks; mark the units connected to nothing. Filter only on what the user said, and then say which filter and how many lines it left out. Call with what they tick. - NOT CONNECTED ('non_raccorde': less than half, or no unit at all): tell the user the sentence of 'A_DIRE_A_L_UTILISATEUR' - « Nous n'avons pas pu connecter les centrales de traitement d'air aux réseaux de votre modèle », in their language - and suggest the pressure-drop page ('lien_pdc'), where they define each network themselves by a start and an end. Nothing is computed. If your rules missed units, fix them and call again. WHAT IS COMPUTED: for each network connected to a chosen unit or fan, the LONGEST path. Networks connected to no unit are not computed here. BEYOND 50 AIR NETWORKS, THE MODEL IS COMPUTED ONE UNIT AT A TIME. Each call computes ONE unit - unit_name, or units with a single name - or the network of ONE piece - network_guid. The whole model, start_role and several units are refused: nothing is computed, and the answer says why. Ask the user which unit, or which piece: on the view-only page, hovering a piece shows its GUID. Call again for the next one; what is computed stays, and is not billed again. YOU SEE A SAMPLE IN THE OVERVIEW, THE WHOLE MODEL HERE. Never choose the units from what read_ifc_overview showed you - one example per type: choose from the list this tool returns. A REQUEST THE TOOL CANNOT MATCH. Names that match nothing come back under 'non_reconnus', each with the closest names; the names that did match are computed. If NOTHING matched - or the GUID or unit_name is unknown - nothing is computed, whatever the size of the model: the list comes back, with the closest names under 'non_reconnus' and what went wrong under 'demande_non_satisfaite'. Correct the names from the list, or ask the user which one they meant, and call again. A PIECE INSTEAD OF A UNIT. When the model has no unit, when the unit the user means was not recognised, or when they simply show a piece: network_gu
  - after: THE CIRCUITS THE FANS OF A MODEL ARE SIZED ON, found without anyone clicking and computed on the pressure-drop page, where the user confirms types and flows and reads the pressure drops. ONLY UNITS AND FANS ARE EXCHANGED. The tool never sends you system names: it sends the air handling units and fans your rules found, each with what the network walk finds connected to it - geometry, not names. A unit is equipment with a FAN - air handling unit, monobloc, ventilation casing, fan. Coils, heat exchangers, filters, silencers, dampers are network pieces: if one shows up in the list (often as 'dans_le_reseau_de' another unit), your rules are too wide - fix them with apply_ifc_rules before choosing. FIRST THE CHECK AND THE LIST, THEN THE CALCULATION. Called with only the token, once your rules are posted with apply_ifc_rules, it computes NOTHING and bills nothing. It walks the networks from every unit and fan and measures the share of the model's air pieces they reach ('raccordement'). Two answers: - CONNECTED (half of the air pieces or more): the COMPLETE list of units and fans ('centrales_et_ventilateurs', each with its number of connected networks) and 'lien_centrales', a VIEW-ONLY page - every unit in a light colour with its name floating above it, each of its networks in the same colour. Give the user that link and say nothing is computed yet. Then: * the user named units, even loosely: map their words onto the EXACT names of the list, say which you picked, and call again with units; * the user asked for the whole model and the list says 'tous_possible' (50 air networks or fewer): call again with all_networks=true; * otherwise show the user the WHOLE list to tick - every unit and fan, however long; never only the main ones. 'Tous' first when it is offered, then one numbered line per unit with its number of connected networks; mark the units connected to nothing. Filter only on what the user said, and then say which filter and how many lines it left out. Call with what they tick. - NOT CONNECTED ('non_raccorde': less than half, or no unit at all): tell the user the sentence of 'A_DIRE_A_L_UTILISATEUR' - « Nous n'avons pas pu connecter les centrales de traitement d'air aux réseaux de votre modèle », in their language - and suggest the pressure-drop page ('lien_pdc'), where they define each network themselves by a start and an end. Nothing is computed. If your rules missed units, fix them and call again. WHAT IS COMPUTED: for each network connected to a chosen unit or fan, the LONGEST path. Networks connected to no unit are not computed here. BEYOND 50 AIR NETWORKS, THE MODEL IS COMPUTED ONE UNIT AT A TIME. Each call computes ONE unit - unit_name, or units with a single name - or the network of ONE piece - network_guid. The whole model, start_role and several units are refused: nothing is computed, and the answer says why. Ask the user which unit, or which piece: on the view-only page, hovering a piece shows its GUID. Call again for the next one; what is computed stays, and is not billed again. YOU SEE A SAMPLE IN THE OVERVIEW, THE WHOLE MODEL HERE. Never choose the units from what read_ifc_overview showed you - one example per type: choose from the list this tool returns. A REQUEST THE TOOL CANNOT MATCH. Names that match nothing come back under 'non_reconnus', each with the closest names; the names that did match are computed. If NOTHING matched - or the GUID or unit_name is unknown - nothing is computed, whatever the size of the model: the list comes back, with the closest names under 'non_reconnus' and what went wrong under 'demande_non_satisfaite'. Correct the names from the list, or ask the user which one they meant, and call again. A PIECE INSTEAD OF A UNIT. When the model has no unit, when the unit the user means was not recognised, or when they simply show a piece: network_gu
- 2026-10-16 `trace_duct_circuits` changed (description)
  - before: THE CIRCUITS THE FANS OF A MODEL ARE SIZED ON, found without anyone clicking and computed on the pressure-drop page, where the user confirms types and flows and reads the pressure drops. ONLY UNITS AND FANS ARE EXCHANGED. The tool never sends you system names: it sends the air handling units and fans your rules found, each with what the network walk finds connected to it - geometry, not names. FIRST THE CHECK AND THE LIST, THEN THE CALCULATION. Called with only the token, once your rules are posted with apply_ifc_rules, it computes NOTHING and bills nothing. It walks the networks from every unit and fan and measures the share of the model's air pieces they reach ('raccordement'). Two answers: - CONNECTED (half of the air pieces or more): the COMPLETE list of units and fans ('centrales_et_ventilateurs', each with its number of connected networks) and 'lien_centrales', a VIEW-ONLY page - every unit in a light colour with its name floating above it, each of its networks in the same colour. Give the user that link and say nothing is computed yet. Then: * the user named units, even loosely: map their words onto the EXACT names of the list, say which you picked, and call again with units; * the user asked for the whole model and the list says 'tous_possible' (50 air networks or fewer): call again with all_networks=true; * otherwise show the user the WHOLE list to tick - every unit and fan, however long; never only the main ones. 'Tous' first when it is offered, then one numbered line per unit with its number of connected networks; mark the units connected to nothing. Filter only on what the user said, and then say which filter and how many lines it left out. Call with what they tick. - NOT CONNECTED ('non_raccorde': less than half, or no unit at all): tell the user the sentence of 'A_DIRE_A_L_UTILISATEUR' - « Nous n'avons pas pu connecter les centrales de traitement d'air aux réseaux de votre modèle », in their language - and suggest the pressure-drop page ('lien_pdc'), where they define each network themselves by a start and an end. Nothing is computed. If your rules missed units, fix them and call again. WHAT IS COMPUTED: for each network connected to a chosen unit or fan, the LONGEST path. Networks connected to no unit are not computed here. BEYOND 50 AIR NETWORKS, THE MODEL IS COMPUTED ONE UNIT AT A TIME. Each call computes ONE unit - unit_name, or units with a single name - or the network of ONE piece - network_guid. The whole model, start_role and several units are refused: nothing is computed, and the answer says why. Ask the user which unit, or which piece: on the view-only page, hovering a piece shows its GUID. Call again for the next one; what is computed stays, and is not billed again. YOU SEE A SAMPLE IN THE OVERVIEW, THE WHOLE MODEL HERE. Never choose the units from what read_ifc_overview showed you - one example per type: choose from the list this tool returns. A REQUEST THE TOOL CANNOT MATCH. Names that match nothing come back under 'non_reconnus', each with the closest names; the names that did match are computed. If NOTHING matched - or the GUID or unit_name is unknown - nothing is computed, whatever the size of the model: the list comes back, with the closest names under 'non_reconnus' and what went wrong under 'demande_non_satisfaite'. Correct the names from the list, or ask the user which one they meant, and call again. A PIECE INSTEAD OF A UNIT. When the model has no unit, when the unit the user means was not recognised, or when they simply show a piece: network_guid computes the network of any piece - the tool finds where its air starts; end_guid computes one circuit to that end - from start_guid if given, else from the start the tool finds. A start found by the tool comes back under 'depart_trouve' with what made it chosen: say so, and ask the user to check it o
  - after: THE CIRCUITS THE FANS OF A MODEL ARE SIZED ON, found without anyone clicking and computed on the pressure-drop page, where the user confirms types and flows and reads the pressure drops. ONLY UNITS AND FANS ARE EXCHANGED. The tool never sends you system names: it sends the air handling units and fans your rules found, each with what the network walk finds connected to it - geometry, not names. A unit is equipment with a FAN - air handling unit, monobloc, ventilation casing, fan. Coils, heat exchangers, filters, silencers, dampers are network pieces: if one shows up in the list (often as 'dans_le_reseau_de' another unit), your rules are too wide - fix them with apply_ifc_rules before choosing. FIRST THE CHECK AND THE LIST, THEN THE CALCULATION. Called with only the token, once your rules are posted with apply_ifc_rules, it computes NOTHING and bills nothing. It walks the networks from every unit and fan and measures the share of the model's air pieces they reach ('raccordement'). Two answers: - CONNECTED (half of the air pieces or more): the COMPLETE list of units and fans ('centrales_et_ventilateurs', each with its number of connected networks) and 'lien_centrales', a VIEW-ONLY page - every unit in a light colour with its name floating above it, each of its networks in the same colour. Give the user that link and say nothing is computed yet. Then: * the user named units, even loosely: map their words onto the EXACT names of the list, say which you picked, and call again with units; * the user asked for the whole model and the list says 'tous_possible' (50 air networks or fewer): call again with all_networks=true; * otherwise show the user the WHOLE list to tick - every unit and fan, however long; never only the main ones. 'Tous' first when it is offered, then one numbered line per unit with its number of connected networks; mark the units connected to nothing. Filter only on what the user said, and then say which filter and how many lines it left out. Call with what they tick. - NOT CONNECTED ('non_raccorde': less than half, or no unit at all): tell the user the sentence of 'A_DIRE_A_L_UTILISATEUR' - « Nous n'avons pas pu connecter les centrales de traitement d'air aux réseaux de votre modèle », in their language - and suggest the pressure-drop page ('lien_pdc'), where they define each network themselves by a start and an end. Nothing is computed. If your rules missed units, fix them and call again. WHAT IS COMPUTED: for each network connected to a chosen unit or fan, the LONGEST path. Networks connected to no unit are not computed here. BEYOND 50 AIR NETWORKS, THE MODEL IS COMPUTED ONE UNIT AT A TIME. Each call computes ONE unit - unit_name, or units with a single name - or the network of ONE piece - network_guid. The whole model, start_role and several units are refused: nothing is computed, and the answer says why. Ask the user which unit, or which piece: on the view-only page, hovering a piece shows its GUID. Call again for the next one; what is computed stays, and is not billed again. YOU SEE A SAMPLE IN THE OVERVIEW, THE WHOLE MODEL HERE. Never choose the units from what read_ifc_overview showed you - one example per type: choose from the list this tool returns. A REQUEST THE TOOL CANNOT MATCH. Names that match nothing come back under 'non_reconnus', each with the closest names; the names that did match are computed. If NOTHING matched - or the GUID or unit_name is unknown - nothing is computed, whatever the size of the model: the list comes back, with the closest names under 'non_reconnus' and what went wrong under 'demande_non_satisfaite'. Correct the names from the list, or ask the user which one they meant, and call again. A PIECE INSTEAD OF A UNIT. When the model has no unit, when the unit the user means was not recognised, or when they simply show a piece: network_gu
- 2026-10-16 `apply_ifc_rules` changed (description)
  - before: Turn what you read in the overview into rules the tool replays on EVERY piece of the model, including the ones you were never shown. THIS IS HOW THE TOOL LEARNS A MODEL. read_ifc_overview gives you some fifty groups — one per object type, not one per piece. You answer with RULES on those groups, and this tool applies them to the three thousand pieces. You never give a verdict piece by piece: the result stays deterministic because a program, not you, does the matching. THEN READ THE ANSWER BACK, AND EXPECT TO POST AGAIN. The answer gives every group with the role your rules gave it and how many pieces that is. A rule that is too wide shows up on one line — « Gaine rectangulaire cadree, 471 pieces, centrale_de_traitement_d_air » is a rule that turned every duct into an air handling unit. Narrow it and post again. Calling this tool costs nothing and may be repeated as often as you need. WHAT NEEDS A ROLE, AND WHAT DOES NOT. Plain ducts and fittings need none: they are network by nature, and the answer marks them segment_ou_raccord so you can see at a glance whether a rule caught them by mistake. What needs a role is everything else — air handling units, fans, fire dampers, balancing dampers, silencers, louvres, diffusers — plus whatever must be kept OUT of the network, such as access zones, equipment plinths or damper motors. TWO ROLE NAMES ARE FIXED, because circuits start from them: give air handling units, monoblocs and ventilation casings the role centrale_de_traitement_d_air, and fans the role ventilateur - exactly these words. The answer lists, under 'equipements', the GUIDs of every piece of the model that got one of them: that list is what trace_duct_circuits computes when called with only the token. Every other role name is yours to choose. ORDER THE LIST YOURSELF, most specific first, down to the most general. The fire damper rule must come before the balancing damper rule, or « damper » takes everything. Equipment must come before terminals: « VEN_MSF_MONOBLOC_SIMPLE_FLUX_REPRISE » contains « reprise », and a return-diffuser rule placed first would claim the air handling unit. Pieces no rule catches are simply listed, with no warning and no failure: the engineer judges on the 3D view, not on a coverage report. NEXT: once 'equipements' lists the air handling units and fans you expect, call trace_duct_circuits with only the token. It computes nothing yet: it checks that the units are connected to the networks and returns the complete list of units and fans, to choose from - see trace_duct_circuits. 'equipements' counts every piece ('pieces') but lists at most thirty names: the count, not the list, is the model.
  - after: Turn what you read in the overview into rules the tool replays on EVERY piece of the model, including the ones you were never shown. THIS IS HOW THE TOOL LEARNS A MODEL. read_ifc_overview gives you some fifty groups — one per object type, not one per piece. You answer with RULES on those groups, and this tool applies them to the three thousand pieces. You never give a verdict piece by piece: the result stays deterministic because a program, not you, does the matching. THEN READ THE ANSWER BACK, AND EXPECT TO POST AGAIN. The answer gives every group with the role your rules gave it and how many pieces that is. A rule that is too wide shows up on one line — « Gaine rectangulaire cadree, 471 pieces, centrale_de_traitement_d_air » is a rule that turned every duct into an air handling unit. Narrow it and post again. Calling this tool costs nothing and may be repeated as often as you need. WHAT NEEDS A ROLE, AND WHAT DOES NOT. Plain ducts and fittings need none: they are network by nature, and the answer marks them segment_ou_raccord so you can see at a glance whether a rule caught them by mistake. What needs a role is everything else — air handling units, fans, fire dampers, balancing dampers, silencers, louvres, diffusers — plus whatever must be kept OUT of the network, such as access zones, equipment plinths or damper motors. TWO ROLE NAMES ARE FIXED, because circuits start from them: give air handling units, monoblocs and ventilation casings the role centrale_de_traitement_d_air, and fans the role ventilateur - exactly these words. ONLY EQUIPMENT THAT MOVES THE AIR gets one of them: a unit is a box with a fan in it. Heating and cooling coils, heat exchangers, filters, silencers, dampers, fire dampers, VAV boxes, humidifiers are NOT units: the air runs through them, they are pieces of the network. Give them another role (coil, silencer, damper...) or none - never one of the two unit roles. A coil in 'equipements' is a rule that is too wide. The answer lists, under 'equipements', the GUIDs of every piece of the model that got one of the two roles: that list is what trace_duct_circuits starts from, and what the pages show as units. Every other role name is yours to choose. ORDER THE LIST YOURSELF, most specific first, down to the most general. The fire damper rule must come before the balancing damper rule, or « damper » takes everything. Equipment must come before terminals: « VEN_MSF_MONOBLOC_SIMPLE_FLUX_REPRISE » contains « reprise », and a return-diffuser rule placed first would claim the air handling unit. Pieces no rule catches are simply listed, with no warning and no failure: the engineer judges on the 3D view, not on a coverage report. NEXT: once 'equipements' lists the air handling units and fans you expect, call trace_duct_circuits with only the token. It computes nothing yet: it checks that the units are connected to the networks and returns the complete list of units and fans, to choose from - see trace_duct_circuits. 'equipements' counts every piece ('pieces') but lists at most thirty names: the count, not the list, is the model.
- 2026-10-16 `read_ifc_overview` changed (description)
  - before: CALL THIS FIRST, as soon as the user gives you a token. It answers within seconds, while the network graph is still being built - use that time to think. THE CIRCUITS OF A MODEL IN FOUR CALLS: 1. read_ifc_overview - this call: the types of the model. 2. apply_ifc_rules - your rules. Give air handling units, monoblocs and ventilation casings the role centrale_de_traitement_d_air, and fans the role ventilateur, exactly these words. Its answer lists under 'equipements' every unit and fan of the model. 3. trace_duct_circuits with ONLY the token - it computes nothing, walks the networks from every unit and fan, and either returns the COMPLETE list of units and fans with a view-only page, or says the units could not be connected to the model's networks. 4. trace_duct_circuits again with the units the user wants, or all_networks=true for all of them (offered up to 50 air networks only). The answer of this call repeats these steps under 'marche_a_suivre'. YOU SEE A SAMPLE, THE TOOL SEES EVERYTHING. This overview shows one example per type, not every piece: you cannot count the units, the fans or the networks of the model from it, and you must not believe you have seen them all. The tool applies your rules to every piece and walks every network. So never pick the networks to compute from this overview: trace_duct_circuits gives you the complete list of units and fans first, and you choose from THAT list. WHAT YOU GET. Not 3 000 parts: the 20 to 50 distinct TYPES of the model (duct types, fittings, dampers, terminals, equipment, proxies), each with its IFC class, predefined type, type name, one example part with ALL its properties, and a catalogue of every property present. WHAT TO DO WITH IT. Write RULES, not verdicts. For roles: which words, in which field, identify a fire damper, a silencer, a balancing damper, an air terminal, an air handling unit, a fan, a pump - and which groups are NOT network at all (access zones, plinths, placeholders, damper motors). For sizes: which 'PropertySet.Property' holds height, width, diameter, length. A rule applies to every part, including those you were not shown, and to the user's next models. TRAPS the field 'a_savoir' warns about: values are in the FILE's unit (see metres_par_unite), not millimetres; insulation sizes and hydraulic diameters look like dimensions and are not. The field 'etat_du_graphe' says whether the networks are ready yet: 'pret' means read_ifc_networks will answer now.
  - after: CALL THIS FIRST, as soon as the user gives you a token. It answers within seconds, while the network graph is still being built - use that time to think. THE CIRCUITS OF A MODEL IN FOUR CALLS: 1. read_ifc_overview - this call: the types of the model. 2. apply_ifc_rules - your rules. Give air handling units, monoblocs and ventilation casings the role centrale_de_traitement_d_air, and fans the role ventilateur, exactly these words - and ONLY to equipment that holds a fan. Coils, heat exchangers, filters, silencers, dampers, VAV boxes are pieces of the network, not units. Its answer lists under 'equipements' every unit and fan of the model. 3. trace_duct_circuits with ONLY the token - it computes nothing, walks the networks from every unit and fan, and either returns the COMPLETE list of units and fans with a view-only page, or says the units could not be connected to the model's networks. 4. trace_duct_circuits again with the units the user wants, or all_networks=true for all of them (offered up to 50 air networks only). The answer of this call repeats these steps under 'marche_a_suivre'. YOU SEE A SAMPLE, THE TOOL SEES EVERYTHING. This overview shows one example per type, not every piece: you cannot count the units, the fans or the networks of the model from it, and you must not believe you have seen them all. The tool applies your rules to every piece and walks every network. So never pick the networks to compute from this overview: trace_duct_circuits gives you the complete list of units and fans first, and you choose from THAT list. WHAT YOU GET. Not 3 000 parts: the 20 to 50 distinct TYPES of the model (duct types, fittings, dampers, terminals, equipment, proxies), each with its IFC class, predefined type, type name, one example part with ALL its properties, and a catalogue of every property present. WHAT TO DO WITH IT. Write RULES, not verdicts. For roles: which words, in which field, identify a fire damper, a silencer, a balancing damper, an air terminal, an air handling unit, a fan, a pump - and which groups are NOT network at all (access zones, plinths, placeholders, damper motors). For sizes: which 'PropertySet.Property' holds height, width, diameter, length. A rule applies to every part, including those you were not shown, and to the user's next models. TRAPS the field 'a_savoir' warns about: values are in the FILE's unit (see metres_par_unite), not millimetres; insulation sizes and hydraulic diameters look like dimensions and are not. The field 'etat_du_graphe' says whether the networks are ready yet: 'pret' means read_ifc_networks will answer now.
- 2026-10-16 `trace_duct_circuits` changed (description, annotations)
  - before: THE CIRCUITS THE FANS OF A MODEL ARE SIZED ON, AND THEIR PRESSURE DROP, without anyone clicking. ONLY UNITS AND FANS ARE EXCHANGED. The tool never sends you system names: it sends the air handling units and fans your rules found, each with what the network walk finds connected to it - geometry, not names. FIRST THE CHECK AND THE LIST, THEN THE CALCULATION. Called with only the token, once your rules are posted with apply_ifc_rules, it computes NOTHING and bills nothing. It walks the networks from every unit and fan and measures the share of the model's air pieces they reach ('raccordement'). Two answers: - CONNECTED (half of the air pieces or more): the COMPLETE list of units and fans ('centrales_et_ventilateurs', each with its number of connected networks) and 'lien_centrales', a VIEW-ONLY page - every unit in a light colour with its name floating above it, each of its networks in the same colour. Give the user that link and say nothing is computed yet. Then: * the user named units, even loosely: map their words onto the EXACT names of the list, say which you picked, and call again with units; * the user asked for the whole model and the list says 'tous_possible' (50 air networks or fewer): call again with all_networks=true; * otherwise show the user the WHOLE list to tick - every unit and fan, however long; never only the main ones. 'Tous' first when it is offered, then one numbered line per unit with its number of connected networks; mark the units connected to nothing. Filter only on what the user said, and then say which filter and how many lines it left out. Call with what they tick. - NOT CONNECTED ('non_raccorde': less than half, or no unit at all): tell the user the sentence of 'A_DIRE_A_L_UTILISATEUR' - « Nous n'avons pas pu connecter les centrales de traitement d'air aux réseaux de votre modèle », in their language - and suggest the pressure-drop page ('lien_pdc'), where they define each network themselves by a start and an end. Nothing is computed. If your rules missed units, fix them and call again. WHAT IS COMPUTED: for each network connected to a chosen unit or fan, the LONGEST path. Networks connected to no unit are not computed here. BEYOND 50 AIR NETWORKS, THE MODEL IS COMPUTED ONE UNIT AT A TIME. Each call computes ONE unit - unit_name, or units with a single name - or the network of ONE piece - network_guid. The whole model, start_role and several units are refused: nothing is computed, and the answer says why. Ask the user which unit, or which piece: on the view-only page, hovering a piece shows its GUID. Call again for the next one; what is computed stays, and is not billed again. YOU SEE A SAMPLE IN THE OVERVIEW, THE WHOLE MODEL HERE. Never choose the units from what read_ifc_overview showed you - one example per type: choose from the list this tool returns. A REQUEST THE TOOL CANNOT MATCH. Names that match nothing come back under 'non_reconnus', each with the closest names; the names that did match are computed. If NOTHING matched - or the GUID or unit_name is unknown - nothing is computed, whatever the size of the model: the list comes back, with the closest names under 'non_reconnus' and what went wrong under 'demande_non_satisfaite'. Correct the names from the list, or ask the user which one they meant, and call again. A PIECE INSTEAD OF A UNIT. When the model has no unit, when the unit the user means was not recognised, or when they simply show a piece: network_guid computes the network of any piece - the tool finds where its air starts; end_guid computes one circuit to that end - from start_guid if given, else from the start the tool finds. A start found by the tool comes back under 'depart_trouve' with what made it chosen: say so, and ask the user to check it on the 3D link. The user gets a GUID by hovering a piece on the view-only page. These work
  - after: THE CIRCUITS THE FANS OF A MODEL ARE SIZED ON, found without anyone clicking and computed on the pressure-drop page, where the user confirms types and flows and reads the pressure drops. ONLY UNITS AND FANS ARE EXCHANGED. The tool never sends you system names: it sends the air handling units and fans your rules found, each with what the network walk finds connected to it - geometry, not names. FIRST THE CHECK AND THE LIST, THEN THE CALCULATION. Called with only the token, once your rules are posted with apply_ifc_rules, it computes NOTHING and bills nothing. It walks the networks from every unit and fan and measures the share of the model's air pieces they reach ('raccordement'). Two answers: - CONNECTED (half of the air pieces or more): the COMPLETE list of units and fans ('centrales_et_ventilateurs', each with its number of connected networks) and 'lien_centrales', a VIEW-ONLY page - every unit in a light colour with its name floating above it, each of its networks in the same colour. Give the user that link and say nothing is computed yet. Then: * the user named units, even loosely: map their words onto the EXACT names of the list, say which you picked, and call again with units; * the user asked for the whole model and the list says 'tous_possible' (50 air networks or fewer): call again with all_networks=true; * otherwise show the user the WHOLE list to tick - every unit and fan, however long; never only the main ones. 'Tous' first when it is offered, then one numbered line per unit with its number of connected networks; mark the units connected to nothing. Filter only on what the user said, and then say which filter and how many lines it left out. Call with what they tick. - NOT CONNECTED ('non_raccorde': less than half, or no unit at all): tell the user the sentence of 'A_DIRE_A_L_UTILISATEUR' - « Nous n'avons pas pu connecter les centrales de traitement d'air aux réseaux de votre modèle », in their language - and suggest the pressure-drop page ('lien_pdc'), where they define each network themselves by a start and an end. Nothing is computed. If your rules missed units, fix them and call again. WHAT IS COMPUTED: for each network connected to a chosen unit or fan, the LONGEST path. Networks connected to no unit are not computed here. BEYOND 50 AIR NETWORKS, THE MODEL IS COMPUTED ONE UNIT AT A TIME. Each call computes ONE unit - unit_name, or units with a single name - or the network of ONE piece - network_guid. The whole model, start_role and several units are refused: nothing is computed, and the answer says why. Ask the user which unit, or which piece: on the view-only page, hovering a piece shows its GUID. Call again for the next one; what is computed stays, and is not billed again. YOU SEE A SAMPLE IN THE OVERVIEW, THE WHOLE MODEL HERE. Never choose the units from what read_ifc_overview showed you - one example per type: choose from the list this tool returns. A REQUEST THE TOOL CANNOT MATCH. Names that match nothing come back under 'non_reconnus', each with the closest names; the names that did match are computed. If NOTHING matched - or the GUID or unit_name is unknown - nothing is computed, whatever the size of the model: the list comes back, with the closest names under 'non_reconnus' and what went wrong under 'demande_non_satisfaite'. Correct the names from the list, or ask the user which one they meant, and call again. A PIECE INSTEAD OF A UNIT. When the model has no unit, when the unit the user means was not recognised, or when they simply show a piece: network_guid computes the network of any piece - the tool finds where its air starts; end_guid computes one circuit to that end - from start_guid if given, else from the start the tool finds. A start found by the tool comes back under 'depart_trouve' with what made it chosen: say so, and ask the user to check it o
- 2026-10-16 `trace_duct_circuits` changed (description, inputSchema, annotations)
  - before: THE CIRCUITS THE FANS OF A MODEL ARE SIZED ON, AND THEIR PRESSURE DROP, without anyone clicking. FIRST THE LIST, THEN THE CALCULATION. Called with only the token, once your rules are posted with apply_ifc_rules, it computes NOTHING and bills nothing: it returns the COMPLETE list of the model's systems ('systemes', each with the units that serve it) and of its air handling units and fans ('centrales_et_ventilateurs', each with the systems it serves). This list is complete, unlike the overview: you may choose from it. - The user named units or systems, even loosely: map their words onto the EXACT names of the list, say which you picked, and call again with systems and/or units. - The user asked for the whole model and the list says 'tous_possible' (50 air networks or fewer): call again with all_networks=true. - Otherwise show the user the WHOLE list to tick - every unit and fan, every system, however long; never only the main ones. 'Tous' first when it is offered, then one numbered line per unit with the systems it serves, then the systems no unit serves. Filter only on what the user said (a name, a building, a level, exhaust...), and then say which filter and how many lines it left out. Call with what they tick. BEYOND 50 AIR NETWORKS, THE MODEL IS COMPUTED ONE NETWORK AT A TIME. The call with only the token returns just the units and fans ('centrales_et_ventilateurs', each with the systems it serves) and the networks link. Each call then computes ONE unit - unit_name, or units with a single name - or the network of ONE piece - start_guid. The whole model, start_role, systems and several units are refused: nothing is computed, and the answer says why. Ask the user which unit, or which piece: on the link, a click on a piece shows its GUID. Call again for the next one; what is computed stays. A system brings in the WHOLE unit that serves it - supply, return, outdoor air, exhaust. To add more later, call again with the new names: what is already computed stays, and is not billed again. The whole model starts from every unit and fan, units first, each explored on its own, and lists them under 'departs'. A NETWORK WITH NO UNIT IS NOT SKIPPED. When no unit or fan of your rules serves it - the unit sits in another file, is not chosen yet, or your rules missed it - it starts from a unit found by its IFC class that your rules gave no role, or else from its largest free duct end, where a missing unit would connect. These starts are SUPPOSED and marked 'depart_suppose' under 'departs': say so, and ask the user to check them on the 3D link. YOU SEE A SAMPLE IN THE OVERVIEW, THE WHOLE MODEL HERE. Never choose the networks from what read_ifc_overview showed you - one example per type: choose from the list this tool returns. A REQUEST THE TOOL CANNOT MATCH. Names that match nothing come back under 'non_reconnus', each with the closest names; the names that did match are computed. If NOTHING matched - or the GUID or unit_name is unknown - nothing is computed, whatever the size of the model: the list comes back, with the closest names under 'non_reconnus' and what went wrong under 'demande_non_satisfaite'. Correct the names from the list, or ask the user which one they meant, and call again. A PIECE INSTEAD OF A UNIT. When the model has no unit, when the unit the user means was not recognised, or when they simply show a piece: network_guid computes the network of any piece - the tool finds where its air starts; end_guid computes one circuit to that end - from start_guid if given, else from the start the tool finds. A start found by the tool comes back under 'depart_trouve' with what made it chosen: say so, and ask the user to check it on the 3D link. The user gets a GUID by clicking a piece on the networks link. These work on complex models too: they designate one network. ONE UNIT BY ITS NAME. unit_name computes the unit or fan of that name, found among all the pieces - units does the same fo
  - after: THE CIRCUITS THE FANS OF A MODEL ARE SIZED ON, AND THEIR PRESSURE DROP, without anyone clicking. ONLY UNITS AND FANS ARE EXCHANGED. The tool never sends you system names: it sends the air handling units and fans your rules found, each with what the network walk finds connected to it - geometry, not names. FIRST THE CHECK AND THE LIST, THEN THE CALCULATION. Called with only the token, once your rules are posted with apply_ifc_rules, it computes NOTHING and bills nothing. It walks the networks from every unit and fan and measures the share of the model's air pieces they reach ('raccordement'). Two answers: - CONNECTED (half of the air pieces or more): the COMPLETE list of units and fans ('centrales_et_ventilateurs', each with its number of connected networks) and 'lien_centrales', a VIEW-ONLY page - every unit in a light colour with its name floating above it, each of its networks in the same colour. Give the user that link and say nothing is computed yet. Then: * the user named units, even loosely: map their words onto the EXACT names of the list, say which you picked, and call again with units; * the user asked for the whole model and the list says 'tous_possible' (50 air networks or fewer): call again with all_networks=true; * otherwise show the user the WHOLE list to tick - every unit and fan, however long; never only the main ones. 'Tous' first when it is offered, then one numbered line per unit with its number of connected networks; mark the units connected to nothing. Filter only on what the user said, and then say which filter and how many lines it left out. Call with what they tick. - NOT CONNECTED ('non_raccorde': less than half, or no unit at all): tell the user the sentence of 'A_DIRE_A_L_UTILISATEUR' - « Nous n'avons pas pu connecter les centrales de traitement d'air aux réseaux de votre modèle », in their language - and suggest the pressure-drop page ('lien_pdc'), where they define each network themselves by a start and an end. Nothing is computed. If your rules missed units, fix them and call again. WHAT IS COMPUTED: for each network connected to a chosen unit or fan, the LONGEST path. Networks connected to no unit are not computed here. BEYOND 50 AIR NETWORKS, THE MODEL IS COMPUTED ONE UNIT AT A TIME. Each call computes ONE unit - unit_name, or units with a single name - or the network of ONE piece - network_guid. The whole model, start_role and several units are refused: nothing is computed, and the answer says why. Ask the user which unit, or which piece: on the view-only page, hovering a piece shows its GUID. Call again for the next one; what is computed stays, and is not billed again. YOU SEE A SAMPLE IN THE OVERVIEW, THE WHOLE MODEL HERE. Never choose the units from what read_ifc_overview showed you - one example per type: choose from the list this tool returns. A REQUEST THE TOOL CANNOT MATCH. Names that match nothing come back under 'non_reconnus', each with the closest names; the names that did match are computed. If NOTHING matched - or the GUID or unit_name is unknown - nothing is computed, whatever the size of the model: the list comes back, with the closest names under 'non_reconnus' and what went wrong under 'demande_non_satisfaite'. Correct the names from the list, or ask the user which one they meant, and call again. A PIECE INSTEAD OF A UNIT. When the model has no unit, when the unit the user means was not recognised, or when they simply show a piece: network_guid computes the network of any piece - the tool finds where its air starts; end_guid computes one circuit to that end - from start_guid if given, else from the start the tool finds. A start found by the tool comes back under 'depart_trouve' with what made it chosen: say so, and ask the user to check it on the 3D link. The user gets a GUID by hovering a piece on the view-only page. These work
- 2026-10-16 `apply_ifc_rules` changed (description)
  - before: Turn what you read in the overview into rules the tool replays on EVERY piece of the model, including the ones you were never shown. THIS IS HOW THE TOOL LEARNS A MODEL. read_ifc_overview gives you some fifty groups — one per object type, not one per piece. You answer with RULES on those groups, and this tool applies them to the three thousand pieces. You never give a verdict piece by piece: the result stays deterministic because a program, not you, does the matching. THEN READ THE ANSWER BACK, AND EXPECT TO POST AGAIN. The answer gives every group with the role your rules gave it and how many pieces that is. A rule that is too wide shows up on one line — « Gaine rectangulaire cadree, 471 pieces, centrale_de_traitement_d_air » is a rule that turned every duct into an air handling unit. Narrow it and post again. Calling this tool costs nothing and may be repeated as often as you need. WHAT NEEDS A ROLE, AND WHAT DOES NOT. Plain ducts and fittings need none: they are network by nature, and the answer marks them segment_ou_raccord so you can see at a glance whether a rule caught them by mistake. What needs a role is everything else — air handling units, fans, fire dampers, balancing dampers, silencers, louvres, diffusers — plus whatever must be kept OUT of the network, such as access zones, equipment plinths or damper motors. TWO ROLE NAMES ARE FIXED, because circuits start from them: give air handling units, monoblocs and ventilation casings the role centrale_de_traitement_d_air, and fans the role ventilateur - exactly these words. The answer lists, under 'equipements', the GUIDs of every piece of the model that got one of them: that list is what trace_duct_circuits computes when called with only the token. Every other role name is yours to choose. ORDER THE LIST YOURSELF, most specific first, down to the most general. The fire damper rule must come before the balancing damper rule, or « damper » takes everything. Equipment must come before terminals: « VEN_MSF_MONOBLOC_SIMPLE_FLUX_REPRISE » contains « reprise », and a return-diffuser rule placed first would claim the air handling unit. Pieces no rule catches are simply listed, with no warning and no failure: the engineer judges on the 3D view, not on a coverage report. NEXT: once 'equipements' lists the air handling units and fans you expect, call trace_duct_circuits with only the token. It computes nothing yet: it returns the complete list of the model's systems and units, to choose from - see trace_duct_circuits. 'equipements' counts every piece ('pieces') but lists at most thirty names: the count, not the list, is the model.
  - after: Turn what you read in the overview into rules the tool replays on EVERY piece of the model, including the ones you were never shown. THIS IS HOW THE TOOL LEARNS A MODEL. read_ifc_overview gives you some fifty groups — one per object type, not one per piece. You answer with RULES on those groups, and this tool applies them to the three thousand pieces. You never give a verdict piece by piece: the result stays deterministic because a program, not you, does the matching. THEN READ THE ANSWER BACK, AND EXPECT TO POST AGAIN. The answer gives every group with the role your rules gave it and how many pieces that is. A rule that is too wide shows up on one line — « Gaine rectangulaire cadree, 471 pieces, centrale_de_traitement_d_air » is a rule that turned every duct into an air handling unit. Narrow it and post again. Calling this tool costs nothing and may be repeated as often as you need. WHAT NEEDS A ROLE, AND WHAT DOES NOT. Plain ducts and fittings need none: they are network by nature, and the answer marks them segment_ou_raccord so you can see at a glance whether a rule caught them by mistake. What needs a role is everything else — air handling units, fans, fire dampers, balancing dampers, silencers, louvres, diffusers — plus whatever must be kept OUT of the network, such as access zones, equipment plinths or damper motors. TWO ROLE NAMES ARE FIXED, because circuits start from them: give air handling units, monoblocs and ventilation casings the role centrale_de_traitement_d_air, and fans the role ventilateur - exactly these words. The answer lists, under 'equipements', the GUIDs of every piece of the model that got one of them: that list is what trace_duct_circuits computes when called with only the token. Every other role name is yours to choose. ORDER THE LIST YOURSELF, most specific first, down to the most general. The fire damper rule must come before the balancing damper rule, or « damper » takes everything. Equipment must come before terminals: « VEN_MSF_MONOBLOC_SIMPLE_FLUX_REPRISE » contains « reprise », and a return-diffuser rule placed first would claim the air handling unit. Pieces no rule catches are simply listed, with no warning and no failure: the engineer judges on the 3D view, not on a coverage report. NEXT: once 'equipements' lists the air handling units and fans you expect, call trace_duct_circuits with only the token. It computes nothing yet: it checks that the units are connected to the networks and returns the complete list of units and fans, to choose from - see trace_duct_circuits. 'equipements' counts every piece ('pieces') but lists at most thirty names: the count, not the list, is the model.
- 2026-10-16 `read_ifc_overview` changed (description)
  - before: CALL THIS FIRST, as soon as the user gives you a token. It answers within seconds, while the network graph is still being built - use that time to think. THE CIRCUITS OF A MODEL IN FOUR CALLS: 1. read_ifc_overview - this call: the types of the model. 2. apply_ifc_rules - your rules. Give air handling units, monoblocs and ventilation casings the role centrale_de_traitement_d_air, and fans the role ventilateur, exactly these words. Its answer lists under 'equipements' every unit and fan of the model. 3. trace_duct_circuits with ONLY the token - it computes nothing and returns the COMPLETE list of the model's systems and units. 4. trace_duct_circuits again with what the user wants: systems and/or units, or all_networks=true for the whole model (offered up to 50 air networks only). The answer of this call repeats these steps under 'marche_a_suivre'. YOU SEE A SAMPLE, THE TOOL SEES EVERYTHING. This overview shows one example per type, not every piece: you cannot count the units, the fans or the networks of the model from it, and you must not believe you have seen them all. The tool applies your rules to every piece and walks every network. So never pick the networks to compute from this overview: trace_duct_circuits gives you the complete list of systems and units first, and you choose from THAT list. WHAT YOU GET. Not 3 000 parts: the 20 to 50 distinct TYPES of the model (duct types, fittings, dampers, terminals, equipment, proxies), each with its IFC class, predefined type, type name, one example part with ALL its properties, and a catalogue of every property present. WHAT TO DO WITH IT. Write RULES, not verdicts. For roles: which words, in which field, identify a fire damper, a silencer, a balancing damper, an air terminal, an air handling unit, a fan, a pump - and which groups are NOT network at all (access zones, plinths, placeholders, damper motors). For sizes: which 'PropertySet.Property' holds height, width, diameter, length. A rule applies to every part, including those you were not shown, and to the user's next models. TRAPS the field 'a_savoir' warns about: values are in the FILE's unit (see metres_par_unite), not millimetres; insulation sizes and hydraulic diameters look like dimensions and are not. The field 'etat_du_graphe' says whether the networks are ready yet: 'pret' means read_ifc_networks will answer now.
  - after: CALL THIS FIRST, as soon as the user gives you a token. It answers within seconds, while the network graph is still being built - use that time to think. THE CIRCUITS OF A MODEL IN FOUR CALLS: 1. read_ifc_overview - this call: the types of the model. 2. apply_ifc_rules - your rules. Give air handling units, monoblocs and ventilation casings the role centrale_de_traitement_d_air, and fans the role ventilateur, exactly these words. Its answer lists under 'equipements' every unit and fan of the model. 3. trace_duct_circuits with ONLY the token - it computes nothing, walks the networks from every unit and fan, and either returns the COMPLETE list of units and fans with a view-only page, or says the units could not be connected to the model's networks. 4. trace_duct_circuits again with the units the user wants, or all_networks=true for all of them (offered up to 50 air networks only). The answer of this call repeats these steps under 'marche_a_suivre'. YOU SEE A SAMPLE, THE TOOL SEES EVERYTHING. This overview shows one example per type, not every piece: you cannot count the units, the fans or the networks of the model from it, and you must not believe you have seen them all. The tool applies your rules to every piece and walks every network. So never pick the networks to compute from this overview: trace_duct_circuits gives you the complete list of units and fans first, and you choose from THAT list. WHAT YOU GET. Not 3 000 parts: the 20 to 50 distinct TYPES of the model (duct types, fittings, dampers, terminals, equipment, proxies), each with its IFC class, predefined type, type name, one example part with ALL its properties, and a catalogue of every property present. WHAT TO DO WITH IT. Write RULES, not verdicts. For roles: which words, in which field, identify a fire damper, a silencer, a balancing damper, an air terminal, an air handling unit, a fan, a pump - and which groups are NOT network at all (access zones, plinths, placeholders, damper motors). For sizes: which 'PropertySet.Property' holds height, width, diameter, length. A rule applies to every part, including those you were not shown, and to the user's next models. TRAPS the field 'a_savoir' warns about: values are in the FILE's unit (see metres_par_unite), not millimetres; insulation sizes and hydraulic diameters look like dimensions and are not. The field 'etat_du_graphe' says whether the networks are ready yet: 'pret' means read_ifc_networks will answer now.
- 2026-10-14 `trace_duct_circuits` changed (description, inputSchema)
  - before: THE CIRCUITS THE FANS OF A MODEL ARE SIZED ON, AND THEIR PRESSURE DROP, without anyone clicking. FIRST THE LIST, THEN THE CALCULATION. Called with only the token, once your rules are posted with apply_ifc_rules, it computes NOTHING and bills nothing: it returns the COMPLETE list of the model's systems ('systemes', each with the units that serve it) and of its air handling units and fans ('centrales_et_ventilateurs', each with the systems it serves). This list is complete, unlike the overview: you may choose from it. - The user named units or systems, even loosely: map their words onto the EXACT names of the list, say which you picked, and call again with systems and/or units. - The user asked for the whole model and the list says 'tous_possible' (50 air networks or fewer): call again with all_networks=true. - Otherwise show the user the WHOLE list to tick - every unit and fan, every system, however long; never only the main ones. 'Tous' first when it is offered, then one numbered line per unit with the systems it serves, then the systems no unit serves. Filter only on what the user said (a name, a building, a level, exhaust...), and then say which filter and how many lines it left out. Call with what they tick. BEYOND 50 AIR NETWORKS, 'Tous' is not offered: the model is too complex to compute at once, and all_networks returns the list again. A system brings in the WHOLE unit that serves it - supply, return, outdoor air, exhaust. To add more later, call again with the new names: what is already computed stays, and is not billed again. The whole model starts from every unit and fan, units first, each explored on its own, and lists them under 'departs'. A NETWORK WITH NO UNIT IS NOT SKIPPED. When no unit or fan of your rules serves it - the unit sits in another file, is not chosen yet, or your rules missed it - it starts from a unit found by its IFC class that your rules gave no role, or else from its largest free duct end, where a missing unit would connect. These starts are SUPPOSED and marked 'depart_suppose' under 'departs': say so, and ask the user to check them on the 3D link. YOU SEE A SAMPLE IN THE OVERVIEW, THE WHOLE MODEL HERE. Never choose the networks from what read_ifc_overview showed you - one example per type: choose from the list this tool returns. A REQUEST THE TOOL CANNOT MATCH. Names that match nothing come back under 'non_reconnus', each with the closest names; the names that did match are computed. If NOTHING matched - or the GUID or unit_name is unknown - nothing is computed, whatever the size of the model: the list comes back, with the closest names under 'non_reconnus' and what went wrong under 'demande_non_satisfaite'. Correct the names from the list, or ask the user which one they meant, and call again. ONE UNIT BY ITS NAME. unit_name computes the unit or fan of that name, found among all the pieces - units does the same for several. start_guid starts from one part - an air handling unit, a fan, a duct - and computes the network it belongs to, nothing else. The answer says so under 'portee' and lists the model's other units and fans under 'autres_departs': tell the user the result is partial. From each starting part it keeps ONE CIRCUIT PER BRANCH: the longest path in metres of each branch. From an air handling unit, that is one circuit per network connected to it - supply, return, intake, exhaust. EACH OF THESE CIRCUITS IS COMPUTED, and becomes a circuit of the model: it has a name, a COLOUR, and a tab on the website. WHAT YOU GET portee what the call covers: the whole model, one role, or one part's network only. circuits one per branch: name, colour, length, and - once 'etat' is 'pret' - the pressure drop in Pa, its linear and local parts, the maximum velocity, the flow used at the start and where it came from. autres_arrivees shorter paths, found but NOT c
  - after: THE CIRCUITS THE FANS OF A MODEL ARE SIZED ON, AND THEIR PRESSURE DROP, without anyone clicking. FIRST THE LIST, THEN THE CALCULATION. Called with only the token, once your rules are posted with apply_ifc_rules, it computes NOTHING and bills nothing: it returns the COMPLETE list of the model's systems ('systemes', each with the units that serve it) and of its air handling units and fans ('centrales_et_ventilateurs', each with the systems it serves). This list is complete, unlike the overview: you may choose from it. - The user named units or systems, even loosely: map their words onto the EXACT names of the list, say which you picked, and call again with systems and/or units. - The user asked for the whole model and the list says 'tous_possible' (50 air networks or fewer): call again with all_networks=true. - Otherwise show the user the WHOLE list to tick - every unit and fan, every system, however long; never only the main ones. 'Tous' first when it is offered, then one numbered line per unit with the systems it serves, then the systems no unit serves. Filter only on what the user said (a name, a building, a level, exhaust...), and then say which filter and how many lines it left out. Call with what they tick. BEYOND 50 AIR NETWORKS, THE MODEL IS COMPUTED ONE NETWORK AT A TIME. The call with only the token returns just the units and fans ('centrales_et_ventilateurs', each with the systems it serves) and the networks link. Each call then computes ONE unit - unit_name, or units with a single name - or the network of ONE piece - start_guid. The whole model, start_role, systems and several units are refused: nothing is computed, and the answer says why. Ask the user which unit, or which piece: on the link, a click on a piece shows its GUID. Call again for the next one; what is computed stays. A system brings in the WHOLE unit that serves it - supply, return, outdoor air, exhaust. To add more later, call again with the new names: what is already computed stays, and is not billed again. The whole model starts from every unit and fan, units first, each explored on its own, and lists them under 'departs'. A NETWORK WITH NO UNIT IS NOT SKIPPED. When no unit or fan of your rules serves it - the unit sits in another file, is not chosen yet, or your rules missed it - it starts from a unit found by its IFC class that your rules gave no role, or else from its largest free duct end, where a missing unit would connect. These starts are SUPPOSED and marked 'depart_suppose' under 'departs': say so, and ask the user to check them on the 3D link. YOU SEE A SAMPLE IN THE OVERVIEW, THE WHOLE MODEL HERE. Never choose the networks from what read_ifc_overview showed you - one example per type: choose from the list this tool returns. A REQUEST THE TOOL CANNOT MATCH. Names that match nothing come back under 'non_reconnus', each with the closest names; the names that did match are computed. If NOTHING matched - or the GUID or unit_name is unknown - nothing is computed, whatever the size of the model: the list comes back, with the closest names under 'non_reconnus' and what went wrong under 'demande_non_satisfaite'. Correct the names from the list, or ask the user which one they meant, and call again. A PIECE INSTEAD OF A UNIT. When the model has no unit, when the unit the user means was not recognised, or when they simply show a piece: network_guid computes the network of any piece - the tool finds where its air starts; end_guid computes one circuit to that end - from start_guid if given, else from the start the tool finds. A start found by the tool comes back under 'depart_trouve' with what made it chosen: say so, and ask the user to check it on the 3D link. The user gets a GUID by clicking a piece on the networks link. These work on complex models too: they designate one network. ONE UNIT BY ITS NAME. unit_name computes the unit or fan of that name, found among all the pieces - units does the same fo
- 2026-10-13 `trace_duct_circuits` changed (description, inputSchema)
  - before: THE CIRCUITS THE FANS OF A MODEL ARE SIZED ON, AND THEIR PRESSURE DROP, without anyone clicking. FIRST THE LIST, THEN THE CALCULATION. Called with only the token, once your rules are posted with apply_ifc_rules, it computes NOTHING and bills nothing: it returns the COMPLETE list of the model's systems ('systemes', each with the units that serve it) and of its air handling units and fans ('centrales_et_ventilateurs', each with the systems it serves). This list is complete, unlike the overview: you may choose from it. - The user named units or systems, even loosely: map their words onto the EXACT names of the list, say which you picked, and call again with systems and/or units. - The user asked for the whole model and the list says 'tous_possible' (50 air networks or fewer): call again with all_networks=true. - Otherwise show the user a short list to tick - 'Tous' first when it is offered, then the systems grouped by unit, biggest first - and call with what they tick. BEYOND 50 AIR NETWORKS, 'Tous' is not offered: the model is too complex to compute at once, and all_networks returns the list again. A system brings in the WHOLE unit that serves it - supply, return, outdoor air, exhaust. To add more later, call again with the new names: what is already computed stays, and is not billed again. The whole model starts from every unit and fan, units first, each explored on its own, and lists them under 'departs'. A NETWORK WITH NO UNIT IS NOT SKIPPED. When no unit or fan of your rules serves it - the unit sits in another file, is not chosen yet, or your rules missed it - it starts from a unit found by its IFC class that your rules gave no role, or else from its largest free duct end, where a missing unit would connect. These starts are SUPPOSED and marked 'depart_suppose' under 'departs': say so, and ask the user to check them on the 3D link. YOU SEE A SAMPLE IN THE OVERVIEW, THE WHOLE MODEL HERE. Never choose the networks from what read_ifc_overview showed you - one example per type: choose from the list this tool returns. A REQUEST THE TOOL CANNOT MATCH. Names that match nothing come back under 'non_reconnus', each with the closest names: ask the user. If nothing at all matched - or the GUID or unit_name is unknown - a model of 50 air networks or fewer is computed WHOLE, and the answer says why under 'demande_non_satisfaite'; beyond 50, the list comes back. Tell the user. ONE UNIT BY ITS NAME. unit_name computes the unit or fan of that name, found among all the pieces - units does the same for several. start_guid starts from one part - an air handling unit, a fan, a duct - and computes the network it belongs to, nothing else. The answer says so under 'portee' and lists the model's other units and fans under 'autres_departs': tell the user the result is partial. From each starting part it keeps ONE CIRCUIT PER BRANCH: the longest path in metres of each branch. From an air handling unit, that is one circuit per network connected to it - supply, return, intake, exhaust. EACH OF THESE CIRCUITS IS COMPUTED, and becomes a circuit of the model: it has a name, a COLOUR, and a tab on the website. WHAT YOU GET portee what the call covers: the whole model, one role, or one part's network only. circuits one per branch: name, colour, length, and - once 'etat' is 'pret' - the pressure drop in Pa, its linear and local parts, the maximum velocity, the flow used at the start and where it came from. autres_arrivees shorter paths, found but NOT computed. lien_3d the page where every circuit shows in its colour. metre the take-off of the whole network. IF A CIRCUIT IS STILL 'calcul', call again with THE SAME ARGUMENTS a moment later. Nothing is recomputed and nothing is billed again: an identical call only reads. A different velocity or flow is applied to the circuits already there, without a new ana
  - after: THE CIRCUITS THE FANS OF A MODEL ARE SIZED ON, AND THEIR PRESSURE DROP, without anyone clicking. FIRST THE LIST, THEN THE CALCULATION. Called with only the token, once your rules are posted with apply_ifc_rules, it computes NOTHING and bills nothing: it returns the COMPLETE list of the model's systems ('systemes', each with the units that serve it) and of its air handling units and fans ('centrales_et_ventilateurs', each with the systems it serves). This list is complete, unlike the overview: you may choose from it. - The user named units or systems, even loosely: map their words onto the EXACT names of the list, say which you picked, and call again with systems and/or units. - The user asked for the whole model and the list says 'tous_possible' (50 air networks or fewer): call again with all_networks=true. - Otherwise show the user the WHOLE list to tick - every unit and fan, every system, however long; never only the main ones. 'Tous' first when it is offered, then one numbered line per unit with the systems it serves, then the systems no unit serves. Filter only on what the user said (a name, a building, a level, exhaust...), and then say which filter and how many lines it left out. Call with what they tick. BEYOND 50 AIR NETWORKS, 'Tous' is not offered: the model is too complex to compute at once, and all_networks returns the list again. A system brings in the WHOLE unit that serves it - supply, return, outdoor air, exhaust. To add more later, call again with the new names: what is already computed stays, and is not billed again. The whole model starts from every unit and fan, units first, each explored on its own, and lists them under 'departs'. A NETWORK WITH NO UNIT IS NOT SKIPPED. When no unit or fan of your rules serves it - the unit sits in another file, is not chosen yet, or your rules missed it - it starts from a unit found by its IFC class that your rules gave no role, or else from its largest free duct end, where a missing unit would connect. These starts are SUPPOSED and marked 'depart_suppose' under 'departs': say so, and ask the user to check them on the 3D link. YOU SEE A SAMPLE IN THE OVERVIEW, THE WHOLE MODEL HERE. Never choose the networks from what read_ifc_overview showed you - one example per type: choose from the list this tool returns. A REQUEST THE TOOL CANNOT MATCH. Names that match nothing come back under 'non_reconnus', each with the closest names; the names that did match are computed. If NOTHING matched - or the GUID or unit_name is unknown - nothing is computed, whatever the size of the model: the list comes back, with the closest names under 'non_reconnus' and what went wrong under 'demande_non_satisfaite'. Correct the names from the list, or ask the user which one they meant, and call again. ONE UNIT BY ITS NAME. unit_name computes the unit or fan of that name, found among all the pieces - units does the same for several. start_guid starts from one part - an air handling unit, a fan, a duct - and computes the network it belongs to, nothing else. The answer says so under 'portee' and lists the model's other units and fans under 'autres_departs': tell the user the result is partial. From each starting part it keeps ONE CIRCUIT PER BRANCH: the longest path in metres of each branch. From an air handling unit, that is one circuit per network connected to it - supply, return, intake, exhaust. EACH OF THESE CIRCUITS IS COMPUTED, and becomes a circuit of the model: it has a name, a COLOUR, and a tab on the website. WHAT YOU GET portee what the call covers: the whole model, one role, or one part's network only. circuits one per branch: name, colour, length, and - once 'etat' is 'pret' - the pressure drop in Pa, its linear and local parts, the maximum velocity, the flow used at the start and where it came from. autres_arrivees shorter paths, found but NOT c

Full history: https://api.protogrid.dev/v1/servers/com.thenewengineer%2Fhvac/changes

## Remotes

- https://thenewengineer.com/mcp (streamable-http, auth none, reachable true, uptime30d 1)

## Packages

_none_

## Tools (11)

- `apply_ifc_rules`: Turn what you read in the overview into rules the tool replays on
EVERY piece of the model, including the ones you were never shown.

THIS IS HOW THE TOOL LEARNS A MODEL. read_ifc_overview gives you some
fifty groups — one per object type, not one per piece. You answer with
RULES on those groups, and this tool applies them to the three thousand
pieces. You never give a verdict piece by piece: the result stays
deterministic because a program, not you, does the matching.

THEN READ THE ANSWER BACK, AND EXPECT TO POST AGAIN. The answer gives
every group with the role your rules gave it and how many pieces that
is. A rule that is too wide shows up on one line — « Gaine
rectangulaire cadree, 471 pieces, centrale_de_traitement_d_air » is a
rule that turned every duct into an air handling unit. Narrow it and
post again. Calling this tool costs nothing and may be repeated as
often as you need.

WHAT NEEDS A ROLE, AND WHAT DOES NOT. Plain ducts and fittings need
none: they are network by nature, and the answer marks them
segment_ou_raccord so you can see at a glance whether a rule caught
them by mistake. What needs a role is everything else — air handling
units, fans, fire dampers, balancing dampers, silencers, louvres,
diffusers — plus whatever must be kept OUT of the network, such as
access zones, equipment plinths or damper motors.

TWO ROLE NAMES ARE FIXED, because circuits start from them: give air
handling units, monoblocs and ventilation casings the role
centrale_de_traitement_d_air, and fans the role ventilateur - exactly
these words. ONLY EQUIPMENT THAT MOVES THE AIR gets one of them: a
unit is a box with a fan in it. Heating and cooling coils, heat
exchangers, filters, silencers, dampers, fire dampers, VAV boxes,
humidifiers are NOT units: the air runs through them, they are
pieces of the network. Give them another role (coil, silencer,
damper...) or none - never one of the two unit roles. A coil in
'equipements' is a rule that is too wide. The answer lists, under
'equipements', the GUIDs of every piece of the model that got one of
the two roles: that list is what trace_duct_circuits starts from,
and what the pages show as units. Every other role name is yours to
choose.

ORDER THE LIST YOURSELF, most specific first, down to the most
general.
The fire damper rule must come before the balancing damper rule, or
« damper » takes everything. Equipment must come before terminals:
« VEN_MSF_MONOBLOC_SIMPLE_FLUX_REPRISE » contains « reprise », and a
return-diffuser rule placed first would claim the air handling unit.

Pieces no rule catches are simply listed, with no warning and no
failure: the engineer judges on the 3D view, not on a coverage report.

NEXT: once 'equipements' lists the air handling units and fans you
expect, call trace_duct_circuits with only the token. It computes
nothing yet: it checks that the units are connected to the networks
and returns the complete list of units and fans, to choose from -
see trace_duct_circuits. 'equipements' counts every piece
('pieces') but lists at most thirty names: the count, not the list,
is the model.

- `check_en378_zones`: DETERMINISTIC: the same inputs always give the same result — from any AI, on any day. Figures come from the standard's tables and formulas, never from a language model's estimate. Every step is auditable.

EN 378 applied to BUILDING projects, volume by volume.

An installation does not occupy one room but several: the machine, the rooms
crossed by refrigerant lines, the rooms served by indoor units. Each volume
is classified on its own — access category (a/b/c) and location class (I–IV)
— and each classification calls for its own measures. The tool answers per
volume, never as a single verdict.

It returns, for every volume: its classification and why, the charge limit
from Tables C.1 and C.2 of EN 378-1 (with the C.2 formula computed when the
table calls for it), whether the charge exceeds it, the EN 378-3 measures
that follow, the applicable texts (EN 378-1 to -4, EN IEC 60079-10-1, SUVA
66139 and 2153) and the ventilation flow rates.

FOUR CONFIGURATIONS COVER ALMOST EVERY BUILDING PROJECT. Bring the user's
case back to one of them wherever possible:
  machine_en_local_technique   chiller or heat pump, all refrigerant inside
                               the machine, standing in a plant room -> c III
  enceinte_accessible_fermee   all refrigerant inside a walk-in ventilated
                               enclosure that stays closed even for
                               maintenance -> the enclosure is c III, the
                               room around it carries no requirement
  enceintes_inaccessibles      one or more units, each in a manufacturer's
                               non-accessible ventilated enclosure -> TWO
                               analyses: the enclosure in operation (class
                               IV, the manufacturer sizes and justifies it,
                               ask him for the enclosure ventilation), and
                               the plant room with the enclosure OPEN for
                               maintenance, which comes back to c III
  split_traversant             split or VRF outdoors, refrigerant lines
                               crossing occupied rooms -> each room on its
                               own; offices and their circulations are b I,
                               and formula C.2 gives the maximum charge for
                               the floor area, or the minimum floor area for
                               the charge

THIS TOOL ANSWERS SAFETY IN THE ROOM. It says NOTHING about whether the
refrigerant may still be placed on the market or refilled: in Switzerland that
is `check_refrigerant_switzerland`. A question that mixes both - « may I use
R-32 for 3 kg in a server room, and until when can I refill it » - needs BOTH
tools: call this one for the room, and check_refrigerant_switzerland for the
dates. Do not answer half the question.

NEVER guess. The refrigerant, the configuration and the charge are always
needed; a split also needs the floor area and how the indoor unit is mounted
(floor, wall, window, ceiling), since C.2 depends on it. Without them the
result is `provisional` and carries `questions_to_ask`: ask them, one or two
at a time, then call again.

Answer from `answer_outline`, volume by volume. In building projects,
detection is preferred over treating a plant room as an ATEX zone. C.3 is
never used. Say that the practical limit alone proves nothing: the charge
limit of Tables C.1 and C.2 is what counts.

SCOPE: building services. Cold rooms, food refrigeration and industrial
process refrigeration are a different trade.

- `check_refrigerant_switzerland`: DETERMINISTIC: the same inputs always give the same result — from any AI, on any day. Figures come from the regulation's annexes and thresholds, never from a language model's estimate. Every step is auditable.

Swiss refrigerant regulation check (ORRChim / ChemRRV annex 2.10, OFEV synthesis
of May 2026, rules adopted 29.10.2025) plus refrigerant data from EN 378-1
Annex E: GWP (AR4, the ORRChim basis), ODP, LFL, safety class, practical limit.

Returns, for a given refrigerant and installation: the date from which machines
using it can no longer be placed on the Swiss market (import from 01.01.2027,
sale to third parties from 01.07.2027), the date from which filling with virgin
refrigerant is banned, the period when only reclaimed refrigerant may be used,
and the date from which all filling is banned.

SCOPE: heating, air conditioning, building cooling and process cooling,
data centres included. NOT food refrigeration, cold rooms or deep freezing:
those are a different trade, and the tool declines them instead of
answering.

Use it whenever the user asks about a refrigerant in Switzerland — its GWP / PRG,
flammability, whether a chiller, heat pump, split, VRF or cold room using it may
still be sold or refilled — in any language: fluide frigorigène, Kältemittel,
refrigerante, refrigerant, R-32, R-410A, R-290, CO2, NH3...

The answer depends on the installation. The regulation distinguishes:
use (building cooling, food refrigeration medium / low temperature / combined /
deep freezing, process cooling, heat pump mainly for heating, ice rink), cooling
capacity Q0K or heating capacity Q0H, self-contained (factory-built packaged
unit) or not, split, direct expansion (incl. VRF), secondary coolant loop
(chilled water / brine), air-cooled condenser and refrigerant charge.
THIS TOOL ANSWERS ONE QUESTION ONLY: may the refrigerant still be sold and
refilled in Switzerland, and until when. It says NOTHING about safety in the
room - charge limits, machine room, detection, ventilation, ATEX. That is
`check_en378_zones`. A question that mixes both - « may I use R-32 for 3 kg in
a server room, and until when can I refill it » - needs BOTH tools: call this
one for the dates, and check_en378_zones for the room. Do not answer half the
question.

NEVER guess these. Call the tool with what the user gave: it returns
`provisional: true`, the possible `scenarios`, and `questions_to_ask` in the
order that matters most. Ask them (one or two at a time), then call again.
Natural refrigerants need no questions. Build your answer on `answer_outline`;
quote exceptions as possible, never as granted.

- `ifc_upload_result`: Where the upload stands. When `state` is `depose`, `token` is the
token to pass to read_ifc_networks.
- `name_ifc_networks`: Apply the names you propose, and get back the updated report.

THE NAMES ARE YOURS, THE NETWORKS ARE NOT. You are naming what the
tool measured; you are not changing what it measured. Nothing you
send here alters a network, a part, or a correction.

WHAT COMES BACK. The updated report, a 3D link where the user sees
your names in colour, and a link to the corrective Dynamo script that
writes the systems back into Revit.

ALWAYS GIVE THE USER THE 3D LINK, and say plainly which names are
yours. Networks are deterministic; names are a proposal. A user who
cannot tell the two apart cannot check your work.

AFTER THE USER HAS BEEN IN THE 3D VIEW, call read_ifc_networks again
with the same token before saying anything about the model. They may
have renamed what you proposed, assigned parts by hand, or refused a
correction — and only a fresh read shows it.

- `open_ifc_upload`: Show an upload box in the conversation where the user can drop an
IFC file (.ifc) of a building services model (HVAC, plumbing,
heating). The file goes straight from the user's browser to
thenewengineer.com - you never see it.

CALL THIS when the user wants to analyse an IFC model and has not yet
given you a link from thenewengineer.com. Then tell the user to drop
the file in the box.

When the upload is done, the box posts a message with a token. Use
that token with read_ifc_networks. If no message arrives and the user
says the upload is done, call ifc_upload_result with the upload_token
returned here.

Prototype: files up to the anonymous size limit of the site.
- `read_ifc_networks`: DETERMINISTIC: networks come from geometry, not from a guess. The
same model always gives the same networks, from any AI, on any day.

Read the networks of an IFC model already uploaded by the user.

WHAT A NETWORK IS. A set of parts that touch each other, cut at
equipment: a pump, an air handling unit, a chiller separates two
systems, so the tool does not run through them. This is measured on
the geometry — you cannot and need not check it.

WHAT YOU GET, PER NETWORK
  state          'homogeneous' — a system exists, some parts were
                 mis-named by the modeller; the tool will correct them.
                 'undetermined' — no system can be read. THIS is where
                 you are useful.
                 'assigned' — the user or you already named it.
  system         the dominant name, when there is one
  part_dominante the share of named parts carrying it
  equipements_voisins  the NAMES of the machines this network is
                 connected to. An undetermined network starting from
                 'AHU-Supply-L2' names itself — but only you can see it.
  systemes_existants   every system name already in the model

WHAT TO DO NEXT. Propose a name for each undetermined network, using
the neighbouring equipment, the existing system names, and anything
the user told you about the project's naming scheme. Ask the user for
their list of planned systems if you do not have it. Then call
name_ifc_networks.

WHAT NOT TO DO. Do not rename a network the report calls
'homogeneous' unless its name plainly contradicts the equipment it is
connected to — and then say why. Do not invent a network: you cannot
see the geometry, and the tool already did that work.

CALL THIS AGAIN WHENEVER THE STATE MAY HAVE MOVED. The token stays
valid for 48 hours and is a key, not a snapshot: every call recomputes
and returns the model AS IT IS NOW. The user works in the browser
between your messages — renaming networks, assigning parts by hand,
accepting or refusing corrections. So the moment they say they have
done something, or you are about to state a figure, call this tool
again.

NEVER ANSWER FROM MEMORY about networks, counts or states. What you
read earlier is already out of date the moment the user touches the
3D view, and a stale figure stated confidently is worse than no
figure at all.

- `read_ifc_overview`: CALL THIS FIRST, as soon as the user gives you a token. It answers
within seconds, while the network graph is still being built - use
that time to think.

THE CIRCUITS OF A MODEL IN FOUR CALLS:
  1. read_ifc_overview - this call: the types of the model.
  2. apply_ifc_rules - your rules. Give air handling units,
     monoblocs and ventilation casings the role
     centrale_de_traitement_d_air, and fans the role ventilateur,
     exactly these words - and ONLY to equipment that holds a fan.
     Coils, heat exchangers, filters, silencers, dampers, VAV boxes
     are pieces of the network, not units. Its answer lists under
     'equipements' every unit and fan of the model.
  3. trace_duct_circuits with ONLY the token - it computes nothing,
     walks the networks from every unit and fan, and either returns
     the COMPLETE list of units and fans with a view-only page, or
     says the units could not be connected to the model's networks.
  4. trace_duct_circuits again with the units the user wants, or
     all_networks=true for all of them (offered up to 50 air
     networks only).
The answer of this call repeats these steps under 'marche_a_suivre'.

YOU SEE A SAMPLE, THE TOOL SEES EVERYTHING. This overview shows one
example per type, not every piece: you cannot count the units, the
fans or the networks of the model from it, and you must not believe
you have seen them all. The tool applies your rules to every piece
and walks every network. So never pick the networks to compute from
this overview: trace_duct_circuits gives you the complete list of
units and fans first, and you choose from THAT list.

WHAT YOU GET. Not 3 000 parts: the 20 to 50 distinct TYPES of the
model (duct types, fittings, dampers, terminals, equipment, proxies),
each with its IFC class, predefined type, type name, one example part
with ALL its properties, and a catalogue of every property present.

WHAT TO DO WITH IT. Write RULES, not verdicts. For roles: which words,
in which field, identify a fire damper, a silencer, a balancing
damper, an air terminal, an air handling unit, a fan, a pump - and
which groups are NOT network at all (access zones, plinths,
placeholders, damper motors). For sizes: which 'PropertySet.Property'
holds height, width, diameter, length. A rule applies to every part,
including those you were not shown, and to the user's next models.

TRAPS the field 'a_savoir' warns about: values are in the FILE's unit
(see metres_par_unite), not millimetres; insulation sizes and
hydraulic diameters look like dimensions and are not.

The field 'etat_du_graphe' says whether the networks are ready yet:
'pret' means read_ifc_networks will answer now.
- `size_expansion_vessel`: DETERMINISTIC: the same inputs always give the same result — from any AI, on any day. Figures come from the standard's tables and formulas, never from a language model's estimate. Every step is auditable.

Size the expansion vessel and pressurisation of a closed heating or
    chilled-water circuit to EN 12828: static height, minimum pressure p0,
    fill pressure pa, final pressure pe, expansion volume, water reserve,
    nominal vessel volume with the standard vessel to buy, safety valve
    setting together with the minimum it must not fall below, pressure
    class of the lowest equipment, intermediate vessel when needed.

    Heights become pressures through the real density of the fluid, at the
    temperature that matters for each: the coldest for p0, the design
    temperature for the valve and the lowest point. Water and glycols
    therefore give different figures for the same height.

    Use it whenever the user asks to size or check an expansion vessel,
    pressurisation unit, pre-charge pressure or safety valve — in any
    language: vase d'expansion, maintien de pression, Ausdehnungsgefäss,
    Druckhaltung, vaso di espansione, vaso de expansión.

    Needs the installation water volume and THREE heights, all measured
    from the point where the expansion vessel connects to the network:
      - the highest point of the installation, above it;
      - the lowest point, usually below it (negative) or level with it;
      - the safety valve, which always sits on the heat generator or
        chiller. If the user does not know it, it is assumed 1 m above
        the vessel connection, and the result says so.
    Ask the user for the volume and the three heights before calling.
    NEVER invent a height: if the lowest point or the valve height is
    unknown, omit it. The result is then marked provisional and lists
    the questions to ask. Build your answer on `answer_outline`: it
    carries the assumptions, the questions and the link to the website,
    which measures all of these on the user's IFC model.
    
- `trace_duct_circuits`: THE CIRCUITS THE FANS OF A MODEL ARE SIZED ON, found without anyone
clicking and computed on the pressure-drop page, where the user
confirms types and flows and reads the pressure drops.

ONLY UNITS AND FANS ARE EXCHANGED. The tool never sends you system
names: it sends the air handling units and fans your rules found,
each with what the network walk finds connected to it - geometry,
not names. A unit is equipment with a FAN - air handling unit,
monobloc, ventilation casing, fan. Coils, heat exchangers, filters,
silencers, dampers are network pieces: if one shows up in the list
(often as 'dans_le_reseau_de' another unit), your rules are too
wide - fix them with apply_ifc_rules before choosing.

FIRST THE CHECK AND THE LIST, THEN THE CALCULATION. Called with only
the token, once your rules are posted with apply_ifc_rules, it
computes NOTHING and bills nothing. It walks the networks from every
unit and fan and measures the share of the model's air pieces they
reach ('raccordement'). Two answers:
  - CONNECTED (half of the air pieces or more): the COMPLETE list of
    units and fans ('centrales_et_ventilateurs', each with its
    number of connected networks) and 'lien_centrales', a VIEW-ONLY
    page - every unit in a light colour with its name floating
    above it, each of its networks in the same colour. Give the
    user that link and say nothing is computed yet. Then:
      * the user named units, even loosely: map their words onto
        the EXACT names of the list, say which you picked, and call
        again with units;
      * the user asked for the whole model and the list says
        'tous_possible' (50 air networks or fewer): call again with
        all_networks=true;
      * otherwise show the user the WHOLE list to tick - every unit
        and fan, however long; never only the main ones. 'Tous'
        first when it is offered, then one numbered line per unit
        with its number of connected networks; mark the units
        connected to nothing. Filter only on what the user said,
        and then say which filter and how many lines it left out.
        Call with what they tick.
  - NOT CONNECTED ('non_raccorde': less than half, or no unit at
    all): tell the user the sentence of 'A_DIRE_A_L_UTILISATEUR' -
    « Nous n'avons pas pu connecter les centrales de traitement
    d'air aux réseaux de votre modèle », in their language - and
    suggest the pressure-drop page ('lien_pdc'), where they define
    each network themselves by a start and an end. Nothing is
    computed. If your rules missed units, fix them and call again.
WHAT IS COMPUTED: for each network connected to a chosen unit or
fan, the LONGEST path. Networks connected to no unit are not
computed here.
BEYOND 50 AIR NETWORKS, THE MODEL IS COMPUTED ONE UNIT AT A TIME.
Each call computes ONE unit - unit_name, or units with a single
name - or the network of ONE piece - network_guid. The whole model,
start_role and several units are refused: nothing is computed, and
the answer says why. Ask the user which unit, or which piece: on the
view-only page, hovering a piece shows its GUID. Call again for the
next one; what is computed stays, and is not billed again.

YOU SEE A SAMPLE IN THE OVERVIEW, THE WHOLE MODEL HERE. Never choose
the units from what read_ifc_overview showed you - one example per
type: choose from the list this tool returns.

A REQUEST THE TOOL CANNOT MATCH. Names that match nothing come back
under 'non_reconnus', each with the closest names; the names that
did match are computed. If NOTHING matched - or the GUID or
unit_name is unknown - nothing is computed, whatever the size of
the model: the list comes back, with the closest names under
'non_reconnus' and what went wrong under 'demande_non_satisfaite'.
Correct the names from the list, or ask the user which one they
meant, and call again.

A PIECE INSTEAD OF A UNIT. When the model has no unit, when the
unit the user means was not recognised, or when they simply show a
piece: network_guid computes the network of any piece - the tool
finds where its air starts; end_guid computes one circuit to that
end - from start_guid if given, else from the start the tool finds.
A start found by the tool comes back under 'depart_trouve' with what
made it chosen: say so, and ask the user to check it on the 3D link.
The user gets a GUID by hovering a piece on the view-only page.
These work on complex models too: they designate one network.

ONE UNIT BY ITS NAME. unit_name computes the unit or
fan of that name, found among all the pieces - units does the same
for several. start_guid starts from
one part - an air handling unit, a fan, a duct - and computes the
network it belongs to, nothing else. The answer says so under 'portee' and
lists the model's other units and fans under 'autres_departs': tell
the user the result is partial.

From each starting part it keeps ONE CIRCUIT PER BRANCH: the longest
path in metres of each branch. From an air handling unit, that is one
circuit per network connected to it - supply, return, intake,
exhaust.

EACH OF THESE CIRCUITS IS COMPUTED, and becomes a circuit of the
model: it has a name, a COLOUR, and a tab on the website. All the
circuits of one unit or fan share THAT UNIT'S colour; on the page,
its networks show in a light version of it, and networks connected
to no unit in grey.

WHAT YOU GET
  portee          what the call covers: the whole model, one role,
                  or one part's network only.
  circuits        one per branch: name, colour, length, its unit,
                  its current type, the flow used at the start and
                  where it came from. NO PRESSURE DROP: see below.
  autres_arrivees shorter paths, found but NOT computed.
  lien_3d         the calculation page: every unit's networks in
                  its colour, its circuits in a deeper shade.
  lien_centrales  the view-only page of the units and their networks.
  lien_classeur   the Excel workbook of the computed circuits: the
                  supply / return box and the flows are corrected
                  there and everything recalculates. Give it too
                  (a free account is needed to download it).
  metre           the take-off of the whole network.

IF A CIRCUIT IS STILL 'calcul', call again with THE SAME ARGUMENTS a
moment later. Nothing is recomputed and nothing is billed again: an
identical call only reads.
A different velocity or flow is applied to the circuits already
there, without a new analysis.

HOW TO USE IT WELL.

Ask the user for the design velocity before calling, or say which one
you used. THIS TOOL DOES NOT READ THE FLOW FROM THE MODEL: look for
it in the air handling unit's properties with read_ifc_overview and
pass it as flow_m3h, one unit at a time - see that argument. Failing
that, the flow comes
from the design velocity: between two branches, the length-weighted
average velocity of the straight ducts equals it, and no duct runs
more than 20 % above it.
Say which of the two it was.

TWO WAYS TO COMPUTE, AND THE USER CHOOSES. Offer them both, in one
short sentence each, before computing:
  - the network AS MODELLED (the default): flows follow the duct
    sections and never rise along a circuit, as in a sized network.
    The pressure drops are NOT returned - see below.
  - a PRELIMINARY network (preliminary_design=true): nothing is
    sized yet, so each stretch carries what its own ducts carry at
    the design velocity, the flow may rise along the circuit, and
    every fitting is computed at that velocity. The pressure drops
    ARE returned, because they no longer depend on any flow the user
    must confirm: they say what a correctly sized circuit with these
    singularities and this length would reach. Quote them only with
    that sentence attached.
Both compute the same circuits, on the same geometry; only the flows
differ. The same circuits can be recomputed either way, by calling
again with or without preliminary_design.

YOU ARE NOT GIVEN THE PRESSURE DROPS, ON PURPOSE - except in the
preliminary mode above. Until the user has
confirmed on the page each circuit's type (supply, return, outdoor
air, exhaust) and its flows, the pressure drop is wrong - the tool
cannot know either. Never estimate, quote or compute one yourself,
not even roughly: say the pressure drops are on the page, once the
type and the flows are confirmed.

Every circuit is computed as a SUPPLY circuit until someone says
otherwise: the tool cannot tell supply from return. The flow rates do
not depend on it - a duct carries what its section allows either
way - but the tee coefficients and the design velocity do. If a
branch is a return, an intake or an exhaust, SAY SO and tell the user
how to set it in the 3D view: hovering the arrow of a circuit shows
its type, and each click on that label moves to the next one -
supply, return, outdoor air, exhaust. A click on the arrow itself
reverses the air direction, which is how the user says at which end
the terminal or the louvre sits when the duct has a constant section.

Say that each circuit was chosen BY LENGTH. A shorter path loaded
with dampers, bends or silencers can lose more pressure.

BEFORE THE LINK, SAY WHAT THE USER MUST CONFIRM ON THE PAGE - see
'A_CONFIRMER_PAR_L_UTILISATEUR', circuit by circuit: whether each
network is supply, return, outdoor air or exhaust (all are computed
as supply until the user says otherwise), and the flows (which are
estimates from the velocity, which were given). Never leave it out:
the figures mean nothing until both are confirmed.

END YOUR ANSWER WITH THE 3D LINK, on its own line, and urge the user
to open it - see 'A_DONNER_A_L_UTILISATEUR'. Name each circuit by
its unit, its colour and its type - several circuits share a
colour. The page is where the calculation is finished: the
user sets the flows (a click on the unit, or typed in the table),
the velocity, the air direction and the circuit type, deletes a
circuit from its tab - its colour goes with it -, adds one by
clicking a start and an end part, and downloads the workbook, one
editable sheet per circuit.

A FLOW THAT LOOKS WRONG IS AN ESTIMATE, NOT A DEFECT. When none was
given, flows come from the design velocity. If you point one out,
say in the same breath that the user sets it on the page or in the
workbook - see 'debits_et_reglages'.

THE USER'S CHOICES STAND. A circuit they deleted is not computed
again: it comes back under 'retires_par_l_utilisateur', and only they
can restore it, by tracing it on the page. A circuit they traced by
hand is never replaced. So after they have been on the page, call
this again before stating any figure - never answer from memory.
- `water_content_from_vessel`: DETERMINISTIC: the same inputs always give the same result — from
any AI, on any day. Figures come from the standard's tables and
formulas, never from a language model's estimate. Every step is
auditable.

Deduce the water content of an installation from the expansion vessel
already fitted.

WHAT THIS IS FOR. Refurbishment, and site visits with no drawings.
Sizing a new vessel, a new pump or a new generator needs the water
content, and on an existing installation nobody has it: the drawings
are lost, or never matched what was built. The vessel on the wall is
the one piece of evidence still standing, and it was chosen from that
very figure.

ASK THE OPERATOR FIRST. Whoever filled or refilled the system knows
the real figure — from the meter, the filling station, or the
maintenance log — and that figure beats any deduction. This tool is
what you use when nobody knows, or to check a number that looks
wrong. It gets the conversation moving; it does not close it.

HOW. The sizing calculation is run backwards: a trial water content is
fed to the EN 12828 sizing, the resulting vessel is compared with the
one on site, and the trial is adjusted until they match. The formulas
are never rewritten in reverse — the answer cannot contradict the
direct calculation, because it is the same code.

WHAT THE ANSWER IS WORTH. A vessel is picked from a catalogue range:
a 200 L unit covers everything needing between 141 and 200 L. The
result is therefore A RANGE, never a single figure. And an oversized
vessel — common — will overstate the content. Compare the range with
what you see on site; it does not replace looking.

It also assumes the vessel was sized correctly in the first place. If
it was not, the deduction inherits the mistake — which is itself
worth knowing: a range far from what the installation plainly holds
means the vessel is wrong, and that is a finding in its own right.

