The skill/command DOCS instructed Claude to run a bare `py ...`, which is the
Windows py-launcher — absent on Linux/macOS (exit 127, hit on GURU-KALI). A blind
py->python3 swap is wrong too: python3 is a broken MS Store shim on some Windows
boxes where `py` is the correct launcher.
Fix mirrors the resolution the .sh skill scripts already do:
- New .claude/scripts/py.sh: picks the interpreter that actually RUNS —
identity.json python.command first, then py -> python3 -> python, each
validated with `-c 'import sys'` so the MS Store stub is skipped. exec's it.
- Repointed all DOC invocations (10 files, ~70 sites) from `py ...` to
`bash "$CLAUDETOOLS_ROOT/.claude/scripts/py.sh" ...` (incl. the `py -c` and
`py -` heredoc forms in checkpoint.md / mailbox.md).
- Left the .sh skill scripts untouched — they already resolve py/python/python3.
- errorlog.md: marked the GURU-KALI entry RESOLVED.
Depends on CLAUDETOOLS_ROOT (seeded by ensure-settings-env.py); py.sh also
self-resolves the repo root via git/cwd as a fallback.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Triggered by ~1h lost on 2026-06-12 when the IX WHM access method was forgotten and
password auth no longer worked. CLAUDE.md Key rules now mandates vaulting via the vault
skill + thorough documentation for any credential surfaced in a session.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 2a used `customers?name=` which is near-exact and missed slug/name spelling
mismatches — e.g. slug gonzvar-tax-services vs Syncro "Gonzvar Tax Service"
(singular), causing a false "not in Syncro". Switch to `query=` (fuzzy) with a
fallback ladder (first word, then de-pluralized token) before concluding not-found.
Two sweeps:
1. .30 is a PHYSICAL box (Lenovo ThinkCentre M83, Ubuntu 26.04), not a Jupiter
VM — the VM was decommissioned 2026-06-12. Fixed inventory tables and the
gururmm-build system page (overview, index, jupiter, gururmm-build,
POWER_FAILURE_RUNBOOK).
2. Windows build chain: Beast (GURU-BEAST-ROG, tailnet 100.101.122.4, i9-14900K)
is PRIMARY; Pluto (172.16.3.36) is FALLBACK. Verified against build-windows.sh
(`attempt_build beast || attempt_build pluto`). Fixed overview, index,
projects/gururmm (build-host table + flow + host detail), systems/pluto, and
the reference_pluto_build_server memory.
Submodule advanced: build-pipeline doc comments corrected to match.
- .gitignore: ignore root tmp/ (temp/ and .claude/tmp/ were already ignored;
root tmp/ was not, which is how scratch got committed and needed cleanup).
- New .claude/scripts/tmp-promotion-check.sh: advisory, read-only, never blocks.
Scans the gitignored scratch dirs (tmp/, temp/, .claude/tmp/) and flags files
worth graduating (scripts, substantial docs, session-log-referenced) before
they're lost to cleanup. Silent when scratch is empty.
- /save (Phase 4) and /scc (new step 2) run the check before sync.sh, pointing
at .claude/TEMP_GRADUATION.md for the graduate-vs-delete decision.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bump guru-rmm pointer (host-migration runbook). Record the migration architecture
decision in memory: physical box becomes .30 (all-but-Gitea-runner), VM retired,
MariaDB migrates (backs the coord claudetools DB per Gate-A).
Double-checked the 2026-06-08 BEC remediation for missed EXO-dependent items now that
the Exchange role is confirmed. Findings: malicious inbox rules gone (cleanup stuck);
all 14 mailboxes clean of fwd/redirect/delete/move rules; no mailbox forwarding; no
transport rules; no rogue delegates. Open (need Ken): Christina-Micek StopProcessing rule
+ Ken FullAccess to Accounting. Corrected stale 'Exchange Admin NOT assigned' note (it IS).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
client.py: send() falls back to ResultMessage.result when no TextBlock streams
(the "(no response)" bug) and reconnects+retries once on a closed SDK session.
message_handler.py: per-thread turn lock so messages arriving mid-turn or from a
second user queue in order (nothing dropped); per-session requester-attribution
env (discord_id -> users.json key), pinned to the thread opener; _USER_MAP caches
only on a successful load; final answer posts as a fresh message at the BOTTOM
(no edit-in-place); a <@id> tag goes out as a fresh send so it actually pings.
main.py: allowed_mentions permits user pings, blocks @everyone/@here/roles.
DISCORD_CLAUDE.md: no thread auto-delete; tiered close-out (Q&A -> one-line rolling
log, substantive -> /save); @mention guidance; opener-pinned attribution note.
whoami-block.sh / sync.sh: bot-context attribution (Executed by ClaudeTools Bot /
Requested by <person>; git author = mapped requester, committer = bot). Strict
no-op for interactive sessions.
users.json: discord_id for Mike/Howard; added Winter Williams (bot-only, full trust).
Reviewed by Code Review Agent + Grok + Gemini (Gemini's "malformed email" finding
verified as a false positive).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
EXO email-cleanup tasks (Search-UnifiedAuditLog, Get-MessageTrace, inbox rules) kept
401/403-ing per tenant because the Exchange Operator SP was missing the Exchange Admin
directory role — admin consent grants Exchange.ManageAsApp but never the directory role.
onboard-tenant.sh assigns it, but tenants consented before that step / by hand never got
it, and nothing audited for it. Hence the recurring 'next onboarding will fix it' (false
for already-onboarded tenants).
- NEW assign-exchange-role.sh: idempotent role assignment via the authoritative
roleManagement/directory/roleAssignments API (the legacy directoryRoles/members list
reads back unreliably). <domain|--all> + --verify/--dry-run.
- Backfilled the whole fleet (--all): 13 stragglers ASSIGNED, 12 already OK, 20 skipped
(tenant-admin not consented), 0 errors. Safe Site included.
- Standing audit documented (assign-exchange-role.sh --all --verify) + memory so no future
session repeats the empty promise.
- Adds wiki/clients/safesite.md (tenant + 4-source endpoint inventory + investigation).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Live-verified 2026-06-08: Security Investigator + User Manager + Tenant Admin Graph
tiers all consented and reading (subscribedSkus/organization HTTP 200) on
safesitellc.com (71b4e637-...). The reference's 'NO' was stale (last touched 2026-04-20).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>