9.4 KiB
Cloverleaf Operations — v3 Native Capability Reference
Larry-Anywhere v3 is self-contained. It does not invoke v1 bash scripts (tbn, hlq, mr, mp, mg, awkcut, each_site, etc.) and it does not invoke v2 cloverleaf-tools.pyz. Those layers can be present on a host; v3 ignores them.
Two kinds of capability:
- Native tools — implemented in pure bash+awk under
$LARRY_HOME/lib/, callable as first-class Anthropic-style tools (nobash_execY/N). - Cloverleaf product binaries — the binaries shipped with Cloverleaf itself (
$HCIROOT/bin/,$HCIROOT/server/bin/,tclsh+ Cloverleaf TCL libraries). These ARE part of Cloverleaf, not v1/v2. v3 invokes them directly viabash_exec(Y/N) when an operation requires the engine.
What Larry has natively (Anthropic tools)
NetConfig analysis — read
| tool | use for |
|---|---|
nc_list_protocols(netconfig) |
"what threads are in this site?" — one name per line |
nc_list_processes(netconfig) |
"what processes are defined?" |
nc_protocol_block(netconfig, name) |
"show me the full definition of thread X" |
nc_protocol_field(netconfig, name, field) |
top-level field (PROCESSNAME, OBWORKASIB, OUTBOUNDONLY, GROUPS, ENCODING, ICLSERVERPORT, AUTOSTART, HOSTDOWN) |
nc_protocol_nested(netconfig, name, path) |
nested field via dotted path. Use this for HOST/PORT/TYPE/ISSERVER — those live in the inner PROTOCOL{} block. e.g. path=PROTOCOL.PORT |
nc_protocol_summary(netconfig, [filter]) |
one-line TSV per protocol with direction, port, host, type — your default "lay of the land" call |
nc_destinations(netconfig, name) |
"what does this thread route to?" — unique DEST list from DATAXLATE. ONE HOP only — for the full multi-hop chain use nc_paths. |
nc_sources(netconfig, name) |
"what routes INTO this thread?" — unique source list. ONE HOP only — for the full chain use nc_paths. |
nc_paths(thread, site, [all], [site_only]) |
"trace the FULL route chain / what feeds X / the whole path / downstream + upstream" — deterministic DFS path enumerator, output SITE THREAD HOPS PATH. Intra-site hops follow DATAXLATE DEST; cross-site links are via named destination blocks (a DEST naming a destination block resolves to its { SITE } { THREAD }; the PORT corroborates). The whole route graph is parsed once into memory and walked with O(1) lookups. For --up, THREAD = feeder ROOT and the queried thread is the terminus. Use this instead of repeated nc_destinations/nc_sources, grep, or read_file for ANY path / chain / route-tracing question. |
nc_xlate_refs(netconfig, [name]) |
"what .xlt files are referenced?" — all or scoped to one protocol |
nc_find_inbound(netconfig, mode, format) |
"which threads are inbound?" — modes: tcp-listen (real upstream-client listeners, ISSERVER=1), icl-or-file (OBWORKASIB=1 internal mux/file inbounds), all. formats: tsv, jsonl, table |
nc_document(thread | name, [site], [out]) |
"document this interface / system end-to-end" — emits the Legacy "ADT Messages" markdown template (Title, Description, Message Flow table Platform|Action|Description|From|To, per-delivery breakdown) for ONE interface (thread, e.g. ADTto_CodaMetrix) or a whole SYSTEM (name pattern, e.g. codametrix → one section per matching delivery thread across sites). Deterministic, pure bash, API-FREE (runs on API-blocked boxes). ★ For every referenced UPOC proc it surfaces the proc's comments, HL7 fields, matched event codes, table lookups, and disposition into the Description, and includes the raw proc TCL in a ## Referenced proc source appendix. When you get this output WITH the API, polish those surfaced UPOC bits into smooth filter prose in the Description — do NOT invent facts, just smooth what's surfaced. On an API-blocked host the deterministic bits + appendix ARE the deliverable (no "summarize by hand" marker). |
NetConfig modification — generate, then write via write_file (Y/N gated)
| tool | use for |
|---|---|
nc_make_jump(netconfig, inbound, new_host, jump_port, [process_old], [process_new], [encoding]) |
Generate the jump threads for cross-env data replay (tag = the inbound thread name). Emits THREE threads + one route-add: linux_<tag>_out (OLD-side outbound tcpip-client, same process as the original inbound), windows_<tag>_in (NEW-side server_jump inbound tcpip-server listening on jump_port), windows_<tag>_out (NEW-side server_jump outbound that re-injects into NEW's existing inbound), AND the route-add snippet to splice into the OLD inbound's DATAXLATE. Generation only — does not modify any file. Larry uses write_file to actually persist, which goes through Y/N. |
When Larry needs to add the OLD-side jump block to an existing NetConfig, the pattern is:
nc_make_jump(...)→ captures full textnc_protocol_block(netconfig, inbound)→ finds the inbound's existing block + line rangeread_file(netconfig)→ loads the whole file- Splice (in Larry's head): insert new block + route-add into the right spots
write_file(netconfig, new_content)→ Y/N preview shows the unified diff
What Larry invokes from Cloverleaf product binaries (via bash_exec, Y/N)
These are shipped with Cloverleaf. v3 invokes them directly — no v1 wrapper between.
| operation | binary or command |
|---|---|
| dump a smat database to text | $HCIROOT/bin/hcidbdump <smat_file> or the equivalent that ships with this Cloverleaf version |
| start/stop/restart an engine site | $HCIROOT/bin/hcienginestop, hcienginerun, hcienginerestart (already wrappers — read them once with read_file to see what they actually call) |
| run a TCL test/route | tclsh with $HCIROOT/tcl/lib/cloverleaf/... libraries on the auto-path. The msi* family (msiAttach, msiGetStatSample, etc.) is the Cloverleaf TCL API for smat/route access. |
| engine connection status | hciconndump or via TCL msi* calls |
| check the netconfig is loadable | Use tclsh to source it; engine will report parse errors |
When Larry doesn't know which binary fits an operation, the protocol is:
list_dir("$HCIROOT/bin")andlist_dir("$HCIROOT/server/bin")to enumerate.read_fileon any wrapper script that looks relevant.- Propose the exact
bash_execcommand to Bryan with a# why:comment.
NetConfig structural cheat-sheet
A site's NetConfig is TCL-style nested blocks. Top-level:
process <name> { ... }— a process container (usually 5–15 per site).protocol <name> { ... }— a thread (the operational unit). Each protocol has:- Top-level fields:
PROCESSNAME,OUTBOUNDONLY,OBWORKASIB,GROUPS,ENCODING,ICLSERVERPORT,AUTOSTART,HOSTDOWN,KEEPMSGONDISK, etc. - Inner
PROTOCOL { ... }block:TYPE(tcpip / pdl-tcpip / file),HOST,PORT,ISSERVER(0=client, 1=listener),LOCAL_IP,MLP_MODE, etc. DATAXLATE { ... }block: the routing rules. Each route is{ TRXID <regex> } { WILDCARD ON } { ROUTE_DETAILS { { DEST <thread> } { XLATE <.xlt> } { PROCS ... } { TYPE xlate|raw|generate } } }.RECVCONTROL,SAVECONTROL,TPS_INBOUND,TPS_OUTBOUND— proc bindings.
- Top-level fields:
Direction inference (canonical)
Use nc_find_inbound rather than rolling this yourself, but for reference:
| if … | direction |
|---|---|
PROTOCOL.ISSERVER == 1 |
inbound-tcp-listen — accepts upstream client TCP connections (e.g. listens for Epic). This is what Bryan means by "fed directly by upstream client systems." |
OBWORKASIB == 1 (and ISSERVER != 1) |
inbound-icl-or-file — receives via Cloverleaf inter-cloverleaf link (ICLSERVERPORT is set) or file drop. Usually TYPE=file. |
OUTBOUNDONLY == 1 |
outbound — TCP client pushing data to an external system. HOST and PORT give the target. |
| none of the above | bidirectional / undefined — rare; investigate. |
The jump-thread pattern (Example 1)
For each inbound thread T_in on the OLD env, you want:
- On OLD — modify NetConfig:
- Add a new outbound protocol
linux_<T_in>_out(tcpip-client, points at the new linux host:jump_port). - Add a route to
T_in's DATAXLATE block routing to that new outbound (TRXID.*, type raw, no xlate).
- Add a new outbound protocol
- On NEW — modify the
server_jumpsite's NetConfig:- Add a new inbound protocol
windows_<T_in>_in(tcpip-server listening on the jump_port, OBWORKASIB=1). - Add a new outbound protocol
windows_<T_in>_out(re-injects into NEW's existing inbound on 127.0.0.1:orig_port). windows_<T_in>_in's DATAXLATE has one route: TRXID.*→ DESTwindows_<T_in>_out, type raw, no xlate.
- Add a new inbound protocol
Net result: data hitting T_in on OLD also flows to NEW via TCP, lands in windows_<T_in>_in, is forwarded by windows_<T_in>_out into NEW's existing T_in, and follows NEW's normal downstream routing — letting Bryan validate the cloned environment with live OLD data. (The tag in each generated name is the OLD inbound thread name.)
Use nc_make_jump for the generation. Use write_file (Y/N) for the persistence.
What this doc replaces
This replaces the earlier v0.2 cheat-sheet that listed v1 commands like tbn, tbp, hlq, mr, mp, mg, hl, etc. v3 doesn't call those. When a user asks something like "find ADT threads," Larry uses nc_find_inbound or nc_protocol_summary --filter ADT, not tbn ADT. The end-user value is the same; the implementation is owned by v3.