fno-agents 0.3.1

PTY supervisor substrate for persistent, attachable multi-CLI coding agents (codex, gemini, claude)
Documentation
# devin readiness manifest (x-83e7) - full-roster parity port from
# the reference manifest for devin per ADAPTING.md.
#
# UNVALIDATED + INERT: devin has no fno provider host (no build_pane_argv arm /
# provider impl), so scrape_targets never selects it and this manifest is
# bundled-but-dormant (like opencode). Markers are reference-derived, NOT pinned
# against a live devin TUI. Our engine is case-sensitive and the reference engine is not, so
# these lowercase needles under-fire until smoke-pinned - the conservative
# never-false-ready direction (readiness OQ#9). The two idle rules
# (welcome/live_prompt) lean on this doubly: a case miss keeps them from ever
# false-badging idle. State vocab + arbitration: see codex.toml.
#
# Priority (highest wins): 300 trust > 290 permission (blocked) > 200 running
# > 190 guide > 180 tool_reading (working) > 120 welcome > 100 live_prompt (idle).
# Each working/idle rule carries the reference `not` guard so a live prompt drawn
# beneath an approval/interrupt footer never wins over the blocked rules.

min_engine_version = 1

[[rule]]
id = "workspace_trust_prompt"
state = "blocked"
priority = 300
region = "bottom_non_empty_lines(8)"
gate = { all = [
  { contains = "do you trust the authors of this directory?" },
  { contains = "with untrusted content." },
  { contains = "yes, trust " },
] }

[[rule]]
id = "permission_prompt"
state = "blocked"
priority = 290
region = "bottom_non_empty_lines(8)"
gate = { all = [
  { contains = "approve once" },
  { contains = "select" },
  { contains = "confirm" },
  { contains = "esc cancel" },
] }

[[rule]]
id = "running_tools_footer"
state = "working"
priority = 200
region = "bottom_non_empty_lines(8)"
gate = { all = [
  { contains = "running tools" },
  { contains = "esc to interrupt" },
  { not = { all = [ { contains = "approve once" }, { contains = "esc cancel" } ] } },
] }

[[rule]]
id = "guide_while_working"
state = "working"
priority = 190
region = "bottom_non_empty_lines(6)"
gate = { all = [
  { contains = "guide devin while it works" },
  { not = { all = [ { contains = "approve once" }, { contains = "esc cancel" } ] } },
] }

[[rule]]
id = "tool_reading_timeout"
state = "working"
priority = 180
region = "bottom_non_empty_lines(8)"
gate = { all = [
  { contains = "reading shell " },
  { contains = "timeout:" },
  { not = { all = [ { contains = "approve once" }, { contains = "esc cancel" } ] } },
] }

[[rule]]
id = "welcome_prompt_footer"
state = "idle"
priority = 120
region = "bottom_non_empty_lines(8)"
gate = { all = [
  { contains = "ask devin to build" },
  { contains = "features, fix bugs" },
  { contains = "your code" },
  { line_regex = '^\s*❭ Ask Devin to build' },
  { not = { any = [
    { all = [ { contains = "approve once" }, { contains = "esc cancel" } ] },
    { all = [ { contains = "running tools" }, { contains = "esc to interrupt" } ] },
    { contains = "guide devin while it works" },
  ] } },
] }

[[rule]]
id = "live_prompt_footer"
state = "idle"
priority = 100
region = "bottom_non_empty_lines(6)"
gate = { all = [
  { contains = "context:" },
  { line_regex = '^\s*❭' },
  { not = { any = [
    { all = [ { contains = "approve once" }, { contains = "esc cancel" } ] },
    { all = [ { contains = "running tools" }, { contains = "esc to interrupt" } ] },
    { contains = "guide devin while it works" },
  ] } },
] }