Files
claudetools/session-logs/2026-06-05-mike-gc-review-and-multisession-sync-isolation.md
Mike Swanson 549110584d sync: auto-sync from GURU-5070 at 2026-06-05 20:02:53
Author: Mike Swanson
Machine: GURU-5070
Timestamp: 2026-06-05 20:02:53
2026-06-05 20:02:59 -07:00

84 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 2026-06-05 — GuruConnect three-way review + multi-session git isolation
## User
- **User:** Mike Swanson (mike)
- **Machine:** GURU-5070
- **Role:** admin
## Session Summary
Two major threads. First, ran an independent **three-way code review of the GuruConnect (GC) project** (Claude synthesis + Gemini 3.1 Pro + Grok 4.3). Started by answering whether GC's in-product audit feature is functional (verdict: the audit-event write path works and is viewable per-machine in the dashboard, but there's no global/searchable audit view and a few event types are stubbed). Then partitioned the GC codebase into three subsystems — server (42 Rust files), agent (34), dashboard (66 TS/TSX) — and ran Gemini and Grok over each via their `review-files` modes, six reviews in parallel to report files under `reports/review-2026-06-05/`. Synthesized everything into `SYNTHESIS-three-way.md` with Claude cross-checks, then a phased `REMEDIATION-PLAN.md`.
While kicking off those reviews I hit (again) the path-resolution gotcha in the agy/grok skills — `review-files` resolves relative paths only against CWD or `$CLAUDETOOLS_ROOT`, never a submodule subdir, so submodule-relative paths fail "file not found." Mike asked to document it; added a `[!WARNING]` callout to both SKILL.md files, fixed the misleading "repo-relative" table wording, and added inline GOTCHA comments at every resolution site in both scripts (committed `ec411f4`).
The review's top convergent finding (CRITICAL on all three surfaces, both models independently): **secrets/tokens in WebSocket URL query strings** (agent creds + dashboard viewer token). Pushed all review artifacts to the GC repo (`ded99c5`), wrote the remediation plan (P0P5), and operationalized it: 6 coord todos (`project_key=guruconnect`) + 13 Gitea issues (#10#22, one per CRITICAL/HIGH) — the latter blocked briefly by a **Gitea outage** (502, port 3000 down) that self-resolved.
Second thread: Mike asked how to isolate 34 concurrent Claude sessions so session data is captured and submodule **pointers stop stepping on each other** (a real collision happened earlier: a concurrent session's commits blocked a clean submodule-pointer bump). Laid out a layered plan (L1 explicit staging/lock, L2 sibling repos + junctions, L3 per-session worktrees) and implemented **L1**: a per-machine concurrency lock in `sync.sh` (atomic mkdir in `.git/`, exit 75 on contention, stale/dead-PID reclaim with re-verify-before-clear), mandatory per-session-unique log filenames, then extended the lock to **all** commit paths by extracting it into a sourceable lib (`sync-lock.sh`) used by `/scc` and `/checkpoint`, and finally a **best-effort coord visibility signal** (`git_sync_<machine>` component, syncing→idle/degraded). Every script change went Coding Agent → Code Review (which caught two real TOCTOU races and a residual race before they shipped). All verified live on the closing `/sync`.
## Key Decisions
- **GC review scoped by subsystem, models read files themselves.** Codebase (~1.2 MB) far exceeds CLI embed/argv limits, so used `review-files` (each model `read_file`s) over server/agent/dashboard rather than embedding diffs. Grok's server pass was split A/B because 42 files exceeded its read-file capacity (Cancelled + 256 KB embed-fallback cap < 548 KB server tree).
- **The WS-query-string finding is partly by-design** — GC's `CLAUDE.md` mandates the viewer token in a query param. Both external models reject it, so the remediation's first step is changing that spec rule, not just code. Logged as remediation P1 / issue #10.
- **Downgraded the bootstrap-secret finding from CRITICAL to HIGH** — GC server deploys on Linux, so the `0o600` chmod is effective; Grok's "Windows ACL no-op" framing doesn't apply to the deployed server. Residual risk is on-disk plaintext + the `info!` log fallback.
- **Isolation L1 over literal "drop git add -A".** Mike approved "patch sync.sh/save to drop git add -A." Found that blind removal would regress untracked-file auto-capture (per `project_sync_script_bug` memory). Instead: serialize with a lock + per-session-unique filenames, keeping a now-serialized `add -A` as the catch-all. Full per-session commit isolation deferred to a tracked todo.
- **Coord enforces nothing; the file lock does.** Coord is advisory, network-dependent, and softfail-offline, so it must not gate the git critical section. Used coord only for best-effort cross-machine *visibility*, never as a blocker — the sync never depends on coord being reachable.
- **Lock keyed per-repo (`<repo>/.git/claudetools-sync.lock`)** so the shared lib mutually excludes with `sync.sh` in ClaudeTools and self-scopes in any project repo (lets `/checkpoint` work generically).
- **`/scc` routed through `sync.sh`** rather than reimplementing rebase-safe push; accepted losing its custom `scc:` commit message in favour of one locked git path.
- **Deferred the ClaudeTools submodule-pointer bump** for guru-connect — entangled with another live session's unpushed commits; left for auto-sync to reconcile rather than publishing another session's WIP.
## Problems Encountered
- **agy/grok `review-files` "file not found"** — file lists were submodule-relative but the driver ran from the reports dir. Fixed by regenerating lists with absolute paths; then documented the gotcha in both skills (the user's actual ask).
- **Grok server review failed first pass** — 42 files Cancelled and the embed fallback (256 KB cap) skipped the 548 KB tree. Split the server list A/B (21+21); both then succeeded.
- **Transient `ask-grok.sh` syntax error** during one background run — a running grok process parsed the script mid-Edit. Not a real bug (`bash -n` clean; comment-only edits).
- **Gitea outage (502, `172.16.3.20:3000` down)** blocked issue creation. Agent correctly refused to fabricate issue numbers. Self-resolved minutes later (v1.25.2); re-ran and created #10#22.
- **Two real TOCTOU races in the sync lock**, caught by Code Review before shipping: (1) non-atomic `rm -rf`+`mkdir` stale recovery → fixed with atomic rename-aside; (2) residual window where a loser renames-away a winner's freshly-acquired live lock → fixed with re-verify-staleness-immediately-before-`mv` + a `sleep 1` busy-spin guard.
- **SendMessage tool unavailable** to resume a paused background agent — spawned fresh agents instead.
## Configuration Changes
ClaudeTools repo (D:\claudetools):
- `ec411f4``.claude/skills/agy/SKILL.md`, `.claude/skills/grok/SKILL.md`, `.claude/skills/agy/scripts/ask-gemini.sh`, `.claude/skills/grok/scripts/ask-grok.sh` (path-gotcha docs + inline comments)
- `6b0ce9a``.claude/scripts/sync.sh` (concurrency lock), `.claude/commands/save.md`, `.claude/commands/sync.md`
- `353ba63` — NEW `.claude/scripts/sync-lock.sh` (shared lock lib + `run` wrapper); `.claude/scripts/sync.sh` (sources it); `.claude/commands/scc.md`, `.claude/commands/checkpoint.md` (lock-protected)
- `f174d1b``.claude/scripts/sync.sh` (best-effort coord `git_sync_<machine>` signal)
GuruConnect submodule (azcomputerguru/guru-connect):
- `ded99c5``reports/review-2026-06-05/` (6 per-model reviews, SYNTHESIS-three-way.md, REMEDIATION-PLAN.md, file lists, run-review.sh driver)
Deferred (untouched): `projects/msp-tools/guru-connect` submodule pointer bump in the ClaudeTools parent.
## Credentials & Secrets
None created or rotated this session. Gitea token used by the Gitea Agent lives at vault `services/gitea.sops.yaml` — note the field path is `credentials.api.api-token` (the bare `token` field returns null); the SSH URI on port 2222 is also in that entry.
## Infrastructure & Servers
- Coord API: `http://172.16.3.30:8001/api/coord` (up; DB softfail 503-aware)
- Gitea: internal `http://172.16.3.20:3000` (preferred on-network), public `https://git.azcomputerguru.com` (NPM/openresty front). Had a ~minutes 502 outage this session; recovered to v1.25.2.
- GC deploy target (per GC CLAUDE.md): server on Linux/Ubuntu 22.04 @ 172.16.3.30:3002 → connect.azcomputerguru.com; agent = Windows.
## Commands & Outputs
- Per-subsystem review driver: `reports/review-2026-06-05/run-review.sh <gemini|grok> <subsystem> <abs-file-list> <out.md>` (uses `ask-{gemini,grok}.sh review-files -i "<instr>" <files>`).
- File lists MUST be absolute for `review-files`: `find "$(pwd)/server/src" -name '*.rs'` from inside the submodule.
- Coord component signal (validated, HTTP 200): `PUT /api/coord/components/claudetools/git_sync_<MACHINE>` with `{state,version,notes,updated_by}`.
- Coord todos created via `urllib` POST to `/api/coord/todos` (fields: text, project_key, auto_created, source_context, created_by_user, created_by_machine).
- Closing `/sync` confirmed: lock acquired/released, submodule pointer skipped (not committed), coord signal `git_sync_GURU-5070 = idle ... (Mike Swanson)`.
## Pending / Incomplete Tasks
- **GuruConnect remediation** — coord todos P0P5 (`project_key=guruconnect`); Gitea issues #10#22. Suggested: ship P0 (issues #11, #12, #15, #16, #17, #19 — small, no protocol changes) on a `feat/spec-019` branch; kick off P1/#10 (WS auth handshake) design review in parallel (longest lead).
- **Multi-session git isolation follow-ups** — coord todo `e84ac521` (`project_key=claudetools`): (1) drop blind `git add -A` for explicit per-session staging (true per-session commit isolation), (2) L2 sibling repos + gitignored junctions to remove submodule pointers, (3) L3 per-session worktrees.
- **ClaudeTools submodule-pointer bump** for guru-connect (`→ ded99c5`) still deferred; auto-sync will reconcile, or push manually once the other session's stack lands.
- **Rollout note:** each machine gets the locked sync only from its *next* sync after pulling these commits (the pulling sync itself runs unlocked).
- Left a `git_sync_GURU-5070` test note earlier; overwritten by the closing real sync.
## Reference Information
- Review artifacts: `projects/msp-tools/guru-connect/reports/review-2026-06-05/` (`SYNTHESIS-three-way.md`, `REMEDIATION-PLAN.md`, `gemini-{server,agent,dashboard}.md`, `grok-server-a.md`, `grok-server-b.md`, `grok-agent.md`, `grok-dashboard.md`)
- Gitea issues: https://git.azcomputerguru.com/azcomputerguru/guru-connect/issues/10 … /22 (C1=#10 … H8=#22)
- Coord todos: guruconnect P0 `5817feff`, P1 `1735bbbb`, P2 `d5d7e50d`, P3 `929de40b`, P4 `fe6b8166`, P5 `c96b71ab`; claudetools isolation `e84ac521`
- Commits — ClaudeTools: `ec411f4`, `6b0ce9a`, `353ba63`, `f174d1b`. guru-connect: `ded99c5`.
- Lock files: `.claude/scripts/sync-lock.sh` (lib + `bash sync-lock.sh run <cmd>` wrapper), lock dir `<repo>/.git/claudetools-sync.lock`, env knobs `SYNC_LOCK_WAIT` (120s), `SYNC_LOCK_STALE` (600s); contention exit code 75 (EX_TEMPFAIL).