Commit 4dc4563 had added MEMORY.md entries for the 49 resurrected
orphan files. My deletion commit 720bdd8 removed the files but missed
the matching index lines (read MEMORY.md before the rebase pulled
4dc4563 in). Index now matches the actual on-disk file set.
Self-check: 72 PASS / 0 WARN / 1 FAIL (autotask manifest issue
remains, not fixable on this machine).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 39 files I deleted in 0c00010 got resurrected by sync-memory.sh on
GURU-5070 (f8ed03c) because the script is additive-only. Re-deleted them
(49 files this time -- some additional drift between machines).
Also added feedback_memory_sync_destructive_ok.md capturing the policy
shift: with everyone onboarded, the memory tooling no longer needs
additive-only safety. memory-dream may apply proposed merges/deletions
and sync-memory.sh should propagate repo-side deletions back to profile
stores. Script updates to honor that are still pending -- without them,
this round of cleanup is also vulnerable to resurrection.
Self-check: 0 WARN, 1 FAIL remaining (autotask command -- manifest issue,
not fixable on this machine; needs Mike to either un-localize /autotask
or move it to capability-gated in baseline/manifest.json).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Applied memory-dream --apply-safe to resolve orphan warning from self-check.
- Added all 49 orphaned feedback/project/reference memories to index
- Index now complete with all 127 memory files properly referenced
This resolves the WARN from self-check about orphaned memory files.
The winget jq build on Windows emits CRLF; a trailing \r silently corrupts
`for x in $(jq ...)` loops and read-from-@tsv fields (single-value $() hides it).
Fix: override `jq(){ command jq "$@" | tr -d '\r'; }`. Windows-build-specific,
so it passes review on Mac/Linux. First hit + fix: the self-check skill engine.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New /self-check skill: each machine probes its own ClaudeTools harness wiring
(identity.json paths, required tooling, settings.json hooks, skill/command/script
set, vault decrypt, coord/Gitea connectivity, Ollama capability tier) and grades
RED/AMBER/GREEN against a checked-in provisional baseline manifest.
- Capability-tier model: architectural/OS/hardware differences (e.g. no local
Ollama) select a fallback ruleset instead of failing.
- Duplicate detection: flags command/skill names that diverge between the repo
and ~/.claude (the "same /cmd, different behaviour" cross-machine bug);
CRLF-only diffs ignored.
- Memory check: index + orphan detection, plus a model-driven semantic pass for
memories that contradict identity/settings.
- V1 is a census tool: --publish writes a per-machine census to coord
(component selfcheck_<host>); fanout requests the fleet to self-check +
self-remediate + re-publish; aggregate derives the proposed baseline. No
machine ever fixes another.
Reviewed twice by the Code Review Agent; three CRITICAL coord-API bugs and the
CRLF false-WARN found and fixed, verified live against the coord API.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jq -r '.stdout' returns the literal string "null" when the API field is JSON
null, causing the RESULT: grep to fail and fire a false drift alert. Fixes:
- Use `.stdout // empty` so null becomes empty string
- Add FINAL_ST tracking; treat non-terminal status as INFRA-ERROR, not drift
- Increase poll window from 20x4s=80s to 30x4s=120s for slow commands
- Read .stderr and .exit_code; include them in the no-RESULT diagnostic
Live check 2026-06-02: KSTEENBB2025 is PASS (today's alert was a false positive).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Live Sonnet-subagent recompile test inlined real passwords/PSK/RADIUS
secret from a session log into the article; review caught it. Added rule
6b to the synthesis brief: wiki references vault paths only, never raw
secrets (carry-over of values the existing article already discloses is
the only exception).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Seed/full synthesis in /wiki-compile (and the /save Phase 3 recompile) now
delegates the draft to a Sonnet subagent (model: "sonnet") instead of
Ollama qwen3 — better prose quality, no local-Ollama dependency. Refresh
mode unchanged (surgical, no model). Main agent still reviews the draft
before writing (billing/IPs/vault-paths; Patterns/History preserved).
Softfail now keys on subagent unavailability -> surgical refresh.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
/save now full-recompiles the worked-on article (Ollama, preserving
Patterns/History) so the session's findings land in the wiki, not just
dynamic fields. Seeds the article if missing. Softfalls to a surgical
refresh when Ollama is down so a save is never blocked. Still pre-sync,
so the article ships in the same commit; /scc inherits via /save logic.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
/save now refreshes the client/project wiki article (refresh-only: live
Syncro fields, sources, last_compiled -- never narrative/Patterns/History)
before sync.sh, so the article + index ship in the same commit as the
session log. Skips root/general scope; suggests /wiki-compile seed when no
article exists; softfails so a wiki hiccup never blocks the save. Folds in
the old post-sync unseeded-wiki check. /scc inherits via /save logic.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
compute_output_path now parses .gitmodules and, for a project scope whose
dir is a submodule (guru-rmm, guru-connect, youtube-sync-docker), falls
back to the MAIN repo root session-logs/ per convention. Non-submodule
projects (gururmm-agent, dataforth-dos) unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reconstructs session logs from Claude Code transcripts when a session
crashes or is closed before /save. Two entry points:
- /recover <uuid|latest> : manual, Claude-reviewed reconstruction
- detect_orphaned_sessions.py : scheduled scan that auto-builds logs for
substantive, unsaved, not-yet-recovered transcripts (banner-marked
RECOVERED-UNVERIFIED), commits them, and posts a #bot-alerts FYI.
recover_session.py is the shared engine: Python extracts the verbatim
command/config/reference timeline; Ollama drafts prose-only narrative.
Machine-local ledger (.claude/state/) prevents reprocessing. Reviewed:
git add scoped to own files, ledger written only after successful push,
per-uuid idempotency, --max cap for unattended runs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Compressed memory store 104 -> 71 files via four passes:
- Syncro: 19 scattered feedback_syncro_* files merged into 3 rule files
(api/billing/workflow) + an on-demand feedback_syncro_history.md for
incident detail, quotes, and tech/product ID tables.
- Four near-duplicate merges: Howard paste-safety, Pluto build server,
Howard backend deferral, IX server access (ssh+tailscale).
- Per-cluster rule/state/history split applied to GuruConnect (2->1),
Dataforth (3->2), Cascades (7->3), GuruRMM (13->3).
- New reference_resource_map.md: single auto-loaded cheatsheet for
"do I have access to X and how do I connect from this machine?"
- MEMORY.md rewritten to match the new layout.
Health: broken backlinks 8->7, overlap clusters 12->5, orphans 17->0.
memory-dream: read-only memory lint/consolidation analyzer (index, backlinks,
stale refs, dup clusters, profile drift); additive-only --apply-safe, all
merges/deletes are proposals. sync-memory.sh: additive repo<->harness-profile
union (no delete/overwrite, conflicts surfaced), wired to a SessionStart hook.
Migrates the useful profile-only memories into the synced repo store.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Require SecurityCenter2 productState RTP-enabled bit before treating a
registered AV as active (lapsed/disabled AV no longer suppresses the
critical Defender finding), and tighten the Datto fallback to AV/EDR
services only — excluding Datto RMM/Backup/Workplace/Continuity/File so
non-AV Datto products can't masquerade as antivirus. Fix misleading comment.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The probe flagged ACG's own MSP tooling (ScreenConnect/ConnectWise Control,
Splashtop, Syncro, Datto RMM, Datto EDR/AV) as CRITICAL "foreign agent" and
flagged Defender-off as CRITICAL even when a 3rd-party AV had legitimately
disabled it. Now: allowlisted tools emit an INFO "expected ACG tooling"
finding (genuinely-foreign tools still CRITICAL); Defender-off is downgraded
to INFO only when a 3rd-party AV is active. JSON contract + grading unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PowerShell ConvertTo-Json collapses a single-element array into a bare
object (or, for string arrays, a bare string). The runner iterated/joined
several facts.* fields, so single-volume / single-NIC / single-admin
machines silently dropped the Fixed Volumes table and errored the network
adapter, local-administrator, and installed-software-diff lines.
Fix jq-side in the runner (backward-compatible with already-written
immutable baselines; PS1 untouched per the todo decision) using
`if type=="array" then . elif .==null then [] else [.] end` at:
volumes, network_adapters (+ inner ip/dns), local_administrators, and
installed_software (both sides of the diff). Verified with synthetic
single-element JSON and a multi-element no-regression check.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fixed post-commit hook to properly escape JSON payloads using python.
Previous implementation was vulnerable to breaking on commit messages
with special characters (quotes, newlines, etc.).
CHANGES:
- Use python json.dumps() for proper JSON escaping
- Prevents 422 validation errors from coordination API
- Handles multi-line commit messages correctly
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Host guard in /opt/gururmm/webhook-handler.py skips docs-only pushes; note the
stale repo copy must not be redeployed over it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Match a known external IP to the RMM agent rather than reconning every
candidate machine (Mike's correction during the Pavon GuruConnect-client
removal). Notes the GuruRMM agent-IP tracking gap (todo 7459428e).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Several bugs found and fixed during live testing against the ACG GravityZone
tenant:
- security_sweep_all_clients: iterate each company (the companies container is
not a valid endpoint parent; passing it 400'd the whole sweep)
- list_quarantine: use service-scoped path quarantine/computers with companyId
(bare quarantine module 404'd; param is companyId not parentId)
- rename GZEndpointSummary.detection_active -> threat_detected with corrected
semantics (True = active threat, tracks with infected; not an engine-on flag)
- status: readable sectioned table renderer for the nested apiKey/license dict
- portable CLAUDETOOLS_ROOT resolution (derive from file path, not a Windows
literal) so it works on the Mac/Linux fleet
Adds scripts/selftest.py: a 29-check read-only harness (all passing) covering
every read command, --json, error exit codes, and destructive-action gating.
EDR/incident commands (blocklist, isolate/unisolate, blocklist-add/remove) and
raw destructive-method gating are included from this session's work.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- raw now refuses destructive methods (delete/uninstall/remove/reconfigure)
without --confirm (it previously bypassed all gating)
- --json is now accepted after the subcommand (shared via a common parent
parser), matching the documented usage
- drop a placeholder-less f-string
- SKILL.md: document raw gating + that raw echoes upstream responses verbatim
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a /bitdefender skill that drives the ACG GravityZone partner tenant
via the JSON-RPC Public API. Read + management ops (companies, endpoints,
live security sweep, policies [read-only/shallow], packages, quarantine,
scans, groups, move/delete). Identity-tier JSON cache (24h TTL,
--refresh); volatile status is always pulled live, never cached.
Security hardening: API key loaded from SOPS vault at runtime (never on
disk/logs/argv/cache); destructive deletes gated behind --confirm; `raw`
also gates destructive methods; upstream error bodies truncated. UNVERIFIED
API methods reachable only via `raw`. Reuses the auth/JSON-RPC pattern from
api/services/gravityzone_service.py.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GC's db layer uses runtime sqlx::query()/query_as() throughout - zero
compile-time macros (verified during v2 Task 1; CLAUDE.md's "compile-time
checked queries" line is stale). Pass B now treats a NEW sqlx::query! macro
as a [LOW] deviation (reintroduces the .sqlx-cache footgun + build-time
DATABASE_URL) instead of blessing macros as the GC norm. Fixed both the
intro divergence note and the Pass B check.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Load .claude/standards/ (index.yml + files) as the compliance baseline;
Rust/TS passes now cite the specific standard each finding violates
- Glob all docs/specs/SPEC-*.md (incl. SPEC-002) + specs/*/plan.md; Pass F
reconciles SPEC phases and plan.md [DONE] markers against code (3rd table)
- Extract a planned-work list from SPEC-002 + active plans; tag findings that
match already-planned work as [TRACKED] so mid-rebuild audits surface net-new
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>