100 Commits
Author SHA1 Message Date
jaredandClaude Opus 4.8 c15a48971d deploy(cinny): follow origin/lotus HEAD while gating on CI
Lint / JS (eslint) (push) Successful in 14s
Lint / Python (ruff) (push) Successful in 26s
Lint / Python deps (pip-audit) (push) Successful in 1m18s
Lint / Secret scan (gitleaks) (push) Successful in 20s
Lint / Shell (shellcheck) (push) Successful in 12s
Companion to cinny's `concurrency: cancel-in-progress`. The poll loop latched
origin/lotus once at startup; with CI cancel-in-progress a superseded run's
status flips to error/failure, so polling the latched (now-cancelled) SHA would
abort and — with the flock skipping the newer push's deploy — strand the newest
commit undeployed (a deploy freeze, the exact class this script fought before).

- Re-resolve origin/lotus each poll iteration; retarget the CI gate to HEAD if
  it advanced (fresh MAX_WAIT window).
- On a failure/error status, re-check HEAD before aborting — only a genuine
  failure of the CURRENT HEAD aborts; a superseded/blip SHA is followed instead.
- Reset to the gated $COMMIT_SHA (not a bare origin/lotus that may have advanced
  past the gate after the loop) so we build exactly what passed CI.

shellcheck clean; reviewed (SHIP).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 22:09:30 -04:00
jaredandClaude Opus 4.8 3835ce4020 docs: document on-device message translation
Add the translation feature to the landing page (Newest July 2026
prose + comparison-table row) and the README custom-features table.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 16:19:01 -04:00
jaredandClaude Opus 4.8 d9dfc54200 fix(cinny): restore gifApiKey placeholder + redact leaked key from README
Lint / Shell (shellcheck) (push) Successful in 29s
Lint / JS (eslint) (push) Successful in 5s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 34s
Lint / Secret scan (gitleaks) (push) Successful in 5s
The production config.json (cp'd from cinny/config.json by deploy/lxc106-cinny.sh)
lost its "gifApiKey": "" placeholder, so lotus_deploy.sh's sed injection had no
field to fill -> the GIF composer button disappeared (it renders only when
gifApiKey is non-empty). Restore the placeholder so future deploys inject the key.

Also redact the real Giphy key that was committed in the README (it belongs only in
/etc/lotus-deploy.env on LXC 106). NOTE: the key remains in git history (commit
f3a7bcd) — it should be rotated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 00:56:47 -04:00
jaredandClaude Opus 4.8 6d5583398b docs: document cinny inline media embeds
- README Custom Features: 'Inline media embeds' row (16 providers, facade, CSP
  note incl. the live LXC 106 frame-src allowlist vs the repo wildcard fallback).
- landing: add inline media embeds to the July 2026 feature list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 12:13:02 -04:00
jaredandClaude Opus 4.8 b72d6620cc chore(nginx): widen CSP frame-src to https: for room widgets (MSC1236)
Lint / Shell (shellcheck) (push) Successful in 8s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 47s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Room widgets embed arbitrary third-party https pages in a sandboxed iframe;
frame-src was 'self' + openstreetmap only. Apply + nginx -s reload.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 13:27:23 -04:00
jaredandClaude Opus 4.8 64262b39ec chore(nginx): drop api.qrserver.com from CSP (invite QR now generated locally)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 22:19:22 -04:00
jaredandClaude Opus 4.8 6293a62e47 feat(nginx): add HSTS + Permissions-Policy to chat.lotusguild.org (P6-4)
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 6s
Lint / Python deps (pip-audit) (push) Successful in 31s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Adds Strict-Transport-Security (2y, includeSubDomains, preload) and a
Permissions-Policy that allows only the features the app uses (camera/mic/
display-capture for calls, geolocation for location share, autoplay/fullscreen/
encrypted-media) and denies the rest. Complements the existing X-Frame/CSP/
Referrer headers.

Apply: reload nginx on the LXC. TLS terminates upstream (listen 80), so verify
the header reaches the browser (front proxy must pass it through) — else set
HSTS at the TLS terminator. Verify a call + location share still work.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 14:41:08 -04:00
jaredandClaude Opus 4.8 7618b3b091 docs: Slack-style per-thread notifications (P4-1)
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 31s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Landing: thread row + prose note the participating-default notifications with
per-thread All/Mentions/Mute. README: Lotus Cinny threads row extended.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 22:41:04 -04:00
jaredandClaude Fable 5 d344b9b4b5 fix(ci): make the SC1091 suppression in lotus_deploy.sh actually apply
Lint / Shell (shellcheck) (push) Successful in 7s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 32s
Lint / Secret scan (gitleaks) (push) Successful in 4s
Shellcheck directives bind to the NEXT command; on the compound line
`set -a; source /etc/lotus-deploy.env; set +a` the existing
`# shellcheck disable=SC1091` bound to `set -a`, so the info-level SC1091
finding on the runtime-only env file still failed the lint workflow
(find -exec shellcheck exits non-zero on any finding). Split the line so the
directive sits directly above `source` (as `source=/dev/null`, the standard
idiom for host-only env files). Verified with CI's exact invocation:
`find . -name "*.sh" -exec shellcheck {} +` now exits 0 (shellcheck 0.9.0).

No runtime behavior change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-01 22:19:39 -04:00
jaredandClaude Opus 4.8 d9585f13f1 docs: July 2026 client batch — threads, math, search cache, session hardening
- landing: Threads row upgraded to ✓ (full side panel + unread chips); prose
  sentence for the new batch (threads, KaTeX math, opt-in encrypted-search
  index, session hardening, crypto diagnostics).
- README: two new rows in the Lotus Cinny custom-features table.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 21:48:34 -04:00
jaredandClaude Opus 4.8 daa532835f docs: advertise the Lotus Chat desktop app (native features)
Lint / Shell (shellcheck) (push) Failing after 8s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 37s
Lint / Secret scan (gitleaks) (push) Successful in 8s
- landing/index.html: desktop-app sentence in the feature prose + a "Desktop App"
  comparison-table section (rich toasts click/reply, jump list, taskbar + volume
  controls, Focus Assist DND, no-sleep, recursive folder upload).
- README.md: a "Desktop app (Tauri)" row in the Lotus Cinny custom-features table.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 10:06:13 -04:00
jaredandClaude Opus 4.8 8481610066 docs(call): document soundboard/quality/permissions (README table + landing)
Lint / Shell (shellcheck) (push) Failing after 32s
Lint / Python (ruff) (push) Successful in 10s
Lint / Python deps (pip-audit) (push) Successful in 36s
Lint / Secret scan (gitleaks) (push) Successful in 8s
Lint / JS (eslint) (push) Failing after 13m15s
- README Custom Features table: add rows for the in-call soundboard (P5-15),
  call quality controls, and room call-permissions (P5-31).
- landing: mention the soundboard, per-user quality controls, and
  server-enforced room call-permissions in the feature blurb.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 22:43:49 -04:00
jaredandClaude Opus 4.8 be8e728034 docs(landing): note self-built Element Call fork + 4 on-device denoise models
Lint / Shell (shellcheck) (push) Failing after 10s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 37s
Lint / Secret scan (gitleaks) (push) Successful in 6s
Update the client-comparison copy to reflect that calls run our self-built
Element Call fork and that the ML noise-suppression tier offers RNNoise, Speex,
DTLN, and DeepFilterNet 3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 22:34:34 -04:00
jaredandClaude Opus 4.8 a06f2c662a feat(livekit-guard): enforce per-room call permissions (screenshare/camera)
Extend voice-limit-guard to enforce a per-room publish-source policy
(io.lotus.room_quality allow_screenshare/allow_camera) for ALL Matrix clients,
alongside the existing participant limit.

- At token issue, re-sign the LiveKit JWT's canPublishSources to drop forbidden
  sources (microphone always kept). Verifies our own secret signed the token
  first and fails open on mismatch, so a secret drift can never mint a token the
  SFU rejects. Limit check and source policy are independent (one's outage can't
  skip the other).
- Live (mid-call) enforcement: a background reconcile loop calls LiveKit
  UpdateParticipant to revoke a forbidden source from participants who joined
  before the policy changed -- which unpublishes their in-progress
  screenshare/camera server-side within ~3s and blocks re-publish. Only removes
  sources (never grants), preserves other permission flags, fails open, and runs
  as a daemon thread that cannot crash or block token issuance.
- Endpoint-specific room-id extraction (/get_token->room_id, /sfu/get->room) so
  a client sending both keys can't get a different room's policy applied.
- Auto-deploy the guard on LXC 151 (py_compile-gated, backup + rollback).
- Unit tests: JWT re-sign/verify + tamper, secret-mismatch, source narrowing,
  reconcile (never-grant / preserve-flags / disable-on-empty), fail-open.

Numeric bitrate/fps caps are NOT server-enforceable on an SFU (LiveKit forwards,
never transcodes) and remain a Lotus-client-cooperative setting; the
screenshare/camera permission is the hard cross-client lever.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 22:34:34 -04:00
jaredandClaude Opus 4.8 1a7ec2b0d6 cinny: drop dead lotus-deploy.sh install block from lxc106-cinny.sh
The cinny/lotus-deploy.sh (hyphen) force-deploy variant was an untracked,
redundant duplicate of the CI-gated cinny/lotus_deploy.sh (underscore) added in
c13549f. It's been removed, so its install block here referenced a file that no
longer exists. The CI-gated lotus_deploy.sh is the single source of truth for
the webhook web deploy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 18:28:02 -04:00
jaredandClaude Opus 4.8 c13549f3da cinny: harden + version-control the webhook web-deploy (lotus_deploy.sh)
Lint / Python (ruff) (push) Successful in 21s
Lint / Python deps (pip-audit) (push) Successful in 50s
Lint / Secret scan (gitleaks) (push) Successful in 7s
Lint / Shell (shellcheck) (push) Failing after 14s
Lint / JS (eslint) (push) Successful in 24s
The live /usr/local/bin/lotus_deploy.sh (the `lotus-deploy` webhook target) was
never under version control and had rotted into two deploy-killing bugs that
froze chat.lotusguild.org on an old build:

1. CI gate: it waited on the WHOLE workflow run with a 15-min cap. Web CI shares
   the single act_runner with the slow Tauri desktop builds, so a web run could
   sit queued >15 min -> "result: timeout" -> deploy aborted. Now it gates only
   on the "Build & Quality Checks" commit-status context (build + unit tests),
   decoupled from "Trigger Desktop Build", and waits up to 45 min.

2. Dead element-call copy: `cp node_modules/@element-hq/element-call-embedded/...`
   under `set -e` aborted every deploy after the widget was forked to
   @lotusguild/element-call-embedded. The build already emits dist/public/
   element-call; replaced the copy with a presence check.

Also: rsync now excludes config.json so the app deploy stops clobbering the
production runtime config (homeserver list / allowCustomHomeservers) that the
matrix repo owns. lxc106-cinny.sh now installs this script (syntax-checked).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 18:10:10 -04:00
jaredandClaude Opus 4.8 d6fd323262 cinny: enable mozilla.org (OIDC/next-gen-auth homeserver)
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 21s
Lint / Python (ruff) (push) Successful in 15s
Lint / Python deps (pip-audit) (push) Successful in 59s
Lint / Secret scan (gitleaks) (push) Successful in 9s
Now that the client supports MSC3861 OIDC login, add mozilla.org to the
homeserverList and its origins to the CSP. mozilla delegates: homeserver ->
mozilla.modular.im, OIDC issuer -> chat.mozilla.org, identity -> vector.im.
- connect-src += mozilla.org mozilla.modular.im chat.mozilla.org vector.im
- img-src += mozilla.org mozilla.modular.im
Applied live to LXC 106 and synced here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 16:58:48 -04:00
jaredandClaude Opus 4.8 b39e3594d5 cinny: allow matrix.org media in CSP img-src
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 5s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 36s
Lint / Secret scan (gitleaks) (push) Successful in 6s
Federated matrix.org users load avatars/images from their own media endpoint
(matrix-client.matrix.org), which img-src still blocked — so every avatar
tripped a CSP violation. Add https://matrix.org + https://*.matrix.org to
img-src to match connect-src. (media-src already allows https: so video/audio
were fine.) Applied live to LXC 106 and synced here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 14:49:08 -04:00
jaredandClaude Opus 4.8 40ceb43672 cinny: version-control the production nginx site config
Lint / Shell (shellcheck) (push) Successful in 7s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 50s
Lint / Secret scan (gitleaks) (push) Successful in 9s
The chat.lotusguild.org nginx config (LXC 106) was edited directly on the box
and never tracked — which is how its CSP drifted (kept a dead Sentry URL and
blocked matrix.org logins). Snapshot it as cinny/nginx.conf (verbatim from prod,
incl. the corrected connect-src that now allows matrix.org/*.matrix.org) and
deploy it via lxc106-cinny.sh: back up the live file, swap, `nginx -t`, and
reload only on success (auto-restore the backup if validation fails, so a bad
config can't take the site down). TLS terminates at the NPM proxy, so this is a
plain HTTP server block with no secrets.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 13:14:49 -04:00
jaredandClaude Opus 4.8 45444e5118 cinny: allow matrix.org logins on the Lotus client
Lint / Shell (shellcheck) (push) Successful in 12s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 1m14s
Lint / Secret scan (gitleaks) (push) Successful in 9s
Add matrix.org to homeserverList so federated friends with matrix.org accounts
can sign into chat.lotusguild.org. defaultHomeserver stays 0 (lotusguild), and
allowCustomHomeservers stays false — only the two listed servers are selectable,
so the client isn't opened up to arbitrary homeservers.

Deploys via lxc106-cinny.sh (cp -> /var/www/html/config.json); lotus-build.sh
preserves the live config across app rebuilds, so this is the authoritative copy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 11:27:43 -04:00
jaredandClaude Opus 4.8 3fe232a6b7 docs: note planned Element Call fork (Lotus Call)
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 34s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Tag the EC embed row and add a callout explaining the plan to fork
element-hq/element-call and self-build it for true ownership (decorations,
focus/screenshare, reconnect mic, theming, call-audio injection — all unfixable
against the prebuilt @element-hq/element-call-embedded bundle). Infra notes:
EC uses our LiveKit SFU (livekit/, LXC 151) + lk-jwt-service; a new build/deploy
pipeline will be needed. Full plan: LotusGuild/cinny → HANDOFF_ELEMENT_CALL_FORK.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 20:57:44 -04:00
jaredandClaude Opus 4.8 8c9edf60c3 docs: bump Element Call reference to 0.20.1
Lint / Shell (shellcheck) (push) Successful in 7s
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 11s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 04:18:43 -04:00
jaredandClaude Opus 4.8 52e9be1f8d docs: bump Element Call to 0.19.4; add noise suppression to landing
Lint / Shell (shellcheck) (push) Successful in 8s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Successful in 33s
Lint / Secret scan (gitleaks) (push) Successful in 6s
- README: correct embedded Element Call version 0.19.3 -> 0.19.4 in the
  Custom Features and Tech Stack tables
- landing/index.html: add a "Noise suppression" row to the Voice & Video
  comparison table (Lotus = 3 tiers incl. on-device RNNoise ML) and note
  the feature in the June 2026 narrative

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 20:30:07 -04:00
jaredandClaude Sonnet 4.6 442ad9b6ed docs: add avatar decorations to Lotus Chat feature description
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 12s
Lint / Python (ruff) (push) Successful in 24s
Lint / Python deps (pip-audit) (push) Successful in 1m25s
Lint / Secret scan (gitleaks) (push) Successful in 4s
99 curated APNG overlay frames stored in user Matrix profile (MSC4133),
visible to other Lotus Chat users in real time across timeline, members
list, and @mention autocomplete. Includes the Lotus Flower decoration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 12:03:00 -04:00
jaredandClaude Fable 5 68a6acfa24 feat: hard cross-client voice channel limits via voice-limit-guard
Lint / Shell (shellcheck) (push) Successful in 7s
Lint / JS (eslint) (push) Successful in 5s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Successful in 1m1s
Lint / Secret scan (gitleaks) (push) Successful in 4s
Add a fail-open Python sidecar (livekit/voice-limit-guard.py) that fronts
lk-jwt-service to enforce per-room voice participant caps for ALL Matrix
clients, not just Lotus Chat:
- lk-jwt-service moved to :8071 (systemd drop-in), guard owns :8070 so NPM's
  existing /sfu/get + /get_token proxy targets are unchanged
- guard reads io.lotus.voice_limit.max_users (Synapse admin API, cached),
  forwards to lk-jwt-service, and on an issued token decodes the LiveKit alias
  + requester, counts distinct Matrix users via LiveKit ListParticipants, and
  returns 403 when the room is full (rejoins/extra devices allowed)
- any error fails open (returns upstream response) so calls never break
- systemd/voice-limit-guard.service; README documents ports, setup, revert

Also update landing page: voice limit is now server-enforced for all clients.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 23:45:41 -04:00
jaredandClaude Fable 5 295a072dc9 docs: add voice channel user limit + call join/leave sounds to landing page
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 22:20:46 -04:00
jaredandClaude Sonnet 4.6 b392798e3f docs: add AFK auto-mute and knock admin badge to landing page
- Feature description paragraph: added AFK auto-mute (1–30 min voice idle
  timeout) and knock-to-join admin badge (live count on Members button)
- Comparison table: new AFK auto-mute row in Voice & Video section

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 21:38:20 -04:00
jaredandClaude Sonnet 4.6 130a7334a3 docs: add animated backgrounds + glassmorphism fix to landing page
Lint / Shell (shellcheck) (push) Successful in 23s
Lint / JS (eslint) (push) Successful in 12s
Lint / Python (ruff) (push) Successful in 7s
Lint / Python deps (pip-audit) (push) Successful in 37s
Lint / Secret scan (gitleaks) (push) Successful in 6s
New table row for 5 animated CSS wallpapers (rain, stars, grid pulse,
aurora, fireflies). Feature blurb updated to mention the animated
backgrounds and the glassmorphism body-background fix.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 13:12:45 -04:00
jaredandClaude Sonnet 4.6 68e922d386 docs: quick reactions 5 → 3 in feature table and blurb
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 32s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 00:33:55 -04:00
jaredandClaude Sonnet 4.6 86ad28933a docs: add glassmorphism, presence ring, emoji prefix to feature list
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 49s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 22:02:33 -04:00
jaredandClaude Sonnet 4.6 85eab8f54c docs: add quick emoji reactions, in-app toasts rows; extend June 2026 feature list
Lint / Shell (shellcheck) (push) Successful in 8s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 36s
Lint / Secret scan (gitleaks) (push) Successful in 6s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 21:32:48 -04:00
jaredandClaude Sonnet 4.6 f65e56d06d docs: update landing page with GIF preview, policy lists, collapsible messages, send animation, context menu
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 7s
Lint / Python deps (pip-audit) (push) Successful in 33s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Adds inline GIF preview and collapsible long messages rows to the
feature comparison table; extends the June 2026 feature list with all
five newly completed items (P3-5, P3-9, P5-19, P5-23, P5-26).
Includes pre-staged README additions for presence tracking, encrypted
search, privacy settings, draft persistence, and PiP persistence.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 20:57:18 -04:00
jaredandClaude Sonnet 4.6 60c215c63d feat: add export history, scheduling, bookmarks rows; update feature list
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 6s
Lint / Python deps (pip-audit) (push) Successful in 34s
Lint / Secret scan (gitleaks) (push) Successful in 4s
New table rows (UX & Extras section):
- Export room history: Lotus ✓ (txt/json/html, date range, E2EE), Element ✓
- Message scheduling: Lotus ✓ (MSC4140), Element ~, others ✗
- Message bookmarks: Lotus ✓, Element ✓, others ✗

also-available paragraph: prepended June 2026 feature groups — message
scheduling, saved messages, history export, activity/mod log, server ACL
editor, room stats, opt-in compression, 13 domain-specific URL preview
cards (YouTube, TikTok, Twitch, Reddit, X/Twitter, Spotify, Steam, IMDb,
Vimeo, GitHub, Discord, npm, Stack Overflow)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 12:40:31 -04:00
jared cfb8b78e7c feat: add custom sounds, quiet hours, room sort to comparison table 2026-06-03 20:32:46 -04:00
jaredandClaude Sonnet 4.6 12a6e7410d docs: update landing page for P1 features — polls create, voice speed, new rows
- Polls: "display & vote" → "create, vote & display; single or multiple choice"
- Voice messages: add 0.75×/1×/1.5×/2× speed note
- 4 new UX & Extras table rows: Media Gallery, Sidebar filter, Favorite rooms, Invite link+QR
- also-available paragraph expanded with all P1 additions
- Comparison date updated to "June 2026 (updated)"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 10:45:04 -04:00
jaredandClaude Sonnet 4.6 5539f1f1fd docs: update landing page for June 2026 features
- Update comparison table date to June 2026
- Add push-to-deafen (M key), night light filter, message length
  counter, and TDS orange typing dots to also-available paragraph
- PTT row notes M = push-to-deafen
- Add Night Light row to UX & Extras comparison table

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 18:47:40 -04:00
jaredandClaude Sonnet 4.6 fee26621bc docs: add who-reacted row and expand also-available feature list
Lint / Shell (shellcheck) (push) Successful in 18s
Lint / JS (eslint) (push) Successful in 18s
Lint / Python (ruff) (push) Successful in 12s
Lint / Python deps (pip-audit) (push) Successful in 49s
Lint / Secret scan (gitleaks) (push) Successful in 15s
- New comparison table row: "Who reacted" with hover tooltip + avatar modal
- also-available paragraph now mentions emoji/sticker picker, pinned messages
  panel, and who-reacted viewer explicitly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 23:07:47 -04:00
jaredandClaude Sonnet 4.6 1580e11dc5 docs: upgrade encrypted search row for Lotus Chat and add notes
Lint / Shell (shellcheck) (push) Successful in 8s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 35s
Lint / Secret scan (gitleaks) (push) Successful in 5s
- Lotus Chat: ~ → ✓ (local cache scan + load-more buttons is a working
  encrypted search feature, not a partial)
- Cinny upstream: added note clarifying it's server-only, no E2EE
- Commet: already ✓, added note that it auto-fetches + decrypts history
  (confirmed via PR #348 and v0.3.0 release notes)
- FluffyChat: added 'cache scan only' note
- Nheko: added 'local DB scan' note

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 22:31:54 -04:00
jaredandClaude Sonnet 4.6 f0a51b8a86 docs: correct presence tracking data based on per-client research
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Successful in 36s
Lint / Secret scan (gitleaks) (push) Successful in 5s
- Cinny upstream: ✗ → ~ (manual AFK only, auto-detection PR unmerged)
- Commet: basic → partial (inactivity monitor shipped Oct 2025, PR #475)
- Element Web/Desktop: 'no idle detection' → partial; 3-min idle timer
  shipped Nov 2023 (matrix-react-sdk PR #11824), but no tab detection,
  no offline-on-close, no user hide toggle
- FluffyChat, Element X, Nheko: basic confirmed, no change

Sources: matrix-react-sdk PR #11824, Commet PR #475, Cinny issue #2395

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 21:45:08 -04:00
jaredandClaude Sonnet 4.6 b30d3138e4 docs: update landing page for May 2026 feature additions
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 31s
Lint / Secret scan (gitleaks) (push) Successful in 8s
- Feature paragraph: add full presence tracking details, encrypted
  search with load-more buttons, auto-clear status, privacy section
- Custom status row: mention auto-clear timer and 64-char limit
- Encrypted search row: clarify per-room load-more + oldest date
- New row: Online presence tracking (idle/away auto-detection) —
  shows Lotus Chat leads all web Matrix clients on this

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 20:58:44 -04:00
jaredandClaude Sonnet 4.6 85ca1ca8a1 docs: document screenshare/PTT/status features in README + landing page
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 58s
Lint / Secret scan (gitleaks) (push) Successful in 4s
README.md:
- Replaced the stale 'Auto-revert spotlight on screenshare' entry
  (that 600ms revert-to-grid code was removed — it caused fullscreen
  to show avatars instead of the screenshare)
- Added accurate entries for all four features added this cycle:
  Screenshare fullscreen, PiP screenshare focus, Screenshare audio
  mute, Custom status message

landing/index.html:
- Updated Lotus Fork feature description paragraph to mention
  screenshare fullscreen, screenshare audio mute, PTT, and custom
  status messages
- Added PTT row to Voice & Video comparison table
- Updated Screenshare row for Lotus Chat to note fullscreen + audio mute
- Added 'Custom status message' row to UX & Extras section

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 12:40:02 -04:00
jaredandClaude Sonnet 4.6 b609497179 docs: document /get_token nginx proxy and NPM override risk
Lint / Shell (shellcheck) (push) Successful in 7s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 51s
Lint / Secret scan (gitleaks) (push) Successful in 10s
LXC 139 NPM proxy host 49 now proxies both /sfu/get and /get_token
to lk-jwt-service (port 8070). Note that re-saving via NPM UI will
overwrite the conf and require re-adding the location blocks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 20:32:28 -04:00
jaredandClaude Sonnet 4.6 30bb0e5748 docs: add presence badges and device sessions to landing page and README
Document the new member list presence indicators and per-member device
sessions panel with per-device SAS verification in both the landing
page feature list and the README custom features table.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 20:18:37 -04:00
jaredandClaude Sonnet 4.6 c4eb7974e4 feat(landing): update feature matrix for voice messages and verification fix
Lint / Shell (shellcheck) (push) Successful in 8s
Lint / JS (eslint) (push) Successful in 5s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 34s
Lint / Secret scan (gitleaks) (push) Successful in 5s
- Lotus Chat voice messages: ~ playback only → ✓ record & play, MSC3245, E2EE
- Lotus Chat device verification: ~ → ✓ SAS emoji, cross-client inline cards
- Update feature description to list voice recording and verification fix

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 12:19:10 -04:00
jaredandClaude Sonnet 4.6 70cc233aec fix: add curl retry and timeout to gitleaks install step
Lint / JS (eslint) (push) Successful in 15s
Lint / Python (ruff) (push) Successful in 8s
Lint / Python deps (pip-audit) (push) Successful in 38s
Lint / Secret scan (gitleaks) (push) Successful in 4s
Lint / Shell (shellcheck) (push) Successful in 6s
The runner intermittently times out (5m) downloading the gitleaks binary
from GitHub. Add --retry 3 --retry-delay 5 --max-time 120 so transient
network blips don't fail the job.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 00:52:23 -04:00
jaredandClaude Sonnet 4.6 35c54672af feat: add per-message read receipts row and update Lotus Chat feature list
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Successful in 36s
Lint / Secret scan (gitleaks) (push) Failing after 5m18s
Add per-message read receipts comparison row (8-col, including new official
Cinny column from dc8f588). Update Lotus Chat feature description to include
per-message read receipt avatars and chat wallpaper in calls.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 00:27:56 -04:00
jaredandClaude Sonnet 4.6 39764ff478 feat: update comparison table for new Lotus Chat features
Lint / Shell (shellcheck) (push) Successful in 13s
Lint / JS (eslint) (push) Successful in 9s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 44s
Lint / Secret scan (gitleaks) (push) Successful in 6s
Reflect four features just added to the Lotus Chat fork:
- Polls: ~ → ✓ (display + vote, sends m.poll.response)
- Image captions: ✗ → ✓ (caption field on upload, sets body)
- Location sharing: ✗ → ~ (OSM map embed view + static share button)
- Message forwarding: ✗ → ✓ (forward to any room via room picker)
Also: correct Element X image captions to ✓ (v26.04.2 scrollable captions)
Update Lotus client card to reflect all added features.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 13:27:18 -04:00
jaredandClaude Sonnet 4.6 90892a57b0 feat: comprehensive client comparison update (May 2026)
Lint / Shell (shellcheck) (push) Successful in 12s
Lint / JS (eslint) (push) Successful in 11s
Lint / Python (ruff) (push) Successful in 8s
Lint / Python deps (pip-audit) (push) Successful in 45s
Lint / Secret scan (gitleaks) (push) Successful in 4s
Research-backed updates for all six clients based on latest releases:
- Commet v0.4.2: polls, screenshare (browsers/Android), macOS Beta, web builds, Vodozemac web binding; updated column header and client card
- Element X v26.04/v26.05: space create/manage shipped, DM voice calls, media captions, live location, multi-account confirmed; updated client card
- FluffyChat v2.3.0+: threads ✓, polls ✓, multi-account ✓
- Nheko v0.12.1: screenshare ✓ (X11/Wayland/Windows), widgets ~ (view only)
- New rows: Voice messages, Pinned messages, Location sharing, Message forwarding
- Updated security note re Commet Vodozemac Dart web binding

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 01:10:24 -04:00
jaredandClaude Sonnet 4.6 f3a7bcd00b feat: update client comparison table (May 2026)
Lint / Shell (shellcheck) (push) Successful in 15s
Lint / JS (eslint) (push) Successful in 8s
Lint / Python (ruff) (push) Successful in 6s
Lint / Python deps (pip-audit) (push) Successful in 1m4s
Lint / Secret scan (gitleaks) (push) Successful in 6s
- Cinny voice/video/calls: ✓ now covers rooms, DMs, group calls,
  screenshare via Element Call embed
- Cinny screenshare: ✓ (via EC iframe)
- Cinny GIF picker: ✓ Giphy with Terminal TDS theme
- Cinny polls: ~ display-only (read-only m.poll.start renderer)
- Cinny deleted messages: ✓ now shows placeholder instead of hiding
- New row: incoming call notification (ring + Answer/Decline for DMs)
- Updated featured client description with custom feature list
- README Lotus Cinny section updated with latest custom features

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 00:49:04 -04:00
jaredandClaude Sonnet 4.6 ffff199b7f Fix NODE_OPTIONS heap size for Vite build (896MB → 6144MB)
Lint / Shell (shellcheck) (push) Successful in 11s
Lint / JS (eslint) (push) Successful in 12s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 40s
Lint / Secret scan (gitleaks) (push) Successful in 5s
OOM observed during rendering-chunks phase at 896MB and 3072MB.
6144MB heap with 8GB LXC memory is confirmed working.
Also update README rebuild command to match.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 20:34:14 -04:00
jaredandClaude Sonnet 4.6 7f7ddd3e3c Switch Lotus Cinny from nightly dev to stable-release fork workflow
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 55s
Lint / Secret scan (gitleaks) (push) Successful in 5s
- Replace nightly build script with daily upstream release checker
  (cinny/upstream-check.sh) — posts to Matrix as LotusBot when a new
  cinnyapp/cinny stable release is published
- Add cinny/lotus-build.sh — merges latest release tag into the lotus
  branch, builds, deploys; triggered via !cinny-update webhook
- Fork lives at code.lotusguild.org/LotusGuild/cinny (lotus branch, v4.11.1)
- deploy/hooks-lxc106.json — adds cinny-build webhook endpoint (port 9000)
- Update landing page: "dev branch / nightly" → "Lotus fork / stable releases"
- Set LotusBot avatar on @hookshot_tinker-tickets

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 16:57:35 -04:00
jared 278f850f0c fix: remove spurious f-string prefix (ruff F541)
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Successful in 38s
Lint / Secret scan (gitleaks) (push) Successful in 4s
2026-04-29 16:15:39 -04:00
jaredandClaude Sonnet 4.6 88627470c1 feat: management polish, !cancel, !wordlestats, welcome fixes
Lint / Shell (shellcheck) (push) Successful in 11s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Failing after 5s
Lint / Python deps (pip-audit) (push) Successful in 41s
Lint / Secret scan (gitleaks) (push) Successful in 5s
- Add !cancel command (anyone cancels own blackjack; PL50+ clears all room games)
- Add !wordlestats top-level command (wraps wordle stats function)
- Add !cleanwelcome admin command to purge stale welcome DM records
- !help now hides management section from sub-PL50 users, hides !health from non-admins
- !announce uses nio room cache for join_rule instead of an API call per room
- Fix _INVITEALL_BLOCKED comment (Commands is knock-gated, not restricted)
- welcome.py: skip duplicate DM if a pending welcome already exists for the user
- welcome.py: add clean_stale_dm_messages() helper
- welcome.py: replace no-op post_welcome_message with log_ready()
- bot.py: update import/call to match welcome.py rename

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 14:50:14 -04:00
jaredandClaude Sonnet 4.6 4ef73afed2 fix: exclude #commands from !inviteall
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 50s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Commands has join_rule=restricted so the join-rule filter didn't catch
it. Added _INVITEALL_BLOCKED set with the Commands room ID — any room
in that set is skipped regardless of join rule. Invite-only rooms
(Management, Cool Kids, Spam and Stuff) are still excluded by the
existing join_rule check.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 22:48:12 -04:00
jaredandClaude Sonnet 4.6 72577dedf7 feat: setpl and inviteall apply space-wide with smart filtering
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) Successful in 39s
Lint / Secret scan (gitleaks) (push) Successful in 4s
!setpl now iterates every Space room via the hierarchy API and updates
the power_levels state event in each. Setting a user to the room's
users_default cleans up the explicit entry rather than leaving a
stale PL0. Rooms where the bot lacks permission are counted and
reported but don't block the rest.

!inviteall skips rooms with join_rule=invite (Management, Cool Kids,
Spam and Stuff) — only public/restricted rooms get the invite. Also
skips rooms where the target is already a member.

_get_space_room_ids() fetches the Space child list via the v1 hierarchy
API with pagination support.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 22:42:12 -04:00
jaredandClaude Sonnet 4.6 789db82d9f feat: management commands for PL50+ users
Lint / Shell (shellcheck) (push) Successful in 8s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 42s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Five new commands, all gated behind is_elevated() (power level >= 50):

!mkroom <name>   — clone #general's power levels, join rules, encryption,
                   history visibility, and avatar into a fresh v12 room,
                   auto-adds it to the Lotus Guild Space, and invites
                   the caller.

!roominfo        — show room display name, ID, member count, join rule,
                   encryption status, and all users with PL > 0.

!topic [text]    — set or clear the current room's topic.

!invite @user    — invite any Matrix user to the current room.

!setpl @user <n> — update a user's power level (0-100); cannot exceed
                   the caller's own level.

Also adds urllib.parse.quote and MATRIX_HOMESERVER to imports, and
adds a "Management (PL50+)" section to !help.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 22:34:08 -04:00
jaredandClaude Sonnet 4.6 66136ff2f7 feat: bypass !ask cooldown for users with power level >= 50
Lint / Shell (shellcheck) (push) Successful in 8s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Successful in 41s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Add is_elevated() helper that reads the room power level from the nio
client store. Users at PL50+ (Nerdy Council and above) skip the cooldown
check entirely. The timestamp is still recorded so cooldown applies
if their power level is later reduced below 50.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 21:39:44 -04:00
jaredandClaude Sonnet 4.6 37f5d2d70d feat: !ask --model flag to pick the LLM per-request
Lint / Shell (shellcheck) (push) Successful in 11s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 42s
Lint / Secret scan (gitleaks) (push) Successful in 8s
Usage: !ask --model <alias> <question>  (or -m for short)
Aliases: phi4, llama3, llama3-1b, gemma, gemma-1b, deepseek,
         codellama, qwen, dolphin, creative, abliterated,
         uncensored, llama2. The 'Thinking...' message shows
         which model is responding. Invalid aliases list all options.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 21:35:22 -04:00
jaredandClaude Sonnet 4.6 3ed15de5ce fix: triviaduel — one guess per player, auto-advance when both wrong
Lint / Shell (shellcheck) (push) Successful in 8s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Successful in 41s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Each player now gets exactly one attempt per question. If their guess
is wrong it's recorded and they're locked out for that round. If both
players have guessed wrong the correct answer is revealed and the game
moves to the next question immediately (no need to wait for the 45s
timeout).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 20:15:56 -04:00
jaredandClaude Sonnet 4.6 121e160535 fix: 20q answers truncate at sentence boundary, not mid-word
Lint / Shell (shellcheck) (push) Successful in 15s
Lint / JS (eslint) (push) Successful in 9s
Lint / Python (ruff) (push) Successful in 10s
Lint / Python deps (pip-audit) (push) Successful in 58s
Lint / Secret scan (gitleaks) (push) Successful in 6s
Instead of a raw 6-word slice (which left dangling fragments like
'Partly - Not exclusively American; has'), extract the first complete
sentence (up to 10 words). Falls back to the 6-word cap only if no
sentence boundary is found in the response.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 20:10:49 -04:00
jaredandClaude Sonnet 4.6 75f9c7bdb9 fix: tighten 20q answer cap to prevent answer leakage
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 8s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Successful in 42s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Reduce word cap from 12 to 6 and add explicit instructions not to use
proper nouns, brand names, or place names in answers. Fixes the case
where the model blurted 'The Grand Canyon State (Arizona)' in response
to a geography question.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 20:08:03 -04:00
jaredandClaude Sonnet 4.6 ee38b1e76a fix: remove unused variable asker in cmd_q (ruff F841)
Lint / Shell (shellcheck) (push) Successful in 8s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 4s
Lint / Secret scan (gitleaks) (push) Has been cancelled
Lint / Python deps (pip-audit) (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 20:07:24 -04:00
jaredandClaude Sonnet 4.6 a7a3891d1c fix: 20q answer dedup cache — prevent repeated answers
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 10s
Lint / Python (ruff) (push) Failing after 10s
Lint / Python deps (pip-audit) (push) Successful in 57s
Lint / Secret scan (gitleaks) (push) Successful in 6s
Add a rolling cache of the last 30 answers (persisted to
twentyq_cache.json) and pass the recent list to the model as an
explicit avoid clause. Also prompt the model to vary categories
each round. If the model still returns a cached answer it is
rejected and one retry is attempted automatically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 19:57:47 -04:00
jaredandClaude Sonnet 4.6 ad09286e27 fix: 20q now answers any question, not just yes/no
Lint / Shell (shellcheck) (push) Successful in 12s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Failing after 5s
Lint / Python deps (pip-audit) (push) Successful in 41s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Allow open-ended questions like "What color is it?" or "How big is it?"
The model now gives brief descriptive answers (capped at 12 words) for
open questions while still answering Yes/No/Sometimes/Partly for binary
ones. Updated command descriptions and in-game prompts accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 19:47:11 -04:00
jaredandClaude Sonnet 4.6 d095c34276 fix: ttt/triviaduel crash, blackjack per-player, improve hottake/nhie prompts
Lint / Shell (shellcheck) (push) Successful in 8s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Failing after 5s
Lint / Python deps (pip-audit) (push) Successful in 43s
Lint / Secret scan (gitleaks) (push) Successful in 5s
- Import MATRIX_USER_ID in commands.py (was missing — caused !ttt and
  !triviaduel to crash with NameError on every invocation)
- Blackjack is now per-player per-room: multiple players can each run
  their own game simultaneously; !hit and !stand operate on the caller's
  own game only
- !hottake: pick a random topic from 20 categories and pass it to the
  model so takes aren't all nostalgia-flavoured
- !nhie: tighter prompt with topic rotation and a word-count cap so
  generated scenarios are simpler and more relatable

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 18:56:30 -04:00
jaredandClaude Sonnet 4.6 54c73535b8 feat: add 9 new games and update help/README
Lint / Shell (shellcheck) (push) Successful in 8s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Failing after 5s
Lint / Python deps (pip-audit) (push) Successful in 41s
Lint / Secret scan (gitleaks) (push) Successful in 5s
New commands: numguess/ng, wordchain/wc/endwc, acronym/ac,
20q/q/answer, nhie, hottake, ttt/move, blackjack/hit/stand,
triviaduel/da. All per-room with AI-generated content where
applicable. callbacks.py wired up for new reaction handlers
(acronym votes, nhie, hottake). Help and README updated with
full command reference.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 16:29:23 -04:00
jaredandClaude Sonnet 4.6 e29263c3e2 hangman: redesign extended stages — drop confusing ear/arm overlap
Lint / Shell (shellcheck) (push) Successful in 12s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 6s
Lint / Python deps (pip-audit) (push) Successful in 41s
Lint / Secret scan (gitleaks) (push) Successful in 5s
The old \O/ ears row looked like 6 limbs when combined with /|\ arms.
New extended progression:
  0-6: same as standard (head → body → arms → legs)
  7:   left foot (/ in the previously empty row below legs)
  8:   both feet (/   \)
  9:   @ head (anguish — full figure visible)
  10:  X head (dead)

Each stage is visually distinct with no overlapping limb confusion.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 16:00:35 -04:00
jaredandClaude Sonnet 4.6 8effb24761 ci: fix pip-audit — restore --local, explicitly ignore pip's own CVE
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) Successful in 48s
Lint / Secret scan (gitleaks) (push) Successful in 5s
-r requirements.txt causes pip-audit to spawn an internal venv which
calls ensurepip, failing with exit 127 on the standalone Python build.
--local avoids the venv. CVE-2026-3219 is in pip itself (not our deps)
so we ignore it explicitly with --ignore-vuln.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 15:46:16 -04:00
jaredandClaude Sonnet 4.6 407e66e499 fix: add guess to help, document 8ball --debug, fix pip-audit CVE false positive
Lint / Shell (shellcheck) (push) Successful in 8s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Failing after 23s
Lint / Secret scan (gitleaks) (push) Successful in 6s
- !help Games section now includes !guess
- !8ball description mentions --debug flag
- pip-audit now scans only requirements.txt instead of --local (which
  was flagging CVE-2026-3219 in pip itself, not our dependencies)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 15:43:30 -04:00
jaredandClaude Sonnet 4.6 49cc0b3d75 hangman: add --hard and --extended flags
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) Failing after 42s
Lint / Secret scan (gitleaks) (push) Successful in 6s
--hard (-h): words 9-15 letters instead of 5-8
--extended (-e): 10 wrong guesses with full body (feet + ears stages)
Flags are combinable: !hangman --hard --extended

Board header shows mode emoji (🔥 hard, 💀 extended, 💀🔥 both).
Wrong counter shows X/10 in extended mode. All guess logic reads
max_wrong from game dict instead of hardcoded 6.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 15:40:51 -04:00
jaredandClaude Sonnet 4.6 22313b4a41 hangman: persist last 30 words to disk to prevent duplicates
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) Failing after 43s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Mirrors riddle/trivia cache pattern: loads hangman_cache.json on startup,
appends each new word, caps at 30, saves after each game. Recent words
are passed to the model prompt to avoid repeats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 15:33:54 -04:00
jaredandClaude Sonnet 4.6 6eb435010d hangman: add retry + log validation failures for word generation
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 42s
Lint / Secret scan (gitleaks) (push) Successful in 7s
Silent failures (word too long/short, has hyphens, empty hint) are now
logged as warnings showing the actual word/hint returned. Retry up to
2 times before giving up, matching riddle's behavior.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 15:19:58 -04:00
jaredandClaude Sonnet 4.6 0a486c2176 8ball: constrain general responses to actual yes/no/maybe style
Lint / Shell (shellcheck) (push) Successful in 18s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Failing after 42s
Lint / Secret scan (gitleaks) (push) Successful in 5s
The creative model was producing fortune-cookie mysticism ("navigate
the curve of fate") instead of 8-ball answers. New system prompt
explicitly requires YES/NO/UNCERTAIN category answers, 2-6 words,
funny and direct — no cryptic prophecies.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 13:45:00 -04:00
jaredandClaude Sonnet 4.6 f4e6e6f9fe debate: switch to CREATIVE_MODEL with system prompt for uncensored arguments
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) Successful in 45s
Lint / Secret scan (gitleaks) (push) Successful in 5s
phi4-mini refused to argue FOR controversial topics, instead deflecting
with neutral takes. The abliterated model with a committed debater system
prompt will actually take both sides without hedging or disclaimers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 21:59:02 -04:00
jaredandClaude Sonnet 4.6 8fc734643b fix: robust JSON extraction with try/except + retry in all AI commands
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Successful in 53s
Lint / Secret scan (gitleaks) (push) Successful in 9s
- Added _extract_riddle_answer() with dual fallback: JSON parse first,
  then regex extraction of quoted riddle/answer values directly from text
- _generate_riddle() now retries up to 2 times on parse/network failure
- Hangman, scramble, WYR, and trivia now catch JSONDecodeError and log
  the raw model output instead of letting the exception propagate silently

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 19:03:18 -04:00
jaredandClaude Sonnet 4.6 78c01cf5f2 riddle/trivia: persist dedup caches to disk so restarts don't reset them
Lint / Shell (shellcheck) (push) Successful in 39s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 54s
Lint / Secret scan (gitleaks) (push) Successful in 7s
riddle_cache.json: stores last 30 riddle texts + answers
trivia_cache.json: stores last 20 questions per category

Both files are capped at their respective maxes so they never grow
unboundedly. Loaded on startup, saved after each new question.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 22:01:22 -04:00
jaredandClaude Sonnet 4.6 a254bb9381 rename BALL_MODEL -> CREATIVE_MODEL
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 6s
Lint / Python deps (pip-audit) (push) Successful in 42s
Lint / Secret scan (gitleaks) (push) Successful in 6s
It's used for 8ball, roasts, riddles, WYR, and debate — not just the
magic 8-ball anymore. CREATIVE_MODEL better reflects its role as the
uncensored/abliterated model for creative generation tasks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 21:58:20 -04:00
jaredandClaude Sonnet 4.6 66f761b466 wyr/riddle: add model attribution + fix truncated WYR options
Lint / Shell (shellcheck) (push) Successful in 20s
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
wyr:
- Reject options that end on a dangling word (but/and/or/with/never etc.)
  so truncated sentences like 'but never' return None and retry
- Add 'via Llama 3.2 3B (abliterated)' credit to the poll message

riddle:
- Add 'via Llama 3.2 3B (abliterated)' credit to the riddle message

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 21:57:11 -04:00
jaredandClaude Sonnet 4.6 bc50e8205a trivia: strengthen prompt to prevent hallucinated/incoherent questions
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 10s
Lint / Python (ruff) (push) Successful in 10s
Lint / Python deps (pip-audit) (push) Successful in 1m11s
Lint / Secret scan (gitleaks) (push) Successful in 8s
The previous system prompt was basically empty. Now it explicitly:
- Requires the answer to be unambiguously correct
- Bans vague, ambiguous, or invented facts
- Requires plausible-but-wrong distractors
- Includes a concrete example of a good question
- Tells the model to pick a simpler topic if unsure

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 21:51:55 -04:00
jaredandClaude Sonnet 4.6 8bbcc0530f riddle: switch to abliterated model to stop shadow/fire loops
Lint / Shell (shellcheck) (push) Successful in 11s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 43s
Lint / Secret scan (gitleaks) (push) Successful in 5s
phi4-mini is too conservative and defaults to the same 2-3 answers.
Use BALL_MODEL (abliterated Llama 3.2) like WYR does.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 21:48:32 -04:00
jaredandClaude Sonnet 4.6 63f1bfda49 riddle/wyr: fix repeat shadow answers and truncate long WYR options
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 11s
Lint / Python deps (pip-audit) (push) Successful in 1m26s
Lint / Secret scan (gitleaks) (push) Successful in 13s
riddle:
- Cache answers separately so the same answer (e.g. 'shadow') can't
  appear twice in a session even if the riddle text differs
- Explicitly ban 'shadow' in the prompt and append avoid-answers clause
- Ban question endings ('what am I?', 'what could it be?') more strictly

wyr:
- Hard-cap options at 10 words server-side so the model can't ignore
  the word limit and generate paragraph-length options

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 21:34:03 -04:00
jaredandClaude Sonnet 4.6 bc84507e64 wyr: few-shot examples + rebuild question from options + switch to abliterated model
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / Python (ruff) (push) Has been cancelled
Lint / JS (eslint) (push) Has been cancelled
Lint / Python deps (pip-audit) (push) Has been cancelled
Lint / Secret scan (gitleaks) (push) Has been cancelled
- Add 3 assistant-turn examples to lock in the JSON format and tone
- Construct the 'question' field from option_a/option_b so it's always
  well-formed regardless of what the model puts in the 'question' key
- Switch from phi4-mini to the abliterated Llama 3.2 model for edgier,
  uncensored dilemmas

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 21:23:01 -04:00
jaredandClaude Sonnet 4.6 b6e99d165b riddle/wyr: fix quality issues from tonight's chat
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 48s
Lint / Secret scan (gitleaks) (push) Successful in 12s
riddle:
- Tighten generation prompt with explicit rules: specific noun answer,
  no answer word in the riddle, no 'what could it possibly mean', clues
  must logically point to ONE answer, prefer concrete things
- Fix answer matching: strip articles (a/an/the), allow partial match
  so 'person' hits 'a person' and 'shadow' hits 'my shadow' etc.

wyr:
- Prompt now asks for genuinely difficult dilemmas with real downsides
  on both sides; explicitly bans boring options like dolphins/karaoke

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 21:17:44 -04:00
jaredandClaude Sonnet 4.6 2457451d4c riddle: add dedup cache to prevent repeated riddles
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 43s
Lint / Secret scan (gitleaks) (push) Successful in 6s
Keep a rolling list of the last 30 riddles used and inject them into
the prompt as an avoid clause, same pattern as trivia's per-category cache.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 20:28:43 -04:00
jaredandClaude Sonnet 4.6 80d77a8a0f fix: wyr votes never counted — reactions arrive as ReactionEvent not UnknownEvent
Lint / Shell (shellcheck) (push) Successful in 12s
Lint / JS (eslint) (push) Successful in 8s
Lint / Python (ruff) (push) Successful in 11s
Lint / Python deps (pip-audit) (push) Successful in 49s
Lint / Secret scan (gitleaks) (push) Successful in 5s
nio has a dedicated ReactionEvent type with .reacts_to and .key attributes.
The callback was registered for UnknownEvent so reaction events were silently
dropped. Register for ReactionEvent and use its native attributes; keep the
UnknownEvent fallback for edge cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 14:00:03 -04:00
jaredandClaude Sonnet 4.6 126979f5cb hangman: edit board in place + fix ASCII art rendering; wyr: debug reaction logging
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 44s
Lint / Secret scan (gitleaks) (push) Successful in 6s
- Add edit_html() to utils using m.replace so messages can be updated
- Hangman board now edits in place on every guess — shows progressing
  ASCII figure as wrong guesses accumulate instead of spamming new messages
- Extract _hangman_board_html() helper for consistent board rendering
- wyr: add INFO-level logging to reaction callback to diagnose vote tracking

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 13:30:46 -04:00
jaredandClaude Sonnet 4.6 3405ab8b32 8ball: add third-party branch for Jared asking about someone other than himself/Wynter
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 6s
Lint / Python deps (pip-audit) (push) Successful in 45s
Lint / Secret scan (gitleaks) (push) Successful in 5s
When Jared asks about a @mentioned third party, give a neutral honest
prediction instead of hijacking the answer to be about Jared.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 11:22:49 -04:00
jaredandClaude Sonnet 4.6 6e0a738552 8ball leon: speak TO Leon in 2nd person, not AS Leon in 1st person
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 48s
Lint / Secret scan (gitleaks) (push) Successful in 6s
The oracle should address Leon ('you survived Raccoon City...') not
impersonate him ('I'm not buying it').

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 11:16:22 -04:00
jaredandClaude Sonnet 4.6 40e921a9da 8ball leon: switch to api/chat so system persona actually sticks
Lint / Shell (shellcheck) (push) Successful in 22s
Lint / JS (eslint) (push) Successful in 15s
Lint / Python (ruff) (push) Successful in 21s
Lint / Python deps (pip-audit) (push) Successful in 2m2s
Lint / Secret scan (gitleaks) (push) Successful in 12s
api/generate has no system role — the model was ignoring the character
context and giving generic one-word answers. Chat API with a proper
system message forces the Leon voice.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 11:00:59 -04:00
jaredandClaude Sonnet 4.6 868bca6494 8ball/roast: add Leon S. Kennedy context for stranger_danger
Lint / Shell (shellcheck) (push) Successful in 35s
Lint / JS (eslint) (push) Successful in 15s
Lint / Python (ruff) (push) Successful in 13s
Lint / Python deps (pip-audit) (push) Successful in 1m46s
Lint / Secret scan (gitleaks) (push) Successful in 14s
- 8ball: stranger_danger gets RE-universe flavored responses drawing on
  Leon's lore (Raccoon City, Ada Wong, bioweapon ops, dry wit)
- roast: stranger_danger/leon added to _ROAST_LORE lookup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 10:56:06 -04:00
jaredandClaude Sonnet 4.6 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
jaredandClaude Sonnet 4.6 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
jaredandClaude Sonnet 4.6 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
jaredandClaude Sonnet 4.6 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
jaredandClaude Sonnet 4.6 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
jaredandClaude Sonnet 4.6 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
jaredandClaude Sonnet 4.6 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
jaredandClaude Sonnet 4.6 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
jaredandClaude Sonnet 4.6 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
jaredandClaude Sonnet 4.6 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