diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index c67faaa..b95ec40 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -17,14 +17,14 @@
-### 🚧 v1.1 Session Lifecycle, Memory & Reporting (In Planning)
+### 🚧 v1.1 Session Lifecycle, Memory & Reporting (In Progress)
**Milestone Goal:** Productionize session workspace with default repos, upgrade to persistent cross-session memory (hindsight), operationalize daily reporting with session lifecycle management, and provide portable setup script with essential tools.
- [x] **Phase 5: Hindsight Memory Provider** — Cross-session persistent memory with entity-aware recall via Hindsight local_embedded
- [x] **Phase 6: Default Repos & SSH Mount** — DEFAULT_REPOS mounted via host filesystem + SSH credential mounting
- [x] **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
+- [x] **Phase 8: Cron Reporting** — Daily session summaries, stale session archiving, and Jira integration
- [ ] **Phase 9: Tooling & Portable Setup** — Custom Docker image with AWS CLI, Terraform, Helm, kubectl, Datadog CLI + portable setup script
## Phase Details
@@ -99,7 +99,11 @@ Plans:
3. Portable setup script (`setup-ngn-agent.sh`) recreates all config (hindsight, repos, SSH, skills, cron) on a fresh machine
4. Setup script accepts SSH key path and repo paths as parameters (no hardcoded paths)
5. After running setup script + gateway restart, a new session has all tools, repos, and skills working
-**Plans**: TBD
+**Plans**: 2 plans
+
+Plans:
+- [ ] 09-01-PLAN.md — Custom Docker image with 5 platform tools + build script (Wave 1)
+- [ ] 09-02-PLAN.md — Portable setup script recreating all config on fresh machine (Wave 1)
## Progress
@@ -112,5 +116,5 @@ Plans:
| 5. Hindsight Memory Provider | v1.1 | 1/1 | Complete | 2026-06-14 |
| 6. Default Repos & SSH Mount | v1.1 | 1/1 | Complete | 2026-06-14 |
| 7. Main Session Skill | v1.1 | 1/1 | Complete | 2026-06-14 |
-| 8. Cron Reporting | v1.1 | 0/2 | Not started | - |
-| 9. Tooling & Portable Setup | v1.1 | 0/TBD | Not started | - |
+| 8. Cron Reporting | v1.1 | 2/2 | Complete | 2026-06-15 |
+| 9. Tooling & Portable Setup | v1.1 | 0/2 | Not started | - |
diff --git a/.planning/STATE.md b/.planning/STATE.md
index 135a98d..dc5cdbb 100644
--- a/.planning/STATE.md
+++ b/.planning/STATE.md
@@ -3,15 +3,15 @@ gsd_state_version: 1.0
milestone: v1.1
milestone_name: Session Lifecycle, Memory & Reporting
status: executing
-stopped_at: Phase 7 complete — session skill created
-last_updated: "2026-06-15T14:44:17.573Z"
+stopped_at: Phase 9 context gathered
+last_updated: "2026-06-15T15:03:12.180Z"
last_activity: 2026-06-15 -- Phase 08 execution started
progress:
total_phases: 5
- completed_phases: 3
+ completed_phases: 4
total_plans: 5
- completed_plans: 3
- percent: 60
+ completed_plans: 5
+ percent: 80
---
# Project State
@@ -70,7 +70,7 @@ None yet.
## Session Continuity
-Last session: 2026-06-15T12:28:17.967Z
-Stopped at: Phase 7 complete — session skill created
-Resume file: .planning/phases/07-main-session-skill/07-01-SUMMARY.md
+Last session: 2026-06-15T15:03:12.173Z
+Stopped at: Phase 9 context gathered
+Resume file: .planning/phases/09-tooling-portable-setup/09-CONTEXT.md
Next action: /gsd-plan-phase 5 (Hindsight Memory Provider)
diff --git a/.planning/phases/09-tooling-portable-setup/09-01-PLAN.md b/.planning/phases/09-tooling-portable-setup/09-01-PLAN.md
new file mode 100644
index 0000000..3ff5d89
--- /dev/null
+++ b/.planning/phases/09-tooling-portable-setup/09-01-PLAN.md
@@ -0,0 +1,224 @@
+---
+phase: 09-tooling-portable-setup
+plan: 01
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - ngn-agent/docker/Dockerfile
+ - ngn-agent/docker/build.sh
+autonomous: true
+requirements: [TOOL-01]
+
+must_haves:
+ truths:
+ - "Custom Docker image can be built with a single command (docker/build.sh)"
+ - "Built image includes aws-cli v2, terraform, helm, kubectl, and datadog CLI (pup)"
+ - "Image is tagged ngn-agent:latest (local only, no registry push)"
+ - "Each tool version is pinned for reproducibility"
+ - "Build uses Dockerfile from the project repo (ngn-agent/docker/Dockerfile)"
+ artifacts:
+ - path: "ngn-agent/docker/Dockerfile"
+ provides: "Custom Hermes-compatible Docker image definition with 5 platform tools"
+ min_lines: 80
+ - path: "ngn-agent/docker/build.sh"
+ provides: "Single-command image build entry point"
+ min_lines: 15
+ key_links:
+ - from: "ngn-agent/docker/build.sh"
+ to: "ngn-agent/docker/Dockerfile"
+ via: "docker build -f"
+ pattern: "docker build.*-f.*Dockerfile"
+ - from: "Dockerfile"
+ to: "aws-cli v2"
+ via: "curl → unzip → aws/install"
+ pattern: "awscli\\.amazonaws\\.com/awscli-exe"
+ - from: "Dockerfile"
+ to: "terraform"
+ via: "HashiCorp apt repo"
+ pattern: "apt\\.releases\\.hashicorp\\.com"
+ - from: "Dockerfile"
+ to: "helm"
+ via: "Buildkite apt repo"
+ pattern: "packages\\.buildkite\\.com/helm"
+ - from: "Dockerfile"
+ to: "kubectl"
+ via: "Google Kubernetes apt repo"
+ pattern: "pkgs\\.k8s\\.io"
+ - from: "Dockerfile"
+ to: "pup (Datadog CLI)"
+ via: "GitHub releases binary download"
+ pattern: "github\\.com/DataDog/pup/releases"
+---
+
+
+**Custom Hermes Docker Image with Platform Engineering Tools**
+
+Create a custom Docker image extending `nikolaik/python-nodejs:python3.11-nodejs20` with five platform engineering CLI tools pre-installed: AWS CLI v2, Terraform, Helm, kubectl, and Datadog CLI (pup). The image is buildable with a single `docker/build.sh` command and tagged `ngn-agent:latest` for local use.
+
+**Purpose:** Eliminate per-session tool installation overhead — tools are baked into the Docker image so every Hermes session has immediate access to aws-cli, terraform, helm, kubectl, and pup without runtime installs.
+
+**Output:**
+- `ngn-agent/docker/Dockerfile` — Version-pinned tool installations on top of the base Hermes image
+- `ngn-agent/docker/build.sh` — Single-command build entry point
+
+
+
+@/Users/bapung/.config/opencode/gsd-core/workflows/execute-plan.md
+@/Users/bapung/.config/opencode/gsd-core/templates/summary.md
+
+
+
+@.planning/ROADMAP.md
+@.planning/phases/09-tooling-portable-setup/09-CONTEXT.md
+@.planning/phases/09-tooling-portable-setup/09-RESEARCH.md
+
+
+
+
+
+ Task 1: Create Dockerfile with version-pinned tool installations
+ ngn-agent/docker/Dockerfile
+
+ Create `ngn-agent/docker/Dockerfile` that:
+
+ 1. **FROM** extends `nikolaik/python-nodejs:python3.11-nodejs20` (per D-01). Add a comment above FROM noting: "D-01: Base image tag python3.11-nodejs20 — verify availability at build time; if manifest not found, update to python3.11-nodejs22-bookworm (Node.js 20 EOL April 2026)."
+
+ 2. **LABEL** with `description="ngn-agent: Custom Hermes Docker image with platform engineering tools"` and `maintainer="ngn-agent"`.
+
+ 3. **ARGs for version pinning** (per D-02):
+ - `TERRAFORM_VERSION=1.15.6`
+ - `HELM_VERSION=4.2.1`
+ - `KUBECTL_VERSION=1.36.1`
+ - `PUPP_VERSION=1.1.0`
+ (AWS CLI v2 is the latest stable — per D-03, install without version pinning but pin to latest known at time of build.)
+
+ 4. **Install system dependencies** in a single RUN:
+ `curl`, `ca-certificates`, `unzip`, `gnupg`, `wget` — clean apt lists after install.
+
+ 5. **Install AWS CLI v2** (per D-03):
+ Use the official curl → unzip → `./aws/install` method (no apt repo for v2). Install to `/usr/local/bin` and `/usr/local/aws-cli`. Clean up zip and extracted files. Reference D-03 in a comment.
+
+ 6. **Install Terraform** (per D-03):
+ Add HashiCorp GPG key, add HashiCorp apt repo, `apt-get install -y terraform=${TERRAFORM_VERSION}`. Clean apt lists. Reference D-03.
+
+ 7. **Install kubectl** (per D-03):
+ Add Google Kubernetes GPG key, add kubernetes apt repo for v1.36, `apt-get install -y kubectl`. Do NOT version-pin kubectl (it must match the target cluster version — per D-03: "latest stable matching cluster version"). Clean apt lists. Reference D-03.
+
+ 8. **Install Helm** (per D-03):
+ Add Buildkite GPG key, add Helm apt repo, `apt-get install -y helm=${HELM_VERSION}`. Clean apt lists. Reference D-03.
+
+ 9. **Install Datadog CLI (pup)** (per D-03):
+ Download the Linux x86_64 tarball from GitHub Releases, extract `pup` binary to `/usr/local/bin/`, clean up. Reference D-03.
+
+ 10. **Verify step**: Single RUN with `echo "=== Tool versions ===" && aws --version && terraform --version && helm version --short && kubectl version --client --output=yaml 2>/dev/null | grep gitVersion && pup --version`. Use `|| true` on version checks that may exit non-zero so build doesn't fail on a single tool being unreachable.
+
+ 11. **CMD** `["bash"]` — matching base image behavior.
+
+ **Build hygiene:**
+ - Do NOT `COPY .` or any full-directory copy — this prevents leaking secrets into image layers (T-09-02 mitigation).
+ - Order tool installs from most-frequently-changed to least-changed to optimize layer caching.
+ - Use `--no-install-recommends` on all apt-get install commands.
+ - Remove apt lists after each apt install to keep image small.
+ - All tool downloads use HTTPS URLs (T-09-01 mitigation).
+ - Add inline comments referencing each D-NN decision for traceability.
+
+
+ test -f /Users/bapung/Razer/ngn-agent/docker/Dockerfile && wc -l /Users/bapung/Razer/ngn-agent/docker/Dockerfile
+
+
+ - Dockerfile exists at ngn-agent/docker/Dockerfile
+ - All 5 tools (aws-cli, terraform, helm, kubectl, pup) are installed via RUN commands
+ - Tool versions are pinned via ARGs (except kubectl which matches cluster version)
+ - D-01 through D-03 are referenced in comments
+ - No `COPY .` or directory-wide copy present
+
+
+
+
+ Task 2: Create build.sh and verify image builds successfully
+ ngn-agent/docker/build.sh
+
+ Create `ngn-agent/docker/build.sh` (per D-04):
+
+ 1. Shebang: `#!/bin/bash` with `set -euo pipefail`.
+
+ 2. Constants:
+ - `IMAGE_NAME="ngn-agent"`
+ - `IMAGE_TAG="latest"`
+ - `DOCKER_DIR` resolved from script location: `"$(cd "$(dirname "$0")" && pwd)"`
+
+ 3. Print build banner: `echo "==> Building ${IMAGE_NAME}:${IMAGE_TAG}..."`
+
+ 4. `docker build` command:
+ - `-t "${IMAGE_NAME}:${IMAGE_TAG}"`
+ - `-f "${DOCKER_DIR}/Dockerfile"`
+ - Build context: `"${DOCKER_DIR}"` (not the repo root — prevents leaking files)
+ - Per D-05: tag is `ngn-agent:latest` (local only, no registry push)
+
+ 5. Print completion banner: `echo "==> Build complete: ${IMAGE_NAME}:${IMAGE_TAG}"` followed by `docker images "${IMAGE_NAME}:${IMAGE_TAG}"`.
+
+ 6. Make the script executable: `chmod +x /Users/bapung/Razer/ngn-agent/docker/build.sh`.
+
+ **Verify the build** by running `docker/build.sh` (or `bash docker/build.sh` if script path issues). If the base image tag `python3.11-nodejs20` fails with a manifest error, update the Dockerfile FROM line to `nikolaik/python-nodejs:python3.11-nodejs22-bookworm` as recommended by research, add a comment noting the change, and retry. After successful build:
+
+ - Run `docker run --rm ngn-agent:latest aws --version` — confirms aws-cli is installed and executable
+ - Run `docker run --rm ngn-agent:latest terraform --version` — confirms terraform works
+ - Run `docker run --rm ngn-agent:latest helm version --short` — confirms helm works
+ - Run `docker run --rm ngn-agent:latest kubectl version --client` — confirms kubectl works
+ - Run `docker run --rm ngn-agent:latest pup --version` — confirms pup works
+
+ If any tool fails in the container, fix the Dockerfile and rebuild. The image must have all 5 tools working.
+
+
+ docker run --rm ngn-agent:latest sh -c 'aws --version && terraform --version && helm version --short && kubectl version --client && pup --version'
+
+
+ - build.sh exists and is executable
+ - `ngn-agent:latest` image builds successfully
+ - All 5 tools execute correctly inside the container
+ - Build script references D-04 and D-05 decisions
+ - If base image tag was updated to python3.11-nodejs22-bookworm due to deprecation, the FROM line is updated and a comment explains the change
+
+
+
+
+
+
+## Trust Boundaries
+
+| Boundary | Description |
+|----------|-------------|
+| Docker build host → Docker daemon | Docker context is read by build daemon |
+| Docker build → external tool repos | Tool downloads cross HTTPS boundaries |
+| Docker image layers → local storage | Built image stored on host filesystem |
+
+## STRIDE Threat Register
+
+| Threat ID | Category | Component | Disposition | Mitigation Plan |
+|-----------|----------|-----------|-------------|-----------------|
+| T-09-01 | Tampering | Tool download MITM (curl/wget from S3, GitHub, apt repos) | mitigate | All downloads use HTTPS. apt repos use GPG key verification to sign packages. |
+| T-09-02 | Information Disclosure | Build context leak (COPY . could send .env into Docker daemon) | mitigate | Build context is `docker/` directory only — not repo root. Dockerfile does not COPY . anywhere. |
+| T-09-03 | Tampering | Base image supply chain (nikolaik/python-nodejs) | accept | Widely used community image; no custom base image available. |
+| T-09-04 | Denial of Service | Base image tag python3.11-nodejs20 may not exist | mitigate | Dockerfile comment flags potential deprecation. If build fails with manifest error, update to python3.11-nodejs22-bookworm. |
+
+## Package Legitimacy Gate
+
+| Package | Registry | Verdict | Disposition |
+|---------|----------|---------|-------------|
+| (none) | — | — | No npm/pip/cargo packages installed. All tools via apt or curl binary downloads. |
+
+
+
+- Automated: `docker run --rm ngn-agent:latest sh -c 'aws --version && terraform --version && helm version --short && kubectl version --client && pup --version'` passes with all 5 tools
+- Manual: User can inspect `docker/images` output to confirm tag and creation date
+
+
+
+1. The image `ngn-agent:latest` exists in local Docker daemon
+2. Running `docker run --rm ngn-agent:latest --version` succeeds for all 5 tools
+3. `docker/build.sh` is the single entry point for rebuilding
+4. Both files are committed to the ngn-agent git repo
+5. Tool versions are pinned (ARGS in Dockerfile) for future reproducibility
+
+
diff --git a/.planning/phases/09-tooling-portable-setup/09-02-PLAN.md b/.planning/phases/09-tooling-portable-setup/09-02-PLAN.md
new file mode 100644
index 0000000..25a3241
--- /dev/null
+++ b/.planning/phases/09-tooling-portable-setup/09-02-PLAN.md
@@ -0,0 +1,478 @@
+---
+phase: 09-tooling-portable-setup
+plan: 02
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - ngn-agent/setup-ngn-agent.sh
+autonomous: true
+requirements: [SETUP-01]
+
+user_setup:
+ - service: hermes
+ why: "Setup script assumes Hermes v0.16+ is installed"
+ env_vars:
+ - name: JIRA_API_TOKEN
+ source: "https://id.atlassian.com/manage/api-tokens"
+ - name: JIRA_EMAIL
+ source: "Your Atlassian account email"
+ - name: TELEGRAM_BOT_TOKEN
+ source: "https://t.me/BotFather — create a bot and copy the token"
+ - name: OPENROUTER_API_KEY
+ source: "https://openrouter.ai/keys (or reuse existing)"
+
+must_haves:
+ truths:
+ - "User can run setup-ngn-agent.sh on a fresh macOS machine with Hermes installed"
+ - "Script validates prerequisites (Hermes on PATH, Docker running, SSH keys exist) before making changes"
+ - "Script prompts for all 4 secrets (JIRA_API_TOKEN, JIRA_EMAIL, TELEGRAM_BOT_TOKEN, OPENROUTER_API_KEY) with masked input"
+ - "Script accepts configurable paths via args or prompts (SSH keys, repo paths, timezone)"
+ - "After running, ~/.hermes/config.yaml has correct docker_volumes, shell_init_files, docker_forward_env, and docker_image"
+ - "After running, ~/.hermes/.env has all secrets and DEFAULT_REPOS"
+ - "After running, ~/.hermes/hindsight/config.json has Hindsight local_embedded config"
+ - "After running, ~/.hermes/scripts/ has session-init.sh and archive-stale-sessions.sh"
+ - "After running, ~/.hermes/skills/ngn-agent/ has all 5 skills with reference files"
+ - "After running, 3 cron jobs (ngn-daily-report, ngn-weekly-stale-summary, ngn-weekly-archive) are registered"
+ - "After running, docker_image in config.yaml points to ngn-agent:latest"
+ - "Script backups existing config.yaml before modifying"
+ - "Script offers to restart Hermes gateway at end"
+ artifacts:
+ - path: "ngn-agent/setup-ngn-agent.sh"
+ provides: "Portable one-shot macOS setup script for ngn-agent configuration"
+ min_lines: 300
+ key_links:
+ - from: "setup-ngn-agent.sh"
+ to: "~/.hermes/config.yaml"
+ via: "hermes config set + Python/sed for docker_volumes"
+ pattern: "hermes config set|config\\.yaml"
+ - from: "setup-ngn-agent.sh"
+ to: "~/.hermes/.env"
+ via: "cat/write secrets to .env"
+ pattern: "(JIRA_API_TOKEN|TELEGRAM_BOT_TOKEN)"
+ - from: "setup-ngn-agent.sh"
+ to: "~/.hermes/hindsight/config.json"
+ via: "write JSON config"
+ pattern: "hindsight/config\\.json"
+ - from: "setup-ngn-agent.sh"
+ to: "~/.hermes/scripts/"
+ via: "heredoc or cat file contents to scripts/"
+ pattern: "(session-init|archive-stale)"
+ - from: "setup-ngn-agent.sh"
+ to: "~/.hermes/skills/ngn-agent/"
+ via: "mkdir -p SKILL.md per skill"
+ pattern: "skills/ngn-agent"
+ - from: "setup-ngn-agent.sh"
+ to: "Hermes cron DB"
+ via: "hermes cron create"
+ pattern: "hermes cron create"
+ - from: "setup-ngn-agent.sh"
+ to: "Docker image"
+ via: "hermes config set terminal.docker_image"
+ pattern: "docker_image ngn-agent"
+---
+
+
+**Portable ngn-agent Setup Script**
+
+Create a single portable bash script (`ngn-agent/setup-ngn-agent.sh`) that can recreate all ngn-agent configuration on a fresh macOS machine with Hermes v0.16+ installed. The script handles prerequisite validation, interactive secret prompts, config file generation (config.yaml, .env, hindsight/config.json), skill/script file creation, cron job registration, and Docker image reference updates — all in one invocation.
+
+**Purpose:** Enable a new machine to be fully configured with ngn-agent's workspace setup (SSH mounts, repo mounts, skills, cron reporting, hindsight memory) by running a single script with parameterized paths and interactive secret entry.
+
+**Output:**
+- `ngn-agent/setup-ngn-agent.sh` — Standalone portable setup script (self-contained, no external file dependencies)
+
+
+
+@/Users/bapung/.config/opencode/gsd-core/workflows/execute-plan.md
+@/Users/bapung/.config/opencode/gsd-core/templates/summary.md
+
+
+
+@.planning/ROADMAP.md
+@.planning/phases/09-tooling-portable-setup/09-CONTEXT.md
+@.planning/phases/09-tooling-portable-setup/09-RESEARCH.md
+@/Users/bapung/.hermes/config.yaml
+@/Users/bapung/.hermes/.env
+@/Users/bapung/.hermes/hindsight/config.json
+@/Users/bapung/.hermes/scripts/session-init.sh
+@/Users/bapung/.hermes/scripts/archive-stale-sessions.sh
+@/Users/bapung/.hermes/skills/ngn-agent/jira/SKILL.md
+@/Users/bapung/.hermes/skills/ngn-agent/aws-diagnostics/SKILL.md
+@/Users/bapung/.hermes/skills/ngn-agent/confluence/SKILL.md
+@/Users/bapung/.hermes/skills/ngn-agent/bitbucket/SKILL.md
+@/Users/bapung/.hermes/skills/ngn-agent/session/SKILL.md
+@/Users/bapung/.hermes/skills/ngn-agent/aws-diagnostics/references/multiregional-patterns.md
+@/Users/bapung/.hermes/skills/ngn-agent/session/references/operational-monitoring.md
+@.planning/phases/08-cron-reporting/08-01-SUMMARY.md
+@.planning/phases/08-cron-reporting/08-02-SUMMARY.md
+
+
+
+
+
+ Task 1: Create setup script skeleton — args, prereqs, and interactive prompts
+ ngn-agent/setup-ngn-agent.sh
+
+ Create `ngn-agent/setup-ngn-agent.sh` starting with the script skeleton, argument parsing, prerequisite validation, and interactive secret prompts. This is the first part of the file (approximately first 120 lines).
+
+ **Script header:**
+ - Shebang: `#!/bin/bash` with `set -euo pipefail` (per D-06)
+ - Comment header block: `# setup-ngn-agent.sh — Portable ngn-agent configuration setup`
+ - Include: `# Phase 9, Plan 2 — recreates all configuration on a fresh macOS machine`
+ - Include: `# Assumes Hermes v0.16+ is installed (per D-07)`
+ - Include: `# Embedded file snapshots frozen at: $(date +%Y-%m-%d)` (per Common Pitfall 4)
+
+ **Argument parsing** (per D-09):
+ Use `getopts` for named arguments with defaults:
+ - `-s1 | --ssh-key-1` — SSH private key path 1 (default: `~/.ssh/id_ed25519razer`)
+ - `-s2 | --ssh-key-2` — SSH private key path 2 (default: `~/.ssh/id_rsa`)
+ - `-sc | --ssh-config` — SSH config path (default: `~/.ssh/config`)
+ - `-sh | --ssh-known-hosts` — SSH known_hosts path (default: `~/.ssh/known_hosts`)
+ - `-r1 | --repo-ops` — rai-ops repo path (default: `~/Razer/rai-ops`)
+ - `-r2 | --repo-deploy` — rai-deployment repo path (default: `~/Razer/rai-deployment`)
+ - `-r3 | --repo-devtools` — rai-devtools repo path (default: `~/Razer/rai-devtools`)
+ - `-t | --timezone` — Timezone (default: `Asia/Singapore`)
+ - `-d | --docker-image` — Docker image tag (default: `ngn-agent:latest`)
+ - `-y | --yes` — Non-interactive mode (skip prompts, use defaults for secrets if set via env)
+ - `-h | --help` — Show usage
+
+ Display usage info when `-h` is passed, showing all parameters with defaults.
+
+ **Prerequisite checks** (per CONTEXT.md "Specific Ideas" > "should validate prerequisites"):
+ 1. Check Hermes CLI is installed: `command -v hermes >/dev/null 2>&1 || { echo "ERROR: Hermes not found — install v0.16+ first"; exit 1; }`
+ 2. Check Docker is running: `docker info >/dev/null 2>&1 || { echo "ERROR: Docker not running"; exit 1; }`
+ 3. Check SSH key files exist (the two key paths from args): test `-f` each, warn if missing but don't abort (user can skip keys).
+ 4. Check repo paths exist: test `-d` each, warn if missing but don't abort.
+ 5. Print a summary of paths being used.
+
+ **Interactive secret prompts** (per D-08):
+ Define a `prompt_secret` function:
+ - Args: var_name, prompt_text, is_optional (default: false)
+ - Use `read -s -p` for masked input (T-09-05 mitigation — no echo to terminal)
+ - If not optional, loop until non-empty value provided
+ - If the env var is already set (e.g., user exported it), skip the prompt
+ - Return the value via `echo`
+
+ Prompt for these secrets (D-08):
+ 1. `JIRA_API_TOKEN` — required — "JIRA API Token (https://id.atlassian.com/manage/api-tokens): "
+ 2. `JIRA_EMAIL` — required — "JIRA Email: "
+ 3. `TELEGRAM_BOT_TOKEN` — required — "Telegram Bot Token (from @BotFather): "
+ 4. `OPENROUTER_API_KEY` — optional (check if already set in env) — "OpenRouter API Key (leave blank to keep existing): "
+ 5. `HINDSIGHT_LLM_API_KEY` — optional (defaults to same as OPENROUTER_API_KEY)
+
+ Store prompted values in variables for use in Task 2.
+
+ **Config directory creation:**
+ - `mkdir -p ~/.hermes/scripts`
+ - `mkdir -p ~/.hermes/hindsight`
+ - `mkdir -p ~/.hermes/skills/ngn-agent`
+ - `mkdir -p ~/.hermes/archive/sessions`
+
+ **Backup existing config** (per Anti-Pattern 4):
+ - If `~/.hermes/config.yaml` exists, copy to `~/.hermes/config.yaml.bak.$(date +%Y%m%d_%H%M%S)` before modifying (T-09-07 mitigation).
+
+ Make the script executable: `chmod +x /Users/bapung/Razer/ngn-agent/setup-ngn-agent.sh`.
+
+ **Embedded content strategy:**
+ - All skill files, script files, and reference files are embedded as heredocs (not base64 — bash heredocs with quoted delimiters preserve file content without encoding overhead for text files).
+ - Each embedded file is a bash function that can be called to write its content to the target path.
+ - The function names follow the pattern: `write_` (e.g., `write_session_init`, `write_jira_skill`).
+
+ **Notes:**
+ - Reference D-06 through D-09 in comments where applicable.
+ - Use `echo " → [message]"` for progress output.
+ - Color/formatting: optional but keep simple (no dependencies).
+
+
+ test -f /Users/bapung/Razer/ngn-agent/setup-ngn-agent.sh && head -20 /Users/bapung/Razer/ngn-agent/setup-ngn-agent.sh | grep -q 'setup-ngn-agent'
+
+
+ - setup-ngn-agent.sh exists and is executable
+ - Argument parsing with getopts handles all 9 parameters with defaults
+ - Usage displayed with `-h`
+ - Prerequisite checks validate Hermes CLI, Docker, SSH key files, repo paths
+ - Interactive `prompt_secret` function implemented for masked input
+ - All 4 secrets prompted (JIRA_API_TOKEN, JIRA_EMAIL, TELEGRAM_BOT_TOKEN, OPENROUTER_API_KEY)
+ - Existing config.yaml is backed up before modification
+ - Embedded file write functions are defined (content filled in Task 2 and Task 3)
+ - D-06 through D-09 referenced in comments
+
+
+
+
+ Task 2: Implement config generation — config.yaml, .env, hindsight/config.json
+ ngn-agent/setup-ngn-agent.sh
+
+ Append (or fill in) the config generation functions in `setup-ngn-agent.sh`. These come after the Task 1 skeleton.
+
+ **Function: `generate_config_yaml`**
+ Write a new `~/.hermes/config.yaml` using `hermes config set` for simple keys and Python for complex YAML structures (per Research Pattern 3 — `hermes config set` for scalars, Python for arrays).
+
+ Keys to set via `hermes config set`:
+ - `terminal.backend docker`
+ - `terminal.docker_image ${DOCKER_IMAGE}` (default `ngn-agent:latest` — per D-10 "Update Docker image reference in config.yaml")
+ - `terminal.cwd /workspace`
+ - `terminal.container_memory 5120`
+ - `terminal.container_disk 51200`
+ - `terminal.container_cpu 1`
+ - `terminal.lifetime_seconds 300`
+ - `memory.provider hindsight`
+ - `terminal.timezone ${TIMEZONE}`
+ - `telegram.reactions false`
+ - `terminal.docker_env.AWS_REGION us-east-1`
+ - `terminal.container_persistent true`
+ - `terminal.docker_mount_cwd_to_workspace true`
+
+ For complex structures (docker_volumes array, shell_init_files, docker_forward_env), use Python 3 with `yaml` module. Write a Python script inline that:
+ 1. Loads existing config.yaml (created by hermes config set calls)
+ 2. Sets `terminal.docker_volumes` to the list:
+ ```
+ "${SSH_KEY_1}:/root/.ssh/id_ed25519razer:ro",
+ "${SSH_KEY_2}:/root/.ssh/id_rsa:ro",
+ "${SSH_CONFIG}:/root/.ssh/config:ro",
+ "${SSH_KNOWN_HOSTS}:/root/.ssh/known_hosts:ro",
+ "${HOME}/.aws/config:/root/.aws/config:ro",
+ "${HOME}/.aws/sso/cache:/root/.aws/sso/cache:rw",
+ "${REPO_OPS}:/workspace/rai-ops:rw",
+ "${REPO_DEPLOY}:/workspace/rai-deployment:rw",
+ "${REPO_DEVTOOLS}:/workspace/rai-devtools:rw",
+ "${HOME}/.hermes/scripts:/usr/local/bin:ro",
+ ```
+ 3. Sets `terminal.docker_forward_env` to `['JIRA_EMAIL', 'JIRA_API_TOKEN', 'DEFAULT_REPOS']`
+ 4. Sets `terminal.shell_init_files` to `['/usr/local/bin/session-init.sh']`
+ 5. Writes back to config.yaml
+ If `python3` + `yaml` module is not available, fall back to a `sed`-based approach using heredoc templates.
+
+ **Function: `generate_env_file`**
+ Write `~/.hermes/.env` with:
+ 1. Comment header: `# ngn-agent Environment — generated by setup-ngn-agent.sh`
+ 2. Required vars (D-08):
+ - `OPENROUTER_API_KEY=` (if provided)
+ - `JIRA_API_TOKEN=`
+ - `JIRA_EMAIL=`
+ - `TELEGRAM_BOT_TOKEN=`
+ - `HINDSIGHT_LLM_API_KEY=` (defaults to OPENROUTER_API_KEY if not separately provided)
+ 3. Config vars:
+ - `DEFAULT_REPOS=rai-ops,rai-deployment,rai-devtools`
+ - `TELEGRAM_ALLOWED_USERS=474440517`
+ - `TERMINAL_TIMEOUT=60`
+ - `TERMINAL_LIFETIME_SECONDS=300`
+ 4. Set file permissions: `chmod 600 ~/.hermes/.env` (T-09-06 mitigation — prevent world-readable secrets)
+ Include comment separators between sections matching the original .env style.
+
+ **Function: `generate_hindsight_config`**
+ Write `~/.hermes/hindsight/config.json` with exact content from current config (D-10):
+ ```json
+ {
+ "mode": "local_embedded",
+ "llm_provider": "openrouter",
+ "llm_base_url": "https://openrouter.ai/api/v1",
+ "llm_model": "qwen/qwen3.5-9b",
+ "bank_id": "hermes",
+ "recall_budget": "low",
+ "recall_prefetch_method": "recall",
+ "auto_recall": true,
+ "recall_types": "observation",
+ "auto_retain": true,
+ "retain_async": true,
+ "retain_every_n_turns": 5,
+ "memory_mode": "hybrid"
+ }
+ ```
+
+ **Function: `generate_cron_env_config`**
+ Ensure cron has the required env vars by running:
+ - `hermes config set cron.env.JIRA_EMAIL "${JIRA_EMAIL}"`
+ - `hermes config set cron.env.JIRA_API_TOKEN "${JIRA_API_TOKEN}"`
+
+ **Definition order:** The functions are defined first, then called from the main execution block at the bottom of the script.
+
+ **Notes:**
+ - Reference D-10 for each section it creates/updates.
+ - If the baseline config.yaml structure changes (e.g., Hermes adds a new required field), the Python YAML script should preserve unknown keys (load, modify, dump — not overwrite completely).
+ - After writing config.yaml, validate with `hermes config get terminal.docker_image` to confirm it was set.
+ - Set `chmod 600` on .env immediately after writing (T-09-06).
+
+
+ grep -c 'generate_config_yaml\|generate_env_file\|generate_hindsight_config' /Users/bapung/Razer/ngn-agent/setup-ngn-agent.sh
+
+
+ - `generate_config_yaml` sets all config.yaml keys using hermes config set + Python YAML
+ - `generate_env_file` writes all secrets and DEFAULT_REPOS to .env with chmod 600
+ - `generate_hindsight_config` writes hindsight/config.json
+ - Docker image reference in config.yaml is updated to ngn-agent:latest (D-10)
+ - Cron env vars (JIRA_EMAIL, JIRA_API_TOKEN) are configured
+ - D-10 referenced in comments for each section
+
+
+
+
+ Task 3: Implement file/cron setup — scripts, skills, cron registration, gateway restart
+ ngn-agent/setup-ngn-agent.sh
+
+ Append the file writing functions and cron registration to `setup-ngn-agent.sh`. These complete the setup script.
+
+ **Function: `write_session_init_script`**
+ Write `~/.hermes/scripts/session-init.sh` with the exact content from the current file (37 lines). This script verifies DEFAULT_REPOS mounts at session start. Use a heredoc with a quoted delimiter (`'EOF'`) to prevent variable expansion:
+ ```bash
+ cat > ~/.hermes/scripts/session-init.sh << 'SCRIPT'
+ #!/bin/bash
+ # session-init.sh — Verify DEFAULT_REPOS mounts at session start
+ # ... (exact content)
+ SCRIPT
+ chmod +x ~/.hermes/scripts/session-init.sh
+ ```
+
+ **Function: `write_archive_script`**
+ Same approach for `~/.hermes/scripts/archive-stale-sessions.sh` (41 lines) with `DRY_RUN=true` default and `set -euo pipefail`.
+
+ **Function: `write_skill_files`**
+ For each of the 5 skills (per D-10: all 5 skill directories), create the directory and write the SKILL.md:
+ 1. `~/.hermes/skills/ngn-agent/jira/SKILL.md`
+ 2. `~/.hermes/skills/ngn-agent/aws-diagnostics/SKILL.md`
+ 3. `~/.hermes/skills/ngn-agent/confluence/SKILL.md`
+ 4. `~/.hermes/skills/ngn-agent/bitbucket/SKILL.md`
+ 5. `~/.hermes/skills/ngn-agent/session/SKILL.md`
+
+ Use heredocs with quoted delimiters to write each file with exact content from the current source files. For `aws-diagnostics` and `session` skills, also create their reference directories and files:
+ - `~/.hermes/skills/ngn-agent/aws-diagnostics/references/multiregional-patterns.md`
+ - `~/.hermes/skills/ngn-agent/session/references/operational-monitoring.md`
+
+ **Function: `register_cron_jobs`**
+ Register 3 cron jobs (D-10) using `hermes cron create` with the exact syntax verified in Phase 8:
+
+ 1. `ngn-daily-report` (per Phase 8 Plan 2 summary):
+ ```
+ hermes cron create --deliver telegram --skill session --skill jira-query \
+ '0 9 * * *' \
+ 'Daily session report. Export sessions, find active ones, check Jira, compose Telegram summary.'
+ ```
+ Note: Use the exact cron registration pattern from Phase 8 SUMMARYs:
+ - Skill-backed: `--deliver telegram --skill 'schedule' 'prompt'`
+ - The `ngn-weekly-stale-summary` and `ngn-weekly-archive` from Phase 8 Plan 2
+
+ 2. `ngn-weekly-stale-summary`:
+ ```
+ hermes cron create --deliver telegram --skill session \
+ '0 20 * * 0' \
+ 'Weekly stale session summary. ...'
+ ```
+
+ 3. `ngn-weekly-archive`:
+ ```
+ hermes cron create --no-agent --script archive-stale-sessions.sh \
+ '5 20 * * 0'
+ ```
+
+ **Function: `offer_gateway_restart`**
+ At the end of the script, after all configuration is complete (per CONTEXT.md "Specific Ideas"):
+ ```bash
+ echo ""
+ echo "==> Setup complete!"
+ echo ""
+ read -p "Restart Hermes gateway now? [Y/n]: " restart
+ if [[ "$restart" =~ ^[Yy]?$ ]]; then
+ hermes gateway restart
+ echo " → Gateway restarted."
+ else
+ echo " → Skipped. Run 'hermes gateway restart' when ready."
+ fi
+ ```
+
+ **Main execution block:**
+ At the bottom of the script, add the main execution flow that calls all functions in order:
+ 1. Parse arguments (Task 1)
+ 2. Check prerequisites (Task 1)
+ 3. Prompt for secrets (Task 1)
+ 4. Create directories (Task 1)
+ 5. Backup existing config (Task 1)
+ 6. Generate config.yaml (Task 2)
+ 7. Generate .env (Task 2)
+ 8. Generate hindsight config (Task 2)
+ 9. Generate cron env config (Task 2)
+ 10. Write session-init script (Task 3)
+ 11. Write archive script (Task 3)
+ 12. Write skill files (Task 3)
+ 13. Register cron jobs (Task 3)
+ 14. Offer gateway restart (Task 3)
+
+ Each step should print a progress indicator like `[1/14] Checking prerequisites...`.
+
+ **Error handling:**
+ - If any step fails (non-zero exit), print a warning but continue (best-effort) unless it's a critical prerequisite.
+ - The `set -euo pipefail` at the top means any failure exits unless explicitly handled with `|| true`.
+ - Wrap non-critical steps: `register_cron_jobs || echo " âš Cron registration had issues (may already exist)"`.
+
+ **Notes:**
+ - Reference D-10 for the full list of what the script creates/updates.
+ - Add a lifecycle comment at the top: "Embedded file snapshots frozen at: $(date +%Y-%m-%d) — Regenerate by re-running this phase."
+ - Test the script after writing: if Docker is running, do a dry-run check with `bash -n setup-ngn-agent.sh` to validate syntax.
+
+
+ bash -n /Users/bapung/Razer/ngn-agent/setup-ngn-agent.sh
+
+
+ - All 5 skill SKILL.md files are embedded as heredocs
+ - 2 reference files (multiregional-patterns.md, operational-monitoring.md) are embedded
+ - 2 scripts (session-init.sh, archive-stale-sessions.sh) are embedded and made executable
+ - 3 cron jobs are registered via hermes cron create
+ - Gateway restart offer is at the end
+ - Script passes `bash -n` syntax validation
+ - D-10 is referenced in comments for each section it creates/updates
+ - Script is fully self-contained (no external file read dependencies)
+
+
+
+
+
+
+## Trust Boundaries
+
+| Boundary | Description |
+|----------|-------------|
+| Terminal (stdin) → script | User types secrets via read -s — masked input, no echo |
+| Script → ~/.hermes/.env | Secrets written to plaintext file at rest |
+| Script → Hermes cron DB | Cron job registration via hermes CLI |
+| Script → ~/.hermes/config.yaml | Config YAML generation |
+
+## STRIDE Threat Register
+
+| Threat ID | Category | Component | Disposition | Mitigation Plan |
+|-----------|----------|-----------|-------------|-----------------|
+| T-09-05 | Information Disclosure | Secret exposure in terminal history | mitigate | `read -s` for all secret prompts (masked input, no echo to terminal) |
+| T-09-06 | Information Disclosure | ~/.hermes/.env world-readable secrets | mitigate | `chmod 600` on .env immediately after writing |
+| T-09-07 | Tampering | Config file corruption from partial write | mitigate | Backup existing config.yaml to `.bak.` before modification |
+| T-09-08 | Information Disclosure | Secrets captured in terminal scrollback | accept | Users are responsible for terminal security on their own machines |
+| T-09-09 | Tampering | Cron job with malicious prompt | accept | Cron prompts are embedded in the setup script, not user-controllable |
+
+## Package Legitimacy Gate
+
+| Package | Registry | Verdict | Disposition |
+|---------|----------|---------|-------------|
+| (none) | — | — | No npm/pip/cargo packages installed. All operations via bash built-ins, hermes CLI, and Python stdlib. |
+
+
+
+- Automated: `bash -n /Users/bapung/Razer/ngn-agent/setup-ngn-agent.sh` passes (syntax check)
+- Automated: `grep -c 'hermes cron create' setup-ngn-agent.sh` returns 3 (all cron jobs)
+- Automated: `grep -c 'write_session_init\|write_archive_script\|write_jira_skill\|write_aws_skill\|write_confluence_skill\|write_bitbucket_skill\|write_session_skill' setup-ngn-agent.sh` returns 8 (all scripts + 5 skills + 2 ref files)
+- Manual: User can inspect `setup-ngn-agent.sh --help` to see all parameters
+- Dry-run: User can run `bash -x setup-ngn-agent.sh` to trace execution (no destructive test needed)
+
+
+
+1. setup-ngn-agent.sh exists, is executable, and passes bash syntax validation
+2. Script accepts all 9 parameters via getopts with documented defaults
+3. Prerequisites checks for Hermes CLI, Docker, SSH keys
+4. All 4 secrets prompted with masked input
+5. Config generation: config.yaml, .env, hindsight/config.json
+6. All 5 skill directories + SKILL.md files + reference files embedded and written
+7. Both scripts (session-init.sh, archive-stale-sessions.sh) embedded and written
+8. All 3 cron jobs registered (ngn-daily-report, ngn-weekly-stale-summary, ngn-weekly-archive)
+9. Docker image reference updated to ngn-agent:latest
+10. Existing config.yaml backed up before modification
+11. Gateway restart offered at completion
+12. D-06 through D-10 referenced in comments for traceability
+
+