Skip to content

Add CI (config/script validation, no auto-deploy) - #30

Open
sergiocoding96 wants to merge 28 commits into
mainfrom
ci/add-workflows
Open

Add CI (config/script validation, no auto-deploy)#30
sergiocoding96 wants to merge 28 commits into
mainfrom
ci/add-workflows

Conversation

@sergiocoding96

Copy link
Copy Markdown
Owner

Adds a CI workflow that validates deploy YAML, Python syntax and shell scripts.

Deliberately no deploy workflow: deploy/install.sh overwrites the live ~/.hermes/config.yaml and profile SOUL/config files, and this repo's snapshot has drifted from the running fleet — auto-deploying would revert the fleet's model configuration.

🤖 Generated with Claude Code

OpenClaw and others added 28 commits May 16, 2026 10:27
- tower/docs: architecture, agent access, Discord permissions, Krati setup

- tower/scripts: provision Krati, align personal agents, Discord hub fixes

- tower/SERGIO-CHANGELOG.md: summary of live sergio config (no secrets)

- .gitignore: agents-auth.json and perf audit artifacts
Adds CloakBrowser-backed scraping service at localhost:9378 as the
primary stealth-scrape path for DataDome / Cloudflare Turnstile /
Imperva-protected domains. Camofox stays for the agent's interactive
browser tool (snapshot/click/type) until Phase 2 mirrors those endpoints.

Why
---
Existing stack failed on DataDome targets (Idealista, Ticketmaster,
Glassdoor): Firecrawl playwright-service uses stock Chromium that
gets blocked, and the Camofox interactive service was silently broken
(better-sqlite3 native module crash, health check didn't catch it).
Benchmarked Cloak vs Camoufox vs stock Playwright; Cloak passes the
same fingerprint checks Camoufox does at lower latency and RAM, and
exposes a Playwright-compatible API that lets us collapse the dual
stack onto one engine.

What ships
----------
- tower/docs/browser-stealth-benchmark-2026-05-16.md
  Full benchmark methodology + numbers (engine launch / per-URL DCL /
  peak RSS / Sannysoft / Cloudflare behavior).
- memos-setup/learnings/2026-05-16-cloak-deprecate-camofox.md
  Decision doc: why this change, what shipped Phase 1, what's deferred
  to Phase 2, rollback path, cost projection.
- skills/web-research/SKILL.md
  New §4 "Cloak Stealth Service" + domain routing table updated to
  send DataDome / Turnstile / Imperva domains to localhost:9378.
- CLAUDE.md
  Architecture, "when to use which tool", and commands sections
  updated to reflect new stack. Health-check commands added.

Deliverables / evidence
-----------------------
- perf-audit-results-idealista/marbella-top20-analysis.md
  Worked example: 20 Marbella properties scraped via Cloak, per-property
  analysis, sub-area heatmap, value/trophy picks. End-to-end proof the
  new pipeline works on a real DataDome target.
- perf-audit-results-idealista/marbella-top20-raw.json
  Structured data behind the analysis (reproducible).
- perf-audit-results-idealista/idealista-estepona-page*.pdf
  PDF renders of the first 2 Estepona listing pages.
- perf-audit-results-idealista/idealista-estepona-page*-CHALLENGE.html
  Evidence of DataDome captcha-mode state from the IP-burn portion
  of testing; kept as documentation of failure mode.

Service infrastructure (on Tower host, not in this repo)
--------------------------------------------------------
- /home/openclaw/.hermes/cloak-service/cloak_service.py (~280 LOC
  FastAPI service: per-domain persistent context, request pacing,
  asset blocking, DataDome detection, CapSolver fallback)
- ~/.config/systemd/user/cloak-service.service (enabled, auto-restart)
- ~/.config/systemd/user/cloak-service.service.d/capsolver.conf
  (CAPSOLVER_API_KEY env, chmod 600, gitignored by being outside repo)

Interim fix bundled
-------------------
Camofox node_modules/better-sqlite3 was failing to load (native module
not registered), making /tabs return 500 silently while /health
reported ok. Rebuilt via `npm rebuild better-sqlite3` on the Tower
host; service restored. Phase 2 retires Camofox entirely.

Phase 2 (not in this PR)
------------------------
Mirror Camofox's /tabs/* interactive endpoints (snapshot, click,
type, scroll, press, back, screenshot) in the Cloak service, then
flip CAMOFOX_URL to point at port 9378 and disable the Camofox
systemd unit. Documented in the decision doc.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ox deprecated to warm-rollback

Same-day continuation of #29. Cloak service (`localhost:9378`) now
exposes the full Camofox HTTP surface used by `tools/browser_camofox.py`,
and `CAMOFOX_URL` env has been flipped to point at it. All gateway
services restarted and confirmed active.

What's now live on port 9378
----------------------------
- POST   /tabs                       create tab + optional initial nav
- POST   /tabs/:id/navigate          go to URL
- GET    /tabs/:id/snapshot          ariaSnapshot YAML + [eN] ref markers
- POST   /tabs/:id/click             click by ref (auto-refresh on stale)
- POST   /tabs/:id/type              type into element by ref
- POST   /tabs/:id/scroll            mouse-wheel up/down
- POST   /tabs/:id/press             keyboard key
- POST   /tabs/:id/back              go_back + refresh refs
- GET    /tabs/:id/screenshot        PNG (base64)
- DELETE /sessions/:userId           close all tabs + context

Plus the Phase 1 surface (/v1/scrape, /v1/save-pdf, /v1/balance, /health)
which is unchanged.

Format-compatibility verification
---------------------------------
Snapshot output diff-tested against Camofox on the same URL at the
same wall-clock:
- Cloak:   refsCount=222, totalChars=41004
- Camofox: refsCount=222, totalChars=41004
- 182-line diff was 100% content drift (HN updated vote counts and
  timestamps between fetches), 0% format drift
- `e15` etc. resolve to the same DOM nodes in both engines

End-to-end agent flow tested:
POST /tabs -> GET /snapshot -> POST /click(e3) -> GET /snapshot ->
POST /navigate -> POST /back -> GET /screenshot -> DELETE /sessions —
all green.

Cutover state
-------------
- ~/.hermes/.env backed up to ~/.hermes/.env.pre-cloak-flip
- CAMOFOX_URL flipped from http://localhost:9377 to http://localhost:9378
- Restarted: hermes-gateway, hermes-gateway-arinze, -hr-agent, -krati,
  -research-agent, -sergio — all `active`
- Camofox systemd service still running (warm-rollback only, no agent
  traffic). Stop+disable scheduled after ~1 week of clean operation.

Rollback
--------
```
sed -i 's|^CAMOFOX_URL=http://localhost:9378$|CAMOFOX_URL=http://localhost:9377|' ~/.hermes/.env
systemctl --user restart hermes-gateway hermes-gateway-arinze hermes-gateway-hr-agent hermes-gateway-krati hermes-gateway-research-agent hermes-gateway-sergio
```

Service source (not in this repo — lives on Tower)
--------------------------------------------------
- /home/openclaw/.hermes/cloak-service/cloak_service.py  (Phase 1, scrape)
- /home/openclaw/.hermes/cloak-service/interactive.py    (Phase 2, ~450 LOC, new)
  - INTERACTIVE_ROLES + SKIP_PATTERNS + MAX_SNAPSHOT_NODES constants
    kept in sync with Camofox server.js lines 98-108, 256
  - _build_refs_from_yaml mirrors Camofox _buildRefsInner (lines 1313-1389)
  - _annotate_yaml_with_refs mirrors Camofox annotation (lines 1933-1965)
  - _ref_to_locator mirrors refToLocator (lines 1412-1421)
  - _window_snapshot mirrors lib/snapshot.js windowSnapshot

Phase 3 (deferred)
------------------
After ~1 week clean: stop+disable camofox.service, mark
tools/browser_camofox.py deprecated in module docstring, optionally
move Cloak service source into this repo under tower/services/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ackend

Triggered after Phase 2 E2E was green; user opted out of the warm-rollback
week. Camofox service stopped + disabled. Cloak now serves 100% of the
agent's web stack (stealth scraping + interactive browser tool).

Tower-side changes
------------------
- `systemctl --user stop camofox.service` (0 active tabs/sessions at stop time)
- `systemctl --user disable camofox.service` (won't restart on Tower reboot)
- Port 9377 released
- `~/.hermes/hermes-agent/tools/browser_camofox.py` module docstring
  rewritten as deprecation notice — file name retained because renaming
  would touch 17 call sites in `browser_tool.py`; HTTP calls land on
  Cloak via `CAMOFOX_URL=http://localhost:9378`
- Camofox install left at `node_modules/@askjo/camofox-browser/` for
  reference / future rollback (~140 MB; remove only if disk pressure)

Repo changes (this commit)
--------------------------
- CLAUDE.md: Camofox bullet updated to "retired", clarifies the
  browser_camofox.py name retention
- skills/web-research/SKILL.md: Phase 3 status block
- memos-setup/learnings/2026-05-16-cloak-deprecate-camofox.md: full
  Phase 3 section appended (what landed, post-stop verification,
  re-enable recipe, deferred Phase 4 considerations)

Verification after Camofox stop
-------------------------------
- Cloak service still active
- All 6 hermes-gateway services still active
- Full E2E flow (`/tmp/e2e_cloak_as_camofox.py`) re-run with Camofox
  dead: 9/9 endpoint calls passed
- `tools.browser_camofox` Python symbols still importable; with
  CAMOFOX_URL=http://localhost:9378 in env, `is_camofox_mode()` →
  True and `check_camofox_available()` → True

Re-enable Camofox if a regression appears
-----------------------------------------
```
systemctl --user enable camofox.service
systemctl --user start camofox.service
sed -i 's|^CAMOFOX_URL=http://localhost:9378$|CAMOFOX_URL=http://localhost:9377|' ~/.hermes/.env
systemctl --user restart hermes-gateway{,-arinze,-hr-agent,-krati,-research-agent,-sergio}
```

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
15-slide widescreen deck summarizing the same-day Camofox → Cloak
migration for sharing with the team. Covers: executive summary, problem
state, benchmark methodology + results, DataDome IP-score discovery,
architecture decision, cost & scaling tiers, Phase 1/2/3 implementation,
final architecture, Marbella worked example, ops state + rollback recipe,
and links.

Generated with pptxgenjs (Node) using a custom slate-900 / cyan accent
design system. Visual QA pass via subagent on rendered JPGs caught 4
high-severity layout issues (title wrap collision, architecture-row
footer overflow, table row clipping, glyph rendering) and 1 cosmetic
imbalance; all 4 fixed and re-verified before shipping.

Files:
- tower/docs/cloak-migration-brief-2026-05-17.pptx (684 KB, editable)
- tower/docs/cloak-migration-brief-2026-05-17.pdf (314 KB, viewable)

Source generator script kept at /tmp/cloak-report/build/generate.js
(not in repo — one-shot artifact; rerun by re-installing pptxgenjs
+ react-icons + sharp deps).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ent vision

Adds 7 new slides (15–22) extending the migration brief into a strategic
"what this enables" Part 2. The original 14 Part 1 slides about the
Cloak migration are unchanged.

New slides
----------
15. PART 2 divider — From plumbing to product
16. The product — discovery agent for property investors (who/what/why)
17. Pipeline + monetization — Tier 1 free baseline + Tier 2 Nota Simple pay-per-use
18. The data moat — what accumulates day 1 / week 2 / month 1+ / month 6+
19. The embedding moat — why specialized property embeddings matter
    (with concrete BGE-vs-trained-encoder comparison)
20. Roadmap — Phase 0 done / Phase 1 next / Phase 2 history / Phase 3 embedding
21. Optionality — three buckets of future business models the data unlocks
22. Links + current state + deferred — replaces old slide 15

Cover subtitle updated to bridge the two parts.

QA: independent subagent visual review caught 5 critical layout issues
(decorative shape colliding with footer, title-wrap collisions on 2
slides, eyebrow mid-word break, footer-text collision) plus 2 minor
cosmetic issues. All 7 fixed and re-verified before shipping.

Files
-----
- tower/docs/cloak-migration-brief-2026-05-17.pptx (923 KB)
- tower/docs/cloak-migration-brief-2026-05-17.pdf (416 KB)

The PPTX source generator is at /tmp/cloak-report/build/generate.js
(one-shot artifact; not in repo).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…dal embeddings, storage cost, meaning-vs-pixels, embedding-vs-LLM

Adds 6 new slides + refreshes the final state slide. Deck now 28 slides
total (was 22). The new content captures the strategic conversation
since the v2 push.

New slides (20-25 in the 28-slide deck)
---------------------------------------
20. Wayback bootstrap — real coverage (~13M snapshots = ~3-5M unique
    listings, ~10-25% national coverage) + legal posture (EU TDM
    exception, Idealista litigation history, recommended hybrid path).
21. Data foundation after 6 months — 2-3M unique listings, ~50M photos,
    per-city annual flow breakdown across top 10-12 Spanish cities.
22. Multimodal embeddings — text-only vs CLIP-class side-by-side,
    SigLIP 2 / OpenCLIP / PaliGemma / Qwen2.5-VL as recommendations.
23. Storage cost comparison — raw photos vs text embedding vs
    multimodal per-photo / per-property / hybrid. Hetzner pricing.
    Compute panel: ~$15/mo + one-time $300-500.
24. Meaning vs pixels — LOST vs PRESERVED table + the photo-URL-not-
    photo insight (link Idealista's CDN, don't host).
25. Embedding vs LLM — catalog vs analyst metaphor. Why fine-tuning
    Gemma is the wrong frame for retrieval. Optimal stack = both.

Updated slides
--------------
- Cover: subtitle bridges Part 1 / Part 2
- Roadmap (slide 26, was 20): Phase 2 + 3 refined with Wayback +
  multimodal embedding language
- Final state slide (slide 28): adds Wayback Phase 2, Multimodal
  Phase 3, lawyer review + Idealista B2B license in Deferred

QA: subagent visual review caught 4 critical issues (title-wrap
collisions, footer overflows) + 2 cosmetic glyph issues (fl ligature,
≠ character). All fixed.

Files
-----
- tower/docs/cloak-migration-brief-2026-05-17.pptx (1.2 MB, editable)
- tower/docs/cloak-migration-brief-2026-05-17.pdf (486 KB, shareable)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nges

Strategic direction change captured per CLAUDE.md governance rule:

- Updated CLAUDE.md active-sprint header to reflect v2-only architecture
  (Paperclip/CEO retired, v1 MemOS server stopped, single-machine, single
  daemon, row-level namespace tenancy, BGE-large embedder)
- New decision doc: memos-setup/learnings/2026-05-17-v2-only-bge-shares.md
- Architecture decks in docs/architecture/:
  * 2026-05-17-memory-system-brief.{pdf,pptx} (merged canonical brief — 34 slides)
  * 2026-05-17-memory-system-decisions.{pdf,pptx} (source A: architectural review)
  * 2026-05-17-session-summary.pptx (source B: one-day overhaul summary)
  * 2026-05-17-memory-system.{pdf,pptx} (intermediate consolidation draft)
- Supporting artifacts: perf-audit harness + results, v2 data-integrity audit
  report, memory-viewer / UMAP-viewer screenshots used as evidence
- Operational scripts: tower-upgrade-hermes-runtime.sh, worktree initiation prompt
- .gitignore: exclude .playwright-mcp/ MCP scratch dir

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ools/

Trackable artefacts from the 2026-05-17 v2-only memory overhaul that had been
sitting only on the box because tools/ was blanket-ignored.

Headline changes:
- tools/memory-map.html — Memory Viewer v3 (D3 force-directed light theme,
  fill=kind / border=owning-agent, topic hubs as DeepSeek-labelled clusters)
- tools/memos-explorer.py — graph-export with HDBSCAN + DeepSeek cluster labels
- tools/memory-graph-watcher.py — WAL-driven debounced auto-refresh daemon
- tower/services/memory-graph-watcher.service — systemd unit template for it
- tools/plugin-patches/ — staged v2 plugin patches (5 logical patches across
  13 files; postinstall-patches.sh re-applies + verifies after npm update)
- tools/d3.v7.min.js — local d3 dep (d3js.org was unreachable from the box)

Gitignore: keep tools/ tracked; ignore only generated data + screenshots
(memory-graph.json, vec-map(-3d).{json,png}, screenshots/). Also tighten
repo-root ignores for playwright test PNGs and perf-audit JSON dumps.

Decision doc: extend memos-setup/learnings/2026-05-17-v2-only-bge-shares.md
with the Viewer v3 design, cluster-labelling pipeline, and watcher unit
docs. Drop the duplicate "Cluster summarisation + auto-refresh watcher"
section now covered upstream in the Memory Viewer section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the 2026-05-21 decision doc and updates the active-sprint header for the
new CTO agent (lives in ~/Coding/Hermes-CTO, joins the v2 plugin as the `cto`
profile). Re-introduces peer cross-agent interaction but keeps the v2-only
stance: no central orchestrator, no cross-machine routing.

Also documents the dirty-episode cold-boot fix (7 episodes marked
reward.skipped) that resolves the slow bridge boot behind the process leak.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rable daemon

Root causes (2026-05-26): (1) a non-idempotent capture retry re-inserted the
same turns tens of thousands of times across multiple agents (95k rows for
~320 real turns; arinze session cost only ~$0.01 in tokens — the damage was DB
bloat), and (2) each gateway bridge cold-loads BGE-large; concurrent boots
starved the CPU past the 30s session.open timeout → respawn/leak/CPU spiral.
No data was lost; the v2 store simply only goes back to its 2026-05-12 birth.

This change:
- Purge + global dedup of all runaway episodes (95,174 → ~320 traces), FTS
  rebuilt, VACUUM (1.8GB → 566MB). [DB ops, not in tree]
- traces_idempotent_turn BEFORE INSERT guard (RAISE(IGNORE)) so a duplicate
  (episode_id,turn_id) insert is silently skipped — structural fix for the
  re-insert loop. [applied to DB; documented in decision doc]
- Raise bridge timeouts in memos_provider (session.open 30→120s, reconnect
  4→90s) so a cold boot finishes before the fatal timeout.
- Replace the dangerous `pkill -f 'bridge\.cts'` band-aids (killed the :18800
  daemon + matched admin shells) with scripts/lib-bridge-safe-cleanup.sh
  (preserves the daemon, targets only node bridges) + staggered restarts.
- Make the :18800 daemon a systemd --user unit (was a fragile manual
  SSH-session process).
- Fix viewer console errors in hermes-profile-switcher.js (mixed-content guard
  for the cross-daemon probe + auth gate before diag/namespace).
- Reconcile CLAUDE.md: extraction + skillEvolver LLMs are DeepSeek (reverted
  from the Gemini stopgap on 2026-05-25), not Gemini.
- Wire this Claude Code session to memos under a 'claude-code' profile
  (.mcp.json; the .claude/settings.json hook config is gitignored — contents
  recorded in the decision doc).

Decision doc: memos-setup/learnings/2026-05-26-capture-outage-rca-recovery.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 3D map intentionally renders only skills/policies/topics; individual
memories were folded into topic clusters. Add a 'Memories' checkbox (default
OFF so it doesn't re-noise the view) that plots trace nodes as small dots,
with legend + styling. Frontend-only; web/dist symlinks to this file.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…uction + WM embedding-merge

Map (tools/memory-map.html, memos-explorer.py):
- reward-heat: explorer exports per-trace value/priority; map colors Memory dots
  red→grey→green by value (heatColor).
- bubble drill-down: clicking a Topic lists its member memories; click one → detail.

Induction #16 (l2-induction.ts, l2/induce.ts, l2/types.ts):
- L2 prompt now classifies experience_type (success_pattern|failure_avoidance) from
  the supporting traces' outcomes/value and emits anti_patterns; induce.ts persists
  experienceType/evidencePolarity + seeds decisionGuidance.antiPattern. Fixes the
  155:1 success:failure imbalance — negative episodes induce avoid-policies.

World-model merge #18 (l3/merge.ts):
- gatherMergeCandidates now also gathers by embedding similarity (cosine ≥ 0.86),
  not only policy-overlap/domain-tag, so semantically-identical world-models from
  different agents merge instead of creating near-duplicates. Decision threshold
  raised to the strict dedup cutoff (clusterMinSimilarity=0.3 was too loose).

Validated: daemon boots clean (:18800 200), stress-test 34/36 (2 fails are the
idle-stopped Firecrawl/SearXNG docker stack, unrelated).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…acking (#17)

#15 reward (core/reward/backprop.ts):
- error_signatures are captured per trace but were never a reward term — a step
  that hit tool failures/loops scored the same as a clean one. backprop now
  subtracts a 0.35 outcome penalty from V for any trace with non-empty
  error_signatures, pushing failures below neutral (lower rank + seeds
  failure_avoidance induction). The LLM R_human scorer already covers
  episode-level satisfaction, so this adds the missing objective signal.

#17 skills (core/config/defaults.ts, core/pipeline/memory-core.ts):
- crystallization bar: skill.minSupport 1→3 (a pattern must recur across ≥3
  episodes, not crystallize from one) + minGain 0.02→0.03. Fixes the
  hyper-specific one-off skills that never re-matched.
- usage tracking: record skill usage when retrieval surfaces a skill into the
  prompt (was only bumped by explicit getSkill → ~all at 0). Verified:
  usage_count sum rose 2→8 across a stress-test run.

Validated: daemon boots clean (:18800 200), stress-test 34/36 (2 = idle
Firecrawl/SearXNG docker, unrelated).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comprehensive 2026-05-26/27 session report: outage RCA + recovery, memory-quality
audit, the 6 quality fixes (#14-#19), and what works / what doesn't / what's left.
Rendered 16:9 PDF via Chrome headless from the HTML source. A Google Doc copy of
the same content was uploaded to the operator's Drive folder.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the failure-induction (l2-induction/induce/l2-types), WM embedding-merge
(l3/merge), outcome-reward (reward/backprop), and crystallization-bar
(config/defaults) files to the patch FILES + MARKERS lists so they survive an
npm reinstall and --check verifies them. All 22 markers present.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Full memory-system story Apr→May 2026: multi-tier origins (Paperclip/CEO +
MemOS v1), the v1/v2 pivots, the 2026-05-17 single-tier overhaul (BGE embedder,
share-scope policy, orphan-cron root cause), the 22 plugin patches, the LLM
provider saga, the CTO agent, and the 2026-05-26/27 outage recovery + quality
overhaul — with current state and roadmap. Brings the 2026-05-17 brief current.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Roadmap for post-recovery work (Phase 1 stability → Phase 2 feedback loop →
Phase 3 shared daemon). Adds tools/build-memory-report.sh to regenerate the
comprehensive report PDF from its HTML source, and records the standing process
that every memory change updates that report. CLAUDE.md header marks the 05-26
pending items as done and points to the roadmap + report.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Each gateway spawns its own bridge.cts that cold-loads BGE-large (~2 cores);
concurrent boots starve the CPU past session.open → respawn → leak/CPU spiral
(the recurring sergio failure). Add bridge_boot_lock() in daemon_manager.py — an
flock on ~/.hermes/memos-plugin/.bridge-boot.lock held around the spawn+open in
_reconnect_bridge so only ONE boot runs at a time (best-effort: proceeds after a
timeout rather than blocking capture forever). Reusing a warm bridge stays fast.

Verified: 3 gateways restarted simultaneously → boots serialized (1 at a time,
load capped ~4 vs 13+ before), no spiral, :18800 healthy. (Phase 3 shared-daemon
will remove this lock.) Also fixed the postinstall footer's dangerous
pkill-based restart hint to use the systemd unit + staggered gateway restarts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First application of the standing process: a memory change (P1.2 flock) updates
the comprehensive report. Moved serialize-boots from 'what's left' to 'what
works', noted per-gateway model loads remain (Phase 3), rebuilt the PDF via
tools/build-memory-report.sh.
…ack SKIP

P1.3: tools/prune-stale-skills.sh archives (reversible, never deletes) skills
with usage_count=0 + null last_used + age>grace(21d) + low gain. Hides them from
retrieval (tier-1 = active+candidate only). DRY-RUN by default; meant to run
weekly so skills accrue usage data (now tracked) before being judged. Archives
0 today (all skills <21d old) — correct.

P1.4: stress-test marks Firecrawl/SearXNG as SKIP (not FAIL) when the on-demand
stack is idle-stopped → 34/34 GREEN, 2 skipped (was '2/36 failing').

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
init() awaited recoverDirtyClosedEpisodes() before the HTTP server started — one
dirty episode's reflect took 154s, leaving :18800 unavailable during the worst
cold boots (and starving concurrently-booting bridges). Now fire-and-forget: the
reflection backfills reward/value after startup while capture/health serve
immediately. Self-capped (the recover fn is sequential). The periodic
autoRescoreDirtyClosedEpisodes() path is unchanged.

Verified in the boot log: server.started now fires the instant the 9-episode
rescore is kicked off; reflect.done events land AFTER server.started.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Boot-reflection now backgrounded (P1.1), boots serialized (P1.2), dead-skill
auto-prune (P1.3), stress-test green/skip (P1.4). Rebuilt PDF.
… P2.1 deferred)

Verified the feedback loop is more wired than assumed: the LLM R_human judge
already sees every user/agent turn pair (buildTaskSummary), so P2.2 (implicit
next-turn signal) is redundant — dropped to avoid double-counting in reward
code. Tool failures already feed error_signatures (P/#15 penalty) and the
subscriber auto-schedules runRepair on bursts; the gap is the adapter not
calling recordToolFailure + no feedback bridge RPC — a cross-layer change
deferred to a focused, tested session (learning-corruption risk). Auto-prune
(P1.3) marked done in the report.
Gateways → thin HTTP clients of the one :18800 daemon (one BGE-large total),
retiring per-gateway bridge.cts. Enablers already shipped: per-request namespace
(patch #2 X-As-Profile) makes the daemon multi-tenant; --daemon self-serves LLM.
Gap = expose the capture write path (session.open/turn.start/turn.end) over HTTP
(reads + memory/search already are). Covers auth (loopback bypass), adapter HTTP
transport behind MEMOS_TRANSPORT flag, namespace correctness, migration/rollback,
risks, verification. Removes the P1.2 boot-lock once landed.
First safe, additive slice of the shared-single-daemon work (roadmap
Phase 3, spec memos-setup/learnings/2026-05-27-p3.1-shared-daemon-spec.md).

- New server/routes/turns.ts: POST /api/v1/turn/start -> core.onTurnStart,
  POST /api/v1/turn/end -> core.onTurnEnd. Registered in registry.ts
  buildRoutes. (session/episode open/close already existed.) Lets the
  :18800 daemon accept the capture WRITE path over HTTP, the prerequisite
  for converting gateways into thin HTTP clients (one BGE-large load total).
- Namespace correctness (spec work item 4): namespaceFor() in
  core/pipeline/memory-core.ts now falls back to effectiveNamespace()
  (request-ALS aware) instead of bare activeNamespace, so X-As-Profile is
  honored on writes. Outside an HTTP request getRequestNamespace() is
  undefined -> resolves to activeNamespace exactly as before (stdio bridge
  unaffected). Without this, a turn written over HTTP landed under 'default'.

Auth: these routes are gated by the existing viewer session check, NOT
added to the public allowlist — a loopback bypass is unsafe because
Tailscale Serve proxies tailnet -> 127.0.0.1. The per-boot internal token
for the adapter + the HTTP-client transport cutover (behind MEMOS_TRANSPORT)
remain the next steps.

Verified: login -> open session/episode -> turn/start + turn/end with
X-As-Profile: claude-code -> trace lands owner_profile_id='claude-code',
share_scope='private'. stress-test 36/36 green; postinstall-patches.sh
--check clean (now 26 tracked files, markers registerTurnRoutes /
'POST /api/v1/turn/start'). Comprehensive report deck + PDF updated
(standing process).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
deploy/install.sh overwrites live fleet config, so this repo intentionally has
no deploy workflow. CI validates YAML, Python syntax and shell scripts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant