From f85fa5b6cf0436ad3868db2b46bcc47ff33286d8 Mon Sep 17 00:00:00 2001 From: Godopu Date: Sun, 6 Sep 2026 13:27:45 +0900 Subject: [PATCH] test(issue-5): add layer-1 herdr and layer-2 watcher test fixtures --- .../issue_5/herdr/agy/wait_timeout.json | 35 ++++ tests/fixtures/issue_5/herdr/agy/working.json | 81 +++++++++ tests/fixtures/issue_5/herdr/claude/idle.json | 81 +++++++++ tests/fixtures/issue_5/herdr/codex/done.json | 81 +++++++++ tests/fixtures/issue_5/herdr/grok/idle.json | 81 +++++++++ tests/fixtures/issue_5/herdr/manifest.json | 167 ++++++++++++++++++ .../fixtures/issue_5/herdr/wait-contract.json | 80 +++++++++ .../issue_5/watcher/blocked_permission.json | 38 ++++ .../issue_5/watcher/finalized_candidate.json | 61 +++++++ .../issue_5/watcher/initial_idle.json | 47 +++++ tests/fixtures/issue_5/watcher/manifest.json | 48 +++++ .../issue_5/watcher/report_pause_15s.json | 60 +++++++ .../issue_5/watcher/restarted_generation.json | 38 ++++ .../issue_5/watcher/tool_running.json | 48 +++++ .../watcher/transport_disconnected.json | 37 ++++ 15 files changed, 983 insertions(+) create mode 100644 tests/fixtures/issue_5/herdr/agy/wait_timeout.json create mode 100644 tests/fixtures/issue_5/herdr/agy/working.json create mode 100644 tests/fixtures/issue_5/herdr/claude/idle.json create mode 100644 tests/fixtures/issue_5/herdr/codex/done.json create mode 100644 tests/fixtures/issue_5/herdr/grok/idle.json create mode 100644 tests/fixtures/issue_5/herdr/manifest.json create mode 100644 tests/fixtures/issue_5/herdr/wait-contract.json create mode 100644 tests/fixtures/issue_5/watcher/blocked_permission.json create mode 100644 tests/fixtures/issue_5/watcher/finalized_candidate.json create mode 100644 tests/fixtures/issue_5/watcher/initial_idle.json create mode 100644 tests/fixtures/issue_5/watcher/manifest.json create mode 100644 tests/fixtures/issue_5/watcher/report_pause_15s.json create mode 100644 tests/fixtures/issue_5/watcher/restarted_generation.json create mode 100644 tests/fixtures/issue_5/watcher/tool_running.json create mode 100644 tests/fixtures/issue_5/watcher/transport_disconnected.json diff --git a/tests/fixtures/issue_5/herdr/agy/wait_timeout.json b/tests/fixtures/issue_5/herdr/agy/wait_timeout.json new file mode 100644 index 0000000..89b7cc9 --- /dev/null +++ b/tests/fixtures/issue_5/herdr/agy/wait_timeout.json @@ -0,0 +1,35 @@ +{ + "schema_version": "1.0.0", + "capture_id": "cap-agy-timeout-01", + "backend": "agy", + "herdr_version": "0.8.2", + "backend_version": "unknown", + "platform": "darwin-arm64", + "provenance": "observed", + "command_argv": [ + "herdr", + "agent", + "wait", + "creator-agy-01", + "--until", + "done", + "--timeout", + "50" + ], + "exit_code": 1, + "stdout_payload": null, + "stderr": "{\"error\":{\"code\":\"timeout\",\"message\":\"timed out waiting for agent status\"},\"id\":\"cli:agent:wait\"}", + "captured_at": "2026-09-06T00:45:00Z", + "collector_clock_id": "CLOCK_MONOTONIC", + "monotonic_start": 100.0, + "monotonic_end": 100.05, + "evidence_reference": ".mam/jobs/129a95db/evidence/timeout_stderr.json", + "normalization_map_reference": "paths_normalized: /Users/godopu16/PuKi/laa/canary_projects/multi-agent-mux -> ", + "payload": { + "error": { + "code": "timeout", + "message": "timed out waiting for agent status" + }, + "id": "cli:agent:wait" + } +} diff --git a/tests/fixtures/issue_5/herdr/agy/working.json b/tests/fixtures/issue_5/herdr/agy/working.json new file mode 100644 index 0000000..ce28b2c --- /dev/null +++ b/tests/fixtures/issue_5/herdr/agy/working.json @@ -0,0 +1,81 @@ +{ + "schema_version": "1.0.0", + "capture_id": "cap-agy-working-01", + "backend": "agy", + "herdr_version": "0.8.2", + "backend_version": "unknown", + "platform": "darwin-arm64", + "provenance": "observed", + "command_argv": [ + "herdr", + "agent", + "get", + "creator-agy-01" + ], + "exit_code": 0, + "stdout_payload": { + "id": "cli:agent:get", + "result": { + "agent": { + "agent": "agy", + "agent_session": { + "agent": "agy", + "kind": "id", + "source": "herdr:antigravity_cli", + "value": "1c53dd89-81fc-49a6-b15e-bef3dfb61697" + }, + "agent_status": "working", + "cwd": "", + "focused": false, + "foreground_cwd": "", + "interactive_ready": true, + "name": "creator-agy-01", + "pane_id": "w2X:p3", + "revision": 2, + "state_change_seq": 29, + "tab_id": "w2X:t1", + "terminal_id": "term_65ac4b5991acc4", + "terminal_title": "agy --dangerously-skip-permissions --conversation ", + "terminal_title_stripped": "agy --dangerously-skip-permissions --conversation", + "workspace_id": "w2X" + }, + "type": "agent_info" + } + }, + "stderr": null, + "captured_at": "2026-09-06T00:45:00Z", + "collector_clock_id": "CLOCK_MONOTONIC", + "monotonic_start": 100.0, + "monotonic_end": 100.05, + "evidence_reference": ".mam/jobs/129a95db/evidence/get_agy_working.json", + "normalization_map_reference": "paths_normalized: /Users/godopu16/PuKi/laa/canary_projects/multi-agent-mux -> ", + "payload": { + "id": "cli:agent:get", + "result": { + "agent": { + "agent": "agy", + "agent_session": { + "agent": "agy", + "kind": "id", + "source": "herdr:antigravity_cli", + "value": "1c53dd89-81fc-49a6-b15e-bef3dfb61697" + }, + "agent_status": "working", + "cwd": "", + "focused": false, + "foreground_cwd": "", + "interactive_ready": true, + "name": "creator-agy-01", + "pane_id": "w2X:p3", + "revision": 2, + "state_change_seq": 29, + "tab_id": "w2X:t1", + "terminal_id": "term_65ac4b5991acc4", + "terminal_title": "agy --dangerously-skip-permissions --conversation ", + "terminal_title_stripped": "agy --dangerously-skip-permissions --conversation", + "workspace_id": "w2X" + }, + "type": "agent_info" + } + } +} diff --git a/tests/fixtures/issue_5/herdr/claude/idle.json b/tests/fixtures/issue_5/herdr/claude/idle.json new file mode 100644 index 0000000..1660aa8 --- /dev/null +++ b/tests/fixtures/issue_5/herdr/claude/idle.json @@ -0,0 +1,81 @@ +{ + "schema_version": "1.0.0", + "capture_id": "cap-claude-idle-01", + "backend": "claude", + "herdr_version": "0.8.2", + "backend_version": "unknown", + "platform": "darwin-arm64", + "provenance": "observed", + "command_argv": [ + "herdr", + "agent", + "get", + "planner-reviewer-claude-01" + ], + "exit_code": 0, + "stdout_payload": { + "id": "cli:agent:get", + "result": { + "agent": { + "agent": "claude", + "agent_session": { + "agent": "claude", + "kind": "id", + "source": "herdr:claude", + "value": "7d5700d0-bab1-4f65-9665-6b887396a9a6" + }, + "agent_status": "idle", + "cwd": "", + "focused": false, + "foreground_cwd": "", + "interactive_ready": true, + "name": "planner-reviewer-claude-01", + "pane_id": "w2X:p1", + "revision": 3, + "state_change_seq": 18, + "tab_id": "w2X:t1", + "terminal_id": "term_65ac4b2b224de2", + "terminal_title": "✳ Multi-agent-mux team leader onboarding", + "terminal_title_stripped": "Multi-agent-mux team leader onboarding", + "workspace_id": "w2X" + }, + "type": "agent_info" + } + }, + "stderr": null, + "captured_at": "2026-09-06T00:45:00Z", + "collector_clock_id": "CLOCK_MONOTONIC", + "monotonic_start": 100.0, + "monotonic_end": 100.05, + "evidence_reference": ".mam/jobs/129a95db/evidence/get_claude_idle.json", + "normalization_map_reference": "paths_normalized: /Users/godopu16/PuKi/laa/canary_projects/multi-agent-mux -> ", + "payload": { + "id": "cli:agent:get", + "result": { + "agent": { + "agent": "claude", + "agent_session": { + "agent": "claude", + "kind": "id", + "source": "herdr:claude", + "value": "7d5700d0-bab1-4f65-9665-6b887396a9a6" + }, + "agent_status": "idle", + "cwd": "", + "focused": false, + "foreground_cwd": "", + "interactive_ready": true, + "name": "planner-reviewer-claude-01", + "pane_id": "w2X:p1", + "revision": 3, + "state_change_seq": 18, + "tab_id": "w2X:t1", + "terminal_id": "term_65ac4b2b224de2", + "terminal_title": "✳ Multi-agent-mux team leader onboarding", + "terminal_title_stripped": "Multi-agent-mux team leader onboarding", + "workspace_id": "w2X" + }, + "type": "agent_info" + } + } +} diff --git a/tests/fixtures/issue_5/herdr/codex/done.json b/tests/fixtures/issue_5/herdr/codex/done.json new file mode 100644 index 0000000..4d89765 --- /dev/null +++ b/tests/fixtures/issue_5/herdr/codex/done.json @@ -0,0 +1,81 @@ +{ + "schema_version": "1.0.0", + "capture_id": "cap-codex-done-01", + "backend": "codex", + "herdr_version": "0.8.2", + "backend_version": "unknown", + "platform": "darwin-arm64", + "provenance": "observed", + "command_argv": [ + "herdr", + "agent", + "get", + "planner-reviewer-codex-01" + ], + "exit_code": 0, + "stdout_payload": { + "id": "cli:agent:get", + "result": { + "agent": { + "agent": "codex", + "agent_session": { + "agent": "codex", + "kind": "id", + "source": "herdr:codex", + "value": "01a071d1-a645-7400-afdb-3b08019800b3" + }, + "agent_status": "done", + "cwd": "", + "focused": true, + "foreground_cwd": "", + "interactive_ready": true, + "name": "planner-reviewer-codex-01", + "pane_id": "w2X:p4", + "revision": 3, + "state_change_seq": 26, + "tab_id": "w2X:t1", + "terminal_id": "term_65ac4b62bd4e75", + "terminal_title": "multi-agent-mux", + "terminal_title_stripped": "multi-agent-mux", + "workspace_id": "w2X" + }, + "type": "agent_info" + } + }, + "stderr": null, + "captured_at": "2026-09-06T00:45:00Z", + "collector_clock_id": "CLOCK_MONOTONIC", + "monotonic_start": 100.0, + "monotonic_end": 100.05, + "evidence_reference": ".mam/jobs/129a95db/evidence/get_codex_done.json", + "normalization_map_reference": "paths_normalized: /Users/godopu16/PuKi/laa/canary_projects/multi-agent-mux -> ", + "payload": { + "id": "cli:agent:get", + "result": { + "agent": { + "agent": "codex", + "agent_session": { + "agent": "codex", + "kind": "id", + "source": "herdr:codex", + "value": "01a071d1-a645-7400-afdb-3b08019800b3" + }, + "agent_status": "done", + "cwd": "", + "focused": true, + "foreground_cwd": "", + "interactive_ready": true, + "name": "planner-reviewer-codex-01", + "pane_id": "w2X:p4", + "revision": 3, + "state_change_seq": 26, + "tab_id": "w2X:t1", + "terminal_id": "term_65ac4b62bd4e75", + "terminal_title": "multi-agent-mux", + "terminal_title_stripped": "multi-agent-mux", + "workspace_id": "w2X" + }, + "type": "agent_info" + } + } +} diff --git a/tests/fixtures/issue_5/herdr/grok/idle.json b/tests/fixtures/issue_5/herdr/grok/idle.json new file mode 100644 index 0000000..e3d44ca --- /dev/null +++ b/tests/fixtures/issue_5/herdr/grok/idle.json @@ -0,0 +1,81 @@ +{ + "schema_version": "1.0.0", + "capture_id": "cap-grok-idle-01", + "backend": "grok", + "herdr_version": "0.8.2", + "backend_version": "unknown", + "platform": "darwin-arm64", + "provenance": "observed", + "command_argv": [ + "herdr", + "agent", + "get", + "reviewer-creator-grok-01" + ], + "exit_code": 0, + "stdout_payload": { + "id": "cli:agent:get", + "result": { + "agent": { + "agent": "grok", + "agent_session": { + "agent": "grok", + "kind": "id", + "source": "herdr:grok", + "value": "3ea2d545-f7cf-4357-a743-25b2c988e46a" + }, + "agent_status": "idle", + "cwd": "", + "focused": false, + "foreground_cwd": "", + "interactive_ready": true, + "name": "reviewer-creator-grok-01", + "pane_id": "w2X:p2", + "revision": 131, + "state_change_seq": 17, + "tab_id": "w2X:t1", + "terminal_id": "term_65ac4b4eb7c7d3", + "terminal_title": "Hermes review and cline deprecation cons… - grok", + "terminal_title_stripped": "Hermes review and cline deprecation cons… - grok", + "workspace_id": "w2X" + }, + "type": "agent_info" + } + }, + "stderr": null, + "captured_at": "2026-09-06T00:45:00Z", + "collector_clock_id": "CLOCK_MONOTONIC", + "monotonic_start": 100.0, + "monotonic_end": 100.05, + "evidence_reference": ".mam/jobs/129a95db/evidence/get_grok_idle.json", + "normalization_map_reference": "paths_normalized: /Users/godopu16/PuKi/laa/canary_projects/multi-agent-mux -> ", + "payload": { + "id": "cli:agent:get", + "result": { + "agent": { + "agent": "grok", + "agent_session": { + "agent": "grok", + "kind": "id", + "source": "herdr:grok", + "value": "3ea2d545-f7cf-4357-a743-25b2c988e46a" + }, + "agent_status": "idle", + "cwd": "", + "focused": false, + "foreground_cwd": "", + "interactive_ready": true, + "name": "reviewer-creator-grok-01", + "pane_id": "w2X:p2", + "revision": 131, + "state_change_seq": 17, + "tab_id": "w2X:t1", + "terminal_id": "term_65ac4b4eb7c7d3", + "terminal_title": "Hermes review and cline deprecation cons… - grok", + "terminal_title_stripped": "Hermes review and cline deprecation cons… - grok", + "workspace_id": "w2X" + }, + "type": "agent_info" + } + } +} diff --git a/tests/fixtures/issue_5/herdr/manifest.json b/tests/fixtures/issue_5/herdr/manifest.json new file mode 100644 index 0000000..594a054 --- /dev/null +++ b/tests/fixtures/issue_5/herdr/manifest.json @@ -0,0 +1,167 @@ +{ + "schema_version": "1.0.0", + "herdr_version": "0.8.2", + "description": "Native Herdr observation fixture manifest across 6 backends", + "backends": { + "claude": { + "installed_binary": "/Users/godopu16/.local/bin/claude", + "active_session": "planner-reviewer-claude-01", + "slots": { + "idle": { + "status": "observed", + "file": "claude/idle.json" + }, + "working": { + "status": "unobserved", + "reason": "session was idle during capture window" + }, + "blocked": { + "status": "unobserved", + "reason": "no interactive permission prompt pending" + }, + "done": { + "status": "unobserved", + "reason": "session in idle state" + }, + "unknown": { + "status": "unobserved", + "reason": "session is active and healthy" + } + } + }, + "agy": { + "installed_binary": "/Users/godopu16/.local/bin/agy", + "active_session": "creator-agy-01", + "slots": { + "idle": { + "status": "unobserved", + "reason": "session actively executing task b75d76d0/129a95db" + }, + "working": { + "status": "observed", + "file": "agy/working.json" + }, + "blocked": { + "status": "unobserved", + "reason": "agy running with --dangerously-skip-permissions" + }, + "done": { + "status": "unobserved", + "reason": "session actively working" + }, + "unknown": { + "status": "unobserved", + "reason": "session is active and healthy" + }, + "wait_timeout": { + "status": "observed", + "file": "agy/wait_timeout.json" + } + } + }, + "hermes": { + "installed_binary": "/Users/godopu16/.local/bin/hermes", + "active_session": null, + "slots": { + "idle": { + "status": "unobserved", + "reason": "no hermes session currently active in herdr persistent daemon" + }, + "working": { + "status": "unobserved", + "reason": "no hermes session currently active in herdr persistent daemon" + }, + "blocked": { + "status": "unobserved", + "reason": "no hermes session currently active in herdr persistent daemon" + }, + "done": { + "status": "unobserved", + "reason": "no hermes session currently active in herdr persistent daemon" + }, + "unknown": { + "status": "unobserved", + "reason": "no hermes session currently active in herdr persistent daemon" + } + } + }, + "grok": { + "installed_binary": "/Users/godopu16/.grok/bin/grok", + "active_session": "reviewer-creator-grok-01", + "slots": { + "idle": { + "status": "observed", + "file": "grok/idle.json" + }, + "working": { + "status": "unobserved", + "reason": "session currently idle waiting for review assignment" + }, + "blocked": { + "status": "unobserved", + "reason": "no permission prompt pending" + }, + "done": { + "status": "unobserved", + "reason": "session currently idle" + }, + "unknown": { + "status": "unobserved", + "reason": "session is active and healthy" + } + } + }, + "opencode": { + "installed_binary": "/Users/godopu16/.opencode/bin/opencode", + "active_session": null, + "slots": { + "idle": { + "status": "unobserved", + "reason": "no opencode session currently active in herdr persistent daemon" + }, + "working": { + "status": "unobserved", + "reason": "no opencode session currently active in herdr persistent daemon" + }, + "blocked": { + "status": "unobserved", + "reason": "no opencode session currently active in herdr persistent daemon" + }, + "done": { + "status": "unobserved", + "reason": "no opencode session currently active in herdr persistent daemon" + }, + "unknown": { + "status": "unobserved", + "reason": "no opencode session currently active in herdr persistent daemon" + } + } + }, + "codex": { + "installed_binary": "/Users/godopu16/.local/bin/codex", + "active_session": "planner-reviewer-codex-01", + "slots": { + "idle": { + "status": "unobserved", + "reason": "session currently in done state" + }, + "working": { + "status": "unobserved", + "reason": "session currently in done state" + }, + "blocked": { + "status": "unobserved", + "reason": "no permission prompt pending" + }, + "done": { + "status": "observed", + "file": "codex/done.json" + }, + "unknown": { + "status": "unobserved", + "reason": "session is active and healthy" + } + } + } + } +} diff --git a/tests/fixtures/issue_5/herdr/wait-contract.json b/tests/fixtures/issue_5/herdr/wait-contract.json new file mode 100644 index 0000000..3798d2b --- /dev/null +++ b/tests/fixtures/issue_5/herdr/wait-contract.json @@ -0,0 +1,80 @@ +{ + "schema_version": "1.0.0", + "herdr_version": "0.8.2", + "cli_command": "herdr agent wait [OPTIONS]", + "options": { + "--until": { + "type": "string", + "repeatable": true, + "possible_values": [ + "idle", + "working", + "blocked", + "done", + "unknown" + ], + "default_when_omitted": [ + "idle", + "done", + "blocked" + ] + }, + "--timeout": { + "type": "integer_ms", + "required": false, + "default_when_omitted": "unlimited (indefinite block)" + } + }, + "call_outcomes": [ + { + "outcome": "state_matched", + "exit_code": 0, + "output_channel": "stdout", + "sample_command": [ + "herdr", + "agent", + "wait", + "creator-agy-01", + "--until", + "working", + "--timeout", + "1000" + ], + "evidence_reference": ".mam/jobs/129a95db/evidence/wait_agy_working_immediate.json" + }, + { + "outcome": "timeout", + "exit_code": 1, + "output_channel": "stderr", + "error_code": "timeout", + "sample_command": [ + "herdr", + "agent", + "wait", + "creator-agy-01", + "--until", + "done", + "--timeout", + "50" + ], + "evidence_reference": ".mam/jobs/129a95db/evidence/timeout_stderr.json" + }, + { + "outcome": "agent_not_found", + "exit_code": 1, + "output_channel": "stderr", + "error_code": "agent_not_found", + "sample_command": [ + "herdr", + "agent", + "wait", + "non-existent-agent-target", + "--until", + "idle", + "--timeout", + "50" + ], + "evidence_reference": ".mam/jobs/129a95db/evidence/unknown_target_stderr.txt" + } + ] +} diff --git a/tests/fixtures/issue_5/watcher/blocked_permission.json b/tests/fixtures/issue_5/watcher/blocked_permission.json new file mode 100644 index 0000000..25e2d06 --- /dev/null +++ b/tests/fixtures/issue_5/watcher/blocked_permission.json @@ -0,0 +1,38 @@ +{ + "schema_version": "1.0.0", + "scenario_id": "blocked_permission", + "backend": "backend_agnostic", + "provenance": "simulated", + "description": "Native status blocked on interactive permission prompt. Completion forbidden.", + "dispatch_context": { + "job_id": "test-job-blocked-01", + "attempt_id": 1, + "agent_session_uuid": "1c53dd89-81fc-49a6-b15e-bef3dfb61697", + "pane_process_generation": "w2X:p3:5678:2026-09-06T00:00:00Z", + "dispatch_ack": true, + "execution_anchor_observed": true + }, + "timeline": [ + { + "collector_clock_id": "CLOCK_MONOTONIC", + "relative_ms": 0, + "source_kind": "herdr", + "source_provenance": "simulated", + "payload": { + "agent_status": "blocked", + "interactive_ready": false, + "matched_rule": "permission_prompt" + } + } + ], + "filesystem": { + "report_path": ".mam/jobs/test-job-blocked-01/report-final.md", + "exists": false, + "manifest_committed": false + }, + "expected_policy": { + "decision": "hold_blocked", + "reason": "agent terminal is blocked awaiting user permission", + "policy_version": "2.0.0" + } +} diff --git a/tests/fixtures/issue_5/watcher/finalized_candidate.json b/tests/fixtures/issue_5/watcher/finalized_candidate.json new file mode 100644 index 0000000..d8e5340 --- /dev/null +++ b/tests/fixtures/issue_5/watcher/finalized_candidate.json @@ -0,0 +1,61 @@ +{ + "schema_version": "1.0.0", + "scenario_id": "finalized_candidate", + "backend": "backend_agnostic", + "provenance": "simulated", + "description": "Execution anchor verified, native status idle/done, atomic rename complete with valid SHA-256 commit manifest. Inferred candidate approved for CAS.", + "dispatch_context": { + "job_id": "test-job-finalized-01", + "attempt_id": 1, + "agent_session_uuid": "7d5700d0-bab1-4f65-9665-6b887396a9a6", + "pane_process_generation": "w2X:p1:1234:2026-09-06T00:00:00Z", + "dispatch_ack": true, + "execution_anchor_observed": true + }, + "timeline": [ + { + "collector_clock_id": "CLOCK_MONOTONIC", + "relative_ms": 0, + "source_kind": "event", + "source_provenance": "simulated", + "payload": { + "event": "started", + "job_id": "test-job-finalized-01" + } + }, + { + "collector_clock_id": "CLOCK_MONOTONIC", + "relative_ms": 5000, + "source_kind": "filesystem", + "source_provenance": "simulated", + "payload": { + "report_manifest": { + "report_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "attempt_id": 1, + "finalized": true + } + } + }, + { + "collector_clock_id": "CLOCK_MONOTONIC", + "relative_ms": 6000, + "source_kind": "herdr", + "source_provenance": "simulated", + "payload": { + "agent_status": "idle", + "interactive_ready": true + } + } + ], + "filesystem": { + "report_path": ".mam/jobs/test-job-finalized-01/report-final.md", + "exists": true, + "manifest_committed": true, + "hash_verified": true + }, + "expected_policy": { + "decision": "candidate_approved", + "reason": "all 4-fold attribution, fresh idle status, and atomic finalization manifest verified", + "policy_version": "2.0.0" + } +} diff --git a/tests/fixtures/issue_5/watcher/initial_idle.json b/tests/fixtures/issue_5/watcher/initial_idle.json new file mode 100644 index 0000000..e4ed352 --- /dev/null +++ b/tests/fixtures/issue_5/watcher/initial_idle.json @@ -0,0 +1,47 @@ +{ + "schema_version": "1.0.0", + "scenario_id": "initial_idle", + "backend": "backend_agnostic", + "provenance": "simulated", + "description": "Dispatch record exists and native status is idle, but no execution anchor observed since dispatch_ack. Inferred completion must be held.", + "dispatch_context": { + "job_id": "test-job-init-idle-01", + "attempt_id": 1, + "agent_session_uuid": "7d5700d0-bab1-4f65-9665-6b887396a9a6", + "pane_process_generation": "w2X:p1:1234:2026-09-06T00:00:00Z", + "dispatch_ack": true, + "execution_anchor_observed": false + }, + "timeline": [ + { + "collector_clock_id": "CLOCK_MONOTONIC", + "relative_ms": 0, + "source_kind": "event", + "source_provenance": "simulated", + "payload": { + "event": "dispatched", + "job_id": "test-job-init-idle-01" + } + }, + { + "collector_clock_id": "CLOCK_MONOTONIC", + "relative_ms": 500, + "source_kind": "herdr", + "source_provenance": "simulated", + "payload": { + "agent_status": "idle", + "interactive_ready": true + } + } + ], + "filesystem": { + "report_path": ".mam/jobs/test-job-init-idle-01/report-final.md", + "exists": false, + "manifest_committed": false + }, + "expected_policy": { + "decision": "hold", + "reason": "no execution anchor observed for this attempt", + "policy_version": "2.0.0" + } +} diff --git a/tests/fixtures/issue_5/watcher/manifest.json b/tests/fixtures/issue_5/watcher/manifest.json new file mode 100644 index 0000000..975ba32 --- /dev/null +++ b/tests/fixtures/issue_5/watcher/manifest.json @@ -0,0 +1,48 @@ +{ + "schema_version": "1.0.0", + "description": "Multi-channel Watcher composite timeline scenario manifest", + "scenarios": { + "initial_idle": { + "file": "initial_idle.json", + "provenance": "simulated", + "expected_decision": "hold", + "description": "Dispatch record exists and native status is idle, but no execution anchor observed since dispatch_ack. Inferred completion must be held." + }, + "tool_running": { + "file": "tool_running.json", + "provenance": "simulated", + "expected_decision": "hold", + "description": "Native status working or interactive_ready with active background tool execution. Inferred completion must be held." + }, + "report_pause_15s": { + "file": "report_pause_15s.json", + "provenance": "simulated", + "expected_decision": "hold", + "description": "Partial report written and stable for >= 15s debounce, but lacks atomic finalization manifest. Completion must be held." + }, + "finalized_candidate": { + "file": "finalized_candidate.json", + "provenance": "simulated", + "expected_decision": "candidate_approved", + "description": "Execution anchor verified, native status idle/done, atomic rename complete with valid SHA-256 commit manifest. Inferred candidate approved for CAS." + }, + "blocked_permission": { + "file": "blocked_permission.json", + "provenance": "simulated", + "expected_decision": "hold_blocked", + "description": "Native status blocked on interactive permission prompt. Completion forbidden." + }, + "transport_disconnected": { + "file": "transport_disconnected.json", + "provenance": "simulated", + "expected_decision": "hold_reconnect", + "description": "Herdr socket connection failure or freshness gap. Cached evidence invalidated; must reconnect and resnapshot." + }, + "restarted_generation": { + "file": "restarted_generation.json", + "provenance": "simulated", + "expected_decision": "reject_stale", + "description": "Pane process restarted with new PID/start time; stale attempt rejected." + } + } +} diff --git a/tests/fixtures/issue_5/watcher/report_pause_15s.json b/tests/fixtures/issue_5/watcher/report_pause_15s.json new file mode 100644 index 0000000..7602e46 --- /dev/null +++ b/tests/fixtures/issue_5/watcher/report_pause_15s.json @@ -0,0 +1,60 @@ +{ + "schema_version": "1.0.0", + "scenario_id": "report_pause_15s", + "backend": "backend_agnostic", + "provenance": "simulated", + "description": "Partial report written and stable for >= 15s debounce, but lacks atomic finalization manifest. Completion must be held.", + "dispatch_context": { + "job_id": "test-job-pause-01", + "attempt_id": 1, + "agent_session_uuid": "1c53dd89-81fc-49a6-b15e-bef3dfb61697", + "pane_process_generation": "w2X:p3:5678:2026-09-06T00:00:00Z", + "dispatch_ack": true, + "execution_anchor_observed": true + }, + "timeline": [ + { + "collector_clock_id": "CLOCK_MONOTONIC", + "relative_ms": 0, + "source_kind": "filesystem", + "source_provenance": "simulated", + "payload": { + "file": "report-final.md.tmp", + "bytes": 250, + "phase": "writing" + } + }, + { + "collector_clock_id": "CLOCK_MONOTONIC", + "relative_ms": 16000, + "source_kind": "filesystem", + "source_provenance": "simulated", + "payload": { + "file": "report-final.md.tmp", + "bytes": 250, + "mtime_stale_sec": 16.0 + } + }, + { + "collector_clock_id": "CLOCK_MONOTONIC", + "relative_ms": 16100, + "source_kind": "herdr", + "source_provenance": "simulated", + "payload": { + "agent_status": "working", + "interactive_ready": true + } + } + ], + "filesystem": { + "report_path": ".mam/jobs/test-job-pause-01/report-final.md", + "exists": false, + "tmp_file_exists": true, + "manifest_committed": false + }, + "expected_policy": { + "decision": "hold", + "reason": "debounce elapsed on partial file, but report is unfinalized without manifest", + "policy_version": "2.0.0" + } +} diff --git a/tests/fixtures/issue_5/watcher/restarted_generation.json b/tests/fixtures/issue_5/watcher/restarted_generation.json new file mode 100644 index 0000000..405c52f --- /dev/null +++ b/tests/fixtures/issue_5/watcher/restarted_generation.json @@ -0,0 +1,38 @@ +{ + "schema_version": "1.0.0", + "scenario_id": "restarted_generation", + "backend": "backend_agnostic", + "provenance": "simulated", + "description": "Pane process restarted with new PID/start time; stale attempt rejected.", + "dispatch_context": { + "job_id": "test-job-restarted-01", + "attempt_id": 1, + "agent_session_uuid": "7d5700d0-bab1-4f65-9665-6b887396a9a6", + "pane_process_generation": "w2X:p1:1234:2026-09-06T00:00:00Z", + "dispatch_ack": true, + "execution_anchor_observed": false + }, + "timeline": [ + { + "collector_clock_id": "CLOCK_MONOTONIC", + "relative_ms": 0, + "source_kind": "herdr", + "source_provenance": "simulated", + "payload": { + "pane_id": "w2X:p1", + "pane_process_generation": "w2X:p1:9999:2026-09-06T01:00:00Z", + "agent_status": "idle" + } + } + ], + "filesystem": { + "report_path": ".mam/jobs/test-job-restarted-01/report-final.md", + "exists": false, + "manifest_committed": false + }, + "expected_policy": { + "decision": "reject_stale", + "reason": "observed process generation does not match active dispatch attempt", + "policy_version": "2.0.0" + } +} diff --git a/tests/fixtures/issue_5/watcher/tool_running.json b/tests/fixtures/issue_5/watcher/tool_running.json new file mode 100644 index 0000000..efc4659 --- /dev/null +++ b/tests/fixtures/issue_5/watcher/tool_running.json @@ -0,0 +1,48 @@ +{ + "schema_version": "1.0.0", + "scenario_id": "tool_running", + "backend": "backend_agnostic", + "provenance": "simulated", + "description": "Native status working or interactive_ready with active background tool execution. Inferred completion must be held.", + "dispatch_context": { + "job_id": "test-job-tool-running-01", + "attempt_id": 1, + "agent_session_uuid": "1c53dd89-81fc-49a6-b15e-bef3dfb61697", + "pane_process_generation": "w2X:p3:5678:2026-09-06T00:00:00Z", + "dispatch_ack": true, + "execution_anchor_observed": true + }, + "timeline": [ + { + "collector_clock_id": "CLOCK_MONOTONIC", + "relative_ms": 0, + "source_kind": "herdr", + "source_provenance": "simulated", + "payload": { + "agent_status": "working", + "interactive_ready": true + } + }, + { + "collector_clock_id": "CLOCK_MONOTONIC", + "relative_ms": 200, + "source_kind": "harness", + "source_provenance": "simulated", + "payload": { + "tool": "bash", + "active": true, + "command": "pytest" + } + } + ], + "filesystem": { + "report_path": ".mam/jobs/test-job-tool-running-01/report-final.md", + "exists": false, + "manifest_committed": false + }, + "expected_policy": { + "decision": "hold", + "reason": "external tool execution currently active", + "policy_version": "2.0.0" + } +} diff --git a/tests/fixtures/issue_5/watcher/transport_disconnected.json b/tests/fixtures/issue_5/watcher/transport_disconnected.json new file mode 100644 index 0000000..74c7032 --- /dev/null +++ b/tests/fixtures/issue_5/watcher/transport_disconnected.json @@ -0,0 +1,37 @@ +{ + "schema_version": "1.0.0", + "scenario_id": "transport_disconnected", + "backend": "backend_agnostic", + "provenance": "simulated", + "description": "Herdr socket connection failure or freshness gap. Cached evidence invalidated; must reconnect and resnapshot.", + "dispatch_context": { + "job_id": "test-job-disconnect-01", + "attempt_id": 1, + "agent_session_uuid": "7d5700d0-bab1-4f65-9665-6b887396a9a6", + "pane_process_generation": "w2X:p1:1234:2026-09-06T00:00:00Z", + "dispatch_ack": true, + "execution_anchor_observed": true + }, + "timeline": [ + { + "collector_clock_id": "CLOCK_MONOTONIC", + "relative_ms": 0, + "source_kind": "herdr", + "source_provenance": "simulated", + "payload": { + "error": "connection_refused", + "transport_healthy": false + } + } + ], + "filesystem": { + "report_path": ".mam/jobs/test-job-disconnect-01/report-final.md", + "exists": false, + "manifest_committed": false + }, + "expected_policy": { + "decision": "hold_reconnect", + "reason": "transport connection failure; previous idle observations cannot be trusted", + "policy_version": "2.0.0" + } +}