Commit Graph

82 Commits

Author SHA1 Message Date
jared 115749e232 hangman: fix display never showing guessed letters + improve word-guess feedback
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 44s
Lint / Secret scan (gitleaks) (push) Successful in 4s
- _hangman_display compared uppercase word chars against lowercase
  guessed_letters set, so letters were never revealed after correct guesses
- Word guess wrong path now shows the board and remaining guesses
- Winner display now includes the guesser's name on correct word guess

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 01:04:27 -04:00
jared c9d9febbe0 wyr: track real reaction votes and announce winner with counts
Lint / Shell (shellcheck) (push) Successful in 27s
Lint / JS (eslint) (push) Successful in 14s
Lint / Python (ruff) (push) Successful in 11s
Lint / Python deps (pip-audit) (push) Successful in 45s
Lint / Secret scan (gitleaks) (push) Successful in 5s
- Add _WYR_POLLS dict keyed by poll event_id to accumulate votes
- record_wyr_vote() called from callbacks.reaction() on every reaction
- reveal() reads actual vote counts and announces winner with percentage
- Handles tie and zero-vote cases
- Remove the useless 'check the reactions above' message

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 01:02:25 -04:00
jared 6c00e8b4fd fix: raise Ollama timeout from 20s to 60s for all game generators
Lint / Shell (shellcheck) (push) Successful in 14s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 45s
Lint / Secret scan (gitleaks) (push) Successful in 5s
phi4-mini can queue behind other requests and take >20s under load,
causing TimeoutError and silent failures in wyr/riddle/hangman/scramble.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 00:57:54 -04:00
jared 82a3f24519 fix: switch all JSON-returning game generators to api/chat + robust parsing
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 1m0s
Lint / Secret scan (gitleaks) (push) Successful in 7s
hangman, scramble, riddle, and wyr all used api/generate which has no
system role. The model would wrap JSON in prose or markdown fences,
causing json.loads() to throw and the command to silently die after
the 'Generating...' message.

Fix for all four: switch to api/chat with a system message enforcing
raw JSON output, strip markdown fences, and use regex to extract the
JSON object even if surrounded by extra text.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 00:55:45 -04:00
jared a47648435e roast: expand Nathan lore with education background
Lint / Shell (shellcheck) (push) Successful in 13s
Lint / JS (eslint) (push) Successful in 9s
Lint / Python (ruff) (push) Successful in 6s
Lint / Python deps (pip-audit) (push) Successful in 47s
Lint / Secret scan (gitleaks) (push) Successful in 6s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 00:53:33 -04:00
jared 4213449a88 wyr: fix JSON parsing failure causing silent no-op after 'Generating...'
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 7s
Lint / Secret scan (gitleaks) (push) Has been cancelled
Lint / Python deps (pip-audit) (push) Has been cancelled
Switch to api/chat with a system prompt for better JSON compliance,
and use regex extraction to find the JSON object even if the model
wraps it in extra text or markdown fences.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 00:52:39 -04:00
jared 83a4a2ffae roast: use chat API with system prompt + few-shot example for actual biting roasts
Lint / Shell (shellcheck) (push) Successful in 13s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Successful in 40s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Switch from api/generate to api/chat so we can set a system role that
instructs the model to be genuinely savage. Add a few-shot example so
it knows what a roast looks like vs a backhanded compliment.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 00:50:10 -04:00
jared acf68038d8 roast: fix refusal prompt, add Cole/Nathan lore, expand known users
Lint / Shell (shellcheck) (push) Successful in 15s
Lint / JS (eslint) (push) Successful in 11s
Lint / Python (ruff) (push) Successful in 15s
Lint / Secret scan (gitleaks) (push) Has been cancelled
Lint / Python deps (pip-audit) (push) Has been cancelled
- Reframe prompt as a consented comedy roast between friends so the
  model doesn't refuse on safety grounds
- Add lore for lonely (Cole, 23, dishwasher, gamer) and
  natcofragomatic (Nathan, DCO Tech 3 at AWS, ginger, tape-drive nerd)
- Use a lookup table (_ROAST_LORE) so adding new users is one line

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 00:48:48 -04:00
jared 0dada4c2b7 lint: fix E741 ambiguous variable names and F841 unused variable
Lint / Shell (shellcheck) (push) Successful in 15s
Lint / JS (eslint) (push) Successful in 13s
Lint / Python (ruff) (push) Successful in 6s
Lint / Python deps (pip-audit) (push) Successful in 43s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 00:41:55 -04:00
jared e4dbcfde7a ping: always show round-trip time instead of only when >500ms
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 8s
Lint / Python (ruff) (push) Failing after 6s
Lint / Python deps (pip-audit) (push) Successful in 1m39s
Lint / Secret scan (gitleaks) (push) Successful in 9s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 00:39:10 -04:00
jared 973e422678 feat: add 7 new commands — hangman, scramble, wyr, riddle, roast, story, debate
Lint / Shell (shellcheck) (push) Successful in 13s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Failing after 5s
Lint / Python deps (pip-audit) (push) Successful in 1m16s
Lint / Secret scan (gitleaks) (push) Successful in 5s
- !hangman: AI picks a 5-8 letter word with hint; players !guess letters/words, 6 wrong = dead
- !scramble: AI picks a word, scrambles it; first correct answer in chat wins (45s timeout)
- !wyr: AI generates Would You Rather with 🅰️/🅱️ reaction voting, 30s reveal
- !riddle: AI generates riddle monitored for 60s, substring match in chat wins
- !roast: AI roasts a target using BALL_MODEL with special Jared/Wynter lore
- !story: collaborative story with !story add <line> and !story end (AI conclusion, max 10 lines)
- !debate: AI writes FOR/AGAINST arguments for any topic using ASK_MODEL
- callbacks.py: route all non-command messages through scramble/riddle answer checkers
- help: updated categories to include all new commands
2026-04-22 00:35:19 -04:00
jared 9015338a1c help: move 8ball to AI category
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 6s
Lint / Python deps (pip-audit) (push) Successful in 43s
Lint / Secret scan (gitleaks) (push) Successful in 6s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 00:15:46 -04:00
jared fb39b17473 trivia: per-category fallbacks, always show model attribution
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 8s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 1m14s
Lint / Secret scan (gitleaks) (push) Successful in 10s
- Replace flat fallback list with per-category fallback dict so
  !trivia music never shows a gaming question when AI is down
- Always show "via <model>" tag on AI questions; show warning tag
  on static fallbacks so users know AI was unavailable

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 00:05:29 -04:00
jared 876c7d26d4 trivia: add 8 new categories + per-category dedup cache
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 56s
Lint / Secret scan (gitleaks) (push) Successful in 5s
New categories: anime, sports, food, history, geography, nature,
mythology, tv (14 total).

Add _trivia_recent dict that tracks the last 20 questions per
category and injects them into the LLM prompt as a avoid list,
preventing duplicate questions within a session.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 23:53:57 -04:00
jared caf9ad806a 8ball: romantic-question-aware fallbacks for Wynter branches
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 1m6s
Lint / Secret scan (gitleaks) (push) Successful in 5s
When Wynter asks a romantic question about Jared ("is he in love
with me", "does he miss me", etc.) the LLM fallback now explicitly
denies the premise instead of giving a generic Jared-wins response.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 23:35:47 -04:00
jared 896b76d6ab 8ball: enforce no-romance lore + AI responses for all users
Lint / Shell (shellcheck) (push) Successful in 22s
Lint / JS (eslint) (push) Successful in 25s
Lint / Python (ruff) (push) Successful in 12s
Lint / Python deps (pip-audit) (push) Successful in 1m36s
Lint / Secret scan (gitleaks) (push) Successful in 6s
- Add explicit Jared/Wynter no-romance lore to all four branch
  bio_contexts and prompts — prevents model from implying romantic
  feelings between them
- Add _implies_jared_wynter_romance() validator; responses that
  suggest romantic connection fall back to the static fallback
- Replace random-list responses for non-Jared/Wynter senders with
  AI-generated magic 8-ball predictions via BALL_MODEL

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 23:25:47 -04:00
jared dcb38618a7 ci: upgrade pip+setuptools before audit to clear bundled CVEs
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Successful in 48s
Lint / Secret scan (gitleaks) (push) Successful in 8s
The python-build-standalone tarball ships pip 24.1.2 and setuptools
70.3.0 which have known CVEs. Upgrade them first so --local audit
only sees current, patched versions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 14:06:01 -04:00
jared f6ce517a69 ci: use pip-audit --local to avoid internal venv ensurepip failure
Lint / Shell (shellcheck) (push) Successful in 11s
Lint / JS (eslint) (push) Successful in 8s
Lint / Python (ruff) (push) Successful in 7s
Lint / Python deps (pip-audit) (push) Failing after 47s
Lint / Secret scan (gitleaks) (push) Successful in 5s
The standalone Python 3.10 binary's venv ensurepip step exits 127.
Workaround: install requirements + pip-audit into the same env,
then audit with --local (no internal venv creation).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 14:03:19 -04:00
jared 353695f8c3 ci: use python-build-standalone 3.10 binary for pip-audit
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Failing after 34s
Lint / Secret scan (gitleaks) (push) Successful in 8s
Debian Bullseye only ships Python 3.9 and python3.10 is not in its
repos. python-dotenv 1.2.2 (vuln fix) requires Python >=3.10.
Use indygreg/python-build-standalone to get a self-contained Python
3.10.15 binary that works on any glibc Linux runner.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 14:00:36 -04:00
jared a85ea312c9 ci: bootstrap pip via ensurepip for python3.10 (no venv package on Debian)
Lint / Shell (shellcheck) (push) Successful in 8s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Failing after 4m41s
Lint / Secret scan (gitleaks) (push) Successful in 6s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 13:50:40 -04:00
jared d4f3563982 ci: use python3.10 for pip-audit (dotenv 1.2.2 requires >=3.10)
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Failing after 7s
Lint / Secret scan (gitleaks) (push) Successful in 6s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 13:48:53 -04:00
jared 0a1c90ef86 deps: pin python-dotenv>=1.2.2 to fix GHSA-mf9w-mj56-hr94
Lint / Shell (shellcheck) (push) Successful in 12s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Failing after 1m40s
Lint / Secret scan (gitleaks) (push) Successful in 31s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 13:45:25 -04:00
jared 0bc9373bd9 8ball: add --debug flag to show post-processed prompt
Lint / Shell (shellcheck) (push) Successful in 12s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Failing after 1m11s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 13:41:59 -04:00
jared 4048659e28 commands: remove deleted models from display map
Lint / Shell (shellcheck) (push) Successful in 16s
Lint / JS (eslint) (push) Successful in 8s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 1m9s
Lint / Secret scan (gitleaks) (push) Successful in 5s
lotusllm, lotusllmben, and llama3.3 70B have been removed from
Ollama on LXC 130 to free ~44 GB disk space.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 00:41:02 -04:00
jared f77fdbc7bb commands: improve model display names with variant labels
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 1m10s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Add uncensored/abliterated tags and accurate parameter counts
to all model display names.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 00:38:37 -04:00
jared bfedd34f1f models: 8ball → llama3.2-abliterate 3B, ask/fortune → phi4-mini
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 8s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Successful in 1m11s
Lint / Secret scan (gitleaks) (push) Successful in 12s
- BALL_MODEL: huihui_ai/llama3.2-abliterate:3b (abliterated 3B,
  follows complex persona instructions without censorship)
- ASK_MODEL + OLLAMA_MODEL: phi4-mini:latest (Phi-4 Mini 3.8B,
  best instruction-following model available within GPU VRAM)
- Update _MODEL_DISPLAY for new model names

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 00:33:20 -04:00
jared 21a64174e6 8ball: fix substring pronoun bug, switch to 3B model
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 1m27s
Lint / Secret scan (gitleaks) (push) Successful in 7s
- Fix about_jared/about_wynter using substring match — "they" matched
  "he", "theme" matched "he", etc., routing Wynter's questions to the
  wrong branch. Now uses \b word boundaries via re.search.
- Switch BALL_MODEL default from sadiq-bd 1B uncensored to
  llama3.2:latest (3B) — the 1B model hallucinates, ignores persona
  instructions, and mentions Jared randomly. GPU is now working on
  Arc A380 at ~25 tok/s so the larger model is practical.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 00:21:42 -04:00
jared f7ca1b00db ask: switch to llama3.2:latest, increase timeout to 120s
Lint / Shell (shellcheck) (push) Successful in 12s
Lint / JS (eslint) (push) Successful in 8s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 1m10s
Lint / Secret scan (gitleaks) (push) Successful in 5s
gemma3:latest produces garbage output on the Vulkan backend (Intel Arc A380).
llama3.2:latest runs correctly at 100% GPU. Timeout bumped to 120s to handle
cold model loads (~22s) without timing out.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 22:49:08 -04:00
jared 1ba1151673 help: move 8ball from AI to Games category
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 1m18s
Lint / Secret scan (gitleaks) (push) Successful in 5s
8ball is only AI-powered for specific users (Wynter/Jared); for everyone
else it's a random static response. Games is the correct category.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 19:32:43 -04:00
jared 05c83e8ad1 8ball: suppress model attribution on fallback, vary fallback responses
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 8s
Lint / Python (ruff) (push) Successful in 6s
Lint / Python deps (pip-audit) (push) Successful in 1m10s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Model attribution is now only shown when the LLM actually generated the
response. If the model refused or gave an invalid answer and we fell back
to the static response, no 'via ...' line is shown.

Fallback responses for all three Wynter branches are now randomised pools
so the bot doesn't always give the same flat yes/no phrase regardless of
what Wynter actually typed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 19:29:20 -04:00
jared 43903af22e Improve help command, model attribution, and model config
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 8s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Successful in 1m25s
Lint / Secret scan (gitleaks) (push) Successful in 5s
help: grouped into AI / Games / Random / Server categories with Option B
purple header; descriptions auto-pulled from the command registry.

Model attribution: added _MODEL_DISPLAY map so 'via lotusllm' becomes
'via Llama 3.2 1B', 'via gemma3:latest' becomes 'via Gemma 3 4B', etc.

Config: OLLAMA_MODEL switched from lotusllm to llama3.2:latest; added
BALL_MODEL (sadiq-bd/llama3.2-1b-uncensored) as a dedicated config var
for the 8ball so it stays on the uncensored model without affecting fortune.

Descriptions: fortune -> AI-generated fortune cookie; ask -> Ask LotusBot;
health -> Bot health & stats (admin only).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 19:27:14 -04:00
jared bb5307c06b 8ball: address Wynter in second person when she's the asker
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 9s
Lint / Python deps (pip-audit) (push) Successful in 1m8s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Responding 'Wynter is too busy...' in third person to someone who just
asked 'will I...' feels disconnected. Changed the prompt to speak
directly to Wynter using you/your, with her name used only for emphasis.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 19:15:45 -04:00
jared 6f5964ffe5 8ball: force name usage over she/her pronouns for Wynter
Lint / Shell (shellcheck) (push) Successful in 11s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Secret scan (gitleaks) (push) Has been cancelled
Lint / Python deps (pip-audit) (push) Has been cancelled
The LLM was responding with 'She's far too busy...' instead of using
'Wynter' by name. Added explicit instruction to both Wynter branches
to always refer to her by name and never use she/her pronouns.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 19:14:33 -04:00
jared 639689bc0d Style: Option B HTML styling across all AI commands
Lint / Shell (shellcheck) (push) Successful in 18s
Lint / JS (eslint) (push) Successful in 14s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 2m0s
Lint / Secret scan (gitleaks) (push) Successful in 7s
8ball: color-coded answer text (green=positive, red=negative, amber=neutral)
for both the random and Jared/Wynter AI branches; question shown as small
italic below the answer; AI responses include model attribution.

fortune: teal header, answer in blockquote italics, model attribution shown
only when response came from the LLM (not the static fallback list).

ask: purple header, question in italic, response in blockquote, model
attribution at bottom.

trivia: blue header with category, green reveal answer, model attribution
shown only for LLM-generated questions (not static fallbacks).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 17:52:16 -04:00
jared 58d8987e32 README: remove stale phase status line
Lint / Shell (shellcheck) (push) Successful in 13s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 6s
Lint / Python deps (pip-audit) (push) Successful in 1m10s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 17:16:44 -04:00
jared ef9ff1106c README: remove Priority Order section, drop vCPUs from infra table
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Has been cancelled
Lint / Python deps (pip-audit) (push) Has been cancelled
Lint / Secret scan (gitleaks) (push) Has been cancelled
Priority Order is stale project tracking that doesn't belong in a README.
vCPUs removed from the infrastructure table — containers are HA and can
migrate between physical hosts so pinning a CPU model is misleading.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 17:16:15 -04:00
jared e14b9a274f ask: instruct LLM not to ask follow-up questions
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 1m6s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Each !ask call is stateless — no context is retained between commands,
so ending a response with a question is misleading. Added explicit
instruction to the system prompt to prevent this.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 17:10:26 -04:00
jared 637b2a4b20 Upgrade fortune, ask, and trivia commands to use Ollama LLM
Lint / Shell (shellcheck) (push) Successful in 11s
Lint / JS (eslint) (push) Successful in 8s
Lint / Python (ruff) (push) Successful in 6s
Lint / Python deps (pip-audit) (push) Successful in 1m36s
Lint / Secret scan (gitleaks) (push) Successful in 5s
fortune: generates a fresh witty one-liner via Ollama on every call,
falls back to static list if LLM is unavailable.

ask: switched to /api/chat endpoint with a system prompt for better
conversational quality; now uses ASK_MODEL (default: gemma3:latest)
separately from the 8ball OLLAMA_MODEL so each can be tuned independently.

trivia: LLM generates a fresh question each time (no more repeating the
same 25 questions); supports !trivia <category> with six categories
(gaming, tech, general, movies, music, science); falls back to static
questions if JSON generation fails.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 17:07:01 -04:00
jared 86cb78d74d Fix ruff lint errors across matrixbot (F401, F841, E402)
Lint / Shell (shellcheck) (push) Successful in 11s
Lint / JS (eslint) (push) Successful in 10s
Lint / Python (ruff) (push) Successful in 10s
Lint / Python deps (pip-audit) (push) Successful in 1m10s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Remove unused imports: logging from bot.py and config.py, RoomMessageText/
UnknownEvent from callbacks.py, functools.partial and MAX_INPUT_LENGTH from
commands.py. Rename unused local variables to _ (resp in cmd_ping, symbols in
render_keyboard_plain, guesses_left in two wordle functions). Move wordle import
to top of commands.py to fix E402.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 16:54:55 -04:00
jared d2983eca23 Fix ruff binary extraction; fix gitleaks to scan app dirs only
Lint / Shell (shellcheck) (push) Successful in 13s
Lint / JS (eslint) (push) Successful in 10s
Lint / Python (ruff) (push) Failing after 8s
Lint / Python deps (pip-audit) (push) Successful in 1m18s
Lint / Secret scan (gitleaks) (push) Successful in 5s
- ruff: add --strip-components=1 to tar extract; the tarball puts the
  binary inside ruff-x86_64-unknown-linux-gnu/ not at the root
- gitleaks: path-based allowlists are broken in v8.21.2 --no-git mode
  (tested down to bare substrings — still fires). Switched to scanning
  only application code directories (matrixbot/, hookshot/, .gitea/,
  systemd/, cinny/, landing/) which excludes deploy/ where the
  intentional Gitea webhook HMAC secrets live. Also removed the
  .gitleaks-baseline.json from the repo (it was flagging itself).
  The .gitleaks.toml is kept for any future per-rule overrides.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 16:48:06 -04:00
jared 78d1645f08 Fix all CI jobs: ruff binary, pip-audit venv, gitleaks baseline
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Failing after 4s
Lint / Python deps (pip-audit) (push) Successful in 1m5s
Lint / Secret scan (gitleaks) (push) Failing after 5s
- ruff: download standalone binary instead of using python3 -m ruff
  (runner image lacks the PATH entry for pip-installed bin scripts)
- pip-audit: add python3-venv to apt install (pip-audit creates a venv
  internally to resolve deps; ensurepip was missing)
- gitleaks: switch from stopwords allowlist to --baseline-path approach.
  Stopwords don't suppress findings from git history scans. The baseline
  records the 4 known-intentional webhook HMAC secrets; CI now only
  fails on findings NOT in the baseline (i.e. newly introduced secrets)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 16:36:59 -04:00
jared 371ed8116f Fix Python runner; add gitleaks secret scanning
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Failing after 42s
Lint / Python deps (pip-audit) (push) Failing after 47s
Lint / Secret scan (gitleaks) (push) Failing after 9s
- All Python jobs now install python3-pip via apt first (runner image
  has no pip by default)
- Added secret-scan job: gitleaks v8.21.2 scans full git history on
  every push/PR with --redact to avoid leaking found secrets in logs
- Added .gitleaks.toml allowlisting deploy/hooks-lxc*.json files
  (webhook HMAC secrets are intentional config, not leaks)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 16:29:14 -04:00
jared d49b33fc42 Fix pip → python3 -m pip in ruff job; add pip-audit dep scan
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 9s
Lint / Python (ruff) (push) Failing after 6s
Lint / Python deps (pip-audit) (push) Failing after 7s
- python3 -m pip works in the act runner where bare 'pip' isn't in PATH
- Added python-audit job: pip-audit checks matrixbot/requirements.txt
  against the OSV database for known CVEs on every push/PR

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 16:26:03 -04:00
jared 0e76c8b51c Fix Jared-asks-about-Wynter branch; add Python lint to CI
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Failing after 7s
- When Jared asks a question containing Wynter's name, it now uses a
  dedicated mock-Wynter prompt instead of the generic positive-Jared
  one. The _is_positive_about_jared guard is also skipped for this
  branch so negative words aimed at Wynter don't trigger the fallback.
  Fallback changed from "Jared is absolutely right!" (nonsensical for
  Wynter questions) to "Sounds about right — Wynter had it coming."
- Added ruff Python lint job to .gitea/workflows/lint.yml covering
  matrixbot/ on every push and PR.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 16:23:59 -04:00
jared b9a251bd7a Integrate matrixbot into existing LXC 151 deploy hook
Lint / Shell (shellcheck) (push) Successful in 11s
Lint / JS (eslint) (push) Successful in 6s
Removed standalone matrixbot/deploy.sh — deploy is handled by the existing
webhook system. Added matrixbot/ block to deploy/lxc151-hookshot.sh: on push,
if any matrixbot/ file changed, source files are synced to /opt/matrixbot and
matrixbot.service is restarted automatically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 16:18:10 -04:00
jared 52c4781e64 Add matrixbot source to repo
All bot source files from LXC 151 (/opt/matrixbot) are now tracked here.
Secrets (.env, credentials.json), venv dirs, and runtime state files
(nio_store, welcome_state.json, wordle_stats.json) are excluded via .gitignore.
Includes deploy.sh to sync files to /opt/matrixbot and restart the service.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 16:16:38 -04:00
jared a559e98d82 Security hardening: TURN peer restriction, TCP relay, rate limits
Lint / Shell (shellcheck) (push) Successful in 14s
Lint / JS (eslint) (push) Successful in 9s
- coturn allowed-peer-ip scoped from 10.10.10.0/24 → 10.10.10.29 only
  (prevents TURN relay being used to reach other internal LXCs)
- coturn no-tcp-relay=true (UDP only; TCP relay was an SSRF vector)
- Added rc_joins (local: 0.1/s burst 3, remote: 0.01/s burst 3)
- Added rc_joins_per_room (1/s burst 3)
- Added rc_invites (per_room: 0.3/s burst 10, per_user: 0.003/s burst 5)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 13:39:03 -04:00
jared 5bb62db222 Fix ToS consent enforcement — disable require_at_registration
Lint / Shell (shellcheck) (push) Successful in 16s
Lint / JS (eslint) (push) Successful in 7s
Previously require_at_registration=true caused Cinny to silently complete
the m.login.terms UIA step during registration (~34ms), meaning users were
auto-consented without ever seeing the ToS page.

Setting require_at_registration=false removes the UIA step from registration.
New users start with NULL consent and are blocked by block_events_error on
first message send. Synapse sends a Server Notice DM with the /_matrix/consent
URL, which they must explicitly visit and submit before messaging is unblocked.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 12:54:43 -04:00
jared 08651fcbda docs: add CI lint badge to README
Lint / Shell (shellcheck) (push) Successful in 8s
Lint / JS (eslint) (push) Successful in 7s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 16:27:33 -04:00
jared 735c1eb30e ci: add lint workflow, shellcheck fixes, and CI failure hookshot alert
Lint / Shell (shellcheck) (push) Has been cancelled
Lint / JS (eslint) (push) Has been cancelled
- .gitea/workflows/lint.yml: new workflow running shellcheck on .sh files
  and eslint on hookshot/ JS transform scripts
- hookshot/.eslintrc.json: declare data/result as hookshot globals
- hookshot/ci-alert.js: new Matrix hookshot transform for CI failure alerts
- hookshot/deploy.sh: fix SC2155 (split local/assign), SC2034 (remove unused var)
- systemd/livekit-clear-port.sh: fix SC2148 (invalid shebang escape)
- cinny/dev-update.sh: fix SC2115 (use ${WEB_ROOT:?} to guard rm -rf)
- deploy/lxc151-hookshot.sh: add shellcheck source=/dev/null for sourced file
- .gitignore: ignore node_modules/
- package.json + package-lock.json: eslint@8 dev dependency

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 16:25:39 -04:00