v0.8.28: expose 5 lib-only tools + fix nc-engine arg-parsing crash
Wires nc_status, nc_engine, nc_xlate, nc_smat_diff, nc_tclgen as first-class LLM tools (all 4 surfaces). nc_engine unlocks TPS testing (hcitps) + the route-test driver. Fixes a real nc-engine.sh bug surfaced by the exposure: the dispatcher treated every --flag as taking a value (--dry-run ate the next token) and a set -u leak from journal.sh crashed start/stop/bounce on bash 3.2; fixed with set +u + a multi-case parser (no over-shift on bare trailing flags). Corrects stale CHANGELOG + nc_engine schema text that misstated the bug as live. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
5214d87a04
commit
d58e4e0ec8
48
CHANGELOG.md
48
CHANGELOG.md
@ -4,6 +4,54 @@ All notable changes to `cloverleaf-larry` / `larry-anywhere` are recorded here.
|
|||||||
Versioning is loose-semver; bumps trigger the in-process self-update on every
|
Versioning is loose-semver; bumps trigger the in-process self-update on every
|
||||||
running client via `LARRY_BASE_URL` + `MANIFEST`.
|
running client via `LARRY_BASE_URL` + `MANIFEST`.
|
||||||
|
|
||||||
|
## v0.8.28 — 2026-05-28
|
||||||
|
|
||||||
|
**★ EXPOSE 5 lib-only tools as first-class LLM tools.** A roadmap audit found
|
||||||
|
~7 working `lib/*.sh` scripts that ran from the shell (`larry tools <name>`) but
|
||||||
|
were NOT wired into larry.sh's LLM `TOOLS_JSON`. This pass exposes the
|
||||||
|
READ/INSPECT/TEST ones (the config-mutating `nc-table` / `nc-create-thread` are
|
||||||
|
a separate next pass). Each tool now has all four larry.sh surfaces —
|
||||||
|
manual-tools registry, `tool_<name>` wrapper, `execute_tool` dispatch case, and
|
||||||
|
the `TOOLS_JSON` LLM spec — mirroring the v0.8.27 `nc_revisions` pattern. The
|
||||||
|
LLM tool count goes 38 → 43.
|
||||||
|
|
||||||
|
- **`nc_status`** ← `nc-status.sh` — engine RUNTIME status (sites/threads/
|
||||||
|
not-up/connections/queued/raw + `--site`/`--filter`/`--format`). READ-ONLY;
|
||||||
|
needs a live engine for real numbers, degrades gracefully on a config-only
|
||||||
|
host (sites → `config-present`, threads → reports the missing tstat binary,
|
||||||
|
no crash).
|
||||||
|
- **`nc_engine`** ← `nc-engine.sh` — engine process control + test drivers
|
||||||
|
(stop/start/bounce/restart/status + route-test/testxlate/tpstest/resend-ib/
|
||||||
|
resend-ob). State changes run only on a live box and are journaled; `status`
|
||||||
|
and the test drivers need a live engine. Unlocks the TPS-test (`tpstest`,
|
||||||
|
wraps `hcitps`) and route-test driver the regression tool needs.
|
||||||
|
- **`nc_xlate`** ← `nc-xlate.sh` — READ-ONLY xlate (.xlt) explorer
|
||||||
|
(list/show/ops/tree/summary/diff). Works fully on a config fixture.
|
||||||
|
- **`nc_smat_diff`** ← `nc-smat-diff.sh` — diff stored SMAT messages across two
|
||||||
|
envs, paired by MSH.10 (`--env-a`/`--env-b`/`--pair-on`). READ-ONLY; full run
|
||||||
|
needs two reachable archives.
|
||||||
|
- **`nc_tclgen`** ← `nc-tclgen.sh` — TCL UPOC skeleton generator (tps-presc/
|
||||||
|
tps-postsc/tps-iclkill/xlate-helper/trxid/ack/field-rewrite). Standalone,
|
||||||
|
deterministic, API-free.
|
||||||
|
|
||||||
|
- **`--help` header-leak fix (4 libs).** The sed comment-header range over-ran
|
||||||
|
into live code: `nc-status.sh` (`2,25p`→`2,20p`), `nc-engine.sh`
|
||||||
|
(`2,30p`→`2,29p`), `nc-xlate.sh` (`2,15p`→`2,11p`), `nc-tclgen.sh`
|
||||||
|
(`2,20p`→`2,19p`). Each now stops exactly at the end of the comment header —
|
||||||
|
no `set -o pipefail` / `NC_SELF=` / `die()` leaking into `--help`.
|
||||||
|
`nc-smat-diff.sh` (`2,22p`) was already clean.
|
||||||
|
|
||||||
|
- **FIXED `nc-engine.sh` arg-parsing crash (found during this exposure pass).**
|
||||||
|
The subcommand dispatcher treated EVERY `--flag` as taking a value
|
||||||
|
(`flags+=("$1" "${2:-}"); shift 2`), so the valueless `--dry-run` swallowed the
|
||||||
|
next token; and the `set -u` that leaks in from sourcing `journal.sh` made the
|
||||||
|
empty-array expansion `"${flags[@]}"` throw `unbound variable` under bash 3.2
|
||||||
|
(macOS/Gundersen), crashing `stop/start/bounce/restart` with `--site`/`--dry-run`.
|
||||||
|
Fix: `set +u` after sourcing `journal.sh` (nc-engine predates nounset and uses
|
||||||
|
bare `$1`/empty arrays), plus a multi-case parser — `--dry-run` is valueless,
|
||||||
|
`--site`/`--confirm` consume one value (without over-shifting on a bare trailing
|
||||||
|
flag). `status` and the test-driver paths were already unaffected.
|
||||||
|
|
||||||
## v0.8.27 — 2026-05-28
|
## v0.8.27 — 2026-05-28
|
||||||
|
|
||||||
**★ NEW TOOL: `nc-revisions.sh` — NetConfig change-history / revision-diff.**
|
**★ NEW TOOL: `nc-revisions.sh` — NetConfig change-history / revision-diff.**
|
||||||
|
|||||||
14
MANIFEST
14
MANIFEST
@ -23,16 +23,16 @@
|
|||||||
# scripts/make-manifest.sh and bump VERSION.
|
# scripts/make-manifest.sh and bump VERSION.
|
||||||
|
|
||||||
# Top-level scripts
|
# Top-level scripts
|
||||||
larry.sh 4de38e7e33507a8c8fde539cb29c031eabbec508674bf51dd9f441e536a76509
|
larry.sh 4bc6355ebd04b3e301c28d9c34a8ec2fdae44fa223f1f065cdcd2790a4676e33
|
||||||
larry-tunnel.sh 6b050e4eeab15669f4858eaf3b807f168f211ced07815db9521bc40a093f6aaa
|
larry-tunnel.sh 6b050e4eeab15669f4858eaf3b807f168f211ced07815db9521bc40a093f6aaa
|
||||||
larry-auth.sh a220cdf7878569dc3028951ee57fc8d5e706a8ca5c6aa45347b58facb386f831
|
larry-auth.sh a220cdf7878569dc3028951ee57fc8d5e706a8ca5c6aa45347b58facb386f831
|
||||||
larry-rollback.sh 91b5e9aa6c79266bf306dcfba4ca791c07971bd6924d67a779037531648aa6d0
|
larry-rollback.sh 91b5e9aa6c79266bf306dcfba4ca791c07971bd6924d67a779037531648aa6d0
|
||||||
install-larry.sh fa36e23a39eacbd0d7ecedd3b42131902f816ee7e98241dfc6e28c6e4ba80423
|
install-larry.sh fa36e23a39eacbd0d7ecedd3b42131902f816ee7e98241dfc6e28c6e4ba80423
|
||||||
|
|
||||||
# Metadata
|
# Metadata
|
||||||
VERSION 0ba962133bcfa080a96ec6b746ae1a4eb7816576618aa6c88d2c14506258715b
|
VERSION 4d1f87fb5ed962079a382ddacb5e4f28b461dd9d6c4a6c4085248832fa8111a5
|
||||||
MANUAL.md c64bd0251a51ad150508b4e1185355bc4826a64071d4de339f92ed550dbfacde
|
MANUAL.md c64bd0251a51ad150508b4e1185355bc4826a64071d4de339f92ed550dbfacde
|
||||||
CHANGELOG.md 3506542eac6c71d4cb29391b234f3fd30aec3853a5f5122b5bceb73d11079f46
|
CHANGELOG.md 567da1b7ddb2f8200eb42cfce6387f30ca753fc065abe4994f887e732d2a36f9
|
||||||
|
|
||||||
# Agent personas (system-prompt overlays)
|
# Agent personas (system-prompt overlays)
|
||||||
agents/larry.md 0a1ef737e7fc133ab35be09f79c3a4df33de814e0404b69b950932d0c8a01be1
|
agents/larry.md 0a1ef737e7fc133ab35be09f79c3a4df33de814e0404b69b950932d0c8a01be1
|
||||||
@ -90,13 +90,13 @@ lib/csv-to-table.sh ca9cfbcb9f6f42bf7925bf8b8d1e25f0f7209be138d7b971e3adef3ff6b5
|
|||||||
lib/table-to-csv.sh ad98e73687bc9e9f6ae0cd79ed5ba26c856076902865230f822dec1a1beae4b1
|
lib/table-to-csv.sh ad98e73687bc9e9f6ae0cd79ed5ba26c856076902865230f822dec1a1beae4b1
|
||||||
|
|
||||||
# NetConfig tooling
|
# NetConfig tooling
|
||||||
lib/nc-engine.sh fbb87aa704a1517f4fa713ccc57301e8744672a69a3e83589a444ff915b7ec24
|
lib/nc-engine.sh e2b12a1c019d40857b96d48d6c185b94aefadab604536ce41077ecc251b0bc58
|
||||||
lib/nc-status.sh a300efdaaef8e2764256ca6d8288a5fd4c1cf5097d8c5b7495135ac0ebf0f5a2
|
lib/nc-status.sh 80d2023babff70c065ffab70b5ecf9bdfd80183ae5808f610335da9c8c27f97f
|
||||||
lib/nc-table.sh a6d5c11dd460cfb100ea50c74d57c1a46ef49112632037534a32cd28600abe7f
|
lib/nc-table.sh a6d5c11dd460cfb100ea50c74d57c1a46ef49112632037534a32cd28600abe7f
|
||||||
lib/nc-xlate.sh ea02693c3dff5db271771d4bb2927b23465b07798df2f9912bc2d2b58a134d54
|
lib/nc-xlate.sh b05caae72889f6404a2a1618ba3ba3666dc34f03d49a779664ea31396dddb112
|
||||||
lib/nc-smat-diff.sh ac003954701ea6b7f4aa1f6941f8536af5b5cdfbb75e306789753d453f06800e
|
lib/nc-smat-diff.sh ac003954701ea6b7f4aa1f6941f8536af5b5cdfbb75e306789753d453f06800e
|
||||||
lib/nc-create-thread.sh 5a9d5407c117183cad831d6b95f0e785b1b806f5ccc67f803c12b3695882b5b7
|
lib/nc-create-thread.sh 5a9d5407c117183cad831d6b95f0e785b1b806f5ccc67f803c12b3695882b5b7
|
||||||
lib/nc-tclgen.sh dc95f523d543192fc7b3ae204107ce67ebb9b7e5184fa0642a1af2e2454d3241
|
lib/nc-tclgen.sh 5b8e73d7f6950a2b84f563132562ea82f62f4acac907257e233c7e68d85506c9
|
||||||
lib/nc-parse.sh 3419b3f8d0cfdaf767f91551d6e2441d0743d80bd31515ffa61c769db1542c2f
|
lib/nc-parse.sh 3419b3f8d0cfdaf767f91551d6e2441d0743d80bd31515ffa61c769db1542c2f
|
||||||
lib/nc-paths.sh 388d2f4560736587a01218cadc1de612cd59e392819d16db2f56f19174c1111b
|
lib/nc-paths.sh 388d2f4560736587a01218cadc1de612cd59e392819d16db2f56f19174c1111b
|
||||||
lib/nc-inbound.sh 52d28c5f8d97bdf96f0fc7b5300d35b106b8e1226578f4cda430deb2a8b4a91b
|
lib/nc-inbound.sh 52d28c5f8d97bdf96f0fc7b5300d35b106b8e1226578f4cda430deb2a8b4a91b
|
||||||
|
|||||||
160
larry.sh
160
larry.sh
@ -78,7 +78,7 @@ set -o pipefail
|
|||||||
# ─────────────────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
# Config
|
# Config
|
||||||
# ─────────────────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
LARRY_VERSION="0.8.27"
|
LARRY_VERSION="0.8.28"
|
||||||
LARRY_HOME="${LARRY_HOME:-$HOME/.larry}"
|
LARRY_HOME="${LARRY_HOME:-$HOME/.larry}"
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
@ -345,7 +345,7 @@ nc-paths.sh|Route-chain PATH tracer: enumerate full root-to-leaf chains for a th
|
|||||||
nc-find.sh|Cross-site search for threads/protocols by name/host/port/xlate across every site under $HCIROOT
|
nc-find.sh|Cross-site search for threads/protocols by name/host/port/xlate across every site under $HCIROOT
|
||||||
nc-inbound.sh|List the inbound (server/listener) threads in a NetConfig
|
nc-inbound.sh|List the inbound (server/listener) threads in a NetConfig
|
||||||
nc-status.sh|Engine runtime status (sites/threads/not-up/queued/connections) — wraps the shipped tstat binaries
|
nc-status.sh|Engine runtime status (sites/threads/not-up/queued/connections) — wraps the shipped tstat binaries
|
||||||
nc-engine.sh|Engine process control (start/stop/cycle/status) — wraps the shipped hcienginerun binaries
|
nc-engine.sh|Engine process control (start/stop/bounce/status) + route-test/testxlate/tpstest/resend drivers — wraps the shipped hci engine binaries
|
||||||
nc-xlate.sh|Visualize and explore a Cloverleaf xlate (.xlt) file — the TCL nested mapping tree
|
nc-xlate.sh|Visualize and explore a Cloverleaf xlate (.xlt) file — the TCL nested mapping tree
|
||||||
nc-table.sh|Read and modify Cloverleaf lookup tables (.tbl) — every write is backed up and auditable
|
nc-table.sh|Read and modify Cloverleaf lookup tables (.tbl) — every write is backed up and auditable
|
||||||
#NetConfig (write)
|
#NetConfig (write)
|
||||||
@ -4152,6 +4152,141 @@ tool_nc_revisions() {
|
|||||||
"$LARRY_LIB_DIR/nc-revisions.sh" "${args[@]}" 2>&1
|
"$LARRY_LIB_DIR/nc-revisions.sh" "${args[@]}" 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# nc_status — engine RUNTIME status. Native-bash wrapper around the shipped
|
||||||
|
# tstat/hcienginestat binaries (v1 status/tstat/not_up/connstatus models).
|
||||||
|
# READ-ONLY: never mutates NetConfig or engine state. Needs a LIVE engine for
|
||||||
|
# real numbers; on a config-only host it degrades gracefully (sites → reports
|
||||||
|
# 'config-present'; threads/connections → reports the missing binary, no crash).
|
||||||
|
# subcommand: sites|threads|not-up|connections|queued|raw (default sites).
|
||||||
|
tool_nc_status() {
|
||||||
|
local subcmd="${1:-sites}" site="$2" filter="$3" fmt="${4:-text}"
|
||||||
|
_lib_err_if_missing || return
|
||||||
|
case "$subcmd" in
|
||||||
|
sites|threads|not-up|connections|queued|raw) : ;;
|
||||||
|
"") subcmd="sites" ;;
|
||||||
|
*) echo "ERROR: unknown nc_status subcommand: $subcmd (sites|threads|not-up|connections|queued|raw)"; return 1 ;;
|
||||||
|
esac
|
||||||
|
local args=("$subcmd")
|
||||||
|
[ -n "$site" ] && args+=(--site "$site")
|
||||||
|
[ -n "$filter" ] && args+=(--filter "$filter")
|
||||||
|
case "$fmt" in text|tsv) args+=(--format "$fmt") ;; "") : ;; *) : ;; esac
|
||||||
|
"$LARRY_LIB_DIR/nc-status.sh" "${args[@]}" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
# nc_engine — engine PROCESS CONTROL + test drivers. Wraps the shipped
|
||||||
|
# hcienginestop/run/restart + route_test/testxlate/tpstest binaries. action:
|
||||||
|
# stop|start|bounce|restart mutate ENGINE STATE on a LIVE box (journaled,
|
||||||
|
# reversible — they do NOT run on the static config fixture); status is a
|
||||||
|
# read-only query; route-test/testxlate/tpstest/resend-ib/resend-ob exercise a
|
||||||
|
# message and require a live engine. NONE of these mutate NetConfig. confirm=yes
|
||||||
|
# skips the y/N prompt; dry_run=1 prints the generated binary command without
|
||||||
|
# executing. target = thread/process for stop/start/bounce; for route-test/
|
||||||
|
# resend it is <thread> <file>, for testxlate <xlate> <xltfile>, for tpstest
|
||||||
|
# <msgfile> <proc-args>.
|
||||||
|
tool_nc_engine() {
|
||||||
|
local action="$1" target="$2" file="$3" site="$4" confirm="$5" dry_run="${6:-0}" extra="$7"
|
||||||
|
_lib_err_if_missing || return
|
||||||
|
[ -n "$action" ] || { echo "ERROR: nc_engine needs an action (stop|start|bounce|restart|status|route-test|testxlate|tpstest|resend-ib|resend-ob)"; return 1; }
|
||||||
|
local args=()
|
||||||
|
case "$action" in
|
||||||
|
stop|start|bounce|restart)
|
||||||
|
[ -n "$target" ] || { echo "ERROR: nc_engine $action needs a target thread/process"; return 1; }
|
||||||
|
args=("$action" "$target")
|
||||||
|
[ -n "$site" ] && args+=(--site "$site")
|
||||||
|
[ "$confirm" = "yes" ] && args+=(--confirm yes)
|
||||||
|
[ "$dry_run" = "1" ] && args+=(--dry-run)
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
args=(status)
|
||||||
|
[ -n "$site" ] && args+=(--site "$site")
|
||||||
|
;;
|
||||||
|
route-test)
|
||||||
|
[ -n "$target" ] && [ -n "$file" ] || { echo "ERROR: nc_engine route-test needs target (thread) and file"; return 1; }
|
||||||
|
args=(route-test "$target" "$file") ;;
|
||||||
|
resend-ib|resend-ob)
|
||||||
|
[ -n "$target" ] && [ -n "$file" ] || { echo "ERROR: nc_engine $action needs target (thread) and file"; return 1; }
|
||||||
|
args=("$action" "$target" "$file") ;;
|
||||||
|
testxlate)
|
||||||
|
[ -n "$target" ] && [ -n "$file" ] || { echo "ERROR: nc_engine testxlate needs target (xlate) and file (xltfile)"; return 1; }
|
||||||
|
args=(testxlate "$target" "$file") ;;
|
||||||
|
tpstest)
|
||||||
|
[ -n "$file" ] || { echo "ERROR: nc_engine tpstest needs file (msgfile) and extra (proc-args)"; return 1; }
|
||||||
|
args=(tpstest "$file" $extra) ;;
|
||||||
|
*) echo "ERROR: unknown nc_engine action: $action"; return 1 ;;
|
||||||
|
esac
|
||||||
|
"$LARRY_LIB_DIR/nc-engine.sh" "${args[@]}" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
# nc_xlate — READ-ONLY xlate (.xlt) explorer. Renders Cloverleaf's TCL
|
||||||
|
# nested-mapping tree. subcommand: list|show|ops|tree|summary|diff. Works fully
|
||||||
|
# on a config fixture (no engine needed). list takes only --site; show/ops/tree/
|
||||||
|
# summary take a <name>; diff takes name + name2.
|
||||||
|
tool_nc_xlate() {
|
||||||
|
local subcmd="${1:-list}" name="$2" name2="$3" site="$4"
|
||||||
|
_lib_err_if_missing || return
|
||||||
|
local args=()
|
||||||
|
case "$subcmd" in
|
||||||
|
list)
|
||||||
|
args=(list)
|
||||||
|
[ -n "$site" ] && args+=(--site "$site") ;;
|
||||||
|
show|ops|tree|summary)
|
||||||
|
[ -n "$name" ] || { echo "ERROR: nc_xlate $subcmd needs name"; return 1; }
|
||||||
|
args=("$subcmd" "$name")
|
||||||
|
[ -n "$site" ] && args+=(--site "$site") ;;
|
||||||
|
diff)
|
||||||
|
[ -n "$name" ] && [ -n "$name2" ] || { echo "ERROR: nc_xlate diff needs name and name2"; return 1; }
|
||||||
|
args=(diff "$name" "$name2") ;;
|
||||||
|
"") args=(list); [ -n "$site" ] && args+=(--site "$site") ;;
|
||||||
|
*) echo "ERROR: unknown nc_xlate subcommand: $subcmd (list|show|ops|tree|summary|diff)"; return 1 ;;
|
||||||
|
esac
|
||||||
|
"$LARRY_LIB_DIR/nc-xlate.sh" "${args[@]}" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
# nc_smat_diff — diff stored SMAT (message-archive) content across TWO
|
||||||
|
# environments, pairing messages by MSH.10 (or --pair-on). READ-ONLY. Needs two
|
||||||
|
# HCIROOTs (env_a/env_b); full run requires both archives reachable. Returns a
|
||||||
|
# markdown summary path + per-pair diff reports under --out.
|
||||||
|
tool_nc_smat_diff() {
|
||||||
|
local thread="$1" env_a="$2" env_b="$3" site_a="$4" site_b="$5"
|
||||||
|
local limit="${6:-0}" ignore="${7:-}" out_path="$8" pair_on="$9" after="${10:-}"
|
||||||
|
_lib_err_if_missing || return
|
||||||
|
[ -n "$thread" ] || { echo "ERROR: nc_smat_diff needs a thread"; return 1; }
|
||||||
|
[ -n "$env_a" ] && [ -n "$env_b" ] || { echo "ERROR: nc_smat_diff needs env_a and env_b (two HCIROOTs)"; return 1; }
|
||||||
|
local args=("$thread" --env-a "$env_a" --env-b "$env_b")
|
||||||
|
[ -n "$site_a" ] && args+=(--site-a "$site_a")
|
||||||
|
[ -n "$site_b" ] && args+=(--site-b "$site_b")
|
||||||
|
case "$limit" in ''|0) : ;; *[!0-9]*) : ;; *) args+=(--limit "$limit") ;; esac
|
||||||
|
[ -n "$ignore" ] && args+=(--ignore "$ignore")
|
||||||
|
[ -n "$out_path" ] && args+=(--out "$out_path")
|
||||||
|
[ -n "$pair_on" ] && args+=(--pair-on "$pair_on")
|
||||||
|
[ -n "$after" ] && args+=(--after "$after")
|
||||||
|
"$LARRY_LIB_DIR/nc-smat-diff.sh" "${args[@]}" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
# nc_tclgen — generate annotated TCL UPOC scaffolding (skeletons). template:
|
||||||
|
# tps-presc|tps-postsc|tps-iclkill|xlate-helper|trxid|ack|field-rewrite|
|
||||||
|
# list-templates. Standalone, deterministic, API-free — emits ready-to-edit TCL
|
||||||
|
# to stdout. field-rewrite needs segment/field/to.
|
||||||
|
tool_nc_tclgen() {
|
||||||
|
local template="$1" proc="$2" description="$3" segment="$4" field="$5" to="$6"
|
||||||
|
_lib_err_if_missing || return
|
||||||
|
[ -n "$template" ] || { echo "ERROR: nc_tclgen needs a template (tps-presc|tps-postsc|tps-iclkill|xlate-helper|trxid|ack|field-rewrite|list-templates)"; return 1; }
|
||||||
|
local args=("$template")
|
||||||
|
case "$template" in
|
||||||
|
list-templates|list) : ;;
|
||||||
|
field-rewrite)
|
||||||
|
[ -n "$proc" ] && [ -n "$segment" ] && [ -n "$field" ] && [ -n "$to" ] \
|
||||||
|
|| { echo "ERROR: nc_tclgen field-rewrite needs proc, segment, field, to"; return 1; }
|
||||||
|
args+=("$proc" --segment "$segment" --field "$field" --to "$to") ;;
|
||||||
|
tps-presc|tps-postsc|tps-iclkill|xlate-helper|trxid|ack)
|
||||||
|
[ -n "$proc" ] || { echo "ERROR: nc_tclgen $template needs a proc name"; return 1; }
|
||||||
|
args+=("$proc")
|
||||||
|
[ -n "$description" ] && args+=(--description "$description") ;;
|
||||||
|
*) echo "ERROR: unknown nc_tclgen template: $template"; return 1 ;;
|
||||||
|
esac
|
||||||
|
"$LARRY_LIB_DIR/nc-tclgen.sh" "${args[@]}" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
tool_nc_diff_interface() {
|
tool_nc_diff_interface() {
|
||||||
local interface="$1" left="$2" right="$3" out_path="${4:-}" include_tables="${5:-0}"
|
local interface="$1" left="$2" right="$3" out_path="${4:-}" include_tables="${5:-0}"
|
||||||
local left_label="${6:-}" right_label="${7:-}" depth="${8:-1}"
|
local left_label="${6:-}" right_label="${7:-}" depth="${8:-1}"
|
||||||
@ -4229,6 +4364,20 @@ execute_tool() {
|
|||||||
nc_revisions) tool_nc_revisions "$(J '.thread // ""')" "$(J '.system // ""')" "$(J '.site // ""')" \
|
nc_revisions) tool_nc_revisions "$(J '.thread // ""')" "$(J '.system // ""')" "$(J '.site // ""')" \
|
||||||
"$(J '.format // "timeline"')" "$(J '.limit // 0')" \
|
"$(J '.format // "timeline"')" "$(J '.limit // 0')" \
|
||||||
"$(J '.since // ""')" "$(J '.hciroot // ""')" ;;
|
"$(J '.since // ""')" "$(J '.hciroot // ""')" ;;
|
||||||
|
nc_status) tool_nc_status "$(J '.subcommand // "sites"')" "$(J '.site // ""')" \
|
||||||
|
"$(J '.filter // ""')" "$(J '.format // "text"')" ;;
|
||||||
|
nc_engine) tool_nc_engine "$(J '.action')" "$(J '.target // ""')" "$(J '.file // ""')" \
|
||||||
|
"$(J '.site // ""')" "$(J '.confirm // ""')" \
|
||||||
|
"$(J '.dry_run // 0' | sed "s/false/0/;s/true/1/")" \
|
||||||
|
"$(J '.proc_args // ""')" ;;
|
||||||
|
nc_xlate) tool_nc_xlate "$(J '.subcommand // "list"')" "$(J '.name // ""')" \
|
||||||
|
"$(J '.name2 // ""')" "$(J '.site // ""')" ;;
|
||||||
|
nc_smat_diff) tool_nc_smat_diff "$(J '.thread')" "$(J '.env_a')" "$(J '.env_b')" \
|
||||||
|
"$(J '.site_a // ""')" "$(J '.site_b // ""')" \
|
||||||
|
"$(J '.limit // 0')" "$(J '.ignore // ""')" \
|
||||||
|
"$(J '.out // ""')" "$(J '.pair_on // ""')" "$(J '.after // ""')" ;;
|
||||||
|
nc_tclgen) tool_nc_tclgen "$(J '.template')" "$(J '.proc // ""')" "$(J '.description // ""')" \
|
||||||
|
"$(J '.segment // ""')" "$(J '.field // ""')" "$(J '.to // ""')" ;;
|
||||||
nc_find) tool_nc_find "$(J '.mode')" "$(J '.query')" "$(J '.format // "table"')" "$(J '.hciroot // ""')" ;;
|
nc_find) tool_nc_find "$(J '.mode')" "$(J '.query')" "$(J '.format // "table"')" "$(J '.hciroot // ""')" ;;
|
||||||
nc_insert_protocol) tool_nc_insert_protocol "$(J '.netconfig')" "$(J '.block')" "$(J '.mode // "end"')" "$(J '.anchor // ""')" ;;
|
nc_insert_protocol) tool_nc_insert_protocol "$(J '.netconfig')" "$(J '.block')" "$(J '.mode // "end"')" "$(J '.anchor // ""')" ;;
|
||||||
nc_add_route) tool_nc_add_route "$(J '.netconfig')" "$(J '.protocol_name')" "$(J '.route')" ;;
|
nc_add_route) tool_nc_add_route "$(J '.netconfig')" "$(J '.protocol_name')" "$(J '.route')" ;;
|
||||||
@ -4286,6 +4435,11 @@ TOOLS_JSON=$(cat <<'TOOLS_END'
|
|||||||
{"name":"nc_document","description":"Document a Cloverleaf INTERFACE end-to-end as a PLAIN-TEXT knowledge entry in Bryan's confirmed Legacy 'ADT Messages' template. OUTPUT IS PLAIN TEXT BY DEFAULT (no markdown) so it pastes cleanly into OneNote, which does NOT render markdown: UPPERCASE headings underlined with dashes, no bold, no backticks, no pipe tables, no '---' rules. Structure: Title; Description prose; Message Flow (one hop per record: Epic-feed → Cloverleaf-routing → Final-Delivery, built from the nc_paths route chain); per-delivery breakdown (inbound PROTOCOL TYPE/HOST/PORT/ISSERVER + inbound TRXID/TPS proc, route TRXID filter + TYPE + PREPROCS/POSTPROCS, XLATE, destination host:port/process). The two tabular sections (Message Flow, Delivery breakdown) render as INDENTED label:value blocks by default (read in any font, zero setup); set onenote_table=true to render them instead as TAB-separated rows (header + one row per record, no leading/trailing pipes) for paste-into-OneNote → Insert > Table. EVERYTHING THIS TOOL EMITS IS DETERMINISTIC, PURE BASH, AND API-FREE — it runs identically on an API-blocked host and never calls a model. ★ KEY FEATURE — for every referenced UPOC proc it locates the .tcl under $HCIROOT/<site>/tclprocs/ and DETERMINISTICALLY surfaces, INLINE in the Description, a compact bit-line: the proc's COMMENTS (the author's own filter notes), the HL7 FIELDS it references (PID.8, PV1.45, EVN.1…), the MATCHED literal event codes (A01 A02 A03…), TABLE lookups (e.g. PeriCalm_Loc), and the DISPOSITION (pass vs kill). Those inline bits are ALWAYS ON. The raw proc TCL appendix is OPT-IN via raw_tcl=true (off by default). ★ WHEN YOU (the model, running WITH the API) GET THIS TOOL'S OUTPUT: transparently POLISH those surfaced UPOC bits into smoother, human-readable filter descriptions inside the Description prose (e.g. turn 'fields: PV1.45 PID.8 · matches: A01 A02 A03 · table: Pericalm_Loc · disposition: kill non-matching' into 'passes only A01/A02/A03 admit/transfer events for female patients whose location is in the Pericalm_Loc table, killing everything else'). Do NOT invent facts not present in the surfaced bits; just smooth them. On an API-blocked host the deterministic bit-lines are the deliverable. MODES: (a) SINGLE INTERFACE — set thread (the delivery/outbound thread, e.g. 'ADTto_CodaMetrix'; optionally site to disambiguate) → one fully-detailed interface section. (b) SYSTEM/PATTERN — set name (case-insensitive substring/regex, e.g. 'codametrix') → one section per matching delivery thread across ALL sites. Give EXACTLY ONE of thread or name. Returns the doc text and (if out is given) writes it there.","input_schema":{"type":"object","properties":{"thread":{"type":"string","description":"SINGLE-INTERFACE mode: the delivery (outbound) thread to document, e.g. 'ADTto_CodaMetrix' or 'ADTto_periwatch'. Accepts a bare thread name or a 'site/thread' node. Give this OR name, not both."},"name":{"type":"string","description":"SYSTEM mode: case-insensitive substring/regex matching delivery thread names across all sites, e.g. 'codametrix', 'periwatch', 'epic_adt'. One section per match. Give this OR thread, not both."},"site":{"type":"string","description":"Home site of the thread (the NetConfig's parent dir). Optional — disambiguates a thread name present in multiple sites."},"out":{"type":"string","description":"Optional output file path. Convention: $LARRY_HOME/knowledge/<system>.txt (plain text)."},"hciroot":{"type":"string","description":"Override $HCIROOT for the NetConfig scan."},"title":{"type":"string","description":"Doc title. Default derived from thread/name."},"onenote_table":{"type":"boolean","description":"Render the tabular sections (Message Flow, Delivery breakdown) as TAB-separated rows (header + one data row per record, real tabs, no leading/trailing pipes) for paste-into-OneNote → Insert > Table. Default false = indented label:value blocks. Non-tabular sections stay plain text either way."},"raw_tcl":{"type":"boolean","description":"Also emit the raw proc-source appendix (verbatim TCL of every referenced UPOC proc). Default false — the readable extracted UPOC bits stay inline in each description regardless; only the verbatim appendix is gated behind this."},"status":{"type":"string","description":"System status fill-in (production/test/decommissioning/...)."},"poc_internal":{"type":"string","description":"Internal owner fill-in."},"poc_vendor":{"type":"string","description":"Vendor POC fill-in."},"escalation":{"type":"string","description":"Escalation path fill-in."},"open_items":{"type":"string","description":"Open items / known issues fill-in. Can be multi-line, will be inserted as-is."},"notes":{"type":"string","description":"Freeform notes fill-in."}},"required":[]}},
|
{"name":"nc_document","description":"Document a Cloverleaf INTERFACE end-to-end as a PLAIN-TEXT knowledge entry in Bryan's confirmed Legacy 'ADT Messages' template. OUTPUT IS PLAIN TEXT BY DEFAULT (no markdown) so it pastes cleanly into OneNote, which does NOT render markdown: UPPERCASE headings underlined with dashes, no bold, no backticks, no pipe tables, no '---' rules. Structure: Title; Description prose; Message Flow (one hop per record: Epic-feed → Cloverleaf-routing → Final-Delivery, built from the nc_paths route chain); per-delivery breakdown (inbound PROTOCOL TYPE/HOST/PORT/ISSERVER + inbound TRXID/TPS proc, route TRXID filter + TYPE + PREPROCS/POSTPROCS, XLATE, destination host:port/process). The two tabular sections (Message Flow, Delivery breakdown) render as INDENTED label:value blocks by default (read in any font, zero setup); set onenote_table=true to render them instead as TAB-separated rows (header + one row per record, no leading/trailing pipes) for paste-into-OneNote → Insert > Table. EVERYTHING THIS TOOL EMITS IS DETERMINISTIC, PURE BASH, AND API-FREE — it runs identically on an API-blocked host and never calls a model. ★ KEY FEATURE — for every referenced UPOC proc it locates the .tcl under $HCIROOT/<site>/tclprocs/ and DETERMINISTICALLY surfaces, INLINE in the Description, a compact bit-line: the proc's COMMENTS (the author's own filter notes), the HL7 FIELDS it references (PID.8, PV1.45, EVN.1…), the MATCHED literal event codes (A01 A02 A03…), TABLE lookups (e.g. PeriCalm_Loc), and the DISPOSITION (pass vs kill). Those inline bits are ALWAYS ON. The raw proc TCL appendix is OPT-IN via raw_tcl=true (off by default). ★ WHEN YOU (the model, running WITH the API) GET THIS TOOL'S OUTPUT: transparently POLISH those surfaced UPOC bits into smoother, human-readable filter descriptions inside the Description prose (e.g. turn 'fields: PV1.45 PID.8 · matches: A01 A02 A03 · table: Pericalm_Loc · disposition: kill non-matching' into 'passes only A01/A02/A03 admit/transfer events for female patients whose location is in the Pericalm_Loc table, killing everything else'). Do NOT invent facts not present in the surfaced bits; just smooth them. On an API-blocked host the deterministic bit-lines are the deliverable. MODES: (a) SINGLE INTERFACE — set thread (the delivery/outbound thread, e.g. 'ADTto_CodaMetrix'; optionally site to disambiguate) → one fully-detailed interface section. (b) SYSTEM/PATTERN — set name (case-insensitive substring/regex, e.g. 'codametrix') → one section per matching delivery thread across ALL sites. Give EXACTLY ONE of thread or name. Returns the doc text and (if out is given) writes it there.","input_schema":{"type":"object","properties":{"thread":{"type":"string","description":"SINGLE-INTERFACE mode: the delivery (outbound) thread to document, e.g. 'ADTto_CodaMetrix' or 'ADTto_periwatch'. Accepts a bare thread name or a 'site/thread' node. Give this OR name, not both."},"name":{"type":"string","description":"SYSTEM mode: case-insensitive substring/regex matching delivery thread names across all sites, e.g. 'codametrix', 'periwatch', 'epic_adt'. One section per match. Give this OR thread, not both."},"site":{"type":"string","description":"Home site of the thread (the NetConfig's parent dir). Optional — disambiguates a thread name present in multiple sites."},"out":{"type":"string","description":"Optional output file path. Convention: $LARRY_HOME/knowledge/<system>.txt (plain text)."},"hciroot":{"type":"string","description":"Override $HCIROOT for the NetConfig scan."},"title":{"type":"string","description":"Doc title. Default derived from thread/name."},"onenote_table":{"type":"boolean","description":"Render the tabular sections (Message Flow, Delivery breakdown) as TAB-separated rows (header + one data row per record, real tabs, no leading/trailing pipes) for paste-into-OneNote → Insert > Table. Default false = indented label:value blocks. Non-tabular sections stay plain text either way."},"raw_tcl":{"type":"boolean","description":"Also emit the raw proc-source appendix (verbatim TCL of every referenced UPOC proc). Default false — the readable extracted UPOC bits stay inline in each description regardless; only the verbatim appendix is gated behind this."},"status":{"type":"string","description":"System status fill-in (production/test/decommissioning/...)."},"poc_internal":{"type":"string","description":"Internal owner fill-in."},"poc_vendor":{"type":"string","description":"Vendor POC fill-in."},"escalation":{"type":"string","description":"Escalation path fill-in."},"open_items":{"type":"string","description":"Open items / known issues fill-in. Can be multi-line, will be inserted as-is."},"notes":{"type":"string","description":"Freeform notes fill-in."}},"required":[]}},
|
||||||
|
|
||||||
{"name":"nc_revisions","description":"NetConfig CHANGE-HISTORY / REVISION-DIFF tracer. Shows how a THREAD, a multi-thread SYSTEM, or a WHOLE SITE changed over time by diffing Cloverleaf's own per-save NetConfig revision SNAPSHOTS (the dirs Cloverleaf writes under $HCIROOT/<site>/revisions/NetConfig<timestamp>/, each holding a full NetConfig), annotated with WHO saved each revision and WHEN — parsed from each snapshot's NetConfig prologue (who: / date:). USE THIS — not grep_files / read_file / bash_exec over the revisions dir — for ANY of: 'who changed X and when', 'what changed in this thread/site over time', 'revision history', 'when did the port/host change', 'show me the change history', 'diff the revisions', 'audit the NetConfig edits'. DETERMINISTIC, PURE BASH, API-FREE — runs identically on an API-blocked host. Revisions are ordered chronologically by the prologue date (NOT by the un-padded dir name, which is not lexically sortable); the LIVE NetConfig is included last as '(current)'. SCOPE is reduced to the relevant protocol-block(s) via nc-parse so the diff is NOT the whole 10k-line NetConfig unless site-wide. TWO FORMATS: format=timeline (DEFAULT) = a plain-text who/when/summary table, one revision per block, where the summary counts routing threads added/removed/modified in scope between consecutive revisions; format=diff = the actual unified diff of the scoped NetConfig section between consecutive revisions (oldest→newest), one block per transition. MODES (give exactly one scope): (a) single THREAD — set thread (a bare name resolved in site / $HCISITE, or 'thread.site', or a 'site/thread' node); (b) SYSTEM — set system (case-insensitive name pattern, e.g. 'codametrix') plus site, one scoped diff per matching thread folded together; (c) whole SITE — set ONLY site (omit thread/system) to track the entire NetConfig. --limit keeps the most-recent N revisions; --since filters to revisions on/after a date (YYYY-MM-DD or YYYYMMDD). Resolves the site under $HCIROOT (or pass hciroot).","input_schema":{"type":"object","properties":{"thread":{"type":"string","description":"SINGLE-THREAD mode: the thread/protocol to track, e.g. 'ADTto_CodaMetrix'. Accepts a bare name (resolved in site or $HCISITE), 'thread.site', or a 'site/thread' node. Give this OR system OR site-only."},"system":{"type":"string","description":"SYSTEM mode: case-insensitive name pattern matching one or more threads (e.g. 'codametrix', 'periwatch'); the scoped diff folds every matching thread's block together. Pair with site."},"site":{"type":"string","description":"The site (NetConfig's parent dir / revisions dir owner). Required for system mode and for whole-site mode (set site and OMIT thread/system to track the entire NetConfig). For single-thread mode it disambiguates / overrides $HCISITE."},"format":{"type":"string","enum":["timeline","diff"],"description":"timeline (default) = plain-text who/when/summary table, one revision per block. diff = the scoped unified diff between consecutive revisions, one block per transition."},"limit":{"type":"integer","description":"Only the most-recent N revisions. 0/omitted = all."},"since":{"type":"string","description":"Only revisions on/after this date. YYYY-MM-DD or YYYYMMDD."},"hciroot":{"type":"string","description":"Override $HCIROOT for site/revisions discovery."}},"required":[]}},
|
{"name":"nc_revisions","description":"NetConfig CHANGE-HISTORY / REVISION-DIFF tracer. Shows how a THREAD, a multi-thread SYSTEM, or a WHOLE SITE changed over time by diffing Cloverleaf's own per-save NetConfig revision SNAPSHOTS (the dirs Cloverleaf writes under $HCIROOT/<site>/revisions/NetConfig<timestamp>/, each holding a full NetConfig), annotated with WHO saved each revision and WHEN — parsed from each snapshot's NetConfig prologue (who: / date:). USE THIS — not grep_files / read_file / bash_exec over the revisions dir — for ANY of: 'who changed X and when', 'what changed in this thread/site over time', 'revision history', 'when did the port/host change', 'show me the change history', 'diff the revisions', 'audit the NetConfig edits'. DETERMINISTIC, PURE BASH, API-FREE — runs identically on an API-blocked host. Revisions are ordered chronologically by the prologue date (NOT by the un-padded dir name, which is not lexically sortable); the LIVE NetConfig is included last as '(current)'. SCOPE is reduced to the relevant protocol-block(s) via nc-parse so the diff is NOT the whole 10k-line NetConfig unless site-wide. TWO FORMATS: format=timeline (DEFAULT) = a plain-text who/when/summary table, one revision per block, where the summary counts routing threads added/removed/modified in scope between consecutive revisions; format=diff = the actual unified diff of the scoped NetConfig section between consecutive revisions (oldest→newest), one block per transition. MODES (give exactly one scope): (a) single THREAD — set thread (a bare name resolved in site / $HCISITE, or 'thread.site', or a 'site/thread' node); (b) SYSTEM — set system (case-insensitive name pattern, e.g. 'codametrix') plus site, one scoped diff per matching thread folded together; (c) whole SITE — set ONLY site (omit thread/system) to track the entire NetConfig. --limit keeps the most-recent N revisions; --since filters to revisions on/after a date (YYYY-MM-DD or YYYYMMDD). Resolves the site under $HCIROOT (or pass hciroot).","input_schema":{"type":"object","properties":{"thread":{"type":"string","description":"SINGLE-THREAD mode: the thread/protocol to track, e.g. 'ADTto_CodaMetrix'. Accepts a bare name (resolved in site or $HCISITE), 'thread.site', or a 'site/thread' node. Give this OR system OR site-only."},"system":{"type":"string","description":"SYSTEM mode: case-insensitive name pattern matching one or more threads (e.g. 'codametrix', 'periwatch'); the scoped diff folds every matching thread's block together. Pair with site."},"site":{"type":"string","description":"The site (NetConfig's parent dir / revisions dir owner). Required for system mode and for whole-site mode (set site and OMIT thread/system to track the entire NetConfig). For single-thread mode it disambiguates / overrides $HCISITE."},"format":{"type":"string","enum":["timeline","diff"],"description":"timeline (default) = plain-text who/when/summary table, one revision per block. diff = the scoped unified diff between consecutive revisions, one block per transition."},"limit":{"type":"integer","description":"Only the most-recent N revisions. 0/omitted = all."},"since":{"type":"string","description":"Only revisions on/after this date. YYYY-MM-DD or YYYYMMDD."},"hciroot":{"type":"string","description":"Override $HCIROOT for site/revisions discovery."}},"required":[]}},
|
||||||
|
{"name":"nc_status","description":"Cloverleaf engine RUNTIME status — the live operational state of an engine, NOT the NetConfig file. READ-ONLY: never mutates NetConfig or engine state. Native-bash wrapper around the shipped tstat/hcienginestat/connstatus binaries (the v3 equivalent of v1 status/tstat/thread_status/not_up/connstatus/dstatus). USE THIS — not bash_exec — for 'is the engine up', 'what threads are down', 'thread status', 'is X connected', 'what's queued', 'site status'. REQUIRES A LIVE ENGINE for real numbers: on a config-only host (no engine binaries on $HCIROOT/bin) it degrades gracefully — subcommand=sites reports 'config-present' per site, while threads/not-up/connections/queued report the missing binary instead of crashing. SUBCOMMANDS: sites (default) = site/daemon-level state; threads = per-thread port/state/host; not-up = only threads NOT in 'up' state; connections = raw connection state (connstatus); queued = threads with messages queued; raw = pass-through to the tstat binary. Scope to one site with site (default = all sites under $HCIROOT). filter is a regex on thread name (threads/not-up). format text (default) or tsv.","input_schema":{"type":"object","properties":{"subcommand":{"type":"string","enum":["sites","threads","not-up","connections","queued","raw"],"description":"What to report. sites (default)=site-level; threads=per-thread; not-up=only non-up threads; connections=raw conn state; queued=threads with queued msgs; raw=pass-through tstat."},"site":{"type":"string","description":"Single site to query. Default = all sites under $HCIROOT (or $HCISITE for thread-level subcommands)."},"filter":{"type":"string","description":"Regex matched against thread name (applies to threads/not-up)."},"format":{"type":"string","enum":["text","tsv"],"description":"Output format. Default text."}},"required":[]}},
|
||||||
|
{"name":"nc_engine","description":"Cloverleaf engine PROCESS CONTROL + message TEST drivers. Native-bash wrapper around the shipped hcienginestop/hcienginerun/hcienginerestart plus route_test/testxlate/tpstest/resend. NONE of these mutate NetConfig. The state-changing actions (stop/start/bounce/restart) RUN ONLY ON A LIVE ENGINE BOX, are JOURNALED (reversible best-effort), and DO NOT run on a static config fixture; the test drivers (route-test/testxlate/tpstest/resend-ib/resend-ob) likewise need a live engine. USE THIS for 'stop/start/bounce thread X', 'restart the process', 'test-route this message', 'test the xlate', 'run a TPS test', 'resend this message'. ACTIONS: stop|start|bounce|restart <target thread/process>; status = read-only engine status query; route-test <thread> <file> = run Cloverleaf route_test for a thread against a message file; testxlate <xlate> <xltfile> = test an xlate; tpstest <msgfile> + proc_args = run a TPS proc test (wraps hcitps); resend-ib/resend-ob <thread> <file> = replay a message inbound (pre-xlate) / outbound (post-xlate). SAFETY: by default the lib prompts y/N before any state change; set confirm=yes to skip the prompt (still journaled), or dry_run=true to PRINT the generated binary command WITHOUT executing (use dry_run to preview on a non-engine host).","input_schema":{"type":"object","properties":{"action":{"type":"string","enum":["stop","start","bounce","restart","status","route-test","testxlate","tpstest","resend-ib","resend-ob"],"description":"The engine action. stop/start/bounce/restart change live engine state (journaled). status is read-only. route-test/testxlate/tpstest/resend-* exercise a message."},"target":{"type":"string","description":"For stop/start/bounce/restart: the thread or process name. For route-test/resend-*: the thread. For testxlate: the xlate name."},"file":{"type":"string","description":"For route-test/resend-*: the message file. For testxlate: the .xlt file. For tpstest: the message file."},"proc_args":{"type":"string","description":"For tpstest only: the TPS proc args appended after the message file."},"site":{"type":"string","description":"Override $HCISITE for stop/start/bounce/status."},"confirm":{"type":"string","description":"Set to 'yes' to skip the interactive y/N prompt before a state change (still journaled)."},"dry_run":{"type":"boolean","description":"true = print the generated binary command WITHOUT executing (preview). Applies to stop/start/bounce/restart."}},"required":["action"]}},
|
||||||
|
{"name":"nc_xlate","description":"READ-ONLY Cloverleaf xlate (.xlt) explorer — visualize and inspect a translation's TCL nested-mapping tree. Works FULLY on a config-only host (no engine needed); never mutates anything. USE THIS — not read_file / grep over a .xlt — for 'show me the xlate', 'what does this translation do', 'list the operations', 'which segments does it touch', 'what tables does it use', 'diff two xlates'. SUBCOMMANDS: list = list .xlt files (scope with site); show <name> = dump the raw .xlt; ops <name> = operations as TSV (num/op/in/out/err/extra); tree <name> = ASCII operation tree (COPY/MOVE/DELETE/TABLE arrows); summary <name> = counts by operation type + segments touched (IN side) + tables referenced; diff <name> <name2> = semantic diff of two xlates (sorted by op). The name is the .xlt basename minus extension; site (the xlate's home site) disambiguates / locates it under $HCIROOT/<site>/Xlate.","input_schema":{"type":"object","properties":{"subcommand":{"type":"string","enum":["list","show","ops","tree","summary","diff"],"description":"list (default)=list .xlt files; show=raw dump; ops=TSV operations; tree=ASCII op tree; summary=counts+segments+tables; diff=semantic diff of name vs name2."},"name":{"type":"string","description":"The xlate basename (with or without .xlt). Required for show/ops/tree/summary/diff."},"name2":{"type":"string","description":"Second xlate basename — diff subcommand only."},"site":{"type":"string","description":"The xlate's home site (located under $HCIROOT/<site>/Xlate). Defaults to $HCISITE."}},"required":[]}},
|
||||||
|
{"name":"nc_smat_diff","description":"Diff stored SMAT (message-archive) CONTENT across TWO Cloverleaf environments. READ-ONLY. Unlike nc_regression (which runs route_test on synthetic input), this samples the ACTUAL archived messages from each env's smatdb and compares them: it pulls the N most-recent messages per side and PAIRS them by MSH.10 (message control ID; override with pair_on), then runs an HL7-aware field diff on each pair. Unmatched control IDs are reported as A-only / B-only. USE THIS for 'compare what prod vs test actually sent for thread X', 'did the message content change between environments', 'diff the archived messages'. REQUIRES TWO ENVIRONMENTS: env_a and env_b are two HCIROOT paths whose smatdbs are both reachable; a full run needs both archives present. Returns a markdown summary (and per-pair diff reports) written under out.","input_schema":{"type":"object","properties":{"thread":{"type":"string","description":"The thread whose archived messages to compare (its .smatdb is auto-located under each env)."},"env_a":{"type":"string","description":"HCIROOT of environment A."},"env_b":{"type":"string","description":"HCIROOT of environment B."},"site_a":{"type":"string","description":"Site on env A. Defaults to $HCISITE."},"site_b":{"type":"string","description":"Site on env B. Defaults to site_a."},"limit":{"type":"integer","description":"Messages to sample per side. Default 50."},"ignore":{"type":"string","description":"HL7 fields to ignore in the per-pair diff (hl7-diff --ignore). Default MSH.7."},"out":{"type":"string","description":"Output directory for per-message diffs + the markdown summary. Default a temp dir."},"pair_on":{"type":"string","description":"HL7 field to pair messages on. Default MSH.10."},"after":{"type":"string","description":"Only messages after this time, e.g. '3 days ago' or '2026-05-20'."}},"required":["thread","env_a","env_b"]}},
|
||||||
|
{"name":"nc_tclgen","description":"Generate annotated TCL UPOC SCAFFOLDING — clean, lint-free Cloverleaf proc skeletons with the right argument handling and boilerplate. DETERMINISTIC, STANDALONE, API-FREE: emits ready-to-edit TCL to stdout (or writes a file). Use to start a UPOC from a template when offline, or as a clean starting point you then fill in. TEMPLATES: tps-presc = PreSC TPS handler (runs before service send); tps-postsc = PostSC handler (after route translation); tps-iclkill = a PreSC proc that conditionally drops (KILLs) a message; xlate-helper = an Xlate-callable helper function; trxid = a routing-key (TRXID) extractor; ack = a raw ACK (AA) generator; field-rewrite = set a specific segment.field to a constant on every message (needs segment/field/to); list-templates = print the available templates. proc = the generated proc name; description = an optional one-line header comment. Note: for a FULLY-written, message-specific UPOC, describe the intent to Larry directly — this tool gives the skeleton.","input_schema":{"type":"object","properties":{"template":{"type":"string","enum":["tps-presc","tps-postsc","tps-iclkill","xlate-helper","trxid","ack","field-rewrite","list-templates"],"description":"Which skeleton to emit."},"proc":{"type":"string","description":"The generated TCL proc name (required for all templates except list-templates)."},"description":{"type":"string","description":"Optional one-line description placed in the proc's header comment."},"segment":{"type":"string","description":"field-rewrite only: the HL7 segment to rewrite, e.g. PID."},"field":{"type":"string","description":"field-rewrite only: the field number within the segment."},"to":{"type":"string","description":"field-rewrite only: the constant value to set."}},"required":["template"]}},
|
||||||
{"name":"nc_find","description":"Cross-site thread search. Native v3 replacement for v1 tbn/tbp/tbh/tbpr/where. Walks every NetConfig under $HCIROOT and returns matching threads with site, port, host, process, direction, file, line. Modes: name=partial name match (like tbn); port=exact port (like tbp); host=substring on host (like tbh); process=substring on PROCESSNAME (like tbpr); where=exact name match across all sites (like the v1 `<thread> where`); xlate=threads referencing a specific .xlt; tclproc=threads referencing a specific TCL proc.","input_schema":{"type":"object","properties":{"mode":{"type":"string","enum":["name","port","host","process","where","xlate","tclproc"],"description":"Search mode."},"query":{"type":"string","description":"Query value: partial name, port number, host substring, process name, exact thread name, xlate filename, or tclproc name."},"format":{"type":"string","enum":["table","tsv","jsonl"],"description":"Output format. Default table."},"hciroot":{"type":"string","description":"Override $HCIROOT."}},"required":["mode","query"]}},
|
{"name":"nc_find","description":"Cross-site thread search. Native v3 replacement for v1 tbn/tbp/tbh/tbpr/where. Walks every NetConfig under $HCIROOT and returns matching threads with site, port, host, process, direction, file, line. Modes: name=partial name match (like tbn); port=exact port (like tbp); host=substring on host (like tbh); process=substring on PROCESSNAME (like tbpr); where=exact name match across all sites (like the v1 `<thread> where`); xlate=threads referencing a specific .xlt; tclproc=threads referencing a specific TCL proc.","input_schema":{"type":"object","properties":{"mode":{"type":"string","enum":["name","port","host","process","where","xlate","tclproc"],"description":"Search mode."},"query":{"type":"string","description":"Query value: partial name, port number, host substring, process name, exact thread name, xlate filename, or tclproc name."},"format":{"type":"string","enum":["table","tsv","jsonl"],"description":"Output format. Default table."},"hciroot":{"type":"string","description":"Override $HCIROOT."}},"required":["mode","query"]}},
|
||||||
{"name":"nc_insert_protocol","description":"Insert a new protocol block into a NetConfig file. ALL WRITES GO THROUGH THE JOURNAL — original is snapshotted, diff is saved, the file is atomically replaced. Use larry_rollback_list to view, larry-rollback.sh CLI to undo. mode=end appends; mode=after needs anchor=existing-protocol-name; mode=before needs anchor.","input_schema":{"type":"object","properties":{"netconfig":{"type":"string","description":"Target NetConfig file path."},"block":{"type":"string","description":"The full protocol block text (starting with 'protocol NAME {' and ending with '}'). Get this from nc_make_jump output."},"mode":{"type":"string","enum":["end","after","before"],"description":"Insertion position. Default end."},"anchor":{"type":"string","description":"For mode=after|before: existing protocol name to position relative to."}},"required":["netconfig","block"]}},
|
{"name":"nc_insert_protocol","description":"Insert a new protocol block into a NetConfig file. ALL WRITES GO THROUGH THE JOURNAL — original is snapshotted, diff is saved, the file is atomically replaced. Use larry_rollback_list to view, larry-rollback.sh CLI to undo. mode=end appends; mode=after needs anchor=existing-protocol-name; mode=before needs anchor.","input_schema":{"type":"object","properties":{"netconfig":{"type":"string","description":"Target NetConfig file path."},"block":{"type":"string","description":"The full protocol block text (starting with 'protocol NAME {' and ending with '}'). Get this from nc_make_jump output."},"mode":{"type":"string","enum":["end","after","before"],"description":"Insertion position. Default end."},"anchor":{"type":"string","description":"For mode=after|before: existing protocol name to position relative to."}},"required":["netconfig","block"]}},
|
||||||
{"name":"nc_add_route","description":"Splice a route entry into an existing protocol's DATAXLATE block. Used to add a new DEST to an inbound's routing (e.g. wiring the OLD inbound to also route to the new linux_<tag>_out jump thread). ALL WRITES GO THROUGH THE JOURNAL.","input_schema":{"type":"object","properties":{"netconfig":{"type":"string"},"protocol_name":{"type":"string","description":"The existing protocol to modify."},"route":{"type":"string","description":"The route entry text (an inner `{ ... }` object with CACHEMSG, ROUTE_DETAILS, TRXID, etc.). Get from nc_make_jump's route_add output."}},"required":["netconfig","protocol_name","route"]}},
|
{"name":"nc_add_route","description":"Splice a route entry into an existing protocol's DATAXLATE block. Used to add a new DEST to an inbound's routing (e.g. wiring the OLD inbound to also route to the new linux_<tag>_out jump thread). ALL WRITES GO THROUGH THE JOURNAL.","input_schema":{"type":"object","properties":{"netconfig":{"type":"string"},"protocol_name":{"type":"string","description":"The existing protocol to modify."},"route":{"type":"string","description":"The route entry text (an inner `{ ... }` object with CACHEMSG, ROUTE_DETAILS, TRXID, etc.). Get from nc_make_jump's route_add output."}},"required":["netconfig","protocol_name","route"]}},
|
||||||
@ -5168,7 +5322,7 @@ agent_turn() {
|
|||||||
# no such block.
|
# no such block.
|
||||||
#
|
#
|
||||||
# v0.8.12 PROMPT CACHING (cost): the system prompt (~6K tok of agent .md) and
|
# v0.8.12 PROMPT CACHING (cost): the system prompt (~6K tok of agent .md) and
|
||||||
# the tools block (~6.7K tok, 35 tools) are STATIC across a session but were
|
# the tools block (~7.5K tok, 43 tools) are STATIC across a session but were
|
||||||
# re-sent UNCACHED every turn — ~12.7K input tok billed at full $3/MTok each
|
# re-sent UNCACHED every turn — ~12.7K input tok billed at full $3/MTok each
|
||||||
# turn (~$0.038/turn just for the prefix). With cache_control breakpoints the
|
# turn (~$0.038/turn just for the prefix). With cache_control breakpoints the
|
||||||
# first turn pays a 1.25x write ($3.75/MTok) and every subsequent turn reads
|
# first turn pays a 1.25x write ($3.75/MTok) and every subsequent turn reads
|
||||||
|
|||||||
@ -49,6 +49,9 @@ fi
|
|||||||
|
|
||||||
# Source journal so journaled actions can call journal_write
|
# Source journal so journaled actions can call journal_write
|
||||||
[ -f "$JOURNAL" ] && . "$JOURNAL" || warn "journal.sh not available — actions will not be reversible"
|
[ -f "$JOURNAL" ] && . "$JOURNAL" || warn "journal.sh not available — actions will not be reversible"
|
||||||
|
# journal.sh enables `set -u`; nc-engine.sh predates it (bare $1/$2 + empty-array
|
||||||
|
# expansions that throw "unbound" under bash 3.2). Restore the assumed env.
|
||||||
|
set +u
|
||||||
|
|
||||||
resolve_binary() {
|
resolve_binary() {
|
||||||
local name="$1"
|
local name="$1"
|
||||||
@ -210,7 +213,12 @@ case "$SUB" in
|
|||||||
# Separate targets from flags
|
# Separate targets from flags
|
||||||
targets=(); flags=()
|
targets=(); flags=()
|
||||||
while [ $# -gt 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
case "$1" in --*) flags+=("$1" "${2:-}"); shift 2 ;; *) targets+=("$1"); shift ;; esac
|
case "$1" in
|
||||||
|
--dry-run) flags+=("$1"); shift ;;
|
||||||
|
--site|--confirm) flags+=("$1" "${2:-}"); shift; [ $# -gt 0 ] && shift ;;
|
||||||
|
--*) flags+=("$1"); shift ;;
|
||||||
|
*) targets+=("$1"); shift ;;
|
||||||
|
esac
|
||||||
done
|
done
|
||||||
for t in "${targets[@]}"; do run_action "$SUB" "$t" "${flags[@]}"; done
|
for t in "${targets[@]}"; do run_action "$SUB" "$t" "${flags[@]}"; done
|
||||||
;;
|
;;
|
||||||
@ -220,6 +228,6 @@ case "$SUB" in
|
|||||||
route-test) shift; cmd_route_test "$@" ;;
|
route-test) shift; cmd_route_test "$@" ;;
|
||||||
testxlate) shift; cmd_testxlate "$@" ;;
|
testxlate) shift; cmd_testxlate "$@" ;;
|
||||||
tpstest) shift; cmd_tpstest "$@" ;;
|
tpstest) shift; cmd_tpstest "$@" ;;
|
||||||
help|-h|--help) sed -n '2,30p' "$NC_SELF" ;;
|
help|-h|--help) sed -n '2,29p' "$NC_SELF" ;;
|
||||||
*) die "unknown subcommand: $SUB" ;;
|
*) die "unknown subcommand: $SUB" ;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@ -147,6 +147,6 @@ case "$SUB" in
|
|||||||
connections) shift; cmd_connections "$@" ;;
|
connections) shift; cmd_connections "$@" ;;
|
||||||
queued) shift; cmd_queued "$@" ;;
|
queued) shift; cmd_queued "$@" ;;
|
||||||
raw) shift; cmd_raw "$@" ;;
|
raw) shift; cmd_raw "$@" ;;
|
||||||
help|-h|--help) sed -n '2,25p' "$NC_SELF" ;;
|
help|-h|--help) sed -n '2,20p' "$NC_SELF" ;;
|
||||||
*) die "unknown subcommand: $SUB" ;;
|
*) die "unknown subcommand: $SUB" ;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
# Output: TCL source to stdout (or --out PATH).
|
# Output: TCL source to stdout (or --out PATH).
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
usage() { sed -n '2,20p' "$0"; exit 0; }
|
usage() { sed -n '2,19p' "$0"; exit 0; }
|
||||||
die() { printf 'nc-tclgen: %s\n' "$*" >&2; exit 1; }
|
die() { printf 'nc-tclgen: %s\n' "$*" >&2; exit 1; }
|
||||||
|
|
||||||
header() {
|
header() {
|
||||||
|
|||||||
@ -150,6 +150,6 @@ case "$SUB" in
|
|||||||
tree) shift; [ $# -ge 1 ] || die "usage: tree NAME"; cmd_tree "$@" ;;
|
tree) shift; [ $# -ge 1 ] || die "usage: tree NAME"; cmd_tree "$@" ;;
|
||||||
summary) shift; [ $# -ge 1 ] || die "usage: summary NAME"; cmd_summary "$@" ;;
|
summary) shift; [ $# -ge 1 ] || die "usage: summary NAME"; cmd_summary "$@" ;;
|
||||||
diff) shift; [ $# -ge 2 ] || die "usage: diff NAME1 NAME2"; cmd_diff "$@" ;;
|
diff) shift; [ $# -ge 2 ] || die "usage: diff NAME1 NAME2"; cmd_diff "$@" ;;
|
||||||
help|-h|--help) sed -n '2,15p' "$NC_SELF" ;;
|
help|-h|--help) sed -n '2,11p' "$NC_SELF" ;;
|
||||||
*) die "unknown subcommand: $SUB" ;;
|
*) die "unknown subcommand: $SUB" ;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user