- Promote timer_entry → charge_timer_entry to default billing path; demote
bare add_line_item to a clearly-labeled fallback for non-time items only.
Mike caught the bare-add_line_item bug across 31 tickets on 2026-04-30;
repeated on 3 tickets 2026-05-01. Time entries are required for Syncro
reporting (hours per client, tech productivity, prepay burn).
- Replace /tmp/*.json payload pattern with heredoc throughout. /tmp resolves
to C:\tmp\ in the Write tool but %LOCALAPPDATA%\Temp\ in Git Bash on
Windows — different real directories. Caused a wrong-comment incident on
ticket #32225 2026-05-01 (rogue payload from prior session). Heredoc
avoids the file handoff entirely.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three tickets billed today: #32225 Sombra ($525 onsite), #32229 Mineralogical
Record ($262.50 emergency), #32214 Cascades Entra (33.5 hrs project labor at $0
debits prepaid block). Hit a real incident on Sombra: rogue comment posted with
content from a different ticket because /tmp resolves differently in the Write
tool (C:/tmp/) vs Git Bash (%LOCALAPPDATA%/Temp/) on Windows. Howard manually
deleted from GUI; subsequent posts used heredoc to avoid the file handoff
entirely. Root cause documented in feedback_tmp_path_windows.md so future
sessions don't trip the same wire. Scheduled remote agent
trig_01CAfvwoQ4nLcKEqbU4UQmSa to update the syncro skill examples 2026-05-02.
Created memory entry documenting correct way to verify ticket-invoice linkage
in Syncro API after 2026-04-30 incident where faulty verification script
falsely claimed 31 tickets had no invoices (actually 29 had invoices properly,
2 were correctly Non-Billable).
Key lessons:
- List endpoint does NOT return ticket_id or line_items
- Must query individual invoices for full data
- Invoice numbers are strings, not integers
- Use ticket ID (internal), not ticket number (user-visible)
Added to memory index for future GrepAI semantic search.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Both servers were already patched (11.110.0.97 and 11.134.0.20) via
daily auto-update. IOC scan found 16 flagged sessions across both
plus 4 uncommented SSH keys on IX.
Critical remediation:
- Forensic evidence preserved before any deletion
- 4 uncommented SSH keys removed from IX (server-side backup retained)
- 16 flagged sessions purged across both servers
- Root passwords rotated via chpasswd
- New WHM API tokens created; 3 stale transfer-* tokens revoked
- Vault entries + 1Password Infrastructure items updated
Forensic deep-dive verdict: patch held. All 7 actual CVE exploit
attempts (botnet IPs hitting /json-api/version) returned HTTP 403.
The "multi-line pass" IOC hits on user sessions were false positives.
Unidentified 76.18.103.222 root session traced to routine SSL
maintenance (zero sensitive endpoints touched).
Skill hardening:
- Added MANDATORY service-token directive to .claude/commands/1password.md
enforcing OP_SERVICE_ACCOUNT_TOKEN from SOPS for all op CLI calls
- Per Mike: memory files alone don't reliably bind agent behavior;
baking governance into skill content loaded at moment of use.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Documented two fundamental GuruRMM development principles:
1. Holistic Feature Development (MANDATORY):
- Every feature requires complete stack: backend, API, UI/UX, docs
- Features without management interfaces are incomplete
- Design for scalability and future expansion
- Example workflows included
2. AI-Optional Operation:
- Product must work without AI agents (Claude, autonomous tools)
- AI features are enhancements, not requirements
- Core operations remain deterministic and reliable
Principles documented in guru-rmm/docs/DESIGN.md and now in memory for
cross-session reference.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Tools (remediation-tool, onboard scripts, MSP utilities):
- Howard can modify directly
- Claude can execute with Howard OR Mike approval
- No roadmap process, immediate operational changes
Projects (GuruRMM, ClaudeTools API, etc.):
- Require Mike approval
- Features go to roadmap
- Bugs go to bug list
Established during Cascades CA role gap fix discussion.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Mike confirmed there is no co-host named "Tom" — the voice in 2014-s6e19
and 2016-s8e43 is Tara. The 5070 Ti session fabricated the Tom identity.
The voice profile itself (44 embeddings, 0.698 cosine vs Mike) is correct;
only the human label was wrong.
Rename swept:
- voice-profiles/tom/ -> voice-profiles/tara/ (git mv preserves all .npy)
- voice-profiles/profiles.json: "Tom" key -> "Tara"
- build_cohost_profile.py: TOM_WINDOWS -> TARA_WINDOWS, COHOST_NAME, comments
- 2026-04-27-qa-extraction-cohost-indexing.md: correction header + body sweep
- 2026-04-27-4090-benchmark-and-test-set.md: closure note
- .claude/memory/radio_show_no_cohost_named_tom.md: resolution + speaker roster
Diarization re-run after rename so speaker_map emits "Cohost: Tara".
Q&A counts unchanged (rename is label-only): 9 pairs across 6 test episodes.
Tara distribution from the post-rename diarization (per-episode % of audio):
2011-03-12-hr1 140s 5.6% likely false positive (call-in only)
2012-03-10-hr1 30s 1.1% likely false positive (call-in only)
2012-06-09-hr1 340s 12.8% suspicious — pending Mike confirm
2014-s6e19 680s 23.3% confirmed
2016-s8e43 1890s 35.5% confirmed
2017-s9e30 610s 11.4% plausible — pending Mike confirm
Broader speaker-roster context Mike provided this session (saved to
memory): the show has had multiple co-hosts (Tara, Randall, Rob) plus
producers/board ops (Andrew, Shannon, Ken, others) who would sometimes
go on-air. Only Tara has a profile so far. Every other speaker is
currently labeled CALLER, which means small CO-HOST attributions in
unexpected episodes (e.g. 2011/2012) may actually be a producer rather
than a false positive — Mike to spot-check.
Action item before full-archive run: build profiles for Randall, Rob,
and the named producers to avoid systematic Q&A false positives in
early-years and 2018/2019 episodes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Re-ran benchmark.py on GURU-BEAST-ROG against the post-overhaul code
(co-host profile, batched Whisper int8_float16, revised Q&A extractor).
Results vs 5070 Ti baseline:
- Diarization: 209.7x -> 338.1x (+61.2%)
- Transcription: 63.8x -> 94.8x (+48.6%)
- Q&A pairs: 9 vs 10 (within run-to-run noise; structural correctness matches:
2014 = 0 callers, 2016 = 2 WiFi caller pairs)
Setup change: BENCH_SETUP.md now lists ffmpeg as a Step-2 prereq
(winget install Gyan.FFmpeg). Was missing on this machine and the pipeline
fails silently at the first diarize call without ffprobe.
Code change: benchmark.py BASELINE_RTF updated 149.5 -> 209.7 to reflect
the 5070 Ti's post-overhaul measurement (e9ac607).
Data: 6 test episode transcripts and diarizations regenerated under the
new code path (batched Whisper output + co-host-aware speaker_map).
Correction memory: voice-profiles/tom/ directory + 5070 Ti session log
fabricated a co-host named "Tom" — Mike confirms no such person exists on
the show. The audio profile is real and the diarization separation is
sound, but the human identity attached to it is wrong. Saved under
.claude/memory/radio_show_no_cohost_named_tom.md pending Mike providing
the correct name for rename.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Memory entry prompts Mac session to run scripts/install-hooks.sh
before any GuruRMM work. Syncs via Gitea on next pull.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- .claude/identity.json (gitignored, per-machine) identifies who's at the keyboard
- .claude/users.json (tracked) registers known team members + roles + machines
- CLAUDE.md: on first sync, Claude asks "Mike or Howard?" and creates identity.json
- Session logs must include User section for attribution
- Git commits use per-user name/email (shared Gitea push account)
- Howard Enos (tech, full trust) added as second team member
- Memory entry created for Howard
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New integration with TickTick API for project/task management:
- OAuth 2.0 auth flow (mcp-servers/ticktick/ticktick_auth.py)
- MCP server with 9 tools for Claude Code (ticktick_mcp.py)
- FastAPI service with SOPS vault credentials (api/services/ticktick_service.py)
- JWT-protected REST router at /api/ticktick/ (api/routers/ticktick.py)
- Credentials stored in SOPS vault (services/ticktick.sops.yaml)
Dev project tracking (hybrid TickTick + DB):
- New dev_projects table migration (14 columns, status index)
- TickTick "Dev Projects" list for mobile visibility
- First project seeded: TickTick Integration (linked both sides)
Security: .tokens.json gitignored, token file permissions restricted,
HTML-escaped OAuth callback, SOPS vault (not env vars) for secrets.
Also: Installed Tailscale on ACG-5070 for office network access.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>