v0.3 scope reduction: drop --hermes flag and Project.hermes field
v0.3 scope reduction: drop --hermes flag and Project.hermes field The --hermes/--no-hermes/--purge-hermes flag plumbing and per-container hermes provisioning are removed. Smoke testing exposed fundamental problems with the bind-mount-the-host-runtime architecture: hermes' Python venv pins to a uv-vendored host-only path, and uid-mapping for file binds doesn't generalize. v0.4 will revisit via pre-built incus images. What v0.3 still ships: setup wizard, llm-share profile (ollama wiring), schema-2 migration, hermes module helpers as a library for v0.4.
Author:
Chris Tusa <chris.tusa@leafscale.com>
Date:
May 08, 2026 13:32
Node:
1bacbaae1c2fcf5cbff002855d3a0b0b86ae2276
Branch:
default
Tags:
v0.3.0
Changed files:
Diff
diff -r a8ec2564f3fe -r 1bacbaae1c2f README.md --- a/README.md Fri May 08 02:41:29 2026 +0000 +++ b/README.md Fri May 08 13:32:26 2026 +0000 @@ -42,11 +42,11 @@ | Subcommand | Description | |---|---| -| `new <name> [--repo <dirname>] [--image <image>]` | Launch an Incus container and bind a local repo into it. | +| `new <name> [--repo <dirname>] [--image <image>]` | Launch an Incus container and bind a local repo into it. (Use `repoman setup --with-llm` first if you want LLM stack wiring.) | | `sync [name] [--no-delete] [--dry-run]` | Mirror local repos to NFS backup via rsync. | | `list` | Print a table of all registered projects (read-only). | | `status [name]` | Show project state from registry + live incus query. | -| `remove <name> --yes [--keep-incus]` | Delete the incus container and registry entry. --yes required. | +| `remove <name> --yes [--keep-incus]` | Delete the incus container and registry entry. `--yes` required. | | `shell <name> [--cwd <path>]` | Open a bash login shell inside the project's container (replaces repoman). | | `--help` / `-h` / `help` | Show usage and subcommand list. | | `--version` / `-V` | Print version string. | @@ -72,18 +72,8 @@ container environment. - Registry default `[defaults].llm.enabled = true`. -Per-project hermes data directories (opt-in): - - repoman new myapp --hermes - -This selectively seeds your host's `~/.hermes/` (credentials, config, skills, hooks, -runtime symlinks) into `~/.local/share/repoman/hermes/myapp/` and bind-mounts that -into the container as `~/.hermes`. Per-container sessions, memories, and SQLite state -stay isolated — never share a hermes data dir between two running instances. - -To delete the data dir alongside the container: - - repoman remove myapp --purge-hermes +Containers created after `--with-llm` setup automatically inherit the `llm-share` +profile and can reach the host's ollama daemon at the configured LAN address. ## Smoke test (requires Incus + NFS) diff -r a8ec2564f3fe -r 1bacbaae1c2f docs/superpowers/plans/2026-05-06-repoman-v0.3-llm-and-setup.md --- a/docs/superpowers/plans/2026-05-06-repoman-v0.3-llm-and-setup.md Fri May 08 02:41:29 2026 +0000 +++ b/docs/superpowers/plans/2026-05-06-repoman-v0.3-llm-and-setup.md Fri May 08 13:32:26 2026 +0000 @@ -1,5 +1,18 @@ # repoman v0.3 — Setup wizard + LLM stack Implementation Plan +## Scope reduction (2026-05-08) + +The `--hermes`/`--no-hermes`/`--purge-hermes` flag-based provisioning was **removed +during smoke testing** and does not ship in v0.3. Smoke testing exposed fundamental +problems with the bind-mount-the-host-runtime architecture: hermes' Python venv pins +to a uv-vendored host-only path, and uid-mapping for file binds does not generalize. +v0.4 will revisit via pre-built incus images. + +v0.3 ships: setup wizard, llm-share profile (ollama wiring), schema-2 migration, +hermes module helpers as a library for v0.4. + +--- + > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Ship `repoman setup` (idempotent host-bootstrap wizard) plus per-container hermes data-dir provisioning (`repoman new --hermes`, `repoman remove --purge-hermes`), with a repoman-managed `llm-share` Incus profile that wires containers to the host's ollama daemon over LAN. diff -r a8ec2564f3fe -r 1bacbaae1c2f docs/superpowers/specs/2026-05-06-repoman-v0.3-llm-and-setup.md --- a/docs/superpowers/specs/2026-05-06-repoman-v0.3-llm-and-setup.md Fri May 08 02:41:29 2026 +0000 +++ b/docs/superpowers/specs/2026-05-06-repoman-v0.3-llm-and-setup.md Fri May 08 13:32:26 2026 +0000 @@ -1,5 +1,24 @@ # repoman v0.3 — Setup wizard + LLM stack integration +## Scope reduction (2026-05-08) + +The `--hermes`/`--no-hermes`/`--purge-hermes` flag-based provisioning described in +this spec was **removed during smoke testing** and will not ship in v0.3. + +Root cause: the bind-mount-the-host-runtime architecture does not survive Python venv +portability constraints. Hermes' venv pins to a uv-vendored host-only path; bind- +mounting it into a container where that path doesn't exist fails at import time. Uid +mapping for the bind also does not generalize cleanly. Copying the venv breaks shebang +paths. + +v0.4 will revisit per-container hermes provisioning via pre-built incus images that +embed a self-contained hermes install rather than sharing the host runtime. + +**v0.3 still ships:** `repoman setup` wizard, `llm-share` profile (ollama client +wiring), schema-2 migration, and the `hermes` module helpers as a library for v0.4. + +--- + **Status:** v0.3 design, under review **Date:** 2026-05-06 **Implementation language:** reef-lang 0.5.20 (no new stdlib requirements vs v0.2) diff -r a8ec2564f3fe -r 1bacbaae1c2f src/cli.reef --- a/src/cli.reef Fri May 08 02:41:29 2026 +0000 +++ b/src/cli.reef Fri May 08 13:32:26 2026 +0000 @@ -11,13 +11,11 @@ import sys.args as args import sys.process as p import config -import hermes import incus import setup import sync import paths import log -import io.dir as iodir export fn cmd_new(argv: [string]): int @@ -39,9 +37,6 @@ let _r2 = flag.string_flag(parser, "image", '\0', "", "container image (overrides default)") let _v = flag.bool_flag(parser, "verbose", 'v', false, "show subprocess output (incus probes)") let _q = flag.bool_flag(parser, "quiet", 'q', false, "force quiet mode even if config sets verbose") - let _f3 = flag.bool_flag(parser, "hermes", '\0', false, "provision a per-container hermes data dir (overrides default)") - let _f4 = flag.bool_flag(parser, "no-hermes", '\0', false, "skip per-container hermes data dir (overrides default)") - if not flag.parse(parser) console.printErr("repoman: error: " + flag.error(parser)) return 2 @@ -92,24 +87,6 @@ verbose = false end if - let cli_hermes: bool = flag.get_bool(parser, "hermes") - let cli_no_hermes: bool = flag.get_bool(parser, "no-hermes") - if cli_hermes and cli_no_hermes - console.printErr("repoman: error: --hermes and --no-hermes are mutually exclusive") - return 2 - end if - mut want_hermes: bool = reg.defaults.llm.hermes_default - if cli_hermes - want_hermes = true - end if - if cli_no_hermes - want_hermes = false - end if - if want_hermes and not reg.defaults.llm.enabled - console.printErr("repoman: error: --hermes requires LLM stack enabled. Run 'repoman setup --with-llm' first.") - return 3 - end if - // Reject duplicate name let pn: int = reg.projects.length() mut i: int = 0 @@ -219,69 +196,6 @@ return 1 end if - // Seed per-container hermes data dir + add disk device (opt-in) - if want_hermes - let dest: string = hermes.state_dir_for(home, name) - if iodir.dir_exists(dest) - log.write("repoman: error: hermes data dir already exists at " + dest) - log.write("hint: incus delete --project " + reg.defaults.incus_project + " " + name + " ; rm -rf " + dest) - return 4 - end if - let source: string = paths.join(home, ".hermes") - log.write("==> hermes seed " + source + " -> " + dest) - let sr = hermes.seed_data_dir(source, dest, reg.defaults.llm.hermes_seed) - if rg.is_err(sr) - log.write("repoman: error: " + rg.unwrap_err(sr)) - return 1 - end if - let user: string = env.get_env_or("USER", "") - let in_path: string = "/home/" + user + "/.hermes" - log.write("==> incus device add " + name + " hermes-state " + dest + " -> " + in_path) - let dr2 = incus.device_add_disk_opts(reg.defaults.incus_project, name, "hermes-state", dest, in_path, ["shift=true"]) - if rg.is_err(dr2) - log.write("repoman: error: " + rg.unwrap_err(dr2)) - log.write("hint: incus delete --project " + reg.defaults.incus_project + " " + name + " ; rm -rf " + dest) - return 1 - end if - // Bind the host's runtime dirs into the container so the Python venv - // and other runtime symlinks resolve through to the same host paths - // they were created against. (Copying breaks venv shebangs.) - let host_hermes: string = paths.join(home, ".hermes") - let host_hermes_agent: string = paths.join(host_hermes, "hermes-agent") - let host_hermes_node: string = paths.join(host_hermes, "node") - let host_hermes_bin: string = paths.join(host_hermes, "bin") - let in_hermes_agent: string = paths.join(in_path, "hermes-agent") - let in_hermes_node: string = paths.join(in_path, "node") - let in_hermes_bin: string = paths.join(in_path, "bin") - log.write("==> incus device add " + name + " hermes-agent (readonly bind)") - let dr3 = incus.device_add_disk_opts(reg.defaults.incus_project, name, "hermes-agent", host_hermes_agent, in_hermes_agent, ["shift=true", "readonly=true"]) - if rg.is_err(dr3) - log.write("repoman: error: " + rg.unwrap_err(dr3)) - log.write("hint: incus delete --project " + reg.defaults.incus_project + " " + name + " ; rm -rf " + dest) - return 1 - end if - log.write("==> incus device add " + name + " hermes-node (readonly bind)") - let dr4 = incus.device_add_disk_opts(reg.defaults.incus_project, name, "hermes-node", host_hermes_node, in_hermes_node, ["shift=true", "readonly=true"]) - if rg.is_err(dr4) - log.write("repoman: error: " + rg.unwrap_err(dr4)) - log.write("hint: incus delete --project " + reg.defaults.incus_project + " " + name + " ; rm -rf " + dest) - return 1 - end if - log.write("==> incus device add " + name + " hermes-runtime-bin (readonly bind)") - let dr5 = incus.device_add_disk_opts(reg.defaults.incus_project, name, "hermes-runtime-bin", host_hermes_bin, in_hermes_bin, ["shift=true", "readonly=true"]) - if rg.is_err(dr5) - log.write("repoman: error: " + rg.unwrap_err(dr5)) - log.write("hint: incus delete --project " + reg.defaults.incus_project + " " + name + " ; rm -rf " + dest) - return 1 - end if - // Restart again so the new devices are mounted - let rr2 = incus.restart(reg.defaults.incus_project, name) - if rg.is_err(rr2) - log.write("repoman: error: " + rg.unwrap_err(rr2)) - return 1 - end if - end if - // Build new project entry and write registry let now: string = time.time_format_iso(time.time_now()) let new_p: config.Project = config.Project { @@ -291,8 +205,7 @@ profiles: eff.profiles, created: now, last_sync: "", - backup: true, - hermes: want_hermes + backup: true } let reg2_r = config.add_project(reg, new_p) if rg.is_err(reg2_r) @@ -527,8 +440,7 @@ + str.pad_right("IMAGE", 33, ' ') + str.pad_right("CREATED", 21, ' ') + str.pad_right("LAST_SYNC", 21, ' ') - + str.pad_right("BACKUP", 8, ' ') - + "HERMES" + + "BACKUP" ) mut i: int = 0 @@ -538,18 +450,13 @@ if p.backup backup_str = "yes" end if - mut hermes_str: string = "no" - if p.hermes - hermes_str = "yes" - end if println( str.pad_right(p.name, 12, ' ') + str.pad_right(p.repo, 18, ' ') + str.pad_right(p.image, 33, ' ') + str.pad_right(p.created, 21, ' ') + str.pad_right(p.last_sync, 21, ' ') - + str.pad_right(backup_str, 8, ' ') - + hermes_str + + backup_str ) i = i + 1 end while @@ -625,16 +532,6 @@ end if println("backup: " + backup_str) println("state: " + state) - mut hstr: string = "no" - if proj.hermes - hstr = "yes" - end if - println("hermes: " + hstr) - if proj.hermes - let home: string = env.get_env_or("HOME", "") - let dest: string = hermes.state_dir_for(home, name) - println(" data dir: " + dest) - end if return 0 end cmd_status_one @@ -651,8 +548,7 @@ + str.pad_right("STATE", 10, ' ') + str.pad_right("CREATED", 21, ' ') + str.pad_right("LAST_SYNC", 21, ' ') - + str.pad_right("BACKUP", 8, ' ') - + "HERMES" + + "BACKUP" ) mut i: int = 0 @@ -667,17 +563,12 @@ if p.backup backup_str = "yes" end if - mut hermes_str: string = "no" - if p.hermes - hermes_str = "yes" - end if println( str.pad_right(p.name, 12, ' ') + str.pad_right(state, 10, ' ') + str.pad_right(p.created, 21, ' ') + str.pad_right(p.last_sync, 21, ' ') - + str.pad_right(backup_str, 8, ' ') - + hermes_str + + backup_str ) i = i + 1 end while @@ -690,7 +581,6 @@ flag.description(parser, "Remove a project: delete its container and registry entry") let _y = flag.bool_flag(parser, "yes", 'y', false, "confirm removal (required)") let _k = flag.bool_flag(parser, "keep-incus", '\0', false, "leave the incus container; only remove from registry") - let _fph = flag.bool_flag(parser, "purge-hermes", '\0', false, "also delete the per-container hermes data dir") if not flag.parse(parser) console.printErr("repoman: error: " + flag.error(parser)) @@ -775,17 +665,6 @@ return 1 end if - let purge: bool = flag.get_bool(parser, "purge-hermes") - if purge - let dest: string = hermes.state_dir_for(home, name) - log.write("==> purge hermes data dir: " + dest) - let pr = hermes.purge_data_dir(dest) - if rg.is_err(pr) - log.write("repoman: warning: " + rg.unwrap_err(pr)) - // Don't fail the overall remove on purge failure — container is gone. - end if - end if - log.write("==> removed '" + name + "'") return 0 end cmd_remove @@ -888,9 +767,8 @@ console.printErr(" setup [--non-interactive] [--with-llm] [--without-llm]") console.printErr(" First-time host bootstrap: incus project, profiles, registry.") console.printErr("") - console.printErr(" new <name> [--repo <dirname>] [--image <image>] [--hermes | --no-hermes]") + console.printErr(" new <name> [--repo <dirname>] [--image <image>]") console.printErr(" Launch a container in the 'repoman' Incus project; bind ~/repos/<dirname>.") - console.printErr(" --hermes seeds a per-container hermes data dir (requires LLM stack).") console.printErr("") console.printErr(" sync [name] [--no-delete] [--dry-run]") console.printErr(" Mirror local repos to NFS backup (rsync --delete by default).") @@ -901,9 +779,8 @@ console.printErr(" status [name]") console.printErr(" Show project state from registry + live incus query.") console.printErr("") - console.printErr(" remove <name> --yes [--keep-incus] [--purge-hermes]") + console.printErr(" remove <name> --yes [--keep-incus]") console.printErr(" Delete the incus container and registry entry. --yes required.") - console.printErr(" --purge-hermes also deletes the per-container hermes data dir.") console.printErr("") console.printErr(" shell <name> [--cwd <path>]") console.printErr(" Open a bash login shell inside the project's container.") diff -r a8ec2564f3fe -r 1bacbaae1c2f src/config.reef --- a/src/config.reef Fri May 08 02:41:29 2026 +0000 +++ b/src/config.reef Fri May 08 13:32:26 2026 +0000 @@ -55,7 +55,6 @@ created: string last_sync: string backup: bool - hermes: bool end Project type Mount = struct @@ -188,8 +187,7 @@ profiles: parse_string_array(toml.toml_array_get(doc.keys, doc.values, doc.count, "project", i, "profiles")), created: toml.toml_array_get(doc.keys, doc.values, doc.count, "project", i, "created"), last_sync: toml.toml_array_get(doc.keys, doc.values, doc.count, "project", i, "last_sync"), - backup: toml.toml_array_get(doc.keys, doc.values, doc.count, "project", i, "backup") != "false", - hermes: toml.toml_array_get(doc.keys, doc.values, doc.count, "project", i, "hermes") == "true" + backup: toml.toml_array_get(doc.keys, doc.values, doc.count, "project", i, "backup") != "false" } projects[i] = p i = i + 1 @@ -237,7 +235,6 @@ toml.toml_set_string(b, "created", p.created) toml.toml_set_string(b, "last_sync", p.last_sync) toml.toml_set_bool(b, "backup", p.backup) - toml.toml_set_bool(b, "hermes", p.hermes) i = i + 1 end while @@ -393,8 +390,7 @@ new_projects[k] = Project { name: old.name, repo: old.repo, image: old.image, profiles: old.profiles, created: old.created, - last_sync: ts, backup: old.backup, - hermes: old.hermes + last_sync: ts, backup: old.backup } else new_projects[k] = reg.projects[k] diff -r a8ec2564f3fe -r 1bacbaae1c2f src/setup.reef --- a/src/setup.reef Fri May 08 02:41:29 2026 +0000 +++ b/src/setup.reef Fri May 08 13:32:26 2026 +0000 @@ -19,7 +19,7 @@ type Environment fn detect_environment(home_dir: string): Environment fn detect_host_lan_ip(): string - fn render_llm_share_template(host_lan_ip: string, user: string, hermes_binary: string): string + fn render_llm_share_template(host_lan_ip: string, user: string): string fn template_contains_placeholder(s: string): bool type Stage fn plan_stages(env: Environment, with_llm: bool): [Stage] @@ -149,11 +149,11 @@ return "" end detect_host_lan_ip -fn render_llm_share_template(host_lan_ip: string, user: string, hermes_binary: string): string +fn render_llm_share_template(host_lan_ip: string, user: string): string let base: string = "name: llm-share\n" + "description: |\n" + - " Local LLM client tools (ollama client + hermes runtime) and host-daemon wiring.\n" + + " Local LLM client tools (ollama client) and host-daemon wiring.\n" + " Created by repoman setup; do not hand-edit (changes will be overwritten).\n" + "config:\n" + " environment.OLLAMA_HOST: \"http://{HOST_LAN_IP}:11434\"\n" + @@ -164,17 +164,6 @@ " path: /usr/local/bin/ollama\n" + " readonly: \"true\"\n" - mut hermes_segment: string = "" - if str.length(hermes_binary) > 0 - hermes_segment = - " hermes-bin:\n" + - " type: disk\n" + - " source: " + hermes_binary + "\n" + - " path: /usr/local/bin/hermes\n" + - " readonly: \"true\"\n" + - " shift: \"true\"\n" - end if - let tail: string = " ollama-state:\n" + " type: disk\n" + @@ -182,7 +171,7 @@ " path: /home/{USER}/.ollama\n" + " shift: \"true\"\n" - let combined: string = base + hermes_segment + tail + let combined: string = base + tail let s1: string = str.replace(combined, "{HOST_LAN_IP}", host_lan_ip) let s2: string = str.replace(s1, "{USER}", user) return s2 @@ -273,7 +262,7 @@ "Add OLLAMA_HOST=" + env.host_lan_ip + ":11434 to your systemd unit and restart ollama." ) end if - let yaml: string = render_llm_share_template(env.host_lan_ip, env.user, env.hermes_binary) + let yaml: string = render_llm_share_template(env.host_lan_ip, env.user) let r = incus.profile_create_or_edit("repoman", "llm-share", yaml) if rg.is_err(r) return @Result[config.Registry, string].Err(rg.unwrap_err(r)) @@ -430,9 +419,6 @@ println("setup complete.") println("") println(" next: repoman new <name>") - if reg.defaults.llm.enabled - println(" repoman new <name> --hermes") - end if println(" repoman list") return 0 end cmd_setup diff -r a8ec2564f3fe -r 1bacbaae1c2f tests/test_config_llm_parse.reef --- a/tests/test_config_llm_parse.reef Fri May 08 02:41:29 2026 +0000 +++ b/tests/test_config_llm_parse.reef Fri May 08 13:32:26 2026 +0000 @@ -6,7 +6,7 @@ let runner = new framework.TestRunner() // Schema 2 with [defaults.llm] populated - let toml: string = "[repoman]\nschema = 2\noutput = \"quiet\"\n\n[defaults]\nrepos_root = \"~/repos\"\nbackup_root = \"/nfs/repos\"\nlogdir = \"~/.local/state/repoman\"\nincus_project = \"repoman\"\ndefault_image = \"images:ubuntu/26.04/cloud\"\nprofiles = [\"default\", \"claude-share\", \"llm-share\"]\n\n[defaults.llm]\nenabled = true\nhermes_default = false\nollama_url = \"http://192.168.168.42:11434\"\nhermes_seed = [\".env\", \"config.yaml\", \"skills/\"]\n\n[[project]]\nname = \"isurus\"\nrepo = \"isurus\"\nimage = \"images:ubuntu/26.04/cloud\"\nprofiles = [\"default\", \"claude-share\", \"llm-share\"]\ncreated = \"2026-05-06T00:00:00Z\"\nlast_sync = \"\"\nbackup = true\nhermes = true\n" + let toml: string = "[repoman]\nschema = 2\noutput = \"quiet\"\n\n[defaults]\nrepos_root = \"~/repos\"\nbackup_root = \"/nfs/repos\"\nlogdir = \"~/.local/state/repoman\"\nincus_project = \"repoman\"\ndefault_image = \"images:ubuntu/26.04/cloud\"\nprofiles = [\"default\", \"claude-share\", \"llm-share\"]\n\n[defaults.llm]\nenabled = true\nhermes_default = false\nollama_url = \"http://192.168.168.42:11434\"\nhermes_seed = [\".env\", \"config.yaml\", \"skills/\"]\n\n[[project]]\nname = \"isurus\"\nrepo = \"isurus\"\nimage = \"images:ubuntu/26.04/cloud\"\nprofiles = [\"default\", \"claude-share\", \"llm-share\"]\ncreated = \"2026-05-06T00:00:00Z\"\nlast_sync = \"\"\nbackup = true\n" let r = config.parse_registry(toml) runner.assert_eq_bool(rg.is_ok(r), true, "schema 2 parses ok") @@ -18,7 +18,6 @@ runner.assert_eq_string(reg.defaults.llm.ollama_url, "http://192.168.168.42:11434", "llm.ollama_url") runner.assert_eq_int(reg.defaults.llm.hermes_seed.length(), 3, "llm.hermes_seed has 3 entries") runner.assert_eq_int(reg.projects.length(), 1, "one project") - runner.assert_eq_bool(reg.projects[0].hermes, true, "project.hermes = true") end if // Schema 2 with [defaults.llm] missing — should default to disabled diff -r a8ec2564f3fe -r 1bacbaae1c2f tests/test_config_llm_serialize.reef --- a/tests/test_config_llm_serialize.reef Fri May 08 02:41:29 2026 +0000 +++ b/tests/test_config_llm_serialize.reef Fri May 08 13:32:26 2026 +0000 @@ -28,8 +28,7 @@ profiles: ["default", "claude-share", "llm-share"], created: "2026-05-06T00:00:00Z", last_sync: "", - backup: true, - hermes: true + backup: true } let reg = config.Registry { schema: 2, @@ -47,7 +46,6 @@ runner.assert_contains_string(s, "ollama_url = \"http://192.168.168.42:11434\"", "writes llm.ollama_url") runner.assert_contains_string(s, "hermes_seed = [", "writes llm.hermes_seed array") runner.assert_contains_string(s, "\".env\"", "hermes_seed contains .env") - runner.assert_contains_string(s, "hermes = true", "writes project.hermes") // Round-trip check let r2 = config.parse_registry(s) @@ -57,7 +55,6 @@ runner.assert_eq_int(reg2.schema, 2, "round-trip schema") runner.assert_eq_bool(reg2.defaults.llm.enabled, true, "round-trip llm.enabled") runner.assert_eq_int(reg2.defaults.llm.hermes_seed.length(), 3, "round-trip hermes_seed length") - runner.assert_eq_bool(reg2.projects[0].hermes, true, "round-trip project.hermes") end if runner.report() diff -r a8ec2564f3fe -r 1bacbaae1c2f tests/test_config_migrate_v1.reef --- a/tests/test_config_migrate_v1.reef Fri May 08 02:41:29 2026 +0000 +++ b/tests/test_config_migrate_v1.reef Fri May 08 13:32:26 2026 +0000 @@ -27,7 +27,6 @@ runner.assert_eq_bool(reg.defaults.llm.enabled, false, "migrated llm.enabled = false") runner.assert_eq_int(reg.defaults.llm.hermes_seed.length(), 0, "migrated hermes_seed empty") runner.assert_eq_int(reg.projects.length(), 1, "project preserved") - runner.assert_eq_bool(reg.projects[0].hermes, false, "migrated project.hermes = false") runner.assert_eq_string(reg.projects[0].name, "isurus", "project name preserved") end if diff -r a8ec2564f3fe -r 1bacbaae1c2f tests/test_config_mutate.reef --- a/tests/test_config_mutate.reef Fri May 08 02:41:29 2026 +0000 +++ b/tests/test_config_mutate.reef Fri May 08 13:32:26 2026 +0000 @@ -24,8 +24,7 @@ let p1: config.Project = config.Project { name: "isurus", repo: "isurus", image: "img", - profiles: new [string](0), created: "t", last_sync: "", backup: true, - hermes: false + profiles: new [string](0), created: "t", last_sync: "", backup: true } let r1 = config.add_project(reg0, p1) runner.assert_eq_bool(rg.is_ok(r1), true, "add new project ok") diff -r a8ec2564f3fe -r 1bacbaae1c2f tests/test_config_roundtrip.reef --- a/tests/test_config_roundtrip.reef Fri May 08 02:41:29 2026 +0000 +++ b/tests/test_config_roundtrip.reef Fri May 08 13:32:26 2026 +0000 @@ -27,8 +27,7 @@ profiles: ["default"], created: "2026-04-28T15:00:00Z", last_sync: "", - backup: true, - hermes: false + backup: true } projects[1] = config.Project { name: "tools", @@ -37,8 +36,7 @@ profiles: ["default", "claude-share"], created: "2026-04-29T10:00:00Z", last_sync: "2026-04-29T11:00:00Z", - backup: false, - hermes: false + backup: false } let reg: config.Registry = config.Registry { schema: 1, output: "quiet", defaults: defaults, projects: projects diff -r a8ec2564f3fe -r 1bacbaae1c2f tests/test_config_serialize.reef --- a/tests/test_config_serialize.reef Fri May 08 02:41:29 2026 +0000 +++ b/tests/test_config_serialize.reef Fri May 08 13:32:26 2026 +0000 @@ -26,8 +26,7 @@ profiles: ["default"], created: "2026-04-28T15:00:00Z", last_sync: "", - backup: true, - hermes: false + backup: true } let reg: config.Registry = config.Registry { schema: 1, diff -r a8ec2564f3fe -r 1bacbaae1c2f tests/test_setup_template.reef --- a/tests/test_setup_template.reef Fri May 08 02:41:29 2026 +0000 +++ b/tests/test_setup_template.reef Fri May 08 13:32:26 2026 +0000 @@ -5,7 +5,7 @@ proc main() let runner = new framework.TestRunner() - let yaml = setup.render_llm_share_template("192.168.168.42", "ctusa", "/home/ctusa/.local/bin/hermes") + let yaml = setup.render_llm_share_template("192.168.168.42", "ctusa") runner.assert_contains_string(yaml, "name: llm-share", "name line") runner.assert_contains_string(yaml, "OLLAMA_HOST", "ollama env key") @@ -14,15 +14,9 @@ runner.assert_contains_string(yaml, "/home/ctusa/.ollama", "user path substitution") runner.assert_contains_string(yaml, "shift: \"true\"", "shift opt set") runner.assert_contains_string(yaml, "readonly: \"true\"", "readonly opt on bin") - runner.assert_contains_string(yaml, "hermes-bin:", "hermes-bin device key") - runner.assert_contains_string(yaml, "/home/ctusa/.local/bin/hermes", "hermes launcher source path") // No placeholders should remain runner.assert_eq_bool(false, setup.template_contains_placeholder(yaml), "no {HOST_LAN_IP} or {USER} left") - // When hermes_binary is empty, hermes-bin device must be absent - let yaml_no_hermes = setup.render_llm_share_template("192.168.168.42", "ctusa", "") - runner.assert_eq_bool(false, str.contains(yaml_no_hermes, "hermes-bin:"), "no hermes-bin device when hermes_binary empty") - runner.report() end main