fix(task-16): hints only name ports pid_line_draw accepts; signal_unknown is judged as a signal line
Two review findings on the P&ID critique focuses. The graph's own `nearest` is computed over every port in its grid, including the `p1..pn` ports it invents on a promoted unknown_block, so a free end near a sheet frame was hinted to connect to the frame — a call `pid_line_draw` refuses, since the frame carries no ACADMCP_PID payload. Every dangling row is now re-hinted over connectable ports only (catalogue / XDATA nodes, declared ports), so every hint is executable. `signal_unknown` — the class the reader assigns to a signal-layer line whose exact class it cannot tell — was skipped by the incompatibility check because it is not in the drawable class table. Its kind is still signal, so a signal-layer line ending on a process port is now an error as spec §11.1 requires; only an unclassified line is skipped. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
This commit is contained in:
co-authored by
Claude Opus 5
parent
3c4fbf6c42
commit
6aded6bbf0
@@ -375,3 +375,57 @@ def test_preflight_flags_a_pid_intent_on_the_wrong_layer_set():
|
||||
assert "LAYER_SET_INTENT_MISMATCH" not in [c.code for c in ok.conflicts]
|
||||
assert pid_plan_warnings("Bearing housing", "mech") == []
|
||||
assert pid_plan_warnings("piping and instrumentation diagram", "mech")
|
||||
|
||||
|
||||
async def test_a_free_end_near_an_invented_frame_port_gets_no_executable_hint(backend):
|
||||
"""The graph's own ``nearest`` is computed over every port in its grid,
|
||||
including the ``p1`` it invents on a promoted frame. A hint that names
|
||||
that port is a hint ``pid_line_draw`` refuses (the frame carries no
|
||||
ACADMCP_PID payload). Every dangling row — not only the ends that touch an
|
||||
unknown block — must be re-hinted over connectable ports."""
|
||||
frame, pump = await _frame_and_pump(backend)
|
||||
await draw_line(backend, {"handle": pump["handle"], "port": "discharge"}, {"x": 420, "y": 106})
|
||||
free = await backend.entity_create_line(300, 108, 417, 108, layer="PROCESS-PIPING-MAIN")
|
||||
|
||||
graph = await build_graph(backend, include_foreign=True)
|
||||
row = next(d for d in graph["dangling"] if d["edge"] == free.handle and d["end"] == "to")
|
||||
assert row["nearest"] and row["nearest"]["node"] == frame, "the graph itself still hints at p1"
|
||||
|
||||
issues = await backend.drawing_critique(["pid_dangling_line"])
|
||||
to_row = next(i for i in issues if i.handles == [free.handle] and i.detail["end"] == "to")
|
||||
assert to_row.detail["nearest"] is None
|
||||
assert "no port within reach" in to_row.detail["hint"]
|
||||
for issue in issues:
|
||||
nearest = issue.detail.get("nearest")
|
||||
if nearest:
|
||||
node = next(n for n in graph["nodes"] if n["id"] == nearest["node"])
|
||||
assert node["source"] in ("catalog", "xdata")
|
||||
assert node["ports"][nearest["port"]]["inferred"] is False
|
||||
|
||||
|
||||
async def test_a_signal_layer_line_of_unknown_class_into_a_process_port_is_incompatible(backend):
|
||||
"""A line on INSTRUMENT-LINE-SIGNAL with a continuous linetype reads as
|
||||
``signal_unknown``: the reader cannot tell pneumatic from data, but it is
|
||||
a signal line, and spec §11.1's rule (a signal-class edge ending on a
|
||||
process port) applies to it. Skipping it would let ``drawing_finalize``
|
||||
pass the connection."""
|
||||
from engineering.layers import apply_layer_set
|
||||
|
||||
await apply_layer_set(backend, "pid")
|
||||
pump = await place_symbol(backend, "centrifugal_pump", 100, 100, tag="P-101")
|
||||
out = pump["ports"]["discharge"]
|
||||
line = await backend.entity_create_line(
|
||||
out["x"], out["y"], out["x"] + 40, out["y"] + 40, layer="INSTRUMENT-LINE-SIGNAL"
|
||||
)
|
||||
await backend.entity_set_properties(line.handle, linetype="Continuous")
|
||||
graph = await build_graph(backend)
|
||||
edge = next(e for e in graph["edges"] if e["id"] == line.handle)
|
||||
assert edge["line_class"] == "signal_unknown" and edge["from"] == {
|
||||
"node": pump["handle"],
|
||||
"port": "discharge",
|
||||
}
|
||||
|
||||
issues = await backend.drawing_critique(["pid_incompatible_connection"])
|
||||
assert len(issues) == 1 and issues[0].severity == "error"
|
||||
assert issues[0].detail["expected"] == "signal" and issues[0].detail["actual"] == "process"
|
||||
assert issues[0].detail["line_class"] == "signal_unknown"
|
||||
|
||||
Reference in New Issue
Block a user