Compare commits

...

10 Commits

Author SHA1 Message Date
17cd0b64aa docs(07): resolve open questions in RESEARCH.md 2026-06-15 20:24:44 +08:00
38a0d1af6d docs(07): create phase plan for Main Session Skill
- 1 plan (07-01-PLAN.md) — creates session/SKILL.md
- Single-file SKILL.md at ~/.hermes/skills/ngn-agent/session/
- Covers SKIL-04 with 7-step lifecycle procedure
- All 14 locked decisions (D-01 through D-14) embedded
- Deferred ideas scoped to Phase 8
2026-06-15 20:22:39 +08:00
d494b274d9 docs(phase-07): research session skill patterns 2026-06-15 20:19:55 +08:00
e227c70c5e docs(state): record phase 7 context session 2026-06-15 20:14:02 +08:00
e4d7f34112 docs(07): capture phase context 2026-06-15 20:13:52 +08:00
6d3fbde186 docs(06-default-repos-ssh-mount): complete 06-01 plan — SUMMARY.md
Default repos and SSH key mounts verified end-to-end.
2026-06-15 20:06:29 +08:00
2ca590edeb test(06-default-repos-ssh-mount): verify end-to-end — SSH auth, repo mounts, clone
End-to-end Docker verification confirmed:
- SSH keys mounted (:ro) and Bitbucket auth succeeds
- All 3 DEFAULT_REPOS mounted at /workspace/<name> with .git present
- session-init.sh runs and reports all repos verified
- On-demand git clone works (REPO-02 capability)
- Parent /workspace mount is :rw (subpath mounts work)
- Automated verification: 5/5 tests PASS
2026-06-15 20:05:53 +08:00
2c3e96b982 feat(06-default-repos-ssh-mount): add DEFAULT_REPOS to .env and update config.yaml
- Added DEFAULT_REPOS=rai-ops,rai-deployment,rai-devtools to ~/.hermes/.env
- Added 4 SSH key mounts (:ro) to docker_volumes: id_ed25519razer, id_rsa, config, known_hosts
- Added 3 repo mounts (:rw) to docker_volumes: rai-ops, rai-deployment, rai-devtools
- Set shell_init_files to ['/usr/local/bin/session-init.sh']
- Added DEFAULT_REPOS to docker_forward_env
- Verified YAML validity, all mounts correct, original entries preserved
2026-06-15 20:05:07 +08:00
ea56c05257 feat(06-default-repos-ssh-mount): create session-init.sh mount verification script
- Non-blocking shell script that verifies DEFAULT_REPOS mounts at session start
- Uses set -uo pipefail (NOT set -e) for graceful handling of missing repos
- Reads DEFAULT_REPOS from environment, splits comma-separated list
- Checks /workspace/<repo>/.git for each repo (not just directory existence)
- Always exits 0 — session starts regardless of mount status
- Located at ~/.hermes/scripts/session-init.sh (outside repo)
2026-06-15 20:04:18 +08:00
42ad94600b docs(06): create phase 6 plan — SSH mount, repo volumes, session-init 2026-06-14 22:14:22 +08:00
9 changed files with 1803 additions and 25 deletions

View File

@@ -28,7 +28,7 @@ The agent must NEVER mutate real infrastructure beyond what the limited IAM role
### Active
- [ ] **MEM-01**: Hindsight memory provider enabled for cross-session recall
- [ ] **REPO-01**: DEFAULT_REPOS auto-cloned into new sessions via shell_init_files
- [ ] **REPO-01**: DEFAULT_REPOS mounted into new sessions from host filesystem
- [ ] **REPO-02**: On-demand additional repo cloning during session
- [ ] **SKIL-04**: Main ngn-agent session skill — session init, Jira ticket creation, doc loading, session-end updates
- [ ] **CRON-01**: Daily session summary report delivered via Telegram

View File

@@ -22,7 +22,7 @@
**Milestone Goal:** Productionize session workspace with default repos, upgrade to persistent cross-session memory (hindsight), and operationalize daily reporting with session lifecycle management.
- [ ] **Phase 5: Hindsight Memory Provider** — Enable cross-session persistent memory with entity-aware recall via Hindsight Cloud API
- [ ] **Phase 6: Default Repos & SSH Mount**Auto-clone DEFAULT_REPOS into every new session with secure credential mounting
- [ ] **Phase 6: Default Repos & SSH Mount**Mount DEFAULT_REPOS into every new session workspace with direct host filesystem mounts + SSH credential mounting
- [ ] **Phase 7: Main Session Skill** — Session lifecycle orchestration skill covering init-to-close workflow
- [ ] **Phase 8: Cron Reporting** — Daily session summaries, stale session archiving, and Jira integration
@@ -43,7 +43,7 @@ Plans:
- [ ] 05-01-PLAN.md — Hindsight Memory Provider: Create config.json, set env var, activate provider, verify
### Phase 6: Default Repos & SSH Mount
**Goal**: Default repos auto-cloned into every new session with secure credential mounting for git operations
**Goal**: Default repos mounted directly from host filesystem into every new session workspace with secure SSH credential mounting for git operations
**Depends on**: Nothing (independent from Phase 5)
**Requirements**: REPO-01, REPO-02
**Success Criteria** (what must be TRUE):
@@ -52,7 +52,10 @@ Plans:
3. User can request additional repo cloning mid-session and agent clones it via git command in Docker
4. SSH credentials are mounted read-only inside Docker (verified by container inspection)
5. Session init script completes within 30s timeout and doesn't block agent startup
**Plans**: TBD
**Plans**: 1 plan
Plans:
- [ ] 06-01-PLAN.md — SSH key + repo volume mounts, session-init.sh, DEFAULT_REPOS config
### Phase 7: Main Session Skill
**Goal**: Full session lifecycle orchestration skill covering the `initial-plan.md` workflow — init to close
@@ -60,11 +63,14 @@ Plans:
**Requirements**: SKIL-04
**Success Criteria** (what must be TRUE):
1. Agent detects similar previous sessions via hindsight on session start
2. Agent loads DEFAULT_REPOS into workspace on session init
3. Agent creates a Jira ticket for the session task automatically
4. Agent loads relevant Confluence docs for context
5. Agent updates docs and Jira ticket at session end with results summary
**Plans**: TBD
2. Agent prompts for Jira ticket creation (Task type, configurable project, optional epic)
3. Agent loads relevant Confluence docs for context (searched by tag)
4. Agent prompts for Jira/Confluence updates at session end
5. Session summary auto-saved to hindsight (no prompt)
**Plans**: 1 plan
Plans:
- [ ] 07-01-PLAN.md — Main Session Skill: create session/SKILL.md with full init→work→close lifecycle
### Phase 8: Cron Reporting
**Goal**: Daily operational reporting with stale session archiving and Jira integration
@@ -87,6 +93,6 @@ Plans:
| 3. Telegram Gateway | v1.0 | — | Complete | 2026-06-14 |
| 4. Skills & Integrations | v1.0 | — | Complete | 2026-06-14 |
| 5. Hindsight Memory Provider | v1.1 | 0/1 | Not started | - |
| 6. Default Repos & SSH Mount | v1.1 | 0/TBD | Not started | - |
| 7. Main Session Skill | v1.1 | 0/TBD | Not started | - |
| 6. Default Repos & SSH Mount | v1.1 | 0/1 | Not started | - |
| 7. Main Session Skill | v1.1 | 0/1 | Not started | - |
| 8. Cron Reporting | v1.1 | 0/TBD | Not started | - |

View File

@@ -3,15 +3,15 @@ gsd_state_version: 1.0
milestone: v1.1
milestone_name: Session Lifecycle, Memory & Reporting
status: executing
stopped_at: Phase 6 context gathered
last_updated: "2026-06-14T13:57:38.427Z"
last_activity: 2026-06-14 -- Phase 05 execution started
stopped_at: Phase 7 context gathered
last_updated: "2026-06-15T12:13:57.820Z"
last_activity: 2026-06-15 -- Phase 06 execution started
progress:
total_phases: 4
completed_phases: 1
total_plans: 1
completed_plans: 1
percent: 25
completed_phases: 2
total_plans: 2
completed_plans: 2
percent: 50
---
# Project State
@@ -21,14 +21,14 @@ progress:
See: .planning/PROJECT.md (updated 2026-06-14)
**Core value:** Agent must NEVER mutate real infrastructure beyond what the limited IAM role permits
**Current focus:** Phase 05hindsight-memory-provider
**Current focus:** Phase 06default-repos-ssh-mount
## Current Position
Phase: 05 (hindsight-memory-provider) — EXECUTING
Phase: 06 (default-repos-ssh-mount) — EXECUTING
Plan: 1 of 1
Status: Executing Phase 05
Last activity: 2026-06-14 -- Phase 05 execution started
Status: Executing Phase 06
Last activity: 2026-06-15 -- Phase 06 execution started
Progress: [░░░░░░░░░░] 0%
@@ -70,7 +70,7 @@ None yet.
## Session Continuity
Last session: 2026-06-14T13:57:38.419Z
Stopped at: Phase 6 context gathered
Resume file: .planning/phases/06-default-repos-ssh-mount/06-CONTEXT.md
Last session: 2026-06-15T12:13:57.813Z
Stopped at: Phase 7 context gathered
Resume file: .planning/phases/07-main-session-skill/07-CONTEXT.md
Next action: /gsd-plan-phase 5 (Hindsight Memory Provider)

View File

@@ -0,0 +1,390 @@
---
phase: 06-default-repos-ssh-mount
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- ~/.hermes/config.yaml
- ~/.hermes/.env
- ~/.hermes/scripts/session-init.sh
autonomous: true
requirements:
- REPO-01
- REPO-02
must_haves:
truths:
- "New Hermes Docker container has SSH keys mounted at /root/.ssh/ — git clone to Bitbucket works without manual auth"
- "DEFAULT_REPOS (rai-ops, rai-deployment, rai-devtools) are available at /workspace/<name> in every new session"
- "Container restart does NOT lose repo mounts — repos persist because they're host-mounted, not cloned"
- "SSH credentials are mounted read-only inside Docker — agent cannot modify keys even as root"
- "session-init.sh logs repo mount status at shell start without blocking the agent prompt"
- "DEFAULT_REPOS is configurable via .env — user adds/removes repos by editing one variable + docker_volumes"
artifacts:
- path: "~/.hermes/scripts/session-init.sh"
provides: "Mount verification script for DEFAULT_REPOS at session start"
min_lines: 25
- path: "~/.hermes/config.yaml"
provides: "Docker volume mounts (SSH keys + repos), shell_init_files, docker_forward_env"
contains: "docker_volumes.*id_ed25519razer"
- path: "~/.hermes/.env"
provides: "DEFAULT_REPOS environment variable"
contains: "DEFAULT_REPOS"
key_links:
- from: "~/.hermes/config.yaml (docker_volumes)"
to: "~/.ssh/id_ed25519razer"
via: "volume mount"
pattern: "id_ed25519razer.*ro"
- from: "~/.hermes/config.yaml (docker_volumes)"
to: "~/Razer/rai-ops"
via: "volume mount"
pattern: "rai-ops.*rw"
- from: "~/.hermes/config.yaml (shell_init_files)"
to: "~/.hermes/scripts/session-init.sh"
via: "shell_init_files path"
pattern: "session-init.sh"
- from: "~/.hermes/.env"
to: "~/.hermes/config.yaml (docker_forward_env)"
via: "env forwarding"
pattern: "DEFAULT_REPOS"
---
<objective>
Mount DEFAULT_REPOS (rai-ops, rai-deployment, rai-devtools) directly from host filesystem into every new Hermes Docker session with SSH credentials mounted read-only for git operations, plus a lightweight session-init.sh verification script.
Purpose: Eliminate the #1 user friction point — manually cloning repos every session. Host-direct mounts preserve existing git worktrees, branches, and uncommitted changes across container restarts (D-02). SSH keys are mounted per-file as read-only (`:ro`) to limit credential exposure (D-01).
Output:
- `~/.hermes/scripts/session-init.sh` — non-blocking mount verification script
- `~/.hermes/.env``DEFAULT_REPOS=rai-ops,rai-deployment,rai-devtools`
- `~/.hermes/config.yaml` — 4 SSH key mounts, 3 repo mounts, shell_init_files, docker_forward_env additions
</objective>
<execution_context>
@/Users/bapung/.config/opencode/gsd-core/workflows/execute-plan.md
@/Users/bapung/.config/opencode/gsd-core/templates/summary.md
</execution_context>
<context>
@/Users/bapung/.planning/PROJECT.md
@/Users/bapung/.planning/ROADMAP.md
# Current Hermes config for editing
@/Users/bapung/.hermes/config.yaml
@/Users/bapung/.hermes/.env
# SSH config for reference
@/Users/bapung/.ssh/config
# Existing scripts for shebang/pattern consistency
@/Users/bapung/.hermes/scripts/ngn-jira
@/Users/bapung/.hermes/scripts/ngn-bitbucket
</context>
<tasks>
<task type="auto">
<name>Task 1: Create session-init.sh mount verification script</name>
<files>~/.hermes/scripts/session-init.sh</files>
<read_first>
~/.hermes/scripts/ngn-jira (shebang pattern)
~/.hermes/scripts/ngn-bitbucket (shebang pattern)
This file's RESEARCH.md §Code Examples for the reference implementation
</read_first>
<action>
Create `~/.hermes/scripts/session-init.sh` with the following behavior (per D-03, D-04):
- **Shebang:** `#!/bin/bash`
- **set options:** `set -uo pipefail` — deliberately NOT `-e` so missing repos don't abort the script (non-blocking session start per D-03)
- **Reads DEFAULT_REPOS** from environment (forwarded via `docker_forward_env` per D-04)
- **Splits comma-separated list** and trims whitespace from each entry
- **For each repo:** checks `[ -d "/workspace/$repo/.git" ]` — confirm it's a valid git checkout, not just an empty dir
- **Logs:**
- `[session-init] ✓ repo — mounted at /workspace/repo` on success
- `[session-init] ⚠ repo — NOT FOUND at /workspace/repo` on failure
- **Summary:** "All DEFAULT_REPOS verified" vs "Some repos missing — check docker_volumes in config.yaml"
- **Exit code:** Always 0 — session starts regardless (discretion area)
- **Empty DEFAULT_REPOS guard:** If env var unset/empty, log "[session-init] DEFAULT_REPOS not set — skipping verification" and exit 0
**Do NOT** include:
- `set -e` — would abort on first missing repo (blocks session start)
- Any `git clone`, `git pull`, or network operations — script must complete in &lt;1s (ROADMAP success criteria 5: 30s timeout)
- Any file writes or modifications — this is a read-only checker
Make the script executable: `chmod +x ~/.hermes/scripts/session-init.sh`
</action>
<verify>
<automated>bash -n ~/.hermes/scripts/session-init.sh 2>&1; chmod +x ~/.hermes/scripts/session-init.sh 2>/dev/null; stat -f "%Sp" ~/.hermes/scripts/session-init.sh | grep -q -- "-rwx"</automated>
</verify>
<acceptance_criteria>
1. Script passes bash syntax check (`bash -n` exits 0)
2. Script is executable (`stat` shows `-rwx` permissions)
3. Logic: does NOT use `set -e`, DOES use `set -uo pipefail`
4. Guard: if DEFAULT_REPOS unset, exits 0 with log message (not error)
5. Verification: `test -d "/workspace/$repo/.git"` (not just `test -d "/workspace/$repo"`)
6. Always exits 0 regardless of mount status
</acceptance_criteria>
</task>
<task type="auto">
<name>Task 2: Add DEFAULT_REPOS to .env and update config.yaml with mounts + shell_init_files + forward_env</name>
<files>~/.hermes/.env, ~/.hermes/config.yaml</files>
<read_first>
~/.hermes/.env (full file — already read in planning context)
~/.hermes/config.yaml (full file — already read in planning context)
The RESEARCH.md §Code Examples for exact mount strings
</read_first>
<action>
Make the following changes:
### A. `~/.hermes/.env` — Append DEFAULT_REPOS
At the tail of the file, before the last line (HINDSIGHT_LLM_API_KEY) or after it, add:
```bash
# DEFAULT_REPOS — repos mounted into every session workspace
# Comma-separated list. Each repo must have a matching docker_volume entry in config.yaml.
DEFAULT_REPOS=rai-ops,rai-deployment,rai-devtools
```
Place this after the LAST existing section (after the "# ngn-agent: OpenRouter fallback" block, near where JIRA_API_TOKEN and HINDSIGHT_LLM_API_KEY are). Group it with the other ngn-agent-specific vars.
### B. `~/.hermes/config.yaml` — Append SSH key mounts to `terminal.docker_volumes`
Add these 4 entries to the `docker_volumes` list (after the existing scripts mount). Each entry is a quoted string. Per D-01:
```yaml
terminal:
docker_volumes:
# ... existing entries remain unchanged ...
# SSH key mounts (read-only — per D-01)
- /Users/bapung/.ssh/id_ed25519razer:/root/.ssh/id_ed25519razer:ro
- /Users/bapung/.ssh/id_rsa:/root/.ssh/id_rsa:ro
- /Users/bapung/.ssh/config:/root/.ssh/config:ro
- /Users/bapung/.ssh/known_hosts:/root/.ssh/known_hosts:ro
# Repo mounts (read-write — per D-02)
- /Users/bapung/Razer/rai-ops:/workspace/rai-ops:rw
- /Users/bapung/Razer/rai-deployment:/workspace/rai-deployment:rw
- /Users/bapung/Razer/rai-devtools:/workspace/rai-devtools:rw
```
**WHY `known_hosts` is included (research finding):** Without `/root/.ssh/known_hosts`, SSH prompts interactively for host key confirmation on first Bitbucket connection. Since the container is non-interactive, this hangs the clone. The host's `~/.ssh/known_hosts` already contains bitbucket.org host keys (verified: 3 keys present).
### C. `~/.hermes/config.yaml` — Set `terminal.shell_init_files`
Change from `shell_init_files: []` to:
```yaml
terminal:
shell_init_files:
- /usr/local/bin/session-init.sh
```
Per D-03. The `~/.hermes/scripts/` directory is already mounted to `/usr/local/bin:ro`, so `/usr/local/bin/session-init.sh` resolves automatically.
### D. `~/.hermes/config.yaml` — Append `DEFAULT_REPOS` to `terminal.docker_forward_env`
Change from `docker_forward_env: [JIRA_EMAIL, JIRA_API_TOKEN]` to include `DEFAULT_REPOS`:
```yaml
terminal:
docker_forward_env:
- JIRA_EMAIL
- JIRA_API_TOKEN
- DEFAULT_REPOS # per D-04
```
**Important YAML formatting rules:**
- `docker_volumes` entries are list items under the existing key — append to the existing list, do NOT replace the entire list.
- `shell_init_files` replaces the existing empty list `[]` with a new list containing one item.
- `docker_forward_env` appends to the existing list — do NOT replace the existing entries.
- Maintain consistent indentation (2-space YAML).
- Preserve all other config keys untouched.
</action>
<verify>
<automated>
# Verify config.yaml is valid YAML
python3 -c "import yaml; c=yaml.safe_load(open('$HOME/.hermes/config.yaml')); volumes=c['terminal']['docker_volumes']; assert any('id_ed25519razer' in v for v in volumes), 'SSH key mount missing'; assert any('rai-ops' in v for v in volumes), 'Repo mount missing'; assert c['terminal']['shell_init_files'] == ['/usr/local/bin/session-init.sh'], 'shell_init_files wrong'; assert 'DEFAULT_REPOS' in c['terminal']['docker_forward_env'], 'DEFAULT_REPOS not in forward_env'" 2>&1
# Verify .env has DEFAULT_REPOS
grep -q 'DEFAULT_REPOS=rai-ops,rai-deployment,rai-devtools' $HOME/.hermes/.env && echo "ENV: OK" || echo "ENV: MISSING"
# Verify SSH key entries are :ro (read-only)
python3 -c "import yaml; c=yaml.safe_load(open('$HOME/.hermes/config.yaml')); vols=c['terminal']['docker_volumes']; ro=[v for v in vols if 'id_ed25519razer' in v]; assert ro and ro[0].endswith(':ro'), f'SSH key not :ro: {ro}'" 2>&1
# Verify repo entries are :rw (read-write)
python3 -c "import yaml; c=yaml.safe_load(open('$HOME/.hermes/config.yaml')); vols=c['terminal']['docker_volumes']; rw=[v for v in vols if 'rai-ops' in v]; assert rw and rw[0].endswith(':rw'), f'Repo mount not :rw: {rw}'" 2>&1
</automated>
</verify>
<acceptance_criteria>
1. `config.yaml` has 4 SSH key mount entries under `docker_volumes`, all `:ro`
2. `config.yaml` has 3 repo mount entries (`rai-ops`, `rai-deployment`, `rai-devtools`) under `docker_volumes`, all `:rw`
3. `config.yaml` `shell_init_files` is set to `["/usr/local/bin/session-init.sh"]`
4. `config.yaml` `docker_forward_env` includes `DEFAULT_REPOS` alongside `JIRA_EMAIL` and `JIRA_API_TOKEN`
5. `.env` has `DEFAULT_REPOS=rai-ops,rai-deployment,rai-devtools`
6. All YAML is valid (python yaml parser confirms)
7. Original config entries are preserved (not deleted)
</acceptance_criteria>
</task>
<task type="auto">
<name>Task 3: Verify end-to-end — SSH auth, repo mounts, script execution via Docker test</name>
<files>(no files modified — verification only)</files>
<read_first>
Phase research §Verified Findings (SSH auth, subpath mounts, known_hosts requirements)
</read_first>
<action>
Run a Docker test container with the EXACT volume mounts defined in Task 2 to verify everything works end-to-end before the agent needs it.
Use the nikolaik/python-nodejs:python3.11-nodejs20 image (same as Hermes uses).
Docker command:
```bash
docker run --rm \
-v ~/.ssh/id_ed25519razer:/root/.ssh/id_ed25519razer:ro \
-v ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro \
-v ~/.ssh/config:/root/.ssh/config:ro \
-v ~/.ssh/known_hosts:/root/.ssh/known_hosts:ro \
-v ~/Razer/rai-ops:/workspace/rai-ops:rw \
-v ~/Razer/rai-deployment:/workspace/rai-deployment:rw \
-v ~/Razer/rai-devtools:/workspace/rai-devtools:rw \
-v ~/.hermes/scripts:/usr/local/bin:ro \
-e DEFAULT_REPOS=rai-ops,rai-deployment,rai-devtools \
nikolaik/python-nodejs:python3.11-nodejs20 \
bash -c '
echo "=== 1. SSH Keys Mounted ==="
ls -la /root/.ssh/ && echo ""
echo "=== 2. SSH Authentication ==="
ssh -T git@bitbucket.org 2>&1 || true && echo ""
echo "=== 3. Repo Mounts ==="
for repo in rai-ops rai-deployment rai-devtools; do
if [ -d "/workspace/$repo/.git" ]; then
echo " ✓ $repo — mounted git repo"
else
echo " ✗ $repo — NOT FOUND"
fi
done && echo ""
echo "=== 4. session-init.sh ==="
session-init.sh && echo "exit code: $?" && echo ""
echo "=== 5. On-Demand Clone (REPO-02) ==="
git clone --depth 1 git@bitbucket.org:razersw/rai-ansible.git /workspace/rai-ansible 2>&1 && \
echo " ✓ Clone succeeded" || echo " ✗ Clone failed"
'
```
**Expected output:**
- SSH keys present at `/root/.ssh/` with correct permissions
- `ssh -T git@bitbucket.org` returns "authenticated via ssh key" (exit code 1 from SSH is expected — this is auth success, just no shell)
- All 3 repos show `✓ repo — mounted git repo`
- `session-init.sh` runs without error, shows all repos verified
- `git clone` of an additional repo succeeds
**If ANY check fails:** Diagnose and fix:
- SSH auth fails: check key permissions (need `600`/`700`), check `known_hosts` has bitbucket.org entries
- Repo mount fails: verify the repo directories exist on host at `~/Razer/<name>/`
- session-init.sh fails: debug the script logic
- Clone fails: check SSH config file mounting
Also verify the parent `/workspace` mount mode (research Pitfall 1):
```bash
docker run --rm \
-v /Users/bapung/Razer/ngn-agent:/workspace:rw \
nikolaik/python-nodejs:python3.11-nodejs20 \
mount | grep /workspace
```
This should show `rw` — NOT `ro`. If `ro`, the parent mount blocks subpath volume creation and the repo mounts will fail at container start.
</action>
<verify>
<automated>
# Run the verification and check output for success signals
TEST_OUTPUT=$(docker run --rm \
-v ~/.ssh/id_ed25519razer:/root/.ssh/id_ed25519razer:ro \
-v ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro \
-v ~/.ssh/config:/root/.ssh/config:ro \
-v ~/.ssh/known_hosts:/root/.ssh/known_hosts:ro \
-v ~/Razer/rai-ops:/workspace/rai-ops:rw \
-v ~/Razer/rai-deployment:/workspace/rai-deployment:rw \
-v ~/Razer/rai-devtools:/workspace/rai-devtools:rw \
-v ~/.hermes/scripts:/usr/local/bin:ro \
-e DEFAULT_REPOS=rai-ops,rai-deployment,rai-devtools \
nikolaik/python-nodejs:python3.11-nodejs20 \
bash -c 'ssh -T git@bitbucket.org 2>&1 | grep -q "authenticated" && echo "SSH_AUTH_OK" || echo "SSH_AUTH_FAIL"; for r in rai-ops rai-deployment rai-devtools; do [ -d "/workspace/$r/.git" ] && echo "REPO_${r}_OK" || echo "REPO_${r}_FAIL"; done; session-init.sh 2>&1 | grep -q "All DEFAULT_REPOS verified" && echo "SCRIPT_OK" || echo "SCRIPT_FAIL"; git clone --depth 1 git@bitbucket.org:razersw/rai-ansible.git /tmp/test-clone 2>&1 | grep -q "done" && echo "CLONE_OK" || echo "CLONE_FAIL"' 2>&1)
echo "$TEST_OUTPUT"
echo "$TEST_OUTPUT" | grep -q "SSH_AUTH_OK" && echo "PASS: SSH auth" || echo "FAIL: SSH auth"
echo "$TEST_OUTPUT" | grep -q "REPO_rai-ops_OK" && echo "PASS: rai-ops mounted" || echo "FAIL: rai-ops mounted"
echo "$TEST_OUTPUT" | grep -q "REPO_rai-deployment_OK" && echo "PASS: rai-deployment mounted" || echo "FAIL: rai-deployment mounted"
echo "$TEST_OUTPUT" | grep -q "REPO_rai-devtools_OK" && echo "PASS: rai-devtools mounted" || echo "FAIL: rai-devtools mounted"
echo "$TEST_OUTPUT" | grep -q "SCRIPT_OK" && echo "PASS: session-init.sh" || echo "FAIL: session-init.sh"
echo "$TEST_OUTPUT" | grep -q "CLONE_OK" && echo "PASS: on-demand clone" || echo "FAIL: on-demand clone"
</automated>
</verify>
<acceptance_criteria>
1. SSH auth succeeds — `authenticated via ssh key` response from Bitbucket
2. All 3 DEFAULT_REPOS are mounted git repos at `/workspace/<name>` (`.git` directory present)
3. `session-init.sh` runs and reports all repos verified
4. On-demand `git clone` of additional repo succeeds (verifies REPO-02 capability)
5. Parent `/workspace` mount is `:rw` (not `:ro`) — verified by mount table inspection
</acceptance_criteria>
</task>
</tasks>
<threat_model>
## Assets
| Asset | Sensitivity | Protection |
|-------|-------------|------------|
| SSH private keys (id_ed25519razer, id_rsa) | HIGH — Bitbucket access | Docker `:ro` mount prevents modification. Per-file mount (not full `~/.ssh/`) limits blast radius. |
| SSH config | MEDIUM — auth routing info | Mounted `:ro` — read-only in container. |
| Repo source code (rai-ops, rai-deployment, rai-devtools) | HIGH — proprietary code | Mounted `:rw` intentionally — agent needs to commit/push. Same exposure as having repo on host. |
| `known_hosts` | LOW — public host keys | Mounted `:ro`. Read-only, prevents MitM host key injection. |
## Trust Boundaries
| Boundary | Description |
|----------|-------------|
| Host → Docker container | SSH keys cross from macOS host into container via volume mount. Docker enforces read-only at VFS level. |
| Container → Bitbucket | Agent inside container authenticates to Bitbucket via mounted SSH keys. Network boundary. |
## STRIDE Threat Register
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-06-01 | Information Disclosure | SSH keys in Docker | mitigate | Keys mounted `:ro` — agent can read (required for auth) but cannot modify. Per-file mount (not full `~/.ssh/`) limits exposure to only the two declared keys. |
| T-06-02 | Spoofing | Bitbucket auth via stolen key | accept | Key is user's personal SSH key. Deferred to future phase: per-repo deploy keys (deferred idea in CONTEXT.md). Current mitigation: key can only be read inside container, not exfiltrated to external hosts. |
| T-06-03 | Tampering | Repo source code | accept | Repos mounted `:rw` by design — agent must create branches, commit, push. Same trust model as developer's local environment. |
| T-06-04 | Tampering | `known_hosts` | mitigate | File mounted `:ro` — prevents agent from injecting fraudulent host keys. File is from trusted host source. |
| T-06-SC | Tampering | Package installs | n/a | Zero packages installed. All changes are config edits + one shell script. |
## Residual Risk
- SSH key is readable by agent inside container. If the agent is compromised via prompt injection, the key could be read. Mitigated by: (a) key permits only Bitbucket read/write to known repos, (b) no other services use the same key, (c) per-repo deploy keys deferred to future phase.
</threat_model>
<verification>
1. All 4 Python-based YAML assertions pass for config.yaml validity
2. `grep` confirms DEFAULT_REPOS in .env
3. Docker test container confirms SSH auth, repo mounts, script execution, and on-demand clone
</verification>
<success_criteria>
1. ✅ SSH keys mounted (`:ro`) and Bitbucket auth works inside Docker (verified by container test)
2. ✅ All 3 DEFAULT_REPOS mounted at `/workspace/<name>` (verified by container test)
3. ✅ `session-init.sh` runs at shell start and reports mount status (verified by container test)
4. ✅ On-demand git clone works inside Docker (verified by container test)
5. ✅ `DEFAULT_REPOS` configurable via `.env` — one variable to add/remove repos
6. ✅ All changes are additive (no existing config removed)
7. ✅ Parent `/workspace` mount confirmed `:rw` (subpath volumes will work)
</success_criteria>
## Artifacts This Phase Produces
| Artifact | Path | Type | Purpose |
|----------|------|------|---------|
| session-init.sh | `~/.hermes/scripts/session-init.sh` | Shell script | Verifies DEFAULT_REPOS mounts at session start |
| DEFAULT_REPOS env var | `~/.hermes/.env` | Config | Defines which repos to verify |
| SSH key mounts (4) | `~/.hermes/config.yaml` → `docker_volumes` | Config | Mounts id_ed25519razer, id_rsa, config, known_hosts as `:ro` |
| Repo mounts (3) | `~/.hermes/config.yaml` → `docker_volumes` | Config | Mounts rai-ops, rai-deployment, rai-devtools as `:rw` |
| shell_init_files entry | `~/.hermes/config.yaml` | Config | Triggers session-init.sh at shell start |
| docker_forward_env entry | `~/.hermes/config.yaml` | Config | Forwards DEFAULT_REPOS into container |
<output>
Create `.planning/phases/06-default-repos-ssh-mount/06-01-SUMMARY.md` when done
</output>

View File

@@ -0,0 +1,143 @@
---
phase: 06-default-repos-ssh-mount
plan: 01
subsystem: infra
tags: docker, ssh, volume-mounts, hermes, git, bitbucket
requires:
- phase: 05-hermes-memory-hindsight
provides: Hermes config structure, .env conventions
provides:
- SSH key mounts for Bitbucket git auth
- 3 default repo mounts (rai-ops, rai-deployment, rai-devtools)
- session-init.sh mount verification script
- DEFAULT_REPOS environment variable
affects: [07-session-skill, 08-cron-reporting]
tech-stack:
added:
- session-init.sh (bash script)
patterns:
- Per-file SSH key mounts (`:ro`) instead of full directory mount
- Non-blocking shell init scripts (no `set -e`)
- Subpath volume mounts with `:rw` parent dependency
key-files:
created:
- ~/.hermes/scripts/session-init.sh
modified:
- ~/.hermes/.env
- ~/.hermes/config.yaml
key-decisions:
- "Mounted SSH keys per-file (`:ro`) rather than full `~/.ssh/` directory — limits credential exposure to only id_ed25519razer and id_rsa"
- "Mounted repos directly from host (`:rw`) instead of cloning inside container — preserves git worktrees, branches, uncommitted changes"
- "Included `known_hosts` mount — prevents SSH host key prompt from blocking non-interactive git operations"
- "session-init.sh uses `set -uo pipefail` (not `-e`) — session starts even if repos are missing"
- "Parent `/workspace` mount verified `:rw` — subpath volume mounts work correctly"
patterns-established:
- "Pattern 1: Per-file credential mounts for limited security boundary"
- "Pattern 2: Non-blocking init scripts with graceful degradation"
requirements-completed: [REPO-01, REPO-02]
duration: 2 min
completed: 2026-06-15
---
# Phase 6 Plan 1: Default Repos & SSH Mount Summary
**SSH key mounts for Bitbucket auth, 3 default repo mounts (rai-ops, rai-deployment, rai-devtools), and session-init.sh non-blocking verification script — all verified end-to-end via Docker test container**
## Performance
- **Duration:** 2 min
- **Started:** 2026-06-15T12:03:47Z
- **Completed:** 2026-06-15T12:05:58Z
- **Tasks:** 3
- **Files modified:** 3
## Accomplishments
- SSH keys (`id_ed25519razer`, `id_rsa`, `config`, `known_hosts`) mounted read-only into Docker — Bitbucket auth verified: "authenticated via ssh key"
- 3 default repos (rai-ops, rai-deployment, rai-devtools) mounted at `/workspace/<name>` with `:rw` — no re-cloning needed across sessions
- `session-init.sh` created in `~/.hermes/scripts/` — non-blocking verification at shell start, triggered via `shell_init_files`
- `DEFAULT_REPOS` env var added to `.env` and forwarded into container via `docker_forward_env`
- On-demand git clone verified working (REPO-02 capability)
- Parent `/workspace` mount confirmed `:rw` — subpath volumes will not fail
## Task Commits
Each task was committed atomically:
1. **Task 1: Create session-init.sh script**`ea56c05` (feat)
2. **Task 2: Update .env and config.yaml**`2c3e96b` (feat)
3. **Task 3: Verify end-to-end Docker test**`2ca590e` (test)
**Plan metadata:** (committed with SUMMARY below)
## Files Created/Modified
- `~/.hermes/scripts/session-init.sh` — Non-blocking mount verification script (25 lines)
- `~/.hermes/.env` — Added `DEFAULT_REPOS=rai-ops,rai-deployment,rai-devtools`
- `~/.hermes/config.yaml` — Added 4 SSH key mounts (`:ro`), 3 repo mounts (`:rw`), `shell_init_files`, `docker_forward_env` entry
## Decisions Made
- **Per-file SSH key mounts** over full `~/.ssh/` directory mount — limits credential exposure to only the keys the agent needs (id_ed25519razer, id_rsa)
- **`known_hosts` included** — without it, SSH prompts for host key confirmation and hangs in non-interactive container; host already has bitbucket.org keys
- **session-init.sh uses `set -uo pipefail`** (not `-e`) — missing repos won't abort session start
- **Host-direct repo mounts** (`:rw`) instead of cloning — preserves existing worktrees, branches, and is not lost on container restart
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 3 - Blocking] `rai-ansible` repo inaccessible for clone test**
- **Found during:** Task 3 (End-to-end verification)
- **Issue:** Plan specified `rai-ansible` for on-demand clone test, but this repo does not exist or the SSH key lacks access
- **Fix:** Used `rai-ops` (known accessible repo) for clone test, cloning to a different path (`/tmp/rai-ops-test`)
- **Files modified:** None (verification only)
- **Verification:** Clone succeeded, git repo contents visible
- **Committed in:** `2ca590e` (Task 3 commit)
**2. [Rule 3 - Blocking] Python `yaml` module not installed for validation**
- **Found during:** Task 2 (config.yaml verification)
- **Issue:** Python yaml module not available on host, blocking automated YAML validation
- **Fix:** Installed pyyaml 6.0.3 via pip3
- **Files modified:** None (host package, not in repo)
- **Verification:** All 10 YAML assertions passed
- **Committed in:** `2c3e96b` (Task 2 commit)
---
**Total deviations:** 2 auto-fixed (2 blocking)
**Impact on plan:** Both deviations minor — clone test used correct accessible repo, pyyaml installed temporarily for validation. No scope creep.
## Issues Encountered
- `rai-ansible` repo not accessible to the SSH key — used `rai-ops` cloned to alternate path instead. SSH auth itself is confirmed working.
- Python `yaml` module not installed on host — installed pyyaml for config validation.
- No pre-existing issues found.
## User Setup Required
None - no external service configuration required. SSH keys and repos already exist on the host filesystem. Changes to `~/.hermes/config.yaml` and `~/.hermes/.env` are ready for next Hermes session.
## Next Phase Readiness
- SSH auth and repo mounts fully verified — ready for Phase 7 (session skill)
- `session-init.sh` provides lightweight mount verification at shell start
- `DEFAULT_REPOS` is configurable via `.env` — user edits one variable + docker_volumes to add/remove repos
- On-demand clone capability verified — agent can clone additional repos during sessions
## Self-Check: PASSED
All commits verified, all files exist, all acceptance criteria met.
---
*Phase: 06-default-repos-ssh-mount*
*Completed: 2026-06-15*

View File

@@ -0,0 +1,297 @@
---
phase: 07-main-session-skill
plan: 01
type: execute
wave: 1
depends_on: []
files_modified: [~/.hermes/skills/ngn-agent/session/SKILL.md]
autonomous: true
requirements: [SKIL-04]
must_haves:
truths:
- Agent detects similar previous sessions via hindsight_recall on session start and presents matches with resume/fresh option
- Agent creates a Jira Task ticket when user requests it, with configurable project and optional epic from cached list
- Agent searches and loads Confluence docs by ngn-agent tag when user requests it
- Agent prompts for Jira/Confluence updates at session end (user confirms before any mutation)
- Session summary is automatically saved to hindsight at session end (no prompt — unconditional per D-12)
- Future sessions can recall this session via hindsight_recall of the saved summary
artifacts:
- path: ~/.hermes/skills/ngn-agent/session/SKILL.md
provides: Full session lifecycle orchestration instructions in Hermes SKILL.md format
min_lines: 180
key_links:
- from: session/SKILL.md Procedure Step 1
to: hindsight_recall tool
via: Tool call instruction
pattern: hindsight_recall
- from: session/SKILL.md Procedure Step 2
to: ngn-jira POST /rest/api/3/issue
via: CLI command in Procedure
pattern: ngn-jira.*POST.*issue
- from: session/SKILL.md Procedure Step 2b
to: hindsight_retain (epic cache)
via: Tool call for caching epics
pattern: hindsight_retain.*epic
- from: session/SKILL.md Procedure Step 3
to: ngn-confluence GET /rest/api/search
via: CLI command tagged search
pattern: ngn-confluence.*tag
- from: session/SKILL.md Procedure Step 5
to: ngn-jira POST comment
via: CLI command for comment
pattern: ngn-jira.*comment
- from: session/SKILL.md Procedure Step 7
to: hindsight_retain tool (session summary)
via: Unconditional tool call
pattern: hindsight_retain.*session-summary
---
<objective>
Create the main ngn-agent session orchestration skill — a Hermes SKILL.md file that guides the agent through the full session lifecycle: detect similar previous sessions, prompt for Jira ticket and Confluence docs, work, and update/save at session end.
**Purpose:** Replace the ad-hoc per-session workflow with a standardized, repeatable session lifecycle covering the `initial-plan.md` `func session()` workflow. Every session follows the same init→work→close pattern regardless of task.
**Output:** `~/.hermes/skills/ngn-agent/session/SKILL.md` — one file, zero code/installs/config changes.
</objective>
<execution_context>
@/Users/bapung/.config/opencode/gsd-core/workflows/execute-plan.md
@/Users/bapung/.config/opencode/gsd-core/templates/summary.md
</execution_context>
<context>
# Containing Artifacts for This Phase
@/Users/bapung/.planning/ROADMAP.md
@/Users/bapung/.planning/REQUIREMENTS.md
@/Users/bapung/.planning/phases/07-main-session-skill/07-CONTEXT.md
@/Users/bapung/.planning/phases/07-main-session-skill/07-RESEARCH.md
@/Users/bapung/Razer/ngn-agent/initial-plan.md
# Existing Skill Format References (4 patterns to follow)
@/Users/bapung/.hermes/skills/ngn-agent/aws-diagnostics/SKILL.md
@/Users/bapung/.hermes/skills/ngn-agent/jira/SKILL.md
@/Users/bapung/.hermes/skills/ngn-agent/confluence/SKILL.md
@/Users/bapung/.hermes/skills/ngn-agent/bitbucket/SKILL.md
</context>
<tasks>
<task type="auto">
<name>Task 1: Create session/SKILL.md with full session lifecycle procedure</name>
<read_first>
- 07-RESEARCH.md §"Example 1: session/SKILL.md (Full Content)" for the reference implementation
- 07-CONTEXT.md for all locked decisions (D-01 through D-14) to embed in the skill
- aws-diagnostics/SKILL.md, jira/SKILL.md, confluence/SKILL.md, bitbucket/SKILL.md for format fidelity
- initial-plan.md for the original func session() workflow
</read_first>
<files>
~/.hermes/skills/ngn-agent/session/SKILL.md
</files>
<action>
Create the directory `~/.hermes/skills/ngn-agent/session/` and write `SKILL.md` with:
**Frontmatter (per D-14 + existing skill convention):**
- `name: session` (matching directory name for clean `skill_view("session")` discovery)
- `description: "Main ngn-agent session lifecycle — init, work, close"`
- `tags: [ngn-agent, platform-engineering, session]`
- `category: devops`, `requires_toolsets: [terminal]`
- `version: 1.0.0`
**Sections (follow exact existing skill structure):**
### When to Use
Broad trigger conditions: "Load this skill at the START of EVERY platform engineering session, before any other work. This skill defines the standard session workflow." Include specific trigger examples (infrastructure task, Jira ticket creation, Confluence doc lookup, session end wrap-up).
### Important
- "Keep this skill loaded for the entire session" — note about re-loading via `skill_view("session")` if evicted
- D-02: Never create Jira tickets without asking first
- D-11: Never update Confluence without asking first
- D-12: Always save session summary to hindsight at end (no prompt)
- D-08: User must confirm before any Jira mutation
- Repos already mounted at `/workspace/` from Phase 6
### Procedure (7 steps — map to D-01 through D-13)
**Step 1: Check for Similar Previous Sessions (D-01)**
- Call `hindsight_recall` with query describing user's task, budget low
- Present matches in format: "Found [N] similar sessions from the last 2 weeks: [Title — Date — snippet]"
- Ask: resume (load context) or start fresh (proceed to step 2)
**Step 2: Prompt for Jira Ticket Creation (D-02, D-05, D-06, D-07)**
- Ask user if they want a Task ticket
- If yes:
1. Ask which Jira project
2. Check hindsight for cached epics (`hindsight_recall` query "jira epics cached"). If cache >24h old or user says it's wrong, refresh via `ngn-jira GET` and save via `hindsight_retain` with `tier: "epic-cache"`
3. Present cached epics, ask if user wants to set parent epic
4. Create Task via `ngn-jira POST /rest/api/3/issue` with project, summary, issuetype "Task", optional parent
5. Note the ticket key for session-end steps
- If no: proceed to step 3
**Step 3: Prompt for Confluence Docs (D-03, D-09, D-10)**
- Ask user if they want to load relevant docs
- If yes:
1. Search by tag via `ngn-confluence GET /rest/api/search?cql=tag="ngn-agent"`
2. Present matching pages (title, space, last modified)
3. Ask which pages to load
4. Load selected page content (expand=body.storage)
- If no: proceed to step 4
**Step 4: Work Phase (D-04)**
- Repos already mounted at `/workspace/` (rai-ops, rai-deployment, rai-devtools)
- Additional repo cloning: `git clone git@bitbucket.org:razersw/<repo>.git /workspace/<repo>`
- Session skill remains loaded for session-end steps
**Step 5: Session-End — Update Jira (D-08, D-12)**
- When user indicates work is complete: ask "Update Jira with summary comment?"
- If yes (and ticket exists): `ngn-jira POST /rest/api/3/issue/<KEY>/comment` with summary body
- Do NOT transition tickets without explicit user confirmation
**Step 6: Session-End — Update Confluence (D-11, D-12)**
- Ask "Create or update Confluence page documenting this session?"
- If yes: POST new page (with `labels: [{"name": "ngn-agent"}]`) or PUT update to existing
- If no: proceed
**Step 7: Save Session Summary to Hindsight (D-12, D-13)**
- **Automatic — no prompt.** Always save.
- Call `hindsight_retain` with `tier: "session-summary"` and structured content containing:
- Date, Task description, Repos worked on, Jira ticket key (or "none")
- Key Decisions, Outcomes, Next Steps
### Pitfalls (from RESEARCH.md)
Include all 6 pitfalls from the research: skill not loaded at start, epic cache too old, Confluence tag mismatch, Jira project 404, empty hindsight recall, long session eviction. Use the exact text from RESEARCH.md §Pitfalls.
### Verification (from RESEARCH.md)
Include the 6-point checklist matching the success criteria in must_haves.
**Formatting rules:**
- Code blocks inside Procedure MUST use triple-backtick with `bash` language tags for CLI commands, and plain text for hindsight tool calls
- Each numbered step should be a separate `### N. Title` heading
- Use bullet points for sub-steps, numbered lists for sequential actions
- The "Important" section must include the context-eviction reload note
- Do NOT include any deferred ideas (daily reporting, stale archive, auto-create Jira — these are Phase 8 and specifically deferred per DEF-01/02/03)
- The file must be >=180 lines to cover all decisions and procedures comprehensively
**Key content differences from the RESEARCH.md example (implement these corrections):**
1. Set `name: session` (not `ngn-agent-session`) in frontmatter — the directory name is `session/`, agent discovers as `ngn-agent/session`, so `skill_view("session")` is the expected call
2. Ensure D-08 is explicit: "Do NOT transition tickets (close/resolve) without explicit user confirmation" appears in Step 5
3. Add context-eviction reload reminder in the Important section and Pitfalls
4. Ensure the Step 7 hindsight_retain is clearly unconditional ("Do NOT ask the user — this step is automatic")
</action>
<verify>
<automated>ls ~/.hermes/skills/ngn-agent/session/SKILL.md && wc -l ~/.hermes/skills/ngn-agent/session/SKILL.md</automated>
</verify>
<done>
- File exists at `~/.hermes/skills/ngn-agent/session/SKILL.md`
- File is >=180 lines
- Frontmatter contains all required fields (name, description, tags, category, requires_toolsets, version)
- All 7 procedure steps present with correct headings
- All sections present: When to Use, Important, Procedure, Pitfalls, Verification
- Step 2 references epic cache with hindsight_retain tier epic-cache
- Step 7 indicates automatic save (no user prompt)
- Step 8 and 9 do not exist (phase only has 7 steps)
</done>
</task>
<task type="auto">
<name>Task 2: Verify skill discoverability, structure, and decision coverage</name>
<read_first>
- ~/.hermes/skills/ngn-agent/session/SKILL.md (just created in Task 1)
- 07-CONTEXT.md (decisions D-01 through D-14 for coverage check)
</read_first>
<files>
~/.hermes/skills/ngn-agent/session/SKILL.md
</files>
<action>
Run the following verification sequence:
1. **Discoverability:** Run `hermes skills list` and confirm the session skill appears in the output. If `hermes` CLI is not available, use `ls ~/.hermes/skills/ngn-agent/session/SKILL.md` to confirm file placement matches the pattern of 4 existing skills.
2. **Structure verification:** Read the created SKILL.md and confirm:
- YAML frontmatter is valid and contains: name, description, metadata.hermes.tags, metadata.hermes.category, metadata.hermes.requires_toolsets, version
- Sections present: ## When to Use, ## Important, ## Procedure, ## Pitfalls, ## Verification
- Procedure has exactly 7 numbered steps (### 1. through ### 7.)
- Step 7 heading says "Save to Hindsight" or similar — confirms automatic save
- All code blocks with CLI commands use ```bash language tag
3. **Decision coverage check:** grep the SKILL.md for each decision D-01 through D-14 to confirm it's implemented:
- D-01 → "hindsight_recall" in Step 1
- D-02 → "Would you like to create a Jira Task" in Step 2
- D-03 → "ngn-agent" tag search in Step 3
- D-04 → "Repos are already mounted" in Step 4
- D-05 → "issuetype.*Task" in Step 2 Jira POST
- D-06 → "Ask which Jira project" in Step 2
- D-07 → "epic cache" or "epic" in Step 2
- D-08 → "Do NOT transition" or "confirm" in Step 5
- D-09 → "tag.*ngn-agent" in Step 3
- D-10 → "which pages" or "user selects" in Step 3
- D-11 → "without asking" or "confirm" in Step 6
- D-12 → "no prompt" and "automatic" in Important or Step 7
- D-13 → structured summary fields (Date, Task, Repos, Jira, Decisions, Outcomes) in Step 7
- D-14 → frontmatter with name, description, tags, requires_toolsets
4. **Deferred ideas check:** grep for "daily report", "stale", "archive", "auto-create" — these MUST NOT appear in the skill content (they belong to Phase 8).
</action>
<verify>
<automated>grep -q '### 7\.' ~/.hermes/skills/ngn-agent/session/SKILL.md && grep -q 'hindsight_recall' ~/.hermes/skills/ngn-agent/session/SKILL.md && grep -q 'hindsight_retain' ~/.hermes/skills/ngn-agent/session/SKILL.md && grep -q 'ngn-jira' ~/.hermes/skills/ngn-agent/session/SKILL.md && grep -q 'ngn-confluence' ~/.hermes/skills/ngn-agent/session/SKILL.md</automated>
</verify>
<done>
- SKILL.md is discoverable by Hermes (appears in `hermes skills list` or confirmed in correct directory)
- All 14 decisions (D-01 through D-14) are implemented in the skill
- No deferred ideas (daily reporting, stale archive, auto-create) appear in the skill
- All 7 procedure steps are present and correctly ordered
- All 5 sections are present (When to Use, Important, Procedure, Pitfalls, Verification)
</done>
</task>
</tasks>
<threat_model>
## Trust Boundaries
| Boundary | Description |
|----------|-------------|
| Agent → Atlassian Cloud API | Jira/Confluence writes cross a network boundary to external SaaS. All mutations gated by user confirmation. |
| Agent → Hindsight local store | Session summary saves to local embedded PostgreSQL. Read-only recall unrestricted. |
## STRIDE Threat Register
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-07-01 | Tampering | Jira ticket creation/update (ngn-jira POST) | mitigate | D-08: Procedure Step 5 explicitly instructs agent to ask user before any Jira mutation. Step 2 also requires user prompt before ticket creation. Skill language: "Never create Jira tickets without asking the user first" in Important section. |
| T-07-02 | Tampering | Confluence page create/update (ngn-confluence POST/PUT) | mitigate | D-11: Procedure Step 6 explicitly instructs agent to ask user before any Confluence update. Skill language: "Never update Confluence without asking the user first" in Important section. |
| T-07-03 | Information Disclosure | hindsight_retain session summary | mitigate | D-13: Summary format is structured, task-level information (repos, Jira ref, decisions, outcomes) — not raw conversation transcripts. Hindsight runs in local_embedded mode (local PostgreSQL). Skill does not instruct agent to retain raw conversation. |
</threat_model>
<verification>
1. File exists at `~/.hermes/skills/ngn-agent/session/SKILL.md`
2. All 14 decisions (D-01 through D-14) are implemented — verified by grep in Task 2 ✓
3. No deferred ideas (daily reporting, stale archive, auto-create) are present ✓
4. Format matches the 4 existing ngn-agent skills (frontmatter, sections, conventions) ✓
5. Skill is discoverable by Hermes or confirmed at correct path ✓
6. All code blocks use correct syntax (bash for CLI, plain text for tool calls) ✓
</verification>
<success_criteria>
- Agent can discover and load the session skill via `skill_view("session")`
- When loaded, the skill guides the agent through the full init→prompt→work→close lifecycle
- At session start: hindsight_recall check for similar sessions (D-01), user prompted for Jira (D-02) and Confluence (D-03)
- At session end: user prompted for Jira update (D-08) and Confluence update (D-11), session summary auto-saved to hindsight (D-12/D-13)
- No write operation (Jira/Confluence) happens without user confirmation
- Epic cache managed in hindsight with refresh when stale (D-07)
</success_criteria>
<output>
Create `.planning/phases/07-main-session-skill/07-01-SUMMARY.md` when done
</output>

View File

@@ -0,0 +1,114 @@
# Phase 7: Main Session Skill - Context
**Gathered:** 2026-06-14
**Status:** Ready for planning
<domain>
## Phase Boundary
Create the main ngn-agent session orchestration SKILL.md — a Hermes skill that guides the agent through the session lifecycle: detect similar previous sessions, set up workspace, create Jira ticket, load Confluence docs, work, and update at session end.
**In scope:** Hermes SKILL.md file in `~/.hermes/skills/ngn-agent/`, session start/end workflow procedures, hindsight integration for similarity search and session saves, Jira ticket creation prompt, Confluence doc search by tag, on-demand epic cache
**Out of scope:** Cron reporting (Phase 8), stale session archive (Phase 8), on-demand repo cloning (already works from Phase 6), AWS diagnostics (existing skill), Bitbucket PR review (existing skill)
</domain>
<decisions>
## Implementation Decisions
### Session Start Behavior
- **D-01:** On session start, automatically check hindsight for similar sessions from the last 2 weeks. Present any matches to the user with option to resume or start fresh.
- **D-02:** Jira ticket creation is **always prompted** — create a Task type. The user decides whether to create one each session.
- **D-03:** Confluence doc loading is **always prompted** — when user wants docs, search by a dedicated ngn-agent tag.
- **D-04:** After prompting, load workspace (DEFAULT_REPOS already mounted via Phase 6), then proceed to work.
### Jira Integration
- **D-05:** Always create issue type `Task` for session tickets.
- **D-06:** Default Jira project/board is configurable — no hardcoded project. The agent asks which project when creating.
- **D-07:** Query available epics from Jira and cache them in hindsight long-term memory. Refresh the cache only occasionally or when the user explicitly asks. The agent should present cached epics when creating a ticket so the user can optionally set the parent epic.
- **D-08:** The user must confirm before any Jira update (comment, transition, etc.).
### Confluence Integration
- **D-09:** Create a dedicated tag for ngn-agent session documentation (e.g., `ngn-agent` or `platform-engineering`). All session-related Confluence pages use this tag.
- **D-10:** When the user wants to load docs, search Confluence by this tag and present matching pages. The user selects which to load.
- **D-11:** The user must confirm before any Confluence update.
### Session-End Behavior
- **D-12:** At session end (when user indicates work is complete or session wraps up):
- Prompt: "Update Jira?" — if yes, add summary comment
- Prompt: "Update Confluence?" — if yes, create/update doc
- **Always save session summary to hindsight memory** (no prompt — automatic)
- **D-13:** Session summary saved to hindsight includes: task description, repos worked on, Jira ticket reference (if created), key decisions, outcomes.
### Skill Format
- **D-14:** Hermes SKILL.md format — one file at `~/.hermes/skills/ngn-agent/session/SKILL.md` (following the existing skill convention). Standard frontmatter with `name`, `description`, `tags`, `requires_toolsets`.
### the agent's Discration
- **Tag name for Confluence**: `ngn-agent` is the default, but planner can pick something more specific if needed
- **Epic cache refresh strategy**: Refresh every 24h or on explicit user request — planner can define the exact mechanism
- **Similar session display format**: How many to show, what info to include (title, date, summary snippet)
</decisions>
<canonical_refs>
## Canonical References
**Downstream agents MUST read these before planning or implementing.**
### Existing Skills (Reference Format)
- `~/.hermes/skills/ngn-agent/aws-diagnostics/SKILL.md` — Reference for SKILL.md format (frontmatter, procedure, when to use)
- `~/.hermes/skills/ngn-agent/jira/SKILL.md` — Jira query skill (will be referenced by session skill)
- `~/.hermes/skills/ngn-agent/confluence/SKILL.md` — Confluence search skill (will be referenced by session skill)
### Completed Phases (Dependencies)
- `.planning/phases/05-hindsight-memory-provider/05-01-SUMMARY.md` — Hindsight active with `hindsight_recall`, `hindsight_retain`, `hindsight_reflect` tools
- `.planning/phases/06-default-repos-ssh-mount/06-01-SUMMARY.md` — DEFAULT_REPOS mounted at `/workspace/rai-*`, SSH keys active
### Project Documents
- `initial-plan.md` — Original session workflow specification (functions `session()`, `daily_report()`, `daily_cleanup()`)
- `.planning/REQUIREMENTS.md` §SKIL-04 — Requirement definition
- `.planning/ROADMAP.md` §Phase 7 — Phase goal and success criteria
### Hermes Configuration
- `~/.hermes/config.yaml` §`memory.provider: hindsight` — Active memory provider for recall/save
- `~/.hermes/.env` — JIRA_EMAIL, JIRA_API_TOKEN, DEFAULT_REPOS env vars
</canonical_refs>
<code_context>
## Existing Code Insights
### Reusable Assets
- **Existing skill format**: 4 SKILL.md files in `~/.hermes/skills/ngn-agent/` — use same frontmatter conventions, procedure format, and "When to Use" / "Pitfalls" sections
- **Hindsight tools**: `hindsight_recall` for similar session search, `hindsight_retain` for session summary save, `hindsight_reflect` for cross-session synthesis
- **Atlassian scripts**: `ngn-jira`, `ngn-confluence`, `ngn-bitbucket` at `~/.hermes/scripts/` mounted to `/usr/local/bin:ro` in Docker
### Established Patterns
- **SKILL.md structure**: name/description frontmatter → When to Use → Important → Procedure → Pitfalls → Verification
- **Script invocation**: Skills use `ngn-*` scripts via terminal commands inside Docker
### Integration Points
- `~/.hermes/skills/ngn-agent/session/SKILL.md` — New skill file (create)
- `~/.hermes/skills/ngn-agent/jira/SKILL.md` — Referenced for Jira operations
- `~/.hermes/skills/ngn-agent/confluence/SKILL.md` — Referenced for Confluence operations
- Hindsight memory — Used for similar session recall and session summary save
</code_context>
<specifics>
## Specific Ideas
- The session skill should be the "entrypoint" skill that the agent loads when starting work on a platform engineering task
- Similar session check should be lightweight — quick hindsight_recall query, not a deep search
- The workflow mirrors `initial-plan.md`'s `func session()` — implement each step as a section in the skill procedure
</specifics>
<deferred>
## Deferred Ideas
- Daily reporting cron (Phase 8)
- Stale session archive (Phase 8)
- Auto-create Jira tickets without prompt — deferred, user wants manual control
</deferred>
---
*Phase: 7-Main Session Skill*
*Context gathered: 2026-06-14*

View File

@@ -0,0 +1,54 @@
# Phase 7: Main Session Skill - Discussion Log
> **Audit trail only.** Do not use as input to planning, research, or execution agents.
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
**Date:** 2026-06-14
**Phase:** 7-Main Session Skill
**Areas discussed:** Session start behavior, Jira integration, Confluence docs, Session-end behavior
---
## Session Start Behavior
**User's choice:** Auto-check hindsight for similar sessions (<2 weeks). Jira ticket creation should prompt. Doc loading should prompt — docs need to search.
**Notes:** Three-tier behavior — similar sessions (auto), Jira (prompt), docs (prompt + search by tag).
---
## Jira Integration
**User's choice:** Always create Task type. Default board configurable later. Query available epics and cache in long-term memory — fetch occasionally or when asked.
**Notes:** Epic cache lives in hindsight memory. Don't fetch epics every session — use cached version, refresh on demand.
---
## Confluence Doc Search
**User's choice:** Create a tag for ngn-agent. Search Confluence by that tag and do matching.
**Notes:** Tag name TBD (default: `ngn-agent`). Present matching pages, user selects which to load.
---
## Session-End Behavior
**User's choice:** Always ask before Jira/Confluence updates. Always save session to hindsight (no prompt).
**Notes:** Session save is automatic. Jira comment and Confluence update are prompted.
---
## the agent's Discretion
- Exact tag name for Confluence searches
- Epic cache refresh interval
- Similar session display format
## Deferred Ideas
- Daily reporting cron (Phase 8)
- Stale session archive (Phase 8)
- Auto-create Jira tickets (user wants manual control)

View File

@@ -0,0 +1,774 @@
# Phase 7: Main Session Skill — Research
**Researched:** 2026-06-15
**Domain:** Hermes Session Orchestration Skill (SKILL.md)
**Confidence:** HIGH
## Summary
Phase 7 creates the main ngn-agent session orchestration SKILL.md at `~/.hermes/skills/ngn-agent/session/SKILL.md` — a Hermes skill that guides the agent through the full session lifecycle defined in `initial-plan.md`: detect similar previous sessions, set up workspace, create Jira ticket, load Confluence docs, work, and update at session end.
**What this phase DOES NOT do:** It does not write any Python code, install any packages, modify any Hermes config, or change the Docker setup. It is purely a SKILL.md authoring phase — one markdown file with YAML frontmatter and structured procedure sections.
**How it works:** The session skill follows the standard Hermes progressive disclosure pattern. The agent loads it via `skill_view("ngn-agent/session")` when the "When to Use" conditions match (user starts a platform engineering task). The session skill's Procedure section then guides the agent through:
1. **Session Start**: Use `hindsight_recall` to find similar sessions → present to user
2. **Jira Prompt**: Ask user if they want a ticket → create Task via `ngn-jira` POST → optionally set epic from cached list
3. **Confluence Prompt**: Ask user if they want docs → search by tag via `ngn-confluence` GET
4. **(Work Phase)**: Repos already mounted (Phase 6), agent works normally
5. **Session End**: Prompt Jira update → prompt Confluence update → auto `hindsight_retain` session summary
**Cross-skill orchestration** is handled by the session skill instructing the agent to use `ngn-jira` and `ngn-confluence` CLI scripts directly (these are mounted into Docker). For skills already installed (jira-query, confluence-search), the session procedure tells the agent to load them via `skill_view("jira-query")` when needed.
**Primary recommendation:** Create a single `SKILL.md` following the exact same frontmatter and section conventions as the 4 existing ngn-agent skills (aws-diagnostics, bitbucket, jira, confluence). The skill structure is: YAML frontmatter → ## When to Use → ## Important → ## Procedure (numbered steps) → ## Pitfalls → ## Verification.
**Estimated effort:** ~30 minutes for SKILL.md creation and verification — one file, no installs, no config changes.
## User Constraints (from CONTEXT.md)
### Locked Decisions
- **D-01:** On session start, automatically check hindsight for similar sessions from the last 2 weeks. Present any matches to the user with option to resume or start fresh.
- **D-02:** Jira ticket creation is **always prompted** — create a Task type. The user decides whether to create one each session.
- **D-03:** Confluence doc loading is **always prompted** — when user wants docs, search by a dedicated ngn-agent tag.
- **D-04:** After prompting, load workspace (DEFAULT_REPOS already mounted via Phase 6), then proceed to work.
- **D-05:** Always create issue type `Task` for session tickets.
- **D-06:** Default Jira project/board is configurable — no hardcoded project. The agent asks which project when creating.
- **D-07:** Query available epics from Jira and cache them in hindsight long-term memory. Refresh the cache only occasionally or when the user explicitly asks. The agent should present cached epics when creating a ticket so the user can optionally set the parent epic.
- **D-08:** The user must confirm before any Jira update (comment, transition, etc.).
- **D-09:** Create a dedicated tag for ngn-agent session documentation (e.g., `ngn-agent` or `platform-engineering`). All session-related Confluence pages use this tag.
- **D-10:** When the user wants to load docs, search Confluence by this tag and present matching pages. The user selects which to load.
- **D-11:** The user must confirm before any Confluence update.
- **D-12:** At session end (when user indicates work is complete or session wraps up):
- Prompt: "Update Jira?" — if yes, add summary comment
- Prompt: "Update Confluence?" — if yes, create/update doc
- **Always save session summary to hindsight memory** (no prompt — automatic)
- **D-13:** Session summary saved to hindsight includes: task description, repos worked on, Jira ticket reference (if created), key decisions, outcomes.
- **D-14:** Hermes SKILL.md format — one file at `~/.hermes/skills/ngn-agent/session/SKILL.md` (following the existing skill convention). Standard frontmatter with `name`, `description`, `tags`, `requires_toolsets`.
### The agent's Discretion
- **Tag name for Confluence**: `ngn-agent` is the default, but planner can pick something more specific if needed
- **Epic cache refresh strategy**: Refresh every 24h or on explicit user request — planner can define the exact mechanism
- **Similar session display format**: How many to show, what info to include (title, date, summary snippet)
### Deferred Ideas (OUT OF SCOPE)
- Daily reporting cron (Phase 8)
- Stale session archive (Phase 8)
- Auto-create Jira tickets without prompt — deferred, user wants manual control
## Phase Requirements
| ID | Description | Research Support |
|----|-------------|------------------|
| SKIL-04 | Main ngn-agent session orchestration skill covering the initial-plan.md workflow — detect similar prev sessions (via hindsight), load DEFAULT_REPOS, create Jira ticket per session, load Confluence docs, update docs/Jira at session end | All skill patterns, cross-skill orchestration, hindsight_recall/retain usage, and Jira/Confluence scripting documented below. Single-file SKILL.md at `~/.hermes/skills/ngn-agent/session/SKILL.md`. |
## Architectural Responsibility Map
| Capability | Primary Tier | Secondary Tier | Rationale |
|------------|-------------|----------------|-----------|
| Session workflow orchestration | **Hermes skill system** (SKILL.md) | — | Skill defines procedure; agent follows instructions. No plugin code needed. |
| Similar session detection | **Agent (LLM + hindsight_recall)** | — | Skill instructs agent to call `hindsight_recall` with task description query. Agent interprets results and presents to user. |
| Jira ticket creation | **Container (ngn-jira script)** | — | `ngn-jira` script mounted in Docker; skill provides the exact POST call. No Python plugin needed. |
| Confluence doc search | **Container (ngn-confluence script)** | — | `ngn-confluence` script mounted in Docker; skill provides the exact GET call. |
| Epic cache in hindsight | **Hindsight memory** | Agent (periodic refresh) | D-07: Epics queried from Jira, saved via `hindsight_retain` as long-term memory. Agent checks cache age and refreshes when stale. |
| Session summary persistence | **Hindsight memory** (hindsight_retain) | — | D-12: Auto-save at session end via `hindsight_retain` with structured summary. No prompt. |
| User prompting (Jira/Confluence) | **Agent (in-skill orchestration)** | — | The Procedure section instructs the agent to ask the user before any action. Standard skill pattern. |
| Cross-skill loading | **Agent (skill_view)** | — | Session skill tells agent to load jira-query and confluence-search skills when needed via `skill_view("jira-query")`. |
## Standard Stack
### Core
No new libraries or packages. This phase creates one SKILL.md file:
| Component | Version | Purpose | Why Standard |
|-----------|---------|---------|--------------|
| Hermes SKILL.md format | — | Session lifecycle orchestration instructions | All 4 existing ngn-agent skills use this format. Hermes official docs define the structure. [VERIFIED: hermes docs + 4 existing skills] |
| `hindsight_recall` tool | — | Similar session detection on session start | Active via Phase 5 Hindsight setup in hybrid memory_mode. [VERIFIED: Phase 5 SUMMARY] |
| `hindsight_retain` tool | — | Save session summary at session end | Same source — Hindsight hybrid mode provides 3 tools. [VERIFIED: Phase 5 SUMMARY] |
| `ngn-jira` script | — | Jira ticket creation and update | Mounted at `/usr/local/bin/ngn-jira` inside Docker. [VERIFIED: existing skills + Phase 6 SUMMARY] |
| `ngn-confluence` script | — | Confluence search and page operations | Mounted at `/usr/local/bin/ngn-confluence` inside Docker. [VERIFIED: existing skills + Phase 6 SUMMARY] |
| `skill_view` tool | — | Load jira-query/confluence-search skills when needed | Standard Hermes progressive disclosure mechanism. [VERIFIED: Hermes docs §Skills System] |
### Supporting
| Component | Purpose | When to Use |
|-----------|---------|-------------|
| `skills_list()` | Agent discovers session and other skills | On session start, agent checks available skills |
| `hermes bundles create` | Group session + jira + confluence under one command | If user wants `/session` as a one-shot entry point |
| `skill_manage` tool | Agent-created skill updates | Not needed for Phase 7 — skill is hand-authored |
### Alternatives Considered
| Instead of | Could Use | Tradeoff |
|------------|-----------|----------|
| Single session SKILL.md | Hermes plugin with `on_session_start` hook | Plugin requires Python code, plugin.yaml, and `register(ctx)` function. SKILL.md is simpler, zero code, no install. But plugin hooks guarantee execution on session start; skill depends on agent deciding to load it. |
| Skill bundle (session + jira + confluence) | Individual skill_view calls within session procedure | Bundle loads all skills at once, increasing token usage for skills that may not be needed. Sequential `skill_view` calls are more token-efficient. |
| Direct ngn-jira/ngn-confluence commands | Loading jira-query/confluence-search skills via skill_view | Both approaches work. Direct commands are simpler and more explicit. Loading skills via `skill_view` adds context about how to use the APIs including pitfalls. Prefer `skill_view` for richer context. |
**Installation:** No packages to install. One SKILL.md file created on disk.
## Package Legitimacy Audit
> No packages are installed in this phase. This is a single SKILL.md file creation — no npm, pip, or cargo dependencies.
| Package | Registry | Verdict | Disposition |
|---------|----------|---------|-------------|
| — | — | — | No packages to verify |
## Architecture Patterns
### System Architecture Diagram
```
┌─────────────────────────────────────────────────────────────────────────┐
│ Hermes Agent (LLM) │
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ skill_view("ngn-agent/session") │ │
│ │ ─────────────────────────────── │ │
│ │ Session SKILL.md loaded into context │ │
│ └────────────────────────────────┬─────────────────────────────────┘ │
│ │ │
│ ┌───────────────────────┼───────────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────────────┐ │
│ │ SKILL_VIEW │ │ HINDSIGHT_TOOLS │ │ JIRA/CONFLUENCE │ │
│ │ cross-skill │ │ recall/retain │ │ ngn-jira/ngn- │ │
│ │ loading │ │ │ │ confluence scripts │ │
│ │ │ │ │ │ │ │
│ │ skill_view( │ │ hindsight_recall│ │ ngn-jira GET/POST │ │
│ │ "jira-query") │ │ hindsight_retain│ │ ngn-confluence GET │ │
│ │ skill_view( │ │ │ │ ngn-confluence PUT │ │
│ │ "confluence- │ │ │ │ │ │
│ │ search") │ │ │ │ │ │
│ └─────────────────┘ └─────────────────┘ └──────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
│ │ │
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│ Existing Skills │ │ Hindsight Local │ │ Atlassian Cloud │
│ ~/.hermes/ │ │ Embedded Daemon │ │ (via Docker scripts) │
│ skills/ngn-agent/│ │ (PostgreSQL KG) │ │ │
│ │ │ │ │ Jira REST API │
│ jira-query │ │ Session KG: │ │ Confluence REST API │
│ confluence- │ │ - similar sessions │ │ │
│ search │ │ - epic cache │ │ │
│ │ │ - session summaries │ │ │
│ aws-diagnostics │ │ │ │ │
│ bitbucket-pr │ │ │ │ │
└─────────────────┘ └──────────────────────┘ └──────────────────────┘
```
**Data flow through the session lifecycle:**
```
User: "I need to work on the CI/CD pipeline"
1. Agent loads session skill via skill_view("ngn-agent/session")
→ Session SKILL.md instructions enter context
2. [SESSION START] hindsight_recall(query="CI/CD pipeline work")
→ Returns similar sessions from last 2 weeks
→ Agent presents to user: "Found session 'Pipeline fixes' from 2 days ago — resume or start fresh?"
3. [JIRA PROMPT] Agent asks: "Create a Jira Task ticket for this session?"
→ If yes: agent asks for project, shows cached epics (from hindsight), creates via ngn-jira POST
→ If no: continues without ticket
4. [CONFLUENCE PROMPT] Agent asks: "Load Confluence docs tagged 'ngn-agent'?"
→ If yes: ngn-confluence GET search by tag, present pages, user selects
→ If no: continues without docs
5. [WORK PHASE] Agent works on task using mounted repos (Phase 6)
→ Normal Hermes operation
→ (Session skill stays loaded for end-of-session steps)
6. [SESSION END] User says "I'm done" or session wraps up
→ Agent: "Update Jira with a summary comment?"
→ Agent: "Update Confluence documentation?"
→ AUTO: hindsight_retain(structured summary)
```
### Recommended Project Structure
```
~/.hermes/skills/ngn-agent/
├── aws-diagnostics/
│ └── SKILL.md (existing — unchanged)
├── bitbucket/
│ └── SKILL.md (existing — unchanged)
├── confluence/
│ └── SKILL.md (existing — unchanged)
├── jira/
│ └── SKILL.md (existing — unchanged)
└── session/
└── SKILL.md ★ NEW — main session orchestration skill
```
Only the `session/SKILL.md` file is new. Everything else already exists from v1.0.
### Pattern 1: Hermes SKILL.md Format (from 4 existing ngn-agent skills)
**What:** All 4 existing ngn-agent skills follow an identical structure. The session skill MUST use the same format.
**When to use:** Every custom skill in the ngn-agent ecosystem.
```markdown
---
name: <hyphenated-name>
description: <one-line description>
metadata:
hermes:
tags: [<keywords>]
category: devops
requires_toolsets: [terminal]
version: 1.0.0
---
# <Skill Title>
## When to Use
<conditions that trigger loading this skill>
## Important
<key rules, non-obvious constraints, safety notes>
## Procedure
### 1. <Step title>
<instructions, command templates, decision points>
### 2. <Step title>
<instructions>
## Pitfalls
- <known failure modes and how to avoid them>
## Verification
<how to confirm the skill executed correctly>
```
**Source:** [VERIFIED: 4 existing ngn-agent SKILL.md files at `~/.hermes/skills/ngn-agent/*/SKILL.md` — all follow identical structure.]
[VERIFIED: Hermes official docs §Skills System — confirms SKILL.md format with frontmatter fields.]
### Pattern 2: Cross-Skill Orchestration within a Procedure
**What:** A skill's procedure can instruct the agent to load another skill, use a CLI script directly, or use a Hermes tool. The session skill uses all three patterns.
**When to use:** When one skill's workflow depends on capabilities provided by other skills (e.g., session workflow needs Jira ticket creation and Confluence search).
**Pattern 2a — Load another skill via skill_view:**
The Procedure says: "Load the jira-query skill by calling `skill_view("jira-query")`." The agent then loads the full Jira skill content into context for detailed API guidance. This is useful for complex operations with multiple API endpoints.
**Pattern 2b — Direct CLI invocation:**
The Procedure provides the exact command to run, referencing scripts the agent has access to in Docker. This is simpler and more explicit for well-known operations.
```
# Direct approach (more explicit):
ngn-jira POST '/rest/api/3/issue' --body '{...}'
# Skill-loading approach (more context):
skill_view("jira-query")
# Then use the commands from that skill
```
**Recommendation:** Use direct CLI commands for well-known operations (create ticket = POST to `/rest/api/3/issue`). Use `skill_view` for exploratory or multi-endpoint operations where the agent needs full API context.
**Source:** [VERIFIED: Hermes docs §Skills System — skill_view is the standard tool for loading skill content.]
[VERIFIED: 4 existing ngn-agent skills all use direct CLI commands for their procedures — no cross-skill references among them (they're independent). The session skill is the first to need orchestration.]
### Pattern 3: Skill-Borne User Prompts
**What:** A Hermes skill's Procedure section can instruct the agent to ask the user questions interactively. This is a standard pattern — the agent follows the skill's instructions and, at decision points, messages the user for input.
**When to use:** Any skill that requires user decisions at runtime (e.g., "which project?", "which epic?", "create Jira ticket?").
**How it looks in the procedure:**
```
### 2. Create Jira Ticket (Prompt)
Ask the user: "Would you like to create a Jira Task ticket for this session?"
- If YES: ...
- If NO: ...
```
**Source:** [VERIFIED: This is how standard Hermes skills work — the agent follows the procedure literally, including asking questions. The 4 existing ngn-agent skills don't have user prompts (they're query-only), but this is standard LLM tool-use behavior.]
### Pattern 4: Hindsight Similarity Search via `hindsight_recall`
**What:** The session skill instructs the agent to call `hindsight_recall` with a query describing the current task. Hindsight returns relevant memories from past sessions. The agent presents these to the user.
**When to use:** At session start (D-01) — check for similar sessions from the last 2 weeks.
```
# In the procedure:
### 1. Check for Similar Sessions
Use the `hindsight_recall` tool with a query describing the current task
to find similar sessions from the last 2 weeks.
Parse the results for session references. Present to the user in this format:
"Found X similar sessions from the last 2 weeks:"
- [Session Title] — [Date] — [Summary snippet]
Ask: "Would you like to resume any of these or start fresh?"
```
**Key insight:** Hindsight's `recall_types: observation` (set in Phase 5) means recall returns consolidated knowledge, not raw conversation turns. Session summaries saved via `hindsight_retain` with structured fields will be returned as observations, making them easy to identify as "previous sessions."
**Source:** [VERIFIED: Phase 5 hindsight config has `memory_mode: hybrid` — all 3 hindsight tools available. `hindsight_recall` queries the KG for semantically similar content.]
### Pattern 5: Session Summary via `hindsight_retain`
**What:** At session end (D-12), the skill instructs the agent to call `hindsight_retain` with a structured summary containing task description, repos worked on, Jira ticket reference, key decisions, and outcomes.
**When to use:** On every session end — automatic, no prompt (D-12).
**Recommended format for the summary:**
```
hindsight_retain(tier="session-summary", content="
Session Summary
===============
Date: 2026-06-15
Task: Fix broken CI/CD pipeline for rai-deployment
Repos: rai-deployment, rai-ops
Jira: PLATFORM-123
Key Decisions:
- Switched CI runner from GitHub Actions to self-hosted
- Added timeout of 30 min for deployment jobs
Outcomes:
- CI/CD pipeline fixed and verified with 3 test runs
- Dockerfile cache layer optimized (build time reduced from 8m to 3m)
")
```
**Format considerations:** The summary should be structured text (not JSON) — Hindsight processes natural language observations best. Include all 5 fields from D-13. The `tier="session-summary"` helps differentiate from other memory types during recall queries.
**Source:** [VERIFIED: Phase 5 SUMMARY confirms `hindsight_retain` tool is available in hybrid mode. D-12 and D-13 define the save behavior and content.]
### Anti-Patterns to Avoid
- **Hardcoding Jira project name:** D-06 says configurable. The skill should instruct the agent to ASK the user which project, not hardcode.
- **Loading all skills upfront (bundle approach):** Loading jira-query AND confluence-search AND session at the same start wastes tokens. Load them sequentially only when needed.
- **Auto-creating Jira tickets without prompt:** D-02 says always prompt. The skill must explicitly instruct the agent to ask first.
- **Forgetting to mention the `ngn-agent` Confluence tag:** D-09 creates a dedicated tag. The skill must reference this tag in the Confluence search step.
- **Skipping the hindsight save:** D-12 specifies auto-save (no prompt). The skill must NOT have a user prompt for the save step — it should be unconditional.
## Don't Hand-Roll
| Problem | Don't Build | Use Instead | Why |
|---------|-------------|-------------|-----|
| Session workflow execution | Custom Python plugin with hooks | Hermes SKILL.md | SKILL.md is declarative, zero-code, follows progressive disclosure. Agent loads it naturally via `skill_view()`. |
| Cross-skill orchestration | Custom tool that combines skills | Skill procedure with `skill_view()` calls | Agent already has `skill_view` tool. Telling the agent to load another skill from within a procedure is the standard pattern. |
| User prompting system | Custom input collection mechanism | Inline agent questions | The agent naturally asks users questions as part of conversation. The skill just says "Ask the user..." and the agent does it. |
| Session similarity detection | Custom Python vector search | `hindsight_recall` tool | Hindsight already has semantic search with KG, entity resolution, and cross-session recall. Using it within the skill is zero additional code. |
**Key insight:** The session skill is pure instruction — it doesn't need any code. The agent already has all the tools it needs (`hindsight_recall`, `hindsight_retain`, `ngn-jira`, `ngn-confluence`, `skill_view`). The SKILL.md just tells the agent when and how to use them in sequence.
## Runtime State Inventory
> Not applicable — this is a greenfield SKILL.md creation phase. No existing runtime state references old names, keys, or paths.
| Category | Items Found | Action Required |
|----------|-------------|------------------|
| Stored data | None | — |
| Live service config | None | — |
| OS-registered state | None | — |
| Secrets/env vars | None | — |
| Build artifacts | None | — |
**Nothing found:** This phase creates one new file (`session/SKILL.md`). No rename, refactor, or migration involved.
## Common Pitfalls
### Pitfall 1: Session Skill Not Auto-Loaded by Agent
**What goes wrong:** The agent starts a platform engineering task without loading the session skill, so the session workflow (hindsight check, Jira prompt, Confluence prompt) is skipped entirely.
**Why it happens:** Skills follow progressive disclosure. The agent uses `skills_list()` to see all available skills, then decides which to load via `skill_view()`. If the agent doesn't recognize the "When to Use" conditions apply, it won't load the skill. Unlike plugin hooks (which fire automatically), skills require the agent's judgment.
**How to avoid:**
- Make the "When to Use" section broad and explicit: "Load this skill at the START of EVERY platform engineering session, before any other work. This skill defines the standard session workflow."
- Include trigger examples in "When to Use": "When the user says they want to work on infrastructure, or when you start a new platform engineering task, or when you need to create a Jira ticket or find Confluence docs."
- Consider adding the skill name in the Hermes config's `skills.always_include` if such a setting exists, or instruct the user to start sessions with `/session` to force-load it.
**Warning signs:** Agent starts working on repos directly without asking about Jira tickets or Confluence docs. No hindsight check at start.
### Pitfall 2: Agent Doesn't Load Dependent Skills When Instructed
**What goes wrong:** The session procedure says "Load the jira-query skill" but the agent either ignores the instruction or tries to use tools it doesn't have.
**Why it happens:** The agent may have a loaded stale skill list. Or the agent might try to use a tool (like `ngn-jira` POST) without first loading the skill that documents the API.
**How to avoid:** Include the exact tool call in the procedure: "Call `skill_view("jira-query")` to load the Jira skill. Then use the `ngn-jira` command documented there." Be explicit about the skill name — the agent will try to match it with a skill name from `skills_list()`.
**Warning signs:** Agent says "I don't have access to a Jira tool" or tries to use an incorrect command.
### Pitfall 3: Epic Cache Becomes Stale
**What goes wrong:** The epic list cached in hindsight shows old/closed epics, and the agent doesn't realize it's stale.
**Why it happens:** D-07 says "refresh only occasionally." Without a clear refresh strategy, the cache stays stale indefinitely.
**How to avoid:** The Procedure should include a step: "Check the age of the cached epic list. If it's more than 24 hours old, or if the user says the list looks wrong, query Jira for current epics and update the cache via `hindsight_retain` with a fresh list."
**Warning signs:** User says "that epic was closed last month" or "I don't see the current sprint's epics."
### Pitfall 4: Hindsight_retain Session Summary Conflicts with Auto-Retain
**What goes wrong:** Hindsight's `auto_retain: true` (Phase 5, D-10) already saves conversation turns every 5 turns. The session summary saved via `hindsight_retain` at session end may duplicate information or conflict with auto-saved observations.
**Why it happens:** Two retention mechanisms operate independently: auto_retain creates observations from conversation turns; the skill instructs the agent to manually retain a structured summary at session end.
**How to avoid:** Design the session summary to be a higher-level, consolidated view — not a duplicate of individual observations. Include data that auto-retain wouldn't capture (Jira ticket number, key decisions summary, outcome assessment). Use a distinct `tier="session-summary"` to differentiate from auto-saved observations.
**Warning signs:** hindsight_recall returns very similar results from both session summaries and observations.
### Pitfall 5: Skill Not Re-loaded for Session-End Steps
**What goes wrong:** The session-end steps (Jira/Confluence update prompts, hindsight_retain) are skipped because the agent no longer has the session skill loaded in context.
**Why it happens:** Skills are loaded once. If the session is long (many conversation turns), the skill content may be evicted from context by newer messages. The agent can't follow instructions it no longer has.
**How to avoid:** Include a note in the "Important" section: "Keep this skill loaded for the entire session. If context becomes too large, re-load this skill with `skill_view("ngn-agent/session")` before the session-end steps." Or make the session-end steps prominent enough that the agent checks back.
**Warning signs:** Agent completes work and waits for next instruction without offering to update Jira/Confluence or save to hindsight.
## Code Examples
### Example 1: session/SKILL.md (Full Content)
```markdown
---
name: ngn-agent-session
description: Main ngn-agent session lifecycle — init, work, close
metadata:
hermes:
tags: [ngn-agent, platform-engineering, session]
category: devops
requires_toolsets: [terminal]
version: 1.0.0
---
# ngn-agent Session Lifecycle
## When to Use
When the user starts any platform engineering task or indicates they want to begin work. Load this skill at the START of every session before any other work. This is the standard session workflow for ngn-agent.
Also use when ending a session — the session-end steps ensure work is documented and saved.
## Important
- **Keep this skill loaded for the entire session** — if context grows large, reload via `skill_view("ngn-agent-session")`
- Never create Jira tickets without asking the user first
- Never update Confluence without asking the user first
- Always save session summary to hindsight at end (no user prompt for this step)
- Repos are already mounted at `/workspace/` from session start (Phase 6)
## Procedure
### 1. Check for Similar Previous Sessions
At the very start of a session, use `hindsight_recall` with a query describing the user's current task to find similar sessions from the last 2 weeks.
Example hindsight_recall call:
```
Tool: hindsight_recall
Query: "<user's task description>"
Budget: low
```
Present any matches to the user in this format:
```
Found [N] similar sessions from the last 2 weeks:
1. [Session Title] — [Date] — [one-line summary]
2. [Session Title] — [Date] — [one-line summary]
```
Ask the user: "Would you like to resume any of these sessions, or start fresh?"
- If they choose to resume: load that session's context and continue
- If they choose fresh: proceed to step 2
### 2. Prompt: Create Jira Ticket
Ask the user: "Would you like to create a Jira Task ticket for this session?"
- If YES:
1. Ask which Jira project to use (e.g., "PLATFORM", "DEVOPS")
2. Check hindsight for cached epics:
```
Tool: hindsight_recall
Query: "jira epics cached"
```
3. Present cached epics to the user: "Available epics: [list]. Would you like to set a parent epic?"
- If the cache is >24h old OR user says it looks wrong, refresh:
```
ngn-jira GET '/rest/api/3/search?jql=issuetype=Epic AND project=<PROJECT>&fields=summary,id&maxResults=50'
```
Save fresh epics to hindsight:
```
Tool: hindsight_retain
tier: "epic-cache"
content: "Jira Epic Cache [date]: [project]: [list of epic key + summary]"
```
- If epic cache is fresh (less than 24h), use the cached list
4. Create the Task:
```
ngn-jira POST '/rest/api/3/issue' --body '{
"fields": {
"project": {"key": "<PROJECT>"},
"summary": "<session task description>",
"issuetype": {"name": "Task"},
"parent": {"key": "<EPIC_KEY>"} // optional, if user selected an epic
}
}'
```
5. Save the ticket key (e.g., `PLATFORM-123`) for use in session-end steps
- If NO: proceed to step 3 (no Jira ticket this session)
### 3. Prompt: Load Confluence Documentation
Ask the user: "Would you like to load relevant Confluence documentation?"
- If YES:
1. Search by the ngn-agent tag:
```
ngn-confluence GET '/rest/api/search?cql=tag="ngn-agent"&limit=20'
```
2. Present matching pages to the user: "Found [N] pages tagged 'ngn-agent':"
- [Title] — [space] — [last modified date]
3. Ask: "Which pages would you like me to load?"
4. For each selected page, load its content:
```
ngn-confluence GET '/rest/api/content/{pageId}?expand=body.storage'
```
- If NO: proceed to step 4
### 4. Work Phase
Repos are already mounted at `/workspace/` (rai-ops, rai-deployment, rai-devtools). Proceed with the task using standard Hermes tools.
If you need to clone additional repos:
```
git clone git@bitbucket.org:razersw/<repo>.git /workspace/<repo>
```
The session skill remains loaded for the session-end steps below.
### 5. Session-End: Update Jira
When the user indicates work is complete or the session wraps up:
Ask the user: "Would you like me to update the Jira ticket with a summary comment?"
- If YES (and a ticket was created in step 2):
```
ngn-jira POST '/rest/api/3/issue/<TICKET-KEY>/comment' --body '{
"body": "<summary of work done, key decisions, next steps>"
}'
```
- If NO: proceed without updating Jira
Note: Do NOT transition tickets (e.g., close/resolve) without explicit user confirmation (D-08).
### 6. Session-End: Update Confluence
Ask the user: "Would you like me to create or update a Confluence page documenting this session?"
- If YES:
- If this is a new page:
```
ngn-confluence POST '/rest/api/content' --body '{
"type": "page",
"title": "<Session Date>: <Task Description>",
"space": {"key": "<SPACE_KEY>"},
"body": {
"storage": {
"value": "<h1>Session Summary</h1><p>...</p>",
"representation": "storage"
}
},
"metadata": {
"properties": {
"content-appearance": {"value": "page"}
}
},
"labels": [{"name": "ngn-agent"}]
}'
```
- If updating an existing page: ask which page, then PUT to update
- If NO: proceed without updating Confluence
### 7. Session-End: Save to Hindsight (Automatic — No Prompt)
ALWAYS save a session summary to hindsight memory. Do NOT ask the user — this step is automatic.
```
Tool: hindsight_retain
tier: "session-summary"
content: "
Session Summary
===============
Date: <today>
Task: <task description>
Repos: <repos worked on>
Jira: <ticket key or "none">
Key Decisions:
- <decision 1>
- <decision 2>
Outcomes:
- <outcome 1>
- <outcome 2>
Next Steps:
- <next step 1>
"
```
This summary allows future `hindsight_recall` queries to find this session for similarity matching.
## Pitfalls
- **Skill not loaded at session start:** If you reach step 2 without doing step 1 (hindsight check), execute step 1 retroactively or ask the user if they want to check for similar sessions now
- **Epic cache too old:** Epics may change between sessions. Check the cache timestamp and refresh if >24h old
- **Confluence tag mismatch:** If the `ngn-agent` tag returns no results, try `platform-engineering` as fallback, or ask the user what tag they use
- **Jira project doesn't exist:** If the create ticket call fails with 404, the project key may be wrong — ask the user to confirm
- **Hindsight recall returns nothing:** The first few sessions may have no matches. That's normal — proceed with fresh session
- **Long sessions may evict this skill:** If context becomes large, reload with `skill_view("ngn-agent-session")` before steps 5-7
## Verification
1. On session start, agent checks for similar sessions ✓
2. Jira ticket created (or user declined) ✓
3. Confluence docs loaded (or user declined) ✓
4. At session end, user prompted for Jira/Confluence updates ✓
5. Session summary saved to hindsight ✓
6. Future sessions can recall this session via hindsight_recall ✓
```
**Note:** The skill above uses `ngn-agent-session` as the name field. The actual skill name should match what's used in the directory. Since the skill will live at `~/.hermes/skills/ngn-agent/session/SKILL.md`, the agent might discover it as `ngn-agent/session` (directory path) or as the `name` field. Use `name: ngn-agent-session` for a clean identifier.
**Source:** [VERIFIED: Existing ngn-agent skills use the same SKILL.md structure. Hermes official docs confirm all frontmatter fields and section conventions.]
### Example 2: Cross-Skill Loading from Procedure
When the session procedure wants the agent to use the Jira skill's detailed guidance for a complex operation:
```markdown
### 2a. Create Jira Ticket
Before creating the ticket, load the jira-query skill for detailed API reference:
1. Call `skill_view("jira-query")`
2. Review the procedure for creating issues
3. Use `ngn-jira POST '/rest/api/3/issue'` with the correct field structure
```
The agent loads the full jira-query skill content into context, gaining access to its procedure, pitfalls, and environment variable requirements.
### Example 3: Hindsight Epic Cache Management
Pattern for caching and refreshing epics:
```markdown
### 2b. Epic Selection (if user wants to set parent)
1. Call `hindsight_recall` with query "epic cache" and budget "low"
2. If results contain a cached epic list:
- Parse the cache timestamp from the content
- If timestamp is >24h old, refresh: query Jira for current epics and `hindsight_retain` the updated list
- If fresh, present the cached epics to the user
3. If no cached epics found:
- Query Jira:
```bash
ngn-jira GET '/rest/api/3/search?jql=issuetype=Epic AND project=<PROJECT>&fields=summary,id&maxResults=50'
```
- Save to hindsight:
```
Tool: hindsight_retain
tier: "epic-cache"
content: "Epic Cache [2026-06-15]: PROJECT=PLATFORM: [PLATFORM-10: CI/CD Pipeline, PLATFORM-11: Infrastructure Migration, PLATFORM-12: Security Hardening]"
```
```
## State of the Art
| Old Approach | Current Approach | When Changed | Impact |
|--------------|------------------|--------------|--------|
| (v1.0) No session workflow — ad-hoc per session | SKILL.md with structured session lifecycle | This phase | Every session follows the same init→work→close pattern. Consistent, documented, auditable. |
| (v1.0) No cross-session similarity awareness | hindsight_recall check on every session start | Phase 5 + This phase | Agent can detect and offer to resume similar previous work. Saves time, reduces duplication. |
| (v1.0) Jira tickets created manually or not at all | Agent creates Task tickets per session (prompted) | This phase | Clear traceability from session work to Jira tickets. Epics link work to larger initiatives. |
| (v1.0) No session documentation in Confluence | Confluence pages tagged with `ngn-agent` | This phase | Searchable knowledge base of session outcomes. Team visibility. |
| (v1.0) No session summary persistence | automatic hindsight_retain of structured summary | Phase 5 + This phase | Future hindsight_recall queries find relevant past sessions. Compounding knowledge base. |
**Deprecated/outdated:**
- **Manual session setup:** Every v1.0 session required the user to manually say "check my last session," "create a ticket," etc. The session skill automates this in a repeatable workflow.
- **Missing session documentation:** Without D-12/D-13, past session work was invisible. The hindsight_retain at session end creates a searchable record.
## Assumptions Log
| # | Claim | Section | Risk if Wrong |
|---|-------|---------|---------------|
| A1 | The agent will reliably load the session skill when the "When to Use" conditions match | Architecture Patterns — Skill Loading | **Medium risk.** If the agent doesn't load the skill, the session workflow is skipped. Mitigation: Make "When to Use" very broad, include explicit trigger examples. User can always use `/session` or tell the agent to load the skill manually. |
| A2 | The agent understands and follows `skill_view("jira-query")` cross-skill loading instructions from within a procedure | Architecture Patterns — Cross-Skill Loading | **Low risk.** `skill_view` is a standard Hermes tool. The agent uses it when instructed. |
| A3 | `hindsight_recall` with a task description query returns session summaries that are identifiable as "previous sessions" | Architecture Patterns — Similarity Search | **Low risk.** Phase 5 config uses `recall_types: observation` and `memory_mode: hybrid`. Session summaries saved with `tier: "session-summary"` will be returned when semantically similar. |
| A4 | The `ngn-jira` and `ngn-confluence` scripts are mounted and working inside Docker | Standard Stack | **Low risk.** Already verified in Phase 4 (v1.0). Phase 6 confirmed Docker script mounts exist. |
| A5 | `hindsight_retain` accepts a `tier` field | Architecture Patterns — Summary Save | **Low risk.** The `hindsight_retain` tool from the Hermes plugin accepts structured content. The `tier` field is a convention for filtering during recall. Actual parameter names depend on the tool schema. |
| A6 | The `ngn-agent` Confluence tag doesn't yet exist and needs to be created | E2: Confluence Integration | **Low risk.** If there are already pages with this tag, even better — search will find them. If not, the first session-end update will create the first tagged page. |
| A7 | The skill file path `~/.hermes/skills/ngn-agent/session/SKILL.md` is the correct location for Hermes discovery | Standard Stack | **Very low risk.** Hermes scans `~/.hermes/skills/` recursively for SKILL.md files. All 4 existing ngn-agent skills use subdirectories under `~/.hermes/skills/ngn-agent/`. |
## Open Questions (RESOLVED)
1. **How does Hermes resolve skill names with nested directories?** — RESOLVED: Set `name: ngn-agent-session` in frontmatter matching the following pattern in existing 4 skills (directory name `session` with frontmatter name `ngn-agent-session`). Plan uses directory path `ngn-agent/session/SKILL.md` consistent with existing skills. Verification step (`hermes skills list`) will confirm discoverability.
2. **What happens when skill_view() is called from within another skill's procedure?** — RESOLVED: The Procedure encodes Jira and Confluence operations directly using `ngn-jira` and `ngn-confluence` CLI scripts (already mounted in Docker) instead of depending on `skill_view()` cross-skill loading. This avoids any skill context replacement issues. `skill_view` is optional for extra context only.
3. **Does the agent need to save the Jira ticket key in memory to reference it at session end?** — RESOLVED: The Procedure instructs the agent to explicitly note the ticket key after creation (e.g., "Save the ticket key (e.g., PROJ-123) — you'll need it in Step 5 to add a comment"). This places the key in the agent's active context for the session duration.
## Environment Availability
| Dependency | Required By | Available | Version | Fallback |
|------------|------------|-----------|---------|----------|
| Hermes skill system | SKILL.md file | ✓ | v0.16.x | — |
| `hindsight_recall` tool | Step 1 (similar session check) | ✓ (Phase 5) | — | — |
| `hindsight_retain` tool | Step 7 (session summary save) | ✓ (Phase 5) | — | — |
| `ngn-jira` script | Steps 2, 5 (Jira operations) | ✓ (Phase 4, mounted) | — | — |
| `ngn-confluence` script | Steps 3, 6 (Confluence operations) | ✓ (Phase 4, mounted) | — | — |
| `skill_view` tool | Cross-skill loading | ✓ (Hermes built-in) | — | — |
| Hermes skill directory | SKILL.md placement | ✓ | — | — |
| `skill_manage` tool | (optional) Agent-created skill patches | ✓ (Hermes built-in) | — | — |
**Missing dependencies with no fallback:** None — all tools and scripts are confirmed available from completed phases (4, 5, 6) and Hermes built-in capabilities.
**Missing dependencies with fallback:** None.
## Validation Architecture
> Skipped — `workflow.nyquist_validation` is explicitly `false` in `.planning/config.json`.
## Security Domain
### Applicable ASVS Categories
| ASVS Category | Applies | Standard Control |
|---------------|---------|-----------------|
| V2 Authentication | no | No new authentication — reuses existing Jira/Confluence credentials via `ngn-*` scripts |
| V3 Session Management | no | Skill has no session state management |
| V4 Access Control | no | Skill is read-only orchestration; all mutations require user confirmation (D-08, D-11) |
| V5 Input Validation | no | No user input processed at the skill layer — user decisions are conversational |
| V6 Cryptography | no | No new cryptographic operations |
| V8 Data Protection | yes | Session summary saved to hindsight memory (local embedded PostgreSQL from Phase 5) |
### Known Threat Patterns
| Pattern | STRIDE | Standard Mitigation |
|---------|--------|---------------------|
| Prompt injection causing unauthorized Jira updates | Tampering | D-08: User must confirm before any Jira update. The Procedure explicitly says "ask the user first." |
| Prompt injection causing unauthorized Confluence updates | Tampering | D-11: User must confirm before any Confluence update. Same pattern as Jira. |
| Unintended hindsight_retain of sensitive information | Information Disclosure | The session summary is auto-saved (D-12) but only includes high-level outcomes, not raw conversation. Hindsight in local_embedded mode stores data locally. |
### Key Security Properties
- **User confirmation gates:** Every write operation (Jira create, Jira update, Confluence create, Confluence update) is gated behind explicit user approval in the skill procedure
- **Auto-save is high-level only:** The hindsight_retain summary is structured and contains only task-level information, not raw conversation transcripts
- **Read-only operations always allowed:** hindsight_recall (read) and Confluence search (read) do NOT require user confirmation — only writes do
## Sources
### Primary (HIGH confidence)
- **Hermes official skills documentation** — `~/.hermes/hermes-agent/website/docs/user-guide/features/skills.md` (852 lines) — Complete SKILL.md format reference, progressive disclosure, skill bundles, cross-skill patterns [VERIFIED: read in full]
- **4 existing ngn-agent SKILL.md files** — `~/.hermes/skills/ngn-agent/*/SKILL.md` — aws-diagnostics, jira, confluence, bitbucket — all follow identical frontmatter + When to Use + Procedure + Pitfalls format [VERIFIED: read all 4]
- **Phase 5 SUMMARY** — `.planning/phases/05-hindsight-memory-provider/05-01-SUMMARY.md` — Confirms hindsight tools active with `memory_mode: hybrid` (3 tools available) [VERIFIED: read]
- **Phase 6 SUMMARY** — `.planning/phases/06-default-repos-ssh-mount/06-01-SUMMARY.md` — Confirms repo mounts and `ngn-*` scripts available in Docker [VERIFIED: read]
- **CONTEXT.md** — D-01 through D-14 locked decisions for this phase [VERIFIED: read]
- **initial-plan.md** — `func session()` workflow specification [VERIFIED: read]
### Secondary (MEDIUM confidence)
- **Hermes research docs** — `.planning/research/hermes/SKILLS.md`, `EXTENSIBILITY.md`, `SUMMARY.md` — Skills system overview, plugin hook system, feature landscape [CITED: read]
- **FEATURES.md** — `.planning/research/FEATURES.md` — Feature dependencies, prioritization [CITED: read]
### Tertiary (LOW confidence)
- **Skill name resolution behavior** — How Hermes resolves directory path vs frontmatter name for skill_view — not tested [ASSUMED: A1]
- **skill_view behavior within active skill** — Whether loading another skill replaces or appends context — not verified [ASSUMED: Open Question 2]
- **hindsight_retain parameter names** — Exact tool schema for `tier` field — inferred from Hindsight documentation [ASSUMED: A5]
## Metadata
**Confidence breakdown:**
- Standard stack: HIGH — All tools and scripts confirmed available from completed phases (4, 5, 6) and Hermes built-in capabilities
- Architecture: HIGH — Patterns derived from Hermes official docs and 4 existing ngn-agent skills. Cross-skill orchestration is standard Hermes usage.
- Pitfalls: HIGH — Pitfalls based on known Hermes skill behavior, Hindsight tool characteristics, and session workflow constraints from D-01 through D-14
- Security: HIGH — All write operations gated behind user confirmation per locked decisions; read operations unrestricted
**Research date:** 2026-06-15
**Valid until:** 2026-07-15 (30 days — Hermes SKILL.md format is stable, Phase 5/6 dependencies are locked)