Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ansible/group_vars/all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ factory_omp_sidebar_extension: "{{ factory_cfg.home }}/.omp/agent/extensions/cod
factory_omp_status_icons_extension: "{{ factory_cfg.home }}/.omp/agent/extensions/aa-mode-icons.ts"
# Blocks pkill/killall/kill-by-pgrep in every omp session (docs/omp.md).
factory_omp_no_pattern_kill_extension: "{{ factory_cfg.home }}/.omp/agent/extensions/fm-no-pattern-kill.ts"
# Herdr's own omp state extension; `herdr integration install omp` writes it (docs/herdr.md).
factory_herdr_omp_integration: "{{ factory_cfg.home }}/.omp/agent/extensions/herdr-omp-agent-state.ts"
# omp as the no-mistakes pi agent, and the omp overlay only daemon-spawned omp
# loads (docs/omp.md#no-mistakes-pipeline-agent).
factory_omp_as_pi_dir: "{{ factory_cfg.home }}/.no-mistakes/omp-as-pi"
Expand Down
39 changes: 39 additions & 0 deletions ansible/tasks/herdr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,42 @@
become_user: "{{ factory_cfg.user }}"
environment: "{{ factory_user_systemd_env }}"
when: factory_manage_services | bool

# Herdr's own omp extension reports each omp pane's state (working, blocked,
# idle) to the sidebar; without it every omp agent shows as idle. herdr refuses
# to install it until the omp extensions directory exists. Every apply runs the
# install so a herdr upgrade refreshes it; the checksum comparison reports a
# change only when herdr rewrote the file.
- name: Install Herdr's omp state integration
when:
- factory_cfg.profiles.agents | bool
- not ansible_check_mode
block:
- name: Ensure the omp extensions directory
ansible.builtin.file:
path: "{{ factory_herdr_omp_integration | dirname }}"
state: directory
owner: "{{ factory_cfg.user }}"
group: "{{ factory_group }}"
mode: "0755"
become: true

- name: Checksum the Herdr omp integration before install
ansible.builtin.stat:
path: "{{ factory_herdr_omp_integration }}"
become: true
register: factory_herdr_omp_before

- name: Run herdr integration install omp
ansible.builtin.command:
argv: ["{{ factory_herdr_bin }}", integration, install, omp]
changed_when: false

- name: Checksum the Herdr omp integration after install
ansible.builtin.stat:
path: "{{ factory_herdr_omp_integration }}"
become: true
register: factory_herdr_omp_after
changed_when: >-
factory_herdr_omp_after.stat.checksum | default('')
!= factory_herdr_omp_before.stat.checksum | default('')
22 changes: 21 additions & 1 deletion ansible/tasks/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# changed_when: false, so verification can never make a second apply report a
# change. Individual task files already assert their own outputs; this file
# checks the wiring that crosses them - the Herdr and omp releases this run
# resolved, the static enablement symlinks, the managed shell environment, the pruner runtime, the
# resolved, Herdr's omp integration, the static enablement symlinks, the managed shell environment, the pruner runtime, the
# Firstmate revision this run resolved and the loopback-only desktop listeners.
#
# A check-mode run cannot observe files it did not create, so verification
Expand Down Expand Up @@ -225,6 +225,26 @@
check_mode: false
when: factory_cfg.profiles.agents | bool

# Without Herdr's omp integration every omp pane shows as idle in the sidebar.
- name: Read the Herdr integration status
ansible.builtin.command:
argv: ["{{ factory_herdr_bin }}", integration, status]
register: factory_verify_herdr_integrations
changed_when: false
check_mode: false
when: factory_cfg.profiles.agents | bool

- name: Assert Herdr's omp integration is current
ansible.builtin.assert:
that:
- "factory_verify_herdr_integrations.stdout is search('(?m)^omp: current')"
fail_msg: >-
`herdr integration status` does not report `omp: current`, so Herdr
shows every omp agent as idle:
{{ factory_verify_herdr_integrations.stdout_lines | select('match', 'omp:') | join(' ') }}
quiet: true
when: factory_cfg.profiles.agents | bool

# --- managed shell environment -----------------------------------------

- name: Read the account profile
Expand Down
2 changes: 1 addition & 1 deletion docs/agent-host-move.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Services that hold state other hosts share, such as a model relay, a monitoring
| systemd user units | Apply writes its own. After apply, list what the new host lacks: `comm -23 <(ssh <old host> 'ls ~/.config/systemd/user' \| sort) <(ls ~/.config/systemd/user \| sort)`. Move only agent-side units from that list. Never move units for services that stay on the old host, and never copy a unit or drop-in that holds an inline credential ([Never export](security.md#never-export)). |
| User crontab | Crontab entries and the scripts they run often name a home's path. After every sync of a home's `data/` to a host where its path differs, run `sed -i 's#<old path>#<new path>#g'` on those scripts there. [Cutover](#cutover) comments the entries out on the old host at step 1, adds them with the new path on the new host at step 6, and deletes them on the old host at step 8. |
| Hand-installed tools in `~/.local/bin` | After apply, list what the new host lacks: `comm -23 <(ssh <old host> 'ls ~/.local/bin' \| sort) <(ls ~/.local/bin \| sort)`. Reinstall each agent-side tool from its source and skip backups. |
| omp rules, extensions and custom models (`~/.omp/agent/rules/`, `extensions/`, `models.yml`) | `rsync -a` them from the old host when they hold no credentials. Then run `herdr integration install omp`, which rewrites Herdr's own extension for the new host's herdr. |
| omp rules, extensions and custom models (`~/.omp/agent/rules/`, `extensions/`, `models.yml`) | `rsync -a --exclude herdr-omp-agent-state.ts` them from the old host when they hold no credentials. Apply already installed Herdr's own omp extension for the new host's herdr ([Pane state](herdr.md#pane-state)). |
| omp keys and MCP credentials (`~/.omp/agent/*.key`, `mcp.json`) and each home's `state/secrets/` | Never copy them ([Never export](security.md#never-export)). Recreate each on the new host by hand, mode `600`, entering the keys yourself. |

```bash
Expand Down
6 changes: 6 additions & 0 deletions docs/herdr.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ herdr agent get <pane_id>

The result carries `terminal_title` and `tokens.who`, `tokens.pr`, and so on.

### Pane state

Herdr learns whether an omp agent is working, blocked or idle from its own omp extension, `~/.omp/agent/extensions/herdr-omp-agent-state.ts`. With the `agents` profile on, every `./factory apply` runs `herdr integration install omp` with the herdr it installed, so a herdr upgrade refreshes the extension; apply reports a change only when herdr rewrote the file, and verification fails unless `herdr integration status` reports `omp: current`. Without the extension Herdr shows every omp agent as idle. Apply installs no integration for other agents.

## Override the layouts or turn parts off

Set these keys under `factory.herdr` in `.local/host.yml`, then run `./factory apply`:
Expand Down Expand Up @@ -210,6 +214,8 @@ ssh <host> cat .local/bin/herdr-sidebar-to-client.py | python3 - <host>

It copies the host's `sidebar_width`, `sidebar_max_width`, `[ui.sidebar.agents]`, `[ui.sidebar.spaces]` and `[theme.custom] sidebar_bg` into `~/.config/herdr/config.toml` on the viewing machine, or into the path given as a second argument, and leaves every other setting there as is. It writes a timestamped `.bak-sidebar-` copy of that file first. Run it again after the host's layout changes.

Pane state (the sidebar dots) is reported on the host by the omp integration `./factory apply` installs, so the host needs nothing more. A machine that views the host with `herdr --remote` should run the same Herdr release as the host: the host runs the latest, so on the viewing machine run `herdr update`, then compare `herdr --version` with the host's.

## Known limits

- Agents without the extension, including non-omp agents, show only their dot on line 1: nothing reports their `who` token.
Expand Down