Canvas
The canvas is the picture of your workshop: each record is a node, and each relationship is a line between two nodes. There are two kinds of canvas:
- the workspace canvas shows the workshop's own records: simulators, data connections, surfaces and the rest;
- each surface canvas shows what is wired to that one surface: its data connections and databases, the warm queries that read them, and its workbenches.
Every node is placed by whoever made it, a person dragging it or an AI giving it a position. No code places a node for you. A node with no position is drawn at the top left, where it can cover another node.
Where a node's position lives
A position is { X, Y }, the node's top left corner on the canvas.
| Canvas | Where the position is stored | In a proposal |
|---|---|---|
| Workspace | the record's Metadata.Position | Proposed.Metadata.Position on the node's own proposal |
| Surface | the surface's own entry for that node, Surfaces.<surface>.<collection>.<lookup>.Metadata.Position (for example a warm query's entry under the surface's WarmQueries); with none there, the record's Metadata.Position | the same path inside the surface's proposal, under Proposed |
So one data connection can sit in one place on the workspace canvas and somewhere else on each surface it feeds.
get_workspace returns all of these: every record's Metadata.Position, each surface's entries,
and every pending proposal's Proposed.Metadata.Position under ProposalGroups.
How big a node is
A node is drawn 250 wide and 56 tall from its position. Two nodes whose boxes overlap cover each other, even when their positions are a few units apart.
The layout convention
One rule keeps every canvas readable, whoever adds to it:
- Lay the canvas out left to right, in the direction data flows. On the workspace canvas: a simulator, then the data connection it feeds, then the surface. On a surface canvas: a data connection or database, then the warm query that reads it, then a workbench.
- A column is 300 on X and a row is 120 on Y.
- Put a new node one column right of what feeds it, in the first row that is clear of every node and every pending proposal. A node nothing feeds starts a new row below the others.
- Space several new nodes one row apart.
- Never copy another node's position.
A worked example
The workspace canvas holds a data connection boiler-1 at (600, 180) and a surface line-1 at
(900, 180). You add a simulator that feeds boiler-1. Data flows from the simulator into the
connection, so the simulator goes one column left of it: (300, 180). If that spot were taken,
the next row down, (300, 300), would be next.
Layout warnings
When an AI checks a proposal (manage_proposals with checkOnly: true), the same check every
proposal door runs also looks at the layout, with every pending proposal shown. It warns about:
LAYOUT_OVERLAP: two nodes whose boxes overlap;LAYOUT_LINES_CROSS: two lines that cross (lines that share a node never count);LAYOUT_NO_POSITION: a node with no position.
Each warning names the nodes, the field to write, and a free spot by the convention that overlaps no node and crosses no line. A warning never blocks a proposal and never moves anything: the free spot is a suggestion, and the place is still the agent's or the person's to choose.
Tidying the canvas
When nodes near what an AI is working on overlap or have no position, the AI may propose new positions for them. It is an ordinary update (the same kind and lookup, with only the position changed), filed in its own proposal group named Tidy the canvas, and a person accepts it like any other proposal. A move is never folded into a group about something else.
Related
- Proposals: how an AI's change reaches the canvas.
- Working with the tools: what an AI reads before it proposes a node.