Commit Graph
8 Commits
Author SHA1 Message Date
Dark-Alex-17 611900057c test(TASK-050): wait on every expected marker before asserting hook counts
Hook processes are fire-and-forget: the binary's exit drain acknowledges
spawns only, so the STARTED writer can land after the terminal one. The
macro-bracketing tests waited only for the terminal marker and then
asserted STARTED's count immediately, flaking on Windows CI and loaded
Linux runners. The bounded wait now covers every expected marker before
the exact-count and absence assertions run; the probe script's scenario K
comment is corrected to state the spawn-ack-only contract it already
waits around.
2026-09-17 00:33:37 -06:00
Dark-Alex-17 4b2428b334 test(TASK-050): probe wildcard whitelist grammar and macro-without-agent inertness
Scenario K pins the global_hooks wildcard forms (exact, <event>.*, *.<name>, *.*) and partial-glob inertness against a real binary; Scenario L proves --macro without --agent fires zero agent.* events.
2026-09-16 21:42:15 -06:00
Dark-Alex-17 c73d5317a0 feat(TASK-049): harden hook dispatch against NUL env values and nested-supervisor latch misses
- strip interior NUL bytes from hook env values in fire_resolved so
  agent-authored text (e.g. escalation questions) cannot suppress a hook
  via a failed spawn; raise the spawn-failure log to warn!
- make Supervisor::has_active_tasks recurse into child supervisors,
  mirroring cancel_recursive, so a prompt ctrl-c that cancels only a
  grandchild still latches as an interruption
- document the signal-first vs error-first classification asymmetry at
  top_level_agent_finished / SpawnResultHooks::fire and the deliberate
  REPL teardown cancel; pin ctrlc-with-no-error => agent.interrupted
- probe Scenario J: pty-driven ctrl-c during a live headless --agent run
  fires exactly one agent.interrupted with no COYOTE_AGENT_ERROR
2026-09-16 20:31:36 -06:00
Dark-Alex-17 a3b71a6889 feat(TASK-049): classify idle-prompt ctrl-c + ctrl-d as a completed exit
Ctrl-C at the reedline prompt no longer latches the abort signal
unconditionally: latch_prompt_interrupt only marks an interruption when
the supervisor had live agents/jobs to cancel (new
Supervisor::has_active_tasks), so the advertised exit path (ctrl-c at an
idle prompt, then ctrl-d) fires agent.completed at teardown instead of
agent.interrupted. Mid-turn ctrl-c still latches directly via
wait_user_interrupt/poll_abort_signal, preserving the
interrupted-then-exit classification.

Also: probe-lane tests for escalation.answered single-fire,
escalation question env truncation, agent.failed inverse gate, and
hooks probe Scenario I (session.started vs session.resumed); comment
notes on escalation.answered semantics and the agent__cancel blind
spot.
2026-09-16 19:55:52 -06:00
Dark-Alex-17 7ace1731c6 fix(TASK-048): cover agent and repo scripts in eol=lf rules; probe Scenario H for installed bundled scripts
Extends the .gitattributes eol=lf guard to assets/agents/** (33 embedded
shell scripts share the CRLF failure mode the hooks rules fix) and
scripts/*.sh. Adopts the probe-authored Scenario H: black-box checks of
the installed log-events.sh (XDG default, 0600, UTC header, secret
filter, symlink refusal) and notify.sh (control-byte-stripped fallback),
plus non-executable .builtin-manifest.
2026-09-16 18:48:15 -06:00
Dark-Alex-17 89a9398c28 feat(TASK-048): install polish, hooks-dir mixin scan, script and probe hardening
- one shared exec-bit predicate (Language-recognized extensions => 0755) used by
  every hook/agent installer; non-script files in hooks dirs stay non-executable
- mixin discovery scans the global hooks dir and each agent's hooks dir;
  .builtin-manifest is never scanned
- NTFS 8.3 short-name aliases rejected as builtin-manifest entries
- hook-script install announcements restricted to real hook locations
- COYOTE_HOOKS_DIR override warning compares canonicalized paths
- embedded assets decode via checked from_utf8 instead of from_utf8_unchecked
- log-events.sh defaults under ${XDG_STATE_HOME:-$HOME/.local/state}/coyote/hooks.log
  keeping 0600/symlink-refusal/secret-filter hardening; notify.sh tty fallback strips
  control bytes; both use UTC ISO-8601 timestamps
- payload files orphaned by a write failure are unlinked; stale coyote-hook-*.json
  payloads swept best-effort at startup
- sweep_removed_agent_hooks never follows symlinked agent dirs
- usage-probe-hooks.sh replaces bare sleeps with a bounded poll, re-verifies 0755 on
  restored scripts, and covers roles/agent hook locations
- TestConfigDirGuard hoisted into crate::testing
- .gitattributes pins LF line endings for bundled scripts

hooks is now a reserved bundle name.
2026-09-16 18:30:02 -06:00
Dark-Alex-17 e7bd75947c feat(TASK-047): three-state hook install mode, top-level manifest reconcile, removed-agent sweep
- Thread an explicit InstallMode (Skip/Prompt/Force) through the hook
  installers: startup install_builtins() is pinned to Skip and never
  prompts (test-pinned on both mocked-TTY and TTY-less paths);
  --install-builtins hooks runs Prompt mode across all three hook
  locations (global hooks dir, roles/hooks, agents/<name>/hooks) under
  one shared keep-all/replace-all sticky scope; force paths keep
  unconditional overwrite semantics.
- Hoist the bundle resolve_conflict/StickyMode/ConflictAction prompt
  into shared config::conflict with a NonInteractive policy: bundle
  installs keep their non-TTY bail, builtin hook refreshes resolve
  non-TTY conflicts to keep. Bundle UX preserved byte-for-byte,
  pinned by tests.
- Extend .builtin-manifest reconcile to the resolved top-level hooks
  dir (shipped set from HookAssets::iter()); malformed-manifest
  fail-safe (zero deletions) preserved and test-pinned.
- Sweep removed builtin agents' hooks: agent dirs absent from the
  embed with a hooks/.builtin-manifest reconcile against an empty
  shipped set; empty hooks dirs are removed, user files and
  manifest-less agent dirs are never touched.
- Update usage-probe-hooks.sh Scenario C to the new non-interactive
  keep contract and add black-box Scenarios E-G covering role/agent
  hook reconcile, top-level manifest fail-safety, and the
  removed-agent sweep.
2026-09-16 17:59:09 -06:00
Dark-Alex-17 e62502c862 test(TASK-038): adopt hook usage-probe regression script
Black-box scenarios against a built binary with dry_run configs: hook
cadence + env scoping, runtime inertness of failing hooks, --info firing
zero agent.* events, --install-builtins hooks install/force/cold-start
semantics, and end-to-end firing of the installed log-events.sh via the
documented relative-path wiring.
2026-09-16 13:44:35 -06:00