diff --git a/CHANGELOG.md b/CHANGELOG.md index d95bd01..dad1710 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,48 @@ All notable changes to `cloverleaf-larry` / `larry-anywhere` are recorded here. Versioning is loose-semver; bumps trigger the in-process self-update on every running client via `LARRY_BASE_URL` + `MANIFEST`. +## v0.8.24 — 2026-05-28 + +**★ PLAIN-TEXT output rewrite of `lib/nc-document.sh` (Bryan's priority — OneNote +readability).** Bryan shares the generated interface doc with a teammate in +OneNote, which does NOT render markdown — `#`, `**bold**`, `| pipe tables |`, +`---` rules and backticks all show as literal junk. The OUTPUT layer is rewritten +to emit clean PLAIN TEXT by default (parsing/extraction logic unchanged): + +- **Default = plain text everywhere.** UPPERCASE headings underlined with a + dashes line; no `**bold**`, no backtick code spans, no `---` horizontal rules, + no `| pipe tables |`. Reads cleanly in any editor and pastes straight into + OneNote. +- **Tabular sections (Message Flow, Delivery breakdown) — two render modes.** + DEFAULT = indented `label:value` blocks (one block per hop/row; reads in any + font, zero setup). New `--onenote-table` flag renders those same sections as + TAB-separated rows (header row + one data row per record, real `\t` between + cells, NO leading/trailing pipes) — paste into OneNote then Insert > Table to + get real cells. Non-tabular sections (Title/Context/Description) stay plain + text in both modes. +- **Removed** the verbose `Filter / translation logic (surfaced deterministically + from the referenced UPOC procs):` preamble line; the surfaced UPOC bits now sit + under a simple `FILTER / TRANSLATION LOGIC` plain heading, still inline in each + interface description (always on). +- **Raw TCL is now OPT-IN behind `--raw-tcl`** (off by default). The readable, + deterministically-extracted UPOC bits stay inline in the per-interface + description regardless; only the verbatim raw-proc appendix is gated. The + appendix is rendered as a plain indented source dump (no ```` ```tcl ```` fences). +- New flags `--onenote-table` and `--raw-tcl` documented in the lib `--help` and + in the `nc_document` tool schema/wrapper in `larry.sh` (`onenote_table`, + `raw_tcl` booleans). The `--help` `sed -n` range was re-pinned to the END of the + comment header (`2,92p`) so it does not leak live code. + +**Folded in two Vera-deferred v0.8.22 minors** (`lib/nc-document.sh`): +- Removed dead/unused `sup`/`fan` counters in `_xlate_filter_block`. +- Added `local` to the previously un-`local`'d `_dest_hit`/`_d` loop variables in + `document_thread`. + +Verified against the real integrator (`HCIROOT=/tmp/clvf_realtest/integrator`, +`--name codametrix`): default output is plain text with `label:value` hop blocks +and no markdown chars; `--onenote-table` produces tab-separated rows; the removed +preamble line is gone; raw TCL only appears with `--raw-tcl`. + ## v0.8.23 — 2026-05-28 **★ REGRESSION CHAIN-WALK route-test capture (Bryan's priority).** New diff --git a/MANIFEST b/MANIFEST index daeca67..f7617f2 100644 --- a/MANIFEST +++ b/MANIFEST @@ -23,16 +23,16 @@ # scripts/make-manifest.sh and bump VERSION. # Top-level scripts -larry.sh 57a96b78c7ab319537b2203a7363454ebcd482ed048d63dc05668fad3c292ee7 +larry.sh b3af140dcb8518ea98327b33177bcef8973ca223ad1f46f90ad6dba0e9f7ded7 larry-tunnel.sh 6b050e4eeab15669f4858eaf3b807f168f211ced07815db9521bc40a093f6aaa larry-auth.sh a220cdf7878569dc3028951ee57fc8d5e706a8ca5c6aa45347b58facb386f831 larry-rollback.sh 91b5e9aa6c79266bf306dcfba4ca791c07971bd6924d67a779037531648aa6d0 install-larry.sh fa36e23a39eacbd0d7ecedd3b42131902f816ee7e98241dfc6e28c6e4ba80423 # Metadata -VERSION 189191ed6bf46fb5d0b7f887c60f28c097b6b4df83273227744f0510b00d89db +VERSION 05d77ce62e5abe7212c0fa5ca747f16348d012c39016080e99c10f8f7f5e20bf MANUAL.md c64bd0251a51ad150508b4e1185355bc4826a64071d4de339f92ed550dbfacde -CHANGELOG.md 646791fb1a6f99c326869c57e17cb1662827afa566e68d91fe580ed68d0f02df +CHANGELOG.md 5432e98a75500cf4cb7d1fa171124d64e693865215d4612f5071294a4f871f6a # Agent personas (system-prompt overlays) agents/larry.md 0a1ef737e7fc133ab35be09f79c3a4df33de814e0404b69b950932d0c8a01be1 @@ -102,7 +102,7 @@ lib/nc-paths.sh 388d2f4560736587a01218cadc1de612cd59e392819d16db2f56f19174c1111b lib/nc-inbound.sh 52d28c5f8d97bdf96f0fc7b5300d35b106b8e1226578f4cda430deb2a8b4a91b lib/nc-make-jump.sh 08a0bc58a299c95c60a59a5202792daf0ada3a8a0be7dc1b4cccc5724f5c9c79 lib/nc-msgs.sh 729e2d6c9159e83fa177fc6b982e48ed8453a9743477cc90afdd3cd4ec7e620c -lib/nc-document.sh e0b5c5b0a778abff2f09377cd1692ba445140e7da84aa8a96a002081f31b870c +lib/nc-document.sh 56808d5ba86ca6b355f405bf33db7de62e8894a5582987e9de1eeee77a8ab3a8 lib/nc-diff-interface.sh 6b64ec3070a3d75d1d79632c9aeb357177fdbcc77c474aa78e6f6929fda1a324 lib/nc-find.sh 8c79e0acad7de56e4e1f12d61e071a4b98c4e2310a1f7fb183697df521215e3f lib/nc-insert-protocol.sh ad1fa0bafbf4fdfb12bad20f9c22c3eed519f8846774331e26aa9becd6f8898a diff --git a/VERSION b/VERSION index cddd48a..0a08824 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.8.23 +0.8.24 diff --git a/larry.sh b/larry.sh index be0dd18..6082443 100755 --- a/larry.sh +++ b/larry.sh @@ -78,7 +78,7 @@ set -o pipefail # ───────────────────────────────────────────────────────────────────────────── # Config # ───────────────────────────────────────────────────────────────────────────── -LARRY_VERSION="0.8.23" +LARRY_VERSION="0.8.24" LARRY_HOME="${LARRY_HOME:-$HOME/.larry}" # ───────────────────────────────────────────────────────────────────────────── @@ -4089,6 +4089,7 @@ tool_nc_document() { # section per matching delivery thread across sites. Exactly one of thread/name. local thread="$1" name="$2" site="$3" out_path="${4:-}" hciroot="${5:-${HCIROOT:-}}" local title="${6:-}" status="${7:-}" poc_internal="${8:-}" poc_vendor="${9:-}" escalation="${10:-}" open_items="${11:-}" notes="${12:-}" + local onenote_table="${13:-0}" raw_tcl="${14:-0}" _lib_err_if_missing || return [ -n "$thread" ] || [ -n "$name" ] \ || { echo "ERROR: nc_document needs either thread (single interface) or name (system pattern)"; return 1; } @@ -4108,6 +4109,8 @@ tool_nc_document() { [ -n "$escalation" ] && args+=(--escalation "$escalation") [ -n "$open_items" ] && args+=(--open-items "$open_items") [ -n "$notes" ] && args+=(--notes "$notes") + [ "$onenote_table" = "1" ] && args+=(--onenote-table) + [ "$raw_tcl" = "1" ] && args+=(--raw-tcl) "$LARRY_LIB_DIR/nc-document.sh" "${args[@]}" 2>&1 } @@ -4182,7 +4185,9 @@ execute_tool() { "$(J '.title // ""')" "$(J '.status // ""')" \ "$(J '.poc_internal // ""')" "$(J '.poc_vendor // ""')" \ "$(J '.escalation // ""')" "$(J '.open_items // ""')" \ - "$(J '.notes // ""')" ;; + "$(J '.notes // ""')" \ + "$(J '.onenote_table // 0' | sed "s/false/0/;s/true/1/")" \ + "$(J '.raw_tcl // 0' | sed "s/false/0/;s/true/1/")" ;; 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_add_route) tool_nc_add_route "$(J '.netconfig')" "$(J '.protocol_name')" "$(J '.route')" ;; @@ -4237,7 +4242,7 @@ TOOLS_JSON=$(cat <<'TOOLS_END' {"name":"nc_tclproc_refs","description":"List every TCL proc name referenced from a protocol block (or from the whole NetConfig if name is omitted). Pulls from DATAFORMAT.PROC, PREPROCS.PROCS, POSTPROCS.PROCS, etc. Unique sorted.","input_schema":{"type":"object","properties":{"netconfig":{"type":"string"},"name":{"type":"string","description":"Optional. Scope to one protocol."}},"required":["netconfig"]}}, {"name":"hl7_field","description":"Extract a specific HL7 v2 field from a message. field_path = SEG[.FIELD[.COMPONENT[.SUBCOMPONENT]]]. Examples: PID.3 (MRN), PID.18 (account number), MSH.7 (timestamp), MSH.9.2 (event code, like A08), PID.5 (patient name with components). Multiple repetitions are returned one per line. Native v3, no v1/v2 dependency.","input_schema":{"type":"object","properties":{"message":{"type":"string","description":"Raw HL7 message text. Segments separated by \\r."},"field_path":{"type":"string","description":"Field path like PID.3 or MSH.9.2"}},"required":["message","field_path"]}}, {"name":"nc_msgs","description":"Query Cloverleaf smat (SQLite!) databases for messages from a thread. Filters: time range, exact HL7 field match. Native v3 — reads smatdb directly with sqlite3 -ascii, no hcidbdump/dbExtract needed. Format text shows messages line-by-line with metadata; count returns just the count; json returns structured data. Operates on LOCAL smatdbs; for a remote env's smatdb, use ssh_pull_smat first (sampled mode is cheaper than pulling the whole DB).","input_schema":{"type":"object","properties":{"thread":{"type":"string","description":"Thread name. The .smatdb file under $HCISITEDIR/exec/processes/*/.smatdb is auto-located unless db is given."},"after":{"type":"string","description":"Time-after filter. Accepts \"3 days ago\", \"2026-05-20 14:30:00\", \"2026-05-20\", or a unix timestamp."},"before":{"type":"string","description":"Time-before filter, same formats as after."},"field":{"type":"string","description":"HL7 field path for exact-match filter, e.g. PID.18 or MSH.10."},"value":{"type":"string","description":"Value the field must equal. Use with field. Repeatable filters not supported via this single tool call — chain calls if you need multi-field AND."},"limit":{"type":"integer","description":"Max messages to return. Default 10."},"format":{"type":"string","enum":["text","json","count","raw"],"description":"text = human-readable with metadata; count = just the number; json = structured; raw = raw bytes separated by 0x1c."},"sitedir":{"type":"string","description":"Override $HCISITEDIR for thread-to-db location."},"db":{"type":"string","description":"Explicit .smatdb path; overrides auto-locate."}},"required":["thread"]}}, - {"name":"nc_document","description":"Document a Cloverleaf INTERFACE end-to-end as a native markdown knowledge entry in Bryan's confirmed Legacy 'ADT Messages' template (Title; Description prose; Message Flow table Platform|Action|Description|From|To with one row per hop 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). 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//tclprocs/ and DETERMINISTICALLY surfaces, into 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). The raw proc TCL is included verbatim in a '## Referenced proc source' appendix for audit (NO 'summarize by hand' marker — the surfaced bits ARE the content). ★ 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 + appendix 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/.md."},"hciroot":{"type":"string","description":"Override $HCIROOT for the NetConfig scan."},"title":{"type":"string","description":"Doc title. Default derived from thread/name."},"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//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/.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_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 ` 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"]}}, diff --git a/lib/nc-document.sh b/lib/nc-document.sh index a1daf4b..683f1b3 100755 --- a/lib/nc-document.sh +++ b/lib/nc-document.sh @@ -1,7 +1,14 @@ #!/usr/bin/env bash -# nc-document.sh — document a Cloverleaf INTERFACE end-to-end as a native markdown +# nc-document.sh — 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). Bryan shares the generated doc +# in OneNote, which does NOT render markdown — `#`, `**bold**`, `| pipe tables |`, +# `---` rules and backticks all show up as literal junk. So the default render is +# clean plain text: UPPERCASE headings (underlined with a dashes line), no bold, +# no backticks, no pipe tables, no `---` rules. It reads cleanly in any editor and +# pastes straight into OneNote. +# # Two modes: # SINGLE THREAD nc-document.sh [site] (e.g. ADTto_CodaMetrix ancout) # nc-document.sh / (v1 node form) @@ -10,9 +17,10 @@ # # Everything emitted by THIS tool is DETERMINISTIC, PURE BASH+AWK, and API-FREE. # It runs identically on an API-blocked host (e.g. Gundersen). It never calls an -# LLM and never reaches the network. The deterministic UPOC-bits + raw proc TCL -# appendix ARE the deliverable; when larry runs WITH the API the model transparently -# polishes those surfaced bits into smoother prose in the Description — that is +# LLM and never reaches the network. The deterministic UPOC bits (always inline in +# each interface's description) ARE the deliverable; the raw proc TCL appendix is +# OPT-IN via --raw-tcl. When larry runs WITH the API the model transparently +# polishes the surfaced bits into smoother prose in the Description — that is # normal agent behavior, NOT a mechanism in this script. # # ───────────────────────────────────────────────────────────────────────────── @@ -20,14 +28,17 @@ # - Title = the interface / message type. # - Description = prose: what the messages are, what the filters key on, where # translation happens, how it's fed — seeded from the surfaced -# UPOC bits. -# - Message Flow = a table (Platform | Action | Description | From | To), one row -# per hop: Epic feed → Cloverleaf cross-site routing → Final -# Delivery. Built from nc-paths.sh (the route-chain enumerator). +# UPOC bits, which stay INLINE in the description by default. +# - Message Flow = one block per hop (Epic feed → Cloverleaf routing → Final +# Delivery), built from nc-paths.sh (the route-chain enumerator). +# DEFAULT render = a label:value block per hop (reads in ANY +# font, zero setup). With --onenote-table this becomes TAB- +# separated rows (header + one row per hop) you paste into +# OneNote and turn into a real table via Insert > Table. # - Per-delivery breakdown: # inbound PROTOCOL TYPE/HOST/PORT/ISSERVER + inbound TRXID/TPS proc, # the route's TRXID filter + TYPE + PREPROCS/POSTPROCS + XLATE, -# destination host:port / process. +# destination host:port / process. Same DEFAULT/--onenote-table behavior. # - ★ DETERMINISTIC UPOC-BITS — for each referenced proc, locate its .tcl under # $HCIROOT//tclprocs/ and extract (no API): # 1. comments (header + inline `#` lines — the author's own filter notes) @@ -35,9 +46,8 @@ # 3. conditions + literal values (matched event-code lists A01/A02/…, etc.) # 4. table lookups (.tbl / table names, e.g. PeriCalm_Loc) # 5. disposition (CONTINUE / KILL / return — pass vs kill) -# Rendered compactly into the Description. -# - Raw proc TCL in a plain appendix (`## Referenced proc source`). NO "summarize -# by hand / on an API box" marker — the extracted bits are the content. +# Rendered compactly INLINE in the Description (always on). +# - Raw proc TCL appendix — OPT-IN behind --raw-tcl (off by default). # # Usage: # nc-document.sh [site] [options] @@ -49,15 +59,26 @@ # --thread NAME single-thread mode (alternative to the positional form) # --site NAME home site of the thread (disambiguates a multi-site name) # --hciroot DIR defaults to $HCIROOT -# --out PATH output markdown path (default: stdout) +# --out PATH output text path (default: stdout) # --title TITLE doc title (default: derived from thread/name) +# --onenote-table render the tabular sections (Message Flow, Delivery +# breakdown) as TAB-separated rows (header row + one data +# row per record, real \t between cells, NO leading/trailing +# pipes) for paste-into-OneNote → Insert > Table. The +# DEFAULT (without this flag) renders them as indented +# label:value blocks that read in any font. Non-tabular +# sections (Title/Context/Description) stay plain text in +# both modes. +# --raw-tcl also emit the raw proc-source appendix (verbatim TCL of +# every referenced UPOC proc). OFF by default — the readable +# extracted UPOC bits stay inline in each description; only +# the verbatim appendix is gated behind this flag. # --poc-vendor TXT Vendor POC content # --poc-internal TXT Internal Owner content # --status TXT e.g. production / test / decommissioning # --escalation TXT Escalation path text # --open-items TXT Open items text # --notes TXT freeform additional notes -# --no-appendix omit the raw proc-source appendix # --inbound-systems P path to the curated inbound-systems lookup TSV (default: # $LARRY_HOME/inbound-systems.tsv, then the shipped seed). # Maps a feed thread name / port: to the external sender @@ -139,7 +160,12 @@ STATUS="" ESCALATION="" OPEN_ITEMS="" NOTES="" -WANT_APPENDIX=1 +# Raw TCL appendix is OPT-IN (--raw-tcl). The readable extracted UPOC bits stay +# inline in each description regardless; only the verbatim appendix is gated. +WANT_APPENDIX=0 +# Tabular sections render as label:value blocks by default; --onenote-table emits +# TAB-separated rows instead (header + one row per record) for OneNote paste. +ONENOTE_TABLE=0 STRICT_DELIVERY=0 INBOUND_SYSTEMS_FILE="${INBOUND_SYSTEMS_FILE:-}" POSITIONAL=() @@ -152,16 +178,18 @@ while [ $# -gt 0 ]; do --hciroot) shift; HCIROOT_OVERRIDE="${1:-}" ;; --out) shift; OUT="${1:-}" ;; --title) shift; TITLE="${1:-}" ;; + --onenote-table) ONENOTE_TABLE=1 ;; + --raw-tcl) WANT_APPENDIX=1 ;; --poc-vendor) shift; POC_VENDOR="${1:-}" ;; --poc-internal) shift; POC_INTERNAL="${1:-}" ;; --status) shift; STATUS="${1:-}" ;; --escalation) shift; ESCALATION="${1:-}" ;; --open-items) shift; OPEN_ITEMS="${1:-}" ;; --notes) shift; NOTES="${1:-}" ;; - --no-appendix) WANT_APPENDIX=0 ;; + --no-appendix) WANT_APPENDIX=0 ;; # back-compat no-op (appendix is now off by default) --strict-delivery) STRICT_DELIVERY=1 ;; --inbound-systems) shift; INBOUND_SYSTEMS_FILE="${1:-}" ;; - -h|--help) sed -n '2,71p' "$NC_SELF" | sed 's/^# \{0,1\}//'; exit 0 ;; + -h|--help) sed -n '2,92p' "$NC_SELF" | sed 's/^# \{0,1\}//'; exit 0 ;; --*) die "unknown flag: $1" ;; *) POSITIONAL+=("$1") ;; esac @@ -230,6 +258,36 @@ out_target() { fi } +# ───────────────────────────────────────────────────────────────────────────── +# PLAIN-TEXT RENDER HELPERS (v0.8.24). The whole doc is plain text so it pastes +# cleanly into OneNote (which does NOT render markdown). No `#`/`##`, no +# `**bold**`, no backticks, no `---` rules, no `| pipe tables |`. +# ───────────────────────────────────────────────────────────────────────────── +TAB=$(printf '\t') + +# A top-level heading: UPPERCASE text underlined with a full-width dashes line. +_h1() { # text + local t; t=$(printf '%s' "$1" | tr '[:lower:]' '[:upper:]') + printf '%s\n' "$t" + printf '%s\n\n' "$(printf '%*s' "${#t}" '' | tr ' ' '=')" +} +# A section heading: UPPERCASE text underlined with dashes. +_h2() { # text + local t; t=$(printf '%s' "$1" | tr '[:lower:]' '[:upper:]') + printf '%s\n' "$t" + printf '%s\n\n' "$(printf '%*s' "${#t}" '' | tr ' ' '-')" +} +# A sub-heading: UPPERCASE text on its own line, no underline (keeps it light). +_h3() { # text + printf '%s\n\n' "$(printf '%s' "$1" | tr '[:lower:]' '[:upper:]')" +} +# A label:value line for a key/value bullet block. Pads the label to a common +# width so values line up in a monospaced view (and still reads fine elsewhere). +# _kv