Skip to content

herdr skills: send-text joins the no-Enter list; faint is the only ghost invariant - #18

Open
RoninATX wants to merge 6 commits into
mainfrom
skills/herdr-ghost-invariant
Open

herdr skills: send-text joins the no-Enter list; faint is the only ghost invariant#18
RoninATX wants to merge 6 commits into
mainfrom
skills/herdr-ghost-invariant

Conversation

@RoninATX

@RoninATX RoninATX commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Follow-up to #17 — two corrections that came back from the panes that adopted it, both verified against the live CLI rather than taken on faith.

pane send-text omits the Enter too

#17's tables already listed it, but the root knowledge doc this was derived from only ever named agent send — and herdr agent --help only calls out that one as well. The omission reads as "send-text is fine," which it isn't. Both skills now carry the corroboration: herdr shipping a separate pane send-keys <pane> Enter is the tell that submitting is its own act.

Raised by the PersonaForge pane during its review.

A ghost is not reliably grey

#17 described a ghost suggestion as faint plus grey #999. A ghost read off a live pane during this work carried \x1b[2m with no 38;2;153;153;153 at all — a detector requiring both would have waved it through as real operator input.

Faint is the invariant; the grey is incidental. Both skills now say so, and the "match on \x1b[2m, not the glyph" rule is extended to "not the grey either."

Docs only — no code.

…ost invariant

Two corrections from the panes that adopted this, both verified against the
live CLI:

- `pane send-text` omits the Enter exactly as `agent send` does. The CLI's
  own help only names `agent send`, so the omission read as "send-text is
  fine" — it isn't. That herdr carries a separate `pane send-keys <pane>
  Enter` is the corroboration: submitting is its own act.

- A ghost composer suggestion is not reliably grey. One read off a live
  pane carried `\x1b[2m` with no `38;2;153;153;153` at all, so a detector
  requiring faint AND grey would have passed it through as real operator
  input. Faint is the invariant; the grey is incidental.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U5Rxy1AE7FV6RwmMFMbotY
Copilot AI lite review requested due to automatic review settings August 7, 2026 14:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the cross-coordinate skill documentation (Coordinator + Child) to reflect two CLI-verified behaviors: (1) pane send-text does not submit (no Enter), and (2) ghost suggestions are reliably identifiable by the ANSI “faint” SGR (\x1b[2m), while the grey color code is not guaranteed.

Changes:

  • Clarifies that pane send-text (like agent send) types without Enter, and submission is a separate act (send-keys … Enter).
  • Refines the ghost-detection guidance to treat \x1b[2m (faint) as the invariant and grey as optional.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
herdr/coordinator/cross-coordinate/SKILL.md Updates Coordinator-side docs for “no Enter” submission behavior and ghost detection invariants.
herdr/child/cross-coordinate/SKILL.md Mirrors the same clarifications in the Child skill documentation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

genuinely must span lines, `pane send-text` the block then `herdr pane send-keys <pane> Enter`
**once**.
tracking item says "relayed." That the CLI carries a *separate*
`pane send-keys <pane> Enter` is the corroboration: submitting is its own act.
cause of most "the Coordinator never answered me" / "the sibling ignored my relay" reports: the
message was pasted, never submitted.
message was pasted, never submitted. That the CLI carries a *separate*
`pane send-keys <pane> Enter` is the corroboration: submitting is its own act.
RoninATX and others added 5 commits August 7, 2026 10:03
PersonaForge's review of the previous commit found the detection rule was
a false-positive machine, and it was right. Two fixes, both verified
against live panes rather than reasoned about:

- **Faint is not sufficient.** A six-pane --ansi sweep found `\x1b[2m` on
  67 lines across three panes and NOT ONE was a composer ghost — they were
  line numbers, tool-output tree glyphs, and truncated JSON. "Discard any
  faint line" over a whole visible read discards most of the transcript.
  The test needs a position anchor: faint ON THE COMPOSER LINE.

- **The composer line IS locatable, contra the previous text.** The claim
  that `❯` "decodes to surrogate bytes, match on \x1b[2m instead" was a
  decoding bug in the reader, not a property of herdr's output: decode the
  same pane as cp1252 and you get mojibake surrogates, decode it as UTF-8
  and U+276F is right there. Verified both ways on one pane. So step 1 is
  find `❯` (as UTF-8), step 2 is faint-test that line — which also closes
  the hole where the old text told you not to match the glyph while giving
  you no other way to find the line.

Also: the grey `#999` is the `❯` prompt marker's own colour, appearing on
empty composers with no ghost at all — it was never a ghost tell in either
direction, which is why the earlier "faint plus grey" phrasing kept
half-matching reality.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U5Rxy1AE7FV6RwmMFMbotY
…lone

Both adopting panes independently hit the same gap in the previous commit,
from opposite sides, and each proposed the anchor the other's data breaks.
An eight-pane sweep settles it: take both conditions.

- Glyph alone hits transcript. A pane displaying a diff OF THIS DOCUMENT
  had 5 U+276F matches in 108 lines — 4 were prose, and the first carried
  faint from line-number chrome, so "first glyph + faint test" returns
  ghost-detected on an innocent diff line. (Found by MindHive and
  PersonaForge independently; pleasingly recursive.)

- Box-rules alone fabricate a composer where none exists. 2 of 8 panes
  swept were non-Claude agents with ZERO composer lines, yet a
  last-two-rules span happily bracketed ordinary transcript. No `❯` line
  means no visible composer — infer nothing.

The composer is the LAST glyph match that also sits between the final two
rules. On all 6 panes that had one, it was the last match and exactly 2
lines from the end.

Also: the previous commit updated the body but left the retired
"discard any faint line" rule verbatim in every Don't list, so the skills
contradicted themselves. Caught by MindHive. Fixed here and in the two
anti-pattern bullets it should have been paired with all along.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U5Rxy1AE7FV6RwmMFMbotY
PersonaForge's validation run caught an over-generalisation in the last
commit. "Always exactly 2 lines from the end" held on all six panes of the
first sweep and got written down as a law; their sweep found a pane at 3.

Nothing depends on the number — the conjunction anchor does the work — but
stating it flatly invites someone to implement a fixed offset, which is
precisely the shortcut the rest of the paragraph exists to prevent. Softened
to "usually within the last two or three lines" with an explicit don't-use-
an-offset note.

Their run also measured the failure the earlier text only predicted: against
the four reference captures, the two-step rule classifies all four correctly
while the original faint-AND-grey rule calls BOTH live ghosts real operator
input.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U5Rxy1AE7FV6RwmMFMbotY
…fy no-match ≠ closed-pane

The L70 eyeball map and L82 script-a-send snippets both subscripted
p['label'] directly. Any pane without a label key (e.g., a sibling
session opened without a label) raised KeyError and crashed the
consumer, including when only eyeballing the map.

Three stacked defects:
1. p['label'] raises KeyError on unlabeled panes.
2. next(..., '') collapses three failure modes (pane closed, pane
   unlabeled, label mismatch) into one empty string.
3. The framing 'empty result means the pane closed' pre-loaded a
   false conclusion; the failure-mode recovery is different for
   each of the three.

Fix: use .get('label') in both snippets. The eyeball map renders
unlabeled panes as (unlabeled) so they remain visible. The
script-a-send comment now says 'no pane carries that label' rather
than 'pane is gone'. Prose rewritten to enumerate the three
possibilities and direct the reader to re-inspect the live pane set.

No workspace-specific labels, pane IDs, or project names are
introduced; the seed remains generic per the publication rule.
… seeds

The deployed copies were repaired in a live workspace; these are the seeds that
regenerate them, so the fixes belong here or they resurface in the next workspace.

coordinator seed - was missing the pane-discovery repair entirely. It ships no
lookup code, so a subscript scan came back clean; absence of the bug is not
presence of the fix, and its prose still tells a reader to match on `label`,
which is what mints the KeyError. Adds `.get('label')`, keeps unlabeled panes
visible in a listing, and reframes an empty result as "not currently resolvable"
rather than "the pane closed" - plus the standing warning not to repair a failed
exact match with a substring match, which resolves to whichever pane is listed
first.

both seeds - relay length ceiling. Past roughly 700 characters `pane run` can die
with BrokenPipe; the error names a pipe rather than a size, so it reads as a
transient glitch worth retrying verbatim. Also records that trimming a relay to
clear the ceiling is a scope edit, not a formatting one.

both seeds - pointer form. "an absolute path" was left unqualified, which mints
unrunnable pointers: `~` is expanded by neither the tracker CLI nor PowerShell,
so it resolves only for an unquoted interactive bash user - the author, never the
recipient - and a backslash absolute is mangled by the bash layer inside
`pane run`. Prefer relative with a stated cwd; forward slashes when absolute.

Also genericises a hardcoded pane id in an example.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

2 participants