From d727c4dbce1592ed2751b892f771142b3d87ef17 Mon Sep 17 00:00:00 2001 From: Bagas Purwa Sentika Date: Mon, 15 Jun 2026 23:13:35 +0800 Subject: [PATCH] =?UTF-8?q?docs(09):=20create=20phase=20plan=20=E2=80=94?= =?UTF-8?q?=20custom=20Docker=20image=20+=20portable=20setup=20script?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 9 splits into two independent Wave 1 plans: - 09-01: Custom Hermes Docker image (ngn-agent:latest) with aws-cli, terraform, helm, kubectl, and datadog CLI (pup), version-pinned - 09-02: Portable setup-ngn-agent.sh with argument parsing, prerequisite checks, interactive secret prompts, config generation, skill/script embedding, and cron registration Also marks Phase 8 as complete (cron reporting shipped 2026-06-15). --- .planning/ROADMAP.md | 14 +- .planning/STATE.md | 16 +- .../09-tooling-portable-setup/09-01-PLAN.md | 224 ++++++++ .../09-tooling-portable-setup/09-02-PLAN.md | 478 ++++++++++++++++++ 4 files changed, 719 insertions(+), 13 deletions(-) create mode 100644 .planning/phases/09-tooling-portable-setup/09-01-PLAN.md create mode 100644 .planning/phases/09-tooling-portable-setup/09-02-PLAN.md 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 + +