$ cat workspace-template.yaml
Ontology Node Test Bench 3
// A test bench that instantiates EVERY ontology node (search x3 for entity/schema/hybrid, traverse x2, entity-360, kb-search -> from-documents bridge, merge RRF, and a self-cleaning create/set/link/delete write chain). The instruction drives the agent to configure, run, and evaluate each node against pass/fail criteria and produce a consolidated report. Use to smoke-test the whole ontology stack after a deploy.
// Canvas Preview
// Instruction
Ontology Node Test Bench
Overview
This workspace instantiates EVERY ontology node so you can exercise each one against the LIVE governed graph and judge its result. Some nodes appear MULTIPLE times to cover their variants (Search is here three times — entity, schema, hybrid modes; Traverse twice — different direction/depth). You are the test driver: configure each node, run it, read its output, and mark it PASS / WARN / FAIL against the criteria below, then present one consolidated report. Most of the bench is READ-ONLY; the four write nodes at the bottom run only if the user opts in, and they clean up after themselves.
The nodes (and what each proves)
- Search · entity mode (
ontology-search, mode=entity) — name-first lexical/kNN search. Outputresults+count. - Search · schema mode (mode=schema) — matches the query to relationship/theme TYPES, returns their instances with
matchedVia. Outputresults. - Search · hybrid mode (mode=hybrid) — both arms, RRF-fused.
- Entity 360 (
ontology-entity-360) — full profile of ONE object id. InputsobjectId,maxNamesPerType. Outputsentity,summaryText,linkCounts. - Traverse · both, depth 1 and Traverse · outgoing, depth 2 (
ontology-traverse) — walk links from an object. InputsobjectId,linkType,direction,depth. Outputresult. - KB Semantic Search (
kb-semantic-search) — vector search over document chunks. OutputdocumentIds(WIRED into From Documents),chunkTexts. - From Documents (bridge) (
ontology-from-documents) — documents → the ontology objects appearing in them.documentIdsis wired from KB Semantic Search. Outputsentities,links,truncated. - Merge Ranked Lists (RRF) (
merge-ranked-lists) — fuseslistA(wired from Search·entityresults) andlistB(wired from From Documentsentities). Outputsitems,itemsText,topId. - Create Object / Set Property / Create Link / Delete (
ontology-create-object/-set-property/-create-link/-delete) — the write path. Run as a self-cleaning round-trip; Delete removes what Create made.
Phase 1 — Configure
- Make ONE
requestUserDecisionbundling: (a) an entity NAME that exists in the graph to probe (default "MAECI"); (b) a relationship/theme question (default "chi ha promulgato le leggi | who promulgated the law"); (c) run the WRITE nodes too? (default No — read-only). Keep a free-text box last. Do not prompt again after this. - Use
nodeFinderto get the fresh ids of ALL nodes — the template-preview ids are stale after cloning. - Apply with ONE
batchUpsertNodes: setqueryon Search · entity mode to the entity NAME; setqueryon Search · schema mode, Search · hybrid mode, and KB Semantic Search to the relationship/theme question. Replace every{{query}}placeholder. Leave id/type inputs (Entity 360objectId, TraverseobjectId/linkType, the write nodes) empty for now — you fill them from earlier outputs in later phases.
Phase 2 — Run the READ nodes and evaluate
Run each with nodeExecutor, read with getNodeOutput, and record a verdict.
A. The three Search variants (run all three):
- entity — PASS if
count > 0and the top result is a NAMED entity matching the probe; WARN if empty; FAIL on error. Keep the top result'sidandtypeIdfor later. - schema — PASS if
resultsis non-empty AND every result carriesmatchedVia.mode = "schema". Then inspect the TOP result'smatchedVia.typeNameandtypeScore: atypeScorearound 0.7–0.9 is a healthy semantic (kNN) match; atypeScorearound 7 means a LEXICAL-noise type won (a known regression) — mark WARN and name the offending type. FAIL if no result carriesmatchedVia.mode = "schema". - hybrid — PASS if
count > 0.
B. Entity 360 + Traverse (need an id from Search·entity):
- Set Entity 360
objectIdto the top entity id from Search·entity (batchUpsertNodes), run it. PASS ifentityis populated andlinkCountslists link types. Note a link-type NAME fromlinkCounts(or fromentity's links) — you need it for Traverse. - Set both Traverse nodes'
objectIdto the same id andlinkTypeto the link-type name you found; run both. PASS ifresultreturns (endpoints may be empty — an isolated entity is still a valid, non-error result; say so). Compare depth-1 vs depth-2 reach.
C. Bridge pipeline (KB → From Documents → Merge — wired, so run downstream and upstream resolves):
- Run KB Semantic Search. PASS if
documentIdsis non-empty; WARN if empty (nothing in the KB matched — note it). - Run From Documents. PASS if
entitiesis non-empty; WARN if empty (the matched documents mention no accessible objects — still valid). Notetruncated. - Run Merge Ranked Lists. PASS if
items/itemsTextare populated andtopIdis set. This proves the RRF fusion of the lexical (listA) and bridge (listB) arms.
Phase 3 — Write nodes (ONLY if the user opted in)
Skip this whole phase if writes were declined; mark the four write nodes SKIPPED. This chain is SELF-CONTAINED and SAFE BY CONSTRUCTION: Create Object's id output is WIRED into Set Property targetId, Create Link sourceObjectId/targetObjectId, and Delete targetId. A wired input overrides any value on the node, so these nodes ALWAYS act on the throwaway object created here and can NEVER touch a real entity. HARD RULE: never put an object id from a search / entity / traverse / merge node onto ANY write node.
- Create Object — set
objectTypeIdto atypeIdyou kept from Search-entity's results. LeaveidentityKeyat its fixed valueontology-testbench-throwaway(this is what keeps the throwaway distinct from every real entity) andpropertiesat the default. Run. It returns the throwawayid. PASS if anidcomes back. - Set Property — leave
targetIdEMPTY (wired from Create Object); set onlyproperties. Run. PASS if it returns the throwaway id, NOT a real entity id. - Create Link — leave
sourceObjectIdandtargetObjectIdEMPTY (both wired from Create Object, so this is a self-link on the throwaway); setlinkTypeIdto a real link-type id (from Entity 360 if available, else mark SKIP). Run. PASS if it returns anid. - Delete — leave
targetIdEMPTY (wired from Create Object). Run this EVEN IF an earlier write step failed (cleanup). PASS if it returnsdeleted_atfor the throwaway. Deleting the throwaway cascades its self-link, leaving the graph exactly as found. NEVER delete anything else.
Phase 4 — Report
Run verification, then present ONE markdown table: a row per node instance (name, PASS/WARN/FAIL/SKIP, and the one-line reason/observation). Lead with an overall verdict (FAIL if any FAIL, else WARN if any WARN, else PASS). Call out specifically: any schema result that matched a lexical-noise type (high typeScore), any empty bridge/KB result (with the likely cause), and — if writes ran — confirm the created object was deleted. In followUp, offer to re-run with a different probe query, or to run the write nodes (they self-clean). No write confirmation is needed beyond the Phase 1 opt-in, since Delete always tears down what Create made.
// Dependencies
1from input import OntologySearch2from process import OntologyEntity3603from process import OntologyTraverse4from input import KBSemanticSearch5from process import OntologyFromDocuments6from process import MergeRankedLists7from process import OntologyCreateObject8from process import OntologySetProperty9from process import OntologyCreateLink10from output import OntologyDelete$ git log --oneline