Skip to content

Add lane registry: lanes.sh + herdr-agent.sh wrapper#48

Open
gering wants to merge 3 commits into
mainfrom
task/add-lane-registry
Open

Add lane registry: lanes.sh + herdr-agent.sh wrapper#48
gering wants to merge 3 commits into
mainfrom
task/add-lane-registry

Conversation

@gering

@gering gering commented Jul 24, 2026

Copy link
Copy Markdown
Owner

Summary

  • Wave 1 foundation for the coordinated Manager/Worker orchestration — a derived-live view of the repo's lanes plus a tested wrapper over the herdr agent primitives every later task will call.
  • herdr-agent.sh: the one wrapper over herdr agent list|get|read|wait (robust python3 validate, degrade-not-block exit codes, bounded wait) and the single home of the realpath cwd↔worktree match, exposed as $HERDR_MATCH_PRELUDE.
  • lanes.sh: joins backlog state with herdr liveness, one row per active worktree, keyed by worktree path.
  • Internal foundation only — no skill is wired to it yet, so no version bump (by decision).

Changes

  • herdr-agent.sh (new) — guarded primitive wrappers; read best-effort (no schema), wait injects a default --timeout (no busy loop); exit codes 3=tools-absent / 4=herdr-failed / 5=malformed. Centralizes match_roots/classify_cwd as $HERDR_MATCH_PRELUDE, sourced side-effect-free (BASH_SOURCE == $0 guard).
  • lanes.sh (new) — ws-statusline states --cachedherdr agent list, keyed by worktree_path (never pane/tab ids). TSV/JSON. Degrade tri-state mirrors worktree-tab-state: outside herdr → blank; inside + unreachable/empty/malformed list → fail-closed unverified; populated-but-unmatched → confidently blank.
  • herdr-tab-glyph.sh — now sources herdr-agent.sh and consumes the shared prelude instead of its own inline match. Output verified byte-identical against a live herdr snapshot (it has no unit test). herdr-teardown.sh left as-is: its 1:1 cwd==target lookup is a distinct operation.
  • test_lanes.py / test_herdr_agent.py (new) — join / degraded / unverified / first-wins / exclusion, and the primitives + degrade + bounded wait. Both run under check-structure.py's plugin-test check.
  • Knowledgefeatures/lane-registry.md documents the above.

Readiness

  • ✅ README — no user-facing skill surface changed
  • ✅ Version — no bump (internal foundation, no skill wired; by decision)
  • ➖ Changelog — none in repo
  • ✅ Knowledge — features/lane-registry.md added
  • ✅ Tests — check-structure.py green (incl. 2 new test files)
  • ✅ Lint — shell syntax clean
  • ➖ Build — N/A (markdown/shell)

Test plan

  • python3 scripts/check-structure.py is green
  • lanes.sh inside herdr shows one row per worktree with correct liveness; outside herdr shows blank liveness
  • herdr-tab-glyph.sh refresh still stamps glyphs identically (no regression)

🤖 Generated with Claude Code

gering and others added 3 commits July 25, 2026 14:52
Foundation for the Manager/Worker orchestration (Wave 1) — a derived-live
view of the repo's lanes plus a tested wrapper over the herdr agent
primitives every later task will call.

- herdr-agent.sh: guarded wrappers over `herdr agent list|get|read|wait`
  (robust python3 JSON validate, degrade-not-block exit codes, bounded
  wait). Centralizes the realpath cwd↔worktree match as $HERDR_MATCH_PRELUDE
  (match_roots/classify_cwd), the ONE place both consumers share.
- lanes.sh: joins `ws-statusline.sh states --cached` (backlog state) with
  `herdr agent list` (liveness), one row per active worktree, keyed by
  worktree path. TSV/JSON. Degrades to states-only outside herdr; fail-closed
  `unverified` on an empty/malformed list (mirrors worktree-tab-state).
- herdr-tab-glyph.sh: now sources herdr-agent.sh and consumes the shared
  prelude instead of its own inline match — byte-identical output verified
  against a live snapshot. herdr-teardown.sh left as-is (its 1:1 cwd==target
  lookup is a distinct operation, not the 1:N classify).
- test_lanes.py + test_herdr_agent.py: join / degraded / unverified /
  first-wins / exclusion, and the primitives + degrade + bounded wait.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8crYp6tzRKMiwW63Zt3GG
Add features/lane-registry.md: the herdr-agent.sh wrapper + centralized
$HERDR_MATCH_PRELUDE, lanes.sh's worktree-path-keyed states⨝liveness join,
the worktree-tab-state degrade tri-state, and the env test-seams. Index updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8crYp6tzRKMiwW63Zt3GG
Apply the agreed findings from a local swarm review (11 ✅ + 1 🟨; the 3 ❌ —
a feature version bump, a README inventory line, and a per-subcommand python3
guard — were deliberately left, see the PR discussion).

herdr-agent.sh:
- Bound herdr list/get/read with a wall-clock timeout (_ha_bounded: timeout →
  gtimeout → perl alarm), honouring the header's "never a hang" promise. wait
  stays governed by its own --timeout. (#6)
- ha_wait now detects the --timeout=MS form too, so a caller's explicit bound in
  either spelling is honoured and no duplicate flag is appended. (#7)
- A missing <target> returns usage code 2, not 4 (server-unreachable), so a
  programmer error is not mistaken for a transient outage. (#12)
- set -u is enabled only on the executed-CLI path, never at source time, so
  sourcing for the prelude/helpers no longer mutates the caller's shell. (#13)
- classify_cwd returns the resolved path as a third tuple element, so a caller
  keying by full path reuses it instead of a second realpath. (#14)

lanes.sh:
- Scrub tab/CR/LF from every TSV cell: agent-derived fields are untrusted, and an
  embedded tab/newline would forge columns/rows. Mirrors herdr-tab-glyph. (#1)
- Guard the agent loop against non-dict (null) elements → never crash, always
  exit 0. (#2)
- flush() now calls the shared classify_cwd instead of re-open-coding the task
  rule, so the classification can't drift between the two consumers. (#15)
- Resolve SCRIPT_DIR via BASH_SOURCE (robust to bare-name invocation). (#5)
- Header wording: exit-0 scope clarified; --json emits [] when no lanes. (#3, #8)

herdr-tab-glyph.sh: consume classify_cwd's new 3-tuple; same BASH_SOURCE fix (#5).
herdr-tab-glyphs.md: point at $HERDR_MATCH_PRELUDE as the shared match SoT. (#10)
Tests extended: null-element + TSV-injection (lanes); --timeout= + missing-target
exit 2 (herdr-agent). Regression: herdr-tab-glyph output byte-identical vs a live
snapshot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8crYp6tzRKMiwW63Zt3GG
@gering
gering force-pushed the task/add-lane-registry branch from 25ee166 to 4f29afb Compare July 25, 2026 12:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant