Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • The theme-first mental model (no hex unless it carries process meaning)
  • write_objects mechanics on DisplaysList (document objects, read-before-write)
  • The build loop (write_objectsget_state → check errorListvisual checkpoint → fix → move on)
  • Binding syntax that hits every display
  • Spacing, typography, and minimum sizing tokens shared between Canvas and Dashboard
  • Symbol-writing rules (Wizard, Library, Solution prefixes)

...

ToolWhen
get_table_schema('DisplaysList')Once at start of session to confirm field names
list_elements('ThemeColors')Once to get the brush catalogue
list_elements('<ElementName>')Before using an element type you have not used this session
list_dynamics() / list_dynamics('<Type>')Before attaching a dynamic you have not used this session
get_objects('DisplaysList', names=['X'], detail='full')Before every modification to an existing display (document-object rule)
write_objects(table_type='DisplaysList', data=[...])After your plan is complete
get_state(target='designer')After every write, to check errorList
get_screenshot(target='display', name='X')At visual checkpoints during a Canvas build, or once at the end of a Dashboard build. See §3 for the cap.

Section 1 — Theme-first mental model

...

  1. PLAN — what am I adding/changing? What tags does it bind to?
  2. READget_objects(detail='full') if modifying an existing display
  3. WRITEwrite_objects(data=[...])
  4. COMPILE CHECKget_state(target='designer'), look at errorList
  5. FIX — if errorList non-empty, fix and go back to step 3
  6. VISUAL CHECKPOINT — see "What errorList covers, and what it doesn't" below
  7. DONE — move to next display or next task

...

If errorList is absent or empty, the display compiled clean.

Never use screenshots to self-validate

What errorList covers, and what it doesn't

errorList is ground truth for compile correctness: bindings resolve, required fields are present, the display will render without crashing. A clean errorList is necessary before you declare the display done.

errorList is blind to visual correctness. None of the following produce an error:

  • Two elements overlapping at the same Left/Top
  • A TextBlock whose LinkedValue clips because its rendered length exceeds Width
  • An element placed outside its intended zone but still inside the display
  • A pipe endpoint 15 px off the tank nozzle it was supposed to connect to
  • A RadialGauge with YMaxValue below the tag's engineering-range maximum (pegs at max forever)
  • Three 48 pt "hero" numbers on the same display, all screaming for attention
  • A Polygon with valid Points but Fill equal to the background (invisible)

All of those compile clean. All are operator-rejected.

Visual checkpoint — paradigm-specific

This step closes the gap errorList leaves open. The rules differ by paradigm because spatial correctness matters far more in Canvas than in Dashboard.

Canvas: spatial correctness is the whole point. Coordinate-based composition of pipes, vessels, zone layouts, and P&ID flow is the class of work where authoring blind gets it wrong the most. Take get_screenshot at authoring checkpoints:

  1. After zone scaffolding lands (background rectangles + zone titles) — verify the zones divide the canvas as planned.
  2. After main equipment is placed (symbols, vessels, pipes) — verify elements landed inside their zones and pipes connect where they should.
  3. Before declaring done — final sanity check of the composed display.

Hard cap: 3 screenshots per display per session. If three checkpoints did not resolve the visual problem, a fourth will not either — the problem is judgment, not pixels. Hand back to the user with a summary of what was built and what looks wrong; ask them to open Designer and guide the next move.

Dashboard: grid reflow is resolved at render time against a specific window size, and most Dashboard mistakes (wrong control choice for the cell purpose, missing Cell.HeaderLink, broken DataGrid → detail wiring) are visible in the structure, not the pixels. Take one get_screenshot at the end, before declaring done, to confirm cells populated and content did not collapse unexpectedly. If that one screenshot reveals a problem, fix and screenshot again; beyond the second screenshot, hand back to the user.

Not for iterative self-soothing. Do not take a screenshot after every write just to feel certain. The cost is real and the behavior encourages re-work spirals over clean planning. Screenshots go at checkpoints, not at every turn.

Write a one-paragraph summary when you declare done, regardless of paradigm: which zones or cells exist, what lives in each, which tags drive what. The summary is what the user reads before they look at the display themselves — and it forces you to notice gaps ("I reserved a zone for alarms but never put an AlarmViewer in it") that errorList cannotwrite_objects success IS the confirmation. The errorList check covers compile correctness. Screenshots are only for sharing visual context with the user — not for the AI to confirm its own work.

Section 4 — Binding syntax

...

// Silently invisible
{ "Type": "Polygon", "Left": 100, "Top": 100, "Width": 50, "Height": 50 }

//

...

Renders

...

correctly

...

{

...

"Type":

...

"Polygon",

...

"Left":

...

100,

...

"Top":

...

100,

...

"Width":

...

50,

...

"Height":

...

50,

...

"Points":

...

"25,0

...

50,50

...

0,50"

...

}


Polygon auto-closes (last point connects back to first). Polyline doesn't. For pipe runs use Gridline (constrains to horizontal/vertical segments — the P&ID convention).

...

Every symbol uses Type: "Symbol". Not Type: "Pump", not Type: "Valve". One element type, many SymbolName values.

{
  "Type": "Symbol",
  "SymbolName": "Wizard/PUMP",
  "Left": 400, "Top": 300,
  "Width": 80, "Height": 80,
  "SymbolLabels": [
    { "Type": "SymbolLabel", "Key": "State", "LabelName": "State", "LabelValue": "@Tag.Pump1/Running", "FieldType": "Expression" },
    { "Type": "SymbolLabel", "Key": "RPM",   "LabelName": "RPM",   "LabelValue": "@Tag.Pump1/Speed",   "FieldType": "Expression" }
  ]
}

The 5 Wizard symbols

The complete Wizard catalog is 5 symbols:

...

The Contents field format starts with CSharp\r\n or VBdotNet\r\n before the code. Full CodeBehind guidance lives in the Skill Scripts Expressions skill.

Section 10 — Common pitfalls

Full CodeBehind guidance lives in the Skill Scripts Expressions skill.

Section 10 — Common pitfalls

MistakeFix
Declaring done on empty errorList aloneerrorList covers compile correctness only. Run the paradigm-specific visual checkpoint in §3 before declaring done.
Taking screenshots after every writeCheckpoints, not reassurance. Canvas: up to 3 per display. Dashboard: one at end.
MistakeFix
Hardcoding hex without thinking about theme switchingUse *Theme properties; reserve hex for process-meaning
Polygon / Gridline without PointsAlways include Points — min 3 for Polygon, 2 for Polyline/Gridline
Using ObjectName instead of NameField is always Name
Using DisplaysDraw as table_typeVisual editor UI, not a writable table. Use DisplaysList
Omitting PanelTypeRequired — "Canvas" or "Dashboard"
Wrapping the envelope in JsonFormatProperties go at top level, no wrapper
Partial write on an existing displayAlways read-modify-write the complete document
Using @Label.X in a display-element binding@Label. is for symbol internals only — use @Tag.
Setting colors without clearing themeSet value AND clear theme: {Fill: '#FF3498DB', FillTheme: ''}
Relying on a static element/symbol listAlways call list_elements() / list_dynamics() to get the authoritative catalog at runtime

...

# Session startup
get_table_schema('DisplaysList')
list_elements('ThemeColors')

# 



Before

...

first

...

use

...

of

...

a

...

type

...

this

...

session

...


list_elements('<ElementName>')

...

list_dynamics('<DynamicName>')

...


Read-modify-write

...

an

...

existing

...

display

...


get_objects('DisplaysList',

...

names=['X'],

...

detail='full')

...

write_objects(table_type='DisplaysList',

...

data=[...])

...

get_state(target='designer')

...

#

...

verify

...

errorList

...

empty


Visual checkpoint (§3)


Canvas: up to 3 per display (after zones, after equipment, before done)


Dashboard: one at end


get_screenshot(target='display', name='X')


...

Display envelope template:

{
  "Name": "MyDisplay",
  "PanelType": "Canvas",
  "DisplayMode": "Page",
  "Navigate": "true",
  "Size": "1600 x 900",
  "OnResize": "StretchFill",
  "Width": 1600,
  "Height": 900,
  "Background": "theme:PageBackground",
  "Elements": []
}

Next skills

...