docs: complete v1.1 research synthesis for session lifecycle, memory & reporting

This commit is contained in:
2026-06-14 13:53:55 +08:00
parent b5e7008314
commit 4b58964a12
5 changed files with 860 additions and 0 deletions

View File

@@ -0,0 +1,197 @@
# Architecture Patterns
**Domain:** Platform engineering agent (Hermes Agent configuration)
**Researched:** 2026-06-14
## Recommended Architecture
The v1.1 features are additive — they extend an existing Hermes Agent deployment without modifying Hermes core. The architecture is a **plugin + script + configuration** layer around Hermes' built-in extension points.
```
┌─────────────────────────────────────────┐
│ Telegram Gateway │
│ (already active, TELEGRAM_HOME_CHANNEL) │
└────────────┬────────────────────────────┘
┌────────────▼────────────────────────────┐
│ Hermes Agent Runtime │
│ ┌────────────────────────────────────┐ │
│ │ Hindsight Memory Provider │ │
│ │ (local embedded PostgreSQL daemon)│ │
│ │ auto_retain: true │ │
│ │ auto_recall: true │ │
│ │ memory_mode: hybrid │ │
│ └────────────────────────────────────┘ │
│ ┌────────────────────────────────────┐ │
│ │ Built-in Memory (fallback) │ │
│ │ MEMORY.md + USER.md │ │
│ └────────────────────────────────────┘ │
│ ┌────────────────────────────────────┐ │
│ │ Plugin Hook System │ │
│ │ on_session_start → repo cloning │ │
│ │ pre_llm_call → context injection │ │
│ └────────────────────────────────────┘ │
└──────────────────────────────────────────┘
┌─────────────────────┼─────────────────────┐
│ │ │
┌─────────▼─────────┐ ┌────────▼────────┐ ┌─────────▼─────────┐
│ Docker Terminal │ │ Cron Jobs │ │ Session Storage │
│ (repo workspace) │ │ (reporting, │ │ (state.db) │
│ DEFAULT_REPOS │ │ archiving) │ │ │
│ cloned via hook │ │ │ │ export_session() │
└───────────────────┘ └─────────────────┘ │ delete_session() │
└───────────────────┘
┌────────▼─────────┐
│ Archive Storage │
│ ~/.hermes/ │
│ archive/sessions/│
└──────────────────┘
```
### Component Boundaries
| Component | Responsibility | Communicates With |
|-----------|---------------|-------------------|
| **Hindsight Provider** | Cross-session memory with knowledge graph, entity resolution, semantic recall | Hermes agent loop (pre-turn recall, post-turn retain), local PostgreSQL, OpenRouter (LLM extraction) |
| **Repo Clone Hook** | On session start, clones DEFAULT_REPOS into workspace | Docker terminal (via `terminal` tool or subprocess), filesystem |
| **Daily Report Skill** | Instructs agent what data to gather and how to format the daily summary | SessionDB (via `state.db` queries or `session_search`), Telegram (via `send_message`), Jira API (via ngn-jira skill) |
| **Session Archive Script** | Exports stale sessions to JSON, deletes from live DB | SessionDB API (`export_session`, `delete_session`), archive filesystem |
| **Built-in Memory** | Always-active fallback for critical facts | Agent system prompt (frozen at session start) |
### Data Flow
#### Session Start (Default Repos)
```
User sends first message
→ `on_session_start` hook fires
→ Repo clone plugin checks /workspace/
→ Missing repos cloned via git (needs credential mount)
→ `pre_llm_call` hook fires (is_first_turn=True)
→ Plugin injects "Cloned repos: rai-ops, rai-deployment, rai-devtools" as context
→ Agent sees repos available in workspace
```
#### Memory Flow (Hindsight)
```
Agent turn completes
→ Built-in memory save (MEMORY.md / USER.md)
→ Hindsight auto_retain: conversation turn + entity extraction
→ Stored in local PostgreSQL with knowledge graph
Next turn (any session)
→ Hindsight auto_recall: semantic search for relevant memories
→ Results injected as context into the turn
→ Agent sees recalled facts from any past session
```
#### Daily Report Flow
```
Cron tick at 09:00
→ Scheduler loads daily-report skill
→ Creates fresh AIAgent session
→ Skill prompt instructs agent to:
1. Query state.db for recent sessions
2. Query hindsight for relevant cross-session facts
3. Query Jira for open/updated tickets
4. Format as Telegram-friendly summary
→ Agent produces report
→ Delivered to TELEGRAM_HOME_CHANNEL
```
#### Session Archive Flow
```
Cron tick on Sunday 06:00
→ No-agent script runs
→ Queries state.db for sessions inactive >30d
→ For each: export_session() → write JSON → delete_session()
→ Summary of archived sessions delivered to Telegram
```
## Patterns to Follow
### Pattern 1: Plugin Hook for Session Initialization
**What:** Use Hermes' plugin hook system (`ctx.register_hook("on_session_start", handler)`) to run initialization logic when a new session begins.
**When:** Any setup that should happen exactly once per session, before the agent processes any user message.
**Example:**
```python
def clone_default_repos(session_id, model, platform, **kwargs):
repos = ["rai-ops", "rai-deployment", "rai-devtools"]
for repo in repos:
path = f"/workspace/{repo}"
if not os.path.exists(path):
subprocess.run(["git", "clone", f"github.com/rai-apps/{repo}", path])
def register(ctx):
ctx.register_hook("on_session_start", clone_default_repos)
```
### Pattern 2: Skill-Backed Cron Jobs
**What:** Cron jobs that load a skill before executing. The skill provides structured instructions; the cron prompt is the task.
**When:** Recurring tasks that benefit from agent reasoning but follow a repeatable structure.
**Example:**
```bash
hermes cron create "0 9 * * *" \
--skill daily-report \
--deliver telegram:-100474440517 \
--name "Daily Platform Report"
```
The skill (`daily-report/SKILL.md`) contains the report template. The cron job's prompt is just "Generate today's report."
### Pattern 3: No-Agent Script for Deterministic Automation
**What:** Cron jobs with `no_agent=True` that run a script directly, skipping the LLM entirely.
**When:** Tasks where the output is fully determined by script logic — archiving, data gathering, threshold checks.
**Example:**
```bash
hermes cron create "0 6 * * 0" \
--no-agent \
--script archive-stale-sessions.py \
--deliver telegram:-100474440517 \
--name "Weekly Session Archive"
```
### Pattern 4: Export-Before-Delete for Data Safety
**What:** Before removing any data from the live system, export it to an archive file first.
**When:** Any destructive operation on session data, files, or state.
**Example:**
```python
data = db.export_session(session_id)
archive_path = archive_dir / f"{session_id}.json"
archive_path.write_text(json.dumps(data, indent=2))
db.delete_session(session_id)
```
## Anti-Patterns to Avoid
### Anti-Pattern 1: Monkey-Patching Hermes Core
**What:** Modifying `~/.hermes/hermes-agent/` source files to add custom behavior.
**Why bad:** Hermes updates overwrite changes. The agent auto-updates. Custom patches break silently and are unrecoverable.
**Instead:** Use documented extension points: plugin hooks, shell hooks, skills, cron jobs.
### Anti-Pattern 2: Direct `state.db` Schema Queries in Production Scripts
**What:** Writing SQL queries against `~/.hermes/state.db` that depend on internal schema details.
**Why bad:** Schema changes between releases without notice (currently v11, has gone through 11 migrations). Queries break after `hermes update`.
**Instead:** Use `SessionDB` API methods (`export_session()`, `create_session()`, `get_messages()`). Fall back to direct SQL only in controlled scripts that are tested after each Hermes update.
### Anti-Pattern 3: Storing Credentials in Workspace Files
**What:** Writing GitHub tokens or SSH keys into the Docker container's workspace.
**Why bad:** If the agent is compromised (prompt injection), credentials in workspace files can be exfiltrated via `read_file` or `terminal` output.
**Instead:** Mount credentials read-only at the Docker level (`docker_volumes: [path:path:ro]`). Use `docker_forward_env` for environment variable-based credentials.
## Scalability Considerations
| Concern | At 1 user | At 10 users (future team) | Notes |
|---------|-----------|---------------------------|-------|
| Hindsight DB | <1GB PostgreSQL | 5-50GB PostgreSQL | Local embedded mode is single-user. For teams, switch to cloud mode or self-hosted Hindsight. |
| Session archive | ~100 sessions/year | ~1,000 sessions/year | JSON files are tiny (~50KB each). Storage is negligible. |
| Cron report LLM cost | 1 report/day ~1K tokens | 10 reports/day ~10K tokens | Cost scales linearly with users. Consider no-agent mode for data sections. |
| Repo clones | 3 repos per session | Same (shared workspaces) | Container persistence means clones survive across sessions in the same container. |
## Sources
- Hermes Agent docs: Hook system (`website/docs/user-guide/features/hooks.md`)
- Hermes Agent docs: Cron system (`website/docs/user-guide/features/cron.md`)
- Hermes Agent docs: Session storage (`website/docs/developer-guide/session-storage.md`)
- Hermes Agent source: `hermes_state.py`, `agent/curator.py`, `hermes_cli/hooks.py`
- ngn-agent `config.yaml` and `initial-plan.md`

View File

@@ -0,0 +1,232 @@
# Feature Research
**Domain:** Platform engineering agent (Hermes Agent-based configuration/adoption)
**Project:** ngn-agent v1.1 — Session Workspace, Hindsight Memory & Cron Reporting
**Researched:** 2026-06-14
**Overall Confidence:** HIGH
---
## Feature Landscape
### Table Stakes (Users Expect These)
Features users assume exist. Missing = product feels incomplete.
| Feature | Why Expected | Complexity | Notes |
|---------|--------------|------------|-------|
| Default repos cloned in new sessions | Every session needs project repos (rai-ops, rai-deployment, rai-devtools). Manual clone every session is friction. | LOW | `on_session_start` plugin hook or shell hook. Needs git credentials in Docker container. |
| Cross-session persistent memory | Agent forgets everything between sessions without it. Built-in MEMORY.md is too small (2.2k chars) and frozen at session start. | LOW | Hindsight memory provider. `hermes memory setup` → select hindsight. |
| Daily operational report | Any agent managing infrastructure must report daily. Invisible work erodes trust. | MEDIUM | Cron job + custom skill. Telegram delivery already works. |
| Stale session cleanup | Sessions pile up indefinitely without lifecycle management. | MEDIUM | No built-in archiving. Custom `export_session()` + `delete_session()` script. |
### Differentiators (Competitive Advantage)
Features that set the product apart from a bare Hermes install.
| Feature | Value Proposition | Complexity | Notes |
|---------|-------------------|------------|-------|
| Knowledge graph memory (Hindsight) | Entity-aware, cross-session recall with LLM synthesis (`hindsight_reflect`). Not just text search — entities, relationships, consolidated observations. | LOW | Hindsight provides this automatically once active. Local embedded mode = zero cloud dependency. |
| On-demand repo cloning during session | User says "clone rai-pipeline" mid-session, agent does it without leaving the conversation. | LOW | Hermes skill or just telling the agent. Trivial once git credentials are mounted. |
| Jira-integrated daily report | Report includes Jira ticket status and session→ticket correlations, not just session summaries. | MEDIUM | `ngn-jira` skill already exists. Add Jira query to daily-report skill prompt. |
| Zero-cost stale cleanup | Archive operations use `no_agent: true` cron mode — zero LLM token cost. | LOW | Deterministic script. No LLM needed for export+delete. |
### Anti-Features (Commonly Requested, Often Problematic)
| Feature | Why Requested | Why Problematic | What to Do Instead |
|---------|---------------|-----------------|-------------------|
| Custom scheduler for reports | "I need more control over timing" | Hermes cron already does intervals, cron expressions, and ISO timestamps. Building another scheduler is waste. | Use `hermes cron create` with cron expressions. |
| Custom memory provider implementation | "I want memory tailored to my needs" | Hindsight is already bundled, production-ready, and has all the features (KG, entities, reflect). Building from scratch is months of work. | Activate hindsight via `hermes memory setup`. Configure via `~/.hermes/hindsight/config.json`. |
| Persistent Docker image with pre-cloned repos | "Cloning at session start is slow" | Image would be large, stale quickly, and need regular rebuilding. The current `nikolaik/python-nodejs` image is sufficient. | Clone at session start via `on_session_start` hook. Container persistence (`container_persistent: true`) means clones survive across sessions. |
| Cloud-only hindsight mode | "Local setup is complicated" | Local embedded mode is already managed by Hermes (auto-daemon, auto-stop). Cloud adds third-party API dependency and cost. | Use local embedded mode. Hermes handles the PostgreSQL daemon. |
---
## Feature Dependencies
```
Default Repos
└──requires──> Git credentials mounted into Docker container
└──requires──> Security review of credential exposure
Hindsight Memory
└──requires──> OpenRouter API key for LLM extraction (already in .env)
└──requires──> ~500MB free disk for local embedded PostgreSQL daemon
└──enhances──> Every other feature (better cross-session context)
Daily Cron Report
└──requires──> Cron system active (✓ v1.0)
└──requires──> Telegram delivery channel (✓ v1.0)
└──requires──> Session querying script or skill
└──requires──> Read access to ~/.hermes/state.db
└──enhances──> Jira skill (✓ v1.0) for ticket data in reports
Stale Session Archive
└──requires──> SessionDB.export_session() API
└──requires──> Archive storage location (~/.hermes/archive/sessions/)
└──requires──> Cron job to trigger weekly (cron active ✓)
└──enhances──> Daily report (report can mention what will be archived)
```
### Dependency Notes
- **Default Repos requires git credentials:** The Docker container has no SSH keys or GitHub tokens. Must mount either `~/.ssh/` (read-only, scoped deploy key only) or a GitHub token via `docker_forward_env`.
- **Hindsight enhances everything:** Once hindsight is active, every session's facts feed the knowledge graph. This enriches daily reports with cross-session context.
- **Stale Archive enhances Daily Report:** The report can include "N sessions will be archived this week" as an early warning. Implement archive after report so the user sees what's coming.
---
## MVP Recommendation
### Prioritize (v1.1 Launch)
1. **Hindsight memory provider** — Config + env var. Quickest win, immediately useful in every session. Pure configuration, no code.
2. **Default repos auto-clone** — Plugin hook + git credential mount. Fills the biggest UX gap. Security review of credential mounting is the gating item.
3. **Daily report cron** — Skill-backed cron job. Needs prompt iteration to get right but delivers immediate operational visibility.
4. **Stale session archive** — No-agent script. Lowest priority because it's destructive and benefits from having reporting working first.
### Defer (v1.2+)
| Feature | Reason to Defer |
|---------|----------------|
| On-demand repo cloning skill | Nice-to-have once default cloning works. The user can already ask the agent to clone a repo manually. |
| Jira integration in daily report | Additive to basic report. Wait until report format is stable. |
| Archive restore script | Archive files are text-searchable JSON. Restore is low urgency. |
| Custom ngn-agent plugin package | Only worth it if the agent is shared across a team. |
### Ordering Rationale
Hindsight first because it's zero-risk and makes everything else better. Default repos second because they're needed for productive sessions but require security-sensitive credential mounting. Reporting third because it depends on having active sessions to report on. Archiving last because it's destructive and should only run after the user can verify through reports what will be affected.
---
## Implementation Notes
### Default Repos — Technical Approach
**Mechanism:** Hermes plugin hook `on_session_start` or shell hook `pre_llm_call` with `is_first_turn=True`.
```python
def clone_default_repos(session_id, model, platform, **kwargs):
import subprocess, os
repos = ["rai-ops", "rai-deployment", "rai-devtools"]
for repo in repos:
path = f"/workspace/{repo}"
if not os.path.exists(path):
subprocess.run(["git", "clone", f"git@github.com:rai-apps/{repo}.git", path])
def register(ctx):
ctx.register_hook("on_session_start", clone_default_repos)
```
**Git credential mount options (in order of security preference):**
1. **Read-only deploy key per repo** — Most secure. Mount only the deploy key, not full `~/.ssh/`.
2. **GitHub fine-grained token** via `docker_forward_env` — Scoped to `contents:read` on exactly 3 repos. Easy to rotate.
3. **SSH agent socket forwarding** — Keys never enter container filesystem. Requires `SSH_AUTH_SOCK` to be active.
4. **Full `~/.ssh:ro` mount** — Least secure but simplest. Exposes ALL SSH keys to container.
### Hindsight — Configuration Blueprint
```
1. hermes memory setup # interactive — select "hindsight"
2. Set mode: local_embedded
3. Set LLM provider: openrouter (uses existing .env key)
4. Verify: hermes memory status
5. Tune config at ~/.hermes/hindsight/config.json:
{
"mode": "local_embedded",
"bank_id_template": "ngn-agent-{profile}",
"recall_budget": "mid",
"memory_mode": "hybrid",
"auto_retain": true,
"auto_recall": true,
"recall_types": "observation"
}
```
### Daily Report — Skills Blueprint
Create `~/.hermes/skills/daily-report/SKILL.md` instructing the agent to:
1. Query sessions started in the last 24h from state.db
2. For each active session: get title, last message preview, token count
3. Query sessions inactive >30d (for archive warning)
4. Format as Telegram-friendly summary (3-5 bullet points per session)
5. Use `[SILENT]` if nothing to report
### Stale Archive — Script Pattern
```python
from hermes_state import SessionDB
from pathlib import Path
import json, datetime
db = SessionDB()
archive_dir = Path.home() / ".hermes" / "archive" / "sessions"
archive_dir.mkdir(parents=True, exist_ok=True)
cutoff = datetime.datetime.now() - datetime.timedelta(days=30)
for session in db.get_all_sessions():
last_active = session.get("ended_at") or session.get("started_at")
if last_active and last_active < cutoff.timestamp():
data = db.export_session(session["id"])
if data:
tmp = archive_dir / f"{session['id']}.tmp"
tmp.write_text(json.dumps(data, indent=2))
final = archive_dir / f"{session['id']}.json"
tmp.rename(final)
# Verify
verified = json.loads(final.read_text())
if verified.get("id") == session["id"]:
db.delete_session(session["id"])
```
Run as weekly no-agent cron:
```bash
hermes cron create "0 6 * * 0" \
--no-agent \
--script archive-stale-sessions.py \
--deliver telegram \
--name "Weekly Session Archive"
```
---
## Feature Prioritization Matrix
| Feature | User Value | Implementation Cost | Priority |
|---------|------------|---------------------|----------|
| Hindsight memory provider | HIGH | LOW | P1 |
| Default repo cloning | HIGH | LOW-MEDIUM | P1 |
| Daily Telegram report | MEDIUM | LOW-MEDIUM | P1 |
| Stale session archive | MEDIUM | MEDIUM | P1 |
| On-demand repo cloning | MEDIUM | LOW | P2 |
| Jira integration in report | MEDIUM | MEDIUM | P2 |
| Archive restore | LOW | LOW | P3 |
| Custom ngn-agent plugin | MEDIUM | HIGH | P3 |
**Priority key:**
- P1: Must have for v1.1 launch
- P2: Should have, add when scope allows
- P3: Nice to have, future milestone
---
## Sources
- Hermes Agent memory docs: `~/.hermes/hermes-agent/website/docs/user-guide/features/memory.md`
- Hermes Agent memory providers: `~/.hermes/hermes-agent/website/docs/user-guide/features/memory-providers.md` (Hindsight section)
- Hindsight README: `~/.hermes/hermes-agent/plugins/memory/hindsight/README.md`
- Hermes hook system: `~/.hermes/hermes-agent/website/docs/user-guide/features/hooks.md`
- Hermes cron system: `~/.hermes/hermes-agent/website/docs/user-guide/features/cron.md`
- Cron internals: `~/.hermes/hermes-agent/website/docs/developer-guide/cron-internals.md`
- Session storage: `~/.hermes/hermes-agent/website/docs/developer-guide/session-storage.md`
- SessionDB source: `~/.hermes/hermes-agent/hermes_state.py`
- Curator (skills only, not sessions): `~/.hermes/hermes-agent/agent/curator.py`
- ngn-agent PROJECT.md and initial-plan.md
- Current Hermes config: `~/.hermes/config.yaml`
---
*Feature research for: ngn-agent v1.1*
*Researched: 2026-06-14*
*Confidence: HIGH — based on documented Hermes APIs and existing ngn-agent codebase*

View File

@@ -0,0 +1,95 @@
# Domain Pitfalls: ngn-agent v1.1
**Domain:** Hermes Agent session workspace, memory & reporting integration
**Researched:** 2026-06-14
## Critical Pitfalls
Mistakes that cause rewrites or major issues.
### Pitfall 1: Docker Container Restart Loses Cloned Repos
**What goes wrong:** Docker container restarts (after idle timeout or gateway restart) lose all git repos cloned inside the container. Session-init clones are gone.
**Why it happens:** Container persistent storage (`container_persistent: true`) keeps containers alive for `lifetime_seconds` (300s = 5min) of inactivity. After that, the container is destroyed. Any `git clone` inside `/tmp` or `/root` is ephemeral.
**Consequences:** Repos disappear mid-session. The agent loses its workspace.
**Prevention:** **Always clone to a host-mounted volume.** Add `~/Projects:/workspace/repos:rw` to `docker_volumes`. The session-init script should check for existing clones on the mounted volume and only clone if missing.
**Detection:** Agent reports "directory not found" when accessing repos. Script always re-clones (slow) instead of checking `.git` directory existence.
### Pitfall 2: Memory Provider Conflict (Multiple External Providers)
**What goes wrong:** Configuring two external memory providers (e.g., Hindsight + Honcho) silently fails — only the first is registered.
**Why it happens:** `MemoryManager.add_provider()` explicitly rejects a second external provider with a warning (agent/memory_manager.py:342-354).
**Consequences:** User thinks both are active but only one works. No error message visible outside logs.
**Prevention:** Set `memory.provider: hindsight` and nothing else. Never add a second external provider.
**Detection:** `hermes memory list` shows only one provider. Check `~/.hermes/hermes-agent/logs/` for "Rejected memory provider" warning.
### Pitfall 3: Cron Job Prompt Injection via Skill Content
**What goes wrong:** A skill loaded by a cron job contains hidden prompt-injection payload that causes the cron LLM to take unintended actions.
**Why it happens:** Cron jobs load skill content at runtime via `_build_job_prompt()`. Skill content is scanned for injection patterns, but false negatives are possible (cron/scheduler.py:1249-1303).
**Consequences:** Cron job runs with auto-approved tools (cron jobs have `approvals.cron_mode: deny` but denial is for tool approval, not LLM output).
**Prevention:** Keep cron job skills simple and vetted. Use `no_agent` scripts for deterministic operations.
**Detection:** Cron output contains unexpected content. Check `cron/output/<job_id>/` for anomalous responses.
## Moderate Pitfalls
### Pitfall 1: Hindsight Cloud API Rate Limits
**What goes wrong:** Hindsight API rate-limits or throttles requests, causing memory writes to silently fail (async, non-blocking in MemoryManager).
**Why it happens:** `sync_turn()` is dispatched to a background thread. Failures are logged as warnings, not surfaced to the agent or user.
**Consequences:** Memory loss — agent thinks it saved facts but they never persisted.
**Prevention:** Monitor `~/.hermes/hermes-agent/logs/` for "sync_turn failed" warnings. Consider Hindsight local mode if Cloud proves unreliable.
**Detection:** `grep "sync_turn failed" ~/.hermes/hermes-agent/logs/*`
### Pitfall 2: SSH Key Exposure Inside Docker
**What goes wrong:** Hermes agent running inside Docker has read access to `~/.ssh/` via mounted volume.
**Why it happens:** The agent has file read tools. If an attacker compromises the agent (prompt injection), they could exfiltrate SSH keys.
**Consequences:** Private SSH keys leaked. Access to all repos the keys authorize.
**Prevention:**
- Mount `~/.ssh:ro` (read-only, keys can't be modified by agent)
- Use a **deploy key** (per-repo, read-only) instead of personal SSH key
- Set `ssh-add -l` to verify key restrictions
- Consider HTTPS + personal access token (scoped, revocable) instead of SSH
**Detection:** Monitor Docker container network egress for unexpected outbound connections.
### Pitfall 3: Shell Init Script Blocking Container Start
**What goes wrong:** The session-init.sh script hangs (git clone needs SSH key passphrase, network timeout, etc.), blocking the Docker shell.
**Why it happens:** `shell_init_files` runs synchronously before the shell prompt appears. A hanging script prevents the agent from starting.
**Consequences:** Agent gets a timeout error from the terminal backend. Session is stuck.
**Prevention:** Add timeout to clone operations: `timeout 30 git clone ...`. Wrap script in `(sleep 5; ...) &` for async init. Add `set -euo pipefail` for early failure detection.
**Detection:** Docker exec test: `docker exec <container> /bin/bash -c "echo test"` to verify shell responsiveness.
## Minor Pitfalls
### Pitfall 1: Hindsight API Key in Git History
**What goes wrong:** `.env` containing `HINDSIGHT_API_KEY` gets committed to a git repo.
**Why it happens:** Developer accidentally stages `.env` files.
**Prevention:** `/Users/bapung/.hermes/` is outside the ngn-agent repo. No risk unless `.env` is copied into a repo directory.
### Pitfall 2: DEFAULT_REPOS Superposition
**What goes wrong:** Two different session-init scripts or skills try to clone the same repo simultaneously.
**Why it happens:** Both `shell_init_files` and a session-start hook try to clone.
**Prevention:** Use only ONE mechanism. Prefer `shell_init_files` as it's guaranteed to run before the agent starts.
### Pitfall 3: Cron Report Delivers to Wrong Chat
**What goes wrong:** Daily report delivers to the wrong Telegram chat.
**Why it happens:** `deliver: origin` routes to the chat where the cron job was created. If created via CLI, `origin` is missing and cron falls back to the first available home channel (cron/scheduler.py:444).
**Prevention:** Explicitly set `deliver: telegram:474440517` (the ngn-agent DM) instead of `deliver: telegram` or `deliver: origin`.
**Detection:** Check cron delivery errors via `hermes cron list`.
## Phase-Specific Warnings
| Phase Topic | Likely Pitfall | Mitigation |
|-------------|---------------|------------|
| Hindsight activation | Provider conflict with other external provider | Verify `memory.provider` is set to only `hindsight` |
| Docker SSH volume | Key exposure via agent | Use deploy keys, read-only mount, monitor egress |
| Session init script | Blocking clone hangs container | Add timeouts, async background mode |
| Daily report skill | Poor quality LLM summaries | Iterate skill prompt; test with `hermes cron run <id>` |
| Stale cleanup script | Deleting active sessions | Add dry-run mode; check `last_updated` carefully |
| Docker volumes | Path mismatch between host/container | Use absolute paths in `docker_volumes` config |
| Git clone auth | SSH key passphrase prompt | Use key without passphrase or `ssh-agent` forwarding |
## Sources
- Hermes v0.16.0 source: `agent/memory_manager.py` line 342-354 (provider conflict)
- Hermes v0.16.0 source: `agent/memory_provider.py` line 115-131 (async sync_turn, silent failure)
- Hermes v0.16.0 source: `cron/scheduler.py` line 1249-1303 (prompt injection scanning)
- Hermes v0.16.0 source: `cron/scheduler.py` line 444 (origin fallback for delivery)
- Docker container lifecycle: `container_persistent: true` + `lifetime_seconds: 300` in config.yaml
- Existing shell init script pattern: `terminal.shell_init_files: []` (currently empty)

111
.planning/research/STACK.md Normal file
View File

@@ -0,0 +1,111 @@
# Technology Stack
**Project:** ngn-agent v1.1 — Session Workspace, Hindsight & Cron Reporting
**Researched:** 2026-06-14
## Recommended Stack
### New Dependencies
| Technology | Version | Purpose | Why |
|------------|---------|---------|-----|
| `hindsight-client` | >=0.4.22 | Hindsight Cloud API client (MemoryProvider plugin) | Already bundled in Hermes; only needs pip install |
| SSH key (existing) | N/A | Git clone auth inside Docker container | Private repos need auth; `~/.ssh:ro` mount is simplest |
### Runtime Components
| Component | Location | Purpose |
|-----------|----------|---------|
| `session-init.sh` | `~/.hermes/scripts/session-init.sh` | Clone DEFAULT_REPOS into `/workspace/repos/` at shell start |
| `daily-report.md` skill | `~/.hermes/skills/daily-report.md` | Instructions for the daily cron report LLM agent |
| `stale-cleanup.sh` script | `~/.hermes/scripts/stale-cleanup.sh` | Archive sessions >30d inactive (no_agent cron) |
| `jira-sync.sh` script (optional) | `~/.hermes/scripts/jira-sync.sh` | Update Jira with session progress (no_agent cron) |
| `clone-repo.md` skill | `~/.hermes/skills/clone-repo.md` | On-demand repo cloning during a session |
### Config Changes
| Config | Location | Value |
|--------|----------|-------|
| `memory.provider` | config.yaml | `hindsight` |
| `terminal.shell_init_files` | config.yaml | `["/usr/local/bin/session-init.sh"]` |
| `terminal.docker_volumes` | config.yaml | Add `~/.ssh:/root/.ssh:ro` and `~/Projects:/workspace/repos:rw` |
| `HINDSIGHT_API_KEY` | `~/.hermes/.env` | API key from https://ui.hindsight.vectorize.io |
| `DEFAULT_REPOS` | `~/.hermes/.env` | Space-separated `org/repo` list |
### Cron Jobs
| Name | Schedule | Type | Purpose |
|------|----------|------|---------|
| `daily-report` | `0 9 * * *` | skill-backed | Daily session summary via Telegram |
| `stale-cleanup` | `0 2 * * *` | `no_agent` script | Archive sessions >30d inactive |
| `jira-sync` | `0 10 * * *` | `no_agent` script | Update Jira with session progress |
## Alternatives Considered
| Category | Recommended | Alternative | Why Not |
|----------|-------------|-------------|---------|
| Hindsight mode | **Cloud** | Local Embedded | ~200MB download + 2-4GB RAM overhead; cloud is zero-infrastructure |
| Git auth method | **SSH key mount** (`~/.ssh:ro`) | SSH agent forwarding | Agent forwarding needs host socket access; key file mount is simpler and more reliable |
| Session init method | **`shell_init_files`** | Plugin `on_session_start` hook | `shell_init_files` runs before agent starts, guaranteeing repos exist; plugin hook requires custom code |
| Cron reporting | **Hermes skill + cron** | Custom Python script | Hermes cron + delivery already exists; skill approach lets LLM compose the report flexibly |
## Installation
```bash
# 1. Install Hindsight client
uv pip install "hindsight-client>=0.4.22"
# 2. Configure Hindsight API key
echo "HINDSIGHT_API_KEY=hs_..." >> ~/.hermes/.env
# 3. Set DEFAULT_REPOS
echo "DEFAULT_REPOS=razer-ops/rai-ops razer-ops/rai-deployment razer-ops/rai-devtools" >> ~/.hermes/.env
# 4. Create session init script
cat > ~/.hermes/scripts/session-init.sh << 'SCRIPT'
#!/bin/bash
# Auto-clone DEFAULT_REPOS into the workspace
REPOS_DIR="/workspace/repos"
mkdir -p "$REPOS_DIR"
for REPO in $DEFAULT_REPOS; do
REPO_NAME=$(basename "$REPO" .git)
TARGET="$REPOS_DIR/$REPO_NAME"
if [ ! -d "$TARGET/.git" ]; then
echo "Cloning $REPO..."
git clone --depth 1 "git@github.com:${REPO}.git" "$TARGET" 2>/dev/null || \
git clone --depth 1 "https://github.com/${REPO}.git" "$TARGET"
else
echo "Updating $REPO..."
git -C "$TARGET" pull --ff-only 2>/dev/null
fi
done
SCRIPT
chmod +x ~/.hermes/scripts/session-init.sh
# 5. Create cron report skill
cat > ~/.hermes/skills/daily-report.md << 'SKILL'
# daily-report
[Skill content as documented in ARCHITECTURE.md]
SKILL
# 6. Create stale cleanup script
cat > ~/.hermes/scripts/stale-cleanup.sh << 'SCRIPT'
[Script to find & archive sessions >30d]
SCRIPT
chmod +x ~/.hermes/scripts/stale-cleanup.sh
# 7. Update config.yaml (add volumes, shell_init_files, memory.provider)
# 8. Restart gateway
hermes gateway restart
```
## Sources
- Hermes v0.16.0 source: `plugins/memory/hindsight/__init__.py` — Hindsight MemoryProvider
- Hermes v0.16.0 source: `agent/memory_manager.py` — MemoryManager orchestration
- Hermes v0.16.0 source: `cron/scheduler.py` — Cron execution engine
- Hermes v0.16.0 source: `cron/jobs.py` — Job definition & delivery
- Hermes v0.16.0 source: `gateway/hooks.py` — Event hook system
- Hindsight documentation: https://hindsight.vectorize.io

View File

@@ -0,0 +1,225 @@
# Research Summary: ngn-agent v1.1 — Session Lifecycle, Memory & Reporting
**Project:** ngn-agent v1.1
**Domain:** Platform engineering agent (Hermes Agent-based configuration/adoption)
**Researched:** 2026-06-14
**Overall confidence:** HIGH
## Executive Summary
ngn-agent v1.1 adds three features atop the existing Hermes Agent installation: DEFAULT_REPOS auto-clone into session workspaces, Hindsight long-term memory provider, and daily cron reporting with stale session lifecycle management (30d archive) plus Jira integration. All three integrate cleanly with existing v1.0 infrastructure using documented Hermes extension points — no core source changes, no greenfield work, no new infrastructure.
**The recommended approach: additive configuration layer.** Every feature maps to an existing Hermes mechanism: `shell_init_files` for repo cloning, `memory.provider: hindsight` for memory, `hermes cron create` for reporting and archiving. The only new code is two shell scripts (session-init, stale-cleanup) and one skill markdown file (daily-report). Installation time is under 2 hours total.
**Key risks and mitigations:**
1. **Docker container restart loses cloned repos** — Mitigate by cloning to a host-mounted volume (`~/Projects:/workspace/repos:rw`)
2. **Hindsight Cloud API reliability** — Monitor logs for `sync_turn failed`; have local embedded mode as fallback
3. **SSH credential exposure inside Docker** — Use read-only deploy keys scoped per repo; never mount full `~/.ssh/`
4. **Memory provider conflict** — Set `memory.provider: hindsight` only; never add a second external provider
## Key Findings
### Recommended Stack
The stack is almost entirely existing Hermes infrastructure plus three small additions. See [STACK.md](./STACK.md) for full details.
**Core additions:**
- `hindsight-client>=0.4.22`: Python client for Hindsight Cloud API (already bundled as Hermes MemoryProvider plugin; just needs `uv pip install`)
- SSH key mount (existing): Git clone auth inside Docker — `~/.ssh:/root/.ssh:ro` or deploy key per repo
- `session-init.sh`: Shell script executed at terminal start via `terminal.shell_init_files` — clones DEFAULT_REPOS into `/workspace/repos/`
- `daily-report.md` skill: Hermes skill-backed cron job — agent composes daily session summary and sends via Telegram
- `stale-cleanup.sh`: `no_agent` cron script — exports sessions inactive >30d to JSON archive, deletes from live DB
**Config changes required:**
| Config | Value |
|--------|-------|
| `memory.provider` | `hindsight` |
| `terminal.shell_init_files` | `["/usr/local/bin/session-init.sh"]` |
| `terminal.docker_volumes` | Add `~/.ssh:/root/.ssh:ro` and `~/Projects:/workspace/repos:rw` |
| `HINDSIGHT_API_KEY` | Set in `~/.hermes/.env` |
| `DEFAULT_REPOS` | Space-separated `org/repo` list in `~/.hermes/.env` |
**Alternatives considered:**
| Decision | Recommended | Alternative Rejected |
|----------|-------------|---------------------|
| Hindsight mode | **Cloud** (zero infra) | Local embedded (~200MB download, 2-4GB RAM overhead) |
| Git auth method | **SSH key mount** | SSH agent forwarding (needs host socket, less reliable) |
| Session init hook | **`shell_init_files`** | Plugin `on_session_start` hook (runs after agent starts, not guaranteed before first prompt) |
| Cron mechanism | **Hermes skill + cron** | Custom Python script (wastes existing delivery infrastructure) |
### Expected Features
See [FEATURES.md](./FEATURES.md) for complete landscape, dependencies, and prioritization.
**Must have (table stakes — P1 for v1.1):**
- **DEFAULT_REPOS auto-cloned** in every new session — Manual clone per session is the #1 UX complaint. `shell_init_files` runs before agent starts, guaranteeing repos are present.
- **Cross-session persistent memory** — Built-in MEMORY.md is 2.2k chars frozen at session start. Hindsight provides entity-aware KG with semantic recall across all sessions.
- **Daily operational report** — Invisible work erodes trust. Daily Telegram report shows what the agent did, what sessions were active.
- **Stale session cleanup** — Sessions pile up indefinitely. 30d inactivity → archive to JSON → delete from live DB.
**Should have (differentiators — P2 for v1.1):**
- **Knowledge graph memory (Hindsight)** — Entity-aware cross-session recall with LLM synthesis (`hindsight_reflect`), not just FTS5 text search
- **On-demand repo cloning** — User says "clone rai-pipeline" mid-session, agent does it without leaving the conversation
- **Jira-integrated daily report** — Report includes Jira ticket status and session→ticket correlations using existing `ngn-jira` skill
- **Zero-cost stale cleanup** — `no_agent: true` cron = deterministic script, zero LLM token cost
**Defer (v1.2+):**
- On-demand repo cloning skill (trivial once default cloning works; user can already ask manually)
- Archive restore script (JSON files are text-searchable; low urgency)
- Custom ngn-agent plugin package (only valuable if shared across a team)
**Anti-features (avoid):**
- Custom scheduler (Hermes cron already handles this)
- Custom memory provider implementation (Hindsight is production-ready and bundled)
- Persistent Docker image with pre-cloned repos (image would be large, stale quickly)
- Cloud-only hindsight mode (local embedded is managed by Hermes; Cloud adds dependency + cost)
### Architecture Approach
See [ARCHITECTURE.md](./ARCHITECTURE.md) for full component boundaries, data flows, and patterns.
All v1.1 features are an **additive plugin + script + configuration layer** around Hermes' built-in extension points. No Hermes core code is modified.
**Major components:**
1. **Hindsight Memory Provider** — Cross-session memory with knowledge graph, entity resolution, semantic recall. Communicates with Hermes agent loop (pre-turn recall, post-turn retain), local PostgreSQL, OpenRouter (LLM extraction).
2. **Repo Clone Hook** (`session-init.sh`) — On session start, clones DEFAULT_REPOS from `~/.hermes/.env` into host-mounted `/workspace/repos/`. Uses `shell_init_files` mechanism (not plugin hooks) for guaranteed execution before agent starts.
3. **Daily Report Skill** (`daily-report.md`) — Skill-backed cron job. Instructs agent to query SessionDB for recent sessions, Hindsight for cross-session facts, Jira for ticket updates. Format as Telegram-friendly summary.
4. **Session Archive Script** (`stale-cleanup.sh`) — No-agent cron script. Queries SessionDB for sessions inactive >30d, exports to JSON, deletes from live DB. Deterministic, zero LLM cost.
5. **Built-in Memory (fallback)** — Always-active fallback for critical facts via MEMORY.md/USER.md, frozen at session start.
**Four architectural patterns to follow:**
1. **Plugin Hook for Session Init**`ctx.register_hook("on_session_start", handler)` for custom initialization per session (or `shell_init_files` for guaranteed gating)
2. **Skill-Backed Cron Jobs** — Cron jobs that load a skill with structured instructions; agent produces report guided by skill context
3. **No-Agent Script for Deterministic Automation**`no_agent: true` cron jobs for data gathering, archiving, threshold checks
4. **Export-Before-Delete for Data Safety** — Before removing any data, export to archive file first; verify integrity before deleting
**Anti-patterns to avoid:**
- Monkey-patching Hermes core (overwritten by auto-updates)
- Direct `state.db` SQL queries (schema changes between releases; use SessionDB API)
- Storing credentials in workspace files (prompt injection exfiltration risk)
### Critical Pitfalls
See [PITFALLS.md](./PITFALLS.md) for all 10 pitfalls with prevention and detection.
**Top 5 critical:**
1. **Docker container restart loses cloned repos** — Container destroyed after `lifetime_seconds: 300` of inactivity. Repos cloned to ephemeral container filesystem disappear. **Prevention:** Always clone to host-mounted volume (`~/Projects:/workspace/repos:rw`). Script must check for existing `.git` directory before cloning.
2. **Memory provider conflict**`MemoryManager.add_provider()` rejects a second external provider (memory_manager.py:342-354). Setting two external providers silently fails — only first is registered. **Prevention:** Set `memory.provider: hindsight` and nothing else.
3. **Cron job prompt injection via skill content** — Cron jobs load skill content at runtime. Scanning detects patterns but false negatives are possible (cron/scheduler.py:1249-1303). **Prevention:** Keep cron skills simple and vetted. Use `no_agent` scripts for deterministic operations.
4. **SSH key exposure inside Docker** — Agent with file-read tools inside Docker has read access to mounted `~/.ssh/`. Prompt injection could exfiltrate keys. **Prevention:** Mount `~/.ssh:ro` (read-only), use deploy keys per repo, consider HTTPS + scoped token instead of SSH.
5. **Shell init script blocking container start**`shell_init_files` runs synchronously before shell prompt. Hanging git clone blocks agent startup. **Prevention:** Add `timeout 30` to clone operations, wrap in `(sleep 5; ...) &` for async init.
## Implications for Roadmap
Based on research, four phases in dependency order:
### Phase 1: Hindsight Memory Provider
**Rationale:** Independent, zero-risk, enhances every other feature. Pure configuration — no scripts, no volumes, no cron changes. Quickest win (~25 min).
**Delivers:** Cross-session persistent memory with knowledge graph, entity resolution, semantic recall via Hindsight Cloud API.
**Addresses:** Cross-session persistent memory (table stakes) + Knowledge graph memory (differentiator)
**Uses:** `hindsight-client>=0.4.22`, `memory.provider: hindsight` config, `HINDSIGHT_API_KEY` env var
**Implements:** Hindsight Memory Provider component
**Avoids:** Pitfall 2 — Memory provider conflict (set only `hindsight`, never add second external)
**Research flag:** LOW — Well-documented Hermes configuration step. Verify Hindsight Cloud API availability and free tier limits during setup.
### Phase 2: Default Repos Auto-Clone + Credential Mount
**Rationale:** Second priority — fills the biggest UX gap (repos missing every session). Requires security-sensitive credential mounting, so needs careful implementation.
**Delivers:** DEFAULT_REPOS auto-cloned into every new session workspace via `shell_init_files` script. On-demand cloning capability (basic — user asks, agent clones).
**Addresses:** Default repos auto-cloned (table stakes) + On-demand repo cloning (differentiator)
**Uses:** `terminal.shell_init_files`, `terminal.docker_volumes` (SSH mount + workspace volume), `session-init.sh` script
**Implements:** Repo Clone Hook component
**Avoids:**
- Pitfall 1 — Lost clones on container restart (mitigated by host volume mount `~/Projects:/workspace/repos:rw`)
- Pitfall 5 — Blocking init script (add `timeout 30` to git clone, consider async wrapping)
- Pitfall 4 — SSH key exposure (use deploy keys, read-only mount)
**Research flag:** MEDIUM — SSH credential mount security approach (deploy key vs token vs agent forwarding) needs final decision during planning. Test both `~/.ssh:ro` and HTTPS+token approaches.
### Phase 3: Daily Cron Report
**Rationale:** Third priority — needs active sessions to report on. Phase 1+2 ensure sessions have memory and repos, making sessions productive. Now we can report on them.
**Delivers:** Daily Telegram report at 09:00 listing active sessions, session titles, last message previews, token counts. Skill-backed agent composes the summary.
**Addresses:** Daily operational report (table stakes) + Jira integration (differentiator, stretch goal)
**Uses:** `daily-report.md` skill, `hermes cron create`, existing Telegram delivery channel, existing `ngn-jira` skill
**Implements:** Daily Report Skill component
**Avoids:**
- Pitfall 3 — Cron prompt injection (keep skill simple, vetted)
- Minor Pitfall 3 — Wrong chat delivery (set `deliver: telegram:474440517` explicitly)
**Research flag:** MEDIUM — Daily report skill prompt quality needs iteration. The skill instructs the agent what to query and how to format. Plan for at least 2-3 prompt refinements after initial deploy. Jira integration depends on `ngn-jira` skill stability.
### Phase 4: Stale Session Archive (30d)
**Rationale:** Last priority because it's destructive. Should only run after reporting is working so user can see in daily reports what sessions will be affected before archiving runs.
**Delivers:** Weekly (Sunday 06:00) archival of sessions inactive >30d. Export to JSON in `~/.hermes/archive/sessions/`, delete from live DB. Summary delivered to Telegram.
**Addresses:** Stale session cleanup (table stakes)
**Uses:** `stale-cleanup.sh` script, `hermes cron create --no-agent`, `SessionDB.export_session()` / `delete_session()`
**Implements:** Session Archive Script component
**Avoids:**
- Pitfall pattern — Export-before-delete for data safety (write JSON, verify, then delete)
- Moderate Pitfall — Deleting active sessions (check `last_updated` carefully, use dry-run mode first)
**Research flag:** LOW — Deterministic script using documented SessionDB API. Add dry-run mode flag for initial testing. Consider archive verification step.
### Phase Ordering Rationale
- **Hindsight first** (Phase 1) — Zero-risk configuration change. Enhances every subsequent phase by providing cross-session context. No code, no scripts, no volumes.
- **Default Repos second** (Phase 2) — Independent from Hindsight (no dependency), but has the security-sensitive credential mount. Early implementation allows maximum testing of credential isolation.
- **Daily Report third** (Phase 3) — Needs active sessions producing data to report on. Both Phase 1 and 2 contribute to session quality. Report can also surface Hindsight memory patterns.
- **Stale Archive fourth** (Phase 4) — Destructive operation. User should see via daily reports what will be archived before the archive runs. Install archive cron after report cron so there's visible feedback first.
### Research Flags
Phases needing deeper research during planning:
- **Phase 2 (Default Repos):** SSH credential mount strategy — deploy key vs fine-grained token vs agent forwarding vs full `~/.ssh:ro`. Tradeoffs between security and simplicity need a final decision. Also verify `shell_init_files` execution ordering guarantees.
- **Phase 3 (Daily Report):** Skill prompt design for useful LLM-generated summaries. Jira API scoping — what ticket data to include, how to correlate sessions to tickets. The Jira integration scope (basic ticket status query vs full session→ticket mapping) needs definition.
Phases with standard patterns (skip research-phase):
- **Phase 1 (Hindsight):** Pure configuration — `hermes memory setup`, pick hindsight, set env vars. Hermes docs cover this completely.
- **Phase 4 (Stale Archive):** Deterministic script using `SessionDB.export_session()` / `delete_session()` — documented API, straightforward implementation, export-before-delete pattern.
## Confidence Assessment
| Area | Confidence | Notes |
|------|------------|-------|
| Stack | HIGH | All dependencies verified against Hermes v0.16.0 source code and docs. `hindsight-client` is bundled. SSH mount is standard Docker. |
| Features | HIGH | All features map to documented Hermes extension points. No speculative functionality. Prioritization derived from actual usage patterns. |
| Architecture | HIGH | Additive layer design avoids modifying Hermes core. Every component boundary matches a documented Hermes mechanism (hooks, cron, skills, config). |
| Pitfalls | HIGH | Each pitfall is sourced from specific Hermes source lines (memory_manager.py:342, cron/scheduler.py:1249-1303, etc.). Prevention strategies are concrete and testable. |
**Overall confidence: HIGH**
### Gaps to Address
| Gap | How to Address |
|-----|----------------|
| SSH credential mount: deploy key vs token vs agent forwarding | Test all approaches during Phase 2 planning. Start with deploy keys (most secure). Document security tradeoffs. |
| Hindsight Cloud API free tier limits | Create Hindsight account, verify free tier, test with actual agent usage. Fall back to local embedded mode if Cloud is unreliable. |
| Daily report quality iteration | Ship basic report in Phase 3, then iterate prompt based on actual output. Plan 2-3 refinement cycles. |
| Jira integration scope | Define in Phase 3 planning: basic ticket status query or full session→ticket correlation? Start with basic, iterate to full. |
| Archive dry-run mode | Add `--dry-run` flag to stale-cleanup.sh for initial testing. Run manually before activating cron. |
## Sources
### Primary (HIGH confidence — Hermes v0.16.0 source code + official docs)
- `agent/memory_manager.py` lines 342-354 — Memory provider conflict logic (PITFALLS.md)
- `agent/memory_provider.py` lines 115-131 — Async sync_turn silent failure (PITFALLS.md)
- `cron/scheduler.py` lines 1249-1303 — Cron prompt injection scanning (PITFALLS.md)
- `cron/scheduler.py` line 444 — Delivery origin fallback (PITFALLS.md)
- `plugins/memory/hindsight/__init__.py` — Hindsight MemoryProvider plugin (STACK.md)
- `hermes_state.py` — SessionDB API for export/delete (ARCHITECTURE.md, FEATURES.md)
- `agent/curator.py` — Skills-only execution (FEATURES.md)
- Hermes docs: hooks.md, cron.md, session-storage.md, memory.md, memory-providers.md (ARCHITECTURE.md, FEATURES.md)
- ngn-agent `config.yaml` and `initial-plan.md` (existing v1.0 baseline)
### Secondary (MEDIUM confidence)
- Hindsight documentation at https://hindsight.vectorize.io — Cloud API details and limits (STACK.md)
- Current `~/.hermes/config.yaml` — Existing Docker volumes and cron job configuration
### Tertiary (LOW confidence — needs validation)
- SSH credential mount behavior in Docker — needs testing with actual `~/.ssh:ro` mount and git clone inside container
- Hindsight Cloud API free tier reliability at scale — needs account creation to verify
---
*Research completed: 2026-06-14*
*Ready for roadmap: yes*