• exec/tests/scfg_paths_test.jsexec/chat_llm.js

    From Rob Swindell (on Debian Linux)@VERT to Git commit to main/sbbs/master on Tuesday, November 03, 2026 22:17:41
    https://gitlab.synchro.net/main/sbbs/-/commit/1f541208c650f6d62d25356f
    Added Files:
    exec/tests/scfg_paths_test.js
    Modified Files:
    exec/chat_llm.js
    Log Message:
    chat_llm: verify SCFG menu paths against the option index

    Indexing scfgindex.h (the new scfg source crawler in the local exec
    repo) gave the corpus SCFG's real option breadcrumbs, which fixed the
    questions whose wording matches an option label. Retrieval is ranking
    though, not verification. Measured on five everyday-phrasing questions
    ("how do I limit how many files a user can download per day?"), none of
    the scfg chunks reached the top twelve and three replies still named a
    path that does not exist -- including one where the right wiki page WAS retrieved and the option was mislocated anyway, which no amount of
    ranking would have fixed.

    fix_scfg_paths() checks a finished reply's SCFG path claims against the
    2065 locations the index knows, the way strip_fake_urls() polices
    citations. A claim whose option label occurs exactly once in SCFG is
    rewritten to the real path -- "File Options > Downloads Per Day" becomes "System > Security Options... > Security Level Values > Downloads Per
    Day". Otherwise the longest real prefix survives, and otherwise the
    path is dropped and the bare SCFG mention kept. The count goes into the
    [prof] line as scfgfix=N, because the chat log is the only place a
    misfire on real traffic would be noticed.

    Only a chain the reply ATTRIBUTES to SCFG is checked. sbbsctrl has a
    menu tree of its own ("servers -> ftp -> configure"), and the terminal interface has menus too, so rewriting an unattributed path into an SCFG
    one would be worse than the error it replaces. A real SCFG path stated
    without naming SCFG is therefore left alone -- the check misses those
    rather than risk corrupting unrelated text.

    Three details the tests pin down, each of which broke a correct reply on
    the way here:

    A hop has to look like a label: Title Case or leading digits, continuing
    only with capitalized words or a short list of connectors. With spaces
    allowed freely, "SCFG->System->Security Options... is where the password
    lives" matched through to "lives" and the rewrite ate the sentence.

    Trailing ellipsis and sentence periods normalize away on both sides.
    Submenu labels carry a "..." that a model routinely omits, so comparing literally turned the CORRECT "System > Security Options... > Create
    Self-signed Certificate" into a bare "System".

    URL spans are excluded before matching, since wiki page IDs are
    colon-separated and ":" is one of the separators a chain can use.

    The ground truth is derived from the index's scfg chunks and cached on
    the index object, which load_index() replaces when the .idx mtime
    changes -- so a nightly rebuild cannot leave stale paths behind, and an
    install whose index_sources has no scfg source gets an inert check.

    exec/tests/scfg_paths_test.js covers the above plus the fabrications
    actually logged in #synchronet, and skips cleanly when the install's
    index carries no SCFG options.

    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net