From f91f28583462417c06113b757894ebca3f68084d Mon Sep 17 00:00:00 2001 From: Panopticon Agent Date: Tue, 29 Sep 2026 23:03:24 -0700 Subject: [PATCH 01/10] feat(workflows): update automatic Sol development and review models Default new 2119-auto-sol tasks to Claude Opus 5.5 and its first final reviewer to GPT-6.1 Sol. Preserve task overrides, the second reviewer, and test-honesty defaults. Update the existing specification and behavioral expectations for task creation and rendered review skills. Pin Codex images to 0.159.1: a same-account model probe is rejected by 0.144.4 but succeeds on 0.159.1. Verify both Linux release asset names, strict parsing of generated config, and real reviewer identity evidence. Keep historical auth-refresh claims explicitly tied to the older CLI. Validation: 209 focused tests; Ruff, formatting, mypy; clean-wheel smoke; fresh Fable review and four killed default/order mutations. Full suite: 3823 passed, 5 skipped, one native-Claude proxy fixture failure reproduced on unmodified HEAD. The formal gate still fails existing coverage findings; this local checkpoint is not release approval. Linux interactive hooks, resume and token refresh were not requalified on the new CLI. --- AGENTS.md | 3 +- specs/REQ-028-reviewable-2119-artifacts.md | 4 +++ src/panopticon/harnesses/codex.py | 6 ++-- src/panopticon/workflows/spec_2119.py | 4 ++- tests/container/test_reviewers.py | 3 +- .../test_workflow_image_layers.py | 2 +- tests/taskservice/test_api.py | 30 +++++++++++++++---- tests/workflows/test_spec_2119_artifacts.py | 2 +- ...st_spec_2119_review_contract_boundaries.py | 3 +- 9 files changed, 42 insertions(+), 15 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 23207ac..5a256e9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -303,7 +303,8 @@ on every PR (the same commands the Makefile wraps). skills/operations/hooks/MCP/system-prompt), and the launch `argv` (first-run vs resume). Selection resolves atomic harness/model pairs: task-explicit → an optional workflow pair → the repo's `default_harness` + opaque `default_model` (`model[:effort]`) → the app default. - A workflow declares both halves or neither, and all built-ins declare neither. An explicit + A workflow declares both halves or neither; `2119-auto-sol` defaults to + `claude` + `claude-opus-5-5`. An explicit task harness that differs from the winning pair drops that pair's model. The resolved opaque strings are recorded on the task, so later default changes never re-route it; model vocabulary belongs to the harness. Codex auth: `CODEX_API_KEY`/`CODEX_ACCESS_TOKEN` in the env-file diff --git a/specs/REQ-028-reviewable-2119-artifacts.md b/specs/REQ-028-reviewable-2119-artifacts.md index 492bd06..0697023 100644 --- a/specs/REQ-028-reviewable-2119-artifacts.md +++ b/specs/REQ-028-reviewable-2119-artifacts.md @@ -51,6 +51,10 @@ built-in workflows when no external workflow directory is present. 1. Every built-in 2119 workflow MUST direct test-honesty review to Sol, while `2119-human-spec` and `2119-auto-spec` use Fable plus Sol for final change review and `2119-auto-sol` uses Sol only for final change review. +2. `2119-auto-sol` MUST default its development launch pair to `claude` with +`claude-opus-5-5`, subject to the task override precedence in REQ-012. +3. `2119-auto-sol` MUST default its first final reviewer to `codex` with `gpt-6.1-sol`, +subject to the reviewer overrides in REQ-036. ### REQ-028.9: Actionable duplicate migration failure diff --git a/src/panopticon/harnesses/codex.py b/src/panopticon/harnesses/codex.py index f8ae51b..f835913 100644 --- a/src/panopticon/harnesses/codex.py +++ b/src/panopticon/harnesses/codex.py @@ -43,9 +43,9 @@ task_id_note, ) -#: The codex release the harness image layer installs — the version the config rendering and -#: auth behavior (symlink write-through, reload-before-refresh) were verified against. -CODEX_VERSION = "0.144.4" +#: The codex release the harness image layer installs. Config parsing and reviewer model +#: identity are verified on this version; auth-refresh observations above are from 0.144.4. +CODEX_VERSION = "0.159.1" #: The credential file codex expects under ``$CODEX_HOME``. AUTH_FILE = "auth.json" diff --git a/src/panopticon/workflows/spec_2119.py b/src/panopticon/workflows/spec_2119.py index 0ed5f75..2fbee1d 100644 --- a/src/panopticon/workflows/spec_2119.py +++ b/src/panopticon/workflows/spec_2119.py @@ -456,9 +456,11 @@ class Spec2119AutoSol(_Spec2119Workflow): name: ClassVar[str] = "2119-auto-sol" opt_in: ClassVar[bool] = True + default_harness: ClassVar[str] = "claude" + default_model: ClassVar[str] = "claude-opus-5-5" fable_reviews: ClassVar[bool] = False reviewers: ClassVar[tuple[ReviewerConfig, ReviewerConfig]] = ( - ReviewerConfig("codex", "gpt-5.6-sol"), + ReviewerConfig("codex", "gpt-6.1-sol"), ReviewerConfig("codex", "gpt-5.6-sol"), ) when_to_use: ClassVar[str] = ( diff --git a/tests/container/test_reviewers.py b/tests/container/test_reviewers.py index 9912f26..8989787 100644 --- a/tests/container/test_reviewers.py +++ b/tests/container/test_reviewers.py @@ -66,6 +66,7 @@ def _claude_payload(model: str, *, result: str | None = None) -> dict[str, Any]: def test_workflows_define_two_opaque_reviewer_pairs_and_sol_variant_uses_same_resolver() -> None: # 2119: REQ-036.1.1 + # 2119: REQ-028.8.3 workflows = _workflows() expected = { "2119-human-spec": ( @@ -77,7 +78,7 @@ def test_workflows_define_two_opaque_reviewer_pairs_and_sol_variant_uses_same_re ReviewerConfig("codex", "gpt-5.6-sol"), ), "2119-auto-sol": ( - ReviewerConfig("codex", "gpt-5.6-sol"), + ReviewerConfig("codex", "gpt-6.1-sol"), ReviewerConfig("codex", "gpt-5.6-sol"), ), } diff --git a/tests/sessionservice/test_workflow_image_layers.py b/tests/sessionservice/test_workflow_image_layers.py index 38915dd..90c7c68 100644 --- a/tests/sessionservice/test_workflow_image_layers.py +++ b/tests/sessionservice/test_workflow_image_layers.py @@ -19,7 +19,7 @@ def test_every_shipped_workflow_layer_matches_audited_content(tmp_path: Path) -> *) echo "unsupported architecture: $arch" >&2; exit 1 ;; \ esac; \ curl --fail --silent --show-error --location \ - "https://github.com/openai/codex/releases/download/rust-v0.144.4/codex-$triple.tar.gz" \ + "https://github.com/openai/codex/releases/download/rust-v0.159.1/codex-$triple.tar.gz" \ | tar --extract --gzip --directory /usr/local/bin; \ if [ -e "/usr/local/bin/codex-$triple" ]; then mv "/usr/local/bin/codex-$triple" /usr/local/bin/codex; fi; \ chmod 0755 /usr/local/bin/codex""" diff --git a/tests/taskservice/test_api.py b/tests/taskservice/test_api.py index e66a398..4769e67 100644 --- a/tests/taskservice/test_api.py +++ b/tests/taskservice/test_api.py @@ -18,6 +18,7 @@ from panopticon.taskservice.service import TaskService from panopticon.taskservice.store_sqlalchemy import SqlAlchemyStore from panopticon.workflows import Spike +from panopticon.workflows.spec_2119 import Spec2119AutoSol class _GatedWorkflow(Workflow): @@ -648,9 +649,23 @@ def test_repo_launch_pair_beats_app_defaults(client: TestClient) -> None: # 2119: REQ-012.2.1 -def test_workflow_launch_pair_beats_repo_pair(tmp_path: Path) -> None: +# 2119: REQ-028.8.2 +@pytest.mark.parametrize( + ("workflow", "repo_harness", "repo_model", "expected"), + [ + (_TunedWorkflow(), "claude", "opus:low", ("codex", "gpt-5.6-sol:high")), + (Spec2119AutoSol(), "codex", "gpt-5.6-sol", ("claude", "claude-opus-5-5")), + ], +) +def test_workflow_launch_pair_beats_repo_pair( + tmp_path: Path, + workflow: Workflow, + repo_harness: str, + repo_model: str, + expected: tuple[str, str], +) -> None: service = TaskService( - SqlAlchemyStore(), {"tuned": _TunedWorkflow()}, FilesystemArtifactStore(tmp_path) + SqlAlchemyStore(), {workflow.name: workflow}, FilesystemArtifactStore(tmp_path) ) asyncio.run(service.init()) asyncio.run( @@ -659,14 +674,17 @@ def test_workflow_launch_pair_beats_repo_pair(tmp_path: Path) -> None: id="r1", name="acme/widgets", git_url="https://x/r1.git", - default_harness="claude", - default_model="opus:low", + default_harness=repo_harness, + default_model=repo_model, + enabled_workflows=[workflow.name], ) ) ) with TestClient(create_app(service)) as tuned_client: - task = tuned_client.post("/tasks", json={"repo_id": "r1", "workflow": "tuned"}).json() - assert (task["harness"], task["starting_model"]) == ("codex", "gpt-5.6-sol:high") + response = tuned_client.post("/tasks", json={"repo_id": "r1", "workflow": workflow.name}) + assert response.status_code == 201 + task = response.json() + assert (task["harness"], task["starting_model"]) == expected # 2119: REQ-012.3.3 diff --git a/tests/workflows/test_spec_2119_artifacts.py b/tests/workflows/test_spec_2119_artifacts.py index 01b063e..7a98f29 100644 --- a/tests/workflows/test_spec_2119_artifacts.py +++ b/tests/workflows/test_spec_2119_artifacts.py @@ -103,7 +103,7 @@ + _VERIFIED_REVIEW_INSTRUCTIONS ) EXPECTED_SOL_ONLY_REVIEW_INSTRUCTIONS = ( - "Workflow reviewer defaults: `codex:gpt-5.6-sol, codex:gpt-5.6-sol`.\n\n" + "Workflow reviewer defaults: `codex:gpt-6.1-sol, codex:gpt-5.6-sol`.\n\n" + _VERIFIED_REVIEW_INSTRUCTIONS ) EXPECTED_DEFERRED_ISSUES_MERGE_INSTRUCTIONS = """## Before merging: file deferred-work issues diff --git a/tests/workflows/test_spec_2119_review_contract_boundaries.py b/tests/workflows/test_spec_2119_review_contract_boundaries.py index 685cca7..31a974e 100644 --- a/tests/workflows/test_spec_2119_review_contract_boundaries.py +++ b/tests/workflows/test_spec_2119_review_contract_boundaries.py @@ -12,7 +12,7 @@ EXPECTED_REVIEW_DEFAULTS = { "2119-human-spec": "Workflow reviewer defaults: `claude:claude-fable-5, codex:gpt-5.6-sol`.", "2119-auto-spec": "Workflow reviewer defaults: `claude:claude-fable-5, codex:gpt-5.6-sol`.", - "2119-auto-sol": "Workflow reviewer defaults: `codex:gpt-5.6-sol, codex:gpt-5.6-sol`.", + "2119-auto-sol": "Workflow reviewer defaults: `codex:gpt-6.1-sol, codex:gpt-5.6-sol`.", } EXPECTED_TRIAGE_END = """End the triage summary PR comment with a "Suggested placeholder issues" section. For each finding you rejected or deferred that is @@ -31,6 +31,7 @@ def _review_skill(workflow: Workflow) -> Skill: def test_review_models_are_pinned_independently_for_each_workflow() -> None: # 2119: REQ-028.8.1 + # 2119: REQ-028.8.3 registry = discover_workflows(_home_workflows=Path("/nonexistent")) assert set(EXPECTED_REVIEW_DEFAULTS) == set(WORKFLOW_NAMES) From 05c26279850b2619a1720464f8a67bdba26c6cdb Mon Sep 17 00:00:00 2001 From: Panopticon Agent Date: Tue, 27 Oct 2026 23:17:23 -0700 Subject: [PATCH 02/10] fix(codex): install companion tools with the pinned runtime Codex 0.159.1 can answer prompts as a standalone executable, but its default shell tool needs codex-code-mode-host. Installing only the main binary makes a task appear ready and then fail when it attempts real work. Install the complete official Linux package under /opt/codex, preserve its relative resources, and expose the entrypoint through a replaceable symlink. Check that the CLI and shell helper are executable before replacing the link. The layer remains idempotent when both harness and workflow tiers install it. Update the audited layer fixture and distinguish synthetic refresh validation from observations involving a real provider. Validation: 48 harness/layer tests; exact production layer built twice; missing/non-executable CLI and helper rejected; unprivileged ARM64 CLI/helper smoke; x86_64 CLI/helper smoke under emulation. Manual ARM64 qualification exercised shell execution, hooks, MCP handshake, model identity and interactive resume. Native refresh/reload used synthetic credentials and a loopback endpoint; real provider token rotation was not attempted. --- src/panopticon/harnesses/codex.py | 24 ++++++++++++------- .../test_workflow_image_layers.py | 10 ++++---- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/panopticon/harnesses/codex.py b/src/panopticon/harnesses/codex.py index f835913..861f9f2 100644 --- a/src/panopticon/harnesses/codex.py +++ b/src/panopticon/harnesses/codex.py @@ -20,7 +20,9 @@ env-file var (rendered into an api-key ``auth.json``), or a **``CODEX_ACCESS_TOKEN``** (ChatGPT Business/Enterprise workspace token, read by codex straight from the env). -Facts pinned against codex-cli 0.144.4 (config schema + observed behavior); see docs/auth.md. +Config, hooks, tools, and session resume are verified against codex-cli 0.159.1. Native +credential refresh and shared-file reload are verified with synthetic credentials; actual +provider refresh observations remain from 0.144.4. See docs/auth.md. """ from __future__ import annotations @@ -44,7 +46,7 @@ ) #: The codex release the harness image layer installs. Config parsing and reviewer model -#: identity are verified on this version; auth-refresh observations above are from 0.144.4. +#: identity are verified on this version; see the module notes for auth-validation scope. CODEX_VERSION = "0.159.1" #: The credential file codex expects under ``$CODEX_HOME``. @@ -189,9 +191,11 @@ def suggested_efforts(self, model: str | None = None) -> Sequence[tuple[str, str return (("low", "Low"), ("medium", "Medium"), ("high", "High"), ("xhigh", "X-high")) def image_layer(self) -> str: - """Install the pinned codex release: the statically-linked musl binary from GitHub - releases (no runtime deps — the base image needs no node). Runs as root (the base image's - build user); the binary is world-executable.""" + """Install the pinned Linux package with its companion tools and relative resources. + + The main executable alone cannot run default shell tools in recent Codex releases. + Preserve the package layout so sibling executables and bundled resources resolve. + """ return ( "RUN set -eux; \\\n" ' arch="$(uname -m)"; \\\n' @@ -200,11 +204,13 @@ def image_layer(self) -> str: ' aarch64) triple="aarch64-unknown-linux-musl" ;; \\\n' ' *) echo "unsupported architecture: $arch" >&2; exit 1 ;; \\\n' " esac; \\\n" + " mkdir --parents /opt/codex; \\\n" " curl --fail --silent --show-error --location \\\n" - f' "https://github.com/openai/codex/releases/download/rust-v{CODEX_VERSION}/codex-$triple.tar.gz" \\\n' - " | tar --extract --gzip --directory /usr/local/bin; \\\n" - ' if [ -e "/usr/local/bin/codex-$triple" ]; then mv "/usr/local/bin/codex-$triple" /usr/local/bin/codex; fi; \\\n' - " chmod 0755 /usr/local/bin/codex" + f' "https://github.com/openai/codex/releases/download/rust-v{CODEX_VERSION}/codex-package-$triple.tar.gz" \\\n' + " | tar --extract --gzip --directory /opt/codex; \\\n" + " test -x /opt/codex/bin/codex; \\\n" + " test -x /opt/codex/bin/codex-code-mode-host; \\\n" + " ln --symbolic --force /opt/codex/bin/codex /usr/local/bin/codex" ) def missing_auth(self, environ: Mapping[str, str], *, home: Path) -> str | None: diff --git a/tests/sessionservice/test_workflow_image_layers.py b/tests/sessionservice/test_workflow_image_layers.py index 90c7c68..278bfc2 100644 --- a/tests/sessionservice/test_workflow_image_layers.py +++ b/tests/sessionservice/test_workflow_image_layers.py @@ -18,11 +18,13 @@ def test_every_shipped_workflow_layer_matches_audited_content(tmp_path: Path) -> aarch64) triple="aarch64-unknown-linux-musl" ;; \ *) echo "unsupported architecture: $arch" >&2; exit 1 ;; \ esac; \ + mkdir --parents /opt/codex; \ curl --fail --silent --show-error --location \ - "https://github.com/openai/codex/releases/download/rust-v0.159.1/codex-$triple.tar.gz" \ - | tar --extract --gzip --directory /usr/local/bin; \ - if [ -e "/usr/local/bin/codex-$triple" ]; then mv "/usr/local/bin/codex-$triple" /usr/local/bin/codex; fi; \ - chmod 0755 /usr/local/bin/codex""" + "https://github.com/openai/codex/releases/download/rust-v0.159.1/codex-package-$triple.tar.gz" \ + | tar --extract --gzip --directory /opt/codex; \ + test -x /opt/codex/bin/codex; \ + test -x /opt/codex/bin/codex-code-mode-host; \ + ln --symbolic --force /opt/codex/bin/codex /usr/local/bin/codex""" # Exact audited layer bytes: an altered or newly shipped layer cannot evade this gate by # spelling, downloading, or renaming the gh executable differently. expected = { From 70f1f49d39575be4d490ef31a9a75204fdafb254 Mon Sep 17 00:00:00 2001 From: Panopticon Agent Date: Tue, 27 Oct 2026 23:17:23 -0700 Subject: [PATCH 03/10] docs(workflows): explain credentials for the Opus and Sol workflow The 2119-auto-sol workflow now starts development on Claude and performs its reviews on Codex. Make both credential requirements visible in the workflow picker so selecting it does not hide a second harness prerequisite. Correct the shared workflow default-pair comment: built-in workflows may now supply a tuned pair. This changes descriptive guidance only; task selection, explicit overrides and persisted task choices keep their existing behavior. Validation: Ruff, strict mypy and independent code review. --- src/panopticon/core/workflow.py | 2 +- src/panopticon/workflows/spec_2119.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/panopticon/core/workflow.py b/src/panopticon/core/workflow.py index 75af00e..a42d562 100644 --- a/src/panopticon/core/workflow.py +++ b/src/panopticon/core/workflow.py @@ -113,7 +113,7 @@ class Workflow(ABC): #: ``credential_dir`` field, and ordinary task workflows retain no repo-write authority. configures_repo_credentials: ClassVar[bool] = False #: Optional tuned launch pair. Workflows must declare both values or neither; discovery also - #: checks that the harness exists. Built-ins deliberately leave the pair unset. + #: checks that the harness exists. A built-in may set a pair to tune its default agent. default_harness: ClassVar[str | None] = None default_model: ClassVar[str | None] = None #: Optional tuned launch pair for a governed review task (ADR 0014). Like the default launch diff --git a/src/panopticon/workflows/spec_2119.py b/src/panopticon/workflows/spec_2119.py index 2fbee1d..da13f53 100644 --- a/src/panopticon/workflows/spec_2119.py +++ b/src/panopticon/workflows/spec_2119.py @@ -464,7 +464,8 @@ class Spec2119AutoSol(_Spec2119Workflow): ReviewerConfig("codex", "gpt-5.6-sol"), ) when_to_use: ClassVar[str] = ( - "Spec-driven 2119 lifecycle with automatic specification and Sol-only reviews." + "Spec-driven 2119 lifecycle with Claude Opus 5.5 development and Codex Sol reviews; " + "requires Claude and Codex credentials." ) class Specifying(_Specifying): From dee8d3be4b4963e0cb9e0a99afdb5780293fd7ff Mon Sep 17 00:00:00 2001 From: Panopticon Agent Date: Tue, 27 Oct 2026 23:17:23 -0700 Subject: [PATCH 04/10] test(tmux): verify clipboard gestures through an isolated terminal String assertions alone could accept broken mouse dispatch or a binding that never sent selected bytes to the clipboard command. Exercise actual SGR drag and double-click input through a PTY in both emacs and vi copy modes. Require exact selected bytes in the paste buffer and capture command, and prove drag copy happens on release. Use unique socket directories, temporary HOME/config paths and a clipboard capture command. Verify the production session constructor excludes the operator config with a negative control, repairs existing defaults, and resolves clipboard precedence on Darwin and other supported platforms. Validation: 32 focused tests, 45 repeated gesture/isolation cases, and six narrow in-memory mutations rejected. Fresh independent requirement reviews confirm the observable clipboard and configuration contracts. --- tests/sessionservice/test_tmux_defaults.py | 398 +++++++++++++-------- 1 file changed, 255 insertions(+), 143 deletions(-) diff --git a/tests/sessionservice/test_tmux_defaults.py b/tests/sessionservice/test_tmux_defaults.py index 5f0ac62..0921656 100644 --- a/tests/sessionservice/test_tmux_defaults.py +++ b/tests/sessionservice/test_tmux_defaults.py @@ -1,18 +1,27 @@ """REQ-030: panopticon's shipped tmux server defaults (mouse, scrollback, clipboard wiring) for -its dedicated ``-L panopticon`` socket. Pure-function tests need no tmux; the tests at the bottom -that source the generated config into a real tmux server (skipped without one) are the ones that -actually prove the config text is valid tmux syntax and lands correctly on a fresh socket.""" +its dedicated ``-L panopticon`` socket. Real-tmux tests exercise production startup and actual +mouse gestures through a PTY, capturing clipboard bytes without touching the operator clipboard. +Pure-function tests cover config generation and clipboard-tool resolution.""" from __future__ import annotations import os +import pty +import select +import shlex import shutil import subprocess import tempfile +import termios +import time +from collections.abc import Iterator +from contextlib import contextmanager +from dataclasses import dataclass from pathlib import Path import pytest +from panopticon.sessionservice import tmux_defaults from panopticon.sessionservice.tmux_defaults import ( HISTORY_LIMIT, clipboard_tool, @@ -30,6 +39,10 @@ def _which(present: set[str]): # 2119: REQ-030.4.1 def test_clipboard_tool_selects_pbcopy_on_darwin_when_present() -> None: assert clipboard_tool(platform="darwin", which=_which({"pbcopy"})) == "pbcopy" + assert ( + clipboard_tool(platform="darwin", which=_which({"pbcopy", "wl-copy", "xclip", "xsel"})) + == "pbcopy" + ) # 2119: REQ-030.4.1 @@ -55,31 +68,39 @@ def test_clipboard_tool_selects_nothing_on_darwin_without_pbcopy() -> None: # 2119: REQ-030.4.3 -def test_clipboard_tool_selects_wl_copy_on_linux_when_present() -> None: - assert clipboard_tool(platform="linux", which=_which({"wl-copy"})) == "wl-copy" +@pytest.mark.parametrize("platform", ["linux", "freebsd14"]) +def test_clipboard_tool_selects_wl_copy_on_linux_when_present(platform: str) -> None: + assert clipboard_tool(platform=platform, which=_which({"wl-copy"})) == "wl-copy" # wl-copy wins even when the other candidates are also present - assert clipboard_tool(platform="linux", which=_which({"wl-copy", "xclip", "xsel"})) == "wl-copy" + assert ( + clipboard_tool(platform=platform, which=_which({"wl-copy", "xclip", "xsel"})) == "wl-copy" + ) # 2119: REQ-030.4.4 -def test_clipboard_tool_falls_back_to_xclip_without_wl_copy() -> None: - assert clipboard_tool(platform="linux", which=_which({"xclip"})) == "xclip -selection clipboard" +@pytest.mark.parametrize("platform", ["linux", "freebsd14"]) +def test_clipboard_tool_falls_back_to_xclip_without_wl_copy(platform: str) -> None: assert ( - clipboard_tool(platform="linux", which=_which({"xclip", "xsel"})) + clipboard_tool(platform=platform, which=_which({"xclip"})) == "xclip -selection clipboard" + ) + assert ( + clipboard_tool(platform=platform, which=_which({"xclip", "xsel"})) == "xclip -selection clipboard" ) # 2119: REQ-030.4.5 -def test_clipboard_tool_falls_back_to_xsel_without_wl_copy_or_xclip() -> None: - assert clipboard_tool(platform="linux", which=_which({"xsel"})) == "xsel --clipboard --input" +@pytest.mark.parametrize("platform", ["linux", "freebsd14"]) +def test_clipboard_tool_falls_back_to_xsel_without_wl_copy_or_xclip(platform: str) -> None: + assert clipboard_tool(platform=platform, which=_which({"xsel"})) == "xsel --clipboard --input" # 2119: REQ-030.4.6 -def test_clipboard_tool_selects_nothing_on_linux_with_no_candidate_present() -> None: - assert clipboard_tool(platform="linux", which=_which(set())) is None +@pytest.mark.parametrize("platform", ["linux", "freebsd14"]) +def test_clipboard_tool_selects_nothing_on_linux_with_no_candidate_present(platform: str) -> None: + assert clipboard_tool(platform=platform, which=_which(set())) is None # a darwin-only tool present doesn't leak into the non-darwin resolution - assert clipboard_tool(platform="linux", which=_which({"pbcopy"})) is None + assert clipboard_tool(platform=platform, which=_which({"pbcopy"})) is None # 2119: REQ-030.1.1 @@ -172,158 +193,249 @@ def test_write_default_config_overwrites_via_atomic_rename_leaving_no_temp_files assert list(tmp_path.iterdir()) == [path] # only the final file — no leftover .tmp scratch -# -- integration: a real tmux server, from a genuinely fresh socket ----------------- +# -- integration: real tmux, isolated from operator sessions and clipboard --------- _HAVE_TMUX = bool(shutil.which("tmux")) -# 2119: REQ-030.1.1 -# 2119: REQ-030.3.1 -@pytest.mark.skipif(not _HAVE_TMUX, reason="needs tmux") -def test_production_new_session_repairs_defaults_on_an_existing_server(tmp_path: Path) -> None: - del tmp_path - tmux_tmpdir = Path(tempfile.mkdtemp(prefix="pn-tmux-", dir="/tmp")) - tmux_tmpdir.chmod(0o700) - environment = {"PATH": os.environ["PATH"], "TMUX_TMPDIR": str(tmux_tmpdir)} - socket = "existing-defaults" - - def tmux(*arguments: str) -> subprocess.CompletedProcess[str]: +@dataclass +class _TmuxServer: + root: Path + environment: dict[str, str] + socket: str = "defaults" + + def run(self, *arguments: str, check: bool = True) -> subprocess.CompletedProcess[bytes]: return subprocess.run( - ["tmux", "-L", socket, *arguments], + ["tmux", "-L", self.socket, *arguments], capture_output=True, - text=True, - env=environment, + env=self.environment, + check=check, + timeout=5, ) - try: - assert tmux("new-session", "-d", "-s", "keeper", "sleep", "30").returncode == 0 - assert tmux("set-option", "-g", "mouse", "off").returncode == 0 - assert tmux("set-option", "-g", "history-limit", "123").returncode == 0 - assert tmux("set-option", "-g", "set-clipboard", "off").returncode == 0 - assert tmux("unbind-key", "-T", "root", "DoubleClick1Pane").returncode == 0 - - created = tmux(*new_session_argv(socket, "-d", "-s", "corrected", "sleep", "30")) - assert created.returncode == 0, created.stderr - assert tmux("show-options", "-g", "mouse").stdout.strip() == "mouse on" - assert tmux("show-options", "-g", "set-clipboard").stdout.strip() == "set-clipboard on" - assert ( - tmux("display-message", "-t", "corrected", "-p", "#{history_limit}").stdout.strip() - == HISTORY_LIMIT - ) - binding = tmux("list-keys", "-T", "root").stdout - assert any( - "DoubleClick1Pane" in line and "select-word" in line for line in binding.splitlines() + def create(self, name: str = "test", command: str = "sleep 30") -> None: + self.run(*new_session_argv(self.socket, "-d", "-s", name, command)) + + +@pytest.fixture +def tmux_server(monkeypatch: pytest.MonkeyPatch) -> Iterator[_TmuxServer]: + # Short, unique socket paths also fit Darwin's Unix-domain socket length limit. + with tempfile.TemporaryDirectory(prefix="pn-tmux-", dir="/tmp") as directory: + root = Path(directory) + environment = { + "PATH": os.environ["PATH"], + "HOME": directory, + "XDG_CONFIG_HOME": directory, + "TMUX_TMPDIR": directory, + "TERM": "xterm-256color", + } + monkeypatch.setattr( + tmux_defaults, "default_config_path", lambda socket, **_: root / f"{socket}.conf" ) + # Never invoke the operator's real clipboard tools. Individual copy tests replace this + # dependency with a capture command; the constructor/config/bindings remain production. + monkeypatch.setattr(tmux_defaults, "clipboard_tool", lambda **_: None) + server = _TmuxServer(root, environment) + try: + yield server + finally: + server.run("kill-server", check=False) + + +@contextmanager +def _attached_terminal(server: _TmuxServer) -> Iterator[int]: + master, slave = pty.openpty() + termios.tcsetwinsize(slave, (24, 80)) + client = subprocess.Popen( + ["tmux", "-L", server.socket, "attach-session", "-t", "test"], + stdin=slave, + stdout=slave, + stderr=slave, + env=server.environment, + ) + os.close(slave) + try: + # Wait for tmux to enable SGR mouse reporting and paint the text before clicking. + output = bytearray() + deadline = time.monotonic() + 5 + while time.monotonic() < deadline: + if select.select([master], [], [], 0.02)[0]: + output.extend(os.read(master, 65536)) + if b"\x1b[?1006h" in output and b"alpha bravo charlie" in output: + break + else: + pytest.fail(f"tmux client did not become ready: {bytes(output)!r}") + yield master finally: - tmux("kill-server") - shutil.rmtree(tmux_tmpdir) + # Only our attached client and isolated server are stopped. OSC 52 remains inside this + # PTY, so even no-tool copying cannot change the terminal application's clipboard. + client.terminate() + try: + client.wait(timeout=5) + finally: + if client.poll() is None: + client.kill() + client.wait(timeout=5) + os.close(master) + + +def _exercise_mouse_copy( + server: _TmuxServer, *, mode: str, gesture: str, capture: Path | None +) -> None: + server.create(command="printf 'alpha bravo charlie\\n'; sleep 30") + server.run("set-window-option", "-t", "test", "mode-keys", mode) + # A stale or empty buffer cannot accidentally satisfy the byte-for-byte assertion. + server.run("set-buffer", "previous-buffer") + with _attached_terminal(server) as terminal: + if gesture == "drag": + # SGR coordinates are one-based. Vi includes its endpoint; emacs excludes it. + # Both gestures therefore select exactly the five letters at columns 7 through 11. + endpoint = 11 if mode == "vi" else 12 + os.write(terminal, f"\x1b[<0;7;1M\x1b[<32;8;1M\x1b[<32;{endpoint};1M".encode()) + deadline = time.monotonic() + 5 + while time.monotonic() < deadline: + if ( + server.run("display-message", "-t", "test", "-p", "#{pane_in_mode}").stdout + == b"1\n" + ): + break + time.sleep(0.02) + else: + pytest.fail("mouse drag did not enter copy-mode") + assert server.run("save-buffer", "-").stdout == b"previous-buffer" + if capture is not None: + assert not capture.exists(), "copy must happen on release" + os.write(terminal, f"\x1b[<0;{endpoint};1m".encode()) + else: + # Two press/release pairs at column 9, within bravo. Actual mouse input exercises + # root DoubleClick1Pane dispatch and the complete chained binding. + os.write(terminal, b"\x1b[<0;9;1M\x1b[<0;9;1m\x1b[<0;9;1M\x1b[<0;9;1m") + deadline = time.monotonic() + 5 + while time.monotonic() < deadline: + if select.select([terminal], [], [], 0.02)[0]: + os.read(terminal, 65536) + buffer = server.run("save-buffer", "-").stdout + mode_active = server.run( + "display-message", "-t", "test", "-p", "#{pane_in_mode}" + ).stdout + captured = capture.read_bytes() if capture is not None and capture.exists() else None + if ( + buffer == b"bravo" + and mode_active == b"0\n" + and (capture is None or captured == b"bravo") + ): + break + assert buffer == b"bravo" + assert mode_active == b"0\n" + if capture is not None: + assert captured == b"bravo" + + +# 2119: REQ-030.2.1 +# 2119: REQ-030.2.2 +# 2119: REQ-030.2.3 +# 2119: REQ-030.2.4 +@pytest.mark.skipif(not _HAVE_TMUX, reason="needs tmux") +@pytest.mark.parametrize("mode", ["emacs", "vi"]) +@pytest.mark.parametrize("gesture", ["drag", "double-click"]) +def test_real_mouse_gesture_copies_exact_bytes_to_clipboard_tool( + tmux_server: _TmuxServer, monkeypatch: pytest.MonkeyPatch, mode: str, gesture: str +) -> None: + capture = tmux_server.root / "clipboard-stdin" + monkeypatch.setattr( + tmux_defaults, "clipboard_tool", lambda **_: f"/bin/cat > {shlex.quote(str(capture))}" + ) + _exercise_mouse_copy(tmux_server, mode=mode, gesture=gesture, capture=capture) + + +# 2119: REQ-030.2.5 +@pytest.mark.skipif(not _HAVE_TMUX, reason="needs tmux") +@pytest.mark.parametrize("mode", ["emacs", "vi"]) +@pytest.mark.parametrize("gesture", ["drag", "double-click"]) +def test_real_mouse_gesture_without_clipboard_tool_copies_exact_paste_buffer( + tmux_server: _TmuxServer, mode: str, gesture: str +) -> None: + _exercise_mouse_copy(tmux_server, mode=mode, gesture=gesture, capture=None) + + +# 2119: REQ-030.1.1 +# 2119: REQ-030.3.1 +@pytest.mark.skipif(not _HAVE_TMUX, reason="needs tmux") +def test_production_new_session_repairs_defaults_on_an_existing_server( + tmux_server: _TmuxServer, +) -> None: + tmux = tmux_server.run + tmux("new-session", "-d", "-s", "keeper", "sleep", "30") + tmux("set-option", "-g", "mouse", "off") + tmux("set-option", "-g", "history-limit", "123") + tmux("set-option", "-g", "set-clipboard", "off") + tmux("unbind-key", "-T", "root", "DoubleClick1Pane") + + tmux_server.create("corrected") + assert tmux("show-options", "-g", "mouse").stdout.strip() == b"mouse on" + assert tmux("show-options", "-g", "set-clipboard").stdout.strip() == b"set-clipboard on" + assert ( + tmux("display-message", "-t", "corrected", "-p", "#{history_limit}").stdout.strip() + == HISTORY_LIMIT.encode() + ) + binding = tmux("list-keys", "-T", "root").stdout + assert any( + b"DoubleClick1Pane" in line and b"select-word" in line for line in binding.splitlines() + ) # 2119: REQ-030.1.1 # 2119: REQ-030.1.2 +# 2119: REQ-030.1.3 # 2119: REQ-030.2.3 # 2119: REQ-030.2.4 # 2119: REQ-030.3.1 @pytest.mark.skipif(not _HAVE_TMUX, reason="needs tmux") -def test_config_loads_correctly_via_dash_f_on_a_genuinely_fresh_socket(tmp_path: Path) -> None: - # This is the property unit tests (which never touch a real tmux binary) can't prove: that the - # generated config text is valid tmux syntax, that `-f` on a `new-session` call is what - # actually makes a brand-new socket's server durably pick up these defaults (separate `tmux -L - # sock set-option ...` calls do NOT — tmux's exit-empty tears a sessionless server back down - # between client invocations), and that the double-click binding's chained sub-commands land as - # ONE bound action rather than three immediate top-level commands (which bare `;` tokens on a - # plain CLI argv would do). - socket = "panopticon-tmux-defaults-itest" - subprocess.run(["tmux", "-L", socket, "kill-server"], capture_output=True) - try: - path = write_default_config(socket, directory=tmp_path, clipboard="cat") - result = subprocess.run( - ["tmux", "-L", socket, "-f", str(path), "new-session", "-d", "-s", "t1", "sleep", "30"], - capture_output=True, - text=True, - ) - assert result.returncode == 0, result.stderr - - def show(option: str) -> str: - return subprocess.run( - ["tmux", "-L", socket, "show-options", "-g", option], - capture_output=True, - text=True, - ).stdout.strip() - - assert show("mouse") == "mouse on" - assert show("history-limit") == f"history-limit {HISTORY_LIMIT}" - assert show("set-clipboard") == "set-clipboard on" - - # not just declared globally — actually effective on the session `-f` just created and its - # first pane specifically (REQ-030.1: "a session created..."/"a pane created...") - def effective(option: str) -> str: - return subprocess.run( - ["tmux", "-L", socket, "show-options", "-A", "-t", "t1", option], - capture_output=True, - text=True, - ).stdout.strip() - - assert effective("mouse") == "mouse* on" - assert effective("set-clipboard") == "set-clipboard on" - pane_history_limit = subprocess.run( - ["tmux", "-L", socket, "display-message", "-t", "t1", "-p", "#{history_limit}"], - capture_output=True, - text=True, - ).stdout.strip() - assert pane_history_limit == HISTORY_LIMIT - - keys = subprocess.run( - ["tmux", "-L", socket, "list-keys", "-T", "root"], capture_output=True, text=True - ).stdout - double_click = next(line for line in keys.splitlines() if "DoubleClick1Pane" in line) - # all three chained sub-commands present on the SAME binding line — proves they're bound - # together as one action, not split into separate immediate top-level commands - assert "copy-mode" in double_click - assert "select-word" in double_click - assert "copy-pipe-and-cancel" in double_click - finally: - subprocess.run(["tmux", "-L", socket, "kill-server"], capture_output=True) +def test_config_loads_correctly_via_production_constructor_on_a_fresh_socket( + tmux_server: _TmuxServer, monkeypatch: pytest.MonkeyPatch +) -> None: + monkeypatch.setattr(tmux_defaults, "clipboard_tool", lambda **_: "cat") + tmux_server.create() + tmux = tmux_server.run + assert tmux("show-options", "-g", "mouse").stdout.strip() == b"mouse on" + assert ( + tmux("show-options", "-g", "history-limit").stdout.strip() + == f"history-limit {HISTORY_LIMIT}".encode() + ) + assert tmux("show-options", "-g", "set-clipboard").stdout.strip() == b"set-clipboard on" + assert tmux("show-options", "-A", "-t", "test", "mouse").stdout.strip() == b"mouse* on" + assert ( + tmux("show-options", "-A", "-t", "test", "set-clipboard").stdout.strip() + == b"set-clipboard on" + ) + assert ( + tmux("display-message", "-t", "test", "-p", "#{history_limit}").stdout.strip() + == HISTORY_LIMIT.encode() + ) + keys = tmux("list-keys", "-T", "root").stdout + double_click = next(line for line in keys.splitlines() if b"DoubleClick1Pane" in line) + assert b"copy-mode" in double_click + assert b"select-word" in double_click + assert b"copy-pipe-and-cancel" in double_click # 2119: REQ-030.5.2 @pytest.mark.skipif(not _HAVE_TMUX, reason="needs tmux") -def test_dash_f_skips_the_operators_own_tmux_conf( - tmp_path: Path, monkeypatch: pytest.MonkeyPatch +def test_production_constructor_skips_the_operators_own_tmux_conf( + tmux_server: _TmuxServer, ) -> None: - fake_home = tmp_path / "home" - fake_home.mkdir() - (fake_home / ".tmux.conf").write_text('set-option -g status-left "OPERATORS-OWN-CONFIG"\n') - monkeypatch.setenv("HOME", str(fake_home)) - socket = "panopticon-tmux-isolation-itest" - control_socket = "panopticon-tmux-isolation-itest-control" - subprocess.run(["tmux", "-L", socket, "kill-server"], capture_output=True) - subprocess.run(["tmux", "-L", control_socket, "kill-server"], capture_output=True) + (tmux_server.root / ".tmux.conf").write_text( + 'set-option -g status-left "OPERATORS-OWN-CONFIG"\n' + ) + control = _TmuxServer(tmux_server.root, tmux_server.environment, socket="control") try: - # negative control: without `-f`, the fake HOME/.tmux.conf IS eligible to load — proves the - # marker would actually appear if `-f` weren't suppressing it, not that it was never reachable - subprocess.run( - ["tmux", "-L", control_socket, "new-session", "-d", "-s", "t1", "sleep", "30"], - check=True, - ) - control_status_left = subprocess.run( - ["tmux", "-L", control_socket, "show-options", "-g", "status-left"], - capture_output=True, - text=True, - ).stdout.strip() - assert "OPERATORS-OWN-CONFIG" in control_status_left - - path = write_default_config(socket, directory=tmp_path, clipboard=None) - subprocess.run( - ["tmux", "-L", socket, "-f", str(path), "new-session", "-d", "-s", "t1", "sleep", "30"], - check=True, + # Negative control proves the fake operator config is discoverable on this tmux build. + control.run("new-session", "-d", "-s", "control", "sleep", "30") + assert b"OPERATORS-OWN-CONFIG" in control.run("show-options", "-g", "status-left").stdout + tmux_server.create() + assert ( + b"OPERATORS-OWN-CONFIG" + not in tmux_server.run("show-options", "-g", "status-left").stdout ) - status_left = subprocess.run( - ["tmux", "-L", socket, "show-options", "-g", "status-left"], - capture_output=True, - text=True, - ).stdout.strip() - assert "OPERATORS-OWN-CONFIG" not in status_left finally: - subprocess.run(["tmux", "-L", control_socket, "kill-server"], capture_output=True) - subprocess.run(["tmux", "-L", socket, "kill-server"], capture_output=True) + control.run("kill-server", check=False) From 91de4a1a7fe00daae188d0bb4da0cd8d8100a632 Mon Sep 17 00:00:00 2001 From: Panopticon Agent Date: Tue, 27 Oct 2026 23:17:23 -0700 Subject: [PATCH 05/10] test(auth): cover credential leakage and encoded scope boundaries Capture authentication logs at DEBUG before accepted and rejected requests so low-level token leakage cannot pass unnoticed. Compare forbidden repo PATCH fields against the complete request schema, reject malformed values and both terminal setup states, and verify persistent repo state after every denial. Exercise encoded REST targets and real MCP resource requests across self, descendant, unrelated and missing tasks. Assert the authenticated subject is fixed by its capability, normalized targets are scoped correctly, and unsupported encoded forms fail closed without changing stored content. Validation: 247 focused tests, five repetitions of the changed cases and four narrow in-memory mutations rejected. Fresh independent Fable review passed all 38 affected credential-scope requirements. No authorization behavior or credential format changed. --- .../test_credential_scoping_spec.py | 246 +++++++++++++++++- 1 file changed, 234 insertions(+), 12 deletions(-) diff --git a/tests/taskservice/test_credential_scoping_spec.py b/tests/taskservice/test_credential_scoping_spec.py index 4de4be0..6d44c63 100644 --- a/tests/taskservice/test_credential_scoping_spec.py +++ b/tests/taskservice/test_credential_scoping_spec.py @@ -27,7 +27,7 @@ from panopticon.core.models import Repo, Responsibility, Skill from panopticon.core.state import Complete, InitialState, State from panopticon.core.workflow import Workflow -from panopticon.taskservice.api import create_app +from panopticon.taskservice.api import RepoPatchIn, create_app from panopticon.taskservice.artifacts_fs import FilesystemArtifactStore from panopticon.taskservice.auth import derive_task_capability, load_client_token from panopticon.taskservice.auth_scope import AuthorizationClass @@ -2119,8 +2119,10 @@ def test_task_capability_rejects_non_object_json_without_crashing(tmp_path: Path assert (mcp.status_code, mcp.json()) == (403, SCOPE_FAILURE) +@pytest.mark.parametrize("encoded_rest_target", [False, True]) def test_rest_and_mcp_resolve_equivalent_actions_to_identical_scope_decisions( tmp_path: Path, + encoded_rest_target: bool, ) -> None: # 2119: REQ-048.8.1 with _client(tmp_path) as client: @@ -2148,6 +2150,24 @@ def test_rest_and_mcp_resolve_equivalent_actions_to_identical_scope_decisions( (("GET", "/tasks/{task_id}/artifacts"), ("tool", "list_artifacts")), (("GET", "/tasks/{task_id}/artifacts/{name}"), ("resource", "artifact")), ] + payloads = { + "get_task": {}, + "set_slug": {"slug": "encoded"}, + "set_url": {"url": "https://example.test/encoded"}, + "set_tokens_used": {"tokens_used": 1}, + "set_token_estimate": {"token_estimate": 2}, + "apply_operation": {"operation": "advance"}, + "set_state": {"state": "COMPLETE"}, + "resolve_responsibility": {"key": "ready", "status": "met"}, + "set_turn": {"turn": "agent"}, + "set_blocked": {"blocked": True}, + "set_attention": {"attention": True}, + "set_dependencies": {"dep_ids": []}, + "put_artifact": {"name": "plan.md", "content": "encoded"}, + "list_artifacts": {}, + "artifact": {}, + } + assert set(payloads) == {surface[1] for _, surface in pairs} classified = policy.classified_surfaces() equivalent_mcp = {surface for _, surface in pairs} assert equivalent_mcp == classified.mcp_surfaces_with_rest_equivalents @@ -2184,7 +2204,7 @@ def test_rest_and_mcp_resolve_equivalent_actions_to_identical_scope_decisions( "method": "tools/call", "params": { "name": mcp_surface[1], - "arguments": {"task_id": target}, + "arguments": {"task_id": target, **payloads[mcp_surface[1]]}, }, } else: @@ -2198,6 +2218,28 @@ def test_rest_and_mcp_resolve_equivalent_actions_to_identical_scope_decisions( assert rest.subject_task_id == subject["id"] assert rest.target_task_id == target assert mcp == rest + if encoded_rest_target: + encoded_target = "".join(f"%{byte:02X}" for byte in str(target).encode()) + encoded_path = concrete_path.replace( + f"/tasks/{target}", f"/tasks/{encoded_target}" + ) + response = client.request( + rest_surface[0], + encoded_path, + headers=_bearer(_task_token(subject["id"])), + json=payloads[mcp_surface[1]], + ) + # Scope precedes workflow/argument validation. A permitted action may + # still fail those later checks (for example a missing responsibility). + assert (response.status_code == 403) is (not mcp.allowed), ( + rest_surface, + target, + response.text, + ) + if not mcp.allowed: + assert response.json() == SCOPE_FAILURE + else: + assert response.status_code in {200, 204, 400, 404, 409, 422} def test_every_task_targeted_mcp_surface_uses_capability_subject_and_decoded_target( @@ -2252,6 +2294,141 @@ def test_every_task_targeted_mcp_surface_uses_capability_subject_and_decoded_tar assert (response.status_code == 403) is denied +@pytest.mark.parametrize("relation", ["self", "child", "grandchild", "unrelated", "missing"]) +def test_encoded_rest_targets_and_mcp_resources_preserve_authenticated_subject( + tmp_path: Path, relation: str +) -> None: + # 2119: REQ-048.8.1 + # 2119: REQ-048.8.2 + with _client(tmp_path) as client: + subject = _create_task(client, workflow="orchestrator") + child = _create_task(client, governor_task_id=str(subject["id"])) + grandchild = _create_task(client, governor_task_id=str(child["id"])) + unrelated = _create_task(client) + targets = { + "self": subject["id"], + "child": child["id"], + "grandchild": grandchild["id"], + "unrelated": unrelated["id"], + "missing": "missing-task", + } + target = str(targets[relation]) + allowed = relation in {"self", "child", "grandchild"} + token = _task_token(subject["id"]) + headers = _bearer(token) + fleet = _bearer(WRITE_TOKEN) + for task in (subject, child, grandchild, unrelated): + seeded = client.put( + f"/tasks/{task['id']}/artifacts/plan.md", + headers=fleet, + content=f"artifact-for-{task['id']}".encode(), + ) + assert seeded.status_code == 204 + before = client.get("/tasks", headers=fleet).json() + # REST path components are decoded by ASGI. MCP tool JSON is already decoded. + encoded_target = "".join(f"%{byte:02X}" for byte in target.encode()) + rest_task = client.get(f"/tasks/{encoded_target}", headers=headers) + tool_request = { + "jsonrpc": "2.0", + "id": 2, + "method": "tools/call", + "params": {"name": "get_task", "arguments": {"task_id": target}}, + } + policy = client.app.state.credential_scope_policy + tool_decision = policy.authorize_mcp(token, tool_request) + assert tool_decision.subject_task_id == subject["id"] + assert tool_decision.target_task_id == target + assert tool_decision.allowed is allowed + if allowed: + assert rest_task.status_code == 200 + assert rest_task.json()["id"] == target + else: + assert (rest_task.status_code, rest_task.json()) == (403, SCOPE_FAILURE) + + # The SDK resolves encoded dot segments, but retains ordinary encoded task-id + # characters. Exercise both representations through the real mounted MCP app. + mcp_headers = {**headers, "Accept": "application/json, text/event-stream"} + initialized = client.post( + "/mcp", + headers=mcp_headers, + json={ + "jsonrpc": "2.0", + "id": 1, + "method": "initialize", + "params": { + "protocolVersion": "2025-06-18", + "capabilities": {}, + "clientInfo": {"name": "scope-test", "version": "1"}, + }, + }, + ) + assert initialized.status_code == 200 + if session_id := initialized.headers.get("mcp-session-id"): + mcp_headers["Mcp-Session-Id"] = session_id + notified = client.post( + "/mcp", + headers=mcp_headers, + json={"jsonrpc": "2.0", "method": "notifications/initialized"}, + ) + assert notified.status_code == 202 + + def rpc_body(response: httpx.Response) -> dict[str, object]: + if "text/event-stream" in response.headers.get("content-type", ""): + return json.loads( + next( + line[5:].strip() + for line in response.text.splitlines() + if line.startswith("data:") + ) + ) + return response.json() + + tool_response = client.post("/mcp", headers=mcp_headers, json=tool_request) + if allowed: + assert tool_response.status_code == 200 + result = rpc_body(tool_response)["result"] + assert result["isError"] is False + assert json.loads(result["content"][0]["text"])["id"] == target + else: + assert (tool_response.status_code, tool_response.json()) == (403, SCOPE_FAILURE) + + rest = client.get(f"/tasks/{encoded_target}/artifacts/%70lan.md", headers=headers) + normalized_uri = ( + f"panopticon://tasks/{subject['id']}/artifacts/%2e%2e/%2E%2E/{target}/artifacts/plan.md" + ) + for uri, expected_target, expected_allowed in ( + (normalized_uri, target, allowed), + (f"panopticon://tasks/{encoded_target}/artifacts/plan.md", encoded_target, False), + (f"task://{encoded_target}/artifacts/plan.md", encoded_target, False), + (f"panopticon://tasks/{target}/artifacts/plan%2Fextra.md", "", False), + ): + request = { + "jsonrpc": "2.0", + "id": 3, + "method": "resources/read", + "params": {"uri": uri}, + } + decision = policy.authorize_mcp(token, request) + assert decision.subject_task_id == subject["id"] + assert decision.target_task_id == expected_target + assert decision.allowed is expected_allowed + response = client.post("/mcp", headers=mcp_headers, json=request) + if expected_allowed: + assert rest.status_code == response.status_code == 200 + assert rest.content == f"artifact-for-{target}".encode() + contents = rpc_body(response)["result"]["contents"] + assert len(contents) == 1 + assert contents[0]["text"].encode() == rest.content + else: + assert (response.status_code, response.json()) == (403, SCOPE_FAILURE) + if uri == normalized_uri: + assert (rest.status_code, rest.json()) == (403, SCOPE_FAILURE) + assert client.get("/tasks", headers=fleet).json() == before + for task in (subject, child, grandchild, unrelated): + stored = client.get(f"/tasks/{task['id']}/artifacts/plan.md", headers=fleet) + assert stored.content == f"artifact-for-{task['id']}".encode() + + def test_every_rest_and_mcp_surface_has_a_scope_classification(tmp_path: Path) -> None: # 2119: REQ-048.8.3 with _client(tmp_path) as client: @@ -3414,6 +3591,43 @@ def test_active_setup_repo_task_can_only_set_its_own_repo_credential_dir( assert configured.status_code == 200, configured.text assert configured.json()["credential_dir"] == "openai.d" + fleet = _bearer(WRITE_TOKEN) + before = {repo: client.get(f"/repos/{repo}", headers=fleet).json() for repo in ("r1", "r2")} + + def assert_denied_unchanged(path: str, headers: dict[str, str], body: object) -> None: + denied = client.patch(path, headers=headers, json=body) + assert (denied.status_code, denied.json()) == (403, SCOPE_FAILURE), body + assert { + repo: client.get(f"/repos/{repo}", headers=fleet).json() for repo in before + } == before + + forbidden_fields = { + "id": "r1", + "name": "stolen", + "git_url": "https://example.test/changed.git", + "default_base": "changed-base", + "env_file": "changed.env", + "image_layer_file": "changed.Dockerfile", + "capabilities": {"docker_in_docker": True}, + "hook_file": "changed.sh", + "enabled_workflows": ["alternate-credential-setup"], + "disabled_workflows": ["spike"], + "default_harness": "codex", + "default_model": "changed-model", + "honesty_reviewer": "codex:changed-model", + "reviewer_1": "codex:changed-model", + "reviewer_2": "codex:changed-model", + } + assert forbidden_fields + assert set(forbidden_fields) == set(RepoPatchIn.model_fields) - {"credential_dir"} + for field, value in {**forbidden_fields, "launch_paused": True, "unknown": "value"}.items(): + for body in ({field: value}, {"credential_dir": "other.d", field: value}): + assert_denied_unchanged("/repos/r1", setup_headers, body) + for value in (False, True, 0, 1, 1.5, [], ["other.d"], {}, {"name": "other.d"}): + assert_denied_unchanged("/repos/r1", setup_headers, {"credential_dir": value}) + for body in ([], ["credential_dir", "other.d"], "other.d", 1, True, None, {}): + assert_denied_unchanged("/repos/r1", setup_headers, body) + for path, headers, body in ( ("/repos/r2", setup_headers, {"credential_dir": "other.d"}), ("/repos/r1", setup_headers, {"name": "stolen"}), @@ -3426,23 +3640,26 @@ def test_active_setup_repo_task_can_only_set_its_own_repo_credential_dir( ("/repos/r1", setup_headers, {"credential_dir": ""}), ("/repos/r1", setup_headers, {"credential_dir": " "}), ("/repos/r1", setup_headers, {"credential_dir": "."}), + ("/repos/r1", setup_headers, {"credential_dir": ".."}), + ("/repos/r1", setup_headers, {"credential_dir": "/"}), ("/repos/r1", setup_headers, {"credential_dir": "/absolute.d"}), ("/repos/r1", setup_headers, {"credential_dir": "../other.d"}), ("/repos/r1", setup_headers, {"credential_dir": "nested/dir"}), + ("/repos/r1", setup_headers, {"credential_dir": "other.d/"}), ("/repos/r1", regular_headers, {"credential_dir": "other.d"}), ): - denied = client.patch(path, headers=headers, json=body) - assert (denied.status_code, denied.json()) == (403, SCOPE_FAILURE) + assert_denied_unchanged(path, headers, body) completed = client.post(f"/tasks/{setup['id']}/operations/advance", headers=setup_headers) assert completed.status_code == 200 - denied_after_completion = client.patch( - "/repos/r1", headers=setup_headers, json={"credential_dir": "other.d"} - ) - assert (denied_after_completion.status_code, denied_after_completion.json()) == ( - 403, - SCOPE_FAILURE, - ) + assert completed.json()["state"] == "COMPLETE" + assert_denied_unchanged("/repos/r1", setup_headers, {"credential_dir": "other.d"}) + dropped = _create_task(client, workflow="setup-repo") + dropped_headers = _bearer(_task_token(dropped["id"])) + response = client.post(f"/tasks/{dropped['id']}/operations/drop", headers=dropped_headers) + assert response.status_code == 200 + assert response.json()["state"] == "DROPPED" + assert_denied_unchanged("/repos/r1", dropped_headers, {"credential_dir": "other.d"}) repo = client.get("/repos/r1", headers=_bearer(WRITE_TOKEN)).json() assert repo["name"] == "acme/one" @@ -3659,12 +3876,14 @@ def test_capability_plaintext_is_absent_from_persistent_and_diagnostic_surfaces( tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: # 2119: REQ-048.3.2 + caplog.set_level(logging.DEBUG) with _client(tmp_path, read=[READ_TOKEN]) as client: task = _create_task(client) capability = _task_token(task["id"]) assert capability not in json.dumps(task) task_response = client.get(f"/tasks/{task['id']}", headers=_bearer(capability)) repo_response = client.get("/repos/r1", headers=_bearer(capability)) + assert task_response.status_code == repo_response.status_code == 200 assert capability not in task_response.text assert capability not in repo_response.text assert capability not in client.get("/tasks", headers=_bearer(WRITE_TOKEN)).text @@ -3680,5 +3899,8 @@ def test_capability_plaintext_is_absent_from_persistent_and_diagnostic_surfaces( path.read_bytes() for path in (tmp_path / "artifacts").rglob("*") if path.is_file() ) assert capability.encode() not in artifact_bytes - client.get("/tasks", headers={"Authorization": f"Bearer {capability}x"}) + rejected = client.get("/tasks", headers={"Authorization": f"Bearer {capability}x"}) + assert (rejected.status_code, rejected.json()) == (401, GENERIC_FAILURE) + scope_rejected = client.get("/tasks/missing", headers=_bearer(capability)) + assert (scope_rejected.status_code, scope_rejected.json()) == (403, SCOPE_FAILURE) assert capability not in caplog.text From 9ff75871aee420eba05ff4d12de4c402893f7f3a Mon Sep 17 00:00:00 2001 From: Panopticon Agent Date: Tue, 27 Oct 2026 23:17:23 -0700 Subject: [PATCH 06/10] test(tasks): reject premature readiness with mixed dependencies A single-dependency test cannot distinguish gating on any incomplete dependency from gating only when all are incomplete. Use two dependencies in a custom workflow and finish them in both possible orders. Both task GET and list responses must stay gated after the first completion and become queued only after the second custom terminal state is reached. Validation: both parameter cases pass; separate mutations changing each service composition path from any to all are rejected. Independent 2119 review passed the dependency-readiness requirements. --- tests/taskservice/test_api.py | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/tests/taskservice/test_api.py b/tests/taskservice/test_api.py index 4769e67..7b753d2 100644 --- a/tests/taskservice/test_api.py +++ b/tests/taskservice/test_api.py @@ -333,7 +333,10 @@ def test_task_responses_keep_dropped_dependencies_gated(client: TestClient) -> N # 2119: REQ-026.2.1 # 2119: REQ-026.2.3 -def test_task_responses_use_workflow_terminality_for_dependency_readiness(tmp_path: Path) -> None: +@pytest.mark.parametrize("completed_index", [0, 1]) +def test_task_responses_use_workflow_terminality_for_dependency_readiness( + tmp_path: Path, completed_index: int +) -> None: service = TaskService( SqlAlchemyStore(), {"archived": _ArchivedWorkflow()}, @@ -342,22 +345,37 @@ def test_task_responses_use_workflow_terminality_for_dependency_readiness(tmp_pa asyncio.run(service.init()) asyncio.run(service.create_repo(Repo(id="r1", name="acme/widgets", git_url="https://x/r1.git"))) with TestClient(create_app(service)) as custom_client: - dependency = custom_client.post( - "/tasks", json={"repo_id": "r1", "workflow": "archived"} - ).json() + dependencies = [ + custom_client.post("/tasks", json={"repo_id": "r1", "workflow": "archived"}).json() + for _ in range(2) + ] dependent = custom_client.post( "/tasks", json={ "repo_id": "r1", "workflow": "archived", - "depends_on_task_ids": [dependency["id"]], + "depends_on_task_ids": [dependency["id"] for dependency in dependencies], }, ).json() assert dependent["container_status"] == "gated" - archived = custom_client.post(f"/tasks/{dependency['id']}/operations/advance") + archived = custom_client.post( + f"/tasks/{dependencies[completed_index]['id']}/operations/advance" + ) assert archived.status_code == 200, archived.text assert archived.json()["state"] == "ARCHIVED" + assert custom_client.get(f"/tasks/{dependent['id']}").json()["container_status"] == "gated" + mixed = custom_client.get("/tasks", params={"terminal": "false"}).json() + assert ( + next(task for task in mixed if task["id"] == dependent["id"])["container_status"] + == "gated" + ) + + remaining = custom_client.post( + f"/tasks/{dependencies[1 - completed_index]['id']}/operations/advance" + ) + assert remaining.status_code == 200, remaining.text + assert remaining.json()["state"] == "ARCHIVED" assert custom_client.get(f"/tasks/{dependent['id']}").json()["container_status"] == "queued" active = custom_client.get("/tasks", params={"terminal": "false"}).json() projected = next(task for task in active if task["id"] == dependent["id"]) From bbfce6d9cc19ccb3a24d612c2e524280ec5301ab Mon Sep 17 00:00:00 2001 From: Panopticon Agent Date: Tue, 27 Oct 2026 23:17:23 -0700 Subject: [PATCH 07/10] test(codex): assert the resume prompt independently of its implementation Pin the literal interrupted-turn prompt in the expected argv instead of importing the production constant, which allowed an incorrect prompt to change implementation and expectation together. Also assert that user-turn resume omits the prompt. Validation: harness suite passes; changing the prompt literal or appending it on a user turn is rejected by targeted in-memory mutations. Independent 2119 review passed the resume contract. --- tests/harnesses/test_codex.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/harnesses/test_codex.py b/tests/harnesses/test_codex.py index 41f9442..ac58910 100644 --- a/tests/harnesses/test_codex.py +++ b/tests/harnesses/test_codex.py @@ -17,7 +17,7 @@ import pytest from panopticon.core.models import Skill -from panopticon.harnesses import INTERRUPT_PROMPT, BootstrapContext, LaunchContext +from panopticon.harnesses import BootstrapContext, LaunchContext from panopticon.harnesses.codex import ( CODEX_VERSION, RECONCILE_AUTH_ENV, @@ -302,10 +302,15 @@ def test_argv_resumes_the_recorded_interactive_session_by_id(tmp_path: Path) -> # 2119: REQ-032.5.2 -def test_argv_resume_appends_interrupt_prompt_on_agent_turn(tmp_path: Path) -> None: +@pytest.mark.parametrize( + ("turn", "suffix"), [("agent", ["You were interrupted. Continue."]), ("user", [])] +) +def test_argv_resume_appends_interrupt_prompt_only_on_agent_turn( + tmp_path: Path, turn: str, suffix: list[str] +) -> None: _seed_session(tmp_path) - argv = HARNESS.argv(_ctx(tmp_path, turn="agent")) - assert argv == ["codex", "resume", "interactive-1", *_SESSION_FLAGS, INTERRUPT_PROMPT] + argv = HARNESS.argv(_ctx(tmp_path, turn=turn)) + assert argv == ["codex", "resume", "interactive-1", *_SESSION_FLAGS, *suffix] def test_argv_resume_omits_model_and_initial_prompt(tmp_path: Path) -> None: From 7d484ab1544a764720b171d81a5d5e834cde8ac9 Mon Sep 17 00:00:00 2001 From: Panopticon Agent Date: Tue, 27 Oct 2026 23:17:23 -0700 Subject: [PATCH 08/10] test(proxy): verify bypass routing across native MCP retries Native MCP health checks may retry or negotiate protocol versions. Require nonempty target traffic with the exact endpoint and bearer credential while allowing multiple correct requests. Capture every HTTP method at the proxy, keep the positive control that proves proxy use without bypass, and require zero proxy requests once production bypass values are applied. Set explicit proxy variables and disable unrelated optional CLI traffic in the disposable environment. Cover runner bypass emission both with and without a repository environment file so the no-file path is also checked when the real CLI integration test is unavailable. Validation: native CLI tests passed ten repeated cases; all 37 local-runner tests passed; disabling bypass generally or only for the no-file path is rejected by narrow in-memory mutations. No real model inference is used. --- tests/sessionservice/test_local_runner.py | 21 +++++++++++---------- tests/test_native_mcp_proxy.py | 21 +++++++++++++++++++-- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/tests/sessionservice/test_local_runner.py b/tests/sessionservice/test_local_runner.py index 548ad84..375cba8 100644 --- a/tests/sessionservice/test_local_runner.py +++ b/tests/sessionservice/test_local_runner.py @@ -314,8 +314,10 @@ def test_spawn_resolves_env_file_against_the_runners_secrets_dir() -> None: assert f"{name}=" in docker_run +@pytest.mark.parametrize("with_env_file", [False, True]) def test_spawn_forces_native_mcp_off_ambient_proxy_and_preserves_bypasses( tmp_path: Path, + with_env_file: bool, ) -> None: # 2119: REQ-035.47 env_file = tmp_path / "repo.env" @@ -330,18 +332,17 @@ def test_spawn_forces_native_mcp_off_ambient_proxy_and_preserves_bypasses( secrets_dir=tmp_path, extra_env={"NO_PROXY": "extra.internal", "no_proxy": "lower-extra.internal"}, run=rec, - ).spawn("t1", env_file=env_file.name) + ).spawn("t1", env_file=env_file.name if with_env_file else None) docker_run = rec.calls[2][0] - expected = ( - "registry.internal,localhost,metadata.internal,extra.internal," - "lower-extra.internal,host.docker.internal" - ) - env_file_index = docker_run.index("--env-file") - upper_index = docker_run.index(f"NO_PROXY={expected}") - lower_index = docker_run.index(f"no_proxy={expected}") - assert env_file_index < upper_index - assert env_file_index < lower_index + expected = "extra.internal,lower-extra.internal,host.docker.internal" + if with_env_file: + expected = "registry.internal,localhost,metadata.internal," + expected + env_file_index = docker_run.index("--env-file") + assert env_file_index < docker_run.index(f"NO_PROXY={expected}") + assert env_file_index < docker_run.index(f"no_proxy={expected}") + else: + assert "--env-file" not in docker_run assert f"NO_PROXY={expected}" in docker_run assert f"no_proxy={expected}" in docker_run diff --git a/tests/test_native_mcp_proxy.py b/tests/test_native_mcp_proxy.py index 86bf657..b439f2f 100644 --- a/tests/test_native_mcp_proxy.py +++ b/tests/test_native_mcp_proxy.py @@ -20,11 +20,19 @@ class _CaptureHandler(http.server.BaseHTTPRequestHandler): hits: list[tuple[str, str | None]] = [] + def parse_request(self) -> bool: + parsed = super().parse_request() + if parsed: + type(self).hits.append((self.path, self.headers.get("Authorization"))) + return parsed + def do_POST(self) -> None: - type(self).hits.append((self.path, self.headers.get("Authorization"))) self.send_response(404) self.end_headers() + do_GET = do_POST + do_CONNECT = do_POST + def log_message(self, format: str, *args: object) -> None: pass @@ -76,8 +84,15 @@ def test_real_claude_mcp_transport_bypasses_ambient_proxy( "HOME": str(home), "PATH": os.environ.get("PATH", os.defpath), "PANOPTICON_SERVICE_AUTH_TOKEN": token, + "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1", "HTTP_PROXY": f"http://127.0.0.1:{proxy.server_address[1]}", "http_proxy": f"http://127.0.0.1:{proxy.server_address[1]}", + "HTTPS_PROXY": f"http://127.0.0.1:{proxy.server_address[1]}", + "https_proxy": f"http://127.0.0.1:{proxy.server_address[1]}", + "ALL_PROXY": f"http://127.0.0.1:{proxy.server_address[1]}", + "all_proxy": f"http://127.0.0.1:{proxy.server_address[1]}", + "NO_PROXY": "", + "no_proxy": "", } workdir = tmp_path / "work" workdir.mkdir() @@ -157,4 +172,6 @@ def capture_runner(command: list[str], **_kwargs: object) -> str: server.server_close() assert _ProxyHandler.hits == [] - assert _TargetHandler.hits == [("/mcp", f"Bearer {token}")] + # Native MCP health checks may retry or negotiate multiple protocol versions. + # Every request must still bypass the proxy and preserve the target credential. + assert set(_TargetHandler.hits) == {("/mcp", f"Bearer {token}")} From c94328f9a8ec10938b7755162d176a051a898abb Mon Sep 17 00:00:00 2001 From: Panopticon Agent Date: Tue, 27 Oct 2026 23:17:23 -0700 Subject: [PATCH 09/10] test(2119): persist current independent requirement verdicts Store the passing review records needed to reproduce the requirements gate from a clean checkout. Reuse existing reviews only where their content hashes still match; record fresh independent Fable judgments for repaired or stale evidence. Preserve tracked audit history and omit superseded untracked records. The records explain concrete rejected counterexamples for clipboard behavior, credential boundaries, dependency readiness, session resume and proxy routing. They do not change requirements, remove coverage or waive failing checks. Validation: pinned rfc2119 0.7.0 check, with clean-checkout verification before publication. --- .2119/verdicts/REQ-001.1.1--91a98485e5ee.json | 8 ++++++++ .2119/verdicts/REQ-001.2.1--2971178e5e35.json | 8 ++++++++ .2119/verdicts/REQ-001.3.1--dae4d92b8d2a.json | 8 ++++++++ .2119/verdicts/REQ-001.4.1--b17d9c27fb31.json | 8 ++++++++ .2119/verdicts/REQ-001.5.1--dece1a1a4b8b.json | 8 ++++++++ .2119/verdicts/REQ-001.6.1--fc6c297d4089.json | 8 ++++++++ .2119/verdicts/REQ-001.7.1--394756dff78c.json | 8 ++++++++ .2119/verdicts/REQ-001.8.1--333d9a5a1792.json | 8 ++++++++ .2119/verdicts/REQ-004.1.1--6c292078b9c1.json | 8 ++++++++ .2119/verdicts/REQ-004.2.1--485807dc2fdb.json | 8 ++++++++ .2119/verdicts/REQ-004.3.1--049ee602f14a.json | 8 ++++++++ .2119/verdicts/REQ-006.1.1--d44d0ccd9c56.json | 8 ++++++++ .2119/verdicts/REQ-006.1.2--7f0324a80f87.json | 8 ++++++++ .2119/verdicts/REQ-006.2.1--f68843e37ef4.json | 8 ++++++++ .2119/verdicts/REQ-006.2.2--f96755abbb86.json | 8 ++++++++ .2119/verdicts/REQ-006.3.1--4badcd34aca2.json | 8 ++++++++ .2119/verdicts/REQ-006.4.1--de5a493494bc.json | 8 ++++++++ .2119/verdicts/REQ-006.4.2--5070d484b6a6.json | 8 ++++++++ .2119/verdicts/REQ-006.4.3--dececf5c56bf.json | 8 ++++++++ .2119/verdicts/REQ-006.4.4--c44610ab8736.json | 8 ++++++++ .2119/verdicts/REQ-006.4.5--12089a98b38c.json | 8 ++++++++ .2119/verdicts/REQ-006.5.1--9a86e76c176d.json | 8 ++++++++ .2119/verdicts/REQ-006.5.2--55168c9c65c2.json | 8 ++++++++ .2119/verdicts/REQ-007.1.1--30513083a049.json | 8 ++++++++ .2119/verdicts/REQ-007.2.1--69086fc1c11d.json | 8 ++++++++ .2119/verdicts/REQ-007.3.1--183403b178d1.json | 8 ++++++++ .2119/verdicts/REQ-008.5.1--6f645191cdc5.json | 8 ++++++++ .2119/verdicts/REQ-008.6.1--a45d8276443f.json | 8 ++++++++ .2119/verdicts/REQ-008.7.1--164b24717ff0.json | 8 ++++++++ .2119/verdicts/REQ-011.1.3--83a4eb3fc522.json | 8 ++++++++ .2119/verdicts/REQ-012.2.1--6a41573bbf33.json | 8 ++++++++ .2119/verdicts/REQ-012.2.2--b630075731fa.json | 8 ++++++++ .2119/verdicts/REQ-012.2.4--db900f1233f5.json | 8 ++++++++ .2119/verdicts/REQ-012.3.1--8e875204958d.json | 8 ++++++++ .2119/verdicts/REQ-012.3.2--141dcdbd61e7.json | 8 ++++++++ .2119/verdicts/REQ-012.3.3--5ae6529ee48b.json | 8 ++++++++ .2119/verdicts/REQ-012.3.4--e6880201af26.json | 8 ++++++++ .2119/verdicts/REQ-012.4.1--0d5b58044b12.json | 8 ++++++++ .2119/verdicts/REQ-012.4.2--6db331c294bb.json | 8 ++++++++ .2119/verdicts/REQ-012.4.3--ca698b73762b.json | 8 ++++++++ .2119/verdicts/REQ-012.5.1--d9944c97f8b1.json | 8 ++++++++ .2119/verdicts/REQ-015.1.1--eda22abe66fe.json | 8 ++++++++ .2119/verdicts/REQ-016.1.1--41e9483c0e6e.json | 8 ++++++++ .2119/verdicts/REQ-016.2.1--d586c75406ac.json | 8 ++++++++ .2119/verdicts/REQ-016.3.1--dc109b8614f4.json | 8 ++++++++ .2119/verdicts/REQ-017.1.1--7bf3c56df43f.json | 8 ++++++++ .2119/verdicts/REQ-017.2.1--a00904b9851d.json | 8 ++++++++ .2119/verdicts/REQ-017.3.1--1f335a1c90a2.json | 8 ++++++++ .2119/verdicts/REQ-017.4.1--184670458f97.json | 8 ++++++++ .2119/verdicts/REQ-018.1.1--36f169334eb4.json | 8 ++++++++ .2119/verdicts/REQ-018.10.1--02f7cdac1115.json | 8 ++++++++ .2119/verdicts/REQ-018.11.1--0700ac1dd443.json | 8 ++++++++ .2119/verdicts/REQ-018.12.1--9f0ad8d77784.json | 8 ++++++++ .2119/verdicts/REQ-018.13.1--60a897302961.json | 8 ++++++++ .2119/verdicts/REQ-018.14.1--982450c06998.json | 8 ++++++++ .2119/verdicts/REQ-018.15.1--7d46336555bf.json | 8 ++++++++ .2119/verdicts/REQ-018.16.1--be430fcdd292.json | 8 ++++++++ .2119/verdicts/REQ-018.17.1--f8a5cad3b0f3.json | 8 ++++++++ .2119/verdicts/REQ-018.18.1--6848ec33e3eb.json | 8 ++++++++ .2119/verdicts/REQ-018.19.1--6a4f04237f29.json | 8 ++++++++ .2119/verdicts/REQ-018.2.1--520062dd6068.json | 8 ++++++++ .2119/verdicts/REQ-018.20.1--4aeae9606abd.json | 8 ++++++++ .2119/verdicts/REQ-018.3.1--c7409bd3c4d9.json | 8 ++++++++ .2119/verdicts/REQ-018.4.1--5d43058b90f2.json | 8 ++++++++ .2119/verdicts/REQ-018.5.1--90fbc7e3790d.json | 8 ++++++++ .2119/verdicts/REQ-018.6.1--8298de0c08f6.json | 8 ++++++++ .2119/verdicts/REQ-018.7.1--287fdd05a5c8.json | 8 ++++++++ .2119/verdicts/REQ-018.8.1--0ffb67cebc0f.json | 8 ++++++++ .2119/verdicts/REQ-018.9.1--bdeaa81c86a8.json | 8 ++++++++ .2119/verdicts/REQ-019.1.1--94ff88e0b7d7.json | 8 ++++++++ .2119/verdicts/REQ-019.2.1--b47ade7d9b70.json | 8 ++++++++ .2119/verdicts/REQ-019.3.1--1c989032515b.json | 8 ++++++++ .2119/verdicts/REQ-019.4.1--ec295a9bdc3c.json | 8 ++++++++ .2119/verdicts/REQ-019.5.1--ce009f9b9a91.json | 8 ++++++++ .2119/verdicts/REQ-019.6.1--a369bcab5837.json | 8 ++++++++ .2119/verdicts/REQ-019.7.1--8d3d2fd0e769.json | 8 ++++++++ .2119/verdicts/REQ-019.8.1--3fed30642ac4.json | 8 ++++++++ .2119/verdicts/REQ-022.2.1--7b39ed38159b.json | 8 ++++++++ .2119/verdicts/REQ-023.1.1--ab2c213bd85f.json | 8 ++++++++ .2119/verdicts/REQ-023.2.1--c97806e04b9c.json | 8 ++++++++ .2119/verdicts/REQ-023.3.1--79edea8071de.json | 8 ++++++++ .2119/verdicts/REQ-023.4.1--cb5e56b153bf.json | 8 ++++++++ .2119/verdicts/REQ-023.5.1--2d97bdd14cbd.json | 8 ++++++++ .2119/verdicts/REQ-024.7.1--de6bf76ae254.json | 8 ++++++++ .2119/verdicts/REQ-025.1.1--0b9b1e9b8d88.json | 8 ++++++++ .2119/verdicts/REQ-026.1.1--33859f27dd42.json | 8 ++++++++ .2119/verdicts/REQ-026.1.2--cc283c1dba64.json | 8 ++++++++ .2119/verdicts/REQ-026.1.3--1a42bb5edb23.json | 8 ++++++++ .2119/verdicts/REQ-026.2.1--8474634b145c.json | 8 ++++++++ .2119/verdicts/REQ-026.2.3--9234323661a0.json | 8 ++++++++ .2119/verdicts/REQ-026.3.1--7149538d9e8d.json | 8 ++++++++ .2119/verdicts/REQ-026.3.2--a8d92f5a98f4.json | 8 ++++++++ .2119/verdicts/REQ-026.3.3--28e8e14e95cb.json | 8 ++++++++ .2119/verdicts/REQ-026.3.4--a01bf1446254.json | 8 ++++++++ .2119/verdicts/REQ-026.3.5--75bdf83a2bee.json | 8 ++++++++ .2119/verdicts/REQ-026.4.1--d2fe3accd242.json | 8 ++++++++ .2119/verdicts/REQ-026.4.2--33f446d79e00.json | 8 ++++++++ .2119/verdicts/REQ-026.4.3--cf130bfb16b1.json | 8 ++++++++ .2119/verdicts/REQ-026.5.1--218063677b29.json | 8 ++++++++ .2119/verdicts/REQ-026.5.2--4f29fc3ed6bc.json | 8 ++++++++ .2119/verdicts/REQ-026.5.3--17db970a1779.json | 8 ++++++++ .2119/verdicts/REQ-026.6.1--1c4605b55497.json | 8 ++++++++ .2119/verdicts/REQ-026.6.2--adae400ce7b0.json | 8 ++++++++ .2119/verdicts/REQ-026.6.3--0e86a599b457.json | 8 ++++++++ .2119/verdicts/REQ-026.6.4--eeee02ab8203.json | 8 ++++++++ .2119/verdicts/REQ-026.6.5--a5cb9b38e497.json | 8 ++++++++ .2119/verdicts/REQ-026.6.8--91f43e2e27db.json | 8 ++++++++ .2119/verdicts/REQ-027.1.1--9b097314b437.json | 8 ++++++++ .2119/verdicts/REQ-027.1.2--1755fcea5014.json | 8 ++++++++ .2119/verdicts/REQ-027.1.3--ebfc2e908f28.json | 8 ++++++++ .2119/verdicts/REQ-027.2.1--242da9f898a9.json | 8 ++++++++ .2119/verdicts/REQ-027.2.2--ec081378b0c4.json | 8 ++++++++ .2119/verdicts/REQ-027.2.3--1e08e4f61768.json | 8 ++++++++ .2119/verdicts/REQ-027.3.1--bdca0cd677e5.json | 8 ++++++++ .2119/verdicts/REQ-027.3.2--e186f432f0bd.json | 8 ++++++++ .2119/verdicts/REQ-027.3.3--23f37cf06481.json | 8 ++++++++ .2119/verdicts/REQ-027.3.4--a2198bb7d8fe.json | 8 ++++++++ .2119/verdicts/REQ-028.1.1--4b5f0f4d3537.json | 8 ++++++++ .2119/verdicts/REQ-028.10.1--e88c9711487f.json | 8 ++++++++ .2119/verdicts/REQ-028.11.1--4d9fb91e910c.json | 8 ++++++++ .2119/verdicts/REQ-028.12.1--e33951052195.json | 8 ++++++++ .2119/verdicts/REQ-028.2.1--0ca7c6de125a.json | 8 ++++++++ .2119/verdicts/REQ-028.3.1--de68f877febb.json | 8 ++++++++ .2119/verdicts/REQ-028.4.1--3c13931b3341.json | 8 ++++++++ .2119/verdicts/REQ-028.5.1--a0a6ceb6eb7c.json | 8 ++++++++ .2119/verdicts/REQ-028.6.1--fa83331abede.json | 8 ++++++++ .2119/verdicts/REQ-028.7.1--f5e423b157d4.json | 8 ++++++++ .2119/verdicts/REQ-028.8.1--d6f04d9444f8.json | 8 ++++++++ .2119/verdicts/REQ-028.8.2--dc7c9a4a7767.json | 8 ++++++++ .2119/verdicts/REQ-028.8.3--dab34c2959bb.json | 8 ++++++++ .2119/verdicts/REQ-028.9.1--10ee3479470d.json | 8 ++++++++ .2119/verdicts/REQ-030.1.1--fc4516e92bee.json | 8 ++++++++ .2119/verdicts/REQ-030.1.2--1aaca3cd2744.json | 8 ++++++++ .2119/verdicts/REQ-030.1.3--aa334eb614ee.json | 8 ++++++++ .2119/verdicts/REQ-030.2.1--0b6493ede8a8.json | 8 ++++++++ .2119/verdicts/REQ-030.2.2--01e0e975dc09.json | 8 ++++++++ .2119/verdicts/REQ-030.2.3--94cf3a001475.json | 8 ++++++++ .2119/verdicts/REQ-030.2.4--191b47ca2bc8.json | 8 ++++++++ .2119/verdicts/REQ-030.2.5--99f116196e6d.json | 8 ++++++++ .2119/verdicts/REQ-030.3.1--bbce5b5ff87c.json | 8 ++++++++ .2119/verdicts/REQ-030.3.2--6f32f8a5b92d.json | 8 ++++++++ .2119/verdicts/REQ-030.4.1--fcb982be3c19.json | 8 ++++++++ .2119/verdicts/REQ-030.4.2--e2386a63e29a.json | 8 ++++++++ .2119/verdicts/REQ-030.4.3--2b80d13b4596.json | 8 ++++++++ .2119/verdicts/REQ-030.4.4--655bc9a7029a.json | 8 ++++++++ .2119/verdicts/REQ-030.4.5--a173543f9001.json | 8 ++++++++ .2119/verdicts/REQ-030.4.6--b5f6e6ff6104.json | 8 ++++++++ .2119/verdicts/REQ-030.5.1--27632b3c10c3.json | 8 ++++++++ .2119/verdicts/REQ-030.5.2--208c7f5b26fe.json | 8 ++++++++ .2119/verdicts/REQ-031.1.1--e7f3dae9271d.json | 8 ++++++++ .2119/verdicts/REQ-031.1.2--7d809f596b36.json | 8 ++++++++ .2119/verdicts/REQ-031.1.3--327a3558cbe5.json | 8 ++++++++ .2119/verdicts/REQ-031.1.4--3f8fa11b7343.json | 8 ++++++++ .2119/verdicts/REQ-031.1.5--0890e0a3d1f6.json | 8 ++++++++ .2119/verdicts/REQ-031.2.1--bf2a81eb5e26.json | 8 ++++++++ .2119/verdicts/REQ-031.2.2--0e533789f260.json | 8 ++++++++ .2119/verdicts/REQ-031.3.1--60f6189f86fb.json | 8 ++++++++ .2119/verdicts/REQ-032.1.1--a9f59b47de16.json | 8 ++++++++ .2119/verdicts/REQ-032.1.2--d051cd38f4f8.json | 8 ++++++++ .2119/verdicts/REQ-032.1.3--43c63811228f.json | 8 ++++++++ .2119/verdicts/REQ-032.1.4--db9b38bf05df.json | 8 ++++++++ .2119/verdicts/REQ-032.2.1--63a22d77cfec.json | 8 ++++++++ .2119/verdicts/REQ-032.2.2--d735d095d2db.json | 8 ++++++++ .2119/verdicts/REQ-032.3.1--688a8fd081ad.json | 8 ++++++++ .2119/verdicts/REQ-032.4.1--671e6841d69d.json | 8 ++++++++ .2119/verdicts/REQ-032.5.1--70fb49eea63b.json | 8 ++++++++ .2119/verdicts/REQ-032.5.2--9d7d8694c538.json | 8 ++++++++ .2119/verdicts/REQ-033.1.1--13e12d59f7c1.json | 8 ++++++++ .2119/verdicts/REQ-033.10.1--5646eda74129.json | 8 ++++++++ .2119/verdicts/REQ-033.2.1--7671d5851c4b.json | 8 ++++++++ .2119/verdicts/REQ-033.3.1--589c2f732fa3.json | 8 ++++++++ .2119/verdicts/REQ-033.4.1--bfc61d9d22bb.json | 8 ++++++++ .2119/verdicts/REQ-033.5.1--3b6cf7b8204b.json | 8 ++++++++ .2119/verdicts/REQ-033.6.1--dd9484d48bc0.json | 8 ++++++++ .2119/verdicts/REQ-033.7.1--dee756ae075d.json | 8 ++++++++ .2119/verdicts/REQ-033.8.1--63fa02856b1d.json | 8 ++++++++ .2119/verdicts/REQ-033.9.1--1487d2b8cd0d.json | 8 ++++++++ .2119/verdicts/REQ-034.1.1--aad04f3a549a.json | 8 ++++++++ .2119/verdicts/REQ-034.1.2--2f9bb821dd9b.json | 8 ++++++++ .2119/verdicts/REQ-034.2.1--0aefc39ecf18.json | 8 ++++++++ .2119/verdicts/REQ-035.14.1--9e4827027914.json | 8 ++++++++ .2119/verdicts/REQ-035.17.1--e5fc76cef15a.json | 8 ++++++++ .2119/verdicts/REQ-035.29.1--3f5d79610567.json | 8 ++++++++ .2119/verdicts/REQ-035.36.1--26cadbfb8714.json | 8 ++++++++ .2119/verdicts/REQ-035.39.1--a64952b5956d.json | 8 ++++++++ .2119/verdicts/REQ-035.4.1--278dcf0fb339.json | 8 ++++++++ .2119/verdicts/REQ-035.45.1--b8383474bc32.json | 8 ++++++++ .2119/verdicts/REQ-035.47.1--41345d31eb3c.json | 8 ++++++++ .2119/verdicts/REQ-035.7.1--0f05671f85c7.json | 8 ++++++++ .2119/verdicts/REQ-036.1.1--295553c79072.json | 8 ++++++++ .2119/verdicts/REQ-038.1.1--318b536ed51a.json | 8 ++++++++ .2119/verdicts/REQ-039.3.1--b679ab343b40.json | 8 ++++++++ .2119/verdicts/REQ-039.4.1--29181ba2025f.json | 8 ++++++++ .2119/verdicts/REQ-040.1.1--81c24293ebba.json | 8 ++++++++ .2119/verdicts/REQ-040.2.1--669ef0f220bd.json | 8 ++++++++ .2119/verdicts/REQ-040.3.1--c4c977a044cf.json | 8 ++++++++ .2119/verdicts/REQ-040.4.1--30da005e8f76.json | 8 ++++++++ .2119/verdicts/REQ-040.5.1--730d0ca6863f.json | 8 ++++++++ .2119/verdicts/REQ-040.6.1--efc53f888ac8.json | 8 ++++++++ .2119/verdicts/REQ-040.7.1--4183cea2d07e.json | 8 ++++++++ .2119/verdicts/REQ-041.3.1--ec848982c3eb.json | 8 ++++++++ .2119/verdicts/REQ-041.4.1--beede4b057e0.json | 8 ++++++++ .2119/verdicts/REQ-042.1.1--58d2b3a829e4.json | 8 ++++++++ .2119/verdicts/REQ-042.2.1--0c40ae502d40.json | 8 ++++++++ .2119/verdicts/REQ-042.3.1--9eddfab894ec.json | 8 ++++++++ .2119/verdicts/REQ-042.4.1--e40a191ba72f.json | 8 ++++++++ .2119/verdicts/REQ-048.1.1--0d57ba4502bb.json | 8 ++++++++ .2119/verdicts/REQ-048.1.2--9e22beb20779.json | 8 ++++++++ .2119/verdicts/REQ-048.1.3--02ee3d06f9ef.json | 8 ++++++++ .2119/verdicts/REQ-048.10.1--53d3f7c04a5e.json | 8 ++++++++ .2119/verdicts/REQ-048.10.2--3455a0666537.json | 8 ++++++++ .2119/verdicts/REQ-048.10.3--e6878234b6a9.json | 8 ++++++++ .2119/verdicts/REQ-048.11.1--499768b56543.json | 8 ++++++++ .2119/verdicts/REQ-048.11.2--5350832ca941.json | 8 ++++++++ .2119/verdicts/REQ-048.11.3--88f702f07f65.json | 8 ++++++++ .2119/verdicts/REQ-048.11.4--7715d1063b7f.json | 8 ++++++++ .2119/verdicts/REQ-048.12.1--613161d69994.json | 8 ++++++++ .2119/verdicts/REQ-048.12.2--a7e06fdd52c7.json | 8 ++++++++ .2119/verdicts/REQ-048.2.1--c1c8e6ffa2a4.json | 8 ++++++++ .2119/verdicts/REQ-048.2.2--017ed57b1bcc.json | 8 ++++++++ .2119/verdicts/REQ-048.2.3--e9a75e193b15.json | 8 ++++++++ .2119/verdicts/REQ-048.2.4--56e9501ae9b4.json | 8 ++++++++ .2119/verdicts/REQ-048.3.1--e58fd8cea0df.json | 8 ++++++++ .2119/verdicts/REQ-048.3.2--0cb054b37c60.json | 8 ++++++++ .2119/verdicts/REQ-048.3.3--8d3ee45125d0.json | 8 ++++++++ .2119/verdicts/REQ-048.4.1--069ac26b55f9.json | 8 ++++++++ .2119/verdicts/REQ-048.4.2--7fc82aabb81b.json | 8 ++++++++ .2119/verdicts/REQ-048.4.3--c827e2d037a4.json | 8 ++++++++ .2119/verdicts/REQ-048.5.1--b27574118414.json | 8 ++++++++ .2119/verdicts/REQ-048.5.2--f8d6164d043c.json | 8 ++++++++ .2119/verdicts/REQ-048.5.3--b14998108cbe.json | 8 ++++++++ .2119/verdicts/REQ-048.5.4--4737fec0f256.json | 8 ++++++++ .2119/verdicts/REQ-048.6.1--5476f71f799e.json | 8 ++++++++ .2119/verdicts/REQ-048.6.2--b40669d2ae91.json | 8 ++++++++ .2119/verdicts/REQ-048.6.3--0fd81d927c61.json | 8 ++++++++ .2119/verdicts/REQ-048.6.4--726594ae9dfe.json | 8 ++++++++ .2119/verdicts/REQ-048.7.1--efeb5255d4af.json | 8 ++++++++ .2119/verdicts/REQ-048.7.2--988df5e5a79f.json | 8 ++++++++ .2119/verdicts/REQ-048.7.3--0f6269ae90ae.json | 8 ++++++++ .2119/verdicts/REQ-048.7.4--86cc5d72cbe2.json | 8 ++++++++ .2119/verdicts/REQ-048.8.1--8486b6a87004.json | 8 ++++++++ .2119/verdicts/REQ-048.8.2--203e902b5831.json | 8 ++++++++ .2119/verdicts/REQ-048.8.3--52b200a79982.json | 8 ++++++++ .2119/verdicts/REQ-048.9.1--bf1843471699.json | 8 ++++++++ .2119/verdicts/REQ-048.9.2--bfa7ff13dab6.json | 8 ++++++++ .2119/verdicts/REQ-051.1.1--e0599fdfd09b.json | 8 ++++++++ .2119/verdicts/REQ-051.1.2--3f4c8247a14b.json | 8 ++++++++ .2119/verdicts/REQ-051.1.3--f1122a4a63e5.json | 8 ++++++++ .2119/verdicts/REQ-051.2.1--439729068fa6.json | 8 ++++++++ .2119/verdicts/REQ-051.2.2--126a77d1d874.json | 8 ++++++++ .2119/verdicts/REQ-051.2.3--1e40002406e0.json | 8 ++++++++ .2119/verdicts/REQ-051.2.4--40974079c6be.json | 8 ++++++++ .2119/verdicts/REQ-051.2.5--f76b8581d32c.json | 8 ++++++++ .2119/verdicts/REQ-051.2.6--9f28a5c59ac7.json | 8 ++++++++ .2119/verdicts/REQ-051.3.1--9796d0085699.json | 8 ++++++++ .2119/verdicts/REQ-051.3.2--31049781af77.json | 8 ++++++++ .2119/verdicts/REQ-051.3.3--cd06027383d9.json | 8 ++++++++ .2119/verdicts/REQ-051.4.1--dba58b727830.json | 8 ++++++++ .2119/verdicts/REQ-051.4.2--9cb7a9a9a82b.json | 8 ++++++++ .2119/verdicts/REQ-051.4.3--851966d5fee8.json | 8 ++++++++ .2119/verdicts/REQ-051.4.4--0c1e64e78580.json | 8 ++++++++ .2119/verdicts/REQ-051.4.5--7f27b19d0b5d.json | 8 ++++++++ .2119/verdicts/REQ-051.4.6--3608b2771ce4.json | 8 ++++++++ .2119/verdicts/REQ-051.4.7--8e80a3359472.json | 8 ++++++++ .2119/verdicts/REQ-051.5.1--4685782778fb.json | 8 ++++++++ .2119/verdicts/REQ-053.1.1--6077d61f80e1.json | 8 ++++++++ .2119/verdicts/REQ-053.2.1--90fb89bcabaf.json | 8 ++++++++ .2119/verdicts/REQ-053.3.1--59558cc9c9ab.json | 8 ++++++++ .2119/verdicts/REQ-053.4.1--5092fb48dccf.json | 8 ++++++++ .2119/verdicts/REQ-053.5.1--744581fafd50.json | 8 ++++++++ .2119/verdicts/REQ-053.6.1--68901d04c6c4.json | 8 ++++++++ .2119/verdicts/REQ-054.1.2--5978a59c4973.json | 8 ++++++++ .2119/verdicts/REQ-054.1.3--a3e7162ad033.json | 8 ++++++++ .2119/verdicts/REQ-054.7.1--8125a690752d.json | 8 ++++++++ .2119/verdicts/REQ-054.7.2--4f643c009183.json | 8 ++++++++ .2119/verdicts/REQ-054.7.6--a7d9a1ab4b4a.json | 8 ++++++++ .2119/verdicts/REQ-054.7.7--1333db5ef5cf.json | 8 ++++++++ .2119/verdicts/REQ-054.7.8--66facda09a35.json | 8 ++++++++ .2119/verdicts/REQ-054.7.9--bab32ddd4708.json | 8 ++++++++ .2119/verdicts/foreground-setup.1.3--3e1f6a7d24e5.json | 8 ++++++++ .2119/verdicts/foreground-setup.1.6--832584d5ac1e.json | 8 ++++++++ .../verdicts/full-width-dashboard.1.1--bf7a0d996595.json | 8 ++++++++ .../verdicts/full-width-dashboard.1.2--9b22f04337ea.json | 8 ++++++++ .../layered-settings-hints.1.1--3df14fffa455.json | 8 ++++++++ .../layered-settings-hints.2.1--34f6c5b3b85d.json | 8 ++++++++ .../layered-settings-hints.3.1--38e6e3c9457e.json | 8 ++++++++ .../layered-settings-hints.4.1--d918efa5cdac.json | 8 ++++++++ .../layered-settings-hints.5.1--a77893723316.json | 8 ++++++++ .../layered-settings-hints.6.1--45e564af521a.json | 8 ++++++++ .2119/verdicts/runtime-readiness.2.1--e28455ca485f.json | 8 ++++++++ .2119/verdicts/runtime-readiness.2.2--6754e34f7505.json | 8 ++++++++ .../skip-terminal-provisioner.1.1--2ba145c5e504.json | 8 ++++++++ .../skip-terminal-provisioner.1.2--dc3ad69edc38.json | 8 ++++++++ .2119/verdicts/task-auth-readiness.3.1--07095e3cf1e7.json | 8 ++++++++ .2119/verdicts/task-auth-readiness.3.2--1965e7dbada3.json | 8 ++++++++ .2119/verdicts/task-auth-readiness.3.3--462183793dd9.json | 8 ++++++++ .2119/verdicts/task-auth-readiness.3.4--0c9955ebd1d0.json | 8 ++++++++ .2119/verdicts/task-auth-readiness.3.5--6f59c463ca1e.json | 8 ++++++++ .2119/verdicts/task-auth-readiness.3.6--e90052889e3f.json | 8 ++++++++ .2119/verdicts/task-auth-readiness.3.7--c60ac8d6c312.json | 8 ++++++++ .2119/verdicts/task-auth-readiness.3.8--45bd73b2a766.json | 8 ++++++++ .2119/verdicts/task-auth-readiness.3.9--4afbbb4e0463.json | 8 ++++++++ 302 files changed, 2416 insertions(+) create mode 100644 .2119/verdicts/REQ-001.1.1--91a98485e5ee.json create mode 100644 .2119/verdicts/REQ-001.2.1--2971178e5e35.json create mode 100644 .2119/verdicts/REQ-001.3.1--dae4d92b8d2a.json create mode 100644 .2119/verdicts/REQ-001.4.1--b17d9c27fb31.json create mode 100644 .2119/verdicts/REQ-001.5.1--dece1a1a4b8b.json create mode 100644 .2119/verdicts/REQ-001.6.1--fc6c297d4089.json create mode 100644 .2119/verdicts/REQ-001.7.1--394756dff78c.json create mode 100644 .2119/verdicts/REQ-001.8.1--333d9a5a1792.json create mode 100644 .2119/verdicts/REQ-004.1.1--6c292078b9c1.json create mode 100644 .2119/verdicts/REQ-004.2.1--485807dc2fdb.json create mode 100644 .2119/verdicts/REQ-004.3.1--049ee602f14a.json create mode 100644 .2119/verdicts/REQ-006.1.1--d44d0ccd9c56.json create mode 100644 .2119/verdicts/REQ-006.1.2--7f0324a80f87.json create mode 100644 .2119/verdicts/REQ-006.2.1--f68843e37ef4.json create mode 100644 .2119/verdicts/REQ-006.2.2--f96755abbb86.json create mode 100644 .2119/verdicts/REQ-006.3.1--4badcd34aca2.json create mode 100644 .2119/verdicts/REQ-006.4.1--de5a493494bc.json create mode 100644 .2119/verdicts/REQ-006.4.2--5070d484b6a6.json create mode 100644 .2119/verdicts/REQ-006.4.3--dececf5c56bf.json create mode 100644 .2119/verdicts/REQ-006.4.4--c44610ab8736.json create mode 100644 .2119/verdicts/REQ-006.4.5--12089a98b38c.json create mode 100644 .2119/verdicts/REQ-006.5.1--9a86e76c176d.json create mode 100644 .2119/verdicts/REQ-006.5.2--55168c9c65c2.json create mode 100644 .2119/verdicts/REQ-007.1.1--30513083a049.json create mode 100644 .2119/verdicts/REQ-007.2.1--69086fc1c11d.json create mode 100644 .2119/verdicts/REQ-007.3.1--183403b178d1.json create mode 100644 .2119/verdicts/REQ-008.5.1--6f645191cdc5.json create mode 100644 .2119/verdicts/REQ-008.6.1--a45d8276443f.json create mode 100644 .2119/verdicts/REQ-008.7.1--164b24717ff0.json create mode 100644 .2119/verdicts/REQ-011.1.3--83a4eb3fc522.json create mode 100644 .2119/verdicts/REQ-012.2.1--6a41573bbf33.json create mode 100644 .2119/verdicts/REQ-012.2.2--b630075731fa.json create mode 100644 .2119/verdicts/REQ-012.2.4--db900f1233f5.json create mode 100644 .2119/verdicts/REQ-012.3.1--8e875204958d.json create mode 100644 .2119/verdicts/REQ-012.3.2--141dcdbd61e7.json create mode 100644 .2119/verdicts/REQ-012.3.3--5ae6529ee48b.json create mode 100644 .2119/verdicts/REQ-012.3.4--e6880201af26.json create mode 100644 .2119/verdicts/REQ-012.4.1--0d5b58044b12.json create mode 100644 .2119/verdicts/REQ-012.4.2--6db331c294bb.json create mode 100644 .2119/verdicts/REQ-012.4.3--ca698b73762b.json create mode 100644 .2119/verdicts/REQ-012.5.1--d9944c97f8b1.json create mode 100644 .2119/verdicts/REQ-015.1.1--eda22abe66fe.json create mode 100644 .2119/verdicts/REQ-016.1.1--41e9483c0e6e.json create mode 100644 .2119/verdicts/REQ-016.2.1--d586c75406ac.json create mode 100644 .2119/verdicts/REQ-016.3.1--dc109b8614f4.json create mode 100644 .2119/verdicts/REQ-017.1.1--7bf3c56df43f.json create mode 100644 .2119/verdicts/REQ-017.2.1--a00904b9851d.json create mode 100644 .2119/verdicts/REQ-017.3.1--1f335a1c90a2.json create mode 100644 .2119/verdicts/REQ-017.4.1--184670458f97.json create mode 100644 .2119/verdicts/REQ-018.1.1--36f169334eb4.json create mode 100644 .2119/verdicts/REQ-018.10.1--02f7cdac1115.json create mode 100644 .2119/verdicts/REQ-018.11.1--0700ac1dd443.json create mode 100644 .2119/verdicts/REQ-018.12.1--9f0ad8d77784.json create mode 100644 .2119/verdicts/REQ-018.13.1--60a897302961.json create mode 100644 .2119/verdicts/REQ-018.14.1--982450c06998.json create mode 100644 .2119/verdicts/REQ-018.15.1--7d46336555bf.json create mode 100644 .2119/verdicts/REQ-018.16.1--be430fcdd292.json create mode 100644 .2119/verdicts/REQ-018.17.1--f8a5cad3b0f3.json create mode 100644 .2119/verdicts/REQ-018.18.1--6848ec33e3eb.json create mode 100644 .2119/verdicts/REQ-018.19.1--6a4f04237f29.json create mode 100644 .2119/verdicts/REQ-018.2.1--520062dd6068.json create mode 100644 .2119/verdicts/REQ-018.20.1--4aeae9606abd.json create mode 100644 .2119/verdicts/REQ-018.3.1--c7409bd3c4d9.json create mode 100644 .2119/verdicts/REQ-018.4.1--5d43058b90f2.json create mode 100644 .2119/verdicts/REQ-018.5.1--90fbc7e3790d.json create mode 100644 .2119/verdicts/REQ-018.6.1--8298de0c08f6.json create mode 100644 .2119/verdicts/REQ-018.7.1--287fdd05a5c8.json create mode 100644 .2119/verdicts/REQ-018.8.1--0ffb67cebc0f.json create mode 100644 .2119/verdicts/REQ-018.9.1--bdeaa81c86a8.json create mode 100644 .2119/verdicts/REQ-019.1.1--94ff88e0b7d7.json create mode 100644 .2119/verdicts/REQ-019.2.1--b47ade7d9b70.json create mode 100644 .2119/verdicts/REQ-019.3.1--1c989032515b.json create mode 100644 .2119/verdicts/REQ-019.4.1--ec295a9bdc3c.json create mode 100644 .2119/verdicts/REQ-019.5.1--ce009f9b9a91.json create mode 100644 .2119/verdicts/REQ-019.6.1--a369bcab5837.json create mode 100644 .2119/verdicts/REQ-019.7.1--8d3d2fd0e769.json create mode 100644 .2119/verdicts/REQ-019.8.1--3fed30642ac4.json create mode 100644 .2119/verdicts/REQ-022.2.1--7b39ed38159b.json create mode 100644 .2119/verdicts/REQ-023.1.1--ab2c213bd85f.json create mode 100644 .2119/verdicts/REQ-023.2.1--c97806e04b9c.json create mode 100644 .2119/verdicts/REQ-023.3.1--79edea8071de.json create mode 100644 .2119/verdicts/REQ-023.4.1--cb5e56b153bf.json create mode 100644 .2119/verdicts/REQ-023.5.1--2d97bdd14cbd.json create mode 100644 .2119/verdicts/REQ-024.7.1--de6bf76ae254.json create mode 100644 .2119/verdicts/REQ-025.1.1--0b9b1e9b8d88.json create mode 100644 .2119/verdicts/REQ-026.1.1--33859f27dd42.json create mode 100644 .2119/verdicts/REQ-026.1.2--cc283c1dba64.json create mode 100644 .2119/verdicts/REQ-026.1.3--1a42bb5edb23.json create mode 100644 .2119/verdicts/REQ-026.2.1--8474634b145c.json create mode 100644 .2119/verdicts/REQ-026.2.3--9234323661a0.json create mode 100644 .2119/verdicts/REQ-026.3.1--7149538d9e8d.json create mode 100644 .2119/verdicts/REQ-026.3.2--a8d92f5a98f4.json create mode 100644 .2119/verdicts/REQ-026.3.3--28e8e14e95cb.json create mode 100644 .2119/verdicts/REQ-026.3.4--a01bf1446254.json create mode 100644 .2119/verdicts/REQ-026.3.5--75bdf83a2bee.json create mode 100644 .2119/verdicts/REQ-026.4.1--d2fe3accd242.json create mode 100644 .2119/verdicts/REQ-026.4.2--33f446d79e00.json create mode 100644 .2119/verdicts/REQ-026.4.3--cf130bfb16b1.json create mode 100644 .2119/verdicts/REQ-026.5.1--218063677b29.json create mode 100644 .2119/verdicts/REQ-026.5.2--4f29fc3ed6bc.json create mode 100644 .2119/verdicts/REQ-026.5.3--17db970a1779.json create mode 100644 .2119/verdicts/REQ-026.6.1--1c4605b55497.json create mode 100644 .2119/verdicts/REQ-026.6.2--adae400ce7b0.json create mode 100644 .2119/verdicts/REQ-026.6.3--0e86a599b457.json create mode 100644 .2119/verdicts/REQ-026.6.4--eeee02ab8203.json create mode 100644 .2119/verdicts/REQ-026.6.5--a5cb9b38e497.json create mode 100644 .2119/verdicts/REQ-026.6.8--91f43e2e27db.json create mode 100644 .2119/verdicts/REQ-027.1.1--9b097314b437.json create mode 100644 .2119/verdicts/REQ-027.1.2--1755fcea5014.json create mode 100644 .2119/verdicts/REQ-027.1.3--ebfc2e908f28.json create mode 100644 .2119/verdicts/REQ-027.2.1--242da9f898a9.json create mode 100644 .2119/verdicts/REQ-027.2.2--ec081378b0c4.json create mode 100644 .2119/verdicts/REQ-027.2.3--1e08e4f61768.json create mode 100644 .2119/verdicts/REQ-027.3.1--bdca0cd677e5.json create mode 100644 .2119/verdicts/REQ-027.3.2--e186f432f0bd.json create mode 100644 .2119/verdicts/REQ-027.3.3--23f37cf06481.json create mode 100644 .2119/verdicts/REQ-027.3.4--a2198bb7d8fe.json create mode 100644 .2119/verdicts/REQ-028.1.1--4b5f0f4d3537.json create mode 100644 .2119/verdicts/REQ-028.10.1--e88c9711487f.json create mode 100644 .2119/verdicts/REQ-028.11.1--4d9fb91e910c.json create mode 100644 .2119/verdicts/REQ-028.12.1--e33951052195.json create mode 100644 .2119/verdicts/REQ-028.2.1--0ca7c6de125a.json create mode 100644 .2119/verdicts/REQ-028.3.1--de68f877febb.json create mode 100644 .2119/verdicts/REQ-028.4.1--3c13931b3341.json create mode 100644 .2119/verdicts/REQ-028.5.1--a0a6ceb6eb7c.json create mode 100644 .2119/verdicts/REQ-028.6.1--fa83331abede.json create mode 100644 .2119/verdicts/REQ-028.7.1--f5e423b157d4.json create mode 100644 .2119/verdicts/REQ-028.8.1--d6f04d9444f8.json create mode 100644 .2119/verdicts/REQ-028.8.2--dc7c9a4a7767.json create mode 100644 .2119/verdicts/REQ-028.8.3--dab34c2959bb.json create mode 100644 .2119/verdicts/REQ-028.9.1--10ee3479470d.json create mode 100644 .2119/verdicts/REQ-030.1.1--fc4516e92bee.json create mode 100644 .2119/verdicts/REQ-030.1.2--1aaca3cd2744.json create mode 100644 .2119/verdicts/REQ-030.1.3--aa334eb614ee.json create mode 100644 .2119/verdicts/REQ-030.2.1--0b6493ede8a8.json create mode 100644 .2119/verdicts/REQ-030.2.2--01e0e975dc09.json create mode 100644 .2119/verdicts/REQ-030.2.3--94cf3a001475.json create mode 100644 .2119/verdicts/REQ-030.2.4--191b47ca2bc8.json create mode 100644 .2119/verdicts/REQ-030.2.5--99f116196e6d.json create mode 100644 .2119/verdicts/REQ-030.3.1--bbce5b5ff87c.json create mode 100644 .2119/verdicts/REQ-030.3.2--6f32f8a5b92d.json create mode 100644 .2119/verdicts/REQ-030.4.1--fcb982be3c19.json create mode 100644 .2119/verdicts/REQ-030.4.2--e2386a63e29a.json create mode 100644 .2119/verdicts/REQ-030.4.3--2b80d13b4596.json create mode 100644 .2119/verdicts/REQ-030.4.4--655bc9a7029a.json create mode 100644 .2119/verdicts/REQ-030.4.5--a173543f9001.json create mode 100644 .2119/verdicts/REQ-030.4.6--b5f6e6ff6104.json create mode 100644 .2119/verdicts/REQ-030.5.1--27632b3c10c3.json create mode 100644 .2119/verdicts/REQ-030.5.2--208c7f5b26fe.json create mode 100644 .2119/verdicts/REQ-031.1.1--e7f3dae9271d.json create mode 100644 .2119/verdicts/REQ-031.1.2--7d809f596b36.json create mode 100644 .2119/verdicts/REQ-031.1.3--327a3558cbe5.json create mode 100644 .2119/verdicts/REQ-031.1.4--3f8fa11b7343.json create mode 100644 .2119/verdicts/REQ-031.1.5--0890e0a3d1f6.json create mode 100644 .2119/verdicts/REQ-031.2.1--bf2a81eb5e26.json create mode 100644 .2119/verdicts/REQ-031.2.2--0e533789f260.json create mode 100644 .2119/verdicts/REQ-031.3.1--60f6189f86fb.json create mode 100644 .2119/verdicts/REQ-032.1.1--a9f59b47de16.json create mode 100644 .2119/verdicts/REQ-032.1.2--d051cd38f4f8.json create mode 100644 .2119/verdicts/REQ-032.1.3--43c63811228f.json create mode 100644 .2119/verdicts/REQ-032.1.4--db9b38bf05df.json create mode 100644 .2119/verdicts/REQ-032.2.1--63a22d77cfec.json create mode 100644 .2119/verdicts/REQ-032.2.2--d735d095d2db.json create mode 100644 .2119/verdicts/REQ-032.3.1--688a8fd081ad.json create mode 100644 .2119/verdicts/REQ-032.4.1--671e6841d69d.json create mode 100644 .2119/verdicts/REQ-032.5.1--70fb49eea63b.json create mode 100644 .2119/verdicts/REQ-032.5.2--9d7d8694c538.json create mode 100644 .2119/verdicts/REQ-033.1.1--13e12d59f7c1.json create mode 100644 .2119/verdicts/REQ-033.10.1--5646eda74129.json create mode 100644 .2119/verdicts/REQ-033.2.1--7671d5851c4b.json create mode 100644 .2119/verdicts/REQ-033.3.1--589c2f732fa3.json create mode 100644 .2119/verdicts/REQ-033.4.1--bfc61d9d22bb.json create mode 100644 .2119/verdicts/REQ-033.5.1--3b6cf7b8204b.json create mode 100644 .2119/verdicts/REQ-033.6.1--dd9484d48bc0.json create mode 100644 .2119/verdicts/REQ-033.7.1--dee756ae075d.json create mode 100644 .2119/verdicts/REQ-033.8.1--63fa02856b1d.json create mode 100644 .2119/verdicts/REQ-033.9.1--1487d2b8cd0d.json create mode 100644 .2119/verdicts/REQ-034.1.1--aad04f3a549a.json create mode 100644 .2119/verdicts/REQ-034.1.2--2f9bb821dd9b.json create mode 100644 .2119/verdicts/REQ-034.2.1--0aefc39ecf18.json create mode 100644 .2119/verdicts/REQ-035.14.1--9e4827027914.json create mode 100644 .2119/verdicts/REQ-035.17.1--e5fc76cef15a.json create mode 100644 .2119/verdicts/REQ-035.29.1--3f5d79610567.json create mode 100644 .2119/verdicts/REQ-035.36.1--26cadbfb8714.json create mode 100644 .2119/verdicts/REQ-035.39.1--a64952b5956d.json create mode 100644 .2119/verdicts/REQ-035.4.1--278dcf0fb339.json create mode 100644 .2119/verdicts/REQ-035.45.1--b8383474bc32.json create mode 100644 .2119/verdicts/REQ-035.47.1--41345d31eb3c.json create mode 100644 .2119/verdicts/REQ-035.7.1--0f05671f85c7.json create mode 100644 .2119/verdicts/REQ-036.1.1--295553c79072.json create mode 100644 .2119/verdicts/REQ-038.1.1--318b536ed51a.json create mode 100644 .2119/verdicts/REQ-039.3.1--b679ab343b40.json create mode 100644 .2119/verdicts/REQ-039.4.1--29181ba2025f.json create mode 100644 .2119/verdicts/REQ-040.1.1--81c24293ebba.json create mode 100644 .2119/verdicts/REQ-040.2.1--669ef0f220bd.json create mode 100644 .2119/verdicts/REQ-040.3.1--c4c977a044cf.json create mode 100644 .2119/verdicts/REQ-040.4.1--30da005e8f76.json create mode 100644 .2119/verdicts/REQ-040.5.1--730d0ca6863f.json create mode 100644 .2119/verdicts/REQ-040.6.1--efc53f888ac8.json create mode 100644 .2119/verdicts/REQ-040.7.1--4183cea2d07e.json create mode 100644 .2119/verdicts/REQ-041.3.1--ec848982c3eb.json create mode 100644 .2119/verdicts/REQ-041.4.1--beede4b057e0.json create mode 100644 .2119/verdicts/REQ-042.1.1--58d2b3a829e4.json create mode 100644 .2119/verdicts/REQ-042.2.1--0c40ae502d40.json create mode 100644 .2119/verdicts/REQ-042.3.1--9eddfab894ec.json create mode 100644 .2119/verdicts/REQ-042.4.1--e40a191ba72f.json create mode 100644 .2119/verdicts/REQ-048.1.1--0d57ba4502bb.json create mode 100644 .2119/verdicts/REQ-048.1.2--9e22beb20779.json create mode 100644 .2119/verdicts/REQ-048.1.3--02ee3d06f9ef.json create mode 100644 .2119/verdicts/REQ-048.10.1--53d3f7c04a5e.json create mode 100644 .2119/verdicts/REQ-048.10.2--3455a0666537.json create mode 100644 .2119/verdicts/REQ-048.10.3--e6878234b6a9.json create mode 100644 .2119/verdicts/REQ-048.11.1--499768b56543.json create mode 100644 .2119/verdicts/REQ-048.11.2--5350832ca941.json create mode 100644 .2119/verdicts/REQ-048.11.3--88f702f07f65.json create mode 100644 .2119/verdicts/REQ-048.11.4--7715d1063b7f.json create mode 100644 .2119/verdicts/REQ-048.12.1--613161d69994.json create mode 100644 .2119/verdicts/REQ-048.12.2--a7e06fdd52c7.json create mode 100644 .2119/verdicts/REQ-048.2.1--c1c8e6ffa2a4.json create mode 100644 .2119/verdicts/REQ-048.2.2--017ed57b1bcc.json create mode 100644 .2119/verdicts/REQ-048.2.3--e9a75e193b15.json create mode 100644 .2119/verdicts/REQ-048.2.4--56e9501ae9b4.json create mode 100644 .2119/verdicts/REQ-048.3.1--e58fd8cea0df.json create mode 100644 .2119/verdicts/REQ-048.3.2--0cb054b37c60.json create mode 100644 .2119/verdicts/REQ-048.3.3--8d3ee45125d0.json create mode 100644 .2119/verdicts/REQ-048.4.1--069ac26b55f9.json create mode 100644 .2119/verdicts/REQ-048.4.2--7fc82aabb81b.json create mode 100644 .2119/verdicts/REQ-048.4.3--c827e2d037a4.json create mode 100644 .2119/verdicts/REQ-048.5.1--b27574118414.json create mode 100644 .2119/verdicts/REQ-048.5.2--f8d6164d043c.json create mode 100644 .2119/verdicts/REQ-048.5.3--b14998108cbe.json create mode 100644 .2119/verdicts/REQ-048.5.4--4737fec0f256.json create mode 100644 .2119/verdicts/REQ-048.6.1--5476f71f799e.json create mode 100644 .2119/verdicts/REQ-048.6.2--b40669d2ae91.json create mode 100644 .2119/verdicts/REQ-048.6.3--0fd81d927c61.json create mode 100644 .2119/verdicts/REQ-048.6.4--726594ae9dfe.json create mode 100644 .2119/verdicts/REQ-048.7.1--efeb5255d4af.json create mode 100644 .2119/verdicts/REQ-048.7.2--988df5e5a79f.json create mode 100644 .2119/verdicts/REQ-048.7.3--0f6269ae90ae.json create mode 100644 .2119/verdicts/REQ-048.7.4--86cc5d72cbe2.json create mode 100644 .2119/verdicts/REQ-048.8.1--8486b6a87004.json create mode 100644 .2119/verdicts/REQ-048.8.2--203e902b5831.json create mode 100644 .2119/verdicts/REQ-048.8.3--52b200a79982.json create mode 100644 .2119/verdicts/REQ-048.9.1--bf1843471699.json create mode 100644 .2119/verdicts/REQ-048.9.2--bfa7ff13dab6.json create mode 100644 .2119/verdicts/REQ-051.1.1--e0599fdfd09b.json create mode 100644 .2119/verdicts/REQ-051.1.2--3f4c8247a14b.json create mode 100644 .2119/verdicts/REQ-051.1.3--f1122a4a63e5.json create mode 100644 .2119/verdicts/REQ-051.2.1--439729068fa6.json create mode 100644 .2119/verdicts/REQ-051.2.2--126a77d1d874.json create mode 100644 .2119/verdicts/REQ-051.2.3--1e40002406e0.json create mode 100644 .2119/verdicts/REQ-051.2.4--40974079c6be.json create mode 100644 .2119/verdicts/REQ-051.2.5--f76b8581d32c.json create mode 100644 .2119/verdicts/REQ-051.2.6--9f28a5c59ac7.json create mode 100644 .2119/verdicts/REQ-051.3.1--9796d0085699.json create mode 100644 .2119/verdicts/REQ-051.3.2--31049781af77.json create mode 100644 .2119/verdicts/REQ-051.3.3--cd06027383d9.json create mode 100644 .2119/verdicts/REQ-051.4.1--dba58b727830.json create mode 100644 .2119/verdicts/REQ-051.4.2--9cb7a9a9a82b.json create mode 100644 .2119/verdicts/REQ-051.4.3--851966d5fee8.json create mode 100644 .2119/verdicts/REQ-051.4.4--0c1e64e78580.json create mode 100644 .2119/verdicts/REQ-051.4.5--7f27b19d0b5d.json create mode 100644 .2119/verdicts/REQ-051.4.6--3608b2771ce4.json create mode 100644 .2119/verdicts/REQ-051.4.7--8e80a3359472.json create mode 100644 .2119/verdicts/REQ-051.5.1--4685782778fb.json create mode 100644 .2119/verdicts/REQ-053.1.1--6077d61f80e1.json create mode 100644 .2119/verdicts/REQ-053.2.1--90fb89bcabaf.json create mode 100644 .2119/verdicts/REQ-053.3.1--59558cc9c9ab.json create mode 100644 .2119/verdicts/REQ-053.4.1--5092fb48dccf.json create mode 100644 .2119/verdicts/REQ-053.5.1--744581fafd50.json create mode 100644 .2119/verdicts/REQ-053.6.1--68901d04c6c4.json create mode 100644 .2119/verdicts/REQ-054.1.2--5978a59c4973.json create mode 100644 .2119/verdicts/REQ-054.1.3--a3e7162ad033.json create mode 100644 .2119/verdicts/REQ-054.7.1--8125a690752d.json create mode 100644 .2119/verdicts/REQ-054.7.2--4f643c009183.json create mode 100644 .2119/verdicts/REQ-054.7.6--a7d9a1ab4b4a.json create mode 100644 .2119/verdicts/REQ-054.7.7--1333db5ef5cf.json create mode 100644 .2119/verdicts/REQ-054.7.8--66facda09a35.json create mode 100644 .2119/verdicts/REQ-054.7.9--bab32ddd4708.json create mode 100644 .2119/verdicts/foreground-setup.1.3--3e1f6a7d24e5.json create mode 100644 .2119/verdicts/foreground-setup.1.6--832584d5ac1e.json create mode 100644 .2119/verdicts/full-width-dashboard.1.1--bf7a0d996595.json create mode 100644 .2119/verdicts/full-width-dashboard.1.2--9b22f04337ea.json create mode 100644 .2119/verdicts/layered-settings-hints.1.1--3df14fffa455.json create mode 100644 .2119/verdicts/layered-settings-hints.2.1--34f6c5b3b85d.json create mode 100644 .2119/verdicts/layered-settings-hints.3.1--38e6e3c9457e.json create mode 100644 .2119/verdicts/layered-settings-hints.4.1--d918efa5cdac.json create mode 100644 .2119/verdicts/layered-settings-hints.5.1--a77893723316.json create mode 100644 .2119/verdicts/layered-settings-hints.6.1--45e564af521a.json create mode 100644 .2119/verdicts/runtime-readiness.2.1--e28455ca485f.json create mode 100644 .2119/verdicts/runtime-readiness.2.2--6754e34f7505.json create mode 100644 .2119/verdicts/skip-terminal-provisioner.1.1--2ba145c5e504.json create mode 100644 .2119/verdicts/skip-terminal-provisioner.1.2--dc3ad69edc38.json create mode 100644 .2119/verdicts/task-auth-readiness.3.1--07095e3cf1e7.json create mode 100644 .2119/verdicts/task-auth-readiness.3.2--1965e7dbada3.json create mode 100644 .2119/verdicts/task-auth-readiness.3.3--462183793dd9.json create mode 100644 .2119/verdicts/task-auth-readiness.3.4--0c9955ebd1d0.json create mode 100644 .2119/verdicts/task-auth-readiness.3.5--6f59c463ca1e.json create mode 100644 .2119/verdicts/task-auth-readiness.3.6--e90052889e3f.json create mode 100644 .2119/verdicts/task-auth-readiness.3.7--c60ac8d6c312.json create mode 100644 .2119/verdicts/task-auth-readiness.3.8--45bd73b2a766.json create mode 100644 .2119/verdicts/task-auth-readiness.3.9--4afbbb4e0463.json diff --git a/.2119/verdicts/REQ-001.1.1--91a98485e5ee.json b/.2119/verdicts/REQ-001.1.1--91a98485e5ee.json new file mode 100644 index 0000000..ed0b06c --- /dev/null +++ b/.2119/verdicts/REQ-001.1.1--91a98485e5ee.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-001.1.1--91a98485e5ee", + "requirementId": "REQ-001.1.1", + "hash": "91a98485e5ee", + "verdict": "pass", + "summary": "Real x keypresses on first and second operator rows assert a confirmation names the highlighted workflow; wrong-row or missing-dialog behavior fails.", + "timestamp": "2026-09-14T07:52:36.066Z" +} diff --git a/.2119/verdicts/REQ-001.2.1--2971178e5e35.json b/.2119/verdicts/REQ-001.2.1--2971178e5e35.json new file mode 100644 index 0000000..2b94ad6 --- /dev/null +++ b/.2119/verdicts/REQ-001.2.1--2971178e5e35.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-001.2.1--2971178e5e35", + "requirementId": "REQ-001.2.1", + "hash": "2971178e5e35", + "verdict": "pass", + "summary": "Mounted confirmation asserts visible enabled Yes and No buttons; clicking each exercises both paths, rejecting a missing or inert choice.", + "timestamp": "2026-09-14T07:52:37.314Z" +} diff --git a/.2119/verdicts/REQ-001.3.1--dae4d92b8d2a.json b/.2119/verdicts/REQ-001.3.1--dae4d92b8d2a.json new file mode 100644 index 0000000..7a1759a --- /dev/null +++ b/.2119/verdicts/REQ-001.3.1--dae4d92b8d2a.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-001.3.1--dae4d92b8d2a", + "requirementId": "REQ-001.3.1", + "hash": "dae4d92b8d2a", + "verdict": "pass", + "summary": "Parameterized No and Escape cancellation dismisses the modal and verifies the original file contents remain intact.", + "timestamp": "2026-09-14T07:52:38.601Z" +} diff --git a/.2119/verdicts/REQ-001.4.1--b17d9c27fb31.json b/.2119/verdicts/REQ-001.4.1--b17d9c27fb31.json new file mode 100644 index 0000000..e630053 --- /dev/null +++ b/.2119/verdicts/REQ-001.4.1--b17d9c27fb31.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-001.4.1--b17d9c27fb31", + "requirementId": "REQ-001.4.1", + "hash": "b17d9c27fb31", + "verdict": "pass", + "summary": "Yes deletes only the selected real file and triggers a second registry fetch whose changed description must appear in the table.", + "timestamp": "2026-09-14T07:52:39.777Z" +} diff --git a/.2119/verdicts/REQ-001.5.1--dece1a1a4b8b.json b/.2119/verdicts/REQ-001.5.1--dece1a1a4b8b.json new file mode 100644 index 0000000..04eb4dc --- /dev/null +++ b/.2119/verdicts/REQ-001.5.1--dece1a1a4b8b.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-001.5.1--dece1a1a4b8b", + "requirementId": "REQ-001.5.1", + "hash": "dece1a1a4b8b", + "verdict": "pass", + "summary": "Built-in x request leaves real file contents intact and stays on WorkflowsScreen, rejecting deletion or a confirmation dialog.", + "timestamp": "2026-09-14T07:52:41.006Z" +} diff --git a/.2119/verdicts/REQ-001.6.1--fc6c297d4089.json b/.2119/verdicts/REQ-001.6.1--fc6c297d4089.json new file mode 100644 index 0000000..7355bcb --- /dev/null +++ b/.2119/verdicts/REQ-001.6.1--fc6c297d4089.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-001.6.1--fc6c297d4089", + "requirementId": "REQ-001.6.1", + "hash": "fc6c297d4089", + "verdict": "pass", + "summary": "Confirmation labels equal the complete file-removal and next-service-restart explanation, rejecting an immediate-unload claim.", + "timestamp": "2026-09-14T07:52:42.169Z" +} diff --git a/.2119/verdicts/REQ-001.7.1--394756dff78c.json b/.2119/verdicts/REQ-001.7.1--394756dff78c.json new file mode 100644 index 0000000..9f358ad --- /dev/null +++ b/.2119/verdicts/REQ-001.7.1--394756dff78c.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-001.7.1--394756dff78c", + "requirementId": "REQ-001.7.1", + "hash": "394756dff78c", + "verdict": "pass", + "summary": "Mounted dialog checks 56 columns, auto height, centered x/y, round accent border and surface background against independently checked new-workflow styles.", + "timestamp": "2026-09-14T07:52:43.370Z" +} diff --git a/.2119/verdicts/REQ-001.8.1--333d9a5a1792.json b/.2119/verdicts/REQ-001.8.1--333d9a5a1792.json new file mode 100644 index 0000000..517f0f6 --- /dev/null +++ b/.2119/verdicts/REQ-001.8.1--333d9a5a1792.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-001.8.1--333d9a5a1792", + "requirementId": "REQ-001.8.1", + "hash": "333d9a5a1792", + "verdict": "pass", + "summary": "Notifications are cleared before x; the built-in rejection must emit exactly the cannot-delete message at request time.", + "timestamp": "2026-09-14T07:52:44.500Z" +} diff --git a/.2119/verdicts/REQ-004.1.1--6c292078b9c1.json b/.2119/verdicts/REQ-004.1.1--6c292078b9c1.json new file mode 100644 index 0000000..38edbbf --- /dev/null +++ b/.2119/verdicts/REQ-004.1.1--6c292078b9c1.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-004.1.1--6c292078b9c1", + "requirementId": "REQ-004.1.1", + "hash": "6c292078b9c1", + "verdict": "pass", + "summary": "Real-git acceptance reads repository-local user.name == 'Panopticon Agent' after a fresh prepare and again after a leaked local identity is re-prepared; spawn unit tests pin the exact 'git config --local user.name' argv on both the fresh and existing-checkout paths, so a wrong name, a non-local scope, or a skipped reassert on an existing workspace all fail.", + "timestamp": "2026-09-14T21:29:19.017Z" +} diff --git a/.2119/verdicts/REQ-004.2.1--485807dc2fdb.json b/.2119/verdicts/REQ-004.2.1--485807dc2fdb.json new file mode 100644 index 0000000..63ac591 --- /dev/null +++ b/.2119/verdicts/REQ-004.2.1--485807dc2fdb.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-004.2.1--485807dc2fdb", + "requirementId": "REQ-004.2.1", + "hash": "485807dc2fdb", + "verdict": "pass", + "summary": "Real-git acceptance reads repository-local user.email == 'panopticon-agent@users.noreply.github.com' after a fresh prepare and again after a leaked local email is re-prepared; spawn unit tests pin the exact 'git config --local user.email' argv on fresh and existing-checkout paths, rejecting a wrong address, a non-local scope, or a skipped reassert.", + "timestamp": "2026-09-14T21:29:20.207Z" +} diff --git a/.2119/verdicts/REQ-004.3.1--049ee602f14a.json b/.2119/verdicts/REQ-004.3.1--049ee602f14a.json new file mode 100644 index 0000000..63b6ecf --- /dev/null +++ b/.2119/verdicts/REQ-004.3.1--049ee602f14a.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-004.3.1--049ee602f14a", + "requirementId": "REQ-004.3.1", + "hash": "049ee602f14a", + "verdict": "pass", + "summary": "All three covering tests pass on this snapshot. Eight runtime counterexamples are rejected: real-Git acceptance detects added global name and email changes; both fresh and resumed preparation assertions reject added global, system, and other-repository identity writes. This tests the observable repository-local boundary without bypassing identity implementation.", + "timestamp": "2026-09-14T21:44:23.563Z" +} diff --git a/.2119/verdicts/REQ-006.1.1--d44d0ccd9c56.json b/.2119/verdicts/REQ-006.1.1--d44d0ccd9c56.json new file mode 100644 index 0000000..101951e --- /dev/null +++ b/.2119/verdicts/REQ-006.1.1--d44d0ccd9c56.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-006.1.1--d44d0ccd9c56", + "requirementId": "REQ-006.1.1", + "hash": "d44d0ccd9c56", + "verdict": "pass", + "summary": "An actual Ctrl+R keypress opens BulkRespawnScreen with down-task candidates; an unbound key or single-task action fails.", + "timestamp": "2026-09-14T07:52:45.699Z" +} diff --git a/.2119/verdicts/REQ-006.1.2--7f0324a80f87.json b/.2119/verdicts/REQ-006.1.2--7f0324a80f87.json new file mode 100644 index 0000000..c8ab93f --- /dev/null +++ b/.2119/verdicts/REQ-006.1.2--7f0324a80f87.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-006.1.2--7f0324a80f87", + "requirementId": "REQ-006.1.2", + "hash": "7f0324a80f87", + "verdict": "pass", + "summary": "The mounted help surface has exactly the Ctrl+R Respawn all down tasks line, rejecting a missing or mislabeled action.", + "timestamp": "2026-09-14T07:52:46.928Z" +} diff --git a/.2119/verdicts/REQ-006.2.1--f68843e37ef4.json b/.2119/verdicts/REQ-006.2.1--f68843e37ef4.json new file mode 100644 index 0000000..07a2970 --- /dev/null +++ b/.2119/verdicts/REQ-006.2.1--f68843e37ef4.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-006.2.1--f68843e37ef4", + "requirementId": "REQ-006.2.1", + "hash": "f68843e37ef4", + "verdict": "pass", + "summary": "Modal rows equal every down candidate and exclude live/failed tasks; replacing the service snapshot tests the exactly-one-down boundary.", + "timestamp": "2026-09-14T07:52:48.172Z" +} diff --git a/.2119/verdicts/REQ-006.2.2--f96755abbb86.json b/.2119/verdicts/REQ-006.2.2--f96755abbb86.json new file mode 100644 index 0000000..df64c0a --- /dev/null +++ b/.2119/verdicts/REQ-006.2.2--f96755abbb86.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-006.2.2--f96755abbb86", + "requirementId": "REQ-006.2.2", + "hash": "f96755abbb86", + "verdict": "pass", + "summary": "Exact modal lines check eight-character IDs, unset slug, absent/padded/multiline memos, normalization before truncation, and 60 versus 61 character ellipsis boundaries.", + "timestamp": "2026-09-14T07:52:49.405Z" +} diff --git a/.2119/verdicts/REQ-006.3.1--4badcd34aca2.json b/.2119/verdicts/REQ-006.3.1--4badcd34aca2.json new file mode 100644 index 0000000..4f5b4b7 --- /dev/null +++ b/.2119/verdicts/REQ-006.3.1--4badcd34aca2.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-006.3.1--4badcd34aca2", + "requirementId": "REQ-006.3.1", + "hash": "4badcd34aca2", + "verdict": "pass", + "summary": "Escape from a real bulk modal restores the base screen and leaves the release-call list empty.", + "timestamp": "2026-09-14T07:52:50.609Z" +} diff --git a/.2119/verdicts/REQ-006.4.1--de5a493494bc.json b/.2119/verdicts/REQ-006.4.1--de5a493494bc.json new file mode 100644 index 0000000..30e185f --- /dev/null +++ b/.2119/verdicts/REQ-006.4.1--de5a493494bc.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-006.4.1--de5a493494bc", + "requirementId": "REQ-006.4.1", + "hash": "de5a493494bc", + "verdict": "pass", + "summary": "Confirmation logs exactly one current-status check and release for each still-down task; recovered statuses are checked but never released.", + "timestamp": "2026-09-14T07:52:51.812Z" +} diff --git a/.2119/verdicts/REQ-006.4.2--5070d484b6a6.json b/.2119/verdicts/REQ-006.4.2--5070d484b6a6.json new file mode 100644 index 0000000..6f8ff04 --- /dev/null +++ b/.2119/verdicts/REQ-006.4.2--5070d484b6a6.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-006.4.2--5070d484b6a6", + "requirementId": "REQ-006.4.2", + "hash": "5070d484b6a6", + "verdict": "pass", + "summary": "Reversed service order versus displayed order, exact check/release events, and overlapping-release detection reject reordered or parallel processing.", + "timestamp": "2026-09-14T07:52:53.021Z" +} diff --git a/.2119/verdicts/REQ-006.4.3--dececf5c56bf.json b/.2119/verdicts/REQ-006.4.3--dececf5c56bf.json new file mode 100644 index 0000000..38f3404 --- /dev/null +++ b/.2119/verdicts/REQ-006.4.3--dececf5c56bf.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-006.4.3--dececf5c56bf", + "requirementId": "REQ-006.4.3", + "hash": "dececf5c56bf", + "verdict": "pass", + "summary": "Exact final notifications verify respawned 2, 1, and 0 from actual release counts, including the real notification surface.", + "timestamp": "2026-09-14T07:52:54.220Z" +} diff --git a/.2119/verdicts/REQ-006.4.4--c44610ab8736.json b/.2119/verdicts/REQ-006.4.4--c44610ab8736.json new file mode 100644 index 0000000..f37c875 --- /dev/null +++ b/.2119/verdicts/REQ-006.4.4--c44610ab8736.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-006.4.4--c44610ab8736", + "requirementId": "REQ-006.4.4", + "hash": "c44610ab8736", + "verdict": "pass", + "summary": "After replacing the modal snapshot with each non-down service status, confirmation releases only the still-down sibling.", + "timestamp": "2026-09-14T07:52:55.463Z" +} diff --git a/.2119/verdicts/REQ-006.4.5--12089a98b38c.json b/.2119/verdicts/REQ-006.4.5--12089a98b38c.json new file mode 100644 index 0000000..cf78daf --- /dev/null +++ b/.2119/verdicts/REQ-006.4.5--12089a98b38c.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-006.4.5--12089a98b38c", + "requirementId": "REQ-006.4.5", + "hash": "12089a98b38c", + "verdict": "pass", + "summary": "Recovered-candidate cases assert the entire notification list is only the aggregate respawn count, rejecting task-specific skip notices.", + "timestamp": "2026-09-14T07:52:56.725Z" +} diff --git a/.2119/verdicts/REQ-006.5.1--9a86e76c176d.json b/.2119/verdicts/REQ-006.5.1--9a86e76c176d.json new file mode 100644 index 0000000..6fd1f1b --- /dev/null +++ b/.2119/verdicts/REQ-006.5.1--9a86e76c176d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-006.5.1--9a86e76c176d", + "requirementId": "REQ-006.5.1", + "hash": "9a86e76c176d", + "verdict": "pass", + "summary": "Empty, non-down, case-mismatched and whitespace-suffixed latest statuses produce exactly no down tasks, replacing an older down snapshot.", + "timestamp": "2026-09-14T07:52:57.931Z" +} diff --git a/.2119/verdicts/REQ-006.5.2--55168c9c65c2.json b/.2119/verdicts/REQ-006.5.2--55168c9c65c2.json new file mode 100644 index 0000000..14a9b0e --- /dev/null +++ b/.2119/verdicts/REQ-006.5.2--55168c9c65c2.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-006.5.2--55168c9c65c2", + "requirementId": "REQ-006.5.2", + "hash": "55168c9c65c2", + "verdict": "pass", + "summary": "No-down cases assert one base screen and no push_screen calls, including an empty latest snapshot and near-miss status strings.", + "timestamp": "2026-09-14T07:52:59.160Z" +} diff --git a/.2119/verdicts/REQ-007.1.1--30513083a049.json b/.2119/verdicts/REQ-007.1.1--30513083a049.json new file mode 100644 index 0000000..ecebc71 --- /dev/null +++ b/.2119/verdicts/REQ-007.1.1--30513083a049.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-007.1.1--30513083a049", + "requirementId": "REQ-007.1.1", + "hash": "30513083a049", + "verdict": "pass", + "summary": "Actual c dispatch copies the highlighted task detail and separately observes terminal and host clipboard attempts, including failure of either transport.", + "timestamp": "2026-09-14T07:53:00.376Z" +} diff --git a/.2119/verdicts/REQ-007.2.1--69086fc1c11d.json b/.2119/verdicts/REQ-007.2.1--69086fc1c11d.json new file mode 100644 index 0000000..0d5ccc5 --- /dev/null +++ b/.2119/verdicts/REQ-007.2.1--69086fc1c11d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-007.2.1--69086fc1c11d", + "requirementId": "REQ-007.2.1", + "hash": "69086fc1c11d", + "verdict": "pass", + "summary": "The open detail widget ends with the exact copy-key hint and a dim span covering that complete trailing line.", + "timestamp": "2026-09-14T07:53:01.642Z" +} diff --git a/.2119/verdicts/REQ-007.3.1--183403b178d1.json b/.2119/verdicts/REQ-007.3.1--183403b178d1.json new file mode 100644 index 0000000..0bfb096 --- /dev/null +++ b/.2119/verdicts/REQ-007.3.1--183403b178d1.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-007.3.1--183403b178d1", + "requirementId": "REQ-007.3.1", + "hash": "183403b178d1", + "verdict": "pass", + "summary": "render_detail is called independently and its full text and split lines exclude the UI-only copy-key hint.", + "timestamp": "2026-09-14T07:53:02.759Z" +} diff --git a/.2119/verdicts/REQ-008.5.1--6f645191cdc5.json b/.2119/verdicts/REQ-008.5.1--6f645191cdc5.json new file mode 100644 index 0000000..0cef5ed --- /dev/null +++ b/.2119/verdicts/REQ-008.5.1--6f645191cdc5.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-008.5.1--6f645191cdc5", + "requirementId": "REQ-008.5.1", + "hash": "6f645191cdc5", + "verdict": "pass", + "summary": "test_user_prompt_submit_waits_for_the_turn_write gates the injected client's set_turn and asserts the hook thread is still alive while the write is pending and only returns 0 after release with the ('t1','agent') call recorded, so a fire-and-forget/background write would fail thread.is_alive(); the codex config test pins UserPromptSubmit to `hook agent prompt`, and hook.main runs the same _run_callback path with the injected client (only the SIGALRM deadline is bypassed off the main thread).", + "timestamp": "2026-10-28T06:05:29.818Z" +} diff --git a/.2119/verdicts/REQ-008.6.1--a45d8276443f.json b/.2119/verdicts/REQ-008.6.1--a45d8276443f.json new file mode 100644 index 0000000..87e60f9 --- /dev/null +++ b/.2119/verdicts/REQ-008.6.1--a45d8276443f.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-008.6.1--a45d8276443f", + "requirementId": "REQ-008.6.1", + "hash": "a45d8276443f", + "verdict": "pass", + "summary": "Rendered-handler delayed-request tests enforce awaited settlement and bounded completion; native stored/custom/env-auth controls and idle/queued logout distinguish user from agent turns. Both always-agent and missing-active-guard mutants were rejected.", + "timestamp": "2026-09-14T08:55:40.829Z" +} diff --git a/.2119/verdicts/REQ-008.7.1--164b24717ff0.json b/.2119/verdicts/REQ-008.7.1--164b24717ff0.json new file mode 100644 index 0000000..56efd14 --- /dev/null +++ b/.2119/verdicts/REQ-008.7.1--164b24717ff0.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-008.7.1--164b24717ff0", + "requirementId": "REQ-008.7.1", + "hash": "164b24717ff0", + "verdict": "pass", + "summary": "A client forbids unversioned reads and changes the seed snapshot; rendered turn and first long-poll cursor must both use that versioned response.", + "timestamp": "2026-09-14T07:53:03.962Z" +} diff --git a/.2119/verdicts/REQ-011.1.3--83a4eb3fc522.json b/.2119/verdicts/REQ-011.1.3--83a4eb3fc522.json new file mode 100644 index 0000000..4371a3e --- /dev/null +++ b/.2119/verdicts/REQ-011.1.3--83a4eb3fc522.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-011.1.3--83a4eb3fc522", + "requirementId": "REQ-011.1.3", + "hash": "83a4eb3fc522", + "verdict": "pass", + "summary": "Pure composer test enumerates registered=True over runner_live x {None, every phase}: failed only for FAILED, live otherwise regardless of runner liveness; real-service test shows failed with the registration still open, then live after re-registration; reverting the registered branch to always-LIVE fails both", + "timestamp": "2026-09-14T07:58:32.215Z" +} diff --git a/.2119/verdicts/REQ-012.2.1--6a41573bbf33.json b/.2119/verdicts/REQ-012.2.1--6a41573bbf33.json new file mode 100644 index 0000000..b2a2cae --- /dev/null +++ b/.2119/verdicts/REQ-012.2.1--6a41573bbf33.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-012.2.1--6a41573bbf33", + "requirementId": "REQ-012.2.1", + "hash": "6a41573bbf33", + "verdict": "pass", + "summary": "Fable 5.1: REST creation with a declared workflow pair and a conflicting repo pair must return the workflow pair for a synthetic workflow and the real 2119-auto-sol; a repo-wins implementation fails both parameter cases.", + "timestamp": "2026-09-30T06:01:31.731Z" +} diff --git a/.2119/verdicts/REQ-012.2.2--b630075731fa.json b/.2119/verdicts/REQ-012.2.2--b630075731fa.json new file mode 100644 index 0000000..8b07bc2 --- /dev/null +++ b/.2119/verdicts/REQ-012.2.2--b630075731fa.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-012.2.2--b630075731fa", + "requirementId": "REQ-012.2.2", + "hash": "b630075731fa", + "verdict": "pass", + "summary": "Fable 5.1: a pairless workflow on a repo with codex/gpt-5.6-sol:medium must yield that pair; falling through to the claude app default changes the asserted harness and model.", + "timestamp": "2026-09-30T06:01:32.779Z" +} diff --git a/.2119/verdicts/REQ-012.2.4--db900f1233f5.json b/.2119/verdicts/REQ-012.2.4--db900f1233f5.json new file mode 100644 index 0000000..6aa3520 --- /dev/null +++ b/.2119/verdicts/REQ-012.2.4--db900f1233f5.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-012.2.4--db900f1233f5", + "requirementId": "REQ-012.2.4", + "hash": "db900f1233f5", + "verdict": "pass", + "summary": "Fable 5.1: app default is switched to codex and the reloaded task must carry the concrete name codex with a null model; a null or stale claude harness fails.", + "timestamp": "2026-09-30T06:01:33.829Z" +} diff --git a/.2119/verdicts/REQ-012.3.1--8e875204958d.json b/.2119/verdicts/REQ-012.3.1--8e875204958d.json new file mode 100644 index 0000000..182b187 --- /dev/null +++ b/.2119/verdicts/REQ-012.3.1--8e875204958d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-012.3.1--8e875204958d", + "requirementId": "REQ-012.3.1", + "hash": "8e875204958d", + "verdict": "pass", + "summary": "Fable 5.1: explicit codex beats both the app default and a repo default of claude; the workflow-pair case is rejected by the adjacent REQ-012.3.3 test. Persistence is only read from the create response here.", + "timestamp": "2026-09-30T06:01:34.870Z" +} diff --git a/.2119/verdicts/REQ-012.3.2--141dcdbd61e7.json b/.2119/verdicts/REQ-012.3.2--141dcdbd61e7.json new file mode 100644 index 0000000..485f7f2 --- /dev/null +++ b/.2119/verdicts/REQ-012.3.2--141dcdbd61e7.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-012.3.2--141dcdbd61e7", + "requirementId": "REQ-012.3.2", + "hash": "141dcdbd61e7", + "verdict": "pass", + "summary": "Fable 5.1: explicit model custom on a codex/gpt-5.6-sol:high workflow must give (codex, custom); keeping the pair model or changing the harness both fail.", + "timestamp": "2026-09-30T06:01:35.949Z" +} diff --git a/.2119/verdicts/REQ-012.3.3--5ae6529ee48b.json b/.2119/verdicts/REQ-012.3.3--5ae6529ee48b.json new file mode 100644 index 0000000..51f253d --- /dev/null +++ b/.2119/verdicts/REQ-012.3.3--5ae6529ee48b.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-012.3.3--5ae6529ee48b", + "requirementId": "REQ-012.3.3", + "hash": "5ae6529ee48b", + "verdict": "pass", + "summary": "Fable 5.1: explicit claude against a codex workflow pair must give (claude, None); leaking the losing pair's model fails the tuple assertion.", + "timestamp": "2026-09-30T06:01:37.013Z" +} diff --git a/.2119/verdicts/REQ-012.3.4--e6880201af26.json b/.2119/verdicts/REQ-012.3.4--e6880201af26.json new file mode 100644 index 0000000..b13f802 --- /dev/null +++ b/.2119/verdicts/REQ-012.3.4--e6880201af26.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-012.3.4--e6880201af26", + "requirementId": "REQ-012.3.4", + "hash": "e6880201af26", + "verdict": "pass", + "summary": "Fable 5.1: explicit codex equal to the workflow pair harness must keep gpt-5.6-sol:high; dropping the model on any explicit harness fails.", + "timestamp": "2026-09-30T06:01:38.130Z" +} diff --git a/.2119/verdicts/REQ-012.4.1--0d5b58044b12.json b/.2119/verdicts/REQ-012.4.1--0d5b58044b12.json new file mode 100644 index 0000000..c1b7951 --- /dev/null +++ b/.2119/verdicts/REQ-012.4.1--0d5b58044b12.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-012.4.1--0d5b58044b12", + "requirementId": "REQ-012.4.1", + "hash": "0d5b58044b12", + "verdict": "pass", + "summary": "Fable 5.1: deliberately unparseable model strings from repo, workflow and explicit sources must be accepted with 201 and returned byte-identical; validation or effort-splitting fails.", + "timestamp": "2026-09-30T06:01:39.185Z" +} diff --git a/.2119/verdicts/REQ-012.4.2--6db331c294bb.json b/.2119/verdicts/REQ-012.4.2--6db331c294bb.json new file mode 100644 index 0000000..0736440 --- /dev/null +++ b/.2119/verdicts/REQ-012.4.2--6db331c294bb.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-012.4.2--6db331c294bb", + "requirementId": "REQ-012.4.2", + "hash": "6db331c294bb", + "verdict": "pass", + "summary": "Fable 5.1: repo-derived, workflow-derived and explicit tasks are re-read after the repo defaults are patched and the workflow class defaults are changed; read-time resolution would return the replacement values.", + "timestamp": "2026-09-30T06:01:40.264Z" +} diff --git a/.2119/verdicts/REQ-012.4.3--ca698b73762b.json b/.2119/verdicts/REQ-012.4.3--ca698b73762b.json new file mode 100644 index 0000000..dc08927 --- /dev/null +++ b/.2119/verdicts/REQ-012.4.3--ca698b73762b.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-012.4.3--ca698b73762b", + "requirementId": "REQ-012.4.3", + "hash": "ca698b73762b", + "verdict": "pass", + "summary": "Fable 5.1: a task created before the app default changes must still read claude while a later task reads codex; storing null and resolving at read time fails.", + "timestamp": "2026-09-30T06:01:41.331Z" +} diff --git a/.2119/verdicts/REQ-012.5.1--d9944c97f8b1.json b/.2119/verdicts/REQ-012.5.1--d9944c97f8b1.json new file mode 100644 index 0000000..d60f219 --- /dev/null +++ b/.2119/verdicts/REQ-012.5.1--d9944c97f8b1.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-012.5.1--d9944c97f8b1", + "requirementId": "REQ-012.5.1", + "hash": "d9944c97f8b1", + "verdict": "pass", + "summary": "Fable 5.1: create with model and no harness, patch adding a model, and patch clearing the harness under an existing model are each rejected with 400, with a valid pair accepted as control.", + "timestamp": "2026-09-30T06:01:42.403Z" +} diff --git a/.2119/verdicts/REQ-015.1.1--eda22abe66fe.json b/.2119/verdicts/REQ-015.1.1--eda22abe66fe.json new file mode 100644 index 0000000..06afc98 --- /dev/null +++ b/.2119/verdicts/REQ-015.1.1--eda22abe66fe.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-015.1.1--eda22abe66fe", + "requirementId": "REQ-015.1.1", + "hash": "eda22abe66fe", + "verdict": "pass", + "summary": "test_argv_preserves_scrollback_for_new_and_resumed_sessions asserts `--no-alt-screen` in argv for both first-run and resumed sessions, and the exact-argv tests (first run, resume by id, agent-turn resume) pin the flag positionally; dropping the flag on either path is rejected.", + "timestamp": "2026-10-28T06:05:31.112Z" +} diff --git a/.2119/verdicts/REQ-016.1.1--41e9483c0e6e.json b/.2119/verdicts/REQ-016.1.1--41e9483c0e6e.json new file mode 100644 index 0000000..9da3862 --- /dev/null +++ b/.2119/verdicts/REQ-016.1.1--41e9483c0e6e.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-016.1.1--41e9483c0e6e", + "requirementId": "REQ-016.1.1", + "hash": "41e9483c0e6e", + "verdict": "pass", + "summary": "Full rendered hook inventory and real subprocess blackholes, later-request stalls, cumulative slow responses, malformed replies, and all three Pi handlers reject callbacks lasting three seconds or longer.", + "timestamp": "2026-09-14T08:55:41.833Z" +} diff --git a/.2119/verdicts/REQ-016.2.1--d586c75406ac.json b/.2119/verdicts/REQ-016.2.1--d586c75406ac.json new file mode 100644 index 0000000..3f83ef0 --- /dev/null +++ b/.2119/verdicts/REQ-016.2.1--d586c75406ac.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-016.2.1--d586c75406ac", + "requirementId": "REQ-016.2.1", + "hash": "d586c75406ac", + "verdict": "pass", + "summary": "Connection, timeout, protocol, status, malformed-response, and later-request failures execute shared callbacks or rendered Pi handlers; tests require successful completion without leaked failure output or values.", + "timestamp": "2026-09-14T08:55:42.859Z" +} diff --git a/.2119/verdicts/REQ-016.3.1--dc109b8614f4.json b/.2119/verdicts/REQ-016.3.1--dc109b8614f4.json new file mode 100644 index 0000000..bbdf89a --- /dev/null +++ b/.2119/verdicts/REQ-016.3.1--dc109b8614f4.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-016.3.1--dc109b8614f4", + "requirementId": "REQ-016.3.1", + "hash": "dc109b8614f4", + "verdict": "pass", + "summary": "Behavioral event matrix covers command hooks, background suppression, native Pi retries/tools/exhaustion/abort, active queued logout, and idle missing model/auth. Native mutations selecting agent after idle logout or user during queued work fail.", + "timestamp": "2026-09-14T08:55:43.825Z" +} diff --git a/.2119/verdicts/REQ-017.1.1--7bf3c56df43f.json b/.2119/verdicts/REQ-017.1.1--7bf3c56df43f.json new file mode 100644 index 0000000..7a9812f --- /dev/null +++ b/.2119/verdicts/REQ-017.1.1--7bf3c56df43f.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-017.1.1--7bf3c56df43f", + "requirementId": "REQ-017.1.1", + "hash": "7bf3c56df43f", + "verdict": "pass", + "summary": "v has no effect with details closed, opens the selected second task when open, and fetches a current slug rather than a stale table value.", + "timestamp": "2026-09-14T07:53:05.129Z" +} diff --git a/.2119/verdicts/REQ-017.2.1--a00904b9851d.json b/.2119/verdicts/REQ-017.2.1--a00904b9851d.json new file mode 100644 index 0000000..0f56b2c --- /dev/null +++ b/.2119/verdicts/REQ-017.2.1--a00904b9851d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-017.2.1--a00904b9851d", + "requirementId": "REQ-017.2.1", + "hash": "a00904b9851d", + "verdict": "pass", + "summary": "Submission trims surrounding whitespace, records exactly the selected task update, refreshes table/detail, and a rejected slug preserves old content and a running app.", + "timestamp": "2026-09-14T07:53:06.310Z" +} diff --git a/.2119/verdicts/REQ-017.3.1--1f335a1c90a2.json b/.2119/verdicts/REQ-017.3.1--1f335a1c90a2.json new file mode 100644 index 0000000..619bbd5 --- /dev/null +++ b/.2119/verdicts/REQ-017.3.1--1f335a1c90a2.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-017.3.1--1f335a1c90a2", + "requirementId": "REQ-017.3.1", + "hash": "1f335a1c90a2", + "verdict": "pass", + "summary": "Escape after editing records no set_slug call and leaves the existing slug in the detail pane.", + "timestamp": "2026-09-14T07:53:07.445Z" +} diff --git a/.2119/verdicts/REQ-017.4.1--184670458f97.json b/.2119/verdicts/REQ-017.4.1--184670458f97.json new file mode 100644 index 0000000..af57702 --- /dev/null +++ b/.2119/verdicts/REQ-017.4.1--184670458f97.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-017.4.1--184670458f97", + "requirementId": "REQ-017.4.1", + "hash": "184670458f97", + "verdict": "pass", + "summary": "Mounted detail rendering includes the exact v: edit slug trailing hint and checks its dim style.", + "timestamp": "2026-09-14T07:53:08.731Z" +} diff --git a/.2119/verdicts/REQ-018.1.1--36f169334eb4.json b/.2119/verdicts/REQ-018.1.1--36f169334eb4.json new file mode 100644 index 0000000..fdade1d --- /dev/null +++ b/.2119/verdicts/REQ-018.1.1--36f169334eb4.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.1.1--36f169334eb4", + "requirementId": "REQ-018.1.1", + "hash": "36f169334eb4", + "verdict": "pass", + "summary": "Before focus leaves the memo, labeled harness/model/effort widgets have nonzero widths and exact current values; missing or focus-only controls fail.", + "timestamp": "2026-09-14T07:53:09.892Z" +} diff --git a/.2119/verdicts/REQ-018.10.1--02f7cdac1115.json b/.2119/verdicts/REQ-018.10.1--02f7cdac1115.json new file mode 100644 index 0000000..ddf8598 --- /dev/null +++ b/.2119/verdicts/REQ-018.10.1--02f7cdac1115.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.10.1--02f7cdac1115", + "requirementId": "REQ-018.10.1", + "hash": "02f7cdac1115", + "verdict": "pass", + "summary": "Enter after filtered candidate navigation changes only the corresponding input and leaves MemoScreen open with no task creation.", + "timestamp": "2026-09-14T07:53:20.671Z" +} diff --git a/.2119/verdicts/REQ-018.11.1--0700ac1dd443.json b/.2119/verdicts/REQ-018.11.1--0700ac1dd443.json new file mode 100644 index 0000000..b68f5bd --- /dev/null +++ b/.2119/verdicts/REQ-018.11.1--0700ac1dd443.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.11.1--0700ac1dd443", + "requirementId": "REQ-018.11.1", + "hash": "0700ac1dd443", + "verdict": "pass", + "summary": "Typed and candidate-selected values survive harness changes; separate mixed cases distinguish touched model/effort from untouched siblings.", + "timestamp": "2026-09-14T07:53:21.999Z" +} diff --git a/.2119/verdicts/REQ-018.12.1--9f0ad8d77784.json b/.2119/verdicts/REQ-018.12.1--9f0ad8d77784.json new file mode 100644 index 0000000..02d8d5c --- /dev/null +++ b/.2119/verdicts/REQ-018.12.1--9f0ad8d77784.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.12.1--9f0ad8d77784", + "requirementId": "REQ-018.12.1", + "hash": "9f0ad8d77784", + "verdict": "pass", + "summary": "Exact rendered summaries cover all default sources and each override type; even a same-value override becomes this task, with API provenance coverage.", + "timestamp": "2026-09-14T07:53:23.253Z" +} diff --git a/.2119/verdicts/REQ-018.13.1--60a897302961.json b/.2119/verdicts/REQ-018.13.1--60a897302961.json new file mode 100644 index 0000000..3c90c9b --- /dev/null +++ b/.2119/verdicts/REQ-018.13.1--60a897302961.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.13.1--60a897302961", + "requirementId": "REQ-018.13.1", + "hash": "60a897302961", + "verdict": "pass", + "summary": "Typing a memo then Enter in the memo editor creates the task with identical memo and initial_prompt values.", + "timestamp": "2026-09-14T07:53:24.507Z" +} diff --git a/.2119/verdicts/REQ-018.14.1--982450c06998.json b/.2119/verdicts/REQ-018.14.1--982450c06998.json new file mode 100644 index 0000000..30c760c --- /dev/null +++ b/.2119/verdicts/REQ-018.14.1--982450c06998.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.14.1--982450c06998", + "requirementId": "REQ-018.14.1", + "hash": "982450c06998", + "verdict": "pass", + "summary": "Ctrl+S creates a task containing the memo while its initial_prompt remains None.", + "timestamp": "2026-09-14T07:53:25.695Z" +} diff --git a/.2119/verdicts/REQ-018.15.1--7d46336555bf.json b/.2119/verdicts/REQ-018.15.1--7d46336555bf.json new file mode 100644 index 0000000..186c0d8 --- /dev/null +++ b/.2119/verdicts/REQ-018.15.1--7d46336555bf.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.15.1--7d46336555bf", + "requirementId": "REQ-018.15.1", + "hash": "7d46336555bf", + "verdict": "pass", + "summary": "The configured editor argv and file round trip are verified separately from Ctrl+G UI dispatch; returned edited text is submitted from the memo.", + "timestamp": "2026-09-14T07:53:26.930Z" +} diff --git a/.2119/verdicts/REQ-018.16.1--be430fcdd292.json b/.2119/verdicts/REQ-018.16.1--be430fcdd292.json new file mode 100644 index 0000000..3576b3b --- /dev/null +++ b/.2119/verdicts/REQ-018.16.1--be430fcdd292.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.16.1--be430fcdd292", + "requirementId": "REQ-018.16.1", + "hash": "be430fcdd292", + "verdict": "pass", + "summary": "Focused Enter cycles through all registered harnesses in order and wraps without creating a task at any step.", + "timestamp": "2026-09-14T07:53:28.096Z" +} diff --git a/.2119/verdicts/REQ-018.17.1--f8a5cad3b0f3.json b/.2119/verdicts/REQ-018.17.1--f8a5cad3b0f3.json new file mode 100644 index 0000000..68373f7 --- /dev/null +++ b/.2119/verdicts/REQ-018.17.1--f8a5cad3b0f3.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.17.1--f8a5cad3b0f3", + "requirementId": "REQ-018.17.1", + "hash": "f8a5cad3b0f3", + "verdict": "pass", + "summary": "Both empty and nonempty candidate lists with no highlight leave MemoScreen open after Enter and issue no create call.", + "timestamp": "2026-09-14T07:53:29.297Z" +} diff --git a/.2119/verdicts/REQ-018.18.1--6848ec33e3eb.json b/.2119/verdicts/REQ-018.18.1--6848ec33e3eb.json new file mode 100644 index 0000000..96a28ae --- /dev/null +++ b/.2119/verdicts/REQ-018.18.1--6848ec33e3eb.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.18.1--6848ec33e3eb", + "requirementId": "REQ-018.18.1", + "hash": "6848ec33e3eb", + "verdict": "pass", + "summary": "Changing harness clears untouched model and effort; mixed touched-model case clears only effort and exact create payloads prove harness defaults survive.", + "timestamp": "2026-09-14T07:53:30.539Z" +} diff --git a/.2119/verdicts/REQ-018.19.1--6a4f04237f29.json b/.2119/verdicts/REQ-018.19.1--6a4f04237f29.json new file mode 100644 index 0000000..76dab84 --- /dev/null +++ b/.2119/verdicts/REQ-018.19.1--6a4f04237f29.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.19.1--6a4f04237f29", + "requirementId": "REQ-018.19.1", + "hash": "6a4f04237f29", + "verdict": "pass", + "summary": "Selector names and traversed values equal registered harnesses and wrap exactly once, rejecting arbitrary or omitted selectable names.", + "timestamp": "2026-09-14T07:53:31.806Z" +} diff --git a/.2119/verdicts/REQ-018.2.1--520062dd6068.json b/.2119/verdicts/REQ-018.2.1--520062dd6068.json new file mode 100644 index 0000000..0112433 --- /dev/null +++ b/.2119/verdicts/REQ-018.2.1--520062dd6068.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.2.1--520062dd6068", + "requirementId": "REQ-018.2.1", + "hash": "520062dd6068", + "verdict": "pass", + "summary": "Real forward Tab presses assert memo to harness to model to effort focus order.", + "timestamp": "2026-09-14T07:53:11.067Z" +} diff --git a/.2119/verdicts/REQ-018.20.1--4aeae9606abd.json b/.2119/verdicts/REQ-018.20.1--4aeae9606abd.json new file mode 100644 index 0000000..0ada70c --- /dev/null +++ b/.2119/verdicts/REQ-018.20.1--4aeae9606abd.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.20.1--4aeae9606abd", + "requirementId": "REQ-018.20.1", + "hash": "4aeae9606abd", + "verdict": "pass", + "summary": "No-match inputs leave a zero-option candidate list with nonzero visible width for both model and effort.", + "timestamp": "2026-09-14T07:53:33.044Z" +} diff --git a/.2119/verdicts/REQ-018.3.1--c7409bd3c4d9.json b/.2119/verdicts/REQ-018.3.1--c7409bd3c4d9.json new file mode 100644 index 0000000..392b9c7 --- /dev/null +++ b/.2119/verdicts/REQ-018.3.1--c7409bd3c4d9.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.3.1--c7409bd3c4d9", + "requirementId": "REQ-018.3.1", + "hash": "c7409bd3c4d9", + "verdict": "pass", + "summary": "Uppercase queries exercise case-insensitive substring filtering for both fields and compare complete visible candidate lists, rejecting prefix-only or extra results.", + "timestamp": "2026-09-14T07:53:12.205Z" +} diff --git a/.2119/verdicts/REQ-018.4.1--5d43058b90f2.json b/.2119/verdicts/REQ-018.4.1--5d43058b90f2.json new file mode 100644 index 0000000..95404a4 --- /dev/null +++ b/.2119/verdicts/REQ-018.4.1--5d43058b90f2.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.4.1--5d43058b90f2", + "requirementId": "REQ-018.4.1", + "hash": "5d43058b90f2", + "verdict": "pass", + "summary": "Down/Down/Up moves highlighted indices through filtered model and effort candidates before selecting the expected item.", + "timestamp": "2026-09-14T07:53:13.463Z" +} diff --git a/.2119/verdicts/REQ-018.5.1--90fbc7e3790d.json b/.2119/verdicts/REQ-018.5.1--90fbc7e3790d.json new file mode 100644 index 0000000..c9cb7b8 --- /dev/null +++ b/.2119/verdicts/REQ-018.5.1--90fbc7e3790d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.5.1--90fbc7e3790d", + "requirementId": "REQ-018.5.1", + "hash": "90fbc7e3790d", + "verdict": "pass", + "summary": "Values explicitly absent from suggestions are typed and submitted; model-only, effort-only and combined cases assert exact created starting_model values.", + "timestamp": "2026-09-14T07:53:14.666Z" +} diff --git a/.2119/verdicts/REQ-018.6.1--8298de0c08f6.json b/.2119/verdicts/REQ-018.6.1--8298de0c08f6.json new file mode 100644 index 0000000..3b523fc --- /dev/null +++ b/.2119/verdicts/REQ-018.6.1--8298de0c08f6.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.6.1--8298de0c08f6", + "requirementId": "REQ-018.6.1", + "hash": "8298de0c08f6", + "verdict": "pass", + "summary": "Cycling Claude to Codex changes the complete visible model and effort vocabularies to the selected harness fixtures.", + "timestamp": "2026-09-14T07:53:15.855Z" +} diff --git a/.2119/verdicts/REQ-018.7.1--287fdd05a5c8.json b/.2119/verdicts/REQ-018.7.1--287fdd05a5c8.json new file mode 100644 index 0000000..0d7319b --- /dev/null +++ b/.2119/verdicts/REQ-018.7.1--287fdd05a5c8.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.7.1--287fdd05a5c8", + "requirementId": "REQ-018.7.1", + "hash": "287fdd05a5c8", + "verdict": "pass", + "summary": "Focus-only reopen tracks changed repo/workflow/app defaults, touched-field controls preserve overrides, and real API default fields reach resolution unchanged.", + "timestamp": "2026-09-14T07:53:17.071Z" +} diff --git a/.2119/verdicts/REQ-018.8.1--0ffb67cebc0f.json b/.2119/verdicts/REQ-018.8.1--0ffb67cebc0f.json new file mode 100644 index 0000000..40280b5 --- /dev/null +++ b/.2119/verdicts/REQ-018.8.1--0ffb67cebc0f.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.8.1--0ffb67cebc0f", + "requirementId": "REQ-018.8.1", + "hash": "0ffb67cebc0f", + "verdict": "pass", + "summary": "Escape is tested from memo and every launch control, with model/effort lists visible, and creates no task.", + "timestamp": "2026-09-14T07:53:18.280Z" +} diff --git a/.2119/verdicts/REQ-018.9.1--bdeaa81c86a8.json b/.2119/verdicts/REQ-018.9.1--bdeaa81c86a8.json new file mode 100644 index 0000000..7d138ac --- /dev/null +++ b/.2119/verdicts/REQ-018.9.1--bdeaa81c86a8.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-018.9.1--bdeaa81c86a8", + "requirementId": "REQ-018.9.1", + "hash": "bdeaa81c86a8", + "verdict": "pass", + "summary": "Mounted memo width equals 64 before control focus and while each candidate list is visible.", + "timestamp": "2026-09-14T07:53:19.491Z" +} diff --git a/.2119/verdicts/REQ-019.1.1--94ff88e0b7d7.json b/.2119/verdicts/REQ-019.1.1--94ff88e0b7d7.json new file mode 100644 index 0000000..b0980e2 --- /dev/null +++ b/.2119/verdicts/REQ-019.1.1--94ff88e0b7d7.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-019.1.1--94ff88e0b7d7", + "requirementId": "REQ-019.1.1", + "hash": "94ff88e0b7d7", + "verdict": "pass", + "summary": "A blocked discovery worker remains unreleased while the mounted memo accepts x, rejecting synchronous mount or input blocking.", + "timestamp": "2026-09-14T07:53:34.306Z" +} diff --git a/.2119/verdicts/REQ-019.2.1--b47ade7d9b70.json b/.2119/verdicts/REQ-019.2.1--b47ade7d9b70.json new file mode 100644 index 0000000..5b23437 --- /dev/null +++ b/.2119/verdicts/REQ-019.2.1--b47ade7d9b70.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-019.2.1--b47ade7d9b70", + "requirementId": "REQ-019.2.1", + "hash": "b47ade7d9b70", + "verdict": "pass", + "summary": "Per-harness model/effort call counts remain exactly one through repeated cycling, early close, and discovery errors.", + "timestamp": "2026-09-14T07:53:35.575Z" +} diff --git a/.2119/verdicts/REQ-019.3.1--1c989032515b.json b/.2119/verdicts/REQ-019.3.1--1c989032515b.json new file mode 100644 index 0000000..dc4f96d --- /dev/null +++ b/.2119/verdicts/REQ-019.3.1--1c989032515b.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-019.3.1--1c989032515b", + "requirementId": "REQ-019.3.1", + "hash": "1c989032515b", + "verdict": "pass", + "summary": "Reopening requires generation-2 model and effort suggestions, rejecting cached values from the preceding modal.", + "timestamp": "2026-09-14T07:53:36.835Z" +} diff --git a/.2119/verdicts/REQ-019.4.1--ec295a9bdc3c.json b/.2119/verdicts/REQ-019.4.1--ec295a9bdc3c.json new file mode 100644 index 0000000..72db5f7 --- /dev/null +++ b/.2119/verdicts/REQ-019.4.1--ec295a9bdc3c.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-019.4.1--ec295a9bdc3c", + "requirementId": "REQ-019.4.1", + "hash": "ec295a9bdc3c", + "verdict": "pass", + "summary": "Both already-running and not-yet-started discovery cases populate the selected harness cache on cycle and render its model/effort vocabulary without duplicate calls.", + "timestamp": "2026-09-14T07:53:38.065Z" +} diff --git a/.2119/verdicts/REQ-019.5.1--ce009f9b9a91.json b/.2119/verdicts/REQ-019.5.1--ce009f9b9a91.json new file mode 100644 index 0000000..ae1c589 --- /dev/null +++ b/.2119/verdicts/REQ-019.5.1--ce009f9b9a91.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-019.5.1--ce009f9b9a91", + "requirementId": "REQ-019.5.1", + "hash": "ce009f9b9a91", + "verdict": "pass", + "summary": "Completed-discovery cycles time actual selection, summary, placeholder and candidate updates with perf_counter and assert each is under 10 milliseconds.", + "timestamp": "2026-09-14T07:53:39.378Z" +} diff --git a/.2119/verdicts/REQ-019.6.1--a369bcab5837.json b/.2119/verdicts/REQ-019.6.1--a369bcab5837.json new file mode 100644 index 0000000..53408bf --- /dev/null +++ b/.2119/verdicts/REQ-019.6.1--a369bcab5837.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-019.6.1--a369bcab5837", + "requirementId": "REQ-019.6.1", + "hash": "a369bcab5837", + "verdict": "pass", + "summary": "Closing during a failing discovery preserves a running dashboard and produces no notification after the worker is released.", + "timestamp": "2026-09-14T07:53:40.626Z" +} diff --git a/.2119/verdicts/REQ-019.7.1--8d3d2fd0e769.json b/.2119/verdicts/REQ-019.7.1--8d3d2fd0e769.json new file mode 100644 index 0000000..64a74b1 --- /dev/null +++ b/.2119/verdicts/REQ-019.7.1--8d3d2fd0e769.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-019.7.1--8d3d2fd0e769", + "requirementId": "REQ-019.7.1", + "hash": "8d3d2fd0e769", + "verdict": "pass", + "summary": "An in-flight discovery is released after closure; presentation attempts are forbidden and all closed-widget values, candidates, suggesters and classes remain unchanged.", + "timestamp": "2026-09-14T07:53:41.889Z" +} diff --git a/.2119/verdicts/REQ-019.8.1--3fed30642ac4.json b/.2119/verdicts/REQ-019.8.1--3fed30642ac4.json new file mode 100644 index 0000000..e17fe37 --- /dev/null +++ b/.2119/verdicts/REQ-019.8.1--3fed30642ac4.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-019.8.1--3fed30642ac4", + "requirementId": "REQ-019.8.1", + "hash": "3fed30642ac4", + "verdict": "pass", + "summary": "A harness returning multiple model and effort entries must present those exact lists with labels and the expected model passed into effort discovery.", + "timestamp": "2026-09-14T07:53:43.113Z" +} diff --git a/.2119/verdicts/REQ-022.2.1--7b39ed38159b.json b/.2119/verdicts/REQ-022.2.1--7b39ed38159b.json new file mode 100644 index 0000000..06032cb --- /dev/null +++ b/.2119/verdicts/REQ-022.2.1--7b39ed38159b.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-022.2.1--7b39ed38159b", + "requirementId": "REQ-022.2.1", + "hash": "7b39ed38159b", + "verdict": "pass", + "summary": "Scope is honest: both tests enumerate only built-in workflows via discover_workflows with home/path dirs suppressed, and Workflow.image_layer() is the sole channel the task service serves and the spawner composes (only spec_2119 overrides it, delegating to CodexHarness.image_layer(), which the audit gate pins byte-for-byte at CODEX_VERSION 0.159.1 so it is non-vacuous). Counterexamples rejected: adding `RUN apt-get install --yes gh` to spike's layer is caught by the `\\bgh\\b` offender scan and by the exact-bytes gate; an obfuscated install (`curl .../gh_2.x.tar.gz | tar` + `install .../bin/gh`) still matches `/bin/gh` and in any case differs from pinned bytes; a newly shipped workflow with any gh layer breaks the exact dict equality. Weakness noted but not material: the regex is keyword-based (would false-positive on a comment mentioning gh) and the exact gate is a change detector that also trips on legitimate codex bumps, relying on human re-audit — yet no gh-reinstalling shipped layer can pass without editing a test. Annotation uses section ID REQ-022.2 (its only bullet), which is permitted; the requirement is a static, observable constraint on shipped fragment content and is testable as stated.", + "timestamp": "2026-10-28T06:16:01.683Z" +} diff --git a/.2119/verdicts/REQ-023.1.1--ab2c213bd85f.json b/.2119/verdicts/REQ-023.1.1--ab2c213bd85f.json new file mode 100644 index 0000000..24aabca --- /dev/null +++ b/.2119/verdicts/REQ-023.1.1--ab2c213bd85f.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-023.1.1--ab2c213bd85f", + "requirementId": "REQ-023.1.1", + "hash": "ab2c213bd85f", + "verdict": "pass", + "summary": "Collapsed rows hide children and grandchildren, count direct children only, render exact dim summary text/connectors, and update after snapshot changes.", + "timestamp": "2026-09-14T07:53:44.336Z" +} diff --git a/.2119/verdicts/REQ-023.2.1--c97806e04b9c.json b/.2119/verdicts/REQ-023.2.1--c97806e04b9c.json new file mode 100644 index 0000000..5d80be6 --- /dev/null +++ b/.2119/verdicts/REQ-023.2.1--c97806e04b9c.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-023.2.1--c97806e04b9c", + "requirementId": "REQ-023.2.1", + "hash": "c97806e04b9c", + "verdict": "pass", + "summary": "Root, nested and terminal governors render exact right/down disclosures as actual Enter toggles collapsed and expanded states.", + "timestamp": "2026-09-14T07:53:45.529Z" +} diff --git a/.2119/verdicts/REQ-023.3.1--79edea8071de.json b/.2119/verdicts/REQ-023.3.1--79edea8071de.json new file mode 100644 index 0000000..218f5a9 --- /dev/null +++ b/.2119/verdicts/REQ-023.3.1--79edea8071de.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-023.3.1--79edea8071de", + "requirementId": "REQ-023.3.1", + "hash": "79edea8071de", + "verdict": "pass", + "summary": "Repeated Enter toggles rows without service mutations; a fresh app resets display state and search keeps matching governed tasks expanded.", + "timestamp": "2026-09-14T07:53:46.736Z" +} diff --git a/.2119/verdicts/REQ-023.4.1--cb5e56b153bf.json b/.2119/verdicts/REQ-023.4.1--cb5e56b153bf.json new file mode 100644 index 0000000..fedd24b --- /dev/null +++ b/.2119/verdicts/REQ-023.4.1--cb5e56b153bf.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-023.4.1--cb5e56b153bf", + "requirementId": "REQ-023.4.1", + "hash": "cb5e56b153bf", + "verdict": "pass", + "summary": "Down and Up skip the summary between real rows, and Down at a trailing summary keeps the real governor selected.", + "timestamp": "2026-09-14T07:53:48.040Z" +} diff --git a/.2119/verdicts/REQ-023.5.1--2d97bdd14cbd.json b/.2119/verdicts/REQ-023.5.1--2d97bdd14cbd.json new file mode 100644 index 0000000..fc1b78c --- /dev/null +++ b/.2119/verdicts/REQ-023.5.1--2d97bdd14cbd.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-023.5.1--2d97bdd14cbd", + "requirementId": "REQ-023.5.1", + "hash": "2d97bdd14cbd", + "verdict": "pass", + "summary": "Mounted help has exactly one ensemble line identifying Enter and both collapse and expand operations.", + "timestamp": "2026-09-14T07:53:49.553Z" +} diff --git a/.2119/verdicts/REQ-024.7.1--de6bf76ae254.json b/.2119/verdicts/REQ-024.7.1--de6bf76ae254.json new file mode 100644 index 0000000..51e1acf --- /dev/null +++ b/.2119/verdicts/REQ-024.7.1--de6bf76ae254.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-024.7.1--de6bf76ae254", + "requirementId": "REQ-024.7.1", + "hash": "de6bf76ae254", + "verdict": "pass", + "summary": "Exact mounted details and help text match lowercase y for slug and Shift+Y for ID; the associated case-sensitive keymap entries are also checked.", + "timestamp": "2026-09-14T07:53:50.753Z" +} diff --git a/.2119/verdicts/REQ-025.1.1--0b9b1e9b8d88.json b/.2119/verdicts/REQ-025.1.1--0b9b1e9b8d88.json new file mode 100644 index 0000000..2ef70d4 --- /dev/null +++ b/.2119/verdicts/REQ-025.1.1--0b9b1e9b8d88.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-025.1.1--0b9b1e9b8d88", + "requirementId": "REQ-025.1.1", + "hash": "0b9b1e9b8d88", + "verdict": "pass", + "summary": "Fable 5.1: task records flow through resolve_join and attach_target to the exact tmux status-left argument for local and ssh attaches; slug-only, memo-only and swapped formats are distinguished by sibling cases.", + "timestamp": "2026-09-30T06:01:44.552Z" +} diff --git a/.2119/verdicts/REQ-026.1.1--33859f27dd42.json b/.2119/verdicts/REQ-026.1.1--33859f27dd42.json new file mode 100644 index 0000000..5610955 --- /dev/null +++ b/.2119/verdicts/REQ-026.1.1--33859f27dd42.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.1.1--33859f27dd42", + "requirementId": "REQ-026.1.1", + "hash": "33859f27dd42", + "verdict": "pass", + "summary": "Candidate filtering rejects single and mixed active dependencies; host wiring and claim rechecks retain the gate.", + "timestamp": "2026-09-14T06:52:11.535Z" +} diff --git a/.2119/verdicts/REQ-026.1.2--cc283c1dba64.json b/.2119/verdicts/REQ-026.1.2--cc283c1dba64.json new file mode 100644 index 0000000..c2a3d18 --- /dev/null +++ b/.2119/verdicts/REQ-026.1.2--cc283c1dba64.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.1.2--cc283c1dba64", + "requirementId": "REQ-026.1.2", + "hash": "cc283c1dba64", + "verdict": "pass", + "summary": "Candidate filtering rejects single and mixed dropped dependencies; host dispatch and stale-claim checks preserve exclusion.", + "timestamp": "2026-09-14T06:52:12.535Z" +} diff --git a/.2119/verdicts/REQ-026.1.3--1a42bb5edb23.json b/.2119/verdicts/REQ-026.1.3--1a42bb5edb23.json new file mode 100644 index 0000000..10c293b --- /dev/null +++ b/.2119/verdicts/REQ-026.1.3--1a42bb5edb23.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.1.3--1a42bb5edb23", + "requirementId": "REQ-026.1.3", + "hash": "1a42bb5edb23", + "verdict": "pass", + "summary": "Real-service spawner tests prove the dependent is unspawnable until the last dependency reaches COMPLETE or a custom terminal state, then spawn_one claims it and forwards initial_prompt to the runner; test_host rejects a DROPPED dependency; a mutation that never clears the gate fails all covering tests.", + "timestamp": "2026-09-14T07:09:23.489Z" +} diff --git a/.2119/verdicts/REQ-026.2.1--8474634b145c.json b/.2119/verdicts/REQ-026.2.1--8474634b145c.json new file mode 100644 index 0000000..f3ed3d3 --- /dev/null +++ b/.2119/verdicts/REQ-026.2.1--8474634b145c.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.2.1--8474634b145c", + "requirementId": "REQ-026.2.1", + "hash": "8474634b145c", + "verdict": "pass", + "summary": "Composer test rejects unclaimed+blocking→anything but gated, claimed+blocking→down, terminal+blocking→'–'; API test asserts gated with a non-terminal dependency at creation and stays gated after the dependency is DROPPED (treating DROPPED as satisfying would fail persisted['container_status']=='gated').", + "timestamp": "2026-10-28T06:05:33.632Z" +} diff --git a/.2119/verdicts/REQ-026.2.3--9234323661a0.json b/.2119/verdicts/REQ-026.2.3--9234323661a0.json new file mode 100644 index 0000000..faf6778 --- /dev/null +++ b/.2119/verdicts/REQ-026.2.3--9234323661a0.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.2.3--9234323661a0", + "requirementId": "REQ-026.2.3", + "hash": "9234323661a0", + "verdict": "pass", + "summary": "test_task_responses_use_workflow_terminality_for_dependency_readiness uses a custom workflow whose terminal state is ARCHIVED (not COMPLETE), asserts gated while one of two deps is archived and queued only after both, so hardcoding COMPLETE or caching stale state is rejected; the test_mcp annotation only asserts a `terminal` field and is incidental.", + "timestamp": "2026-10-28T06:05:34.916Z" +} diff --git a/.2119/verdicts/REQ-026.3.1--7149538d9e8d.json b/.2119/verdicts/REQ-026.3.1--7149538d9e8d.json new file mode 100644 index 0000000..bb00fb6 --- /dev/null +++ b/.2119/verdicts/REQ-026.3.1--7149538d9e8d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.3.1--7149538d9e8d", + "requirementId": "REQ-026.3.1", + "hash": "7149538d9e8d", + "verdict": "pass", + "summary": "Dependency-wait rows exercise live, gated and agent-turn cases, with exact held/held 1 text and dim-only styling; attention and dropped-only controls remain orange.", + "timestamp": "2026-09-14T07:53:51.984Z" +} diff --git a/.2119/verdicts/REQ-026.3.2--a8d92f5a98f4.json b/.2119/verdicts/REQ-026.3.2--a8d92f5a98f4.json new file mode 100644 index 0000000..a7d87a3 --- /dev/null +++ b/.2119/verdicts/REQ-026.3.2--a8d92f5a98f4.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.3.2--a8d92f5a98f4", + "requirementId": "REQ-026.3.2", + "hash": "a8d92f5a98f4", + "verdict": "pass", + "summary": "Fable 5.1: a gated dependent's persisted turn stays user across the API before and after its dependency drops, the Actor vocabulary is pinned to agent/user, and the dashboard renders held without mutating the task records.", + "timestamp": "2026-09-30T06:01:47.753Z" +} diff --git a/.2119/verdicts/REQ-026.3.3--28e8e14e95cb.json b/.2119/verdicts/REQ-026.3.3--28e8e14e95cb.json new file mode 100644 index 0000000..8786144 --- /dev/null +++ b/.2119/verdicts/REQ-026.3.3--28e8e14e95cb.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.3.3--28e8e14e95cb", + "requirementId": "REQ-026.3.3", + "hash": "28e8e14e95cb", + "verdict": "pass", + "summary": "Opened detail asserts waiting on 2/3 and every active, complete and dropped dependency slug/state, rejecting missing counts or members.", + "timestamp": "2026-09-14T07:53:54.419Z" +} diff --git a/.2119/verdicts/REQ-026.3.4--a01bf1446254.json b/.2119/verdicts/REQ-026.3.4--a01bf1446254.json new file mode 100644 index 0000000..2fd0594 --- /dev/null +++ b/.2119/verdicts/REQ-026.3.4--a01bf1446254.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.3.4--a01bf1446254", + "requirementId": "REQ-026.3.4", + "hash": "a01bf1446254", + "verdict": "pass", + "summary": "A DROPPED dependency is rendered alongside the instruction to edit dependencies or drop the dependent task.", + "timestamp": "2026-09-14T07:53:55.614Z" +} diff --git a/.2119/verdicts/REQ-026.3.5--75bdf83a2bee.json b/.2119/verdicts/REQ-026.3.5--75bdf83a2bee.json new file mode 100644 index 0000000..91ab689 --- /dev/null +++ b/.2119/verdicts/REQ-026.3.5--75bdf83a2bee.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.3.5--75bdf83a2bee", + "requirementId": "REQ-026.3.5", + "hash": "75bdf83a2bee", + "verdict": "pass", + "summary": "Fable 5.1: an unclaimed gated task must be present as a dashboard row initially and after a feed refresh, and in the service list before any spawn pass claims it; filtering gated rows out fails.", + "timestamp": "2026-09-30T06:01:48.793Z" +} diff --git a/.2119/verdicts/REQ-026.4.1--d2fe3accd242.json b/.2119/verdicts/REQ-026.4.1--d2fe3accd242.json new file mode 100644 index 0000000..f2148bf --- /dev/null +++ b/.2119/verdicts/REQ-026.4.1--d2fe3accd242.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.4.1--d2fe3accd242", + "requirementId": "REQ-026.4.1", + "hash": "d2fe3accd242", + "verdict": "pass", + "summary": "Fable 5.1: a self-dependency and a three-task indirect cycle are both rejected over REST, and concurrent two- and three-task updates can commit at most all-but-one edge.", + "timestamp": "2026-09-30T06:01:49.846Z" +} diff --git a/.2119/verdicts/REQ-026.4.2--33f446d79e00.json b/.2119/verdicts/REQ-026.4.2--33f446d79e00.json new file mode 100644 index 0000000..9332ef4 --- /dev/null +++ b/.2119/verdicts/REQ-026.4.2--33f446d79e00.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.4.2--33f446d79e00", + "requirementId": "REQ-026.4.2", + "hash": "33f446d79e00", + "verdict": "pass", + "summary": "Fable 5.1: the 400 detail must name every task id on the a-b-c cycle and carry the edit-dependencies advice; a generic error or one naming only the submitted task fails.", + "timestamp": "2026-09-30T06:01:50.884Z" +} diff --git a/.2119/verdicts/REQ-026.4.3--cf130bfb16b1.json b/.2119/verdicts/REQ-026.4.3--cf130bfb16b1.json new file mode 100644 index 0000000..c1be325 --- /dev/null +++ b/.2119/verdicts/REQ-026.4.3--cf130bfb16b1.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.4.3--cf130bfb16b1", + "requirementId": "REQ-026.4.3", + "hash": "cf130bfb16b1", + "verdict": "pass", + "summary": "Fable 5.1: after cycle and missing-dependency rejections the task must still list its prior dependency; a partial write or cleared list fails.", + "timestamp": "2026-09-30T06:01:51.938Z" +} diff --git a/.2119/verdicts/REQ-026.5.1--218063677b29.json b/.2119/verdicts/REQ-026.5.1--218063677b29.json new file mode 100644 index 0000000..605f2e7 --- /dev/null +++ b/.2119/verdicts/REQ-026.5.1--218063677b29.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.5.1--218063677b29", + "requirementId": "REQ-026.5.1", + "hash": "218063677b29", + "verdict": "pass", + "summary": "A user-turn governor with two active and one completed children renders exactly held 2 in dim style; escalated and blocked controls reject inappropriate demotion.", + "timestamp": "2026-09-14T07:53:58.095Z" +} diff --git a/.2119/verdicts/REQ-026.5.2--4f29fc3ed6bc.json b/.2119/verdicts/REQ-026.5.2--4f29fc3ed6bc.json new file mode 100644 index 0000000..b30c898 --- /dev/null +++ b/.2119/verdicts/REQ-026.5.2--4f29fc3ed6bc.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.5.2--4f29fc3ed6bc", + "requirementId": "REQ-026.5.2", + "hash": "4f29fc3ed6bc", + "verdict": "pass", + "summary": "Governors with only complete or custom-terminal children retain ordinary orange user or green agent presentation.", + "timestamp": "2026-09-14T07:53:59.326Z" +} diff --git a/.2119/verdicts/REQ-026.5.3--17db970a1779.json b/.2119/verdicts/REQ-026.5.3--17db970a1779.json new file mode 100644 index 0000000..96e871d --- /dev/null +++ b/.2119/verdicts/REQ-026.5.3--17db970a1779.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.5.3--17db970a1779", + "requirementId": "REQ-026.5.3", + "hash": "17db970a1779", + "verdict": "pass", + "summary": "Governor detail includes both active child slug/state pairs and excludes completed children and unrelated governors children.", + "timestamp": "2026-09-14T07:54:00.557Z" +} diff --git a/.2119/verdicts/REQ-026.6.1--1c4605b55497.json b/.2119/verdicts/REQ-026.6.1--1c4605b55497.json new file mode 100644 index 0000000..a1269fd --- /dev/null +++ b/.2119/verdicts/REQ-026.6.1--1c4605b55497.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.6.1--1c4605b55497", + "requirementId": "REQ-026.6.1", + "hash": "1c4605b55497", + "verdict": "pass", + "summary": "Dependency/governor wait controls are dim, attention restores orange, and no-wait user tasks remain orange for absent, false and true attention markers.", + "timestamp": "2026-09-14T07:54:01.811Z" +} diff --git a/.2119/verdicts/REQ-026.6.2--adae400ce7b0.json b/.2119/verdicts/REQ-026.6.2--adae400ce7b0.json new file mode 100644 index 0000000..4648254 --- /dev/null +++ b/.2119/verdicts/REQ-026.6.2--adae400ce7b0.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.6.2--adae400ce7b0", + "requirementId": "REQ-026.6.2", + "hash": "adae400ce7b0", + "verdict": "pass", + "summary": "Fable 5.1: attention true then false is persisted and reloaded while turn=agent and blocked=true must be unchanged. Only that one starting combination is exercised.", + "timestamp": "2026-09-30T06:01:52.985Z" +} diff --git a/.2119/verdicts/REQ-026.6.3--0e86a599b457.json b/.2119/verdicts/REQ-026.6.3--0e86a599b457.json new file mode 100644 index 0000000..a2d403b --- /dev/null +++ b/.2119/verdicts/REQ-026.6.3--0e86a599b457.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.6.3--0e86a599b457", + "requirementId": "REQ-026.6.3", + "hash": "0e86a599b457", + "verdict": "pass", + "summary": "Fable 5.1: blocked is toggled both ways under attention false and attention true and the marker must be unchanged each time.", + "timestamp": "2026-09-30T06:01:54.051Z" +} diff --git a/.2119/verdicts/REQ-026.6.4--eeee02ab8203.json b/.2119/verdicts/REQ-026.6.4--eeee02ab8203.json new file mode 100644 index 0000000..650454b --- /dev/null +++ b/.2119/verdicts/REQ-026.6.4--eeee02ab8203.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.6.4--eeee02ab8203", + "requirementId": "REQ-026.6.4", + "hash": "eeee02ab8203", + "verdict": "pass", + "summary": "Fable 5.1: turn=user is written under attention false and attention true and the marker must be unchanged in both.", + "timestamp": "2026-09-30T06:01:55.138Z" +} diff --git a/.2119/verdicts/REQ-026.6.5--a5cb9b38e497.json b/.2119/verdicts/REQ-026.6.5--a5cb9b38e497.json new file mode 100644 index 0000000..a68a86d --- /dev/null +++ b/.2119/verdicts/REQ-026.6.5--a5cb9b38e497.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.6.5--a5cb9b38e497", + "requirementId": "REQ-026.6.5", + "hash": "a5cb9b38e497", + "verdict": "pass", + "summary": "Fable 5.1: turn=agent with attention set must return attention false, and the task change-feed version must advance by exactly one, rejecting a separate follow-up write.", + "timestamp": "2026-09-30T06:01:56.195Z" +} diff --git a/.2119/verdicts/REQ-026.6.8--91f43e2e27db.json b/.2119/verdicts/REQ-026.6.8--91f43e2e27db.json new file mode 100644 index 0000000..f195c9f --- /dev/null +++ b/.2119/verdicts/REQ-026.6.8--91f43e2e27db.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-026.6.8--91f43e2e27db", + "requirementId": "REQ-026.6.8", + "hash": "91f43e2e27db", + "verdict": "pass", + "summary": "Dependency and governor waits with blocked markers render exact red user warning text, including a dependency wait with attention also set.", + "timestamp": "2026-09-14T07:54:03.058Z" +} diff --git a/.2119/verdicts/REQ-027.1.1--9b097314b437.json b/.2119/verdicts/REQ-027.1.1--9b097314b437.json new file mode 100644 index 0000000..68cc90c --- /dev/null +++ b/.2119/verdicts/REQ-027.1.1--9b097314b437.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-027.1.1--9b097314b437", + "requirementId": "REQ-027.1.1", + "hash": "9b097314b437", + "verdict": "pass", + "summary": "Fable 5.1: the model default and both the single and list REST representations must start null, and non-timestamp or date-only values are rejected with 422 leaving null.", + "timestamp": "2026-09-30T06:01:57.248Z" +} diff --git a/.2119/verdicts/REQ-027.1.2--1755fcea5014.json b/.2119/verdicts/REQ-027.1.2--1755fcea5014.json new file mode 100644 index 0000000..3022986 --- /dev/null +++ b/.2119/verdicts/REQ-027.1.2--1755fcea5014.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-027.1.2--1755fcea5014", + "requirementId": "REQ-027.1.2", + "hash": "1755fcea5014", + "verdict": "pass", + "summary": "Fable 5.1: offset-with-microseconds and naive timestamps must round-trip byte-exact, null must clear, the updated task is returned, and state, turn and blocked are asserted unchanged.", + "timestamp": "2026-09-30T06:01:58.345Z" +} diff --git a/.2119/verdicts/REQ-027.1.3--ebfc2e908f28.json b/.2119/verdicts/REQ-027.1.3--ebfc2e908f28.json new file mode 100644 index 0000000..97684ce --- /dev/null +++ b/.2119/verdicts/REQ-027.1.3--ebfc2e908f28.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-027.1.3--ebfc2e908f28", + "requirementId": "REQ-027.1.3", + "hash": "ebfc2e908f28", + "verdict": "pass", + "summary": "Fable 5.1: a year-2000 deadline and a year-2099 deadline must both be stored and returned unchanged; server-side expiry or rejection of past deadlines fails.", + "timestamp": "2026-09-30T06:01:59.405Z" +} diff --git a/.2119/verdicts/REQ-027.2.1--242da9f898a9.json b/.2119/verdicts/REQ-027.2.1--242da9f898a9.json new file mode 100644 index 0000000..7070213 --- /dev/null +++ b/.2119/verdicts/REQ-027.2.1--242da9f898a9.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-027.2.1--242da9f898a9", + "requirementId": "REQ-027.2.1", + "hash": "242da9f898a9", + "verdict": "pass", + "summary": "Actual e writes exactly injected now plus twelve hours despite conflicting env; constructor parameters and snooze-env access are guarded, including expired deadlines.", + "timestamp": "2026-09-14T07:54:04.316Z" +} diff --git a/.2119/verdicts/REQ-027.2.2--ec081378b0c4.json b/.2119/verdicts/REQ-027.2.2--ec081378b0c4.json new file mode 100644 index 0000000..773b2e5 --- /dev/null +++ b/.2119/verdicts/REQ-027.2.2--ec081378b0c4.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-027.2.2--ec081378b0c4", + "requirementId": "REQ-027.2.2", + "hash": "ec081378b0c4", + "verdict": "pass", + "summary": "Actual e clears both active finite and reserved indefinite snoozes and records None rather than extending the deadline.", + "timestamp": "2026-09-14T07:54:05.586Z" +} diff --git a/.2119/verdicts/REQ-027.2.3--1e08e4f61768.json b/.2119/verdicts/REQ-027.2.3--1e08e4f61768.json new file mode 100644 index 0000000..921daa3 --- /dev/null +++ b/.2119/verdicts/REQ-027.2.3--1e08e4f61768.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-027.2.3--1e08e4f61768", + "requirementId": "REQ-027.2.3", + "hash": "1e08e4f61768", + "verdict": "pass", + "summary": "Uppercase E writes the exact reserved timestamp only to the selected task, and keymap uniqueness plus separate e/E actions are asserted.", + "timestamp": "2026-09-14T07:54:06.760Z" +} diff --git a/.2119/verdicts/REQ-027.3.1--bdca0cd677e5.json b/.2119/verdicts/REQ-027.3.1--bdca0cd677e5.json new file mode 100644 index 0000000..2bb992e --- /dev/null +++ b/.2119/verdicts/REQ-027.3.1--bdca0cd677e5.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-027.3.1--bdca0cd677e5", + "requirementId": "REQ-027.3.1", + "hash": "bdca0cd677e5", + "verdict": "pass", + "summary": "Every rendered cell must have a full dim span; exact finite 12h/4h and indefinite snoozed text overrides blocked styling.", + "timestamp": "2026-09-14T07:54:07.956Z" +} diff --git a/.2119/verdicts/REQ-027.3.2--e186f432f0bd.json b/.2119/verdicts/REQ-027.3.2--e186f432f0bd.json new file mode 100644 index 0000000..20d70e1 --- /dev/null +++ b/.2119/verdicts/REQ-027.3.2--e186f432f0bd.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-027.3.2--e186f432f0bd", + "requirementId": "REQ-027.3.2", + "hash": "e186f432f0bd", + "verdict": "pass", + "summary": "Injected times exactly at and after expiry restore ordinary user/agent/blocked/attention styles without writes or changing the saved deadline, including offline refresh.", + "timestamp": "2026-09-14T07:54:09.122Z" +} diff --git a/.2119/verdicts/REQ-027.3.3--23f37cf06481.json b/.2119/verdicts/REQ-027.3.3--23f37cf06481.json new file mode 100644 index 0000000..2392271 --- /dev/null +++ b/.2119/verdicts/REQ-027.3.3--23f37cf06481.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-027.3.3--23f37cf06481", + "requirementId": "REQ-027.3.3", + "hash": "23f37cf06481", + "verdict": "pass", + "summary": "Injected clocks determine snooze writes and boundary rendering; a changed clock expires cached UI without service data changes.", + "timestamp": "2026-09-14T07:54:10.322Z" +} diff --git a/.2119/verdicts/REQ-027.3.4--a2198bb7d8fe.json b/.2119/verdicts/REQ-027.3.4--a2198bb7d8fe.json new file mode 100644 index 0000000..750b601 --- /dev/null +++ b/.2119/verdicts/REQ-027.3.4--a2198bb7d8fe.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-027.3.4--a2198bb7d8fe", + "requirementId": "REQ-027.3.4", + "hash": "a2198bb7d8fe", + "verdict": "pass", + "summary": "Attention pierces a blocked gated snooze to orange user; unpierced gated and held candidates render snoozed dim state.", + "timestamp": "2026-09-14T07:54:11.454Z" +} diff --git a/.2119/verdicts/REQ-028.1.1--4b5f0f4d3537.json b/.2119/verdicts/REQ-028.1.1--4b5f0f4d3537.json new file mode 100644 index 0000000..467788e --- /dev/null +++ b/.2119/verdicts/REQ-028.1.1--4b5f0f4d3537.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-028.1.1--4b5f0f4d3537", + "requirementId": "REQ-028.1.1", + "hash": "4b5f0f4d3537", + "verdict": "pass", + "summary": "Fable 5.1: every discovered workflow plus skill-less and skilled fixtures must expose the exact ordered list provision, artifacts, then workflow skills; overriding the artifacts name is rejected at construction and at rescan.", + "timestamp": "2026-09-30T06:02:00.451Z" +} diff --git a/.2119/verdicts/REQ-028.10.1--e88c9711487f.json b/.2119/verdicts/REQ-028.10.1--e88c9711487f.json new file mode 100644 index 0000000..b1058c6 --- /dev/null +++ b/.2119/verdicts/REQ-028.10.1--e88c9711487f.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-028.10.1--e88c9711487f", + "requirementId": "REQ-028.10.1", + "hash": "e88c9711487f", + "verdict": "pass", + "summary": "Fable 5.1: the test-owned literal states artifacts complement the pull request and its task URL and do not replace either; exact equality rejects replacement wording.", + "timestamp": "2026-09-30T06:02:12.253Z" +} diff --git a/.2119/verdicts/REQ-028.11.1--4d9fb91e910c.json b/.2119/verdicts/REQ-028.11.1--4d9fb91e910c.json new file mode 100644 index 0000000..b56555a --- /dev/null +++ b/.2119/verdicts/REQ-028.11.1--4d9fb91e910c.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-028.11.1--4d9fb91e910c", + "requirementId": "REQ-028.11.1", + "hash": "4d9fb91e910c", + "verdict": "pass", + "summary": "Fable 5.1: the literal defines an artifact as a durable user-reviewable document, says the examples are not exhaustive, and routes GitHub URLs to the external URL field and p hotkey; each clause is required by exact equality.", + "timestamp": "2026-09-30T06:02:13.341Z" +} diff --git a/.2119/verdicts/REQ-028.12.1--e33951052195.json b/.2119/verdicts/REQ-028.12.1--e33951052195.json new file mode 100644 index 0000000..33fd658 --- /dev/null +++ b/.2119/verdicts/REQ-028.12.1--e33951052195.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-028.12.1--e33951052195", + "requirementId": "REQ-028.12.1", + "hash": "e33951052195", + "verdict": "pass", + "summary": "Fable 5.1: the honesty command and dispatch argv must contain codex exec --dangerously-bypass-approvals-and-sandbox, the reviewer prompt literal forbids checkout edits, and the git status --porcelain check is asserted as a literal sentence. The review-instruction equality itself reuses the source constant, so only those literal assertions carry weight.", + "timestamp": "2026-09-30T06:02:14.413Z" +} diff --git a/.2119/verdicts/REQ-028.2.1--0ca7c6de125a.json b/.2119/verdicts/REQ-028.2.1--0ca7c6de125a.json new file mode 100644 index 0000000..b79147e --- /dev/null +++ b/.2119/verdicts/REQ-028.2.1--0ca7c6de125a.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-028.2.1--0ca7c6de125a", + "requirementId": "REQ-028.2.1", + "hash": "0ca7c6de125a", + "verdict": "pass", + "summary": "Fable 5.1: the served artifacts skill must equal a test-owned literal that names put_artifact and the REST PUT to /tasks//artifacts/; dropping either mechanism fails.", + "timestamp": "2026-09-30T06:02:01.531Z" +} diff --git a/.2119/verdicts/REQ-028.3.1--de68f877febb.json b/.2119/verdicts/REQ-028.3.1--de68f877febb.json new file mode 100644 index 0000000..1878002 --- /dev/null +++ b/.2119/verdicts/REQ-028.3.1--de68f877febb.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-028.3.1--de68f877febb", + "requirementId": "REQ-028.3.1", + "hash": "de68f877febb", + "verdict": "pass", + "summary": "Fable 5.1: the test-owned literal carries the a hotkey and the specification, review output, triage summary and stage or gate report examples; exact equality rejects any omission.", + "timestamp": "2026-09-30T06:02:02.582Z" +} diff --git a/.2119/verdicts/REQ-028.4.1--3c13931b3341.json b/.2119/verdicts/REQ-028.4.1--3c13931b3341.json new file mode 100644 index 0000000..d5e6afb --- /dev/null +++ b/.2119/verdicts/REQ-028.4.1--3c13931b3341.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-028.4.1--3c13931b3341", + "requirementId": "REQ-028.4.1", + "hash": "3c13931b3341", + "verdict": "pass", + "summary": "Fable 5.1: SPECIFYING responsibilities for all three built-ins must equal an exact four-item tuple containing a single spec-artifact entry; zero or two artifact responsibilities fail.", + "timestamp": "2026-09-30T06:02:03.627Z" +} diff --git a/.2119/verdicts/REQ-028.5.1--a0a6ceb6eb7c.json b/.2119/verdicts/REQ-028.5.1--a0a6ceb6eb7c.json new file mode 100644 index 0000000..4ae4420 --- /dev/null +++ b/.2119/verdicts/REQ-028.5.1--a0a6ceb6eb7c.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-028.5.1--a0a6ceb6eb7c", + "requirementId": "REQ-028.5.1", + "hash": "a0a6ceb6eb7c", + "verdict": "pass", + "summary": "Fable 5.1: the spec skill must equal a literal ending in the publish-specification sentence, and every review skill must end with the literal publish-review-outputs-and-triage sentence.", + "timestamp": "2026-09-30T06:02:04.718Z" +} diff --git a/.2119/verdicts/REQ-028.6.1--fa83331abede.json b/.2119/verdicts/REQ-028.6.1--fa83331abede.json new file mode 100644 index 0000000..bf29fe5 --- /dev/null +++ b/.2119/verdicts/REQ-028.6.1--fa83331abede.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-028.6.1--fa83331abede", + "requirementId": "REQ-028.6.1", + "hash": "fa83331abede", + "verdict": "pass", + "summary": "Fable 5.1: BUILDING url-recorded must exist with the exact set_url description for all three built-ins; removal raises KeyError.", + "timestamp": "2026-09-30T06:02:05.816Z" +} diff --git a/.2119/verdicts/REQ-028.7.1--f5e423b157d4.json b/.2119/verdicts/REQ-028.7.1--f5e423b157d4.json new file mode 100644 index 0000000..90e8fad --- /dev/null +++ b/.2119/verdicts/REQ-028.7.1--f5e423b157d4.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-028.7.1--f5e423b157d4", + "requirementId": "REQ-028.7.1", + "hash": "f5e423b157d4", + "verdict": "pass", + "summary": "Fable 5.1: discovery with a nonexistent home directory must map the three names to their built-in classes; a missing or externally supplied registration fails.", + "timestamp": "2026-09-30T06:02:06.886Z" +} diff --git a/.2119/verdicts/REQ-028.8.1--d6f04d9444f8.json b/.2119/verdicts/REQ-028.8.1--d6f04d9444f8.json new file mode 100644 index 0000000..3b468d8 --- /dev/null +++ b/.2119/verdicts/REQ-028.8.1--d6f04d9444f8.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-028.8.1--d6f04d9444f8", + "requirementId": "REQ-028.8.1", + "hash": "d6f04d9444f8", + "verdict": "pass", + "summary": "Fable 5.1: all three built-ins must run honesty review with gpt-5.6-sol, and the reviewer-defaults line must read Fable plus Sol for human/auto-spec and two codex Sol models for auto-sol. Note the requirement bundles three obligations and 'Sol' now spans two model versions.", + "timestamp": "2026-09-30T06:02:07.956Z" +} diff --git a/.2119/verdicts/REQ-028.8.2--dc7c9a4a7767.json b/.2119/verdicts/REQ-028.8.2--dc7c9a4a7767.json new file mode 100644 index 0000000..3cc90ed --- /dev/null +++ b/.2119/verdicts/REQ-028.8.2--dc7c9a4a7767.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-028.8.2--dc7c9a4a7767", + "requirementId": "REQ-028.8.2", + "hash": "dc7c9a4a7767", + "verdict": "pass", + "summary": "Fable 5.1: real Spec2119AutoSol on a repo defaulting to codex/gpt-5.6-sol must create (claude, claude-opus-5-5) over REST. Mutations removing the pair and changing the model string were both killed by this test; override precedence relies on the workflow-agnostic REQ-012.3 tests.", + "timestamp": "2026-09-30T06:02:09.018Z" +} diff --git a/.2119/verdicts/REQ-028.8.3--dab34c2959bb.json b/.2119/verdicts/REQ-028.8.3--dab34c2959bb.json new file mode 100644 index 0000000..33eabe3 --- /dev/null +++ b/.2119/verdicts/REQ-028.8.3--dab34c2959bb.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-028.8.3--dab34c2959bb", + "requirementId": "REQ-028.8.3", + "hash": "dab34c2959bb", + "verdict": "pass", + "summary": "Fable 5.1: the discovered workflow's reviewers tuple and the rendered defaults line must put codex:gpt-6.1-sol first. Mutations reverting slot one to gpt-5.6-sol and swapping slot order were both killed; slot-one override is covered by the generic REQ-036 resolver test.", + "timestamp": "2026-09-30T06:02:10.088Z" +} diff --git a/.2119/verdicts/REQ-028.9.1--10ee3479470d.json b/.2119/verdicts/REQ-028.9.1--10ee3479470d.json new file mode 100644 index 0000000..c6fc749 --- /dev/null +++ b/.2119/verdicts/REQ-028.9.1--10ee3479470d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-028.9.1--10ee3479470d", + "requirementId": "REQ-028.9.1", + "hash": "10ee3479470d", + "verdict": "pass", + "summary": "Fable 5.1: for every built-in name a real external duplicate file must raise the exact message naming that file and the removal remedy, including with duplicate-skipping enabled.", + "timestamp": "2026-09-30T06:02:11.172Z" +} diff --git a/.2119/verdicts/REQ-030.1.1--fc4516e92bee.json b/.2119/verdicts/REQ-030.1.1--fc4516e92bee.json new file mode 100644 index 0000000..794e1f5 --- /dev/null +++ b/.2119/verdicts/REQ-030.1.1--fc4516e92bee.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.1.1--fc4516e92bee", + "requirementId": "REQ-030.1.1", + "hash": "fc4516e92bee", + "verdict": "pass", + "summary": "Real-tmux tests close the loop on observable session state: on a fresh socket the production new_session_argv path yields `show-options -A -t test mouse` == `mouse* on` (stock default is off, so a config lacking/negating the line fails), and the repair test pre-sets `mouse off` on an existing server and asserts production session creation flips it back on; the four call-site argv tests (local/shell runner, dashboard, _start_sessions) plus the shell-runner live-socket spawn reject a call site that drops `-f`/`source-file` — the pure string check on config text is weak alone but is not the only coverage.", + "timestamp": "2026-10-28T06:11:23.491Z" +} diff --git a/.2119/verdicts/REQ-030.1.2--1aaca3cd2744.json b/.2119/verdicts/REQ-030.1.2--1aaca3cd2744.json new file mode 100644 index 0000000..27e485a --- /dev/null +++ b/.2119/verdicts/REQ-030.1.2--1aaca3cd2744.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.1.2--1aaca3cd2744", + "requirementId": "REQ-030.1.2", + "hash": "1aaca3cd2744", + "verdict": "pass", + "summary": "Pane-level `#{history_limit}` is asserted equal to 50000 (constant pinned by `HISTORY_LIMIT == \"50000\"`) after production creation on a fresh socket and on an existing server pre-set to 123; applying the option after the pane exists (or any other value) yields 123/2000 and fails.", + "timestamp": "2026-10-28T06:04:10.090Z" +} diff --git a/.2119/verdicts/REQ-030.1.3--aa334eb614ee.json b/.2119/verdicts/REQ-030.1.3--aa334eb614ee.json new file mode 100644 index 0000000..c05fd46 --- /dev/null +++ b/.2119/verdicts/REQ-030.1.3--aa334eb614ee.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.1.3--aa334eb614ee", + "requirementId": "REQ-030.1.3", + "hash": "aa334eb614ee", + "verdict": "pass", + "summary": "Config text asserts the exact `set-option -g set-clipboard on` line and real-tmux tests read `set-clipboard on` from global and session scope after production creation, including on a server pre-set to `off`; stock tmux (`external`) or a missing/late `-f` fails.", + "timestamp": "2026-10-28T06:04:11.410Z" +} diff --git a/.2119/verdicts/REQ-030.2.1--0b6493ede8a8.json b/.2119/verdicts/REQ-030.2.1--0b6493ede8a8.json new file mode 100644 index 0000000..e120685 --- /dev/null +++ b/.2119/verdicts/REQ-030.2.1--0b6493ede8a8.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.2.1--0b6493ede8a8", + "requirementId": "REQ-030.2.1", + "hash": "0b6493ede8a8", + "verdict": "pass", + "summary": "Real PTY SGR drag in emacs copy-mode with the resolved tool replaced by a capture command asserts no capture exists before release (`copy must happen on release`), then exactly b\"bravo\" after release; stock tmux's copy-selection-and-cancel default (no pipe) never creates the file and fails, and the exact copy-mode MouseDragEnd1Pane line is asserted in config text.", + "timestamp": "2026-10-28T06:04:12.613Z" +} diff --git a/.2119/verdicts/REQ-030.2.2--01e0e975dc09.json b/.2119/verdicts/REQ-030.2.2--01e0e975dc09.json new file mode 100644 index 0000000..fad0c87 --- /dev/null +++ b/.2119/verdicts/REQ-030.2.2--01e0e975dc09.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.2.2--01e0e975dc09", + "requirementId": "REQ-030.2.2", + "hash": "01e0e975dc09", + "verdict": "pass", + "summary": "Same real drag exercised with `mode-keys vi` (inclusive endpoint) asserting capture == b\"bravo\" only after release, plus the exact copy-mode-vi MouseDragEnd1Pane copy-pipe-and-cancel line with the xclip command; a binding only in the emacs table or a missing pipe fails.", + "timestamp": "2026-10-28T06:04:13.860Z" +} diff --git a/.2119/verdicts/REQ-030.2.3--94cf3a001475.json b/.2119/verdicts/REQ-030.2.3--94cf3a001475.json new file mode 100644 index 0000000..c344dbf --- /dev/null +++ b/.2119/verdicts/REQ-030.2.3--94cf3a001475.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.2.3--94cf3a001475", + "requirementId": "REQ-030.2.3", + "hash": "94cf3a001475", + "verdict": "pass", + "summary": "Real double-click at column 9 of `alpha bravo charlie` must yield exactly b\"bravo\" in the paste buffer (pre-seeded with a sentinel), rejecting line/partial selections; the existing-server test unbinds root DoubleClick1Pane and asserts production creation restores a select-word binding, and the chained config line is asserted verbatim.", + "timestamp": "2026-10-28T06:04:15.145Z" +} diff --git a/.2119/verdicts/REQ-030.2.4--191b47ca2bc8.json b/.2119/verdicts/REQ-030.2.4--191b47ca2bc8.json new file mode 100644 index 0000000..3c4daa2 --- /dev/null +++ b/.2119/verdicts/REQ-030.2.4--191b47ca2bc8.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.2.4--191b47ca2bc8", + "requirementId": "REQ-030.2.4", + "hash": "191b47ca2bc8", + "verdict": "pass", + "summary": "Double-click with the resolved tool replaced by a capture command asserts the capture file contains exactly b\"bravo\"; tmux's stock double-click binding (no external pipe) or a wrong tool leaves no capture and fails, and the exact `copy-pipe-and-cancel \"pbcopy\"` tail is asserted in the config line.", + "timestamp": "2026-10-28T06:04:16.416Z" +} diff --git a/.2119/verdicts/REQ-030.2.5--99f116196e6d.json b/.2119/verdicts/REQ-030.2.5--99f116196e6d.json new file mode 100644 index 0000000..8dd88c8 --- /dev/null +++ b/.2119/verdicts/REQ-030.2.5--99f116196e6d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.2.5--99f116196e6d", + "requirementId": "REQ-030.2.5", + "hash": "99f116196e6d", + "verdict": "pass", + "summary": "With clipboard_tool resolving None, all four mode/gesture combinations assert `save-buffer -` == b\"bravo\" over a pre-seeded sentinel buffer, and config text asserts copy-selection-and-cancel on all three bindings with no copy-pipe-and-cancel anywhere; a binding still piping to a phantom tool fails the text assertion.", + "timestamp": "2026-10-28T06:04:17.666Z" +} diff --git a/.2119/verdicts/REQ-030.3.1--bbce5b5ff87c.json b/.2119/verdicts/REQ-030.3.1--bbce5b5ff87c.json new file mode 100644 index 0000000..c3de413 --- /dev/null +++ b/.2119/verdicts/REQ-030.3.1--bbce5b5ff87c.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.3.1--bbce5b5ff87c", + "requirementId": "REQ-030.3.1", + "hash": "bbce5b5ff87c", + "verdict": "pass", + "summary": "All four named creators (LocalRunner.spawn, ShellRunner.spawn, _start_sessions service+runner, ensure_dashboard_session) are each pinned by a recorder test asserting `tmux -L -f ` with `source-file` indexed before `new-session` and the cfg file byte-equal to server_default_config_text (whose lines are individually pinned for mouse/history-limit 50000/set-clipboard/drag/vi-drag/double-click/fallback), so a call site that omits -f, loads a partial config, or orders -f/source-file after new-session is rejected; real-tmux tests on the same constructor reject the 'applied after session' counterexample (pane #{history_limit} must read 50000 on a fresh socket, and an existing server with mouse off/history-limit 123/DoubleClick unbound must be repaired by the production new-session), while shell-runner and container real-tmux spawns confirm `mouse on` lands through the production path; an AST guard forbids any other production `new-session` literal. Minor non-material gap: unit tests don't assert the source-file operand equals the -f path and the live-runner integration checks only `mouse`.", + "timestamp": "2026-10-28T06:11:24.731Z" +} diff --git a/.2119/verdicts/REQ-030.3.2--6f32f8a5b92d.json b/.2119/verdicts/REQ-030.3.2--6f32f8a5b92d.json new file mode 100644 index 0000000..32128cd --- /dev/null +++ b/.2119/verdicts/REQ-030.3.2--6f32f8a5b92d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.3.2--6f32f8a5b92d", + "requirementId": "REQ-030.3.2", + "hash": "6f32f8a5b92d", + "verdict": "pass", + "summary": "Each first-touch path (LocalRunner/ShellRunner kill-session, console and _start_sessions has-session probes, every new-session) is asserted to carry `-f ` as argv[3] with `-f` indexed before `new-session`, so the nearest violations are rejected: dropping defaults_argv from the leading call fails `first_tmux[:4]`, placing `-f` after `new-session` (where tmux reads it as new-session's own `-f flags`, leaving the pane at stock 2000) fails the index check, and setting history-limit via a separate set-option between new-session and respawn-pane fails because `index(\"-f\")` raises; test_local_runner additionally asserts the literal `set-option -g history-limit 50000` line in the loaded file, and the argv-ordering proxy is grounded by the real-tmux fresh-socket test in test_tmux_defaults.py that uses production new_session_argv and reads the created pane's `#{history_limit}` == 50000; minor weakness is that shell_runner/console/terminal compare config content only to the production helper's own output (self-referential) and the ensure_dashboard_session .3.2 test is ordering-only, but content is cross-covered by the REQ-030.1.2 literal and real-tmux assertions.", + "timestamp": "2026-10-28T06:11:26.051Z" +} diff --git a/.2119/verdicts/REQ-030.4.1--fcb982be3c19.json b/.2119/verdicts/REQ-030.4.1--fcb982be3c19.json new file mode 100644 index 0000000..3017726 --- /dev/null +++ b/.2119/verdicts/REQ-030.4.1--fcb982be3c19.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.4.1--fcb982be3c19", + "requirementId": "REQ-030.4.1", + "hash": "fcb982be3c19", + "verdict": "pass", + "summary": "clipboard_tool(platform=\"darwin\") with an injected PATH predicate returns exactly \"pbcopy\" both alone and with all linux tools also present, and a monkeypatched shutil.which proves the default predicate is resolved at call time; returning None or a linux tool on darwin fails.", + "timestamp": "2026-10-28T06:04:20.196Z" +} diff --git a/.2119/verdicts/REQ-030.4.2--e2386a63e29a.json b/.2119/verdicts/REQ-030.4.2--e2386a63e29a.json new file mode 100644 index 0000000..864308a --- /dev/null +++ b/.2119/verdicts/REQ-030.4.2--e2386a63e29a.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.4.2--e2386a63e29a", + "requirementId": "REQ-030.4.2", + "hash": "e2386a63e29a", + "verdict": "pass", + "summary": "Darwin with no tools and darwin with only wl-copy/xclip/xsel present both must return None; a fallthrough to the linux chain on darwin is the rejected counterexample.", + "timestamp": "2026-10-28T06:04:21.474Z" +} diff --git a/.2119/verdicts/REQ-030.4.3--2b80d13b4596.json b/.2119/verdicts/REQ-030.4.3--2b80d13b4596.json new file mode 100644 index 0000000..f0fbb00 --- /dev/null +++ b/.2119/verdicts/REQ-030.4.3--2b80d13b4596.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.4.3--2b80d13b4596", + "requirementId": "REQ-030.4.3", + "hash": "2b80d13b4596", + "verdict": "pass", + "summary": "On linux and freebsd14, wl-copy alone and wl-copy alongside xclip/xsel must return exactly \"wl-copy\"; preferring xclip or returning a different string fails.", + "timestamp": "2026-10-28T06:04:22.750Z" +} diff --git a/.2119/verdicts/REQ-030.4.4--655bc9a7029a.json b/.2119/verdicts/REQ-030.4.4--655bc9a7029a.json new file mode 100644 index 0000000..f343692 --- /dev/null +++ b/.2119/verdicts/REQ-030.4.4--655bc9a7029a.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.4.4--655bc9a7029a", + "requirementId": "REQ-030.4.4", + "hash": "655bc9a7029a", + "verdict": "pass", + "summary": "Non-darwin with xclip (and with xclip+xsel, wl-copy absent) must return the exact string \"xclip -selection clipboard\"; bare \"xclip\" or xsel precedence fails.", + "timestamp": "2026-10-28T06:04:24.060Z" +} diff --git a/.2119/verdicts/REQ-030.4.5--a173543f9001.json b/.2119/verdicts/REQ-030.4.5--a173543f9001.json new file mode 100644 index 0000000..06cd240 --- /dev/null +++ b/.2119/verdicts/REQ-030.4.5--a173543f9001.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.4.5--a173543f9001", + "requirementId": "REQ-030.4.5", + "hash": "a173543f9001", + "verdict": "pass", + "summary": "Non-darwin with only xsel present must return exactly \"xsel --clipboard --input\"; any other flag spelling or a None result fails.", + "timestamp": "2026-10-28T06:04:25.296Z" +} diff --git a/.2119/verdicts/REQ-030.4.6--b5f6e6ff6104.json b/.2119/verdicts/REQ-030.4.6--b5f6e6ff6104.json new file mode 100644 index 0000000..8ecb0fc --- /dev/null +++ b/.2119/verdicts/REQ-030.4.6--b5f6e6ff6104.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.4.6--b5f6e6ff6104", + "requirementId": "REQ-030.4.6", + "hash": "b5f6e6ff6104", + "verdict": "pass", + "summary": "Non-darwin with no candidates, and with only pbcopy present, must return None; leaking pbcopy into the non-darwin chain is the rejected counterexample.", + "timestamp": "2026-10-28T06:04:26.575Z" +} diff --git a/.2119/verdicts/REQ-030.5.1--27632b3c10c3.json b/.2119/verdicts/REQ-030.5.1--27632b3c10c3.json new file mode 100644 index 0000000..645b1b0 --- /dev/null +++ b/.2119/verdicts/REQ-030.5.1--27632b3c10c3.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.5.1--27632b3c10c3", + "requirementId": "REQ-030.5.1", + "hash": "27632b3c10c3", + "verdict": "pass", + "summary": "Both no-socket spawn tests assert full-list equality over every emitted tmux argv (and sha256-pin the shell pane command), so an implementation that adds `-f `, a `source-file cfg ;` chain, or a separate `set-option`/`bind-key` call when tmux_socket=None is rejected; the real defaults_argv/new_session_argv helpers run unmocked and the only two no-socket session-creation paths (LocalRunner, ShellRunner) are both covered.", + "timestamp": "2026-10-28T06:11:27.331Z" +} diff --git a/.2119/verdicts/REQ-030.5.2--208c7f5b26fe.json b/.2119/verdicts/REQ-030.5.2--208c7f5b26fe.json new file mode 100644 index 0000000..4db3ebf --- /dev/null +++ b/.2119/verdicts/REQ-030.5.2--208c7f5b26fe.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-030.5.2--208c7f5b26fe", + "requirementId": "REQ-030.5.2", + "hash": "208c7f5b26fe", + "verdict": "pass", + "summary": "A marker `~/.tmux.conf` is proven loadable by a plain `-L control` server (negative control), then production creation on the dedicated socket asserts the marker is absent from `status-left`; dropping `-f` would load the operator file and fail.", + "timestamp": "2026-10-28T06:04:27.804Z" +} diff --git a/.2119/verdicts/REQ-031.1.1--e7f3dae9271d.json b/.2119/verdicts/REQ-031.1.1--e7f3dae9271d.json new file mode 100644 index 0000000..8e8ba13 --- /dev/null +++ b/.2119/verdicts/REQ-031.1.1--e7f3dae9271d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-031.1.1--e7f3dae9271d", + "requirementId": "REQ-031.1.1", + "hash": "e7f3dae9271d", + "verdict": "pass", + "summary": "Failed Docker probe through the start command prevents migration, session startup, and console entry.", + "timestamp": "2026-09-14T06:52:14.621Z" +} diff --git a/.2119/verdicts/REQ-031.1.2--7d809f596b36.json b/.2119/verdicts/REQ-031.1.2--7d809f596b36.json new file mode 100644 index 0000000..a7cb3c9 --- /dev/null +++ b/.2119/verdicts/REQ-031.1.2--7d809f596b36.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-031.1.2--7d809f596b36", + "requirementId": "REQ-031.1.2", + "hash": "7d809f596b36", + "verdict": "pass", + "summary": "Failed Docker probe through the host command prevents migration and background session startup.", + "timestamp": "2026-09-14T06:52:15.665Z" +} diff --git a/.2119/verdicts/REQ-031.1.3--327a3558cbe5.json b/.2119/verdicts/REQ-031.1.3--327a3558cbe5.json new file mode 100644 index 0000000..6566447 --- /dev/null +++ b/.2119/verdicts/REQ-031.1.3--327a3558cbe5.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-031.1.3--327a3558cbe5", + "requirementId": "REQ-031.1.3", + "hash": "327a3558cbe5", + "verdict": "pass", + "summary": "Exact diagnostic content covers unreachable Docker and macOS/Linux remedies; both command paths verify delivery.", + "timestamp": "2026-09-14T06:52:16.663Z" +} diff --git a/.2119/verdicts/REQ-031.1.4--3f8fa11b7343.json b/.2119/verdicts/REQ-031.1.4--3f8fa11b7343.json new file mode 100644 index 0000000..32989df --- /dev/null +++ b/.2119/verdicts/REQ-031.1.4--3f8fa11b7343.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-031.1.4--3f8fa11b7343", + "requirementId": "REQ-031.1.4", + "hash": "3f8fa11b7343", + "verdict": "pass", + "summary": "Both refusal commands are exercised as subprocesses and must return nonzero with the expected diagnostic.", + "timestamp": "2026-09-14T06:52:17.730Z" +} diff --git a/.2119/verdicts/REQ-031.1.5--0890e0a3d1f6.json b/.2119/verdicts/REQ-031.1.5--0890e0a3d1f6.json new file mode 100644 index 0000000..d557aea --- /dev/null +++ b/.2119/verdicts/REQ-031.1.5--0890e0a3d1f6.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-031.1.5--0890e0a3d1f6", + "requirementId": "REQ-031.1.5", + "hash": "0890e0a3d1f6", + "verdict": "pass", + "summary": "Successful probe drives both real command paths to exactly two detached tmux sessions with the required process commands.", + "timestamp": "2026-09-14T06:52:18.720Z" +} diff --git a/.2119/verdicts/REQ-031.2.1--bf2a81eb5e26.json b/.2119/verdicts/REQ-031.2.1--bf2a81eb5e26.json new file mode 100644 index 0000000..9b090a8 --- /dev/null +++ b/.2119/verdicts/REQ-031.2.1--bf2a81eb5e26.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-031.2.1--bf2a81eb5e26", + "requirementId": "REQ-031.2.1", + "hash": "bf2a81eb5e26", + "verdict": "pass", + "summary": "Host process entry rejects a failed real probe path before migration or spawn/heal loop entry; reachable startup enters the loop.", + "timestamp": "2026-09-14T06:52:19.722Z" +} diff --git a/.2119/verdicts/REQ-031.2.2--0e533789f260.json b/.2119/verdicts/REQ-031.2.2--0e533789f260.json new file mode 100644 index 0000000..06221dc --- /dev/null +++ b/.2119/verdicts/REQ-031.2.2--0e533789f260.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-031.2.2--0e533789f260", + "requirementId": "REQ-031.2.2", + "hash": "0e533789f260", + "verdict": "pass", + "summary": "Shared diagnostic text is pinned to actionable macOS/Linux remedies and the host preflight verifies exact delivery.", + "timestamp": "2026-09-14T06:52:20.690Z" +} diff --git a/.2119/verdicts/REQ-031.3.1--60f6189f86fb.json b/.2119/verdicts/REQ-031.3.1--60f6189f86fb.json new file mode 100644 index 0000000..e2b68c9 --- /dev/null +++ b/.2119/verdicts/REQ-031.3.1--60f6189f86fb.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-031.3.1--60f6189f86fb", + "requirementId": "REQ-031.3.1", + "hash": "60f6189f86fb", + "verdict": "pass", + "summary": "Unreachable Docker leaves container tasks unclaimed and unspawned through direct and host-wired spawner paths; recovery permits retry.", + "timestamp": "2026-09-14T06:52:21.742Z" +} diff --git a/.2119/verdicts/REQ-032.1.1--a9f59b47de16.json b/.2119/verdicts/REQ-032.1.1--a9f59b47de16.json new file mode 100644 index 0000000..d9a60c8 --- /dev/null +++ b/.2119/verdicts/REQ-032.1.1--a9f59b47de16.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-032.1.1--a9f59b47de16", + "requirementId": "REQ-032.1.1", + "hash": "a9f59b47de16", + "verdict": "pass", + "summary": "test_argv_resumes_the_recorded_interactive_session_by_id asserts exact argv ['codex','resume','interactive-1',*flags], so emitting `--last` or omitting the recorded id is rejected; the exec-newer test confirms the id is the interactive one, not merely the newest file.", + "timestamp": "2026-10-28T06:05:36.198Z" +} diff --git a/.2119/verdicts/REQ-032.1.2--d051cd38f4f8.json b/.2119/verdicts/REQ-032.1.2--d051cd38f4f8.json new file mode 100644 index 0000000..43368ad --- /dev/null +++ b/.2119/verdicts/REQ-032.1.2--d051cd38f4f8.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-032.1.2--d051cd38f4f8", + "requirementId": "REQ-032.1.2", + "hash": "d051cd38f4f8", + "verdict": "pass", + "summary": "Two tests reject wrong-recency selection: one where filename order and creation order both disagree with mtime (name/glob/creation-order picks 'older'), and one where st_mtime floats collide but st_mtime_ns differs (float comparison would tie or pick arbitrarily).", + "timestamp": "2026-10-28T06:05:37.478Z" +} diff --git a/.2119/verdicts/REQ-032.1.3--43c63811228f.json b/.2119/verdicts/REQ-032.1.3--43c63811228f.json new file mode 100644 index 0000000..3b1ba23 --- /dev/null +++ b/.2119/verdicts/REQ-032.1.3--43c63811228f.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-032.1.3--43c63811228f", + "requirementId": "REQ-032.1.3", + "hash": "43c63811228f", + "verdict": "pass", + "summary": "test_argv_resume_picks_interactive_over_a_newer_exec_rollout seeds a `codex_exec` rollout with a newer mtime and asserts resume targets 'interactive-1'; selecting by newest file (the --last failure mode) is rejected, and the all-exec test rejects resuming `codex_exec`/`exec` when no interactive rollout exists.", + "timestamp": "2026-10-28T06:05:38.784Z" +} diff --git a/.2119/verdicts/REQ-032.1.4--db9b38bf05df.json b/.2119/verdicts/REQ-032.1.4--db9b38bf05df.json new file mode 100644 index 0000000..4e81d49 --- /dev/null +++ b/.2119/verdicts/REQ-032.1.4--db9b38bf05df.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-032.1.4--db9b38bf05df", + "requirementId": "REQ-032.1.4", + "hash": "db9b38bf05df", + "verdict": "pass", + "summary": "test_argv_resume_skips_a_newer_subagent_thread_of_the_interactive_session seeds a newer `codex-tui` rollout with thread_source='subagent' and asserts resume targets the older root ('user') session; filtering on originator alone is rejected.", + "timestamp": "2026-10-28T06:05:40.050Z" +} diff --git a/.2119/verdicts/REQ-032.2.1--63a22d77cfec.json b/.2119/verdicts/REQ-032.2.1--63a22d77cfec.json new file mode 100644 index 0000000..c7e9bff --- /dev/null +++ b/.2119/verdicts/REQ-032.2.1--63a22d77cfec.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-032.2.1--63a22d77cfec", + "requirementId": "REQ-032.2.1", + "hash": "63a22d77cfec", + "verdict": "pass", + "summary": "test_argv_resume_stays_fresh_when_no_rollouts_recorded asserts argv equals exactly ['codex',*_SESSION_FLAGS] (same literal the first-run tests pin), so a `resume` subcommand or altered flags are rejected; the empty-candidate code path is also exercised by the all-malformed→fresh test.", + "timestamp": "2026-10-28T06:05:41.338Z" +} diff --git a/.2119/verdicts/REQ-032.2.2--d735d095d2db.json b/.2119/verdicts/REQ-032.2.2--d735d095d2db.json new file mode 100644 index 0000000..782c1a4 --- /dev/null +++ b/.2119/verdicts/REQ-032.2.2--d735d095d2db.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-032.2.2--d735d095d2db", + "requirementId": "REQ-032.2.2", + "hash": "d735d095d2db", + "verdict": "pass", + "summary": "test_argv_resume_falls_back_to_fresh_when_every_rollout_is_exec (originators `codex_exec` and `exec`) and the all-malformed test assert exact first-run argv, so raising, or resuming 'reviewer-2' as the newest file, is rejected.", + "timestamp": "2026-10-28T06:05:42.629Z" +} diff --git a/.2119/verdicts/REQ-032.3.1--688a8fd081ad.json b/.2119/verdicts/REQ-032.3.1--688a8fd081ad.json new file mode 100644 index 0000000..5e9fb7d --- /dev/null +++ b/.2119/verdicts/REQ-032.3.1--688a8fd081ad.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-032.3.1--688a8fd081ad", + "requirementId": "REQ-032.3.1", + "hash": "688a8fd081ad", + "verdict": "pass", + "summary": "Empty, non-JSON, payload-less, and originator-less first lines are each seeded newer than the interactive rollout and the test asserts the interactive one is still resumed; the all-malformed variant asserts first-run argv, so raising on any malformed line or selecting a malformed file is rejected.", + "timestamp": "2026-10-28T06:05:43.971Z" +} diff --git a/.2119/verdicts/REQ-032.4.1--671e6841d69d.json b/.2119/verdicts/REQ-032.4.1--671e6841d69d.json new file mode 100644 index 0000000..7e498d2 --- /dev/null +++ b/.2119/verdicts/REQ-032.4.1--671e6841d69d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-032.4.1--671e6841d69d", + "requirementId": "REQ-032.4.1", + "hash": "671e6841d69d", + "verdict": "pass", + "summary": "test_argv_resume_reads_only_the_first_line_of_each_rollout wraps Path.open with a byte-accounting proxy that raises once reads exceed the first line's length and appends 5000 garbage lines; the production scan uses path.open()+readline(), so read_text()/read()/readlines()/full iteration are all intercepted and rejected (builtin open() would evade the wrapper, but is not the code path).", + "timestamp": "2026-10-28T06:05:45.281Z" +} diff --git a/.2119/verdicts/REQ-032.5.1--70fb49eea63b.json b/.2119/verdicts/REQ-032.5.1--70fb49eea63b.json new file mode 100644 index 0000000..200c4cf --- /dev/null +++ b/.2119/verdicts/REQ-032.5.1--70fb49eea63b.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-032.5.1--70fb49eea63b", + "requirementId": "REQ-032.5.1", + "hash": "70fb49eea63b", + "verdict": "pass", + "summary": "test_argv_resume_session_flags_unchanged asserts argv[3:] == the exact three-flag list on resume, and first-run tests pin the same list, so dropping/reordering/adding a flag on resume relative to first run is rejected.", + "timestamp": "2026-10-28T06:05:46.591Z" +} diff --git a/.2119/verdicts/REQ-032.5.2--9d7d8694c538.json b/.2119/verdicts/REQ-032.5.2--9d7d8694c538.json new file mode 100644 index 0000000..190ea4a --- /dev/null +++ b/.2119/verdicts/REQ-032.5.2--9d7d8694c538.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-032.5.2--9d7d8694c538", + "requirementId": "REQ-032.5.2", + "hash": "9d7d8694c538", + "verdict": "pass", + "summary": "Parametrized test asserts exact argv with 'You were interrupted. Continue.' appended only for turn='agent' and nothing appended for turn='user', so a changed prompt string, omission on agent turn, or leakage onto user turn is rejected.", + "timestamp": "2026-10-28T06:05:47.833Z" +} diff --git a/.2119/verdicts/REQ-033.1.1--13e12d59f7c1.json b/.2119/verdicts/REQ-033.1.1--13e12d59f7c1.json new file mode 100644 index 0000000..0e07ceb --- /dev/null +++ b/.2119/verdicts/REQ-033.1.1--13e12d59f7c1.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-033.1.1--13e12d59f7c1", + "requirementId": "REQ-033.1.1", + "hash": "13e12d59f7c1", + "verdict": "pass", + "summary": "Fable 5.1: each review skill must contain the literal end-with-Suggested-placeholder-issues sentence and end with a test-owned triage literal.", + "timestamp": "2026-09-30T06:02:15.521Z" +} diff --git a/.2119/verdicts/REQ-033.10.1--5646eda74129.json b/.2119/verdicts/REQ-033.10.1--5646eda74129.json new file mode 100644 index 0000000..604586f --- /dev/null +++ b/.2119/verdicts/REQ-033.10.1--5646eda74129.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-033.10.1--5646eda74129", + "requirementId": "REQ-033.10.1", + "hash": "5646eda74129", + "verdict": "pass", + "summary": "Fable 5.1: the deferred-issues-filed description must equal a literal ending 'Filing zero issues is a legal outcome.'", + "timestamp": "2026-09-30T06:02:25.123Z" +} diff --git a/.2119/verdicts/REQ-033.2.1--7671d5851c4b.json b/.2119/verdicts/REQ-033.2.1--7671d5851c4b.json new file mode 100644 index 0000000..5d00185 --- /dev/null +++ b/.2119/verdicts/REQ-033.2.1--7671d5851c4b.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-033.2.1--7671d5851c4b", + "requirementId": "REQ-033.2.1", + "hash": "7671d5851c4b", + "verdict": "pass", + "summary": "Fable 5.1: the one-paragraph entry sentence with its three required contents is asserted as a full literal; dropping any of the three fails.", + "timestamp": "2026-09-30T06:02:16.605Z" +} diff --git a/.2119/verdicts/REQ-033.3.1--589c2f732fa3.json b/.2119/verdicts/REQ-033.3.1--589c2f732fa3.json new file mode 100644 index 0000000..0a09dce --- /dev/null +++ b/.2119/verdicts/REQ-033.3.1--589c2f732fa3.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-033.3.1--589c2f732fa3", + "requirementId": "REQ-033.3.1", + "hash": "589c2f732fa3", + "verdict": "pass", + "summary": "Fable 5.1: the omit-simply-wrong instruction must be present and its negations absent.", + "timestamp": "2026-09-30T06:02:17.673Z" +} diff --git a/.2119/verdicts/REQ-033.4.1--bfc61d9d22bb.json b/.2119/verdicts/REQ-033.4.1--bfc61d9d22bb.json new file mode 100644 index 0000000..5641cf0 --- /dev/null +++ b/.2119/verdicts/REQ-033.4.1--bfc61d9d22bb.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-033.4.1--bfc61d9d22bb", + "requirementId": "REQ-033.4.1", + "hash": "bfc61d9d22bb", + "verdict": "pass", + "summary": "Fable 5.1: the literal framing as recommendations for the user to endorse, reject or edit at the PR approval gate is asserted in two independent tests.", + "timestamp": "2026-09-30T06:02:18.741Z" +} diff --git a/.2119/verdicts/REQ-033.5.1--3b6cf7b8204b.json b/.2119/verdicts/REQ-033.5.1--3b6cf7b8204b.json new file mode 100644 index 0000000..75339fa --- /dev/null +++ b/.2119/verdicts/REQ-033.5.1--3b6cf7b8204b.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-033.5.1--3b6cf7b8204b", + "requirementId": "REQ-033.5.1", + "hash": "3b6cf7b8204b", + "verdict": "pass", + "summary": "Fable 5.1: MERGING keys must equal [deferred-issues-filed, pr-merged] in that order for all three built-ins; omission or reversed order fails.", + "timestamp": "2026-09-30T06:02:19.809Z" +} diff --git a/.2119/verdicts/REQ-033.6.1--dd9484d48bc0.json b/.2119/verdicts/REQ-033.6.1--dd9484d48bc0.json new file mode 100644 index 0000000..98af7fd --- /dev/null +++ b/.2119/verdicts/REQ-033.6.1--dd9484d48bc0.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-033.6.1--dd9484d48bc0", + "requirementId": "REQ-033.6.1", + "hash": "dd9484d48bc0", + "verdict": "pass", + "summary": "Fable 5.1: the babysit-merge prefix must equal a test-owned literal that tells the agent to re-read the section and user PR comments before the unchanged base merge steps.", + "timestamp": "2026-09-30T06:02:20.870Z" +} diff --git a/.2119/verdicts/REQ-033.7.1--dee756ae075d.json b/.2119/verdicts/REQ-033.7.1--dee756ae075d.json new file mode 100644 index 0000000..b22f2cc --- /dev/null +++ b/.2119/verdicts/REQ-033.7.1--dee756ae075d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-033.7.1--dee756ae075d", + "requirementId": "REQ-033.7.1", + "hash": "dee756ae075d", + "verdict": "pass", + "summary": "Fable 5.1: the exact prefix literal requires gh issue create for endorsed or unobjected suggestions, incorporating user edits.", + "timestamp": "2026-09-30T06:02:21.918Z" +} diff --git a/.2119/verdicts/REQ-033.8.1--63fa02856b1d.json b/.2119/verdicts/REQ-033.8.1--63fa02856b1d.json new file mode 100644 index 0000000..9150058 --- /dev/null +++ b/.2119/verdicts/REQ-033.8.1--63fa02856b1d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-033.8.1--63fa02856b1d", + "requirementId": "REQ-033.8.1", + "hash": "63fa02856b1d", + "verdict": "pass", + "summary": "Fable 5.1: the exact prefix literal includes the skip-explicitly-rejected step; removing it breaks equality.", + "timestamp": "2026-09-30T06:02:22.970Z" +} diff --git a/.2119/verdicts/REQ-033.9.1--1487d2b8cd0d.json b/.2119/verdicts/REQ-033.9.1--1487d2b8cd0d.json new file mode 100644 index 0000000..8fc3cc0 --- /dev/null +++ b/.2119/verdicts/REQ-033.9.1--1487d2b8cd0d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-033.9.1--1487d2b8cd0d", + "requirementId": "REQ-033.9.1", + "hash": "1487d2b8cd0d", + "verdict": "pass", + "summary": "Fable 5.1: the exact prefix literal requires a self-contained issue with title, PR link, review comment reference, deferral reason and implementation scope.", + "timestamp": "2026-09-30T06:02:24.029Z" +} diff --git a/.2119/verdicts/REQ-034.1.1--aad04f3a549a.json b/.2119/verdicts/REQ-034.1.1--aad04f3a549a.json new file mode 100644 index 0000000..b1b2b73 --- /dev/null +++ b/.2119/verdicts/REQ-034.1.1--aad04f3a549a.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-034.1.1--aad04f3a549a", + "requirementId": "REQ-034.1.1", + "hash": "aad04f3a549a", + "verdict": "pass", + "summary": "Typed uppercase letters and punctuation yield an exact visible complete query and only matching ID prefixes, excluding substring and partial-query near matches.", + "timestamp": "2026-09-14T07:54:12.681Z" +} diff --git a/.2119/verdicts/REQ-034.1.2--2f9bb821dd9b.json b/.2119/verdicts/REQ-034.1.2--2f9bb821dd9b.json new file mode 100644 index 0000000..a795e0c --- /dev/null +++ b/.2119/verdicts/REQ-034.1.2--2f9bb821dd9b.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-034.1.2--2f9bb821dd9b", + "requirementId": "REQ-034.1.2", + "hash": "2f9bb821dd9b", + "verdict": "pass", + "summary": "Backspace removes the last query character and restores matching IDs; repeated Backspace empties the query and restores all repositories.", + "timestamp": "2026-09-14T07:54:14.032Z" +} diff --git a/.2119/verdicts/REQ-034.2.1--0aefc39ecf18.json b/.2119/verdicts/REQ-034.2.1--0aefc39ecf18.json new file mode 100644 index 0000000..42134a9 --- /dev/null +++ b/.2119/verdicts/REQ-034.2.1--0aefc39ecf18.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-034.2.1--0aefc39ecf18", + "requirementId": "REQ-034.2.1", + "hash": "0aefc39ecf18", + "verdict": "pass", + "summary": "Filtering to bravo then completing creation asserts the exact bravo repo ID in the create payload.", + "timestamp": "2026-09-14T07:54:15.301Z" +} diff --git a/.2119/verdicts/REQ-035.14.1--9e4827027914.json b/.2119/verdicts/REQ-035.14.1--9e4827027914.json new file mode 100644 index 0000000..aaff9fd --- /dev/null +++ b/.2119/verdicts/REQ-035.14.1--9e4827027914.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-035.14.1--9e4827027914", + "requirementId": "REQ-035.14.1", + "hash": "9e4827027914", + "verdict": "pass", + "summary": "create_app in enforced mode is asserted to raise for: auth_file=None and missing.json; ../, absolute, and symlink escapes; chmod 0 unreadable; 'not-json' and '[]'; write missing/empty/string/[1]; read string/[1]; and overlap via shared-token and write=[READ_TOKEN]; read omitted entirely is accepted (200), so each conjunct's nearest violation is rejected.", + "timestamp": "2026-10-28T06:05:49.098Z" +} diff --git a/.2119/verdicts/REQ-035.17.1--e5fc76cef15a.json b/.2119/verdicts/REQ-035.17.1--e5fc76cef15a.json new file mode 100644 index 0000000..3dbf357 --- /dev/null +++ b/.2119/verdicts/REQ-035.17.1--e5fc76cef15a.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-035.17.1--e5fc76cef15a", + "requirementId": "REQ-035.17.1", + "hash": "e5fc76cef15a", + "verdict": "pass", + "summary": "Docker spawn without env_file is asserted to carry no --env-file, no raw token in argv, and a /run/secrets mount whose source is not the host credential path and whose content is the task capability; shell spawn's exported auth file is asserted distinct from the host file; shared client (_default_client/_make_client), live (client.live + shell /tasks/t2/live curl stdin), and _TASK_LIB panopticon_advance are each asserted to send the bearer from that file, so mounting the host file directly, passing the token by env, or an unauthenticated lib call is rejected.", + "timestamp": "2026-10-28T06:05:50.366Z" +} diff --git a/.2119/verdicts/REQ-035.29.1--3f5d79610567.json b/.2119/verdicts/REQ-035.29.1--3f5d79610567.json new file mode 100644 index 0000000..f35f0e3 --- /dev/null +++ b/.2119/verdicts/REQ-035.29.1--3f5d79610567.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-035.29.1--3f5d79610567", + "requirementId": "REQ-035.29.1", + "hash": "3f5d79610567", + "verdict": "pass", + "summary": "Launch argv tests cover Linux wildcard binding for absent/empty overrides and disabled loopback; standalone startup verifies loopback.", + "timestamp": "2026-09-14T06:52:22.845Z" +} diff --git a/.2119/verdicts/REQ-035.36.1--26cadbfb8714.json b/.2119/verdicts/REQ-035.36.1--26cadbfb8714.json new file mode 100644 index 0000000..00cf3ba --- /dev/null +++ b/.2119/verdicts/REQ-035.36.1--26cadbfb8714.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-035.36.1--26cadbfb8714", + "requirementId": "REQ-035.36.1", + "hash": "26cadbfb8714", + "verdict": "pass", + "summary": "Both 401 and 403 cause immediate termination without retry through the real HTTP client; entrypoint propagation is exercised.", + "timestamp": "2026-09-14T06:52:23.842Z" +} diff --git a/.2119/verdicts/REQ-035.39.1--a64952b5956d.json b/.2119/verdicts/REQ-035.39.1--a64952b5956d.json new file mode 100644 index 0000000..6e38b12 --- /dev/null +++ b/.2119/verdicts/REQ-035.39.1--a64952b5956d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-035.39.1--a64952b5956d", + "requirementId": "REQ-035.39.1", + "hash": "a64952b5956d", + "verdict": "pass", + "summary": "test_runner_injects_only_the_subject_task_capability rewrites the credential file to write=[WRITE_TOKEN, ROTATED] before spawn and asserts the mounted snapshot == {'task': capability derived from ROTATED} with no raw read/write tokens in any mounted file, so deriving from the stale/first token or including raw tokens is rejected; the hardening test's raw-token snapshot assertion is a different helper and not the Docker evidence.", + "timestamp": "2026-10-28T06:05:51.691Z" +} diff --git a/.2119/verdicts/REQ-035.4.1--278dcf0fb339.json b/.2119/verdicts/REQ-035.4.1--278dcf0fb339.json new file mode 100644 index 0000000..720fdec --- /dev/null +++ b/.2119/verdicts/REQ-035.4.1--278dcf0fb339.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-035.4.1--278dcf0fb339", + "requirementId": "REQ-035.4.1", + "hash": "278dcf0fb339", + "verdict": "pass", + "summary": "Routes are enumerated from app.routes (a superset of the OpenAPI surface) and include the new POST /tasks/{id}/launcher-failure; every mutating route plus both /live GETs returns 401 with the generic body for read tokens; exempting launcher-failure from the mutating set is caught by the read-token launcher-failure case", + "timestamp": "2026-09-14T07:58:33.539Z" +} diff --git a/.2119/verdicts/REQ-035.45.1--b8383474bc32.json b/.2119/verdicts/REQ-035.45.1--b8383474bc32.json new file mode 100644 index 0000000..1a62d87 --- /dev/null +++ b/.2119/verdicts/REQ-035.45.1--b8383474bc32.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-035.45.1--b8383474bc32", + "requirementId": "REQ-035.45.1", + "hash": "b8383474bc32", + "verdict": "pass", + "summary": "Both 401 and 403 abort the liveness loop without retry, and background rejection terminates the host main loop.", + "timestamp": "2026-09-14T06:52:24.888Z" +} diff --git a/.2119/verdicts/REQ-035.47.1--41345d31eb3c.json b/.2119/verdicts/REQ-035.47.1--41345d31eb3c.json new file mode 100644 index 0000000..f8727b1 --- /dev/null +++ b/.2119/verdicts/REQ-035.47.1--41345d31eb3c.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-035.47.1--41345d31eb3c", + "requirementId": "REQ-035.47.1", + "hash": "41345d31eb3c", + "verdict": "pass", + "summary": "Unit test asserts the exact NO_PROXY/no_proxy literals in the docker run argv (both spellings, positioned after --env-file) and would reject an emission that omits the service host, uses the full URL, drops env-file or lowercase bypass entries, or is ordered before --env-file; the real-CLI test adds a positive control (proxy hit without bypass) then proves zero proxy hits and only Bearer-authenticated target hits once the runner's emitted values are applied.", + "timestamp": "2026-10-28T06:11:28.609Z" +} diff --git a/.2119/verdicts/REQ-035.7.1--0f05671f85c7.json b/.2119/verdicts/REQ-035.7.1--0f05671f85c7.json new file mode 100644 index 0000000..36a0b9c --- /dev/null +++ b/.2119/verdicts/REQ-035.7.1--0f05671f85c7.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-035.7.1--0f05671f85c7", + "requirementId": "REQ-035.7.1", + "hash": "0f05671f85c7", + "verdict": "pass", + "summary": "Missing, Basic, empty Bearer, two-part, lowercase-scheme, unknown, truncated, extended and read-token headers each yield 401, WWW-Authenticate: Bearer and the identical generic JSON across every registered route and /mcp; non-ASCII token covered at ASGI level; the launcher-failure route is included explicitly", + "timestamp": "2026-09-14T07:58:34.842Z" +} diff --git a/.2119/verdicts/REQ-036.1.1--295553c79072.json b/.2119/verdicts/REQ-036.1.1--295553c79072.json new file mode 100644 index 0000000..5555b10 --- /dev/null +++ b/.2119/verdicts/REQ-036.1.1--295553c79072.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-036.1.1--295553c79072", + "requirementId": "REQ-036.1.1", + "hash": "295553c79072", + "verdict": "pass", + "summary": "Fable 5.1: per-slot overrides are applied independently, split on the first colon with the remainder verbatim, auto-sol keeps two codex Sol defaults (gpt-6.1-sol, gpt-5.6-sol), and six malformed forms raise in both slots before the run callable is touched.", + "timestamp": "2026-09-30T06:02:26.188Z" +} diff --git a/.2119/verdicts/REQ-038.1.1--318b536ed51a.json b/.2119/verdicts/REQ-038.1.1--318b536ed51a.json new file mode 100644 index 0000000..8e8f366 --- /dev/null +++ b/.2119/verdicts/REQ-038.1.1--318b536ed51a.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-038.1.1--318b536ed51a", + "requirementId": "REQ-038.1.1", + "hash": "318b536ed51a", + "verdict": "pass", + "summary": "Both sort modes assert the entire order across active, finite/indefinite snoozed, exact/past-expired, attention-pierced, COMPLETE and DROPPED tasks.", + "timestamp": "2026-09-14T07:54:16.533Z" +} diff --git a/.2119/verdicts/REQ-039.3.1--b679ab343b40.json b/.2119/verdicts/REQ-039.3.1--b679ab343b40.json new file mode 100644 index 0000000..7bf9807 --- /dev/null +++ b/.2119/verdicts/REQ-039.3.1--b679ab343b40.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-039.3.1--b679ab343b40", + "requirementId": "REQ-039.3.1", + "hash": "b679ab343b40", + "verdict": "pass", + "summary": "Shared event traces enforce close then backoff then reopen; identity and registration checks remain intact, and a late-backoff negative control is rejected.", + "timestamp": "2026-09-14T06:55:53.730Z" +} diff --git a/.2119/verdicts/REQ-039.4.1--29181ba2025f.json b/.2119/verdicts/REQ-039.4.1--29181ba2025f.json new file mode 100644 index 0000000..aa7b814 --- /dev/null +++ b/.2119/verdicts/REQ-039.4.1--29181ba2025f.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-039.4.1--29181ba2025f", + "requirementId": "REQ-039.4.1", + "hash": "29181ba2025f", + "verdict": "pass", + "summary": "Shared event traces enforce close then backoff then reopen; identity and registration checks remain intact, and a late-backoff negative control is rejected.", + "timestamp": "2026-09-14T06:55:55.141Z" +} diff --git a/.2119/verdicts/REQ-040.1.1--81c24293ebba.json b/.2119/verdicts/REQ-040.1.1--81c24293ebba.json new file mode 100644 index 0000000..c526feb --- /dev/null +++ b/.2119/verdicts/REQ-040.1.1--81c24293ebba.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-040.1.1--81c24293ebba", + "requirementId": "REQ-040.1.1", + "hash": "81c24293ebba", + "verdict": "pass", + "summary": "The global HOTKEYS table has one f action for open_checkout and explicitly marks it hidden.", + "timestamp": "2026-09-14T07:54:17.791Z" +} diff --git a/.2119/verdicts/REQ-040.2.1--669ef0f220bd.json b/.2119/verdicts/REQ-040.2.1--669ef0f220bd.json new file mode 100644 index 0000000..d61cbb9 --- /dev/null +++ b/.2119/verdicts/REQ-040.2.1--669ef0f220bd.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-040.2.1--669ef0f220bd", + "requirementId": "REQ-040.2.1", + "hash": "669ef0f220bd", + "verdict": "pass", + "summary": "Both no current task and a stale highlighted ID notify the exact no-task warning and make no opener call.", + "timestamp": "2026-09-14T07:54:19.023Z" +} diff --git a/.2119/verdicts/REQ-040.3.1--c4c977a044cf.json b/.2119/verdicts/REQ-040.3.1--c4c977a044cf.json new file mode 100644 index 0000000..92d2f85 --- /dev/null +++ b/.2119/verdicts/REQ-040.3.1--c4c977a044cf.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-040.3.1--c4c977a044cf", + "requirementId": "REQ-040.3.1", + "hash": "c4c977a044cf", + "verdict": "pass", + "summary": "An unprovisioned clone=None task produces the exact warning and no open attempt.", + "timestamp": "2026-09-14T07:54:20.305Z" +} diff --git a/.2119/verdicts/REQ-040.4.1--30da005e8f76.json b/.2119/verdicts/REQ-040.4.1--30da005e8f76.json new file mode 100644 index 0000000..6bc5022 --- /dev/null +++ b/.2119/verdicts/REQ-040.4.1--30da005e8f76.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-040.4.1--30da005e8f76", + "requirementId": "REQ-040.4.1", + "hash": "30da005e8f76", + "verdict": "pass", + "summary": "A clone recognized as local is opened despite a remote runner_host, rejecting host-name-based suppression.", + "timestamp": "2026-09-14T07:54:21.504Z" +} diff --git a/.2119/verdicts/REQ-040.5.1--730d0ca6863f.json b/.2119/verdicts/REQ-040.5.1--730d0ca6863f.json new file mode 100644 index 0000000..44e4a40 --- /dev/null +++ b/.2119/verdicts/REQ-040.5.1--730d0ca6863f.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-040.5.1--730d0ca6863f", + "requirementId": "REQ-040.5.1", + "hash": "730d0ca6863f", + "verdict": "pass", + "summary": "A non-directory clone is checked at its exact path, never opened, and produces the correct host-specific or hostless warning.", + "timestamp": "2026-09-14T07:54:22.810Z" +} diff --git a/.2119/verdicts/REQ-040.6.1--efc53f888ac8.json b/.2119/verdicts/REQ-040.6.1--efc53f888ac8.json new file mode 100644 index 0000000..9c5a832 --- /dev/null +++ b/.2119/verdicts/REQ-040.6.1--efc53f888ac8.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-040.6.1--efc53f888ac8", + "requirementId": "REQ-040.6.1", + "hash": "efc53f888ac8", + "verdict": "pass", + "summary": "The action passes the exact verified local clone path to the opener.", + "timestamp": "2026-09-14T07:54:24.074Z" +} diff --git a/.2119/verdicts/REQ-040.7.1--4183cea2d07e.json b/.2119/verdicts/REQ-040.7.1--4183cea2d07e.json new file mode 100644 index 0000000..a782e37 --- /dev/null +++ b/.2119/verdicts/REQ-040.7.1--4183cea2d07e.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-040.7.1--4183cea2d07e", + "requirementId": "REQ-040.7.1", + "hash": "4183cea2d07e", + "verdict": "pass", + "summary": "A FileNotFoundError from the opener is caught and becomes exactly the missing-file-manager warning.", + "timestamp": "2026-09-14T07:54:25.366Z" +} diff --git a/.2119/verdicts/REQ-041.3.1--ec848982c3eb.json b/.2119/verdicts/REQ-041.3.1--ec848982c3eb.json new file mode 100644 index 0000000..e1a3d78 --- /dev/null +++ b/.2119/verdicts/REQ-041.3.1--ec848982c3eb.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-041.3.1--ec848982c3eb", + "requirementId": "REQ-041.3.1", + "hash": "ec848982c3eb", + "verdict": "pass", + "summary": "Fable 5.1: the served artifacts skill must equal a literal opening with the system-prompt standing expectation and explaining put_artifact and the REST endpoint.", + "timestamp": "2026-09-30T06:02:27.264Z" +} diff --git a/.2119/verdicts/REQ-041.4.1--beede4b057e0.json b/.2119/verdicts/REQ-041.4.1--beede4b057e0.json new file mode 100644 index 0000000..712b965 --- /dev/null +++ b/.2119/verdicts/REQ-041.4.1--beede4b057e0.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-041.4.1--beede4b057e0", + "requirementId": "REQ-041.4.1", + "hash": "beede4b057e0", + "verdict": "pass", + "summary": "Fable 5.1: the same literal preserves the a hotkey, the complement-not-replace sentence and the GitHub-URL-to-p-hotkey exception.", + "timestamp": "2026-09-30T06:02:28.355Z" +} diff --git a/.2119/verdicts/REQ-042.1.1--58d2b3a829e4.json b/.2119/verdicts/REQ-042.1.1--58d2b3a829e4.json new file mode 100644 index 0000000..99a89a8 --- /dev/null +++ b/.2119/verdicts/REQ-042.1.1--58d2b3a829e4.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-042.1.1--58d2b3a829e4", + "requirementId": "REQ-042.1.1", + "hash": "58d2b3a829e4", + "verdict": "pass", + "summary": "A mounted artifact-bearing task with no PR URL displays exactly *a followed by one separator and its task label.", + "timestamp": "2026-09-14T07:54:26.588Z" +} diff --git a/.2119/verdicts/REQ-042.2.1--0c40ae502d40.json b/.2119/verdicts/REQ-042.2.1--0c40ae502d40.json new file mode 100644 index 0000000..19329c3 --- /dev/null +++ b/.2119/verdicts/REQ-042.2.1--0c40ae502d40.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-042.2.1--0c40ae502d40", + "requirementId": "REQ-042.2.1", + "hash": "0c40ae502d40", + "verdict": "pass", + "summary": "Real dashboard rows identify decimal GitHub PR numbers including URL suffixes while rejecting other hosts, lookalike hosts, schemes, malformed URLs and nonnumeric suffixes.", + "timestamp": "2026-09-14T07:54:27.815Z" +} diff --git a/.2119/verdicts/REQ-042.3.1--9eddfab894ec.json b/.2119/verdicts/REQ-042.3.1--9eddfab894ec.json new file mode 100644 index 0000000..721905e --- /dev/null +++ b/.2119/verdicts/REQ-042.3.1--9eddfab894ec.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-042.3.1--9eddfab894ec", + "requirementId": "REQ-042.3.1", + "hash": "9eddfab894ec", + "verdict": "pass", + "summary": "Exact composed slug-cell output places artifact before PR with one separating space and a single complete-prefix separator.", + "timestamp": "2026-09-14T07:54:28.985Z" +} diff --git a/.2119/verdicts/REQ-042.4.1--e40a191ba72f.json b/.2119/verdicts/REQ-042.4.1--e40a191ba72f.json new file mode 100644 index 0000000..1f54c83 --- /dev/null +++ b/.2119/verdicts/REQ-042.4.1--e40a191ba72f.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-042.4.1--e40a191ba72f", + "requirementId": "REQ-042.4.1", + "hash": "e40a191ba72f", + "verdict": "pass", + "summary": "Exact outputs preserve tree connector, disclosure, slug and first memo line for both, either and neither indicator; neither produces no separator.", + "timestamp": "2026-09-14T07:54:30.157Z" +} diff --git a/.2119/verdicts/REQ-048.1.1--0d57ba4502bb.json b/.2119/verdicts/REQ-048.1.1--0d57ba4502bb.json new file mode 100644 index 0000000..c3ced88 --- /dev/null +++ b/.2119/verdicts/REQ-048.1.1--0d57ba4502bb.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.1.1--0d57ba4502bb", + "requirementId": "REQ-048.1.1", + "hash": "0d57ba4502bb", + "verdict": "pass", + "summary": "Real LocalRunner.spawn builds the docker argv with only the process launcher stubbed; the test requires exactly one read-only mount at the designated path whose JSON equals {\"task\": } and asserts every configured read/write token is absent from argv and all mounted files, so a snapshot carrying {\"write\":[token]} or a capability bound to the sibling task fails the exact-equality check.", + "timestamp": "2026-10-28T06:06:21.626Z" +} diff --git a/.2119/verdicts/REQ-048.1.2--9e22beb20779.json b/.2119/verdicts/REQ-048.1.2--9e22beb20779.json new file mode 100644 index 0000000..e5cd602 --- /dev/null +++ b/.2119/verdicts/REQ-048.1.2--9e22beb20779.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.1.2--9e22beb20779", + "requirementId": "REQ-048.1.2", + "hash": "9e22beb20779", + "verdict": "pass", + "summary": "Fleet write token claims two tasks, reports lifecycle on both, mutates both slugs, lists runners, creates and patches a repo, and reclaims a runner with asserted 200/201; any regression to 401/403 on those surfaces (e.g. claim reclassified as task-only) fails.", + "timestamp": "2026-10-28T06:06:22.886Z" +} diff --git a/.2119/verdicts/REQ-048.1.3--02ee3d06f9ef.json b/.2119/verdicts/REQ-048.1.3--02ee3d06f9ef.json new file mode 100644 index 0000000..20aedd1 --- /dev/null +++ b/.2119/verdicts/REQ-048.1.3--02ee3d06f9ef.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.1.3--02ee3d06f9ef", + "requirementId": "REQ-048.1.3", + "hash": "02ee3d06f9ef", + "verdict": "pass", + "summary": "With an allowlisted Origin, GET /tasks is asserted 200 for the read token and 403 for both the fleet write token and a task capability; a service that let the write token through cross-origin would return 200 and fail.", + "timestamp": "2026-10-28T06:06:24.249Z" +} diff --git a/.2119/verdicts/REQ-048.10.1--53d3f7c04a5e.json b/.2119/verdicts/REQ-048.10.1--53d3f7c04a5e.json new file mode 100644 index 0000000..32db183 --- /dev/null +++ b/.2119/verdicts/REQ-048.10.1--53d3f7c04a5e.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.10.1--53d3f7c04a5e", + "requirementId": "REQ-048.10.1", + "hash": "53d3f7c04a5e", + "verdict": "pass", + "summary": "All 11 names × query/cookie/JSON and the 5 alternate headers are asserted 401 both alone and alongside the valid Bearer header, nine header-shape variants are 401, and the exact Bearer header is 200; accepting ?access_token= or tolerating a stray X-API-Key next to a valid header fails.", + "timestamp": "2026-10-28T06:06:58.377Z" +} diff --git a/.2119/verdicts/REQ-048.10.2--3455a0666537.json b/.2119/verdicts/REQ-048.10.2--3455a0666537.json new file mode 100644 index 0000000..85bd2f4 --- /dev/null +++ b/.2119/verdicts/REQ-048.10.2--3455a0666537.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.10.2--3455a0666537", + "requirementId": "REQ-048.10.2", + "hash": "3455a0666537", + "verdict": "pass", + "summary": "Every registered path × three origins × ten methods, their preflights, and invalid-token responses are asserted to lack any 'true' value in Access-Control-Allow-Credentials; enabling allow_credentials would fail.", + "timestamp": "2026-10-28T06:06:59.695Z" +} diff --git a/.2119/verdicts/REQ-048.10.3--e6878234b6a9.json b/.2119/verdicts/REQ-048.10.3--e6878234b6a9.json new file mode 100644 index 0000000..313dc77 --- /dev/null +++ b/.2119/verdicts/REQ-048.10.3--e6878234b6a9.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.10.3--e6878234b6a9", + "requirementId": "REQ-048.10.3", + "hash": "e6878234b6a9", + "verdict": "pass", + "summary": "Preflights on task/repo/artifact paths must have body in {b'', b'OK'}, headers a subset of the fixed CORS/transport set, max-age in {None,'600'}, identical responses across paths, and no seeded task id/repo name/artifact bytes anywhere in the wire; a leaked header or max-age 3600 fails.", + "timestamp": "2026-10-28T06:07:00.927Z" +} diff --git a/.2119/verdicts/REQ-048.11.1--499768b56543.json b/.2119/verdicts/REQ-048.11.1--499768b56543.json new file mode 100644 index 0000000..5c9db25 --- /dev/null +++ b/.2119/verdicts/REQ-048.11.1--499768b56543.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.11.1--499768b56543", + "requirementId": "REQ-048.11.1", + "hash": "499768b56543", + "verdict": "pass", + "summary": "With no allowlist and with an empty list, every registered route's actual and preflight responses plus the live stream are asserted to lack Access-Control-Allow-Origin for three origins; a default-on CORS would fail.", + "timestamp": "2026-10-28T06:07:02.236Z" +} diff --git a/.2119/verdicts/REQ-048.11.2--5350832ca941.json b/.2119/verdicts/REQ-048.11.2--5350832ca941.json new file mode 100644 index 0000000..6ee4391 --- /dev/null +++ b/.2119/verdicts/REQ-048.11.2--5350832ca941.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.11.2--5350832ca941", + "requirementId": "REQ-048.11.2", + "hash": "5350832ca941", + "verdict": "pass", + "summary": "Twenty invalid entries (wildcards, trailing slash, path, query, fragment, userinfo, null, data:, bad port, malformed IPv6) raise at create_app alone and mixed with a valid origin, while port, localhost, and IPv6 exact origins are accepted; tolerating 'https://phone.example/' fails.", + "timestamp": "2026-10-28T06:07:03.476Z" +} diff --git a/.2119/verdicts/REQ-048.11.3--88f702f07f65.json b/.2119/verdicts/REQ-048.11.3--88f702f07f65.json new file mode 100644 index 0000000..b4c1fea --- /dev/null +++ b/.2119/verdicts/REQ-048.11.3--88f702f07f65.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.11.3--88f702f07f65", + "requirementId": "REQ-048.11.3", + "hash": "88f702f07f65", + "verdict": "pass", + "summary": "Allow-Methods is asserted exactly {GET,HEAD,OPTIONS} and Allow-Headers exactly {authorization,content-type}, with POST/PUT/PATCH/DELETE/CONNECT/TRACE/PROPFIND preflights and Accept/X-Extra/X-API-Key/Cookie/Proxy-Authorization header requests all ≥400 across two origins and three paths; permitting POST or Accept fails.", + "timestamp": "2026-10-28T06:07:04.763Z" +} diff --git a/.2119/verdicts/REQ-048.11.4--7715d1063b7f.json b/.2119/verdicts/REQ-048.11.4--7715d1063b7f.json new file mode 100644 index 0000000..64aaa0f --- /dev/null +++ b/.2119/verdicts/REQ-048.11.4--7715d1063b7f.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.11.4--7715d1063b7f", + "requirementId": "REQ-048.11.4", + "hash": "7715d1063b7f", + "verdict": "pass", + "summary": "Allowed origin yields Allow-Origin equal to the exact origin with Vary containing Origin (also on 401 and 404), while trailing-slash, http scheme, different port, evil, and null origins get no Allow-Origin; echoing '*' or a near-match origin fails.", + "timestamp": "2026-10-28T06:07:06.009Z" +} diff --git a/.2119/verdicts/REQ-048.12.1--613161d69994.json b/.2119/verdicts/REQ-048.12.1--613161d69994.json new file mode 100644 index 0000000..710cf7a --- /dev/null +++ b/.2119/verdicts/REQ-048.12.1--613161d69994.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.12.1--613161d69994", + "requirementId": "REQ-048.12.1", + "hash": "613161d69994", + "verdict": "pass", + "summary": "The full Action × Relation × orchestrates matrix (×4 principals) is decided twice with equality asserted, repeated under six clock perturbations and clock-raising stubs with sys.setprofile confirming no time calls, against the real authorize function; any nondeterministic or clock-dependent decision fails.", + "timestamp": "2026-10-28T06:07:07.287Z" +} diff --git a/.2119/verdicts/REQ-048.12.2--a7e06fdd52c7.json b/.2119/verdicts/REQ-048.12.2--a7e06fdd52c7.json new file mode 100644 index 0000000..dff3681 --- /dev/null +++ b/.2119/verdicts/REQ-048.12.2--a7e06fdd52c7.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.12.2--a7e06fdd52c7", + "requirementId": "REQ-048.12.2", + "hash": "a7e06fdd52c7", + "verdict": "pass", + "summary": "A fresh subprocess imports auth and auth_scope, exercises derivation and the full authorize matrix, and asserts no name in import attempts or sys.modules equals panopticon.container or starts with anthropic/openai, backed by an AST scan for literal and dynamic imports; a transitive container import would fail.", + "timestamp": "2026-10-28T06:07:08.563Z" +} diff --git a/.2119/verdicts/REQ-048.2.1--c1c8e6ffa2a4.json b/.2119/verdicts/REQ-048.2.1--c1c8e6ffa2a4.json new file mode 100644 index 0000000..85decc4 --- /dev/null +++ b/.2119/verdicts/REQ-048.2.1--c1c8e6ffa2a4.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.2.1--c1c8e6ffa2a4", + "requirementId": "REQ-048.2.1", + "hash": "c1c8e6ffa2a4", + "verdict": "pass", + "summary": "Token is split into four dot segments and checked against ptc1/self, unpadded base64url (edge subjects '???'→'Pz8_' and '~~~'→'fn5-' reject standard base64 or padding), and an independently computed HMAC-SHA256 keyed by the write token over the exact domain string; a different key, domain, or encoding fails the equality.", + "timestamp": "2026-10-28T06:06:25.532Z" +} diff --git a/.2119/verdicts/REQ-048.2.2--017ed57b1bcc.json b/.2119/verdicts/REQ-048.2.2--017ed57b1bcc.json new file mode 100644 index 0000000..1f62bbf --- /dev/null +++ b/.2119/verdicts/REQ-048.2.2--017ed57b1bcc.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.2.2--017ed57b1bcc", + "requirementId": "REQ-048.2.2", + "hash": "017ed57b1bcc", + "verdict": "pass", + "summary": "With three write tokens configured, capabilities derived from the oldest, middle, and newest each get 200 on GET /tasks/{id} and PUT slug; a service honoring only the newest generation would return 401 for the others.", + "timestamp": "2026-10-28T06:06:26.845Z" +} diff --git a/.2119/verdicts/REQ-048.2.3--e9a75e193b15.json b/.2119/verdicts/REQ-048.2.3--e9a75e193b15.json new file mode 100644 index 0000000..4b8c538 --- /dev/null +++ b/.2119/verdicts/REQ-048.2.3--e9a75e193b15.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.2.3--e9a75e193b15", + "requirementId": "REQ-048.2.3", + "hash": "e9a75e193b15", + "verdict": "pass", + "summary": "Nine malformed mutations, a flipped-MAC forgery, and a sibling-bound capability are rejected, and the full wire tuple (status, headers, body) is asserted identical between an existing and a missing target and between an existing and a never-created asserted subject; a 404-vs-401 or body difference would fail.", + "timestamp": "2026-10-28T06:06:28.078Z" +} diff --git a/.2119/verdicts/REQ-048.2.4--56e9501ae9b4.json b/.2119/verdicts/REQ-048.2.4--56e9501ae9b4.json new file mode 100644 index 0000000..da53161 --- /dev/null +++ b/.2119/verdicts/REQ-048.2.4--56e9501ae9b4.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.2.4--56e9501ae9b4", + "requirementId": "REQ-048.2.4", + "hash": "56e9501ae9b4", + "verdict": "pass", + "summary": "Derivation is asserted equal across 20 in-process calls and a fresh subprocess for four (root, task_id) pairs and distinct across tasks; any nonce, clock, or process-state dependence would produce a mismatch.", + "timestamp": "2026-10-28T06:06:29.366Z" +} diff --git a/.2119/verdicts/REQ-048.3.1--e58fd8cea0df.json b/.2119/verdicts/REQ-048.3.1--e58fd8cea0df.json new file mode 100644 index 0000000..7ba555e --- /dev/null +++ b/.2119/verdicts/REQ-048.3.1--e58fd8cea0df.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.3.1--e58fd8cea0df", + "requirementId": "REQ-048.3.1", + "hash": "e58fd8cea0df", + "verdict": "pass", + "summary": "Snapshot contents must equal {\"task\": expected} exactly, the argv must carry exactly one --env PANOPTICON_SERVICE_AUTH_FILE=/run/secrets/panopticon-service-auth and one ro mount of that snapshot, and the in-container client built from that env emits Bearer ; an extra key, a second credential mount, or a missing env pointer fails.", + "timestamp": "2026-10-28T06:06:30.635Z" +} diff --git a/.2119/verdicts/REQ-048.3.2--0cb054b37c60.json b/.2119/verdicts/REQ-048.3.2--0cb054b37c60.json new file mode 100644 index 0000000..5350fce --- /dev/null +++ b/.2119/verdicts/REQ-048.3.2--0cb054b37c60.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.3.2--0cb054b37c60", + "requirementId": "REQ-048.3.2", + "hash": "0cb054b37c60", + "verdict": "pass", + "summary": "Capability plaintext is asserted absent from task/repo REST bodies, the SQLite file bytes, all artifact bytes, every captured docker/tmux argv, and DEBUG-level caplog after both a 401 and a 403 auth outcome; a serializer field, DB audit row, or auth log line containing the token would fail.", + "timestamp": "2026-10-28T06:06:31.930Z" +} diff --git a/.2119/verdicts/REQ-048.3.3--8d3ee45125d0.json b/.2119/verdicts/REQ-048.3.3--8d3ee45125d0.json new file mode 100644 index 0000000..dbc756b --- /dev/null +++ b/.2119/verdicts/REQ-048.3.3--8d3ee45125d0.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.3.3--8d3ee45125d0", + "requirementId": "REQ-048.3.3", + "hash": "8d3ee45125d0", + "verdict": "pass", + "summary": "After rewriting the credential file without the old token and rebuilding the app, the old-generation capability is asserted 401 on every registered route while middle/new capabilities stay non-401 and still PUT slug; a second removal repeats the check, so either lingering acceptance or over-broad revocation fails.", + "timestamp": "2026-10-28T06:06:33.200Z" +} diff --git a/.2119/verdicts/REQ-048.4.1--069ac26b55f9.json b/.2119/verdicts/REQ-048.4.1--069ac26b55f9.json new file mode 100644 index 0000000..9759a44 --- /dev/null +++ b/.2119/verdicts/REQ-048.4.1--069ac26b55f9.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.4.1--069ac26b55f9", + "requirementId": "REQ-048.4.1", + "hash": "069ac26b55f9", + "verdict": "pass", + "summary": "Own task, transitions, operations, states, skills, briefing, wake, overview, artifact list/bytes, registrations, and the live stream (':ok','keepalive' bytes) are read with the capability and compared byte-for-byte against fleet responses and against a sibling workflow's output; a 403 on any listed surface or substituted sibling data fails.", + "timestamp": "2026-10-28T06:06:34.463Z" +} diff --git a/.2119/verdicts/REQ-048.4.2--7fc82aabb81b.json b/.2119/verdicts/REQ-048.4.2--7fc82aabb81b.json new file mode 100644 index 0000000..a726087 --- /dev/null +++ b/.2119/verdicts/REQ-048.4.2--7fc82aabb81b.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.4.2--7fc82aabb81b", + "requirementId": "REQ-048.4.2", + "hash": "7fc82aabb81b", + "verdict": "pass", + "summary": "GET /tasks with a plain capability must equal exactly [own]; an orchestrator must see exactly {self, child, grandchild} excluding sibling, peer, and ancestor; a non-orchestrator with a governed child must still see only itself, so any leak of unrelated or ungoverned tasks fails the set equality.", + "timestamp": "2026-10-28T06:06:35.722Z" +} diff --git a/.2119/verdicts/REQ-048.4.3--c827e2d037a4.json b/.2119/verdicts/REQ-048.4.3--c827e2d037a4.json new file mode 100644 index 0000000..beae5a6 --- /dev/null +++ b/.2119/verdicts/REQ-048.4.3--c827e2d037a4.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.4.3--c827e2d037a4", + "requirementId": "REQ-048.4.3", + "hash": "c827e2d037a4", + "verdict": "pass", + "summary": "Each of two tasks in different repos reads its own repo's id/name/git_url with asserted values and gets 403 on the other repo; a capability that could read the sibling repo would return 200 and fail.", + "timestamp": "2026-10-28T06:06:37.014Z" +} diff --git a/.2119/verdicts/REQ-048.5.1--b27574118414.json b/.2119/verdicts/REQ-048.5.1--b27574118414.json new file mode 100644 index 0000000..8099e33 --- /dev/null +++ b/.2119/verdicts/REQ-048.5.1--b27574118414.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.5.1--b27574118414", + "requirementId": "REQ-048.5.1", + "hash": "b27574118414", + "verdict": "pass", + "summary": "Slug, URL, turn, blocked, attention, tokens-used, token-estimate, in-scope dependencies, state, transition, operation, and responsibility resolution are each applied with the capability and re-read after a fresh service on the same DB with value equality; a 200 that did not persist or a 403 on any setter fails.", + "timestamp": "2026-10-28T06:06:38.256Z" +} diff --git a/.2119/verdicts/REQ-048.5.2--f8d6164d043c.json b/.2119/verdicts/REQ-048.5.2--f8d6164d043c.json new file mode 100644 index 0000000..9bbdb48 --- /dev/null +++ b/.2119/verdicts/REQ-048.5.2--f8d6164d043c.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.5.2--f8d6164d043c", + "requirementId": "REQ-048.5.2", + "hash": "f8d6164d043c", + "verdict": "pass", + "summary": "PUT creates (204), GET returns the bytes, list equals ['design.md'], a second PUT replaces and the re-read returns the new bytes; a denied replace or missing list entry fails.", + "timestamp": "2026-10-28T06:06:39.568Z" +} diff --git a/.2119/verdicts/REQ-048.5.3--b14998108cbe.json b/.2119/verdicts/REQ-048.5.3--b14998108cbe.json new file mode 100644 index 0000000..4f3493f --- /dev/null +++ b/.2119/verdicts/REQ-048.5.3--b14998108cbe.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.5.3--b14998108cbe", + "requirementId": "REQ-048.5.3", + "hash": "b14998108cbe", + "verdict": "pass", + "summary": "Capability opens a registration (201), lists it, holds /live (200 start plus keepalive bytes), and closes it (204) while sibling registration/live are 403; a denied DELETE /registrations/{id} or live 403 fails.", + "timestamp": "2026-10-28T06:06:40.819Z" +} diff --git a/.2119/verdicts/REQ-048.5.4--4737fec0f256.json b/.2119/verdicts/REQ-048.5.4--4737fec0f256.json new file mode 100644 index 0000000..0d58c3c --- /dev/null +++ b/.2119/verdicts/REQ-048.5.4--4737fec0f256.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.5.4--4737fec0f256", + "requirementId": "REQ-048.5.4", + "hash": "4737fec0f256", + "verdict": "pass", + "summary": "Real enforced service: own claimed task -> 200 changing only lifecycle phase/detail (task record equal, registration retained); unclaimed, other-runner, COMPLETE, DROPPED, ARCHIVED -> 409 with version and lifecycle untouched; extra control fields, blank/None/int runner_id or detail and 4097 chars -> 422 while exactly 4096 -> 200; mutants dropping the terminal check, the claim check, extra=forbid or widening max_length all fail", + "timestamp": "2026-09-14T07:58:36.122Z" +} diff --git a/.2119/verdicts/REQ-048.6.1--5476f71f799e.json b/.2119/verdicts/REQ-048.6.1--5476f71f799e.json new file mode 100644 index 0000000..8dd23fd --- /dev/null +++ b/.2119/verdicts/REQ-048.6.1--5476f71f799e.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.6.1--5476f71f799e", + "requirementId": "REQ-048.6.1", + "hash": "5476f71f799e", + "verdict": "pass", + "summary": "Every route derived from the app containing {task_id} (minus runner-session/retry) plus DELETE /registrations is exercised against a sibling with asserted (403, scope body), including operations/drop, and the sibling's record is asserted unchanged; a successful cross-task drop or any non-403 fails.", + "timestamp": "2026-10-28T06:06:42.084Z" +} diff --git a/.2119/verdicts/REQ-048.6.2--b40669d2ae91.json b/.2119/verdicts/REQ-048.6.2--b40669d2ae91.json new file mode 100644 index 0000000..b42777d --- /dev/null +++ b/.2119/verdicts/REQ-048.6.2--b40669d2ae91.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.6.2--b40669d2ae91", + "requirementId": "REQ-048.6.2", + "hash": "b40669d2ae91", + "verdict": "pass", + "summary": "Admin surface set is independently derived from registered routes, asserted equal to the policy's inventory and to a hardcoded list, then each is called with a task capability expecting (403, scope body) including lifecycle PUT/DELETE on self and migration with an operator token present; a task-token claim or lifecycle report returning 200 fails.", + "timestamp": "2026-10-28T06:06:43.323Z" +} diff --git a/.2119/verdicts/REQ-048.6.3--0fd81d927c61.json b/.2119/verdicts/REQ-048.6.3--0fd81d927c61.json new file mode 100644 index 0000000..493c3fe --- /dev/null +++ b/.2119/verdicts/REQ-048.6.3--0fd81d927c61.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.6.3--0fd81d927c61", + "requirementId": "REQ-048.6.3", + "hash": "0fd81d927c61", + "verdict": "pass", + "summary": "For every task-targeted route and the launcher-failure endpoint, an existing sibling target and 'missing' are both asserted to produce exactly (403, {\"detail\":\"credential scope forbids operation\"}); a 404 for the missing case would fail.", + "timestamp": "2026-10-28T06:06:44.642Z" +} diff --git a/.2119/verdicts/REQ-048.6.4--726594ae9dfe.json b/.2119/verdicts/REQ-048.6.4--726594ae9dfe.json new file mode 100644 index 0000000..5076798 --- /dev/null +++ b/.2119/verdicts/REQ-048.6.4--726594ae9dfe.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.6.4--726594ae9dfe", + "requirementId": "REQ-048.6.4", + "hash": "726594ae9dfe", + "verdict": "pass", + "summary": "Active setup-repo task patches own credential_dir to 200 while sibling repo, every other RepoPatchIn field (set-checked against the model), non-string values, '', '.', '..', '/', absolute, '../x', 'nested/dir', trailing-slash, a non-opted-in task, and COMPLETE/DROPPED setup tasks are all (403, scope body) with repos asserted unchanged; an alternate flagged workflow succeeds so name-matching would fail.", + "timestamp": "2026-10-28T06:06:45.908Z" +} diff --git a/.2119/verdicts/REQ-048.7.1--efeb5255d4af.json b/.2119/verdicts/REQ-048.7.1--efeb5255d4af.json new file mode 100644 index 0000000..52a1d22 --- /dev/null +++ b/.2119/verdicts/REQ-048.7.1--efeb5255d4af.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.7.1--efeb5255d4af", + "requirementId": "REQ-048.7.1", + "hash": "efeb5255d4af", + "verdict": "pass", + "summary": "Orchestrator creates a child with governor=self in its own repo (201), while governor None/unrelated/child and repo r2 each get (403, scope body), a non-orchestrator is denied, and an alternate orchestrates=True workflow succeeds; accepting a wrong governor or repo would fail.", + "timestamp": "2026-10-28T06:06:47.172Z" +} diff --git a/.2119/verdicts/REQ-048.7.2--988df5e5a79f.json b/.2119/verdicts/REQ-048.7.2--988df5e5a79f.json new file mode 100644 index 0000000..4ed010d --- /dev/null +++ b/.2119/verdicts/REQ-048.7.2--988df5e5a79f.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.7.2--988df5e5a79f", + "requirementId": "REQ-048.7.2", + "hash": "988df5e5a79f", + "verdict": "pass", + "summary": "Reads across child/grandchild/great-grandchild (metadata, artifacts, registrations) return 200, and artifact put, slug, token-estimate, turn, dependencies, and planning responsibility are applied and re-read with value equality; a 403 on any preplan action fails.", + "timestamp": "2026-10-28T06:06:48.395Z" +} diff --git a/.2119/verdicts/REQ-048.7.3--0f6269ae90ae.json b/.2119/verdicts/REQ-048.7.3--0f6269ae90ae.json new file mode 100644 index 0000000..8fd176f --- /dev/null +++ b/.2119/verdicts/REQ-048.7.3--0f6269ae90ae.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.7.3--0f6269ae90ae", + "requirementId": "REQ-048.7.3", + "hash": "0f6269ae90ae", + "verdict": "pass", + "summary": "On the governed child, drop/advance/transition/state, claim, provisioning, migration, lifecycle PUT/DELETE, launcher-failure, and governor reassignment (None and unrelated) are each asserted (403, scope body); any of those returning 200 fails.", + "timestamp": "2026-10-28T06:06:49.650Z" +} diff --git a/.2119/verdicts/REQ-048.7.4--86cc5d72cbe2.json b/.2119/verdicts/REQ-048.7.4--86cc5d72cbe2.json new file mode 100644 index 0000000..df7de52 --- /dev/null +++ b/.2119/verdicts/REQ-048.7.4--86cc5d72cbe2.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.7.4--86cc5d72cbe2", + "requirementId": "REQ-048.7.4", + "hash": "86cc5d72cbe2", + "verdict": "pass", + "summary": "A non-orchestrating task with a governed child and grandchild is denied child creation and every read/preplan surface via REST, /live, MCP tools, and the artifact resource with (403, scope body); any permitted delegation action fails.", + "timestamp": "2026-10-28T06:06:50.869Z" +} diff --git a/.2119/verdicts/REQ-048.8.1--8486b6a87004.json b/.2119/verdicts/REQ-048.8.1--8486b6a87004.json new file mode 100644 index 0000000..546ef72 --- /dev/null +++ b/.2119/verdicts/REQ-048.8.1--8486b6a87004.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.8.1--8486b6a87004", + "requirementId": "REQ-048.8.1", + "hash": "8486b6a87004", + "verdict": "pass", + "summary": "For all 15 listed REST/MCP pairs across self, three descendant depths, unrelated, and missing targets, policy.authorize_rest_request is asserted equal to policy.authorize_mcp and the actual REST and /mcp responses are asserted 403 iff denied; an MCP tool allowing a sibling target that REST denies fails.", + "timestamp": "2026-10-28T06:06:52.140Z" +} diff --git a/.2119/verdicts/REQ-048.8.2--203e902b5831.json b/.2119/verdicts/REQ-048.8.2--203e902b5831.json new file mode 100644 index 0000000..0b820d4 --- /dev/null +++ b/.2119/verdicts/REQ-048.8.2--203e902b5831.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.8.2--203e902b5831", + "requirementId": "REQ-048.8.2", + "hash": "203e902b5831", + "verdict": "pass", + "summary": "A conflicting actor_task_id argument leaves subject_task_id equal to the capability's task, sibling task_id in arguments or URI is denied with target recorded as sibling, and %2e%2e-normalized and percent-encoded URIs are asserted to resolve to the expected target; deriving the subject from arguments would fail.", + "timestamp": "2026-10-28T06:06:53.350Z" +} diff --git a/.2119/verdicts/REQ-048.8.3--52b200a79982.json b/.2119/verdicts/REQ-048.8.3--52b200a79982.json new file mode 100644 index 0000000..3fa3cf8 --- /dev/null +++ b/.2119/verdicts/REQ-048.8.3--52b200a79982.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.8.3--52b200a79982", + "requirementId": "REQ-048.8.3", + "hash": "52b200a79982", + "verdict": "pass", + "summary": "The policy inventory is asserted set-equal to every registered APIRoute (minus the four exclusions) and every MCP tool/resource template, with each assignment an AuthorizationClass in the five-value set; an unclassified new route or an out-of-set class fails.", + "timestamp": "2026-10-28T06:06:54.586Z" +} diff --git a/.2119/verdicts/REQ-048.9.1--bf1843471699.json b/.2119/verdicts/REQ-048.9.1--bf1843471699.json new file mode 100644 index 0000000..7babec5 --- /dev/null +++ b/.2119/verdicts/REQ-048.9.1--bf1843471699.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.9.1--bf1843471699", + "requirementId": "REQ-048.9.1", + "hash": "bf1843471699", + "verdict": "pass", + "summary": "Apps start with read absent and read=[] and serve the write token, while write=[], missing write, and string write each raise the invalid-credential ValueError; accepting an empty write array or rejecting an absent read would fail.", + "timestamp": "2026-10-28T06:06:55.880Z" +} diff --git a/.2119/verdicts/REQ-048.9.2--bfa7ff13dab6.json b/.2119/verdicts/REQ-048.9.2--bfa7ff13dab6.json new file mode 100644 index 0000000..44e949d --- /dev/null +++ b/.2119/verdicts/REQ-048.9.2--bfa7ff13dab6.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-048.9.2--bfa7ff13dab6", + "requirementId": "REQ-048.9.2", + "hash": "bfa7ff13dab6", + "verdict": "pass", + "summary": "Every registered GET/HEAD route with 'missing' params and a non-integer entry_index is asserted not 401/403 for the read token except /live and /session/input which must be 401, while every mutation, MCP tool, resource, and unknown tool are 401 before argument validation; a scope-403 on a read route or a 422 on a mutation fails.", + "timestamp": "2026-10-28T06:06:57.141Z" +} diff --git a/.2119/verdicts/REQ-051.1.1--e0599fdfd09b.json b/.2119/verdicts/REQ-051.1.1--e0599fdfd09b.json new file mode 100644 index 0000000..8ca3613 --- /dev/null +++ b/.2119/verdicts/REQ-051.1.1--e0599fdfd09b.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.1.1--e0599fdfd09b", + "requirementId": "REQ-051.1.1", + "hash": "e0599fdfd09b", + "verdict": "pass", + "summary": "Filesystem bootstrap and launch tests assert the .pi volume root, nested agent settings/auth/sessions, and reject legacy-root authentication or resume detection while accepting native paths.", + "timestamp": "2026-09-14T08:55:44.935Z" +} diff --git a/.2119/verdicts/REQ-051.1.2--3f4c8247a14b.json b/.2119/verdicts/REQ-051.1.2--3f4c8247a14b.json new file mode 100644 index 0000000..81b7aec --- /dev/null +++ b/.2119/verdicts/REQ-051.1.2--3f4c8247a14b.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.1.2--3f4c8247a14b", + "requirementId": "REQ-051.1.2", + "hash": "3f4c8247a14b", + "verdict": "pass", + "summary": "Native bootstrap, preflight, session detection, and captured child environment agree on PI_CODING_AGENT_DIR; wrong root, ignored native auth, or omitted child override fail independent assertions.", + "timestamp": "2026-09-14T08:55:45.950Z" +} diff --git a/.2119/verdicts/REQ-051.1.3--f1122a4a63e5.json b/.2119/verdicts/REQ-051.1.3--f1122a4a63e5.json new file mode 100644 index 0000000..b3cb3f2 --- /dev/null +++ b/.2119/verdicts/REQ-051.1.3--f1122a4a63e5.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.1.3--f1122a4a63e5", + "requirementId": "REQ-051.1.3", + "hash": "f1122a4a63e5", + "verdict": "pass", + "summary": "Real bootstrap imports each native auth/models/trust/custom entry both together and alone, compares structured and binary destination content, and snapshots source bytes to reject omission or source mutation.", + "timestamp": "2026-09-14T08:55:46.962Z" +} diff --git a/.2119/verdicts/REQ-051.2.1--439729068fa6.json b/.2119/verdicts/REQ-051.2.1--439729068fa6.json new file mode 100644 index 0000000..407ba6c --- /dev/null +++ b/.2119/verdicts/REQ-051.2.1--439729068fa6.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.2.1--439729068fa6", + "requirementId": "REQ-051.2.1", + "hash": "439729068fa6", + "verdict": "pass", + "summary": "OAuth preflight accepts nonempty native fields and numeric expiry boundaries; wrong provider/type, missing fields, empty strings, nonstring fields, and string/null/boolean expiry near-misses are rejected.", + "timestamp": "2026-09-14T08:55:48.045Z" +} diff --git a/.2119/verdicts/REQ-051.2.2--126a77d1d874.json b/.2119/verdicts/REQ-051.2.2--126a77d1d874.json new file mode 100644 index 0000000..5cca865 --- /dev/null +++ b/.2119/verdicts/REQ-051.2.2--126a77d1d874.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.2.2--126a77d1d874", + "requirementId": "REQ-051.2.2", + "hash": "126a77d1d874", + "verdict": "pass", + "summary": "Malformed and Codex-shaped files at native and mounted locations are rejected with exact actionable credential-free diagnostics; valid Pi entries alongside Codex markers remain accepted and stale persisted auth cannot be bypassed.", + "timestamp": "2026-09-14T08:55:49.051Z" +} diff --git a/.2119/verdicts/REQ-051.2.3--1e40002406e0.json b/.2119/verdicts/REQ-051.2.3--1e40002406e0.json new file mode 100644 index 0000000..c309a77 --- /dev/null +++ b/.2119/verdicts/REQ-051.2.3--1e40002406e0.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.2.3--1e40002406e0", + "requirementId": "REQ-051.2.3", + "hash": "1e40002406e0", + "verdict": "pass", + "summary": "Selected custom providers accept dummy/literal and fully resolved environment keys; missing, empty, partially unresolved, and other-provider-only keys fail despite a valid alternate provider fixture.", + "timestamp": "2026-09-14T08:55:50.095Z" +} diff --git a/.2119/verdicts/REQ-051.2.4--40974079c6be.json b/.2119/verdicts/REQ-051.2.4--40974079c6be.json new file mode 100644 index 0000000..0c1fe05 --- /dev/null +++ b/.2119/verdicts/REQ-051.2.4--40974079c6be.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.2.4--40974079c6be", + "requirementId": "REQ-051.2.4", + "hash": "40974079c6be", + "verdict": "pass", + "summary": "Environment and stored Anthropic API-key paths accept nonempty and resolved strings; missing fields, invalid types/case, empty or unresolved keys, and wrong providers fail while another valid credential remains usable.", + "timestamp": "2026-09-14T08:55:51.060Z" +} diff --git a/.2119/verdicts/REQ-051.2.5--f76b8581d32c.json b/.2119/verdicts/REQ-051.2.5--f76b8581d32c.json new file mode 100644 index 0000000..6775abb --- /dev/null +++ b/.2119/verdicts/REQ-051.2.5--f76b8581d32c.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.2.5--f76b8581d32c", + "requirementId": "REQ-051.2.5", + "hash": "f76b8581d32c", + "verdict": "pass", + "summary": "Setup-token-only preflight is rejected, bootstrap produces no auth file or copied token, diagnostics exclude OAuth remediation, and Pi documentation assertions reject the forbidden setup-token credential path.", + "timestamp": "2026-09-14T08:55:52.043Z" +} diff --git a/.2119/verdicts/REQ-051.2.6--9f28a5c59ac7.json b/.2119/verdicts/REQ-051.2.6--9f28a5c59ac7.json new file mode 100644 index 0000000..1f46c55 --- /dev/null +++ b/.2119/verdicts/REQ-051.2.6--9f28a5c59ac7.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.2.6--9f28a5c59ac7", + "requirementId": "REQ-051.2.6", + "hash": "9f28a5c59ac7", + "verdict": "pass", + "summary": "Explicit OAuth environment and native-file inputs pass preflight and reach the child unchanged; documentation requires the complete unsupported/account-risk warning, rejecting omission or silent credential stripping.", + "timestamp": "2026-09-14T08:55:53.176Z" +} diff --git a/.2119/verdicts/REQ-051.3.1--9796d0085699.json b/.2119/verdicts/REQ-051.3.1--9796d0085699.json new file mode 100644 index 0000000..bc0418f --- /dev/null +++ b/.2119/verdicts/REQ-051.3.1--9796d0085699.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.3.1--9796d0085699", + "requirementId": "REQ-051.3.1", + "hash": "9796d0085699", + "verdict": "pass", + "summary": "Full model-object equality checks HTTP/HTTPS localhost, IPv4, and IPv6 adaptation with ports and portless URLs; nested URLs, metadata, scheme/path/query/fragment, and original source bytes remain preserved.", + "timestamp": "2026-09-14T08:55:54.183Z" +} diff --git a/.2119/verdicts/REQ-051.3.2--31049781af77.json b/.2119/verdicts/REQ-051.3.2--31049781af77.json new file mode 100644 index 0000000..4d433bb --- /dev/null +++ b/.2119/verdicts/REQ-051.3.2--31049781af77.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.3.2--31049781af77", + "requirementId": "REQ-051.3.2", + "hash": "31049781af77", + "verdict": "pass", + "summary": "Native materialization compares LAN/public/Unix/malformed and near-loopback endpoints unchanged, including localhost suffixes, 127.0.0.10, non-loopback IPv6, unspecified addresses, and FTP loopback.", + "timestamp": "2026-09-14T08:55:55.245Z" +} diff --git a/.2119/verdicts/REQ-051.3.3--cd06027383d9.json b/.2119/verdicts/REQ-051.3.3--cd06027383d9.json new file mode 100644 index 0000000..9f5d805 --- /dev/null +++ b/.2119/verdicts/REQ-051.3.3--cd06027383d9.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.3.3--cd06027383d9", + "requirementId": "REQ-051.3.3", + "hash": "cd06027383d9", + "verdict": "pass", + "summary": "First-launch bootstrap and captured child argv require the exact native provider/model argument and complete provider-object preservation except loopback adaptation; accidental resume, truncation, or field loss fails.", + "timestamp": "2026-09-14T08:55:56.253Z" +} diff --git a/.2119/verdicts/REQ-051.4.1--dba58b727830.json b/.2119/verdicts/REQ-051.4.1--dba58b727830.json new file mode 100644 index 0000000..7d3d5e8 --- /dev/null +++ b/.2119/verdicts/REQ-051.4.1--dba58b727830.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.4.1--dba58b727830", + "requirementId": "REQ-051.4.1", + "hash": "dba58b727830", + "verdict": "pass", + "summary": "Zero, positive and negative exit statuses require exact Pi/status failed details and ordered failure reporting before the real stop-handler SIGTERM boundary.", + "timestamp": "2026-09-14T08:10:33.299Z" +} diff --git a/.2119/verdicts/REQ-051.4.2--9cb7a9a9a82b.json b/.2119/verdicts/REQ-051.4.2--9cb7a9a9a82b.json new file mode 100644 index 0000000..3489a99 --- /dev/null +++ b/.2119/verdicts/REQ-051.4.2--9cb7a9a9a82b.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.4.2--9cb7a9a9a82b", + "requirementId": "REQ-051.4.2", + "hash": "9cb7a9a9a82b", + "verdict": "pass", + "summary": "Real Spawner under HostDaemon.tick against an enforced service for 257 passes: claim, failed status and exact detail unchanged, tasks version unchanged, autospec runner and executions receive zero calls, and only release clears; removing _is_orphan's FAILED exclusion fails on the first pass", + "timestamp": "2026-09-14T07:58:48.865Z" +} diff --git a/.2119/verdicts/REQ-051.4.3--851966d5fee8.json b/.2119/verdicts/REQ-051.4.3--851966d5fee8.json new file mode 100644 index 0000000..9794e68 --- /dev/null +++ b/.2119/verdicts/REQ-051.4.3--851966d5fee8.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.4.3--851966d5fee8", + "requirementId": "REQ-051.4.3", + "hash": "851966d5fee8", + "verdict": "pass", + "summary": "Malformed, empty and codex-shaped inputs require one exact credential-free message in lifecycle and stderr; authenticated service evidence verifies persistence before launcher return.", + "timestamp": "2026-09-14T08:10:34.404Z" +} diff --git a/.2119/verdicts/REQ-051.4.4--0c1e64e78580.json b/.2119/verdicts/REQ-051.4.4--0c1e64e78580.json new file mode 100644 index 0000000..9a40f44 --- /dev/null +++ b/.2119/verdicts/REQ-051.4.4--0c1e64e78580.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.4.4--0c1e64e78580", + "requirementId": "REQ-051.4.4", + "hash": "0c1e64e78580", + "verdict": "pass", + "summary": "Real claimed and registered tasks retain preflight, workflow, bootstrap and launch failures without readiness through 257 daemon passes until explicit release; transport-fetch tests require reporting on all three fetch operations.", + "timestamp": "2026-09-14T08:10:35.700Z" +} diff --git a/.2119/verdicts/REQ-051.4.5--7f27b19d0b5d.json b/.2119/verdicts/REQ-051.4.5--7f27b19d0b5d.json new file mode 100644 index 0000000..6d9bd2f --- /dev/null +++ b/.2119/verdicts/REQ-051.4.5--7f27b19d0b5d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.4.5--7f27b19d0b5d", + "requirementId": "REQ-051.4.5", + "hash": "7f27b19d0b5d", + "verdict": "pass", + "summary": "Enforced-auth integration exercises task-capability failure reporting; both real buffered-stderr paths reject independent disabled-flush mutants, rejected and timed-out reports preserve diagnosis and exit, and long reports retain the first 4096 characters with full stderr.", + "timestamp": "2026-09-14T08:10:36.812Z" +} diff --git a/.2119/verdicts/REQ-051.4.6--3608b2771ce4.json b/.2119/verdicts/REQ-051.4.6--3608b2771ce4.json new file mode 100644 index 0000000..aa822c1 --- /dev/null +++ b/.2119/verdicts/REQ-051.4.6--3608b2771ce4.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.4.6--3608b2771ce4", + "requirementId": "REQ-051.4.6", + "hash": "3608b2771ce4", + "verdict": "pass", + "summary": "LocalRunner.spawn with a recording tmux runner yields events starting, awaiting, launch, failed with the agent failing inside respawn-pane, and the task still reads failed after spawn returns; moving the AWAITING report after respawn-pane fails the workflow case", + "timestamp": "2026-09-14T07:58:53.537Z" +} diff --git a/.2119/verdicts/REQ-051.4.7--8e80a3359472.json b/.2119/verdicts/REQ-051.4.7--8e80a3359472.json new file mode 100644 index 0000000..64191ce --- /dev/null +++ b/.2119/verdicts/REQ-051.4.7--8e80a3359472.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.4.7--8e80a3359472", + "requirementId": "REQ-051.4.7", + "hash": "8e80a3359472", + "verdict": "pass", + "summary": "Tests require report-before-stop despite rejected or unavailable reporting, including the separate transport branch; real service callbacks remove registration and operator retry clears failure and releases the claim.", + "timestamp": "2026-09-14T08:10:37.957Z" +} diff --git a/.2119/verdicts/REQ-051.5.1--4685782778fb.json b/.2119/verdicts/REQ-051.5.1--4685782778fb.json new file mode 100644 index 0000000..0e1f198 --- /dev/null +++ b/.2119/verdicts/REQ-051.5.1--4685782778fb.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-051.5.1--4685782778fb", + "requirementId": "REQ-051.5.1", + "hash": "4685782778fb", + "verdict": "pass", + "summary": "Pinned native resource loading consumes generated first-run and resume arguments, checks skill instructions in loaded resources and prompt, and explicitly rejects missing or malformed rendered skill files.", + "timestamp": "2026-09-14T08:55:57.282Z" +} diff --git a/.2119/verdicts/REQ-053.1.1--6077d61f80e1.json b/.2119/verdicts/REQ-053.1.1--6077d61f80e1.json new file mode 100644 index 0000000..f1036e1 --- /dev/null +++ b/.2119/verdicts/REQ-053.1.1--6077d61f80e1.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-053.1.1--6077d61f80e1", + "requirementId": "REQ-053.1.1", + "hash": "6077d61f80e1", + "verdict": "pass", + "summary": "Compositor output checks the bottom hidden-content indicator at top/middle offsets, full label in spare cells, one-cell arrow, and no overwrite when no cell is free.", + "timestamp": "2026-09-14T07:54:31.308Z" +} diff --git a/.2119/verdicts/REQ-053.2.1--90fb89bcabaf.json b/.2119/verdicts/REQ-053.2.1--90fb89bcabaf.json new file mode 100644 index 0000000..b0738d2 --- /dev/null +++ b/.2119/verdicts/REQ-053.2.1--90fb89bcabaf.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-053.2.1--90fb89bcabaf", + "requirementId": "REQ-053.2.1", + "hash": "90fb89bcabaf", + "verdict": "pass", + "summary": "Compositor output checks the top indicator below the header after scrolling, full label, one-cell arrow and omission where row content fills the width.", + "timestamp": "2026-09-14T07:54:32.597Z" +} diff --git a/.2119/verdicts/REQ-053.3.1--59558cc9c9ab.json b/.2119/verdicts/REQ-053.3.1--59558cc9c9ab.json new file mode 100644 index 0000000..083f401 --- /dev/null +++ b/.2119/verdicts/REQ-053.3.1--59558cc9c9ab.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-053.3.1--59558cc9c9ab", + "requirementId": "REQ-053.3.1", + "hash": "59558cc9c9ab", + "verdict": "pass", + "summary": "Top, bottom and all-fitting viewports assert absence of indicators whenever that direction has no hidden content.", + "timestamp": "2026-09-14T07:54:33.845Z" +} diff --git a/.2119/verdicts/REQ-053.4.1--5092fb48dccf.json b/.2119/verdicts/REQ-053.4.1--5092fb48dccf.json new file mode 100644 index 0000000..8bbf46d --- /dev/null +++ b/.2119/verdicts/REQ-053.4.1--5092fb48dccf.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-053.4.1--5092fb48dccf", + "requirementId": "REQ-053.4.1", + "hash": "5092fb48dccf", + "verdict": "pass", + "summary": "Rendered horizontal scrollbar cells and thumb styles equal the no-vertical-overflow baseline across x/y offsets, with width and scrollbar-size invariants.", + "timestamp": "2026-09-14T07:54:35.136Z" +} diff --git a/.2119/verdicts/REQ-053.5.1--744581fafd50.json b/.2119/verdicts/REQ-053.5.1--744581fafd50.json new file mode 100644 index 0000000..7f79953 --- /dev/null +++ b/.2119/verdicts/REQ-053.5.1--744581fafd50.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-053.5.1--744581fafd50", + "requirementId": "REQ-053.5.1", + "hash": "744581fafd50", + "verdict": "pass", + "summary": "Real keyboard traversal through every row in both directions checks identifying text and cursor background in compositor output, including narrow-content protection.", + "timestamp": "2026-09-14T07:54:36.361Z" +} diff --git a/.2119/verdicts/REQ-053.6.1--68901d04c6c4.json b/.2119/verdicts/REQ-053.6.1--68901d04c6c4.json new file mode 100644 index 0000000..f30a06c --- /dev/null +++ b/.2119/verdicts/REQ-053.6.1--68901d04c6c4.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-053.6.1--68901d04c6c4", + "requirementId": "REQ-053.6.1", + "hash": "68901d04c6c4", + "verdict": "pass", + "summary": "Every vertical offset is scanned for each intersecting real row ID, including layouts with ensemble summaries; narrow layouts compare content to an unmodified baseline.", + "timestamp": "2026-09-14T07:54:37.624Z" +} diff --git a/.2119/verdicts/REQ-054.1.2--5978a59c4973.json b/.2119/verdicts/REQ-054.1.2--5978a59c4973.json new file mode 100644 index 0000000..51c1941 --- /dev/null +++ b/.2119/verdicts/REQ-054.1.2--5978a59c4973.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-054.1.2--5978a59c4973", + "requirementId": "REQ-054.1.2", + "hash": "5978a59c4973", + "verdict": "pass", + "summary": "Opt-in live journey asserts no panopticon on PATH, installs the doc-parsed wheel into a fresh pipx home with isolated HOME and no PYTHONPATH passthrough, resolves the executable from a fresh login shell, and runs --version and doctor from a non-checkout cwd; evidence exists only under the disposable-host opt-in.", + "timestamp": "2026-09-14T06:56:29.696Z" +} diff --git a/.2119/verdicts/REQ-054.1.3--a3e7162ad033.json b/.2119/verdicts/REQ-054.1.3--a3e7162ad033.json new file mode 100644 index 0000000..46b04c2 --- /dev/null +++ b/.2119/verdicts/REQ-054.1.3--a3e7162ad033.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-054.1.3--a3e7162ad033", + "requirementId": "REQ-054.1.3", + "hash": "a3e7162ad033", + "verdict": "pass", + "summary": "Unmocked cli.main(['--version']) must exit 0 and print exactly 'panopticon ' plus importlib.metadata's installed version; the live journey cross-checks the same output against pipx's reported package version.", + "timestamp": "2026-09-14T06:56:30.686Z" +} diff --git a/.2119/verdicts/REQ-054.7.1--8125a690752d.json b/.2119/verdicts/REQ-054.7.1--8125a690752d.json new file mode 100644 index 0000000..a55a53b --- /dev/null +++ b/.2119/verdicts/REQ-054.7.1--8125a690752d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-054.7.1--8125a690752d", + "requirementId": "REQ-054.7.1", + "hash": "8125a690752d", + "verdict": "pass", + "summary": "Live fixture asserts isolated config/data/cache absent, the panopticon tmux server has no session and no socket, docker ps --all is empty, and the GitHub repo is https github.com with the acceptance prefix, disposable topic, push permission, reviewed base SHA at the default branch head, and no marker file; opt-in only.", + "timestamp": "2026-09-14T06:56:31.693Z" +} diff --git a/.2119/verdicts/REQ-054.7.2--4f643c009183.json b/.2119/verdicts/REQ-054.7.2--4f643c009183.json new file mode 100644 index 0000000..7b64e05 --- /dev/null +++ b/.2119/verdicts/REQ-054.7.2--4f643c009183.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-054.7.2--4f643c009183", + "requirementId": "REQ-054.7.2", + "hash": "4f643c009183", + "verdict": "pass", + "summary": "Live PTY journey installs via the doc-parsed pipx argv, drives only documented quickstart prompts, verifies service and runner tmux sessions, runs panopticon tasks from an env with auth variables stripped (and 401 with a bad token), and completes one github-self-reviewed task to COMPLETE with a merged PR; the walkthrough is SHA-pinned; opt-in only.", + "timestamp": "2026-09-14T06:56:32.677Z" +} diff --git a/.2119/verdicts/REQ-054.7.6--a7d9a1ab4b4a.json b/.2119/verdicts/REQ-054.7.6--a7d9a1ab4b4a.json new file mode 100644 index 0000000..bc87d77 --- /dev/null +++ b/.2119/verdicts/REQ-054.7.6--a7d9a1ab4b4a.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-054.7.6--a7d9a1ab4b4a", + "requirementId": "REQ-054.7.6", + "hash": "a7d9a1ab4b4a", + "verdict": "pass", + "summary": "Task is created only via documented n/picker/workflow/prompt keystrokes after asserting zero pre-existing tasks, and both PLANNING and ITERATING approvals are typed into the attached agent pane while a monitor fails on any transition before input; deterministic tests prove the monitor rejects automatic transitions.", + "timestamp": "2026-09-14T06:56:33.762Z" +} diff --git a/.2119/verdicts/REQ-054.7.7--1333db5ef5cf.json b/.2119/verdicts/REQ-054.7.7--1333db5ef5cf.json new file mode 100644 index 0000000..f685608 --- /dev/null +++ b/.2119/verdicts/REQ-054.7.7--1333db5ef5cf.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-054.7.7--1333db5ef5cf", + "requirementId": "REQ-054.7.7", + "hash": "1333db5ef5cf", + "verdict": "pass", + "summary": "A runtime httpx hook raises on any non-GET/HEAD post-setup request and a pinned-AST guard whitelists post-setup calls, driver inputs, loops, and helper bodies; a deterministic test runs the guard on the file itself and many shortcut cases prove REST, MCP, fixture, seeded-task, alias, and rebinding mutations are rejected.", + "timestamp": "2026-09-14T06:56:34.800Z" +} diff --git a/.2119/verdicts/REQ-054.7.8--66facda09a35.json b/.2119/verdicts/REQ-054.7.8--66facda09a35.json new file mode 100644 index 0000000..8830de6 --- /dev/null +++ b/.2119/verdicts/REQ-054.7.8--66facda09a35.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-054.7.8--66facda09a35", + "requirementId": "REQ-054.7.8", + "hash": "66facda09a35", + "verdict": "pass", + "summary": "quickstart is forked onto a real pty; 't' and the doc-parsed Ctrl-b d chord are sent only while list-clients shows the expected sole session with a monitor failing on any premature switch (including after a NUL probe), and the dashboard pane id and pane pid are asserted unchanged after return; opt-in only.", + "timestamp": "2026-09-14T06:56:35.803Z" +} diff --git a/.2119/verdicts/REQ-054.7.9--bab32ddd4708.json b/.2119/verdicts/REQ-054.7.9--bab32ddd4708.json new file mode 100644 index 0000000..d10232e --- /dev/null +++ b/.2119/verdicts/REQ-054.7.9--bab32ddd4708.json @@ -0,0 +1,8 @@ +{ + "reviewId": "REQ-054.7.9--bab32ddd4708", + "requirementId": "REQ-054.7.9", + "hash": "bab32ddd4708", + "verdict": "pass", + "summary": "open/xdg-open and BROWSER are recorder shims; a monitor fails if a log appears before the doc-parsed a or p key, the artifact log must contain exactly one line equal to data/artifacts//plan.md with bytes matching the REST artifact, and the browser log must equal the task's PR URL; opt-in only.", + "timestamp": "2026-09-14T06:56:36.859Z" +} diff --git a/.2119/verdicts/foreground-setup.1.3--3e1f6a7d24e5.json b/.2119/verdicts/foreground-setup.1.3--3e1f6a7d24e5.json new file mode 100644 index 0000000..963972a --- /dev/null +++ b/.2119/verdicts/foreground-setup.1.3--3e1f6a7d24e5.json @@ -0,0 +1,8 @@ +{ + "reviewId": "foreground-setup.1.3--3e1f6a7d24e5", + "requirementId": "foreground-setup.1.3", + "hash": "3e1f6a7d24e5", + "verdict": "pass", + "summary": "Actual repository-screen s invokes configure_repo with the selected repo; interrupted attempts preserve the second selection without creating or releasing tasks.", + "timestamp": "2026-09-14T07:54:38.835Z" +} diff --git a/.2119/verdicts/foreground-setup.1.6--832584d5ac1e.json b/.2119/verdicts/foreground-setup.1.6--832584d5ac1e.json new file mode 100644 index 0000000..d1aaecc --- /dev/null +++ b/.2119/verdicts/foreground-setup.1.6--832584d5ac1e.json @@ -0,0 +1,8 @@ +{ + "reviewId": "foreground-setup.1.6--832584d5ac1e", + "requirementId": "foreground-setup.1.6", + "hash": "832584d5ac1e", + "verdict": "pass", + "summary": "Bare invocation on a fresh install routes to quickstart with the real doctor checks and tmux absent from PATH: output must include the not-found line and both install commands from the real hint, exit is 1, and migrate/session start are asserted never called; only the tmux prerequisite is exercised.", + "timestamp": "2026-09-14T06:56:37.860Z" +} diff --git a/.2119/verdicts/full-width-dashboard.1.1--bf7a0d996595.json b/.2119/verdicts/full-width-dashboard.1.1--bf7a0d996595.json new file mode 100644 index 0000000..387a5a0 --- /dev/null +++ b/.2119/verdicts/full-width-dashboard.1.1--bf7a0d996595.json @@ -0,0 +1,8 @@ +{ + "reviewId": "full-width-dashboard.1.1--bf7a0d996595", + "requirementId": "full-width-dashboard.1.1", + "hash": "bf7a0d996595", + "verdict": "pass", + "summary": "A genuinely vertically overflowing mounted table has zero-width vertical scrollbar and equal scrollable/content-region widths.", + "timestamp": "2026-09-14T07:54:40.129Z" +} diff --git a/.2119/verdicts/full-width-dashboard.1.2--9b22f04337ea.json b/.2119/verdicts/full-width-dashboard.1.2--9b22f04337ea.json new file mode 100644 index 0000000..ccb13d6 --- /dev/null +++ b/.2119/verdicts/full-width-dashboard.1.2--9b22f04337ea.json @@ -0,0 +1,8 @@ +{ + "reviewId": "full-width-dashboard.1.2--9b22f04337ea", + "requirementId": "full-width-dashboard.1.2", + "hash": "9b22f04337ea", + "verdict": "pass", + "summary": "Down-key traversal visits every real row and keeps its row region inside the window while the vertical scrollbar remains zero-width.", + "timestamp": "2026-09-14T07:54:41.400Z" +} diff --git a/.2119/verdicts/layered-settings-hints.1.1--3df14fffa455.json b/.2119/verdicts/layered-settings-hints.1.1--3df14fffa455.json new file mode 100644 index 0000000..5986320 --- /dev/null +++ b/.2119/verdicts/layered-settings-hints.1.1--3df14fffa455.json @@ -0,0 +1,8 @@ +{ + "reviewId": "layered-settings-hints.1.1--3df14fffa455", + "requirementId": "layered-settings-hints.1.1", + "hash": "3df14fffa455", + "verdict": "pass", + "summary": "Every current relationship has exact surfaces and setting names; isolated relationship rendering names the opposite layer in each direction.", + "timestamp": "2026-09-14T07:54:42.602Z" +} diff --git a/.2119/verdicts/layered-settings-hints.2.1--34f6c5b3b85d.json b/.2119/verdicts/layered-settings-hints.2.1--34f6c5b3b85d.json new file mode 100644 index 0000000..40685e6 --- /dev/null +++ b/.2119/verdicts/layered-settings-hints.2.1--34f6c5b3b85d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "layered-settings-hints.2.1--34f6c5b3b85d", + "requirementId": "layered-settings-hints.2.1", + "hash": "34f6c5b3b85d", + "verdict": "pass", + "summary": "The registry and exact visible hints cover reviewer, workflow launch, repo launch and opt-in availability relationships with distinct override/filter semantics.", + "timestamp": "2026-09-14T07:54:43.882Z" +} diff --git a/.2119/verdicts/layered-settings-hints.3.1--38e6e3c9457e.json b/.2119/verdicts/layered-settings-hints.3.1--38e6e3c9457e.json new file mode 100644 index 0000000..9287496 --- /dev/null +++ b/.2119/verdicts/layered-settings-hints.3.1--38e6e3c9457e.json @@ -0,0 +1,8 @@ +{ + "reviewId": "layered-settings-hints.3.1--38e6e3c9457e", + "requirementId": "layered-settings-hints.3.1", + "hash": "38e6e3c9457e", + "verdict": "pass", + "summary": "Exact text/style/widget-count checks combine with SVG-painted full-hint checks on all three surfaces at 80/120 columns; forcing one-cell clipped hints fails all ten layout cases.", + "timestamp": "2026-09-14T07:54:45.091Z" +} diff --git a/.2119/verdicts/layered-settings-hints.4.1--d918efa5cdac.json b/.2119/verdicts/layered-settings-hints.4.1--d918efa5cdac.json new file mode 100644 index 0000000..9d8df4a --- /dev/null +++ b/.2119/verdicts/layered-settings-hints.4.1--d918efa5cdac.json @@ -0,0 +1,8 @@ +{ + "reviewId": "layered-settings-hints.4.1--d918efa5cdac", + "requirementId": "layered-settings-hints.4.1", + "hash": "d918efa5cdac", + "verdict": "pass", + "summary": "Exact workflow-screen text identifies repo reviewer overrides, repo availability filtering and per-task harness/model overrides, rejecting inheritance wording.", + "timestamp": "2026-09-14T07:54:46.338Z" +} diff --git a/.2119/verdicts/layered-settings-hints.5.1--a77893723316.json b/.2119/verdicts/layered-settings-hints.5.1--a77893723316.json new file mode 100644 index 0000000..7ba3fc7 --- /dev/null +++ b/.2119/verdicts/layered-settings-hints.5.1--a77893723316.json @@ -0,0 +1,8 @@ +{ + "reviewId": "layered-settings-hints.5.1--a77893723316", + "requirementId": "layered-settings-hints.5.1", + "hash": "a77893723316", + "verdict": "pass", + "summary": "Exact repo-screen hint identifies workflow sources for reviewers/availability and per-task overrides for repo harness/model defaults.", + "timestamp": "2026-09-14T07:54:47.544Z" +} diff --git a/.2119/verdicts/layered-settings-hints.6.1--45e564af521a.json b/.2119/verdicts/layered-settings-hints.6.1--45e564af521a.json new file mode 100644 index 0000000..c837ed4 --- /dev/null +++ b/.2119/verdicts/layered-settings-hints.6.1--45e564af521a.json @@ -0,0 +1,8 @@ +{ + "reviewId": "layered-settings-hints.6.1--45e564af521a", + "requirementId": "layered-settings-hints.6.1", + "hash": "45e564af521a", + "verdict": "pass", + "summary": "Real modal and API tests cover effective app/repo/workflow launch provenance before overrides, including refreshed defaults and painted summaries at 80/120 columns.", + "timestamp": "2026-09-14T07:54:48.853Z" +} diff --git a/.2119/verdicts/runtime-readiness.2.1--e28455ca485f.json b/.2119/verdicts/runtime-readiness.2.1--e28455ca485f.json new file mode 100644 index 0000000..7badfee --- /dev/null +++ b/.2119/verdicts/runtime-readiness.2.1--e28455ca485f.json @@ -0,0 +1,8 @@ +{ + "reviewId": "runtime-readiness.2.1--e28455ca485f", + "requirementId": "runtime-readiness.2.1", + "hash": "e28455ca485f", + "verdict": "pass", + "summary": "Tests assert /identity is 401 unauthenticated and 200 with a read token, body service=='panopticon-task-service', api_revision==1, version==version('panopticon-next') (nonempty), instance_id equal to the resolved launch runtime's id even when the parent process env carries a stale PANOPTICON_INSTANCE_ID, and the auth secret absent from the body; a public endpoint, inherited stale identity, or leaked secret is rejected.", + "timestamp": "2026-10-28T06:05:54.236Z" +} diff --git a/.2119/verdicts/runtime-readiness.2.2--6754e34f7505.json b/.2119/verdicts/runtime-readiness.2.2--6754e34f7505.json new file mode 100644 index 0000000..1d3ddb1 --- /dev/null +++ b/.2119/verdicts/runtime-readiness.2.2--6754e34f7505.json @@ -0,0 +1,8 @@ +{ + "reviewId": "runtime-readiness.2.2--6754e34f7505", + "requirementId": "runtime-readiness.2.2", + "hash": "6754e34f7505", + "verdict": "pass", + "summary": "test_runtime_identity_is_authenticated_fleet_read asserts policy.classification_for_rest('GET','/identity') is AuthorizationClass.FLEET_READ alongside behavioral 401 without a token and 200 with a read-only token, so classifying the route as public (unauthenticated 200) or fleet-write (read token 401) is rejected.", + "timestamp": "2026-10-28T06:05:55.462Z" +} diff --git a/.2119/verdicts/skip-terminal-provisioner.1.1--2ba145c5e504.json b/.2119/verdicts/skip-terminal-provisioner.1.1--2ba145c5e504.json new file mode 100644 index 0000000..1b81ada --- /dev/null +++ b/.2119/verdicts/skip-terminal-provisioner.1.1--2ba145c5e504.json @@ -0,0 +1,8 @@ +{ + "reviewId": "skip-terminal-provisioner.1.1--2ba145c5e504", + "requirementId": "skip-terminal-provisioner.1.1", + "hash": "2ba145c5e504", + "verdict": "pass", + "summary": "Terminal task is now claimed by the daemon's runner (host-1), so terminal state is the only reason provision is skipped; a nonterminal control with the same claim is provisioned; deleting the terminal gate in HostDaemon.tick fails all three parametrizations (COMPLETE, DROPPED, projected terminal).", + "timestamp": "2026-09-14T07:09:33.107Z" +} diff --git a/.2119/verdicts/skip-terminal-provisioner.1.2--dc3ad69edc38.json b/.2119/verdicts/skip-terminal-provisioner.1.2--dc3ad69edc38.json new file mode 100644 index 0000000..d63d062 --- /dev/null +++ b/.2119/verdicts/skip-terminal-provisioner.1.2--dc3ad69edc38.json @@ -0,0 +1,8 @@ +{ + "reviewId": "skip-terminal-provisioner.1.2--dc3ad69edc38", + "requirementId": "skip-terminal-provisioner.1.2", + "hash": "dc3ad69edc38", + "verdict": "pass", + "summary": "cleaned == ['terminal'] is asserted for COMPLETE, DROPPED and a projected-terminal custom state on a task claimed by this runner; gating cleanup on non-terminal fails all three.", + "timestamp": "2026-09-14T07:09:34.129Z" +} diff --git a/.2119/verdicts/task-auth-readiness.3.1--07095e3cf1e7.json b/.2119/verdicts/task-auth-readiness.3.1--07095e3cf1e7.json new file mode 100644 index 0000000..9956c7c --- /dev/null +++ b/.2119/verdicts/task-auth-readiness.3.1--07095e3cf1e7.json @@ -0,0 +1,8 @@ +{ + "reviewId": "task-auth-readiness.3.1--07095e3cf1e7", + "requirementId": "task-auth-readiness.3.1", + "hash": "07095e3cf1e7", + "verdict": "pass", + "summary": "Real credential checks precede the container spawn boundary; missing repository transport leaves no workspace or launch, while repaired transport starts only after explicit retry.", + "timestamp": "2026-09-14T08:00:30.804Z" +} diff --git a/.2119/verdicts/task-auth-readiness.3.2--1965e7dbada3.json b/.2119/verdicts/task-auth-readiness.3.2--1965e7dbada3.json new file mode 100644 index 0000000..8275019 --- /dev/null +++ b/.2119/verdicts/task-auth-readiness.3.2--1965e7dbada3.json @@ -0,0 +1,8 @@ +{ + "reviewId": "task-auth-readiness.3.2--1965e7dbada3", + "requirementId": "task-auth-readiness.3.2", + "hash": "1965e7dbada3", + "verdict": "pass", + "summary": "Synthetic ambient credentials do not satisfy repository readiness, and network, HTTP, subprocess, and agent-execution boundaries are guarded during real presence checks.", + "timestamp": "2026-09-14T08:00:32.130Z" +} diff --git a/.2119/verdicts/task-auth-readiness.3.3--462183793dd9.json b/.2119/verdicts/task-auth-readiness.3.3--462183793dd9.json new file mode 100644 index 0000000..582c608 --- /dev/null +++ b/.2119/verdicts/task-auth-readiness.3.3--462183793dd9.json @@ -0,0 +1,8 @@ +{ + "reviewId": "task-auth-readiness.3.3--462183793dd9", + "requirementId": "task-auth-readiness.3.3", + "hash": "462183793dd9", + "verdict": "pass", + "summary": "Real REST and store assertions preserve the claiming runner and durable task pause and require the selected harness plus foreground setup and retry in the failure reason.", + "timestamp": "2026-09-14T08:00:33.525Z" +} diff --git a/.2119/verdicts/task-auth-readiness.3.4--0c9955ebd1d0.json b/.2119/verdicts/task-auth-readiness.3.4--0c9955ebd1d0.json new file mode 100644 index 0000000..58b510e --- /dev/null +++ b/.2119/verdicts/task-auth-readiness.3.4--0c9955ebd1d0.json @@ -0,0 +1,8 @@ +{ + "reviewId": "task-auth-readiness.3.4--0c9955ebd1d0", + "requirementId": "task-auth-readiness.3.4", + "hash": "0c9955ebd1d0", + "verdict": "pass", + "summary": "Repairing repository credential files does not release the failed task or enable spawning and healing; persisted holds survive service restart and only explicit retry reopens execution.", + "timestamp": "2026-09-14T08:00:34.919Z" +} diff --git a/.2119/verdicts/task-auth-readiness.3.5--6f59c463ca1e.json b/.2119/verdicts/task-auth-readiness.3.5--6f59c463ca1e.json new file mode 100644 index 0000000..0975853 --- /dev/null +++ b/.2119/verdicts/task-auth-readiness.3.5--6f59c463ca1e.json @@ -0,0 +1,8 @@ +{ + "reviewId": "task-auth-readiness.3.5--6f59c463ca1e", + "requirementId": "task-auth-readiness.3.5", + "hash": "6f59c463ca1e", + "verdict": "pass", + "summary": "The actual spawn dispatcher reaches the shell backend with no container credentials and fails the test if it invokes the injected credential check.", + "timestamp": "2026-09-14T08:00:36.278Z" +} diff --git a/.2119/verdicts/task-auth-readiness.3.6--e90052889e3f.json b/.2119/verdicts/task-auth-readiness.3.6--e90052889e3f.json new file mode 100644 index 0000000..25cd6cb --- /dev/null +++ b/.2119/verdicts/task-auth-readiness.3.6--e90052889e3f.json @@ -0,0 +1,8 @@ +{ + "reviewId": "task-auth-readiness.3.6--e90052889e3f", + "requirementId": "task-auth-readiness.3.6", + "hash": "e90052889e3f", + "verdict": "pass", + "summary": "Claude gateway and Codex transports are exercised with Pi environment, native file, OAuth, and custom-model matrices; missing or malformed transport controls reject false readiness.", + "timestamp": "2026-09-14T08:00:37.608Z" +} diff --git a/.2119/verdicts/task-auth-readiness.3.7--c60ac8d6c312.json b/.2119/verdicts/task-auth-readiness.3.7--c60ac8d6c312.json new file mode 100644 index 0000000..d10f59d --- /dev/null +++ b/.2119/verdicts/task-auth-readiness.3.7--c60ac8d6c312.json @@ -0,0 +1,8 @@ +{ + "reviewId": "task-auth-readiness.3.7--c60ac8d6c312", + "requirementId": "task-auth-readiness.3.7", + "hash": "c60ac8d6c312", + "verdict": "pass", + "summary": "A stale task candidate rejected by real repository admission retains the concrete service rejection reason in captured runner diagnostics.", + "timestamp": "2026-09-14T08:00:38.870Z" +} diff --git a/.2119/verdicts/task-auth-readiness.3.8--45bd73b2a766.json b/.2119/verdicts/task-auth-readiness.3.8--45bd73b2a766.json new file mode 100644 index 0000000..b0b3e79 --- /dev/null +++ b/.2119/verdicts/task-auth-readiness.3.8--45bd73b2a766.json @@ -0,0 +1,8 @@ +{ + "reviewId": "task-auth-readiness.3.8--45bd73b2a766", + "requirementId": "task-auth-readiness.3.8", + "hash": "45bd73b2a766", + "verdict": "pass", + "summary": "After reopening the persistent store and constructing a fresh runner, claimed and unclaimed paused tasks cannot reach spawn, heal, or startup-release side effects.", + "timestamp": "2026-09-14T08:00:40.057Z" +} diff --git a/.2119/verdicts/task-auth-readiness.3.9--4afbbb4e0463.json b/.2119/verdicts/task-auth-readiness.3.9--4afbbb4e0463.json new file mode 100644 index 0000000..73e6d13 --- /dev/null +++ b/.2119/verdicts/task-auth-readiness.3.9--4afbbb4e0463.json @@ -0,0 +1,8 @@ +{ + "reviewId": "task-auth-readiness.3.9--4afbbb4e0463", + "requirementId": "task-auth-readiness.3.9", + "hash": "4afbbb4e0463", + "verdict": "pass", + "summary": "The real container launcher accepts persistent Codex credentials, rejects their removal, and reports through the current launcher-failure API; bypassing validation is rejected by the test.", + "timestamp": "2026-09-14T08:00:41.328Z" +} From 626d82128b51a2e4088bbfe878ba2fc4aa33a602 Mon Sep 17 00:00:00 2001 From: Panopticon Agent Date: Tue, 27 Oct 2026 23:32:09 -0700 Subject: [PATCH 10/10] test(2119): distinguish advisory requirements from coverage gaps The repository-policy test incorrectly required coveredCount to equal the number of all requirements. The gate legitimately counts unannotated MAY and SHOULD statements in the total without treating them as missing mandatory coverage; the current corpus has four such advisory items. Require zero uncovered requirements and a nonempty, bounded covered count. Add an unannotated MAY to the mixed-grammar fixture and pin six discovered items, five covered MUSTs and no uncovered obligations. Canonical namespace, legacy verdict and mandatory coverage checks remain intact; no enforcement setting or requirement is weakened. Validation: the policy module passes six tests with two migration-window skips. Removing a MUST annotation and incorrectly counting the optional item as covered are each rejected by targeted in-memory mutations. Eight fresh independent Fable reviews passed the affected requirements; their verdicts are included so a clean checkout can reproduce the gate. --- .../file-scoped-requirement-ids.3.1--86689f563d84.json | 8 ++++++++ .../file-scoped-requirement-ids.3.2--55b19cd3a9a3.json | 8 ++++++++ .../file-scoped-requirement-ids.3.3--a778316bf0e6.json | 8 ++++++++ .../file-scoped-requirement-ids.3.4--4e686207f691.json | 8 ++++++++ .../file-scoped-requirement-ids.4.1--7a14b7f2a87c.json | 8 ++++++++ .../file-scoped-requirement-ids.4.2--484a886ba42f.json | 8 ++++++++ .../file-scoped-requirement-ids.4.3--c6ae11d6e00d.json | 8 ++++++++ .../file-scoped-requirement-ids.4.4--239fe11577aa.json | 8 ++++++++ tests/test_2119_file_scoped_ids.py | 9 ++++++--- 9 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 .2119/verdicts/file-scoped-requirement-ids.3.1--86689f563d84.json create mode 100644 .2119/verdicts/file-scoped-requirement-ids.3.2--55b19cd3a9a3.json create mode 100644 .2119/verdicts/file-scoped-requirement-ids.3.3--a778316bf0e6.json create mode 100644 .2119/verdicts/file-scoped-requirement-ids.3.4--4e686207f691.json create mode 100644 .2119/verdicts/file-scoped-requirement-ids.4.1--7a14b7f2a87c.json create mode 100644 .2119/verdicts/file-scoped-requirement-ids.4.2--484a886ba42f.json create mode 100644 .2119/verdicts/file-scoped-requirement-ids.4.3--c6ae11d6e00d.json create mode 100644 .2119/verdicts/file-scoped-requirement-ids.4.4--239fe11577aa.json diff --git a/.2119/verdicts/file-scoped-requirement-ids.3.1--86689f563d84.json b/.2119/verdicts/file-scoped-requirement-ids.3.1--86689f563d84.json new file mode 100644 index 0000000..578a506 --- /dev/null +++ b/.2119/verdicts/file-scoped-requirement-ids.3.1--86689f563d84.json @@ -0,0 +1,8 @@ +{ + "reviewId": "file-scoped-requirement-ids.3.1--86689f563d84", + "requirementId": "file-scoped-requirement-ids.3.1", + "hash": "86689f563d84", + "verdict": "pass", + "summary": "The live `check --json` run against the real corpus (with `reviews: true` in .2119.yml) rejects the nearest violations: if 0.7.0 re-keyed or orphaned any pre-adoption `REQ-NNN.x.y` verdict, the still-annotated requirement would surface as pending review (exit 1 / `ok` false) or as an entry in `uncoveredRequirements`, and a hash-scheme break would populate `staleReviews` — all asserted empty/zero at lines 146-154; the fixture's REQ-900.1.1 verdict plus `total 6 / covered 5 / uncovered []` confirms coexistence without weakening mandatory coverage since the only unannotated item is a MAY; the byte-for-byte diff test is explicitly migration-window scoped and its skip is legitimate; minor non-material gap: `legacy_verdict_ids` is only used as a count floor rather than asserting each legacy verdict's requirementId is individually reported satisfied (snapshot lacks `.2119/`, so the corpus itself could not be inspected).", + "timestamp": "2026-10-28T06:30:41.639Z" +} diff --git a/.2119/verdicts/file-scoped-requirement-ids.3.2--55b19cd3a9a3.json b/.2119/verdicts/file-scoped-requirement-ids.3.2--55b19cd3a9a3.json new file mode 100644 index 0000000..a848177 --- /dev/null +++ b/.2119/verdicts/file-scoped-requirement-ids.3.2--55b19cd3a9a3.json @@ -0,0 +1,8 @@ +{ + "reviewId": "file-scoped-requirement-ids.3.2--55b19cd3a9a3", + "requirementId": "file-scoped-requirement-ids.3.2", + "hash": "55b19cd3a9a3", + "verdict": "pass", + "summary": "Active test runs real rfc2119@0.7.0 check --json over the repository's pre-adoption REQ-*.json verdicts (asserted present) and requires exit 0, ok=true, staleReviews==[]; a gate that re-derived legacy IDs or re-hashed unchanged verdicts would orphan/stale those reviews and fail, while the fixture's review --dispatch (exit 1 listing unreviewed IDs) proves stale/pending detection is live so [] is not vacuous; the migration-scoped diff test honestly guarded that legacy verdicts were not regenerated during the window. Minor non-material gap: no review --dispatch run on the real repo, but staleReviews is the equivalent replacement-review observable.", + "timestamp": "2026-10-28T06:30:42.940Z" +} diff --git a/.2119/verdicts/file-scoped-requirement-ids.3.3--a778316bf0e6.json b/.2119/verdicts/file-scoped-requirement-ids.3.3--a778316bf0e6.json new file mode 100644 index 0000000..84660c0 --- /dev/null +++ b/.2119/verdicts/file-scoped-requirement-ids.3.3--a778316bf0e6.json @@ -0,0 +1,8 @@ +{ + "reviewId": "file-scoped-requirement-ids.3.3--a778316bf0e6", + "requirementId": "file-scoped-requirement-ids.3.3", + "hash": "a778316bf0e6", + "verdict": "pass", + "summary": "Unmocked rfc2119@0.7.0 run on a tmp fixture asserts the CLI emits the literal resolved IDs `- alpha-feature.1.1 (test-quality):` etc. and that check reports requirementCount 6 / coveredCount 5 / uncoveredRequirements [], so a resolver yielding `alpha-feature.md.1.1`, `alpha_feature.1.1`, bare `1.1`, or an off-by-one item/section number is rejected; a title-derived namespace is rejected by the repo-level check since specs like source-selection.md (H1 'Repository Source Selection') are annotated by stem; the MAY correction keeps the legacy MAY unannotated while still pinning every file-scoped MUST item as covered.", + "timestamp": "2026-10-28T06:30:44.207Z" +} diff --git a/.2119/verdicts/file-scoped-requirement-ids.3.4--4e686207f691.json b/.2119/verdicts/file-scoped-requirement-ids.3.4--4e686207f691.json new file mode 100644 index 0000000..7db4d70 --- /dev/null +++ b/.2119/verdicts/file-scoped-requirement-ids.3.4--4e686207f691.json @@ -0,0 +1,8 @@ +{ + "reviewId": "file-scoped-requirement-ids.3.4--4e686207f691", + "requirementId": "file-scoped-requirement-ids.3.4", + "hash": "4e686207f691", + "verdict": "pass", + "summary": "test_070_resolves_both_grammars_and_distinct_file_namespaces builds alpha-feature.md and beta-feature.md with identical local headings (### 1 item 1, ### 2 item 1) and runs the real pinned rfc2119@0.7.0 CLI (no mocks); the nearest violation — the resolver dropping the filename namespace so alpha-feature.1.1 and beta-feature.1.1 collapse to one ID — is rejected three independent ways: `cover` must print exactly '5 requirement(s) covered, 0 uncovered' (a collapse yields 3), `review --dispatch` must list both '- alpha-feature.1.1 (test-quality):' and '- beta-feature.1.1 (test-quality):' as separate pending reviews, and the final check must report requirementCount == 6 (a collapse yields 4); the revised 6/5/[] assertion also preserves mandatory coverage since uncoveredRequirements == [] rejects any dropped MUST annotation while the exact total rejects the CLI silently discarding the advisory MAY, and the legacy REQ-900 spec in the same run with ok=True and resolved verdicts for all five IDs exercises the coexistence contract (4.1–4.4) rather than just file-scoped parsing in isolation.", + "timestamp": "2026-10-28T06:30:45.459Z" +} diff --git a/.2119/verdicts/file-scoped-requirement-ids.4.1--7a14b7f2a87c.json b/.2119/verdicts/file-scoped-requirement-ids.4.1--7a14b7f2a87c.json new file mode 100644 index 0000000..073edf5 --- /dev/null +++ b/.2119/verdicts/file-scoped-requirement-ids.4.1--7a14b7f2a87c.json @@ -0,0 +1,8 @@ +{ + "reviewId": "file-scoped-requirement-ids.4.1--7a14b7f2a87c", + "requirementId": "file-scoped-requirement-ids.4.1", + "hash": "7a14b7f2a87c", + "verdict": "pass", + "summary": "test_070_resolves_both_grammars_and_distinct_file_namespaces runs a single `npx --yes rfc2119@0.7.0 check --json` over a fixture of two file-scoped specs (2 items each) plus one legacy REQ-900 spec (1 MUST + 1 MAY) and asserts requirementCount == 6 exactly, which rejects legacy-only discovery (would be 2), file-scoped-only discovery (would be 4), and MAY-dropping parsers (would be 5); the real-repo run additionally requires requirementCount >= legacy-verdict count + 35 (the file-scoped spec's own item count) with ok/staleReviews/uncoveredRequirements clean, so a gate that silently ignored either grammar fails. The correction to total 6 / covered 5 / uncovered [] correctly models an unannotated MAY (counted, not covered, not uncovered) without weakening mandatory coverage, and the dispatch listing of alpha-feature.1.1, beta-feature.1.1 and REQ-900.1.1 from one run preserves the distinct-namespace/coexistence contract; the only soft assertion (0 < coveredCount <= requirementCount) is auxiliary, not the discovery discriminator.", + "timestamp": "2026-10-28T06:30:46.705Z" +} diff --git a/.2119/verdicts/file-scoped-requirement-ids.4.2--484a886ba42f.json b/.2119/verdicts/file-scoped-requirement-ids.4.2--484a886ba42f.json new file mode 100644 index 0000000..f62120f --- /dev/null +++ b/.2119/verdicts/file-scoped-requirement-ids.4.2--484a886ba42f.json @@ -0,0 +1,8 @@ +{ + "reviewId": "file-scoped-requirement-ids.4.2--484a886ba42f", + "requirementId": "file-scoped-requirement-ids.4.2", + "hash": "484a886ba42f", + "verdict": "pass", + "summary": "test_070_resolves_both_grammars_and_distinct_file_namespaces runs a single pinned `rfc2119@0.7.0 check --json` on a fixture with a legacy `### REQ-900.1:` spec (1 MUST + 1 unannotated MAY) and two file-scoped specs, annotated via one full-ID comment line; a CLI that dropped legacy annotations would yield coveredCount 4 and uncoveredRequirements [REQ-900.1.1], and one that dropped file-scoped annotations would yield coveredCount 1 with four uncovered, so the asserted requirementCount==6 / coveredCount==5 / uncoveredRequirements==[] rejects both counterexamples while the MAY correction keeps the mandatory check intact; the real-repo single run additionally requires uncoveredRequirements==[] across ~1200 legacy full-ID annotations and the bare `# 2119-spec:` form used by this very file, so neither grammar's annotations can silently fail to resolve.", + "timestamp": "2026-10-28T06:30:47.914Z" +} diff --git a/.2119/verdicts/file-scoped-requirement-ids.4.3--c6ae11d6e00d.json b/.2119/verdicts/file-scoped-requirement-ids.4.3--c6ae11d6e00d.json new file mode 100644 index 0000000..4b5de57 --- /dev/null +++ b/.2119/verdicts/file-scoped-requirement-ids.4.3--c6ae11d6e00d.json @@ -0,0 +1,8 @@ +{ + "reviewId": "file-scoped-requirement-ids.4.3--c6ae11d6e00d", + "requirementId": "file-scoped-requirement-ids.4.3", + "hash": "c6ae11d6e00d", + "verdict": "pass", + "summary": "test_070_resolves_both_grammars_and_distinct_file_namespaces runs one `check --json` against the repo under `.2119.yml reviews: true` after asserting both REQ-*.json and file-scoped-requirement-ids.*.json verdict files exist, requiring ok=True and staleReviews=[]; a run that failed to resolve legacy (or file-scoped) verdicts would leave covered MUST items pending and fail there, and the fixture separately records `pass` for REQ-900.1.1 plus four file-scoped IDs and expects a single check with requirementCount 6 / coveredCount 5 / uncoveredRequirements [] — the corrected counts keep mandatory coverage strict since the only uncovered item is an unannotated MAY; minor non-material caveat that the tmp fixture lacks a reviews:true config so the real-repo run carries the verdict-resolution evidence.", + "timestamp": "2026-10-28T06:30:49.195Z" +} diff --git a/.2119/verdicts/file-scoped-requirement-ids.4.4--239fe11577aa.json b/.2119/verdicts/file-scoped-requirement-ids.4.4--239fe11577aa.json new file mode 100644 index 0000000..ef725e5 --- /dev/null +++ b/.2119/verdicts/file-scoped-requirement-ids.4.4--239fe11577aa.json @@ -0,0 +1,8 @@ +{ + "reviewId": "file-scoped-requirement-ids.4.4--239fe11577aa", + "requirementId": "file-scoped-requirement-ids.4.4", + "hash": "239fe11577aa", + "verdict": "pass", + "summary": "The tmp_path fixture in test_070_resolves_both_grammars_and_distinct_file_namespaces builds two differently named file-scoped specs (alpha-feature, beta-feature) that reuse identical local numbers (1.1 and 2.1) alongside a legacy REQ-900 spec with one MUST and one unannotated MAY, then drives the real pinned CLI (no mocks): a collapsed namespace (IDs derived from local numbers only, or cross-file duplicate detection) would be rejected because lint would not report '3 spec file(s) clean', `cover` would not report exactly '5 requirement(s) covered, 0 uncovered' (annotations alpha-feature.1.1/beta-feature.1.1 would be unresolvable or merged to 3 covered), `review --dispatch` would not list both '- alpha-feature.1.1 (test-quality):' and '- beta-feature.1.1 (test-quality):' as separate pending reviews, and the post-pass `check --json` would not yield requirementCount==6 / coveredCount==5 / uncoveredRequirements==[] / ok==True (a collision gives 4 total and either fewer distinct verdicts or pending reviews); the correction to total6/covered5 keeps mandatory coverage enforced via uncoveredRequirements==[] while counting the MAY only in the total, and the ROOT-level check still also exercises coexistence (legacy + file-scoped verdict globs, staleReviews==[]) against a live corpus where 15 file-scoped specs all reuse '### 1:'; note the supplied snapshot omits .2119/verdicts, .github/workflows, and AGENTS.md so those ROOT preconditions could not be re-verified here, but that does not weaken the self-contained 4.4 evidence.", + "timestamp": "2026-10-28T06:30:50.459Z" +} diff --git a/tests/test_2119_file_scoped_ids.py b/tests/test_2119_file_scoped_ids.py index f963e25..7b6911f 100644 --- a/tests/test_2119_file_scoped_ids.py +++ b/tests/test_2119_file_scoped_ids.py @@ -151,7 +151,9 @@ def test_070_resolves_both_grammars_and_distinct_file_namespaces(tmp_path: Path) assert report["ok"] is True assert report["staleReviews"] == [] assert report["requirementCount"] >= len(legacy_verdict_ids) + 35 - assert report["coveredCount"] == report["requirementCount"] + assert report["uncoveredRequirements"] == [] + # The total includes advisory MAY/SHOULD items, which need not have tests. + assert 0 < report["coveredCount"] <= report["requirementCount"] (tmp_path / "specs").mkdir() (tmp_path / "tests").mkdir() @@ -163,7 +165,7 @@ def test_070_resolves_both_grammars_and_distinct_file_namespaces(tmp_path: Path) ) (tmp_path / "specs" / "REQ-900-legacy.md").write_text( "# REQ-900: Legacy\n\n## Overview\n\nTest.\n\n## Requirements\n\n" - "### REQ-900.1: Behavior\n\n1. It MUST work.\n" + "### REQ-900.1: Behavior\n\n1. It MUST work.\n2. It MAY retry.\n" ) (tmp_path / "tests" / "coverage.py").write_text( "# 2119: alpha-feature.1.1, alpha-feature.2.1, " @@ -235,8 +237,9 @@ def test_070_resolves_both_grammars_and_distinct_file_namespaces(tmp_path: Path) assert mixed_check.returncode == 0, mixed_check.stdout + mixed_check.stderr mixed_report = json.loads(mixed_check.stdout) assert mixed_report["ok"] is True - assert mixed_report["requirementCount"] == 5 + assert mixed_report["requirementCount"] == 6 assert mixed_report["coveredCount"] == 5 + assert mixed_report["uncoveredRequirements"] == [] # 2119: 5.1