Skip to content

Instantly share code, notes, and snippets.

@kenwebb
Last active August 11, 2025 12:30
Show Gist options
  • Save kenwebb/aa12715ee232ed94c4e3c8237753c895 to your computer and use it in GitHub Desktop.
Save kenwebb/aa12715ee232ed94c4e3c8237753c895 to your computer and use it in GitHub Desktop.
AI, Graphviz, Xholon
<?xml version="1.0" encoding="UTF-8"?>
<!--Xholon Workbook http://www.primordion.com/Xholon/gwt/ MIT License, Copyright (C) Ken Webb, Mon Aug 11 2025 08:29:31 GMT-0400 (Eastern Daylight Time)-->
<XholonWorkbook>
<Notes><![CDATA[
Xholon
------
Title: AI, Graphviz, Xholon
Description:
Url: http://www.primordion.com/Xholon/gwt/
InternalName: aa12715ee232ed94c4e3c8237753c895
Keywords:
My Notes
--------
2025 August 10
TODO done
- figure out how to do connections between nodes
- ex: "CEO" -> "CTO"; same level siblings
- ex: "Board of Directors" -> "CEO" in different levels
- every graphviz node must have a unique roleName
- a graphviz parser will need to maintain a searchable JSO structure, containing:
- roleName of the node
- xpath path from root, or reference to the actual generated node
- ex: "Board of Directors": "ancestor::Digraph/Node[@roleName='Board of Directors']"
### Windsurf
- see: rip:~/A2025_August__/workbook01$
- added $wnd in front of xh.root()
- added this. in front of println
- runtime errors:
Warning: Could not find nodes for relationship Quebec -> Newfoundland
Warning: Could not find nodes for relationship Ontario -> Quebec
Warning: Could not find nodes for relationship Hello -> World
http://127.0.0.1:8080/Xholon.html?app=AI%2C+Graphviz%2C+Xholon&src=lstr&gui=clsc&jslib=graphviz2xholon
### References
(1) https://gist.github.com/kenwebb/7c98bbda3541598f5aca9c128f856689
has some useful links
]]></Notes>
<markdown><![CDATA[
[Duck AI chat, using Haiku model](https://duckduckgo.com/?q=DuckDuckGo+AI+Chat&ia=chat&duckai=1)
Write an example of a nested graphviz diagram.
Very good. Add a directed arrow from "Software Team" to "Hardware Team", while keeping the rest of the structure the same.
``` graphviz
digraph NestedExample {
// Define graph attributes
rankdir=TB;
// Outer cluster
subgraph cluster_company {
label="Company Structure";
style=filled;
color=lightgrey;
// Department cluster
subgraph cluster_engineering {
label="Engineering Department";
style=filled;
color=lightblue;
// Engineering team nodes
"Software Team" [shape=box];
"Hardware Team" [shape=box];
// New connection between teams
"Software Team" -> "Hardware Team";
}
// Management nodes
"CEO" [shape=diamond];
"CTO" [shape=diamond];
// Connections
"CEO" -> "CTO";
"CTO" -> "Software Team";
"CTO" -> "Hardware Team";
}
// External connections
"Board of Directors" [shape=oval];
"Board of Directors" -> "CEO";
}
```
]]></markdown>
<_-.XholonClass>
<GraphvizSystem/>
<Node>
<Digraph/>
<Cluster/>
</Node>
</_-.XholonClass>
<xholonClassDetails>
<Avatar><Color>red</Color></Avatar>
</xholonClassDetails>
<GraphvizSystem>
<!-- I manually created a Xholon representation of the AI-generated graphviz structure -->
<Digraph roleName="NestedExample">
<!-- cluster_company -->
<Cluster roleName="Company Structure">
<Color>lightgrey</Color>
<!-- cluster_engineering -->
<Cluster roleName="Engineering Department">
<Color>lightblue</Color>
<Node roleName="Software Team"><Script>const me=this.parent();me["Hardware Team"]=me.next();</Script></Node>
<Node roleName="Hardware Team"/>
</Cluster>
<Node roleName="CEO"><Script>const me=this.parent();me.CTO=me.next();</Script></Node>
<Node roleName="CTO"><Script>const me=this.parent();me["Software Team"]=me.xpath("../Cluster/Node[1]");;me["Hardware Team"]=me.xpath("../Cluster/Node[2]");</Script></Node>
</Cluster>
<Node roleName="Board of Directors">
<Script>const me=this.parent();me.CEO=me.xpath("../Cluster/Node[@roleName='CEO']");</Script>
</Node>
</Digraph>
<!-- Windsurf experiment result -->
<Digraph>
<!-- Top-level nodes -->
<Node roleName="Hello"/>
<Node roleName="World"/>
<Node roleName="Ontario"/>
<Node roleName="Quebec"/>
<Node roleName="Newfoundland"/>
<!-- Relationships -->
<!-- Relationship: Hello -> World -->
<!-- KSW version; Windsurf code was incorrect, but was a good starting point -->
<Script><![CDATA[
$wnd.xh.gviz2xh = (from, to) => {
const farr = $wnd.xh.root().subtreeAsArray();
const tarr = $wnd.xh.root().subtreeAsArray();
let i = 0;
let fnode = null;
while (i < farr.length) {
if (farr[i].role() === from) {fnode = farr[i]; break;}
i++;
}
let j = 0;
let tnode = null;
while (j < tarr.length) {
if (tarr[j].role() === to) {tnode = tarr[j]; break;}
j++;
}
// Create a relationship if both nodes are found
if (fnode != null && tnode != null) {
fnode[tnode.role()] = tnode;
} else {
this.println(`Warning: Could not find nodes for relationship ${from} -> ${to}`);
console.log(`Warning: Could not find nodes for relationship ${from} -> ${to}`);
}
}
$wnd.xh.gviz2xh("Hello","World");
$wnd.xh.gviz2xh("Ontario","Quebec");
$wnd.xh.gviz2xh("Quebec","Newfoundland");
]]></Script>
</Digraph>
</GraphvizSystem>
<SvgClient><Attribute_String roleName="svgUri"><![CDATA[data:image/svg+xml,
<svg width="100" height="50" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Block</title>
<rect id="GraphvizSystem/Digraph" fill="#98FB98" height="50" width="50" x="25" y="0"/>
<g>
<title>Height</title>
<rect id="GraphvizSystem/Digraph/Cluster" fill="#6AB06A" height="50" width="10" x="80" y="0"/>
</g>
</g>
</svg>
]]></Attribute_String><Attribute_String roleName="setup">${MODELNAME_DEFAULT},${SVGURI_DEFAULT}</Attribute_String></SvgClient>
</XholonWorkbook>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment