From 4520237754e7ad22b71181fef06b3b5588ff943e Mon Sep 17 00:00:00 2001 From: Bagas Purwa Sentika Date: Mon, 15 Jun 2026 23:31:23 +0800 Subject: [PATCH] docs(09-tooling-portable-setup-02): complete portable setup script plan - Created 1340-line standalone setup-ngn-agent.sh with argument parsing, prereq checks, masked secret prompts, config generation, embedded skills/scripts, cron registration, and gateway restart offer - All 3 tasks committed atomically --- .../09-02-SUMMARY.md | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 .planning/phases/09-tooling-portable-setup/09-02-SUMMARY.md diff --git a/.planning/phases/09-tooling-portable-setup/09-02-SUMMARY.md b/.planning/phases/09-tooling-portable-setup/09-02-SUMMARY.md new file mode 100644 index 0000000..93198e6 --- /dev/null +++ b/.planning/phases/09-tooling-portable-setup/09-02-SUMMARY.md @@ -0,0 +1,167 @@ +--- +phase: 09-tooling-portable-setup +plan: 02 +subsystem: setup +tags: [bash, hermes, setup-script, provisioning, cron, skills] + +requires: + - phase: 08-cron-reporting + plan: 01 + provides: archive-stale-sessions.sh script content, cron registration patterns (hermes cron create CLI syntax, DRY_RUN pattern) + - phase: 08-cron-reporting + plan: 02 + provides: Weekly cron job patterns (ngn-weekly-stale-summary, ngn-weekly-archive) with 5-minute offset between summary and archive + - phase: 07-main-session-skill + provides: session skill SKILL.md content for embedding; hindsight_retain templates, Jira ticket creation pattern with epic cache + - phase: 04-jira-skill + provides: jira-query skill SKILL.md content for embedding + +provides: + - ngn-agent/setup-ngn-agent.sh — 1340-line standalone portable setup script with embedded file snapshots + - All 5 skill files + 2 reference files embedded as heredocs for self-contained re-creation + - Config generation: config.yaml (via hermes config set + Python yaml), .env (with chmod 600), hindsight/config.json + - 3 cron job registrations (ngn-daily-report, ngn-weekly-stale-summary, ngn-weekly-archive) + - Interactive secret prompts with masked input (T-09-05 mitigation) + - Best-effort error handling pattern for non-critical steps + +affects: + - Phase 10+ (any phase needing to regenerate ngn-agent configuration on a new machine) + +tech-stack: + added: [] + patterns: + - Standalone portable setup script with embedded heredocs (no external file dependencies) + - Hybrid config generation: hermes config set for scalars + Python yaml (fallback sed) for arrays + - prompt_secret function with env-var skip, masked input, loop-until-nonempty + - Best-effort error handling: non-critical steps wrapped with || true + - Progress indicator pattern [N/14] for step-by-step execution + +key-files: + created: + - ngn-agent/setup-ngn-agent.sh — 1340-line portable setup script + modified: [] + +key-decisions: + - "Each embedded file is a separate write function (write_session_init, write_jira_skill, etc.) — self-documenting and independently testable" + - "Config.yaml uses hybrid approach: hermes config set for scalar keys, Python yaml module for arrays, sed fallback when yaml unavailable" + - "Skill and script files embedded as heredocs with quoted delimiters ('EOF') — prevents variable expansion at script generation time" + - "Cron registration wrapped with 2>/dev/null + 'may already exist' message — idempotent re-runs" + - "Non-interactive mode (-y) reads secrets from environment variables with : ${VAR:?error} validation" + +patterns-established: + - "Standalone portable setup script pattern: argument parsing → prereq checks → secret prompts → file generation → cron registration → restart offer" + - "Embedded heredoc pattern: each file is a bash function with cat > path << 'QUOTED_DELIM' to prevent variable expansion in embedded content" + - "Hybrid YAML generation: hermes config set for scalars, Python yaml for arrays, sed fallback" + +requirements-completed: [SETUP-01] + +duration: 4 min +completed: 2026-06-15 +--- + +# Phase 9 Plan 2: Portable ngn-agent Setup Script Summary + +**Portable 1340-line standalone bash setup script (ngn-agent/setup-ngn-agent.sh) for recreating all ngn-agent Hermes configuration on a fresh macOS machine — argument parsing, interactive secrets, config YAML/env/hindsight generation, all 5 skills + 2 scripts embedded, 3 cron jobs registered, gateway restart offer** + +## Performance + +- **Duration:** 4 min +- **Started:** 2026-06-15 23:26 +08 +- **Completed:** 2026-06-15 23:30 +08 +- **Tasks:** 3 +- **Files modified:** 1 (1340 lines added) + +## Accomplishments + +- Created `setup-ngn-agent.sh` (1340 lines) — fully self-contained, no external file dependencies +- Argument parsing with getopts for 9 configurable parameters (SSH keys, repo paths, timezone, docker image) +- Prerequisite validation: Hermes CLI on PATH, Docker running, SSH key file existence, repo path existence +- Interactive masked secret prompts for JIRA_API_TOKEN, JIRA_EMAIL, TELEGRAM_BOT_TOKEN, OPENROUTER_API_KEY (T-09-05) +- Config generation via hermes config set (scalars) + Python yaml (arrays) + sed fallback +- .env generation with chmod 600 permissions (T-09-06) +- hindsight/config.json with local_embedded mode, qwen/qwen3.5-9b model, hybrid memory +- All 5 skills (jira, aws-diagnostics, confluence, bitbucket, session) + 2 reference files embedded as heredocs +- Both scripts (session-init.sh, archive-stale-sessions.sh) embedded as heredocs with executable permission +- 3 cron jobs registered with proper schedules and delivery methods +- Config.yaml backup before modification (T-09-07) +- Gateway restart offer at completion +- Non-interactive mode (-y) for automated provisioning + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Create setup script skeleton — args, prereqs, and interactive prompts** - `2de51b1` (feat) +2. **Task 2: Implement config generation — config.yaml, .env, hindsight/config.json** - `9da9728` (feat) +3. **Task 3: Implement file/cron setup — scripts, skills, cron registration, gateway restart** - `5a8c183` (feat) + +## Files Created/Modified + +- `ngn-agent/setup-ngn-agent.sh` — 1340-line standalone portable setup script (created) + +## Decisions Made + +- **Embedded heredocs over base64**: All skill files, scripts, and reference files are embedded using heredocs with quoted delimiters (`'EOF'`) — prevents variable expansion at script generation time, keeps content human-readable without encoding overhead. Each file is a separate bash function for modularity and independent testing. + +- **Hybrid config.yaml generation**: `hermes config set` for scalar keys (docker_image, memory.provider, timezone, etc.) + Python yaml module for arrays (docker_volumes, shell_init_files, docker_forward_env). Python's yaml.safe_load → modify → yaml.dump preserves unknown keys and maintains proper YAML formatting. Fallback to sed-based injection if the `yaml` Python module is unavailable. + +- **Best-effort error handling**: The script uses `set -euo pipefail` for strict mode, but non-critical steps like cron registration are wrapped with `|| echo "⚠ ..."` — allowing the script to continue if a cron job already exists or if the Hermes CLI returns a non-fatal error. + +- **Prompt_secret with env-var skip**: Secret prompts check if the environment variable is already set before prompting (supports pre-exported secrets or non-interactive mode via `-y` flag). + +- **Cron job registration order**: Daily report first (most critical), then weekly summary, then weekly archive. Archive runs 5 minutes after summary (20:05 vs 20:00) per Phase 8 pattern to prevent race conditions. + +## Deviations from Plan + +None — plan executed exactly as written. + +## Issues Encountered + +None. All three tasks completed cleanly with syntax validation passing (`bash -n`). + +## User Setup Required + +**External services require manual configuration.** See [09-USER-SETUP.md](./09-USER-SETUP.md) for: +- Hermes CLI v0.16+ installation (pre-requisite) +- JIRA_API_TOKEN from https://id.atlassian.com/manage/api-tokens +- TELEGRAM_BOT_TOKEN from https://t.me/BotFather +- OPENROUTER_API_KEY from https://openrouter.ai/keys + +The setup script handles interactive prompting for all 4 secrets. + +## Threat Flags + +None — all threat mitigations from the plan's threat model are satisfied: +- T-09-05 (Information Disclosure — secret exposure in terminal history): Mitigated — `read -s` for all secret prompts with masked input. +- T-09-06 (Information Disclosure — .env world-readable secrets): Mitigated — `chmod 600` on .env immediately after writing. +- T-09-07 (Tampering — config file corruption): Mitigated — backup existing config.yaml to `.bak.` before modification. +- T-09-08 (Information Disclosure — terminal scrollback): Accepted — users responsible for terminal security. +- T-09-09 (Tampering — cron prompt injection): Accepted — prompts embedded in setup script, not user-controllable. + +## Next Phase Readiness + +- Phase 9 Plan 1 (Docker custom image) complete, Plan 2 (setup script) complete +- Phase 9 fully complete — both Dockerfile + build script and portable setup script artifacts ready +- User can run `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) +- Ready for next phase (v1.1 milestone completion, validation, or v1.2 planning) + +## Self-Check: PASSED + +| Check | Result | +|-------|--------| +| File exists | ✓ setup-ngn-agent.sh (1340 lines) | +| File executable | ✓ | +| Syntax validation (`bash -n`) | ✓ | +| Task 1 commit (2de51b1) | ✓ | +| Task 2 commit (9da9728) | ✓ | +| Task 3 commit (5a8c183) | ✓ | +| Script ≥ 300 lines | ✓ (1340 lines) | +| `hermes cron create` count = 3 | ✓ | +| Function names ≥ 8 matched | ✓ (14 matches) | +| SUMMARY.md exists | ✓ | + +--- + +*Phase: 09-tooling-portable-setup* +*Completed: 2026-06-15*