Files
stack/tools/unslop-hook/README.md
T
jason.woltje 7db4c5c2ed feat(agent): interactive TUI launcher + identity + TOOLS.md (#35)
- scripts/agent.sh <name>: launches interactive pi TUI in the container
  with contracts + optional mission + agent identity + named session +
  optional workspace/tools; the Mosaic alternative to vanilla pi
- pi adapter: MOSAIC_INTERACTIVE branch (clean TUI, no -p, no initial
  prompt); headless exec rebuilt via positional args (no word-splitting
  on the request); MOSAIC_AGENT_NAME optional in headless
- loader: AGENT IDENTITY section when the launcher names the agent
- compose: fixed command removed (request defaults live in run-agent.sh);
  MOSAIC_INTERACTIVE/MOSAIC_AGENT_NAME passthrough
- docs/TOOLS.md: full on-demand tool reference; AGENTS.md routes to it
- RELEASE -> 0.0.8 (container change); build verified

Closes #35
2026-09-03 11:24:56 -05:00

84 lines
4.3 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.
# unslop-hook
Mechanical AI-tell enforcement for pi seats. Anti-drift gate for the writing
standard in SYSTEM.md / ms-unslop: prose distribution alone decays over long
sessions; this check cannot forget.
- `lists.json`: committed machine source for every list the checker enforces:
words, phrases, punct rules, regex patterns, density thresholds. Each entry
carries provenance (`ms-unslop:<pattern id>` or `system-md`), the mention
convention, and the documented divergence of the density gate from
SYSTEM.md's outright em-dash ban. Edit lists here, not in code.
- `unslop-check.js`: dependency-free checker (node CLI + module) driven by
lists.json. Loads and schema-validates the lists on first use and hard-fails
closed: empty, unparseable, or invalid lists throw. Detects banned vocabulary,
chatbot/sycophancy phrases, filler phrases, em/en dashes, curly quotes,
`not just X but Y`. Strips fenced and inline code first, so quoted code is
never flagged. Exit 0 clean, 1 violations, 2 gate broken (lists unreadable,
never a clean verdict).
- `extension.ts`: pi extension. `message_end` checks finalized assistant text
and notifies the operator (TUI/RPC). `before_agent_start` reads the most
recent assistant reply from the session file and, if it carries tells,
injects a correction notice the model sees on its next turn. `/unslop`
reports session stats. Violation state lives in the session file, so the
injection path survives restart, resume, fork, and reload (an in-memory
pending flag was measured dead across print-mode turns, 2026-08-19). A
broken lists.json fails closed: checks stop, `broken_lists` /
`skipped_broken` events log the reason, operator notified once, seat keeps
running.
- `test-unslop-check.js`: unit tests with red and green controls.
## Use
```bash
node test-unslop-check.js # suite
node unslop-check.js <file> # CLI check
UNSLOP_LISTS=<path> node unslop-check.js <file> # alt lists location
pi -e ~/.mosaic/tools/unslop-hook/extension.ts # ad-hoc load
# deploy: copy dir to ~/.pi/agent/extensions/unslop-hook/ or seat .pi
# equivalent, or list it in settings.json "extensions"
```
Env: `MOSAIC_UNSLOP_HOOK=0` disables. `MOSAIC_UNSLOP_LOG=<path>` appends JSONL
events (loaded / flagged / notice_injected / checked / broken_lists /
skipped_broken) for headless evidence. `UNSLOP_LISTS=<path>` overrides the
lists.json location for both CLI and extension.
## Verified here (2026-08-19)
- Unit suite 24/24 (8 behavioral, 11 loader/CLI, 5 review follow-up), red and
green controls both exercised, including exit-2 on broken lists and on an
unreadable input file (S3).
- CLI: slop file exit 1, clean file exit 0, broken lists exit 2 with the fault
named on stderr.
- Extension, healthy path (print mode, zai/glm-5.3:low): startup probe loads
lists.json, reply checked clean.
- Extension, broken-lists path (print mode): `broken_lists` at startup,
`skipped_broken` per turn, seat survives, reply still delivered.
- Earlier live evidence (pre-C1, inline lists): forced-slop turn flagged;
fresh-process follow-up injected the notice and the reply came back clean;
full TUI trial (notify line, injection, /unslop stats) on session vision-unslop.
- Log evidence in session scratchpad.
## Limits
- `/unslop` command not tested headless (print mode has no command surface);
it is a thin stats wrapper.
- En dash flag fires on typographic ranges too (23); acceptable for fleet
prose, revisit if it noisifies technical writing.
- Notice injection is a nudger, not a blocker. Output already streamed to the
user stays as-is; correction lands on the next turn.
- A broken lists.json latches for the session: repairing the file mid-session
does not revive checks until the seat restarts. Acceptable for an advisory
gate (review S1).
- The fail-closed operator notification requires a UI. Print-mode sessions
log `skipped_broken` but notify nobody (review S2).
- The word/phrase lists are the mechanical subset of ms-unslop only, keyed to
pattern ids in lists.json. Style judgments (voice, rhythm, structure) stay in
the skill, not the gate.
## Promotion path
Stack issue (A4): checker shared as the single source for a matching Claude
Code Stop-hook script; lists versioned beside SYSTEM.md contract text.