cloverleaf-larry/agents/cloverleaf-cheatsheet.md

100 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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:
1. **Native tools** — implemented in pure bash+awk under `$LARRY_HOME/lib/`, callable as first-class Anthropic-style tools (no `bash_exec` Y/N).
2. **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 via `bash_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:
1. `nc_make_jump(...)` → captures full text
2. `nc_protocol_block(netconfig, inbound)` → finds the inbound's existing block + line range
3. `read_file(netconfig)` → loads the whole file
4. Splice (in Larry's head): insert new block + route-add into the right spots
5. `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:
1. `list_dir("$HCIROOT/bin")` and `list_dir("$HCIROOT/server/bin")` to enumerate.
2. `read_file` on any wrapper script that looks relevant.
3. Propose the exact `bash_exec` command 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 515 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.
## 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:
1. **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).
2. **On NEW** — modify the `server_jump` site'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 `.*` → DEST `windows_<T_in>_out`, type raw, no xlate.
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.