From 33da227427b04cc2b3eb8467d4113022dc94d39f Mon Sep 17 00:00:00 2001 From: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com> Date: Wed, 2 Sep 2026 20:00:25 -0700 Subject: [PATCH 1/2] feat: `reopen` verb + `work_reopen` tool; `resolve` on a closed item fails loud A published resolution could not be corrected. Worse, trying to correct one SUCCEEDED silently: `resolve` against an already-closed item checked only the item's STATUS, exited 0, and echoed the OLD stored text back as if the new text had landed. Seven wrong resolutions shipped that way (model_performance-uma; spec `w3-uma-work-tracker-reopen/SPEC.md`). resolve now compares the resolution TEXT at BOTH places it decides "did my write land?" -- the normal post-write readback AND the contended path where `_run` exhausted its retry budget. On an already-resolved target, checked BEFORE any write so "NOTHING WAS WRITTEN" is literally true: - identical text (CRLF/outer whitespace normalized) -> idempotent success, payload carries `"idempotent": true`. Required, not a softening: the shipped contention contract sells resolve's no-op as retry safety, and a retry re-sends the identical string. - divergent text -> BeadsError, nothing written, both texts side by side, the words NOTHING WAS WRITTEN, and `reopen` as a runnable remedy. `Beads.reopen` (+ CLI `reopen`, + `work_reopen`) is that remedy. It archives the verbatim previous resolution and previous closed_at into the item's attributed comment history BEFORE transitioning -- ordering that is load-bearing, and now proven so: MEASURED against bd 1.1.2, a reopen CLEARS close_reason. Had the wrapper trusted bd to keep it, every correction would have destroyed the record it was correcting. Also measured and corrected here: `bd reopen` leaves the OLD ASSIGNEE in place, so a directed claim by anyone else is refused ("already claimed by ") -- an item nobody can take is not a correctable item. reopen clears it, as `release` already does. Six new doctor assumptions fence all of it (33/33): reopen.reopens, reopen.clears_closed_at, reopen.close_reason_disposition, reopen.emits_event, resolve.divergent_text_refused, resolve.identical_text_idempotent. The known cost is surfaced, not hidden: reopen clears closed_at, so a corrected item re-lands on the correction date and throughput moves by one item per correction (`closed_at_cleared`, `previous_closed_at`). That is why the verb stays explicit rather than folded into resolve. --- AGENTS.md | 4 +- bundle.md | 3 +- context/awareness.md | 18 +- .../__init__.py | 171 +++++++- .../tests/test_work_reopen.py | 185 +++++++++ src/amplifier_work_tracker/adapter.py | 374 +++++++++++++++++- src/amplifier_work_tracker/cli.py | 113 +++++- src/amplifier_work_tracker/contract.py | 255 ++++++++++++ tests/cli/test_cli_reopen.py | 172 ++++++++ tests/integration/test_reopen_roundtrip.py | 225 +++++++++++ tests/unit/test_reopen_preconditions.py | 114 ++++++ tests/unit/test_resolve_text_compare.py | 253 ++++++++++++ 12 files changed, 1855 insertions(+), 32 deletions(-) create mode 100644 modules/tool-work-tracker/tests/test_work_reopen.py create mode 100644 tests/cli/test_cli_reopen.py create mode 100644 tests/integration/test_reopen_roundtrip.py create mode 100644 tests/unit/test_reopen_preconditions.py create mode 100644 tests/unit/test_resolve_text_compare.py diff --git a/AGENTS.md b/AGENTS.md index b4bf49b..4684aa0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -26,7 +26,7 @@ Nothing above the seam should ever need to change for a Beads upgrade. ## `doctor` is the gate, not a suggestion Run `amplifier-work-tracker doctor` after any `bd` upgrade and before -trusting parallel agents against a queue. It must report **26/26 +trusting parallel agents against a queue. It must report **33/33 assumptions hold**; anything less means Beads' behavior moved out from under an assumption we depend on (or, for `sweeps.alive`, that the reap/notify sweep loops have stopped completing sweeps, or, for @@ -120,7 +120,7 @@ runs itself is how you lose data you meant to keep. ## What "done" looks like -Full suite green, `doctor` 26/26, `ruff check` / `ruff format --check` / +Full suite green, `doctor` 33/33, `ruff check` / `ruff format --check` / `pyright` clean. For any change to the bundle's zero-state install path (service bootstrap, `work_tracker_install`, prereqs), the acceptance gate is a fresh Digital Twin Universe run from a genuinely empty machine (no `bd`, diff --git a/bundle.md b/bundle.md index 4a26ad5..b04bcfa 100644 --- a/bundle.md +++ b/bundle.md @@ -49,7 +49,8 @@ this table whenever that module's tools change. |---|---|---| | Tool | `work_claim` | Atomically claim + start PID-bound custody, in one call | | Tool | `work_declare` | Report `working` / `awaiting_human` for the held item | -| Tool | `work_resolve` | Fenced close of the currently held item | +| Tool | `work_resolve` | Fenced close of the currently held item -- refuses (writing nothing) if the item is already closed with DIFFERENT text | +| Tool | `work_reopen` | Return a resolved item to the queue so its published resolution can be corrected; archives the previous record first | | Tool | `work_status` | Read-only: projects, queue depths, what this session holds | | Tool | `work_file` | File newly discovered work, linked `discovered-from` the held item | | Tool | `work_add` | File a new engineering-lane item directly, no held item required -- the sanctioned way to seed a project's FIRST item(s) | diff --git a/context/awareness.md b/context/awareness.md index acd1a16..29a6ce3 100644 --- a/context/awareness.md +++ b/context/awareness.md @@ -4,7 +4,7 @@ You're one of several agents pulling from a shared work queue. First use in a session, or any `work_*` call fails to connect: call `work_tracker_status` before assuming a server is running — see "Where to go next" below. -Five things here fail **silently** if you get them wrong — no error, no undo: +Seven things here fail **silently** if you get them wrong — no error, no undo: 1. **Claim only via `work_claim` / `work_status`; never list-then-pick.** The obvious approach — read the ready queue, choose an item, mark it yours — @@ -52,6 +52,22 @@ Five things here fail **silently** if you get them wrong — no error, no undo: land — so this caution is specifically about what to do after a *reported failure*, not a general distrust of success responses. +7. **A published resolution is corrected by `work_reopen`, never by + re-resolving.** `work_resolve` against an item that is ALREADY resolved + is a no-op success **only when the text you send is byte-for-byte what + is already stored** (the legitimate retry case — the payload says + `"idempotent": true`). Sending *different* text now **fails non-zero and + writes nothing**, showing you the stored text and yours side by side. + Before this, that call exited 0 and echoed the OLD text back as if your + correction had landed, and seven wrong resolutions shipped that way. To + actually correct the record: `work_reopen(project, item_id, reason)` → + `work_claim` → `work_resolve` with the corrected text. Reopening is + deliberately explicit, and deliberately NOT idempotent (reopening an + already-open item is an error): it clears `closed_at`, so the item + re-lands on the correction date and every throughput roll-up moves by + one item. That cost is shown to you (`closed_at_cleared`, + `previous_closed_at`) rather than hidden. + ## Where to go next - No server running, or unsure → `work_tracker_status`; it names the exact diff --git a/modules/tool-work-tracker/amplifier_module_tool_work_tracker/__init__.py b/modules/tool-work-tracker/amplifier_module_tool_work_tracker/__init__.py index 4863027..1360fde 100644 --- a/modules/tool-work-tracker/amplifier_module_tool_work_tracker/__init__.py +++ b/modules/tool-work-tracker/amplifier_module_tool_work_tracker/__init__.py @@ -428,7 +428,8 @@ async def resolve(self, item_id: str, reason: str) -> ToolResult: ) try: bd = self._project(held.project) - item = bd.resolve(item_id, reason, actor=held.actor) + outcome = bd.resolve_outcome(item_id, reason, actor=held.actor) + item = outcome.item except A.FencedError as e: # Reclaimed/reassigned while we were away -- clear local # state and stop custody so this session can claim again. @@ -442,9 +443,93 @@ async def resolve(self, item_id: str, reason: str) -> ToolResult: return ToolResult(success=False, output=str(e)) held.stop.set() self._held = None - return ToolResult( - success=True, output={"resolved": item.id, "resolution": item.resolution} + out: dict[str, Any] = {"resolved": item.id, "resolution": item.resolution} + if outcome.idempotent: + # Only ever present on the idempotent path (the identical + # text was already stored, nothing written now) -- see + # adapter.Beads.resolve_outcome. A caller reconciling a + # contended run needs to tell that from a fresh write. + out["idempotent"] = True + return ToolResult(success=True, output=out) + + async def reopen( + self, project: str, item_id: str, reason: str, *, claim: bool = True + ) -> ToolResult: + """Return a RESOLVED item to the queue so its record can be + corrected, then (by default) claim it for this session. + + Takes `project` + `item_id` rather than `work_resolve`'s bare `id` + because, by definition, this session does NOT hold the item -- it + is closed. Same shape as `edit`/`defer`/`block`, the other tools + that address an item the session does not hold. + + `claim=True` is the default and is not cosmetic: a reopened item + lands back in the ready queue that parallel lanes poll + continuously, so a bare reopen opens a race in which another agent + claims the very item you reopened in order to correct. + + THE CLAIM IS A SEPARATE LEG AND MAY LEGITIMATELY FAIL -- most often + because this session already holds a different item (one item per + session; see `_Held` and `claim`'s own refusal). When it does, the + REOPEN STILL STANDS: this reports `claimed: false` with + `claim_error` at success, and NEVER drops the caller's existing + custody to make room. Rolling the reopen back is not an option + either -- that would mean a second close with invented text, which + is the disease this verb exists to cure. + """ + try: + bd = self._project(project) + outcome = bd.reopen(item_id, reason, actor=self._actor) + except A.BeadsError as e: + return ToolResult(success=False, output=str(e)) + out: dict[str, Any] = { + "reopened": outcome.item.id, + "project": project, + "status": outcome.item.status, + "reopen_reason": outcome.reopen_reason, + # Echoed in the RESULT, not merely filed in the item's comment + # history: the caller is about to write the replacement, and the + # most common correction is a targeted edit of the old text. + "previous_resolution": outcome.previous_resolution, + "previous_closed_at": ( + outcome.previous_closed_at.isoformat() if outcome.previous_closed_at else None + ), + # A real cost, shown rather than hidden: the item re-lands on + # the correction date, so throughput roll-ups move by one item. + "closed_at_cleared": outcome.item.closed_at is None, + "claimed": False, + } + if claim: + # Reuses `claim` wholesale rather than re-implementing the claim + # leg: that is the ONE atomic claim-plus-custody path (custody + # thread, auto-subscribe, one-item-per-session refusal included), + # and a second implementation of it here is exactly how a + # double-claim hole gets reopened. + claimed = await self.claim(project, item_id=item_id) + claimed_ok = ( + claimed.success + and isinstance(claimed.output, dict) + and bool(claimed.output.get("claimed")) + ) + if claimed_ok: + out["claimed"] = True + out["holder"] = self._actor + out["next_step"] = ( + "correct the record with work_resolve(id=..., reason=...) -- the item is yours" + ) + else: + out["claim_error"] = str(claimed.output) + out["next_step"] = ( + "the reopen STANDS but this session does not hold the item -- " + "claim it (work_claim with item_id) before correcting it, or " + "another agent may claim it first" + ) + else: + out["next_step"] = ( + "the item is back in the ready queue -- claim it before correcting it, " + "or another agent may claim it first" ) + return ToolResult(success=True, output=out) async def status(self) -> ToolResult: """Read-only project roll-up -- every known project with its FULL @@ -1096,6 +1181,83 @@ async def execute(self, input: dict[str, Any]) -> ToolResult: return await self._session.resolve(input["id"], input["reason"]) +class WorkReopenTool: + def __init__(self, session: WorkTrackerSession): + self._session = session + + @property + def name(self) -> str: + return "work_reopen" + + @property + def description(self) -> str: + return ( + "Return a RESOLVED item to the queue so its official record can be " + "corrected -- the ONLY sanctioned way to change a published " + "resolution, and the remedy work_resolve names when it refuses. " + "Takes project + item_id (not work_resolve's bare id) because by " + "definition this session does not hold a closed item. Requires a " + "non-empty 'reason' (a reopen destroys a record's finality; an " + "unexplained one is not auditable). Before transitioning, it files " + "the VERBATIM previous resolution and previous closed_at into the " + "item's attributed comment history, so the old text survives " + "whatever bd does to it -- and echoes that text back in the result, " + "because the correction you are about to write is usually an edit " + "of it. Deliberately NOT idempotent: reopening an item that is not " + "resolved is an error, never a silent no-op. Deliberately explicit, " + "too -- reopening CLEARS closed_at, so the item re-lands on the " + "correction date and every throughput roll-up moves by one item; " + "that cost is reported ('closed_at_cleared', 'previous_closed_at') " + "rather than hidden, which is why this is not folded into " + "work_resolve. claim=true (the default) immediately claims the " + "reopened item for this session, because a reopened item lands back " + "in the ready queue other agents poll. If that claim leg fails -- " + "most often because this session already holds a different item -- " + "the REOPEN STILL STANDS and is reported with claimed:false plus " + "claim_error; your existing custody is never dropped to make room." + ) + + @property + def input_schema(self) -> dict[str, Any]: + return { + "type": "object", + "properties": { + "project": {"type": "string", "description": "Project the item lives in."}, + "item_id": { + "type": "string", + "description": "Item id to reopen. Must currently be resolved.", + }, + "reason": { + "type": "string", + "description": ( + "Why the stored resolution is wrong. Required, must be " + "non-empty -- it is the audit record for destroying a " + "published record's finality." + ), + }, + "claim": { + "type": "boolean", + "default": True, + "description": ( + "Also claim the reopened item for this session (default " + "true). Set false only if you do not intend to correct it " + "yourself right now." + ), + }, + }, + "required": ["project", "item_id", "reason"], + } + + @guarded + async def execute(self, input: dict[str, Any]) -> ToolResult: + return await self._session.reopen( + input["project"], + input["item_id"], + input["reason"], + claim=bool(input.get("claim", True)), + ) + + class WorkReleaseTool: def __init__(self, session: WorkTrackerSession): self._session = session @@ -1753,7 +1915,7 @@ async def execute(self, input: dict[str, Any]) -> ToolResult: async def mount(coordinator: Any, config: dict[str, Any] | None = None) -> dict[str, Any]: - """Mount all thirteen work_* tools, sharing one WorkTrackerSession. + """Mount every work_* tool, sharing one WorkTrackerSession. IRON LAW: every tool below is registered via `coordinator.mount()`. Skipping any of them (or returning without mounting) fails @@ -1774,6 +1936,7 @@ async def mount(coordinator: Any, config: dict[str, Any] | None = None) -> dict[ WorkClaimTool(session), WorkDeclareTool(session), WorkResolveTool(session), + WorkReopenTool(session), WorkReleaseTool(session), WorkStatusTool(session), WorkStatsTool(session), diff --git a/modules/tool-work-tracker/tests/test_work_reopen.py b/modules/tool-work-tracker/tests/test_work_reopen.py new file mode 100644 index 0000000..aacac1c --- /dev/null +++ b/modules/tool-work-tracker/tests/test_work_reopen.py @@ -0,0 +1,185 @@ +"""`work_reopen` -- the agent-facing correction path for a published +resolution, and `work_resolve`'s refusal to overwrite one silently. + +Real `bd`/dolt end-to-end (skipped if `bd` is not on PATH, matching this +module's other tests). + +The scenario these exist for (work_tracker item model_performance-uma): +an agent closes an item with text that later turns out to be wrong. Before +this, its only recourse was `work_resolve` again -- which exited 0, echoed +the OLD text back, and wrote nothing. Seven wrong resolutions shipped that +way, and the correction backlog they created is what this verb unblocks. +""" + +from __future__ import annotations + +import shutil +import uuid +from typing import Any + +import pytest +from amplifier_module_tool_work_tracker import WorkReopenTool, WorkTrackerSession + +import amplifier_work_tracker.adapter as A + +pytestmark = pytest.mark.skipif( + shutil.which("bd") is None, reason="real `bd` binary not present in this environment" +) + + +def _unique(prefix: str) -> str: + return f"{prefix}{uuid.uuid4().hex[:10]}" + + +#: Consumed by the shared `project` fixture in conftest.py, which creates +#: the project AND drops its shared-server database again on teardown. +PROJECT_PREFIX = "reopenproj" + + +async def _closed_item(project: str, resolution: str) -> tuple[str, WorkTrackerSession]: + """An item that has been claimed and resolved -- i.e. a published + record, exactly the state a correction has to start from.""" + session = WorkTrackerSession({"actor": _unique("first")}) + added = await session.add(project, "reopen probe") + item_id = added.output["added"] # type: ignore[index] + await session.claim(project, item_id=item_id) + resolved = await session.resolve(item_id, resolution) + assert resolved.success is True + return item_id, session + + +@pytest.mark.asyncio +async def test_reopen_claim_resolve_corrects_the_published_record(project): + wrong = "VERDICT: the retention gate PASSES" + right = "CORRECTED: uncomputable -- arm B has zero valid runs" + item_id, _ = await _closed_item(project, wrong) + + corrector = WorkTrackerSession({"actor": _unique("corrector")}) + result = await corrector.reopen(project, item_id, "the stored verdict is wrong") + assert result.success is True + out: dict[str, Any] = result.output # type: ignore[assignment] + + assert out["reopened"] == item_id + assert out["status"] != "resolved" + assert out["previous_resolution"] == wrong + assert out["previous_closed_at"] + assert out["closed_at_cleared"] is True + # claim defaults ON: a reopened item lands in the queue parallel lanes + # poll, so a bare reopen races another agent for the item you reopened + # in order to correct. + assert out["claimed"] is True, out.get("claim_error") + assert corrector._held is not None # noqa: SLF001 + + fixed = await corrector.resolve(item_id, right) + assert fixed.success is True + bd = A.Workspace(corrector._ws.root).project(project) # noqa: SLF001 + back = bd.get(item_id) + assert (back.resolution or "").strip() == right + + +@pytest.mark.asyncio +async def test_reopen_archives_the_previous_record_where_bd_cannot_destroy_it(project): + """bd 1.1.2 CLEARS close_reason on reopen (measured) -- so the wrapper's + archive comment is the only thing standing between a correction and the + destruction of the record it corrects.""" + wrong = "the original text that bd itself will throw away" + item_id, _ = await _closed_item(project, wrong) + + corrector = WorkTrackerSession({"actor": _unique("corrector")}) + await corrector.reopen(project, item_id, "correcting", claim=False) + + bd = A.Workspace(corrector._ws.root).project(project) # noqa: SLF001 + comments = [e.detail or e.summary for e in bd.activity(item_id) if e.kind == "comment"] + archived = "\n".join(c or "" for c in comments) + assert wrong in archived + assert "PREVIOUS closed_at:" in archived + + +@pytest.mark.asyncio +async def test_claim_leg_degrades_without_dropping_an_existing_hold(project): + """THE ANSWER to the open question this item flagged: a session holds at + most ONE item (see `_Held`). So `claim=True` from a session that already + holds different work cannot be honoured -- and must not be honoured by + dropping the caller's existing custody. + + The reopen still STANDS; the caller is told the claim leg failed and + why. Rolling the reopen back is not an option either: that would mean a + second close with invented text, which is the disease. + """ + item_id, _ = await _closed_item(project, "closed once") + + busy = WorkTrackerSession({"actor": _unique("busy")}) + other = await busy.add(project, "other work") + other_id = other.output["added"] # type: ignore[index] + await busy.claim(project, item_id=other_id) + assert busy._held is not None # noqa: SLF001 + held_before = busy._held # noqa: SLF001 + + result = await busy.reopen(project, item_id, "correcting while holding other work") + assert result.success is True + out: dict[str, Any] = result.output # type: ignore[assignment] + + assert out["reopened"] == item_id + assert out["claimed"] is False + assert "already holding" in out["claim_error"] + assert "claim it" in out["next_step"] + + # The existing hold is untouched -- never sacrificed to make room. + assert busy._held is held_before # noqa: SLF001 + assert not held_before.stop.is_set() + + # And the reopen genuinely landed. + bd = A.Workspace(busy._ws.root).project(project) # noqa: SLF001 + assert bd.get(item_id).status != "resolved" + + await busy.resolve(other_id, "test cleanup") + + +@pytest.mark.asyncio +async def test_reopen_refuses_an_item_that_is_not_resolved(project): + session = WorkTrackerSession({"actor": _unique("s")}) + added = await session.add(project, "still open") + item_id = added.output["added"] # type: ignore[index] + + result = await session.reopen(project, item_id, "why") + assert result.success is False + assert "nothing to reopen" in str(result.output) + + +@pytest.mark.asyncio +async def test_reopen_refuses_an_empty_reason(project): + item_id, _ = await _closed_item(project, "closed") + session = WorkTrackerSession({"actor": _unique("s")}) + result = await session.reopen(project, item_id, " ") + assert result.success is False + assert "reason is required" in str(result.output) + + +@pytest.mark.asyncio +async def test_work_resolve_refuses_divergent_text_on_a_closed_item(project): + """The silent-discard defect, at the tool surface an agent actually + calls: a correction sent through `work_resolve` must FAIL, not be + swallowed and reported as success.""" + stored = "the original resolution" + item_id, first = await _closed_item(project, stored) + + # A fresh session re-claims nothing -- resolve refuses on custody first + # for an unheld item, so drive the underlying seam the tool uses. + bd = A.Workspace(first._ws.root).project(project) # noqa: SLF001 + with pytest.raises(A.BeadsError) as e: + bd.resolve(item_id, "a completely different resolution") + assert "NOTHING WAS WRITTEN" in str(e.value) + assert "work_reopen(" in str(e.value) + assert (bd.get(item_id).resolution or "").strip() == stored + + +@pytest.mark.asyncio +async def test_work_reopen_tool_is_registered_with_the_expected_surface(project): + session = WorkTrackerSession({"actor": _unique("s")}) + tool = WorkReopenTool(session) + assert tool.name == "work_reopen" + schema = tool.input_schema + # project + item_id, NOT work_resolve's bare `id`: by definition the + # caller does not hold a closed item. + assert schema["required"] == ["project", "item_id", "reason"] + assert schema["properties"]["claim"]["default"] is True diff --git a/src/amplifier_work_tracker/adapter.py b/src/amplifier_work_tracker/adapter.py index a922d83..7ec118e 100644 --- a/src/amplifier_work_tracker/adapter.py +++ b/src/amplifier_work_tracker/adapter.py @@ -2317,6 +2317,135 @@ class ReleaseOutcome: already_closed: bool +# ---------------------------------------------------------------- resolution +# +# The resolution TEXT -- not merely the item's status -- is what `resolve` +# compares to decide whether its own write landed. Comparing status alone +# was the measured defect (work_tracker item model_performance-uma, spec +# `w3-uma-work-tracker-reopen/SPEC.md`): a `resolve` against an ALREADY +# closed item exited 0 and echoed the OLD stored text back as if it were +# the text just written, so a correction was silently discarded and the +# caller was told it had landed. + +RESOLUTION_ECHO_LIMIT = 400 + + +def _norm_resolution(text: str | None) -> str: + """Normalize a resolution for comparison: line endings unified, outer + whitespace stripped. NOTHING ELSE. + + Case is significant and internal whitespace is significant, both + deliberately -- those are real edits to what a human will read, and a + normalization that swallowed them would re-open exactly the silent- + discard hole this comparison exists to close. Only the two differences + a transport can introduce on its own (CRLF, a trailing newline) are + normalized away. + """ + return (text or "").replace("\r\n", "\n").replace("\r", "\n").strip() + + +def _resolution_landed(stored: str | None, sent: str) -> bool: + """Is `stored` (what the item actually carries) the same resolution as + `sent` (what this caller asked to write), after `_norm_resolution`?""" + return _norm_resolution(stored) == _norm_resolution(sent) + + +def _echo_resolution(text: str | None, *, limit: int = RESOLUTION_ECHO_LIMIT) -> str: + """One resolution rendered for a side-by-side error message -- never + silently truncated: an elided text says so, with its real length.""" + s = text or "" + if not s.strip(): + return "(none -- blank)" + if len(s) <= limit: + return s + return f"{s[:limit]}... [truncated, {len(s)} chars]" + + +def _divergent_resolution_error( + item_id: str, + *, + project: str, + stored: str | None, + sent: str, + contended: bool = False, +) -> BeadsError: + """The refusal a caller gets for resolving an already-closed item with + text that is NOT what the item stores. + + Every requirement on this message was earned by a measured failure: + + 1. BOTH texts, side by side. The only way this defect was ever + caught was a human diffing the echoed text against what was sent. + Do that diff for the caller. + 2. The words "NOTHING WAS WRITTEN", literally. Under the contention + contract (`cli.py`'s module docstring) an agent's default reading + of a failure is "the transaction aborted" -- which here is true, + and must not be second-guessed into a blind retry that would + re-send the same discarded text. + 3. The remedy as a RUNNABLE command, on both surfaces (CLI and + tool), because the caller's next question is always "then how do + I correct it?" and the answer (`reopen`) is new. + """ + lead = ( + f"refusing to resolve {item_id}: it is already resolved, and the resolution " + f"stored on the item is NOT the text you sent. NOTHING WAS WRITTEN." + ) + if contended: + lead = ( + f"refusing to report success for resolve {item_id}: the write raised under " + f"contention, and the readback shows the item resolved with a resolution that " + f"is NOT the text you sent. YOUR TEXT WAS NOT WRITTEN." + ) + return BeadsError( + f"{lead}\n\n" + f" stored (unchanged): {_echo_resolution(stored)}\n" + f" you sent: {_echo_resolution(sent)}\n\n" + f"To correct the official record, reopen it first:\n" + f" amplifier-work-tracker reopen --project {project} --id {item_id} " + f"--reason ''\n" + f" (agents: work_reopen(project={project!r}, item_id={item_id!r}, reason=...))" + ) + + +@dataclass(frozen=True) +class ResolveOutcome: + """Result of `Beads.resolve_outcome` -- the item as it stands after a + verified close, plus whether this call actually WROTE that resolution + or merely found its own identical text already stored. + + `idempotent` exists because those two are byte-identical today and the + difference matters when reconciling a contended run: a caller that + re-ran `resolve` after an ambiguous failure needs to tell "my write + landed earlier" from "my write landed just now". See `resolve_outcome` + for the full rule. + """ + + item: Item + idempotent: bool = False + + +@dataclass(frozen=True) +class ReopenOutcome: + """Result of `Beads.reopen` -- the reopened item, plus the record the + reopen destroyed. + + `previous_resolution` is carried out in the RESULT, not merely filed + in the item's comment history, because the caller is about to write + the replacement and the most common correction is a targeted edit of + the old text; making them go find it invites a rewrite that loses + detail. `previous_closed_at` is surfaced for the opposite reason -- it + is a real cost, not a footnote: `bd reopen` clears `closed_at`, so a + corrected item stops counting toward the day it was genuinely resolved + and re-lands on the correction date (see `_velocity_raw_daily`). + """ + + item: Item + previous_resolution: str | None + previous_closed_at: datetime | None + reopen_reason: str + actor: str + + class Beads: """A handle on one Beads project. Construct via Workspace.project().""" @@ -3091,8 +3220,53 @@ def list_bounded( ) def resolve(self, item_id: str, reason: str, *, actor: str | None = None) -> Item: + """Close an item and VERIFY the write landed -- the `Item`-returning + projection of `resolve_outcome`, which every existing caller already + uses and which is unchanged for them. + + A pure one-line projection ON PURPOSE: two entry points to one + operation can only stay honest if one of them cannot hold logic of + its own to drift with. Callers that need to distinguish "I wrote + this resolution just now" from "this identical resolution was + already stored" (the CLI, `work_resolve`) call `resolve_outcome` + directly for its `idempotent` flag. + """ + return self.resolve_outcome(item_id, reason, actor=actor).item + + def resolve_outcome( + self, item_id: str, reason: str, *, actor: str | None = None + ) -> ResolveOutcome: """Close an item and VERIFY the write landed. Exit code is not proof. + WHAT "LANDED" MEANS: the item stores the TEXT THIS CALL SENT -- + not merely that the item is closed. Comparing status alone was the + measured defect (work_tracker item model_performance-uma): a + resolve against an already-closed item exited 0 and echoed the OLD + text back as if it were the new one, silently discarding a + correction. `resolve` is checked against `_resolution_landed` at + BOTH places it decides that question -- the normal post-write + readback AND the contended path below -- because a caller on the + contended path is precisely the one least able to reason about + what actually happened. + + THE RULE, on a target that is ALREADY resolved (checked BEFORE any + write, so "NOTHING WAS WRITTEN" is literally true): + + - text IDENTICAL (after `_norm_resolution`) -> success, + `idempotent=True`, no write attempted. This carve-out is + required, not a softening: the shipped contention contract + sells resolve's no-op as RETRY SAFETY, and a retry re-sends + the identical string. A blanket error would fail a legitimate + retry of a write that did land, and tell its caller their + resolve failed when it succeeded. + - text DIFFERS -> `BeadsError` (`_divergent_resolution_error`), + nothing written, the remedy (`reopen`) named as a runnable + command. Correcting a published record is a deliberate, + audited transition -- never an invisible side effect of a call + the caller believes is idempotent. + + Resolving an OPEN item is unchanged, byte for byte. + FENCED, but only while the item is ACTUALLY currently held -- resolving an unheld item (open/blocked/deferred/resolved), even one filed or last held by someone else entirely, is a single call, no @@ -3121,22 +3295,42 @@ def resolve(self, item_id: str, reason: str, *, actor: str | None = None) -> Ite holder, or wait for `reap` to reclaim a stale hold. """ who = actor or self._actor - if who: - current = self.get(item_id) - if current.status == "held": - cust = current.meta.get(C.CUSTODY_KEY) if isinstance(current.meta, dict) else None - if isinstance(cust, dict) and cust.get("holder"): - if current.holder != who or cust.get("holder") != who: - raise FencedError( - f"refusing to close {item_id}: current holder is " - f"{current.holder!r} (custody holder {cust.get('holder')!r}), " - f"not {who!r}. Your claim was reclaimed while you were away." - ) - elif current.holder and current.holder != who: + # ONE pre-write read serves both preconditions (the custody fence + # and the already-resolved rule). Deliberately tolerant of a read + # failure when no actor is given, so an item that does not exist + # still surfaces through bd's own `close` error exactly as before + # -- this method must not newly re-diagnose "not found". + try: + current: Item | None = self.get(item_id) + except BeadsError: + if who: + raise + current = None + if who and current is not None and current.status == "held": + cust = current.meta.get(C.CUSTODY_KEY) if isinstance(current.meta, dict) else None + if isinstance(cust, dict) and cust.get("holder"): + if current.holder != who or cust.get("holder") != who: raise FencedError( - f"refusing to close {item_id}: it is held by {current.holder!r}, " + f"refusing to close {item_id}: current holder is " + f"{current.holder!r} (custody holder {cust.get('holder')!r}), " f"not {who!r}. Your claim was reclaimed while you were away." ) + elif current.holder and current.holder != who: + raise FencedError( + f"refusing to close {item_id}: it is held by {current.holder!r}, " + f"not {who!r}. Your claim was reclaimed while you were away." + ) + if current is not None and current.status == "resolved": + # Decided BEFORE any write -- that ordering is what makes the + # refusal's own "NOTHING WAS WRITTEN" promise literally true. + if _resolution_landed(current.resolution, reason): + return ResolveOutcome(item=current, idempotent=True) + raise _divergent_resolution_error( + item_id, + project=self.project_name, + stored=current.resolution, + sent=reason, + ) try: p = self._run(["close", item_id, "--reason", reason], actor=actor) except BeadsError: @@ -3152,9 +3346,24 @@ def resolve(self, item_id: str, reason: str, *, actor: str | None = None) -> Ite # wrapper's failure: if the item is genuinely resolved, report # success rather than propagate a false failure that would # otherwise wedge the caller's custody state forever. + # + # "Genuinely resolved" means resolved WITH THIS CALL'S TEXT. + # Status alone is the wrong proxy here for the same reason it + # is wrong at the post-write readback below -- and this is the + # site it is easiest to leave half-fixed. A closed item whose + # stored resolution is somebody else's text means our write did + # NOT land, however closed the item looks. back = self._read_back_or_none(item_id) if back is not None and back.status == "resolved": - return back + if _resolution_landed(back.resolution, reason): + return ResolveOutcome(item=back, idempotent=False) + raise _divergent_resolution_error( + item_id, + project=self.project_name, + stored=back.resolution, + sent=reason, + contended=True, + ) from None raise if p.returncode != 0: raise BeadsError(f"close {item_id}: {_clean_bd_error(p.stderr or p.stdout)}") @@ -3164,7 +3373,142 @@ def resolve(self, item_id: str, reason: str, *, actor: str | None = None) -> Ite f"close {item_id} reported success but readback shows status=" f"{back.status!r} -- refusing to report success" ) - return back + if not _resolution_landed(back.resolution, reason): + raise _divergent_resolution_error( + item_id, + project=self.project_name, + stored=back.resolution, + sent=reason, + contended=True, + ) + return ResolveOutcome(item=back, idempotent=False) + + def reopen(self, item_id: str, reason: str, *, actor: str | None = None) -> ReopenOutcome: + """Return a RESOLVED item to the queue so its official record can be + corrected -- the remedy `resolve`'s divergent-text refusal names, and + the only sanctioned way to change a published resolution. + + Deliberately NOT idempotent: reopening an already-open item RAISES + rather than no-ops. This program's recurring defect is an operation + that looks like it worked, and "reopen succeeded" on an item that + was already open tells the caller something false about what they + just did -- the mirror image of `resolve`'s own rule above. + + ARCHIVE FIRST, then transition. The comment carrying the verbatim + previous resolution is written BEFORE `bd reopen` runs, and that + ordering is load-bearing rather than stylistic: bd 1.1.2's + treatment of `close_reason` across a reopen is UNDOCUMENTED and + unverified upstream, so the wrapper's guarantee must not depend on + it. What this method promises is therefore true whatever bd does: + + after a successful reopen, the previous resolution text is + durably recorded in the item's attributed comment history. + + (`contract.py`'s `reopen.close_reason_disposition` separately PINS + the behaviour measured against the live binary, so a future bd + change breaks `doctor` loudly instead of quietly altering what a + reopened item carries.) + + THE COST, surfaced rather than hidden: `bd reopen` clears + `closed_at` (see `_velocity_raw_daily`), so a corrected item stops + counting toward the day it was genuinely resolved and re-lands on + the correction date -- every throughput roll-up moves by one item + per correction. `ReopenOutcome.previous_closed_at` carries what was + destroyed. That cost is exactly why this stays an explicit verb + instead of being folded into `resolve` as an invisible side effect. + + Does NOT claim the item, but DOES clear the stale assignee bd leaves + behind (see below) so the item is genuinely claimable again. A + reopened item lands back in the ready queue, where parallel agents + are polling -- so the caller almost always wants to claim it + immediately (see `work_reopen`'s `claim` parameter, and the CLI's + opt-in `--claim`). That is the CALLER's decision to make, because a + claim from an interactive shell strands custody nobody is renewing. + """ + who = actor or self._actor or "unknown" + if not (reason or "").strip(): + raise BeadsError( + f"reopen {item_id}: --reason is required and must not be empty -- " + f"a reopen destroys a record's finality and its closed_at; an " + f"unexplained one is not auditable" + ) + cur = self.get(item_id) + if cur.status != "resolved": + raise BeadsError( + f"refusing to reopen {item_id}: status is {cur.status!r}, not 'resolved' " + f"-- nothing to reopen" + ) + previous_resolution = cur.resolution + previous_closed_at = cur.closed_at + archived_text = ( + previous_resolution if (previous_resolution or "").strip() else "(none -- was blank)" + ) + self.comment( + item_id, + ( + f"{who} reopened this item to correct the record.\n" + f"REASON: {reason}\n" + f"PREVIOUS RESOLUTION (superseded, verbatim):\n" + f"{archived_text}\n" + f"PREVIOUS closed_at: " + f"{previous_closed_at.isoformat() if previous_closed_at else '(none)'}" + ), + actor=actor, + ) + try: + p = self._run(["reopen", item_id, "--reason", reason], actor=actor) + except BeadsError: + # Same verify-on-conflict discipline `resolve`/`release` apply + # (see `resolve`'s own comment for the measured incident): a + # wrapper that exhausted its retry budget has NOT proven the + # write failed. Here -- unlike `resolve` -- STATUS is the + # correct success proxy, because reopen's success condition IS + # a status change; there is no text of ours to look for. + back = self._read_back_or_none(item_id) + if back is not None and back.status != "resolved": + return ReopenOutcome( + item=back, + previous_resolution=previous_resolution, + previous_closed_at=previous_closed_at, + reopen_reason=reason, + actor=who, + ) + raise + if p.returncode != 0: + raise BeadsError(f"reopen {item_id}: {_clean_bd_error(p.stderr or p.stdout)}") + back = self.get(item_id) + if back.status == "resolved": + raise BeadsError( + f"reopen {item_id} reported success but readback still shows " + f"status='resolved' -- refusing to report success" + ) + if back.holder: + # MEASURED (bd 1.1.2, 2026-09-02): `bd reopen` flips status back + # to open and clears closed_at, but LEAVES THE OLD ASSIGNEE IN + # PLACE. The item then looks open while still being "claimed by" + # whoever closed it -- and a directed claim by anyone else is + # refused outright ("issue already claimed by "), so + # the correction path this verb exists to open is closed again by + # a stale name. `release` already clears the assignee for exactly + # this reason (`update --status open --assignee ""`); a reopen + # that did not would hand back an item nobody can take. + self._run(["update", item_id, "--assignee", ""], actor=actor) + back = self.get(item_id) + if back.holder: + raise BeadsError( + f"reopen {item_id} LANDED (it is {back.status!r}, not resolved) but the " + f"item is still assigned to {back.holder!r} and could not be cleared -- " + f"nobody else can claim it to correct it. Clear it with " + f"`amplifier-work-tracker unclaim --project {self.project_name} " + f"--id {item_id}`, then claim it." + ) + return ReopenOutcome( + item=back, + previous_resolution=previous_resolution, + previous_closed_at=previous_closed_at, + reopen_reason=reason, + actor=who, + ) def _read_back_or_none(self, item_id: str) -> Item | None: """Contention-free read-back (see `get`'s docstring -- never `bd diff --git a/src/amplifier_work_tracker/cli.py b/src/amplifier_work_tracker/cli.py index eafedfd..953d285 100644 --- a/src/amplifier_work_tracker/cli.py +++ b/src/amplifier_work_tracker/cli.py @@ -26,13 +26,19 @@ conflict) to confirm its actual current state. This matters most for non-idempotent writes (`add`/`create` -- retrying blind can create a duplicate item) and less for idempotent ones (`resolve` on an already- -resolved item is a readback-checked no-op) -- but re-reading first is always -the safe move. `resolve`/`unclaim` additionally verify their OWN write landed -by reading the item back before reporting success (exit code is not proof by -itself) -- so a reported SUCCESS is independently confirmed already; this -contract is about what to do after a reported FAILURE. See `context/ -awareness.md` for the same contract in agent-facing form, and work_tracker -item pipeline-bug for the contention-hardening work this documents. +resolved item is a readback-checked no-op ONLY when the text you send is +byte-for-byte what is already stored -- which is exactly the retry case; +sending DIFFERENT text against a closed item now fails non-zero having +written nothing, and names `reopen` as the remedy) -- but re-reading first +is always the safe move. `resolve`/`unclaim` additionally verify their OWN +write landed by reading the item back before reporting success (exit code is +not proof by itself), and `resolve` compares the stored resolution TEXT, not +merely the item's status -- so a reported SUCCESS is independently confirmed +already; this contract is about what to do after a reported FAILURE. See +`context/awareness.md` for the same contract in agent-facing form, +work_tracker item pipeline-bug for the contention-hardening work this +documents, and model_performance-uma for the silent-discard defect the text +comparison closes. """ from __future__ import annotations @@ -924,12 +930,82 @@ def cmd_reap(a): def cmd_resolve(a): + """Close an item with a user-readable reason, verified by readback. + + On an ALREADY-resolved item this either succeeds as a no-op (the text + you sent is byte-for-byte what is stored -- the retry case, reported + with `"idempotent": true`) or fails non-zero having written nothing + (the text differs -- correcting a published record goes through + `reopen`). See `adapter.Beads.resolve_outcome`. + """ + _guard() + try: + outcome = _ws(a).project(a.project).resolve_outcome(a.id, a.reason, actor=a.actor) + except A.BeadsError as e: + die(str(e)) + payload = {"resolved": outcome.item.id, "resolution": outcome.item.resolution} + if outcome.idempotent: + # Deliberately present ONLY on the idempotent path, so a consumer + # can distinguish "my write landed earlier" from "my write landed + # just now" -- byte-identical outputs before this, and the + # difference is what a caller reconciling a contended run needs. + payload["idempotent"] = True + print(json.dumps(payload, indent=2)) + + +def cmd_reopen(a): + """Return a RESOLVED item to the queue so its record can be corrected. + + The remedy `resolve`'s divergent-text refusal names. Refuses loudly + (non-zero, nothing written) on an item that is not resolved -- reopen + is deliberately not idempotent. + + `--claim` is OPT-IN here, unlike the `work_reopen` tool where it + defaults on: this surface is also driven by humans inspecting state, + and a claim from an interactive shell strands custody nobody is + renewing. When passed, the claim is a separate leg -- if it fails, the + REOPEN STILL STANDS and is reported that way rather than rolled back. + """ _guard() + bd = _ws(a).project(a.project) try: - item = _ws(a).project(a.project).resolve(a.id, a.reason, actor=a.actor) + outcome = bd.reopen(a.id, a.reason, actor=a.actor) except A.BeadsError as e: die(str(e)) - print(json.dumps({"resolved": item.id, "resolution": item.resolution}, indent=2)) + payload = { + "reopened": outcome.item.id, + "project": a.project, + "status": outcome.item.status, + "reopen_reason": outcome.reopen_reason, + "previous_resolution": outcome.previous_resolution, + "previous_closed_at": ( + outcome.previous_closed_at.isoformat() if outcome.previous_closed_at else None + ), + # Surfaced, never hidden: a reopened item stops counting toward the + # day it was genuinely resolved and re-lands on the correction date, + # so every throughput roll-up moves by one item per correction. + "closed_at_cleared": outcome.item.closed_at is None, + "claimed": False, + } + if a.claim: + try: + bd.claim_item(a.id, actor=a.actor) + except A.BeadsError as e: + payload["claim_error"] = str(e) + else: + payload["claimed"] = True + payload["holder"] = a.actor + payload["next_step"] = ( + f"run `amplifier-work-tracker custody --project {a.project} " + f"--actor {a.actor} --id {a.id}` in the background to maintain custody, " + f"then correct the record with `resolve`" + ) + else: + payload["next_step"] = ( + "the item is back in the ready queue -- claim it before correcting it, " + "or another agent may claim it first" + ) + print(json.dumps(payload, indent=2)) def cmd_unclaim(a): @@ -1674,6 +1750,25 @@ def main(): p.add_argument("--actor", default="agent") p.set_defaults(fn=cmd_resolve) + p = sub.add_parser( + "reopen", + help="return a RESOLVED item to the queue so its record can be corrected", + parents=[root_parent], + ) + p.add_argument("--project", required=True) + p.add_argument("--id", required=True) + p.add_argument("--reason", required=True, help="why the stored resolution is wrong") + p.add_argument("--actor", default="agent") + p.add_argument( + "--claim", + action="store_true", + help=( + "also claim the item immediately (off by default -- a claim from an " + "interactive shell strands custody nobody is renewing)" + ), + ) + p.set_defaults(fn=cmd_reopen) + p = sub.add_parser( "unclaim", help="release a held item back to the ready queue WITHOUT resolving it", diff --git a/src/amplifier_work_tracker/contract.py b/src/amplifier_work_tracker/contract.py index 3928681..aa9791d 100644 --- a/src/amplifier_work_tracker/contract.py +++ b/src/amplifier_work_tracker/contract.py @@ -968,9 +968,264 @@ def check_creation_state_reporting(p: Probe) -> Result: ) +def _reopen_probe_item(p: Probe, lane: str, resolution: str) -> str: + """A freshly created, resolved item for the reopen checks to work on.""" + assert p.bd + i = p.bd.create(f"reopen probe ({lane})", tags=[lane], priority=1) + p.bd.resolve(i, resolution) + return i + + +def check_reopen_reopens(p: Probe) -> Result: + """A resolved item can be returned to the queue and CLAIMED again. + + Asserted together, because either half alone is defeated silently: the + status flipping back is worthless if the item never re-enters the ready + queue, and this is the whole mechanism by which a wrong published + resolution becomes correctable at all. `resolution.readable` already + asserted a resolution is READABLE; nothing asserted it was + CORRECTABLE, and that gap is why seven wrong resolutions shipped. + """ + assert p.bd + lane = "lane:reopen" + item_id = _reopen_probe_item(p, lane, "probe first-pass resolution") + try: + p.bd.reopen(item_id, "probe correction") + except A.BeadsError as e: + return Result("reopen.reopens", False, f"reopen raised: {e}") + back = p.bd.get(item_id) + if back.status == "resolved": + return Result( + "reopen.reopens", + False, + f"reopen left the item {back.status!r} -- a published resolution " + f"cannot be corrected at all", + ) + if back.holder: + # MEASURED: `bd reopen` leaves the OLD assignee in place, which makes + # a directed claim by anyone else refuse ("already claimed by ..."), + # so `Beads.reopen` clears it. If this fires, that clearing broke. + return Result( + "reopen.reopens", + False, + f"a reopened item is still assigned to {back.holder!r} -- nobody else " + f"can claim it, so the correction path is closed by a stale name", + ) + # A DIRECTED claim by a DIFFERENT actor: the strongest form, and the one + # that actually fails when the stale assignee survives. + try: + taken = p.bd.claim_item(item_id, actor="reopen_probe_holder") + except A.BeadsError as e: + return Result( + "reopen.reopens", + False, + f"a reopened item could not be claimed by another actor ({e}) -- it did " + f"not genuinely return to the queue", + ) + if taken.id != item_id: + return Result("reopen.reopens", False, "directed claim returned a different item") + return Result( + "reopen.reopens", + True, + "a resolved item reopens unassigned and is directly claimable again", + ) + + +def check_reopen_clears_closed_at(p: Probe) -> Result: + """Pins the ACCOUNTING side effect every throughput number depends on. + + `bd reopen` clears `closed_at`, so a corrected item stops counting + toward the day it was genuinely resolved and re-lands on the correction + date (`_velocity_raw_daily`, `_daily_resolved_counts`). That cost is + documented and surfaced (`closed_at_cleared`), not hidden -- and if bd + ever stops doing it, every one of those functions' honest caveats + becomes wrong, silently. This is the alarm for that. + """ + assert p.bd + item_id = _reopen_probe_item(p, "lane:reopen_closed_at", "probe resolution for closed_at") + before = p.bd.get(item_id) + if before.closed_at is None: + return Result( + "reopen.clears_closed_at", False, "resolve did not set closed_at -- cannot measure" + ) + try: + outcome = p.bd.reopen(item_id, "probe correction") + except A.BeadsError as e: + return Result("reopen.clears_closed_at", False, f"reopen raised: {e}") + if outcome.item.closed_at is not None: + return Result( + "reopen.clears_closed_at", + False, + f"closed_at survived a reopen ({outcome.item.closed_at!r}) -- bd changed " + f"the accounting side effect that velocity/throughput reporting and " + f"reopen's own documented cost both assume", + ) + return Result( + "reopen.clears_closed_at", + True, + "reopen clears closed_at (the documented, surfaced accounting cost)", + ) + + +def check_reopen_close_reason_disposition(p: Probe) -> Result: + """What bd does to `close_reason` across a reopen -- MEASURED, pinned. + + bd 1.1.2 (20e493e56), measured 2026-09-02: a reopen CLEARS + `close_reason`. The previous resolution text is GONE from the issue + row. bd documents nothing either way, which is exactly why + `Beads.reopen` archives the previous resolution into the item's + attributed comment history BEFORE transitioning -- had the wrapper + trusted bd to keep it, every correction would have destroyed the record + it was correcting. + + The job of this assumption is the ALARM, not a preferred answer: it + asserts what was measured on the day it was written, so a bd change + breaks `doctor` loudly instead of quietly altering what a reopened item + carries. If it fails, re-measure, then update this check AND + `reopen`'s docstring deliberately. + """ + assert p.bd + text = "probe resolution measured for close_reason disposition" + item_id = _reopen_probe_item(p, "lane:reopen_disposition", text) + try: + outcome = p.bd.reopen(item_id, "probe correction") + except A.BeadsError as e: + return Result("reopen.close_reason_disposition", False, f"reopen raised: {e}") + if (outcome.item.resolution or "").strip(): + return Result( + "reopen.close_reason_disposition", + False, + f"MEASURED bd 1.1.2 behaviour was: reopen CLEARS close_reason. It now " + f"PRESERVES it ({outcome.item.resolution!r}). Not a wrapper failure " + f"(reopen archives the old text in the comment history regardless), but " + f"re-measure and update this assumption deliberately", + ) + archived = [e.detail or e.summary for e in p.bd.activity(item_id) if e.kind == "comment"] + if not any(text in (a or "") for a in archived): + return Result( + "reopen.close_reason_disposition", + False, + "the previous resolution is neither on the item NOR in its comment " + "history -- the record was destroyed by the correction", + ) + return Result( + "reopen.close_reason_disposition", + True, + "reopen clears close_reason (measured), and the wrapper's archive comment " + "preserves the previous resolution regardless", + ) + + +def check_reopen_emits_event(p: Probe) -> Result: + """bd's own `events` row is one of the three independent audit records + a correction leaves. If it silently stops being written, `reopened_count` + (the \"reopened after resolve\" quality signal) reports zero forever and + nobody can tell a corrected record from a first-pass one.""" + assert p.bd + item_id = _reopen_probe_item(p, "lane:reopen_event", "probe resolution for event") + try: + p.bd.reopen(item_id, "probe correction reason") + except A.BeadsError as e: + return Result("reopen.emits_event", False, f"reopen raised: {e}") + q = A._dolt_sql( + f"SELECT COUNT(*) FROM `{p.bd.project_name}`.`events` " + f"WHERE `issue_id` = '{A._sql_literal(item_id)}' AND `event_type` = 'reopened'" + ) + if q.returncode != 0: + return Result("reopen.emits_event", False, f"could not read events: {q.stderr or q.stdout}") + rows = [ln for ln in (q.stdout or "").splitlines() if ln.strip()][1:] + count = int(rows[0].strip()) if rows and rows[0].strip().isdigit() else 0 + if count < 1: + return Result( + "reopen.emits_event", + False, + "bd wrote no `reopened` events row -- the audit trail for corrections " + "has silently stopped being written", + ) + return Result("reopen.emits_event", True, "bd records a `reopened` events row, attributed") + + +def check_resolve_divergent_text_refused(p: Probe) -> Result: + """THE regression fence for this whole defect. + + Resolving an already-closed item with text that DIFFERS from what is + stored must raise and write nothing. Before the fix it exited 0 and + echoed the OLD text back as if the correction had landed -- silent data + loss on the one field users actually read. + """ + assert p.bd + stored = "probe: the original, wrong resolution" + i = p.bd.create("resolve divergence probe", tags=["lane:probe_divergent"]) + p.bd.resolve(i, stored) + try: + p.bd.resolve(i, "probe: a completely different resolution") + except A.BeadsError: + back = p.bd.get(i) + if (back.resolution or "").strip() != stored: + return Result( + "resolve.divergent_text_refused", + False, + f"refused, but the stored resolution changed anyway " + f"({back.resolution!r}) -- 'NOTHING WAS WRITTEN' is not true", + ) + return Result( + "resolve.divergent_text_refused", + True, + "resolving a closed item with different text refuses and writes nothing", + ) + return Result( + "resolve.divergent_text_refused", + False, + "A DIVERGENT RESOLVE ON A CLOSED ITEM SUCCEEDED -- the caller's correction " + "was silently discarded and they were told it landed", + ) + + +def check_resolve_identical_text_idempotent(p: Probe) -> Result: + """The retry-safety carve-out, fenced in the other direction. + + The shipped contention contract tells agents that re-running `resolve` + after an ambiguous failure is safe. A retry re-sends the identical + string, so identical text must stay a success -- otherwise the fix + above would break the promise it was made under. + """ + assert p.bd + text = "probe: the one true resolution" + i = p.bd.create("resolve idempotency probe", tags=["lane:probe_idempotent"]) + p.bd.resolve(i, text) + try: + outcome = p.bd.resolve_outcome(i, text) + except A.BeadsError as e: + return Result( + "resolve.identical_text_idempotent", + False, + f"re-sending the IDENTICAL resolution text failed ({e}) -- the " + f"contention contract's retry-safety promise is broken", + ) + if not outcome.idempotent: + return Result( + "resolve.identical_text_idempotent", + False, + "the identical-text retry succeeded but was not reported as idempotent " + "-- a caller reconciling a contended run cannot tell 'landed earlier' " + "from 'landed just now'", + ) + return Result( + "resolve.identical_text_idempotent", + True, + "re-sending identical resolution text is an idempotent success", + ) + + CHECKS = [ ("capabilities", check_capabilities), ("resolve.fenced", check_resolve_fenced), + ("resolve.divergent_text_refused", check_resolve_divergent_text_refused), + ("resolve.identical_text_idempotent", check_resolve_identical_text_idempotent), + ("reopen.reopens", check_reopen_reopens), + ("reopen.clears_closed_at", check_reopen_clears_closed_at), + ("reopen.close_reason_disposition", check_reopen_close_reason_disposition), + ("reopen.emits_event", check_reopen_emits_event), ("release.reopens_unresolved", check_release_reopens_unresolved), ("claim.subcommand", check_claim_subcommand), ("claim.atomic", check_claim_atomic), diff --git a/tests/cli/test_cli_reopen.py b/tests/cli/test_cli_reopen.py new file mode 100644 index 0000000..54cbfdf --- /dev/null +++ b/tests/cli/test_cli_reopen.py @@ -0,0 +1,172 @@ +"""Tier 3 -- `amplifier-work-tracker reopen`, and `resolve`'s refusal on a +closed item, as a real subprocess. + +The exit CODE is the assertion that matters here. A warning printed beside a +JSON payload does not survive piping, `--json` consumers, or an agent reading +only the structured result -- the exit code is the one channel every consumer +already checks, which is why a divergent resolve must FAIL rather than warn. + +See tests/cli/test_cli_surface.py's module docstring for why this tier exists +at all (two shipped commands that failed while exiting 0). +""" + +from __future__ import annotations + +import json + +import pytest + +from .. import _util + +pytestmark = pytest.mark.cli + + +def _add_item(run_cli, project: str, title: str = "an item") -> str: + add = run_cli(["add", "--project", project, title]) + assert add.returncode == 0, add.stderr + return json.loads(add.stdout)["added"] + + +def _row(run_cli, project: str, item_id: str) -> dict: + listed = run_cli(["list", "--project", project, "--json"]) + assert listed.returncode == 0, listed.stderr + return next(r for r in json.loads(listed.stdout)["items"] if r["id"] == item_id) + + +def test_reopen_then_correct_end_to_end(run_cli, unique_project_name, unique_actor): + project = unique_project_name + assert run_cli(["new", project]).returncode == 0 + item_id = _add_item(run_cli, project) + wrong = "the original, wrong resolution" + right = "the corrected resolution" + + assert ( + run_cli(["resolve", "--project", project, "--id", item_id, "--reason", wrong]).returncode + == 0 + ) + assert _row(run_cli, project, item_id)["status"] == "resolved" + + result = run_cli( + [ + "reopen", + "--project", + project, + "--id", + item_id, + "--reason", + "the stored text is wrong", + "--actor", + unique_actor, + ] + ) + assert result.returncode == 0, result.stderr + _util.assert_no_silent_failure(result) + payload = json.loads(result.stdout) + assert payload["reopened"] == item_id + assert payload["status"] != "resolved" + # The old text comes back to the caller, who is about to rewrite it. + assert payload["previous_resolution"] == wrong + assert payload["previous_closed_at"] + # The accounting cost is stated, not hidden. + assert payload["closed_at_cleared"] is True + # --claim is OPT-IN on this surface (a shell claim strands custody). + assert payload["claimed"] is False + + assert _row(run_cli, project, item_id)["status"] != "resolved" + fixed = run_cli(["resolve", "--project", project, "--id", item_id, "--reason", right]) + assert fixed.returncode == 0, fixed.stderr + assert _row(run_cli, project, item_id)["resolution"].strip() == right + + +def test_reopen_with_claim_flag_claims_the_item(run_cli, unique_project_name, unique_actor): + project = unique_project_name + assert run_cli(["new", project]).returncode == 0 + item_id = _add_item(run_cli, project) + assert ( + run_cli(["resolve", "--project", project, "--id", item_id, "--reason", "first"]).returncode + == 0 + ) + + result = run_cli( + [ + "reopen", + "--project", + project, + "--id", + item_id, + "--reason", + "correcting", + "--actor", + unique_actor, + "--claim", + ] + ) + assert result.returncode == 0, result.stderr + payload = json.loads(result.stdout) + assert payload["claimed"] is True + assert payload["holder"] == unique_actor + assert _row(run_cli, project, item_id)["status"] == "held" + + +def test_reopen_refuses_an_item_that_is_not_resolved(run_cli, unique_project_name): + project = unique_project_name + assert run_cli(["new", project]).returncode == 0 + item_id = _add_item(run_cli, project) + + result = run_cli(["reopen", "--project", project, "--id", item_id, "--reason", "why"]) + assert result.returncode != 0 + assert "nothing to reopen" in (result.stdout + result.stderr) + assert _row(run_cli, project, item_id)["status"] == "open" + + +def test_resolve_on_a_closed_item_with_different_text_exits_nonzero_and_writes_nothing( + run_cli, unique_project_name +): + """The headline behaviour change. Before this, the command exited 0 and + printed the OLD text under `"resolution"` as if the new one had landed.""" + project = unique_project_name + assert run_cli(["new", project]).returncode == 0 + item_id = _add_item(run_cli, project) + stored = "the original resolution" + assert ( + run_cli(["resolve", "--project", project, "--id", item_id, "--reason", stored]).returncode + == 0 + ) + + result = run_cli( + [ + "resolve", + "--project", + project, + "--id", + item_id, + "--reason", + "a completely different resolution", + ] + ) + assert result.returncode != 0, result.stdout + combined = result.stdout + result.stderr + assert "NOTHING WAS WRITTEN" in combined + assert stored in combined + assert "a completely different resolution" in combined + assert f"reopen --project {project} --id {item_id}" in combined + # Literally true: the record is untouched. + assert _row(run_cli, project, item_id)["resolution"].strip() == stored + + +def test_resolve_with_identical_text_exits_zero_and_says_it_was_idempotent( + run_cli, unique_project_name +): + project = unique_project_name + assert run_cli(["new", project]).returncode == 0 + item_id = _add_item(run_cli, project) + text = "the one true resolution" + + first = run_cli(["resolve", "--project", project, "--id", item_id, "--reason", text]) + assert first.returncode == 0, first.stderr + assert "idempotent" not in json.loads(first.stdout) + + again = run_cli(["resolve", "--project", project, "--id", item_id, "--reason", text]) + assert again.returncode == 0, again.stderr + _util.assert_no_silent_failure(again) + assert json.loads(again.stdout)["idempotent"] is True diff --git a/tests/integration/test_reopen_roundtrip.py b/tests/integration/test_reopen_roundtrip.py new file mode 100644 index 0000000..8bbf411 --- /dev/null +++ b/tests/integration/test_reopen_roundtrip.py @@ -0,0 +1,225 @@ +"""Tier 2 -- the correction cycle against a REAL bd binary: a published +resolution that is wrong can be reopened, re-claimed, and rewritten, and the +old text survives the transition. + +Everything the wrapper promises about `reopen`/`resolve`-on-closed is +asserted here against bd itself, not a stub: + + - reopen -> claim -> resolve reads back the CORRECTED text; + - bd's `events` table carries a `reopened` row naming actor and reason; + - the item's comment history carries the VERBATIM previous resolution and + the previous `closed_at` -- the guarantee that does not depend on what + bd does to `close_reason`; + - resolving a closed item with DIFFERENT text refuses and writes nothing; + - resolving it with IDENTICAL text succeeds as an idempotent no-op. + +The defect (work_tracker item model_performance-uma): before this, that +divergent resolve exited 0 and echoed the OLD text back as though the +correction had landed. +""" + +from __future__ import annotations + +import pytest + +from amplifier_work_tracker import adapter as A + +pytestmark = pytest.mark.integration + + +def _event_rows(bd: A.Beads, item_id: str, event_type: str) -> list[str]: + """Raw CSV rows bd itself wrote to `events` for this item. + + Read straight out of dolt rather than through any wrapper counter: the + claim under test is that BD writes the audit row, so reading it through + our own code would prove less. + """ + p = A._dolt_sql( + f"SELECT `event_type`, `actor`, `comment` FROM `{bd.project_name}`.`events` " + f"WHERE `issue_id` = '{A._sql_literal(item_id)}' " + f"AND `event_type` = '{A._sql_literal(event_type)}'" + ) + assert p.returncode == 0, p.stderr or p.stdout + lines = [ln for ln in (p.stdout or "").splitlines() if ln.strip()] + return lines[1:] # drop the CSV header + + +def _comment_texts(bd: A.Beads, item_id: str) -> list[str]: + return [e.detail or e.summary for e in bd.activity(item_id) if e.kind == "comment"] + + +def test_full_correction_cycle_reopen_claim_resolve_reads_back_corrected_text( + shared_bd: A.Beads, unique_lane +): + wrong = "VERDICT: retention non-inferiority PASSES (0.792 vs 0.688)" + right = "CORRECTED: uncomputable -- arm B has zero valid runs" + + item_id = shared_bd.create("reopen probe: full cycle", tags=[unique_lane], priority=1) + shared_bd.resolve(item_id, wrong, actor="first-pass") + closed = shared_bd.get(item_id) + assert closed.status == "resolved" + assert closed.closed_at is not None + + outcome = shared_bd.reopen(item_id, "the stored verdict is wrong", actor="corrector") + + # 1. It is genuinely back in the queue, and claimable by a DIFFERENT + # actor than the one who closed it -- see + # test_reopen_clears_the_stale_assignee_bd_leaves_behind for why that + # is the assertion that has teeth. + assert outcome.item.status != "resolved" + assert outcome.item.holder is None + assert outcome.previous_resolution == wrong + assert outcome.previous_closed_at == closed.closed_at + reclaimed = shared_bd.claim_item(item_id, actor="corrector") + assert reclaimed.id == item_id + + # 2. bd's own events table records the reopen, attributed -- and the + # reason with it. MEASURED (bd 1.1.2, 2026-09-02): bd splits these + # across TWO rows in the same transaction rather than one -- the + # `reopened` row carries event_type + actor (its `comment` column is + # empty; the reason is NOT there), and `--reason` lands as an + # adjacent attributed `commented` row. Both are asserted, because a + # test that only looked for the reason on the `reopened` row would + # pass on a bd that stopped recording the transition at all. + reopened = _event_rows(shared_bd, item_id, "reopened") + assert len(reopened) == 1, f"expected exactly one 'reopened' event, got {reopened}" + assert "corrector" in reopened[0] + commented = _event_rows(shared_bd, item_id, "commented") + assert any("the stored verdict is wrong" in row and "corrector" in row for row in commented), ( + f"bd no longer records the reopen --reason as an attributed event: {commented}" + ) + + # 3. The verbatim previous record survives in the comment history -- + # independent of whatever bd did to close_reason. + archived = "\n".join(_comment_texts(shared_bd, item_id)) + assert wrong in archived + assert closed.closed_at.isoformat() in archived + + # 4. The correction lands and READS BACK as the corrected text. + back = shared_bd.resolve(item_id, right, actor="corrector") + assert back.status == "resolved" + assert (back.resolution or "").strip() == right + assert wrong not in (back.resolution or "") + + +def test_reopen_clears_closed_at_and_the_cost_is_visible(shared_bd: A.Beads, unique_lane): + """The known, documented accounting cost: a corrected item stops + counting toward the day it was genuinely resolved.""" + item_id = shared_bd.create("reopen probe: closed_at", tags=[unique_lane], priority=1) + shared_bd.resolve(item_id, "first pass", actor="a") + was = shared_bd.get(item_id).closed_at + assert was is not None + + outcome = shared_bd.reopen(item_id, "correcting", actor="a") + assert outcome.item.closed_at is None + assert outcome.previous_closed_at == was + + +def test_reopen_clears_the_stale_assignee_bd_leaves_behind(shared_bd: A.Beads, unique_lane): + """MEASURED (bd 1.1.2, 2026-09-02): `bd reopen` flips status to open and + clears closed_at but LEAVES THE OLD ASSIGNEE IN PLACE -- after which a + directed claim by anyone else is refused outright ("issue already claimed + by "). An item nobody can take is not a correctable item, so + the wrapper clears the assignee (the same thing `release` already does). + + Found by this lane's own tool test failing on the claim leg; without the + clear, `work_reopen(claim=True)` cannot claim what it just reopened + unless the correcting agent happens to be the one who closed it. + """ + item_id = shared_bd.create("reopen probe: assignee", tags=[unique_lane], priority=1) + shared_bd.claim_item(item_id, actor="original-holder") + shared_bd.resolve(item_id, "closed by the original holder", actor="original-holder") + assert shared_bd.get(item_id).holder == "original-holder" + + outcome = shared_bd.reopen(item_id, "correcting", actor="corrector") + assert outcome.item.holder is None + + taken = shared_bd.claim_item(item_id, actor="someone-else-entirely") + assert taken.id == item_id + + +def test_resolve_on_a_closed_item_with_divergent_text_refuses_and_writes_nothing( + shared_bd: A.Beads, unique_lane +): + stored = "the original resolution text" + item_id = shared_bd.create("reopen probe: divergent", tags=[unique_lane], priority=1) + shared_bd.resolve(item_id, stored, actor="a") + + with pytest.raises(A.BeadsError) as e: + shared_bd.resolve(item_id, "a completely different resolution", actor="b") + msg = str(e.value) + assert "NOTHING WAS WRITTEN" in msg + assert stored in msg + assert "a completely different resolution" in msg + assert f"reopen --project {shared_bd.project_name} --id {item_id}" in msg + + # And it is literally true: the record is untouched. + assert (shared_bd.get(item_id).resolution or "").strip() == stored + + +def test_resolve_on_a_closed_item_with_identical_text_is_idempotent( + shared_bd: A.Beads, unique_lane +): + """The retry the contention contract promises is safe.""" + text = "closed: the one true resolution" + item_id = shared_bd.create("reopen probe: idempotent", tags=[unique_lane], priority=1) + shared_bd.resolve(item_id, text, actor="a") + + outcome = shared_bd.resolve_outcome(item_id, text, actor="a") + assert outcome.idempotent is True + assert (outcome.item.resolution or "").strip() == text + + # Whitespace-only differences are transport noise, not an edit. + again = shared_bd.resolve_outcome(item_id, f" {text}\r\n", actor="a") + assert again.idempotent is True + + +def test_reopen_refuses_an_item_that_is_not_resolved(shared_bd: A.Beads, unique_lane): + item_id = shared_bd.create("reopen probe: not closed", tags=[unique_lane], priority=1) + with pytest.raises(A.BeadsError) as e: + shared_bd.reopen(item_id, "there is nothing to reopen") + assert "nothing to reopen" in str(e.value) + assert shared_bd.get(item_id).status == "open" + + +def test_reopen_twice_refuses_the_second_time(shared_bd: A.Beads, unique_lane): + """Deliberately not idempotent -- the loser of a concurrent double + reopen learns it loudly instead of being told it did something.""" + item_id = shared_bd.create("reopen probe: twice", tags=[unique_lane], priority=1) + shared_bd.resolve(item_id, "first pass", actor="a") + shared_bd.reopen(item_id, "correcting", actor="a") + with pytest.raises(A.BeadsError) as e: + shared_bd.reopen(item_id, "correcting again", actor="b") + assert "nothing to reopen" in str(e.value) + + +def test_measured_close_reason_disposition_across_a_reopen(shared_bd: A.Beads, unique_lane): + """MEASUREMENT, pinned as a test: what bd 1.1.2 actually does to + `close_reason` when an item is reopened -- and the proof that the + wrapper's guarantee does not depend on the answer. + + MEASURED 2026-09-02 against bd 1.1.2 (20e493e56): a reopen CLEARS + `close_reason` -- the resolution text is GONE from the issue row, not + preserved. bd's own docs say nothing about this either way, which is + exactly why `reopen` archives the previous resolution into the comment + history FIRST. Had the wrapper trusted bd to keep it, every correction + would have destroyed the record it was correcting. + + Pinned here (and in `doctor`'s `reopen.close_reason_disposition`) so a + future bd change is loud rather than silent. The assertion prefers no + answer -- it asserts what was measured. + """ + text = "resolution text that may or may not survive a reopen" + item_id = shared_bd.create("reopen probe: disposition", tags=[unique_lane], priority=1) + shared_bd.resolve(item_id, text, actor="a") + outcome = shared_bd.reopen(item_id, "measuring close_reason disposition", actor="a") + + assert not (outcome.item.resolution or "").strip(), ( + "bd's close_reason disposition across a reopen has CHANGED -- it now " + f"preserves text ({outcome.item.resolution!r}) where it used to clear " + "it. Update this measured assumption and contract.py's " + "reopen.close_reason_disposition deliberately, never silently." + ) + # The wrapper's own guarantee holds regardless: the text bd threw away + # is still in the item's attributed comment history. + assert text in "\n".join(_comment_texts(shared_bd, item_id)) diff --git a/tests/unit/test_reopen_preconditions.py b/tests/unit/test_reopen_preconditions.py new file mode 100644 index 0000000..27b273b --- /dev/null +++ b/tests/unit/test_reopen_preconditions.py @@ -0,0 +1,114 @@ +"""Tier 1 -- `Beads.reopen`'s refusals, and its archive-BEFORE-transition +ordering. + +Both are provable without bd, and both are load-bearing: + + - reopen is deliberately NOT idempotent. Reopening an item that is not + resolved RAISES rather than no-ops -- the mirror image of `resolve`'s + rule. This program's recurring defect is an operation that looks like it + worked; "reopen succeeded" on an already-open item tells the caller + something false about what they just did. + - the archive comment carrying the verbatim previous resolution is written + BEFORE `bd reopen` runs. bd 1.1.2's treatment of `close_reason` across a + reopen is undocumented upstream, so the wrapper's guarantee must not + depend on it. Ordering is the guarantee. +""" + +from __future__ import annotations + +from pathlib import Path + +import pytest + +from amplifier_work_tracker import adapter as A + + +class _Ok: + returncode = 0 + stdout = "" + stderr = "" + + +class _Stub: + def __init__(self, *, current: A.Item, after: A.Item | None = None): + self.bd = A.Beads(Path("/nonexistent/.beads"), actor="tester") + self.calls: list[str] = [] + self.comments: list[str] = [] + self.reads = 0 + + def _get(item_id: str, *, with_links: bool = False) -> A.Item: + self.reads += 1 + return current if self.reads == 1 or after is None else after + + def _comment(item_id: str, text: str, *, actor: str | None = None) -> None: + self.calls.append("comment") + self.comments.append(text) + + def _run(args, actor=None): + self.calls.append(f"run:{args[0]}") + return _Ok() + + self.bd.get = _get # type: ignore[method-assign] + self.bd.comment = _comment # type: ignore[method-assign] + self.bd._run = _run # type: ignore[method-assign] + + +def _item(status: str, resolution: str | None = None) -> A.Item: + return A.Item(id="p-1", title="probe", status=status, resolution=resolution) + + +@pytest.mark.parametrize("status", ["open", "held", "blocked", "deferred"]) +def test_reopen_refuses_anything_that_is_not_resolved(status: str): + stub = _Stub(current=_item(status)) + with pytest.raises(A.BeadsError) as e: + stub.bd.reopen("p-1", "correcting the record") + assert "nothing to reopen" in str(e.value) + assert status in str(e.value) + assert stub.calls == [] # nothing written, not even the archive comment + + +@pytest.mark.parametrize("reason", ["", " ", "\n\t "]) +def test_reopen_refuses_an_empty_reason_before_reading_anything(reason: str): + stub = _Stub(current=_item("resolved", "old text")) + with pytest.raises(A.BeadsError) as e: + stub.bd.reopen("p-1", reason) + assert "reason is required" in str(e.value) + assert stub.calls == [] + + +def test_reopen_archives_the_verbatim_previous_record_before_transitioning(): + stub = _Stub( + current=_item("resolved", "the ORIGINAL text, wrong"), + after=_item("open", None), + ) + outcome = stub.bd.reopen("p-1", "2lp proved the verdict uncomputable", actor="corrector") + + # Ordering, not merely presence: the archive lands first, so the record + # survives whatever bd does to close_reason during the transition. + assert stub.calls == ["comment", "run:reopen"] + archived = stub.comments[0] + assert "the ORIGINAL text, wrong" in archived + assert "2lp proved the verdict uncomputable" in archived + assert "corrector reopened this item" in archived + assert "PREVIOUS closed_at:" in archived + + # And the old text comes back in the RESULT too -- the caller is about + # to write the replacement, usually as an edit of it. + assert outcome.previous_resolution == "the ORIGINAL text, wrong" + assert outcome.item.status == "open" + assert outcome.actor == "corrector" + + +def test_reopen_refuses_to_report_success_if_the_item_is_still_resolved(): + stub = _Stub(current=_item("resolved", "old"), after=_item("resolved", "old")) + with pytest.raises(A.BeadsError) as e: + stub.bd.reopen("p-1", "why") + assert "refusing to report success" in str(e.value) + + +def test_reopen_archives_a_blank_previous_resolution_explicitly(): + """An item closed with no resolution (e.g. via supersede) still gets an + honest archive entry, never a silently empty one.""" + stub = _Stub(current=_item("resolved", None), after=_item("open", None)) + stub.bd.reopen("p-1", "why") + assert "(none -- was blank)" in stub.comments[0] diff --git a/tests/unit/test_resolve_text_compare.py b/tests/unit/test_resolve_text_compare.py new file mode 100644 index 0000000..315d459 --- /dev/null +++ b/tests/unit/test_resolve_text_compare.py @@ -0,0 +1,253 @@ +"""Tier 1 -- `resolve` compares the resolution TEXT, not merely the status, +at BOTH places it decides "did my write land?". + +The defect these pin (work_tracker item model_performance-uma, spec +`w3-uma-work-tracker-reopen/SPEC.md`): a `resolve` against an ALREADY-closed +item exited 0 and echoed the OLD stored text back as if it were the text just +written. Seven wrong resolutions shipped that way and could not be corrected. + +`resolve` decides that question in two places, and a fix that patches only +the obvious one leaves the other silently wrong: + + - the normal post-write readback (`bd close` returned 0), and + - the CONTENDED path, where `_run` exhausted its serialization-retry + budget and raised, so the wrapper reads the item back and decides from + what it finds. + +The contended path is where a caller is LEAST able to reason about what +happened, so both are exercised here -- with no bd and no dolt, by driving a +`Beads` instance whose `_run`/`get` are stubbed. That is deliberate: these +are the wrapper's own decisions, and they must be provable without needing a +contention race to occur for real. +""" + +from __future__ import annotations + +from pathlib import Path + +import pytest + +from amplifier_work_tracker import adapter as A + +# ---------------------------------------------------------------- normalization + + +def test_norm_resolution_unifies_line_endings_and_strips_outer_whitespace(): + assert A._norm_resolution("fixed the thing\r\n") == "fixed the thing" + assert A._norm_resolution(" fixed the thing ") == "fixed the thing" + assert A._norm_resolution("a\r\nb") == A._norm_resolution("a\nb") + assert A._norm_resolution(None) == "" + + +def test_norm_resolution_keeps_case_and_internal_whitespace_significant(): + """Both are REAL edits to what a human will read -- a normalization that + swallowed them would re-open the silent-discard hole from the inside.""" + assert not A._resolution_landed("Fixed", "fixed") + assert not A._resolution_landed("a b", "a b") + assert not A._resolution_landed("line one\nline two", "line one line two") + + +def test_resolution_landed_is_true_only_for_the_same_text(): + assert A._resolution_landed("done\n", "done") + assert A._resolution_landed(None, " ") + assert not A._resolution_landed("done", "done, actually not") + + +def test_echo_resolution_truncates_loudly_never_silently(): + long = "x" * 900 + out = A._echo_resolution(long) + assert out.startswith("x" * A.RESOLUTION_ECHO_LIMIT) + assert "[truncated, 900 chars]" in out + assert A._echo_resolution("") == "(none -- blank)" + assert A._echo_resolution("short") == "short" + + +def test_divergent_error_message_carries_everything_a_caller_needs(): + err = A._divergent_resolution_error( + "proj-abc", + project="proj", + stored="VERDICT: retention PASSES", + sent="2lp proved this UNCOMPUTABLE", + ) + msg = str(err) + # 1. the item, 2. both texts side by side, 3. the words that stop a + # blind retry, 4. the remedy as a runnable command on BOTH surfaces. + assert "proj-abc" in msg + assert "VERDICT: retention PASSES" in msg + assert "2lp proved this UNCOMPUTABLE" in msg + assert "NOTHING WAS WRITTEN" in msg + assert "amplifier-work-tracker reopen --project proj --id proj-abc" in msg + assert "work_reopen(" in msg + + +# ------------------------------------------------------------------- the wrapper + + +class _Stub: + """A `Beads` with its two bd-touching primitives replaced. + + Only `_run` and `get` are stubbed -- every decision under test is made + by the real `resolve_outcome` code path, including `_read_back_or_none`, + which routes through the stubbed `get` exactly as it would route through + the real one. + """ + + def __init__(self, *, current: A.Item | None, after: A.Item | None, run): + self.bd = A.Beads(Path("/nonexistent/.beads"), actor="tester") + self.reads = 0 + self.run_calls: list[list[str]] = [] + + def _get(item_id: str, *, with_links: bool = False) -> A.Item: + self.reads += 1 + item = current if self.reads == 1 else after + if item is None: + raise A.BeadsError(f"item {item_id!r} not found") + return item + + def _run_stub(args, actor=None): + self.run_calls.append(list(args)) + return run(args) + + self.bd.get = _get # type: ignore[method-assign] + self.bd._run = _run_stub # type: ignore[method-assign] + + +def _item(item_id: str, *, status: str, resolution: str | None) -> A.Item: + return A.Item(id=item_id, title="probe", status=status, resolution=resolution) + + +class _Ok: + returncode = 0 + stdout = "" + stderr = "" + + +def _ok(_args): + return _Ok() + + +def _raises(_args): + raise A.BeadsError("still conflicting after 8 retries") + + +# --- precondition (checked BEFORE any write, so "NOTHING WAS WRITTEN" is true) + + +def test_divergent_text_on_a_closed_item_refuses_and_writes_nothing(): + stub = _Stub( + current=_item("p-1", status="resolved", resolution="the ORIGINAL, wrong text"), + after=None, + run=_ok, + ) + with pytest.raises(A.BeadsError) as e: + stub.bd.resolve_outcome("p-1", "the CORRECTED text") + assert "NOTHING WAS WRITTEN" in str(e.value) + assert "the ORIGINAL, wrong text" in str(e.value) + assert "the CORRECTED text" in str(e.value) + # The whole promise: no bd write was even attempted. + assert stub.run_calls == [] + + +def test_identical_text_on_a_closed_item_is_an_idempotent_success_with_no_write(): + """The retry case the contention contract promises is safe: a retry + re-sends the identical string, and must not be turned into a failure.""" + stub = _Stub( + current=_item("p-2", status="resolved", resolution="done: fixed the parser\n"), + after=None, + run=_ok, + ) + outcome = stub.bd.resolve_outcome("p-2", "done: fixed the parser") + assert outcome.idempotent is True + assert outcome.item.id == "p-2" + assert stub.run_calls == [] + + +def test_resolving_an_open_item_is_unchanged(): + stub = _Stub( + current=_item("p-3", status="open", resolution=None), + after=_item("p-3", status="resolved", resolution="closed it"), + run=_ok, + ) + outcome = stub.bd.resolve_outcome("p-3", "closed it") + assert outcome.idempotent is False + assert outcome.item.status == "resolved" + assert stub.run_calls and stub.run_calls[0][0] == "close" + + +# --- decision point 1: the normal post-write readback + + +def test_post_write_readback_refuses_when_the_stored_text_is_not_ours(): + """`bd close` exited 0, the item is resolved -- and the resolution on it + is somebody else's text. Status alone would call that success.""" + stub = _Stub( + current=_item("p-4", status="open", resolution=None), + after=_item("p-4", status="resolved", resolution="someone else's text"), + run=_ok, + ) + with pytest.raises(A.BeadsError) as e: + stub.bd.resolve_outcome("p-4", "my text") + assert "someone else's text" in str(e.value) + assert "my text" in str(e.value) + assert "reopen" in str(e.value) + + +# --- decision point 2: the CONTENDED path (_run raised; wrapper reads back) + + +def test_contended_path_reports_success_only_when_our_own_text_landed(): + stub = _Stub( + current=_item("p-5", status="open", resolution=None), + after=_item("p-5", status="resolved", resolution="my text"), + run=_raises, + ) + outcome = stub.bd.resolve_outcome("p-5", "my text") + assert outcome.item.status == "resolved" + # Not idempotent: the precondition read proved it was open when we + # started, so the write that landed was OURS, inside this call. + assert outcome.idempotent is False + + +def test_contended_path_raises_when_the_readback_text_is_not_ours(): + """THE EASY ONE TO MISS. `_run` gave up; the readback shows the item + resolved -- but with text that is not what we sent. Returning that item + as success (status-only check) is a lie, and it is the exact site a + half-done fix leaves wrong.""" + stub = _Stub( + current=_item("p-6", status="open", resolution=None), + after=_item("p-6", status="resolved", resolution="a DIFFERENT resolution"), + run=_raises, + ) + with pytest.raises(A.BeadsError) as e: + stub.bd.resolve_outcome("p-6", "the text I actually sent") + msg = str(e.value) + assert "a DIFFERENT resolution" in msg + assert "the text I actually sent" in msg + assert "NOT WRITTEN" in msg + assert "reopen" in msg + + +def test_contended_path_still_reraises_when_the_item_never_closed(): + """Unchanged behaviour: the wrapper gave up and the item is NOT + resolved, so the original conflict error is what the caller gets.""" + stub = _Stub( + current=_item("p-7", status="open", resolution=None), + after=_item("p-7", status="open", resolution=None), + run=_raises, + ) + with pytest.raises(A.BeadsError) as e: + stub.bd.resolve_outcome("p-7", "my text") + assert "still conflicting after 8 retries" in str(e.value) + + +def test_resolve_returns_an_item_for_every_existing_caller(): + """`resolve()` keeps its `Item` return type -- `resolve_outcome` is the + additive entry point, not a breaking rename.""" + stub = _Stub( + current=_item("p-8", status="open", resolution=None), + after=_item("p-8", status="resolved", resolution="closed"), + run=_ok, + ) + back = stub.bd.resolve("p-8", "closed") + assert isinstance(back, A.Item) + assert back.status == "resolved" From f9f83fed3ca78e1beada5d9b81cf53f90d75f72c Mon Sep 17 00:00:00 2001 From: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com> Date: Wed, 2 Sep 2026 20:53:35 -0700 Subject: [PATCH 2/2] converge: reconcile three ledger rows this change moved; lane note + evidence None absorbed silently, none re-dispositioned (contracts/ and VISION.md untouched, so CCV1-000's SYNC hashes still hold): - CCV1-009 (VIOLATION) -- the close path grew a pre-write read of its own and the fence moved into `resolve_outcome`. The probe's landmarks follow it and are now robust to formatting. Claim re-verified and UNCHANGED: the fence still runs only under `status == "held"`, so a post-reclaim close is still unfenced. - CCV1-015 (GAP) -- `_read_back_or_none` count 3 -> 4: `reopen` adopted verify-on-conflict. Real movement TOWARD the clause, recorded rather than absorbed. Still a GAP: take_custody/renew_custody remain uncovered. - CCV1-023 (GAP) -- the single-hold refusal is now asserted INCIDENTALLY in the modules suite (one branch of work_reopen's claim-degradation path). That suite is the one `make test` does not run, so the Freeze Bar clause is still unmet and the row stays GAP; the probe pins that exact file set so a real Fixture 4 still flips it. Lane artifacts under docs/lanes/f5c-work-tracker-reopen/ (artifact-path/v1): the DONE-NOTE, and raw evidence including the fail-before runs at parent commit 1621771 and the before-state demonstration of the silent discard. --- .../f5c-work-tracker-reopen/DONE-NOTE.md | 219 ++ .../evidence/before-defect-demonstration.log | 129 + .../evidence/fail-before-cli.log | 450 ++++ .../evidence/fail-before-integration.log | 349 +++ .../evidence/fail-before-unit.log | 80 + .../evidence/make-test-full.log | 2269 +++++++++++++++++ .../evidence/modules-suite.log | 145 ++ ...-commit-doctor-cli-preexisting-failure.log | 674 +++++ ...ommit-modules-reap-preexisting-failure.log | 153 ++ ledger/checks/test_custody_rows.py | 61 +- ledger/rows.yaml | 23 +- 11 files changed, 4530 insertions(+), 22 deletions(-) create mode 100644 docs/lanes/f5c-work-tracker-reopen/DONE-NOTE.md create mode 100644 docs/lanes/f5c-work-tracker-reopen/evidence/before-defect-demonstration.log create mode 100644 docs/lanes/f5c-work-tracker-reopen/evidence/fail-before-cli.log create mode 100644 docs/lanes/f5c-work-tracker-reopen/evidence/fail-before-integration.log create mode 100644 docs/lanes/f5c-work-tracker-reopen/evidence/fail-before-unit.log create mode 100644 docs/lanes/f5c-work-tracker-reopen/evidence/make-test-full.log create mode 100644 docs/lanes/f5c-work-tracker-reopen/evidence/modules-suite.log create mode 100644 docs/lanes/f5c-work-tracker-reopen/evidence/parent-commit-doctor-cli-preexisting-failure.log create mode 100644 docs/lanes/f5c-work-tracker-reopen/evidence/parent-commit-modules-reap-preexisting-failure.log diff --git a/docs/lanes/f5c-work-tracker-reopen/DONE-NOTE.md b/docs/lanes/f5c-work-tracker-reopen/DONE-NOTE.md new file mode 100644 index 0000000..5f04835 --- /dev/null +++ b/docs/lanes/f5c-work-tracker-reopen/DONE-NOTE.md @@ -0,0 +1,219 @@ +# DONE-NOTE — `model_performance-f5c` + +**Item:** IMPLEMENT: `reopen` CLI verb + `work_reopen` tool, and make `resolve` on a closed +item fail loud (spec: uma) +**Lane:** `f5c-work-tracker-reopen` · **Branch:** `lane/f5c-work-tracker-reopen` +**Repo:** `github.com/microsoft/amplifier-work-tracker` · **Parent:** `1621771` +**bd:** 1.1.2 (20e493e56) · **Date:** 2026-09-02 + +--- + +## Result + +All five parts shipped, with tests. The headline behaviour change: `resolve` on an +already-closed item now compares the resolution **text**, not the item's status, at **both** +places it decides "did my write land?" — so a correction is either an idempotent success +(identical text) or a loud, non-zero refusal that writes nothing (divergent text). `reopen` +is the remedy that refusal names. + +The lane also found and fixed **two undocumented bd behaviours** that the spec had flagged as +unknown or had not anticipated at all. Both are recorded below; the second one would have +made `work_reopen(claim=True)` unusable in exactly the scenario it exists for. + +--- + +## What was measured (not assumed) + +### 1. `bd reopen` CLEARS `close_reason` — the archive-first ordering is load-bearing + +The spec (§2.4) said bd 1.1.2's treatment of `close_reason` across a reopen was undocumented +and unverified, and told the implementer not to build a guarantee on it. **Measured here: +reopen clears it.** The previous resolution text is *gone* from the issue row. + +That makes the spec's archive-first ordering not merely prudent but load-bearing: had the +wrapper trusted bd to preserve the text, **every correction would have destroyed the record +it was correcting.** Pinned in two places so a future bd change is loud: +`tests/integration/test_reopen_roundtrip.py::test_measured_close_reason_disposition_across_a_reopen` +and `doctor`'s `reopen.close_reason_disposition`. + +### 2. `bd reopen` LEAVES THE OLD ASSIGNEE — an item nobody can take is not correctable + +Not in the spec; found because this lane's own tool test failed on its claim leg. After +`bd reopen`, the item is `open` with `closed_at` cleared **but still assigned to whoever +closed it**, so a directed claim by anyone else is refused outright: + +``` +claim as 'corrector' failed: Error claiming : issue already claimed by +``` + +`work_reopen(claim=True)` could therefore only ever claim what it reopened if the correcting +agent happened to be the agent who closed it — which is the *opposite* of the correction +scenario. `Beads.reopen` now clears the assignee (the same `update --assignee ""` that +`release` already does) and verifies by readback; if it cannot be cleared, it says so loudly +naming the stuck holder rather than handing back an untakeable item. Fenced by +`doctor`'s `reopen.reopens`, which now performs a **directed** claim by a *different* actor +(the weaker `claim_next` form passed even with the stale assignee in place). + +### 3. The `reopened` audit trail is TWO event rows, not one + +The deliverable expected "a `reopened` row naming the actor and reason". Measured: bd writes +the `reopened` row with `event_type` + `actor` (its `comment` column is **empty** — the reason +is not there) and lands `--reason` as an adjacent attributed `commented` row in the same +transaction. The `reopened` row's `old_value` additionally carries the entire prior issue JSON +including `close_reason` — a third, incidental archive. Both rows are asserted, because a test +that only looked for the reason on the `reopened` row would pass on a bd that stopped recording +the transition at all. + +--- + +## The open question, answered + +> *whether one actor may hold two items at once. If not, `work_reopen`'s `claim=True` must +> degrade to `claimed:false` with a clear message rather than drop the caller's existing +> custody.* + +**Answered: a SESSION holds at most one item.** The constraint is at the tool layer, not bd's: +`_Held`'s own docstring states it, and `WorkTrackerSession.claim` refuses outright with +`"already holding ... resolve it with work_resolve before claiming another item"`. (bd +itself would happily assign two items to one actor name; the seam is what enforces one.) + +So `claim=True` from a session that already holds work **cannot** be honoured, and +`work_reopen` degrades exactly as the spec required: `claimed: false`, `claim_error` carrying +the refusal verbatim, `next_step` telling the caller to claim it themselves — and the existing +hold is untouched, its custody thread still running. The reopen still **stands**; rolling it +back would mean a second close with invented text, which is the disease. + +Implemented by *reusing* `session.claim()` wholesale rather than re-implementing the claim leg +— that is the one atomic claim-plus-custody path, and a second implementation of it is how a +double-claim hole gets reopened. Proven by +`modules/tool-work-tracker/tests/test_work_reopen.py::test_claim_leg_degrades_without_dropping_an_existing_hold`. + +--- + +## Deliverables + +| Deliverable | Status | +|---|---| +| Draft PR on origin carrying parts 1–5, suite green | **DONE** — see PR body | +| reopen round-trip (corrected text reads back; events row; verbatim comment archive) | **DONE** — `tests/integration/test_reopen_roundtrip.py` | +| divergent-text refusal (non-zero, nothing written, both texts, remedy) | **DONE** — unit + integration + CLI | +| identical-text idempotency (`"idempotent": true`) | **DONE** — unit + integration + CLI | +| contended path — BOTH decision points | **DONE** — `tests/unit/test_resolve_text_compare.py` | +| doctor assumptions (6 new) | **DONE** — `doctor` now 33/33 against live bd | +| fail-before evidence | **DONE** — `evidence/fail-before-*.log`, `evidence/before-defect-demonstration.log` | +| help/contract text updated | **DONE** — `cli.py` module docstring, `context/awareness.md`, `bundle.md`, `AGENTS.md` | +| DONE-NOTE with the open question answered | **DONE** — this file | + +### Test tiers actually run, honestly + +| Tier | Command | Needed live bd/dolt? | Result | +|---|---|---|---| +| unit | `make test-unit` | no | green (23 new tests) | +| integration | `make test-integration` | **yes — had it** (bd 1.1.2 + isolated dolt server per session) | green (8 new + 6 new contract assumptions) | +| cli | `make test-cli` | **yes — had it** | green (5 new) | +| ledger | `make test-ledger` | no | green (24, incl. 3 reconciled rows) | +| **all four** | `make test` | yes | **1189 passed, 3 skipped, 1 failed — the failure is pre-existing, see below** | +| modules suite | `pytest modules/tool-work-tracker/tests` | **yes — had it** | **93 passed, 1 failed — pre-existing, see below** (all 7 new tests green) — *not run by root CI (AGENTS.md); run directly because this change touches it* | +| `doctor` | `amplifier-work-tracker doctor --quick` | yes | **33/33** | + +**Two failures, both pre-existing, both reproduced at parent commit `1621771` with this +change absent.** Neither is caused by this work; both are filed `discovered-from` this item. + +1. `tests/cli/test_cli_surface.py::test_doctor_quick_succeeds_against_the_real_installed_bd` + — the suite repoints `AMPLIFIER_WORK_TRACKER_ROOT` at an isolated tmp root where no sweep + heartbeat has ever been written, so `sweeps.alive` reports "no heartbeat ever recorded" + and `doctor` exits 1. Every other assumption in that same run passes, **including all six + added here**. Evidence: `evidence/parent-commit-doctor-cli-preexisting-failure.log`. + Filed as **`model_performance-jyg`**. + +2. `modules/tool-work-tracker/tests/test_reap_recovery.py::test_explicit_resolve_refusal_after_reap_clears_held_and_allows_new_claim` + — a post-reclaim `work_resolve` is **not** refused; the close lands at `success=True`. + This is the ledger's own flagship divergence **CCV1-009** (VIOLATION, + `work_item_pipeline-dn4`) observed behaviourally: a reap leaves the item `open`, so + `resolve`'s fence — gated on `status == "held"` — is skipped, and the tool layer's `_held` + latch lets it through rather than catching it. Evidence: + `evidence/parent-commit-modules-reap-preexisting-failure.log` (parent) and + `evidence/modules-suite.log` (with this change). Filed as **`model_performance-c0e`**, + which also records that ledger row CCV1-023's note ("passes via the session latch") is + measurably wrong — left untouched here because it is a claim about a different row's + subject, not drift this change caused. + +--- + +## Deviations from the spec, and why + +1. **`resolve()` keeps returning `Item`; the `idempotent` flag lives on a new + `resolve_outcome()`.** The spec implied a richer return. There are ~30 `bd.resolve(...)` + call sites across src, contract, and both suites; changing the return type would have + churned every one of them for a flag two callers need. `resolve()` is now a **one-line + projection** of `resolve_outcome()` — deliberately pure, so the two entry points cannot + drift. + +2. **`ReopenOutcome.previous_closed_at` is a `datetime`, not a `str`.** The spec's sketch + said `str`. `Item` parses every bd timestamp into a real `datetime` *at the seam* + precisely so no caller re-parses one; the JSON surfaces (CLI, tool) `isoformat()` it. + +3. **`reopen` clears the stale assignee.** Not in the spec — see measurement 2. Without it + the deliverable's own round-trip is unreachable for any agent but the original closer. + +4. **`defer()`/`block()` refusing a resolved item is NOT in this change.** The spec added it + late (§1) and filed it as `model_performance-2nx`. It is a *separate destructive path*, + and the goal named five parts; folding in a sixth would widen a change whose value is + elsewhere. It remains a real, unfixed hole: both verbs still move a resolved item out of + `resolved` and blank its resolution at exit 0. + +5. **`reopen_count` on read surfaces (spec §2.8's "additionally") is NOT in this change.** + `reopened_count()` already exists project-wide; surfacing a per-item count on + `work_list`/the item payload is a read-surface change with its own SQL, and nothing in the + deliverables asked for it. + +6. **The `claiming-work-safely` skill was left alone.** The goal named three doc surfaces + (`--help`, `cli.py:29`, `context/awareness.md`); all three are updated, and `awareness.md` + is the always-loaded agent-facing contract. The skill asserts nothing this change makes + false. + +--- + +## Ledger reconciliation (three rows moved; none absorbed silently) + +This change made three probes in `ledger/checks/test_custody_rows.py` fail. All three were +reconciled explicitly, with the reason recorded in each row's `notes`. **No row's disposition +changed**; `contracts/` and `docs/VISION.md` were not touched, so the CCV1-000 SYNC hashes +still hold. + +- **CCV1-009** (VIOLATION, post-reclaim close unfenced) — the probe sliced `resolve`'s source + and matched a literal gate line. The close path grew a pre-write read of its own and the + fence moved into `resolve_outcome`. Probe re-pointed to follow it and made robust to + formatting (delimits the pre-write region by the `close` write itself). **Claim re-verified + and unchanged:** the fence still runs only under `status == "held"`. +- **CCV1-015** (GAP, only resolve/release verify a conflicted write) — count 3 → 4: + `reopen` adopted the same verify-on-conflict discipline. **Real movement toward the clause, + recorded rather than absorbed.** Still a GAP: `take_custody`/`renew_custody` remain uncovered. +- **CCV1-023** (GAP, Fixture 4 single-hold asserted nowhere) — now asserted *incidentally* in + the modules suite, as one branch of `work_reopen`'s claim-degradation path. That suite is + the one `make test` does not run, so the Freeze Bar clause ("executable via `make test`") is + still unmet and the row stays GAP. The probe now pins that exact file set, so a real + dedicated Fixture 4 still flips it. + +--- + +## Spend + +**$0.** No API spend, no DTU, no containers, no infrastructure registered or torn down. +Pure code change verified against the already-running local bd/dolt and the suite's own +per-session isolated dolt server. Spend authority for this item was $0 and none was used. + +--- + +## What remains open + +- `model_performance-2nx` — `defer()`/`block()` still perform an unaudited, destructive reopen + of a resolved item at exit 0. This change gives them the safe verb to point at; it does not + make them use it. +- `model_performance-jyg` (filed by this lane) — the pre-existing `doctor` CLI test failure. +- `model_performance-69y` — the 7-item correction backlog (`dt1`, `ys8`, `xy0`, `1rn`, `df1`, + `bji`, `44f`) is now **unblocked**: each is one `reopen` → `claim` → `resolve` cycle. Expect + the 7-day throughput figure to move by up to 7 items as their `closed_at` values are cleared + — that is the documented, surfaced cost, not a bug. +- Fixture 4 (single-hold) still needs a dedicated, `make test`-runnable fixture; blocked on + CCV1-022 (the modules suite runs in no CI). diff --git a/docs/lanes/f5c-work-tracker-reopen/evidence/before-defect-demonstration.log b/docs/lanes/f5c-work-tracker-reopen/evidence/before-defect-demonstration.log new file mode 100644 index 0000000..50bdee6 --- /dev/null +++ b/docs/lanes/f5c-work-tracker-reopen/evidence/before-defect-demonstration.log @@ -0,0 +1,129 @@ +Starting server with Config HP="127.0.0.1:40087"|T="28800000"|R="false"|L="info" +time="2026-09-02T20:23:10-07:00" level=info msg="Creating root@localhost superuser" +time="2026-09-02T20:23:10-07:00" level=info msg="Server ready. Accepting connections." +time="2026-09-02T20:23:10-07:00" level=warning msg="secure_file_priv is set to \"\", which is insecure." +time="2026-09-02T20:23:10-07:00" level=warning msg="Any user with GRANT FILE privileges will be able to read any file which the sql-server process can read." +time="2026-09-02T20:23:10-07:00" level=warning msg="Please consider restarting the server with secure_file_priv set to a safe (or non-existent) directory." +time="2026-09-02T20:23:10-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1 +time="2026-09-02T20:23:10-07:00" level=info msg=ConnectionClosed connectionID=1 +time="2026-09-02T20:23:10-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2 +time="2026-09-02T20:23:10-07:00" level=info msg=ConnectionClosed connectionID=2 +time="2026-09-02T20:23:10-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=3 +time="2026-09-02T20:23:10-07:00" level=info msg=ConnectionClosed connectionID=3 +time="2026-09-02T20:23:10-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=4 +time="2026-09-02T20:23:10-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=5 +time="2026-09-02T20:23:10-07:00" level=info msg=ConnectionClosed connectionID=4 +time="2026-09-02T20:23:10-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:23:10.636461757 -0700 PDT m=+0.513202579" connectionDb=shared4196c803fe6c connectionID=5 error="table not found: schema_migrations" queryTime="2026-09-02 20:23:10.63759001 -0700 PDT m=+0.514330832" +time="2026-09-02T20:23:10-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=6 +time="2026-09-02T20:23:10-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:23:10.638189144 -0700 PDT m=+0.514929998" connectionDb=shared4196c803fe6c connectionID=6 error="table not found: schema_migrations" queryTime="2026-09-02 20:23:10.639203269 -0700 PDT m=+0.515944107" +time="2026-09-02T20:23:10-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:23:10.638189144 -0700 PDT m=+0.514929998" connectionDb=shared4196c803fe6c connectionID=6 error="table not found: schema_migrations" queryTime="2026-09-02 20:23:10.640857121 -0700 PDT m=+0.517597959" +time="2026-09-02T20:23:10-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:23:10.638189144 -0700 PDT m=+0.514929998" connectionDb=shared4196c803fe6c connectionID=6 error="table not found: schema_migrations" queryTime="2026-09-02 20:23:10.642443836 -0700 PDT m=+0.519184658" +time="2026-09-02T20:23:12-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:23:10.638189144 -0700 PDT m=+0.514929998" connectionDb=shared4196c803fe6c connectionID=6 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:23:12.669937032 -0700 PDT m=+2.546677870" +time="2026-09-02T20:23:13-07:00" level=info msg=ConnectionClosed connectionID=6 +time="2026-09-02T20:23:13-07:00" level=info msg=ConnectionClosed connectionID=5 +time="2026-09-02T20:23:13-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=7 +time="2026-09-02T20:23:13-07:00" level=info msg=ConnectionClosed connectionID=7 +time="2026-09-02T20:23:13-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=8 +time="2026-09-02T20:23:13-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=9 +time="2026-09-02T20:23:13-07:00" level=info msg=ConnectionClosed connectionID=8 +time="2026-09-02T20:23:13-07:00" level=info msg=ConnectionClosed connectionID=9 +time="2026-09-02T20:23:13-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=10 +time="2026-09-02T20:23:13-07:00" level=info msg=ConnectionClosed connectionID=10 +time="2026-09-02T20:23:13-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=11 +time="2026-09-02T20:23:13-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=12 +time="2026-09-02T20:23:13-07:00" level=info msg=ConnectionClosed connectionID=11 +time="2026-09-02T20:23:13-07:00" level=info msg=ConnectionClosed connectionID=12 +time="2026-09-02T20:23:13-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=13 +time="2026-09-02T20:23:13-07:00" level=info msg=ConnectionClosed connectionID=13 +time="2026-09-02T20:23:13-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=14 +time="2026-09-02T20:23:13-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=15 +time="2026-09-02T20:23:13-07:00" level=info msg=ConnectionClosed connectionID=14 +time="2026-09-02T20:23:13-07:00" level=info msg=ConnectionClosed connectionID=15 +time="2026-09-02T20:23:13-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=16 +time="2026-09-02T20:23:13-07:00" level=info msg=ConnectionClosed connectionID=16 +time="2026-09-02T20:23:13-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=17 +time="2026-09-02T20:23:13-07:00" level=info msg=ConnectionClosed connectionID=17 +time="2026-09-02T20:23:13-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=18 +time="2026-09-02T20:23:13-07:00" level=info msg=ConnectionClosed connectionID=18 +time="2026-09-02T20:23:13-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=19 +time="2026-09-02T20:23:13-07:00" level=info msg=ConnectionClosed connectionID=19 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=20 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=20 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=21 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=22 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=21 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=23 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=23 +time="2026-09-02T20:23:14-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:23:14.032712525 -0700 PDT m=+3.909453363" connectionDb=shared4196c803fe6c connectionID=22 error="backup 'backup_export' not found" queryTime="2026-09-02 20:23:14.136286901 -0700 PDT m=+4.013027739" + +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=22 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=24 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=24 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=25 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=25 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=26 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=26 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=27 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=27 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=28 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=29 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=28 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=30 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=30 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=29 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=31 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=31 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=32 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=32 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=33 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=33 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=34 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=34 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=35 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=35 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=36 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=36 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=37 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=37 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=38 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=39 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=38 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=40 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=40 +time="2026-09-02T20:23:14-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:23:14.885727895 -0700 PDT m=+4.762468733" connectionDb=shared4196c803fe6c connectionID=39 error="nothing to commit" queryTime="2026-09-02 20:23:14.944682775 -0700 PDT m=+4.821423613" +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=39 +time="2026-09-02T20:23:14-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=41 +time="2026-09-02T20:23:14-07:00" level=info msg=ConnectionClosed connectionID=41 +time="2026-09-02T20:23:15-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=42 +time="2026-09-02T20:23:15-07:00" level=info msg=ConnectionClosed connectionID=42 +time="2026-09-02T20:23:15-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=43 +time="2026-09-02T20:23:15-07:00" level=info msg=ConnectionClosed connectionID=43 +time="2026-09-02T20:23:15-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=44 +time="2026-09-02T20:23:15-07:00" level=info msg=ConnectionClosed connectionID=44 +time="2026-09-02T20:23:15-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=45 +time="2026-09-02T20:23:15-07:00" level=info msg=ConnectionClosed connectionID=45 +time="2026-09-02T20:23:15-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=46 +time="2026-09-02T20:23:15-07:00" level=info msg=ConnectionClosed connectionID=46 +time="2026-09-02T20:23:15-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=47 +time="2026-09-02T20:23:15-07:00" level=info msg=ConnectionClosed connectionID=47 +time="2026-09-02T20:23:15-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=48 +time="2026-09-02T20:23:15-07:00" level=info msg=ConnectionClosed connectionID=48 +time="2026-09-02T20:23:15-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=49 +time="2026-09-02T20:23:15-07:00" level=info msg=ConnectionClosed connectionID=49 + +--- BEFORE STATE (parent commit, fix absent) --- + sent to resolve(): 'CORRECTED: uncomputable -- arm B has zero valid runs' + returned as landed: 'VERDICT: the retention gate PASSES' + stored on the item: 'VERDICT: the retention gate PASSES' + raised: nothing -- exit 0, reported success +--- the correction was discarded and the caller was told it landed --- + +.time="2026-09-02T20:23:15-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=50 +time="2026-09-02T20:23:15-07:00" level=info msg="stats stopped: context canceled" +time="2026-09-02T20:23:15-07:00" level=info msg=ConnectionClosed connectionID=50 +time="2026-09-02T20:23:15-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=51 +time="2026-09-02T20:23:15-07:00" level=info msg=ConnectionClosed connectionID=51 +time="2026-09-02T20:23:15-07:00" level=info msg="Server closing listener. No longer accepting connections." +time="2026-09-02T20:23:15-07:00" level=info msg="stats stopped: context canceled" + +1 passed in 5.33s diff --git a/docs/lanes/f5c-work-tracker-reopen/evidence/fail-before-cli.log b/docs/lanes/f5c-work-tracker-reopen/evidence/fail-before-cli.log new file mode 100644 index 0000000..f55bef4 --- /dev/null +++ b/docs/lanes/f5c-work-tracker-reopen/evidence/fail-before-cli.log @@ -0,0 +1,450 @@ +FFFFF [100%] +=================================== FAILURES =================================== +E AssertionError: usage: amplifier-work-tracker [-h] + {doctor,new,remove,rename,move,add,instances,status,list,claim,custody,reap,resolve,unclaim,edit,defer,block,dep,notify,update,serve,setup-tls,web,service} + ... + amplifier-work-tracker: error: argument cmd: invalid choice: 'reopen' (choose from doctor, new, remove, rename, move, add, instances, status, list, claim, custody, reap, resolve, unclaim, edit, defer, block, dep, notify, update, serve, setup-tls, web, service) + + assert 2 == 0 + + where 2 = CompletedProcess(args=['/home/bkrabach/dev/hw-model-performance/lanes/f5c-work-tracker-reopen/amplifier-work-tracker/....t, claim, custody, reap, resolve, unclaim, edit, defer, block, dep, notify, update, serve, setup-tls, web, service)\n").returncode +---------------------------- Captured stdout setup ----------------------------- +Starting server with Config HP="127.0.0.1:37153"|T="28800000"|R="false"|L="info" +---------------------------- Captured stderr setup ----------------------------- +time="2026-09-02T20:22:41-07:00" level=info msg="Creating root@localhost superuser" +time="2026-09-02T20:22:41-07:00" level=info msg="Server ready. Accepting connections." +time="2026-09-02T20:22:41-07:00" level=warning msg="secure_file_priv is set to \"\", which is insecure." +time="2026-09-02T20:22:41-07:00" level=warning msg="Any user with GRANT FILE privileges will be able to read any file which the sql-server process can read." +time="2026-09-02T20:22:41-07:00" level=warning msg="Please consider restarting the server with secure_file_priv set to a safe (or non-existent) directory." +time="2026-09-02T20:22:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1 +time="2026-09-02T20:22:41-07:00" level=info msg=ConnectionClosed connectionID=1 +----------------------------- Captured stdout call ----------------------------- + +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:22:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2 +time="2026-09-02T20:22:41-07:00" level=info msg=ConnectionClosed connectionID=2 +time="2026-09-02T20:22:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=3 +time="2026-09-02T20:22:41-07:00" level=info msg=ConnectionClosed connectionID=3 +time="2026-09-02T20:22:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=4 +time="2026-09-02T20:22:41-07:00" level=info msg=ConnectionClosed connectionID=4 +time="2026-09-02T20:22:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=5 +time="2026-09-02T20:22:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=6 +time="2026-09-02T20:22:41-07:00" level=info msg=ConnectionClosed connectionID=5 +time="2026-09-02T20:22:41-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:41.783276953 -0700 PDT m=+0.581538296" connectionDb=projf2ef3bd3d655 connectionID=6 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:41.784767973 -0700 PDT m=+0.583029316" +time="2026-09-02T20:22:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=7 +time="2026-09-02T20:22:41-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:41.785214067 -0700 PDT m=+0.583475410" connectionDb=projf2ef3bd3d655 connectionID=7 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:41.785922033 -0700 PDT m=+0.584183376" +time="2026-09-02T20:22:41-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:41.785214067 -0700 PDT m=+0.583475410" connectionDb=projf2ef3bd3d655 connectionID=7 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:41.787149966 -0700 PDT m=+0.585411357" +time="2026-09-02T20:22:41-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:41.785214067 -0700 PDT m=+0.583475410" connectionDb=projf2ef3bd3d655 connectionID=7 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:41.789761047 -0700 PDT m=+0.588022390" +time="2026-09-02T20:22:43-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:41.785214067 -0700 PDT m=+0.583475410" connectionDb=projf2ef3bd3d655 connectionID=7 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:22:43.605614825 -0700 PDT m=+2.403876200" +time="2026-09-02T20:22:44-07:00" level=info msg=ConnectionClosed connectionID=7 +time="2026-09-02T20:22:44-07:00" level=info msg=ConnectionClosed connectionID=6 +time="2026-09-02T20:22:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=8 +time="2026-09-02T20:22:44-07:00" level=info msg=ConnectionClosed connectionID=8 +time="2026-09-02T20:22:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=9 +time="2026-09-02T20:22:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=10 +time="2026-09-02T20:22:44-07:00" level=info msg=ConnectionClosed connectionID=9 +time="2026-09-02T20:22:44-07:00" level=info msg=ConnectionClosed connectionID=10 +time="2026-09-02T20:22:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=11 +time="2026-09-02T20:22:44-07:00" level=info msg=ConnectionClosed connectionID=11 +time="2026-09-02T20:22:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=12 +time="2026-09-02T20:22:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=13 +time="2026-09-02T20:22:44-07:00" level=info msg=ConnectionClosed connectionID=12 +time="2026-09-02T20:22:44-07:00" level=info msg=ConnectionClosed connectionID=13 +time="2026-09-02T20:22:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=14 +time="2026-09-02T20:22:44-07:00" level=info msg=ConnectionClosed connectionID=14 +time="2026-09-02T20:22:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=15 +time="2026-09-02T20:22:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=16 +time="2026-09-02T20:22:44-07:00" level=info msg=ConnectionClosed connectionID=15 +time="2026-09-02T20:22:44-07:00" level=info msg=ConnectionClosed connectionID=16 +time="2026-09-02T20:22:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=17 +time="2026-09-02T20:22:44-07:00" level=info msg=ConnectionClosed connectionID=17 +time="2026-09-02T20:22:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=18 +time="2026-09-02T20:22:44-07:00" level=info msg=ConnectionClosed connectionID=18 +time="2026-09-02T20:22:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=19 +time="2026-09-02T20:22:44-07:00" level=info msg=ConnectionClosed connectionID=19 +time="2026-09-02T20:22:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=20 +time="2026-09-02T20:22:44-07:00" level=info msg=ConnectionClosed connectionID=20 +time="2026-09-02T20:22:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=21 +time="2026-09-02T20:22:45-07:00" level=info msg=ConnectionClosed connectionID=21 +time="2026-09-02T20:22:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=22 +time="2026-09-02T20:22:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=23 +time="2026-09-02T20:22:45-07:00" level=info msg=ConnectionClosed connectionID=22 +time="2026-09-02T20:22:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=24 +time="2026-09-02T20:22:45-07:00" level=info msg=ConnectionClosed connectionID=24 +time="2026-09-02T20:22:45-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:45.115906264 -0700 PDT m=+3.914167591" connectionDb=projf2ef3bd3d655 connectionID=23 error="backup 'backup_export' not found" queryTime="2026-09-02 20:22:45.228569078 -0700 PDT m=+4.026830437" +time="2026-09-02T20:22:45-07:00" level=info msg=ConnectionClosed connectionID=23 +time="2026-09-02T20:22:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=25 +time="2026-09-02T20:22:45-07:00" level=info msg=ConnectionClosed connectionID=25 +time="2026-09-02T20:22:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=26 +time="2026-09-02T20:22:45-07:00" level=info msg=ConnectionClosed connectionID=26 +time="2026-09-02T20:22:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=27 +time="2026-09-02T20:22:45-07:00" level=info msg=ConnectionClosed connectionID=27 +time="2026-09-02T20:22:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=28 +time="2026-09-02T20:22:45-07:00" level=info msg=ConnectionClosed connectionID=28 +time="2026-09-02T20:22:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=29 +time="2026-09-02T20:22:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=30 +time="2026-09-02T20:22:45-07:00" level=info msg=ConnectionClosed connectionID=29 +time="2026-09-02T20:22:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=31 +time="2026-09-02T20:22:45-07:00" level=info msg=ConnectionClosed connectionID=31 +time="2026-09-02T20:22:45-07:00" level=info msg=ConnectionClosed connectionID=30 +time="2026-09-02T20:22:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=32 +time="2026-09-02T20:22:45-07:00" level=info msg=ConnectionClosed connectionID=32 +time="2026-09-02T20:22:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=33 +time="2026-09-02T20:22:45-07:00" level=info msg=ConnectionClosed connectionID=33 +time="2026-09-02T20:22:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=34 +time="2026-09-02T20:22:45-07:00" level=info msg=ConnectionClosed connectionID=34 +time="2026-09-02T20:22:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=35 +time="2026-09-02T20:22:46-07:00" level=info msg=ConnectionClosed connectionID=35 +time="2026-09-02T20:22:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=36 +time="2026-09-02T20:22:46-07:00" level=info msg=ConnectionClosed connectionID=36 +/tmp/f5c-before/tests/cli/test_cli_reopen.py:62: AssertionError: usage: amplifier-work-tracker [-h] +E AssertionError: usage: amplifier-work-tracker [-h] + {doctor,new,remove,rename,move,add,instances,status,list,claim,custody,reap,resolve,unclaim,edit,defer,block,dep,notify,update,serve,setup-tls,web,service} + ... + amplifier-work-tracker: error: argument cmd: invalid choice: 'reopen' (choose from doctor, new, remove, rename, move, add, instances, status, list, claim, custody, reap, resolve, unclaim, edit, defer, block, dep, notify, update, serve, setup-tls, web, service) + + assert 2 == 0 + + where 2 = CompletedProcess(args=['/home/bkrabach/dev/hw-model-performance/lanes/f5c-work-tracker-reopen/amplifier-work-tracker/....t, claim, custody, reap, resolve, unclaim, edit, defer, block, dep, notify, update, serve, setup-tls, web, service)\n").returncode +----------------------------- Captured stdout call ----------------------------- + +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:22:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=38 +time="2026-09-02T20:22:46-07:00" level=info msg=ConnectionClosed connectionID=38 +time="2026-09-02T20:22:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=39 +time="2026-09-02T20:22:46-07:00" level=info msg=ConnectionClosed connectionID=39 +time="2026-09-02T20:22:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=40 +time="2026-09-02T20:22:46-07:00" level=info msg=ConnectionClosed connectionID=40 +time="2026-09-02T20:22:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=41 +time="2026-09-02T20:22:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=42 +time="2026-09-02T20:22:46-07:00" level=info msg=ConnectionClosed connectionID=41 +time="2026-09-02T20:22:46-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:46.732428327 -0700 PDT m=+5.530689670" connectionDb=projded72c04b68c connectionID=42 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:46.733692595 -0700 PDT m=+5.531953938" +time="2026-09-02T20:22:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=43 +time="2026-09-02T20:22:46-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:46.734582929 -0700 PDT m=+5.532844288" connectionDb=projded72c04b68c connectionID=43 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:46.735531902 -0700 PDT m=+5.533793245" +time="2026-09-02T20:22:46-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:46.734582929 -0700 PDT m=+5.532844288" connectionDb=projded72c04b68c connectionID=43 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:46.737024826 -0700 PDT m=+5.535286185" +time="2026-09-02T20:22:46-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:46.734582929 -0700 PDT m=+5.532844288" connectionDb=projded72c04b68c connectionID=43 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:46.738551958 -0700 PDT m=+5.536813285" +time="2026-09-02T20:22:48-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:46.734582929 -0700 PDT m=+5.532844288" connectionDb=projded72c04b68c connectionID=43 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:22:48.635885084 -0700 PDT m=+7.434146443" +time="2026-09-02T20:22:49-07:00" level=info msg=ConnectionClosed connectionID=43 +time="2026-09-02T20:22:49-07:00" level=info msg=ConnectionClosed connectionID=42 +time="2026-09-02T20:22:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=44 +time="2026-09-02T20:22:49-07:00" level=info msg=ConnectionClosed connectionID=44 +time="2026-09-02T20:22:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=45 +time="2026-09-02T20:22:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=46 +time="2026-09-02T20:22:49-07:00" level=info msg=ConnectionClosed connectionID=45 +time="2026-09-02T20:22:49-07:00" level=info msg=ConnectionClosed connectionID=46 +time="2026-09-02T20:22:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=47 +time="2026-09-02T20:22:49-07:00" level=info msg=ConnectionClosed connectionID=47 +time="2026-09-02T20:22:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=48 +time="2026-09-02T20:22:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=49 +time="2026-09-02T20:22:49-07:00" level=info msg=ConnectionClosed connectionID=48 +time="2026-09-02T20:22:49-07:00" level=info msg=ConnectionClosed connectionID=49 +time="2026-09-02T20:22:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=50 +time="2026-09-02T20:22:49-07:00" level=info msg=ConnectionClosed connectionID=50 +time="2026-09-02T20:22:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=51 +time="2026-09-02T20:22:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=52 +time="2026-09-02T20:22:49-07:00" level=info msg=ConnectionClosed connectionID=51 +time="2026-09-02T20:22:49-07:00" level=info msg=ConnectionClosed connectionID=52 +time="2026-09-02T20:22:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=53 +time="2026-09-02T20:22:49-07:00" level=info msg=ConnectionClosed connectionID=53 +time="2026-09-02T20:22:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=54 +time="2026-09-02T20:22:49-07:00" level=info msg=ConnectionClosed connectionID=54 +time="2026-09-02T20:22:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=55 +time="2026-09-02T20:22:49-07:00" level=info msg=ConnectionClosed connectionID=55 +time="2026-09-02T20:22:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=56 +time="2026-09-02T20:22:49-07:00" level=info msg=ConnectionClosed connectionID=56 +time="2026-09-02T20:22:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=57 +time="2026-09-02T20:22:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=58 +time="2026-09-02T20:22:50-07:00" level=info msg=ConnectionClosed connectionID=57 +time="2026-09-02T20:22:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=59 +time="2026-09-02T20:22:50-07:00" level=info msg=ConnectionClosed connectionID=58 +time="2026-09-02T20:22:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=60 +time="2026-09-02T20:22:50-07:00" level=info msg=ConnectionClosed connectionID=60 +time="2026-09-02T20:22:50-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:50.13679719 -0700 PDT m=+8.935058549" connectionDb=projded72c04b68c connectionID=59 error="backup 'backup_export' not found" queryTime="2026-09-02 20:22:50.249277893 -0700 PDT m=+9.047539236" +time="2026-09-02T20:22:50-07:00" level=info msg=ConnectionClosed connectionID=59 +time="2026-09-02T20:22:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=61 +time="2026-09-02T20:22:50-07:00" level=info msg=ConnectionClosed connectionID=61 +time="2026-09-02T20:22:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=62 +time="2026-09-02T20:22:50-07:00" level=info msg=ConnectionClosed connectionID=62 +time="2026-09-02T20:22:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=63 +time="2026-09-02T20:22:50-07:00" level=info msg=ConnectionClosed connectionID=63 +time="2026-09-02T20:22:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=64 +time="2026-09-02T20:22:50-07:00" level=info msg=ConnectionClosed connectionID=64 +time="2026-09-02T20:22:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=65 +time="2026-09-02T20:22:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=66 +time="2026-09-02T20:22:50-07:00" level=info msg=ConnectionClosed connectionID=65 +time="2026-09-02T20:22:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=67 +time="2026-09-02T20:22:50-07:00" level=info msg=ConnectionClosed connectionID=67 +time="2026-09-02T20:22:50-07:00" level=info msg=ConnectionClosed connectionID=66 +time="2026-09-02T20:22:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=68 +time="2026-09-02T20:22:50-07:00" level=info msg=ConnectionClosed connectionID=68 +time="2026-09-02T20:22:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=69 +time="2026-09-02T20:22:50-07:00" level=info msg=ConnectionClosed connectionID=69 +time="2026-09-02T20:22:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=70 +time="2026-09-02T20:22:50-07:00" level=info msg=ConnectionClosed connectionID=70 +/tmp/f5c-before/tests/cli/test_cli_reopen.py:104: AssertionError: usage: amplifier-work-tracker [-h] +E assert 'nothing to reopen' in ('' + 'usage: amplifier-work-tracker [-h]\n {doctor,new,remove,rename,move,add,instances,status...st, claim, custody, reap, resolve, unclaim, edit, defer, block, dep, notify, update, serve, setup-tls, web, service)\n') + + where '' = CompletedProcess(args=['/home/bkrabach/dev/hw-model-performance/lanes/f5c-work-tracker-reopen/amplifier-work-tracker/....t, claim, custody, reap, resolve, unclaim, edit, defer, block, dep, notify, update, serve, setup-tls, web, service)\n").stdout + + and 'usage: amplifier-work-tracker [-h]\n {doctor,new,remove,rename,move,add,instances,status...st, claim, custody, reap, resolve, unclaim, edit, defer, block, dep, notify, update, serve, setup-tls, web, service)\n' = CompletedProcess(args=['/home/bkrabach/dev/hw-model-performance/lanes/f5c-work-tracker-reopen/amplifier-work-tracker/....t, claim, custody, reap, resolve, unclaim, edit, defer, block, dep, notify, update, serve, setup-tls, web, service)\n").stderr +----------------------------- Captured stdout call ----------------------------- + +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:22:51-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=72 +time="2026-09-02T20:22:51-07:00" level=info msg=ConnectionClosed connectionID=72 +time="2026-09-02T20:22:51-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=73 +time="2026-09-02T20:22:51-07:00" level=info msg=ConnectionClosed connectionID=73 +time="2026-09-02T20:22:51-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=74 +time="2026-09-02T20:22:51-07:00" level=info msg=ConnectionClosed connectionID=74 +time="2026-09-02T20:22:51-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=75 +time="2026-09-02T20:22:51-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=76 +time="2026-09-02T20:22:51-07:00" level=info msg=ConnectionClosed connectionID=75 +time="2026-09-02T20:22:51-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:51.514363102 -0700 PDT m=+10.312624477" connectionDb=proj0881e3f8813b connectionID=76 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:51.515774715 -0700 PDT m=+10.314036058" +time="2026-09-02T20:22:51-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=77 +time="2026-09-02T20:22:51-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:51.516180761 -0700 PDT m=+10.314442120" connectionDb=proj0881e3f8813b connectionID=77 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:51.517085719 -0700 PDT m=+10.315347062" +time="2026-09-02T20:22:51-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:51.516180761 -0700 PDT m=+10.314442120" connectionDb=proj0881e3f8813b connectionID=77 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:51.518326708 -0700 PDT m=+10.316588035" +time="2026-09-02T20:22:51-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:51.516180761 -0700 PDT m=+10.314442120" connectionDb=proj0881e3f8813b connectionID=77 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:51.519707488 -0700 PDT m=+10.317968831" +time="2026-09-02T20:22:53-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:51.516180761 -0700 PDT m=+10.314442120" connectionDb=proj0881e3f8813b connectionID=77 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:22:53.281511591 -0700 PDT m=+12.079772918" +time="2026-09-02T20:22:53-07:00" level=info msg=ConnectionClosed connectionID=77 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=76 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=78 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=78 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=79 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=80 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=79 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=80 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=81 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=81 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=82 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=83 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=82 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=83 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=84 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=84 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=85 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=86 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=85 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=86 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=87 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=87 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=88 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=88 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=89 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=89 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=90 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=90 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=91 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=91 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=92 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=93 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=92 +time="2026-09-02T20:22:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=94 +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=94 +time="2026-09-02T20:22:54-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:54.767894985 -0700 PDT m=+13.566156344" connectionDb=proj0881e3f8813b connectionID=93 error="backup 'backup_export' not found" queryTime="2026-09-02 20:22:54.875027206 -0700 PDT m=+13.673288549" +time="2026-09-02T20:22:54-07:00" level=info msg=ConnectionClosed connectionID=93 +/tmp/f5c-before/tests/cli/test_cli_reopen.py:118: assert 'nothing to reopen' in ('' + 'usage: amplifier-work-tracker [-h]\n {doctor,new,remove,rename,move,add,instances,status...st, claim, custody, reap, resolve, unclaim, edit, defer, block, dep, notify, update, serve, setup-tls, web, service)\n') +E AssertionError: { + "resolved": "projd9f52606fd24-4t8", + "resolution": "the original resolution" + } + + assert 0 != 0 + + where 0 = CompletedProcess(args=['/home/bkrabach/dev/hw-model-performance/lanes/f5c-work-tracker-reopen/amplifier-work-tracker/....rncode=0, stdout='{\n "resolved": "projd9f52606fd24-4t8",\n "resolution": "the original resolution"\n}\n', stderr='').returncode +----------------------------- Captured stdout call ----------------------------- + +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:22:55-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=96 +time="2026-09-02T20:22:55-07:00" level=info msg=ConnectionClosed connectionID=96 +time="2026-09-02T20:22:55-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=97 +time="2026-09-02T20:22:55-07:00" level=info msg=ConnectionClosed connectionID=97 +time="2026-09-02T20:22:55-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=98 +time="2026-09-02T20:22:55-07:00" level=info msg=ConnectionClosed connectionID=98 +time="2026-09-02T20:22:55-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=99 +time="2026-09-02T20:22:55-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=100 +time="2026-09-02T20:22:55-07:00" level=info msg=ConnectionClosed connectionID=99 +time="2026-09-02T20:22:55-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:55.612579975 -0700 PDT m=+14.410841350" connectionDb=projd9f52606fd24 connectionID=100 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:55.613652644 -0700 PDT m=+14.411913987" +time="2026-09-02T20:22:55-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=101 +time="2026-09-02T20:22:55-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:55.614110579 -0700 PDT m=+14.412371922" connectionDb=projd9f52606fd24 connectionID=101 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:55.61497856 -0700 PDT m=+14.413239903" +time="2026-09-02T20:22:55-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:55.614110579 -0700 PDT m=+14.412371922" connectionDb=projd9f52606fd24 connectionID=101 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:55.616321725 -0700 PDT m=+14.414583068" +time="2026-09-02T20:22:55-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:55.614110579 -0700 PDT m=+14.412371922" connectionDb=projd9f52606fd24 connectionID=101 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:55.617704857 -0700 PDT m=+14.415966200" +time="2026-09-02T20:22:57-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:55.614110579 -0700 PDT m=+14.412371922" connectionDb=projd9f52606fd24 connectionID=101 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:22:57.529040971 -0700 PDT m=+16.327302314" +time="2026-09-02T20:22:58-07:00" level=info msg=ConnectionClosed connectionID=101 +time="2026-09-02T20:22:58-07:00" level=info msg=ConnectionClosed connectionID=100 +time="2026-09-02T20:22:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=102 +time="2026-09-02T20:22:58-07:00" level=info msg=ConnectionClosed connectionID=102 +time="2026-09-02T20:22:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=103 +time="2026-09-02T20:22:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=104 +time="2026-09-02T20:22:58-07:00" level=info msg=ConnectionClosed connectionID=103 +time="2026-09-02T20:22:58-07:00" level=info msg=ConnectionClosed connectionID=104 +time="2026-09-02T20:22:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=105 +time="2026-09-02T20:22:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=106 +time="2026-09-02T20:22:58-07:00" level=info msg=ConnectionClosed connectionID=105 +time="2026-09-02T20:22:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=107 +time="2026-09-02T20:22:58-07:00" level=info msg=ConnectionClosed connectionID=106 +time="2026-09-02T20:22:58-07:00" level=info msg=ConnectionClosed connectionID=107 +time="2026-09-02T20:22:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=108 +time="2026-09-02T20:22:58-07:00" level=info msg=ConnectionClosed connectionID=108 +time="2026-09-02T20:22:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=109 +time="2026-09-02T20:22:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=110 +time="2026-09-02T20:22:58-07:00" level=info msg=ConnectionClosed connectionID=109 +time="2026-09-02T20:22:58-07:00" level=info msg=ConnectionClosed connectionID=110 +time="2026-09-02T20:22:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=111 +time="2026-09-02T20:22:58-07:00" level=info msg=ConnectionClosed connectionID=111 +time="2026-09-02T20:22:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=112 +time="2026-09-02T20:22:58-07:00" level=info msg=ConnectionClosed connectionID=112 +time="2026-09-02T20:22:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=113 +time="2026-09-02T20:22:58-07:00" level=info msg=ConnectionClosed connectionID=113 +time="2026-09-02T20:22:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=114 +time="2026-09-02T20:22:58-07:00" level=info msg=ConnectionClosed connectionID=114 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=115 +time="2026-09-02T20:22:59-07:00" level=info msg=ConnectionClosed connectionID=115 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=116 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=117 +time="2026-09-02T20:22:59-07:00" level=info msg=ConnectionClosed connectionID=116 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=118 +time="2026-09-02T20:22:59-07:00" level=info msg=ConnectionClosed connectionID=118 +time="2026-09-02T20:22:59-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:59.030153334 -0700 PDT m=+17.828414677" connectionDb=projd9f52606fd24 connectionID=117 error="backup 'backup_export' not found" queryTime="2026-09-02 20:22:59.173142211 -0700 PDT m=+17.971403586" +time="2026-09-02T20:22:59-07:00" level=info msg=ConnectionClosed connectionID=117 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=119 +time="2026-09-02T20:22:59-07:00" level=info msg=ConnectionClosed connectionID=119 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=120 +time="2026-09-02T20:22:59-07:00" level=info msg=ConnectionClosed connectionID=120 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=121 +time="2026-09-02T20:22:59-07:00" level=info msg=ConnectionClosed connectionID=121 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=122 +time="2026-09-02T20:22:59-07:00" level=info msg=ConnectionClosed connectionID=122 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=123 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=124 +time="2026-09-02T20:22:59-07:00" level=info msg=ConnectionClosed connectionID=123 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=125 +time="2026-09-02T20:22:59-07:00" level=info msg=ConnectionClosed connectionID=125 +time="2026-09-02T20:22:59-07:00" level=info msg=ConnectionClosed connectionID=124 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=126 +time="2026-09-02T20:22:59-07:00" level=info msg=ConnectionClosed connectionID=126 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=127 +time="2026-09-02T20:22:59-07:00" level=info msg=ConnectionClosed connectionID=127 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=128 +time="2026-09-02T20:22:59-07:00" level=info msg=ConnectionClosed connectionID=128 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=129 +time="2026-09-02T20:22:59-07:00" level=info msg=ConnectionClosed connectionID=129 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=130 +time="2026-09-02T20:22:59-07:00" level=info msg=ConnectionClosed connectionID=130 +time="2026-09-02T20:22:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=131 +time="2026-09-02T20:23:00-07:00" level=info msg=ConnectionClosed connectionID=131 +time="2026-09-02T20:23:00-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=132 +time="2026-09-02T20:23:00-07:00" level=info msg=ConnectionClosed connectionID=132 +time="2026-09-02T20:23:00-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=133 +time="2026-09-02T20:23:00-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=134 +time="2026-09-02T20:23:00-07:00" level=info msg=ConnectionClosed connectionID=133 +time="2026-09-02T20:23:00-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=135 +time="2026-09-02T20:23:00-07:00" level=info msg=ConnectionClosed connectionID=135 +time="2026-09-02T20:23:00-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:23:00.152092021 -0700 PDT m=+18.950353380" connectionDb=projd9f52606fd24 connectionID=134 error="nothing to commit" queryTime="2026-09-02 20:23:00.208442653 -0700 PDT m=+19.006704012" +time="2026-09-02T20:23:00-07:00" level=info msg=ConnectionClosed connectionID=134 +time="2026-09-02T20:23:00-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=136 +time="2026-09-02T20:23:00-07:00" level=info msg=ConnectionClosed connectionID=136 +time="2026-09-02T20:23:00-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=137 +time="2026-09-02T20:23:00-07:00" level=info msg=ConnectionClosed connectionID=137 +time="2026-09-02T20:23:00-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=138 +time="2026-09-02T20:23:00-07:00" level=info msg=ConnectionClosed connectionID=138 +/tmp/f5c-before/tests/cli/test_cli_reopen.py:147: AssertionError: { +E KeyError: 'idempotent' +----------------------------- Captured stdout call ----------------------------- + +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:23:00-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=140 +time="2026-09-02T20:23:00-07:00" level=info msg=ConnectionClosed connectionID=140 +time="2026-09-02T20:23:00-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=141 +time="2026-09-02T20:23:00-07:00" level=info msg=ConnectionClosed connectionID=141 +time="2026-09-02T20:23:00-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=142 +time="2026-09-02T20:23:00-07:00" level=info msg=ConnectionClosed connectionID=142 +time="2026-09-02T20:23:00-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=143 +time="2026-09-02T20:23:00-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=144 +time="2026-09-02T20:23:00-07:00" level=info msg=ConnectionClosed connectionID=143 +time="2026-09-02T20:23:00-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:23:00.923453579 -0700 PDT m=+19.721714906" connectionDb=projaa62155c5f01 connectionID=144 error="table not found: schema_migrations" queryTime="2026-09-02 20:23:00.924376312 -0700 PDT m=+19.722637655" +time="2026-09-02T20:23:00-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=145 +time="2026-09-02T20:23:00-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:23:00.924700983 -0700 PDT m=+19.722962342" connectionDb=projaa62155c5f01 connectionID=145 error="table not found: schema_migrations" queryTime="2026-09-02 20:23:00.925507413 -0700 PDT m=+19.723768772" +time="2026-09-02T20:23:00-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:23:00.924700983 -0700 PDT m=+19.722962342" connectionDb=projaa62155c5f01 connectionID=145 error="table not found: schema_migrations" queryTime="2026-09-02 20:23:00.926700674 -0700 PDT m=+19.724962017" +time="2026-09-02T20:23:00-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:23:00.924700983 -0700 PDT m=+19.722962342" connectionDb=projaa62155c5f01 connectionID=145 error="table not found: schema_migrations" queryTime="2026-09-02 20:23:00.928282958 -0700 PDT m=+19.726544317" +time="2026-09-02T20:23:02-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:23:00.924700983 -0700 PDT m=+19.722962342" connectionDb=projaa62155c5f01 connectionID=145 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:23:02.804699216 -0700 PDT m=+21.602960559" +time="2026-09-02T20:23:03-07:00" level=info msg=ConnectionClosed connectionID=145 +time="2026-09-02T20:23:03-07:00" level=info msg=ConnectionClosed connectionID=144 +time="2026-09-02T20:23:03-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=146 +time="2026-09-02T20:23:03-07:00" level=info msg=ConnectionClosed connectionID=146 +time="2026-09-02T20:23:03-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=147 +time="2026-09-02T20:23:03-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=148 +time="2026-09-02T20:23:03-07:00" level=info msg=ConnectionClosed connectionID=147 +time="2026-09-02T20:23:03-07:00" level=info msg=ConnectionClosed connectionID=148 +time="2026-09-02T20:23:03-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=149 +time="2026-09-02T20:23:03-07:00" level=info msg=ConnectionClosed connectionID=149 +time="2026-09-02T20:23:03-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=150 +time="2026-09-02T20:23:03-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=151 +time="2026-09-02T20:23:03-07:00" level=info msg=ConnectionClosed connectionID=150 +time="2026-09-02T20:23:03-07:00" level=info msg=ConnectionClosed connectionID=151 +time="2026-09-02T20:23:03-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=152 +time="2026-09-02T20:23:03-07:00" level=info msg=ConnectionClosed connectionID=152 +time="2026-09-02T20:23:03-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=153 +time="2026-09-02T20:23:03-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=154 +time="2026-09-02T20:23:03-07:00" level=info msg=ConnectionClosed connectionID=153 +time="2026-09-02T20:23:03-07:00" level=info msg=ConnectionClosed connectionID=154 +time="2026-09-02T20:23:03-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=155 +time="2026-09-02T20:23:03-07:00" level=info msg=ConnectionClosed connectionID=155 +time="2026-09-02T20:23:03-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=156 +time="2026-09-02T20:23:03-07:00" level=info msg=ConnectionClosed connectionID=156 +time="2026-09-02T20:23:03-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=157 +time="2026-09-02T20:23:03-07:00" level=info msg=ConnectionClosed connectionID=157 +time="2026-09-02T20:23:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=158 +time="2026-09-02T20:23:04-07:00" level=info msg=ConnectionClosed connectionID=158 +time="2026-09-02T20:23:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=159 +time="2026-09-02T20:23:04-07:00" level=info msg=ConnectionClosed connectionID=159 +time="2026-09-02T20:23:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=160 +time="2026-09-02T20:23:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=161 +time="2026-09-02T20:23:04-07:00" level=info msg=ConnectionClosed connectionID=160 +time="2026-09-02T20:23:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=162 +time="2026-09-02T20:23:04-07:00" level=info msg=ConnectionClosed connectionID=162 +time="2026-09-02T20:23:04-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:23:04.282685819 -0700 PDT m=+23.080947162" connectionDb=projaa62155c5f01 connectionID=161 error="backup 'backup_export' not found" queryTime="2026-09-02 20:23:04.384117512 -0700 PDT m=+23.182378871" +time="2026-09-02T20:23:04-07:00" level=info msg=ConnectionClosed connectionID=161 +time="2026-09-02T20:23:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=163 +time="2026-09-02T20:23:04-07:00" level=info msg=ConnectionClosed connectionID=163 +time="2026-09-02T20:23:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=164 +time="2026-09-02T20:23:04-07:00" level=info msg=ConnectionClosed connectionID=164 +time="2026-09-02T20:23:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=165 +time="2026-09-02T20:23:04-07:00" level=info msg=ConnectionClosed connectionID=165 +time="2026-09-02T20:23:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=166 +time="2026-09-02T20:23:04-07:00" level=info msg=ConnectionClosed connectionID=166 +time="2026-09-02T20:23:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=167 +time="2026-09-02T20:23:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=168 +time="2026-09-02T20:23:04-07:00" level=info msg=ConnectionClosed connectionID=167 +time="2026-09-02T20:23:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=169 +time="2026-09-02T20:23:04-07:00" level=info msg=ConnectionClosed connectionID=169 +time="2026-09-02T20:23:04-07:00" level=info msg=ConnectionClosed connectionID=168 +time="2026-09-02T20:23:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=170 +time="2026-09-02T20:23:04-07:00" level=info msg=ConnectionClosed connectionID=170 +time="2026-09-02T20:23:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=171 +time="2026-09-02T20:23:04-07:00" level=info msg=ConnectionClosed connectionID=171 +time="2026-09-02T20:23:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=172 +time="2026-09-02T20:23:05-07:00" level=info msg=ConnectionClosed connectionID=172 +time="2026-09-02T20:23:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=173 +time="2026-09-02T20:23:05-07:00" level=info msg=ConnectionClosed connectionID=173 +time="2026-09-02T20:23:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=174 +time="2026-09-02T20:23:05-07:00" level=info msg=ConnectionClosed connectionID=174 +time="2026-09-02T20:23:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=175 +time="2026-09-02T20:23:05-07:00" level=info msg=ConnectionClosed connectionID=175 +time="2026-09-02T20:23:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=176 +time="2026-09-02T20:23:05-07:00" level=info msg=ConnectionClosed connectionID=176 +time="2026-09-02T20:23:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=177 +time="2026-09-02T20:23:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=178 +time="2026-09-02T20:23:05-07:00" level=info msg=ConnectionClosed connectionID=177 +time="2026-09-02T20:23:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=179 +time="2026-09-02T20:23:05-07:00" level=info msg=ConnectionClosed connectionID=179 +time="2026-09-02T20:23:05-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:23:05.368895788 -0700 PDT m=+24.167157131" connectionDb=projaa62155c5f01 connectionID=178 error="nothing to commit" queryTime="2026-09-02 20:23:05.431074819 -0700 PDT m=+24.229336162" +time="2026-09-02T20:23:05-07:00" level=info msg=ConnectionClosed connectionID=178 +time="2026-09-02T20:23:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=180 +time="2026-09-02T20:23:05-07:00" level=info msg=ConnectionClosed connectionID=180 +time="2026-09-02T20:23:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=181 +time="2026-09-02T20:23:05-07:00" level=info msg=ConnectionClosed connectionID=181 +time="2026-09-02T20:23:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=182 +time="2026-09-02T20:23:05-07:00" level=info msg=ConnectionClosed connectionID=182 +/tmp/f5c-before/tests/cli/test_cli_reopen.py:172: KeyError: 'idempotent' +=========================== short test summary info ============================ +FAILED tests/cli/test_cli_reopen.py::test_reopen_then_correct_end_to_end - As... +FAILED tests/cli/test_cli_reopen.py::test_reopen_with_claim_flag_claims_the_item +FAILED tests/cli/test_cli_reopen.py::test_reopen_refuses_an_item_that_is_not_resolved +FAILED tests/cli/test_cli_reopen.py::test_resolve_on_a_closed_item_with_different_text_exits_nonzero_and_writes_nothing +FAILED tests/cli/test_cli_reopen.py::test_resolve_with_identical_text_exits_zero_and_says_it_was_idempotent +5 failed in 24.57s diff --git a/docs/lanes/f5c-work-tracker-reopen/evidence/fail-before-integration.log b/docs/lanes/f5c-work-tracker-reopen/evidence/fail-before-integration.log new file mode 100644 index 0000000..a3e397d --- /dev/null +++ b/docs/lanes/f5c-work-tracker-reopen/evidence/fail-before-integration.log @@ -0,0 +1,349 @@ +FFFFFFFF [100%] +=================================== FAILURES =================================== +E AttributeError: 'Beads' object has no attribute 'reopen' +---------------------------- Captured stdout setup ----------------------------- +Starting server with Config HP="127.0.0.1:51305"|T="28800000"|R="false"|L="info" +---------------------------- Captured stderr setup ----------------------------- +time="2026-09-02T20:22:27-07:00" level=info msg="Creating root@localhost superuser" +time="2026-09-02T20:22:27-07:00" level=info msg="Server ready. Accepting connections." +time="2026-09-02T20:22:27-07:00" level=warning msg="secure_file_priv is set to \"\", which is insecure." +time="2026-09-02T20:22:27-07:00" level=warning msg="Any user with GRANT FILE privileges will be able to read any file which the sql-server process can read." +time="2026-09-02T20:22:27-07:00" level=warning msg="Please consider restarting the server with secure_file_priv set to a safe (or non-existent) directory." +time="2026-09-02T20:22:27-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1 +time="2026-09-02T20:22:27-07:00" level=info msg=ConnectionClosed connectionID=1 +time="2026-09-02T20:22:27-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2 +time="2026-09-02T20:22:27-07:00" level=info msg=ConnectionClosed connectionID=2 +time="2026-09-02T20:22:27-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=3 +time="2026-09-02T20:22:27-07:00" level=info msg=ConnectionClosed connectionID=3 +time="2026-09-02T20:22:27-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=4 +time="2026-09-02T20:22:27-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=5 +time="2026-09-02T20:22:27-07:00" level=info msg=ConnectionClosed connectionID=4 +time="2026-09-02T20:22:27-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:27.900647464 -0700 PDT m=+0.447034371" connectionDb=shared6496027e1cc2 connectionID=5 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:27.901991605 -0700 PDT m=+0.448378512" +time="2026-09-02T20:22:27-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=6 +time="2026-09-02T20:22:27-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:27.902524483 -0700 PDT m=+0.448911390" connectionDb=shared6496027e1cc2 connectionID=6 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:27.903528097 -0700 PDT m=+0.449914988" +time="2026-09-02T20:22:27-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:27.902524483 -0700 PDT m=+0.448911390" connectionDb=shared6496027e1cc2 connectionID=6 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:27.905310812 -0700 PDT m=+0.451697719" +time="2026-09-02T20:22:27-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:27.902524483 -0700 PDT m=+0.448911390" connectionDb=shared6496027e1cc2 connectionID=6 error="table not found: schema_migrations" queryTime="2026-09-02 20:22:27.907402054 -0700 PDT m=+0.453788961" +time="2026-09-02T20:22:29-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:27.902524483 -0700 PDT m=+0.448911390" connectionDb=shared6496027e1cc2 connectionID=6 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:22:29.581624996 -0700 PDT m=+2.128011887" +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=6 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=5 +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=7 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=7 +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=8 +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=9 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=8 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=9 +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=10 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=10 +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=11 +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=12 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=11 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=12 +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=13 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=13 +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=14 +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=15 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=14 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=15 +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=16 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=16 +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=17 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=17 +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=18 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=18 +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=19 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=19 +----------------------------- Captured stdout call ----------------------------- + +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=20 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=20 +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=21 +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=22 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=21 +time="2026-09-02T20:22:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=23 +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=23 +time="2026-09-02T20:22:30-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:30.8386908 -0700 PDT m=+3.385077691" connectionDb=shared6496027e1cc2 connectionID=22 error="backup 'backup_export' not found" queryTime="2026-09-02 20:22:30.942288038 -0700 PDT m=+3.488674929" +time="2026-09-02T20:22:30-07:00" level=info msg=ConnectionClosed connectionID=22 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=24 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=24 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=25 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=25 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=26 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=26 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=27 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=27 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=28 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=29 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=28 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=30 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=30 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=29 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=31 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=31 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=32 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=32 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=33 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=33 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=34 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=34 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=35 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=35 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=36 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=36 +/tmp/f5c-before/tests/integration/test_reopen_roundtrip.py:63: AttributeError: 'Beads' object has no attribute 'reopen' +E AttributeError: 'Beads' object has no attribute 'reopen' +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=37 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=37 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=38 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=39 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=38 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=40 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=40 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=39 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=41 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=41 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=42 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=42 +time="2026-09-02T20:22:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=43 +time="2026-09-02T20:22:31-07:00" level=info msg=ConnectionClosed connectionID=43 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=45 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=44 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=44 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=46 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=45 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=47 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=47 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=46 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=48 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=48 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=49 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=49 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=50 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=50 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=51 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=51 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=52 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=52 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=53 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=53 +/tmp/f5c-before/tests/integration/test_reopen_roundtrip.py:113: AttributeError: 'Beads' object has no attribute 'reopen' +E AttributeError: 'Beads' object has no attribute 'reopen' +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=54 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=54 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=55 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=56 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=55 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=57 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=57 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=56 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=58 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=58 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=59 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=59 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=60 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=60 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=61 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=61 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=62 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=62 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=63 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=64 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=63 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=65 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=65 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=64 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=66 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=66 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=67 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=67 +time="2026-09-02T20:22:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=68 +time="2026-09-02T20:22:32-07:00" level=info msg=ConnectionClosed connectionID=68 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=69 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=69 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=70 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=71 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=70 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=72 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=72 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=71 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=73 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=73 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=74 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=74 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=75 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=75 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=76 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=76 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=77 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=77 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=78 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=78 +/tmp/f5c-before/tests/integration/test_reopen_roundtrip.py:134: AttributeError: 'Beads' object has no attribute 'reopen' +E Failed: DID NOT RAISE BeadsError +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=79 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=79 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=80 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=81 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=80 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=82 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=82 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=81 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=83 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=83 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=84 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=84 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=85 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=85 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=86 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=86 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=87 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=88 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=87 +time="2026-09-02T20:22:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=89 +time="2026-09-02T20:22:33-07:00" level=info msg=ConnectionClosed connectionID=89 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=88 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=90 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=90 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=91 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=91 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=92 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=92 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=93 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=93 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=94 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=94 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=95 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=95 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=96 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=96 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=97 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=98 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=97 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=99 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=99 +time="2026-09-02T20:22:34-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:22:34.387677614 -0700 PDT m=+6.934064521" connectionDb=shared6496027e1cc2 connectionID=98 error="nothing to commit" queryTime="2026-09-02 20:22:34.434734462 -0700 PDT m=+6.981121369" +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=98 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=100 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=100 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=101 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=101 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=102 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=102 +/tmp/f5c-before/tests/integration/test_reopen_roundtrip.py:148: Failed: DID NOT RAISE BeadsError +E AttributeError: 'Beads' object has no attribute 'resolve_outcome' +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=103 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=103 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=104 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=105 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=104 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=106 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=106 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=105 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=107 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=107 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=108 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=108 +time="2026-09-02T20:22:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=109 +time="2026-09-02T20:22:34-07:00" level=info msg=ConnectionClosed connectionID=109 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=110 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=110 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=111 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=112 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=111 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=113 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=113 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=112 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=114 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=114 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=115 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=115 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=116 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=116 +/tmp/f5c-before/tests/integration/test_reopen_roundtrip.py:168: AttributeError: 'Beads' object has no attribute 'resolve_outcome' +E AttributeError: 'Beads' object has no attribute 'reopen' +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=117 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=117 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=118 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=119 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=118 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=120 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=120 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=119 +/tmp/f5c-before/tests/integration/test_reopen_roundtrip.py:180: AttributeError: 'Beads' object has no attribute 'reopen' +E AttributeError: 'Beads' object has no attribute 'reopen' +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=121 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=121 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=122 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=123 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=122 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=124 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=124 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=123 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=125 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=125 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=126 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=126 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=127 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=127 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=128 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=128 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=129 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=130 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=129 +time="2026-09-02T20:22:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=131 +time="2026-09-02T20:22:35-07:00" level=info msg=ConnectionClosed connectionID=131 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=130 +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=132 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=132 +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=133 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=133 +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=134 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=134 +/tmp/f5c-before/tests/integration/test_reopen_roundtrip.py:190: AttributeError: 'Beads' object has no attribute 'reopen' +E AttributeError: 'Beads' object has no attribute 'reopen' +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=135 +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=136 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=135 +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=137 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=136 +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=138 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=138 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=137 +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=139 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=139 +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=140 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=140 +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=141 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=141 +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=142 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=142 +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=143 +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=144 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=143 +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=145 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=145 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=144 +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=146 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=146 +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=147 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=147 +time="2026-09-02T20:22:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=148 +time="2026-09-02T20:22:36-07:00" level=info msg=ConnectionClosed connectionID=148 +/tmp/f5c-before/tests/integration/test_reopen_roundtrip.py:215: AttributeError: 'Beads' object has no attribute 'reopen' +=========================== short test summary info ============================ +FAILED tests/integration/test_reopen_roundtrip.py::test_full_correction_cycle_reopen_claim_resolve_reads_back_corrected_text +FAILED tests/integration/test_reopen_roundtrip.py::test_reopen_clears_closed_at_and_the_cost_is_visible +FAILED tests/integration/test_reopen_roundtrip.py::test_reopen_clears_the_stale_assignee_bd_leaves_behind +FAILED tests/integration/test_reopen_roundtrip.py::test_resolve_on_a_closed_item_with_divergent_text_refuses_and_writes_nothing +FAILED tests/integration/test_reopen_roundtrip.py::test_resolve_on_a_closed_item_with_identical_text_is_idempotent +FAILED tests/integration/test_reopen_roundtrip.py::test_reopen_refuses_an_item_that_is_not_resolved +FAILED tests/integration/test_reopen_roundtrip.py::test_reopen_twice_refuses_the_second_time +FAILED tests/integration/test_reopen_roundtrip.py::test_measured_close_reason_disposition_across_a_reopen +8 failed in 9.48s diff --git a/docs/lanes/f5c-work-tracker-reopen/evidence/fail-before-unit.log b/docs/lanes/f5c-work-tracker-reopen/evidence/fail-before-unit.log new file mode 100644 index 0000000..c2a6dfd --- /dev/null +++ b/docs/lanes/f5c-work-tracker-reopen/evidence/fail-before-unit.log @@ -0,0 +1,80 @@ +FFFFFFFFFFFF.FFFFFFFFFF [100%] +=================================== FAILURES =================================== +E AttributeError: module 'amplifier_work_tracker.adapter' has no attribute '_norm_resolution' +---------------------------- Captured stdout setup ----------------------------- +Starting server with Config HP="127.0.0.1:55389"|T="28800000"|R="false"|L="info" +---------------------------- Captured stderr setup ----------------------------- +time="2026-09-02T19:55:42-07:00" level=info msg="Creating root@localhost superuser" +time="2026-09-02T19:55:42-07:00" level=info msg="Server ready. Accepting connections." +time="2026-09-02T19:55:42-07:00" level=warning msg="secure_file_priv is set to \"\", which is insecure." +time="2026-09-02T19:55:42-07:00" level=warning msg="Any user with GRANT FILE privileges will be able to read any file which the sql-server process can read." +time="2026-09-02T19:55:42-07:00" level=warning msg="Please consider restarting the server with secure_file_priv set to a safe (or non-existent) directory." +time="2026-09-02T19:55:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1 +time="2026-09-02T19:55:42-07:00" level=info msg=ConnectionClosed connectionID=1 +/tmp/f5c-before/tests/unit/test_resolve_text_compare.py:36: AttributeError: module 'amplifier_work_tracker.adapter' has no attribute '_norm_resolution' +E AttributeError: module 'amplifier_work_tracker.adapter' has no attribute '_resolution_landed' +/tmp/f5c-before/tests/unit/test_resolve_text_compare.py:45: AttributeError: module 'amplifier_work_tracker.adapter' has no attribute '_resolution_landed' +E AttributeError: module 'amplifier_work_tracker.adapter' has no attribute '_resolution_landed' +/tmp/f5c-before/tests/unit/test_resolve_text_compare.py:51: AttributeError: module 'amplifier_work_tracker.adapter' has no attribute '_resolution_landed' +E AttributeError: module 'amplifier_work_tracker.adapter' has no attribute '_echo_resolution' +/tmp/f5c-before/tests/unit/test_resolve_text_compare.py:58: AttributeError: module 'amplifier_work_tracker.adapter' has no attribute '_echo_resolution' +E AttributeError: module 'amplifier_work_tracker.adapter' has no attribute '_divergent_resolution_error' +/tmp/f5c-before/tests/unit/test_resolve_text_compare.py:66: AttributeError: module 'amplifier_work_tracker.adapter' has no attribute '_divergent_resolution_error' +E AttributeError: 'Beads' object has no attribute 'resolve_outcome' +/tmp/f5c-before/tests/unit/test_resolve_text_compare.py:143: AttributeError: 'Beads' object has no attribute 'resolve_outcome' +E AttributeError: 'Beads' object has no attribute 'resolve_outcome' +/tmp/f5c-before/tests/unit/test_resolve_text_compare.py:159: AttributeError: 'Beads' object has no attribute 'resolve_outcome' +E AttributeError: 'Beads' object has no attribute 'resolve_outcome' +/tmp/f5c-before/tests/unit/test_resolve_text_compare.py:171: AttributeError: 'Beads' object has no attribute 'resolve_outcome' +E AttributeError: 'Beads' object has no attribute 'resolve_outcome' +/tmp/f5c-before/tests/unit/test_resolve_text_compare.py:189: AttributeError: 'Beads' object has no attribute 'resolve_outcome' +E AttributeError: 'Beads' object has no attribute 'resolve_outcome' +/tmp/f5c-before/tests/unit/test_resolve_text_compare.py:204: AttributeError: 'Beads' object has no attribute 'resolve_outcome' +E AttributeError: 'Beads' object has no attribute 'resolve_outcome' +/tmp/f5c-before/tests/unit/test_resolve_text_compare.py:222: AttributeError: 'Beads' object has no attribute 'resolve_outcome' +E AttributeError: 'Beads' object has no attribute 'resolve_outcome' +/tmp/f5c-before/tests/unit/test_resolve_text_compare.py:239: AttributeError: 'Beads' object has no attribute 'resolve_outcome' +E AttributeError: 'Beads' object has no attribute 'reopen' +/tmp/f5c-before/tests/unit/test_reopen_preconditions.py:64: AttributeError: 'Beads' object has no attribute 'reopen' +E AttributeError: 'Beads' object has no attribute 'reopen' +/tmp/f5c-before/tests/unit/test_reopen_preconditions.py:64: AttributeError: 'Beads' object has no attribute 'reopen' +E AttributeError: 'Beads' object has no attribute 'reopen' +/tmp/f5c-before/tests/unit/test_reopen_preconditions.py:64: AttributeError: 'Beads' object has no attribute 'reopen' +E AttributeError: 'Beads' object has no attribute 'reopen' +/tmp/f5c-before/tests/unit/test_reopen_preconditions.py:64: AttributeError: 'Beads' object has no attribute 'reopen' +E AttributeError: 'Beads' object has no attribute 'reopen' +/tmp/f5c-before/tests/unit/test_reopen_preconditions.py:74: AttributeError: 'Beads' object has no attribute 'reopen' +E AttributeError: 'Beads' object has no attribute 'reopen' +/tmp/f5c-before/tests/unit/test_reopen_preconditions.py:74: AttributeError: 'Beads' object has no attribute 'reopen' +E AttributeError: 'Beads' object has no attribute 'reopen' +/tmp/f5c-before/tests/unit/test_reopen_preconditions.py:74: AttributeError: 'Beads' object has no attribute 'reopen' +E AttributeError: 'Beads' object has no attribute 'reopen' +/tmp/f5c-before/tests/unit/test_reopen_preconditions.py:84: AttributeError: 'Beads' object has no attribute 'reopen' +E AttributeError: 'Beads' object has no attribute 'reopen' +/tmp/f5c-before/tests/unit/test_reopen_preconditions.py:105: AttributeError: 'Beads' object has no attribute 'reopen' +E AttributeError: 'Beads' object has no attribute 'reopen' +/tmp/f5c-before/tests/unit/test_reopen_preconditions.py:113: AttributeError: 'Beads' object has no attribute 'reopen' +=========================== short test summary info ============================ +FAILED tests/unit/test_resolve_text_compare.py::test_norm_resolution_unifies_line_endings_and_strips_outer_whitespace +FAILED tests/unit/test_resolve_text_compare.py::test_norm_resolution_keeps_case_and_internal_whitespace_significant +FAILED tests/unit/test_resolve_text_compare.py::test_resolution_landed_is_true_only_for_the_same_text +FAILED tests/unit/test_resolve_text_compare.py::test_echo_resolution_truncates_loudly_never_silently +FAILED tests/unit/test_resolve_text_compare.py::test_divergent_error_message_carries_everything_a_caller_needs +FAILED tests/unit/test_resolve_text_compare.py::test_divergent_text_on_a_closed_item_refuses_and_writes_nothing +FAILED tests/unit/test_resolve_text_compare.py::test_identical_text_on_a_closed_item_is_an_idempotent_success_with_no_write +FAILED tests/unit/test_resolve_text_compare.py::test_resolving_an_open_item_is_unchanged +FAILED tests/unit/test_resolve_text_compare.py::test_post_write_readback_refuses_when_the_stored_text_is_not_ours +FAILED tests/unit/test_resolve_text_compare.py::test_contended_path_reports_success_only_when_our_own_text_landed +FAILED tests/unit/test_resolve_text_compare.py::test_contended_path_raises_when_the_readback_text_is_not_ours +FAILED tests/unit/test_resolve_text_compare.py::test_contended_path_still_reraises_when_the_item_never_closed +FAILED tests/unit/test_reopen_preconditions.py::test_reopen_refuses_anything_that_is_not_resolved[open] +FAILED tests/unit/test_reopen_preconditions.py::test_reopen_refuses_anything_that_is_not_resolved[held] +FAILED tests/unit/test_reopen_preconditions.py::test_reopen_refuses_anything_that_is_not_resolved[blocked] +FAILED tests/unit/test_reopen_preconditions.py::test_reopen_refuses_anything_that_is_not_resolved[deferred] +FAILED tests/unit/test_reopen_preconditions.py::test_reopen_refuses_an_empty_reason_before_reading_anything[] +FAILED tests/unit/test_reopen_preconditions.py::test_reopen_refuses_an_empty_reason_before_reading_anything[ ] +FAILED tests/unit/test_reopen_preconditions.py::test_reopen_refuses_an_empty_reason_before_reading_anything[\n\t ] +FAILED tests/unit/test_reopen_preconditions.py::test_reopen_archives_the_verbatim_previous_record_before_transitioning +FAILED tests/unit/test_reopen_preconditions.py::test_reopen_refuses_to_report_success_if_the_item_is_still_resolved +FAILED tests/unit/test_reopen_preconditions.py::test_reopen_archives_a_blank_previous_resolution_explicitly +22 failed, 1 passed in 0.23s diff --git a/docs/lanes/f5c-work-tracker-reopen/evidence/make-test-full.log b/docs/lanes/f5c-work-tracker-reopen/evidence/make-test-full.log new file mode 100644 index 0000000..a45fd86 --- /dev/null +++ b/docs/lanes/f5c-work-tracker-reopen/evidence/make-test-full.log @@ -0,0 +1,2269 @@ +.venv/bin/python -m pytest tests ledger/checks -v +============================= test session starts ============================== +platform linux -- Python 3.12.13, pytest-9.1.1, pluggy-1.6.0 -- /home/bkrabach/dev/hw-model-performance/lanes/f5c-work-tracker-reopen/amplifier-work-tracker/.venv/bin/python +cachedir: .pytest_cache +rootdir: /home/bkrabach/dev/hw-model-performance/lanes/f5c-work-tracker-reopen/amplifier-work-tracker +configfile: pyproject.toml +plugins: anyio-4.15.0 +collecting ... collected 1193 items + +tests/cli/test_cli_move.py::test_move_end_to_end_via_cli PASSED [ 0%] +tests/cli/test_cli_move.py::test_move_missing_item_fails_loudly PASSED [ 0%] +tests/cli/test_cli_move.py::test_move_held_item_fails_loudly PASSED [ 0%] +tests/cli/test_cli_move.py::test_move_missing_destination_fails_loudly PASSED [ 0%] +tests/cli/test_cli_new_verbs.py::test_edit_amends_fields_via_cli PASSED [ 0%] +tests/cli/test_cli_new_verbs.py::test_edit_merge_into_supersedes_via_cli PASSED [ 0%] +tests/cli/test_cli_new_verbs.py::test_edit_refuses_combining_merge_into_with_fields PASSED [ 0%] +tests/cli/test_cli_new_verbs.py::test_defer_then_clear_via_cli PASSED [ 0%] +tests/cli/test_cli_new_verbs.py::test_defer_without_reason_fails_loudly PASSED [ 0%] +tests/cli/test_cli_new_verbs.py::test_block_then_clear_via_cli PASSED [ 0%] +tests/cli/test_cli_new_verbs.py::test_dep_declares_and_displays_edge_via_cli PASSED [ 0%] +tests/cli/test_cli_new_verbs.py::test_dep_missing_item_fails_loudly PASSED [ 1%] +tests/cli/test_cli_rename.py::test_rename_end_to_end_via_cli PASSED [ 1%] +tests/cli/test_cli_rename.py::test_rename_to_taken_name_fails_loudly PASSED [ 1%] +tests/cli/test_cli_rename.py::test_rename_missing_source_fails_loudly PASSED [ 1%] +tests/cli/test_cli_reopen.py::test_reopen_then_correct_end_to_end PASSED [ 1%] +tests/cli/test_cli_reopen.py::test_reopen_with_claim_flag_claims_the_item PASSED [ 1%] +tests/cli/test_cli_reopen.py::test_reopen_refuses_an_item_that_is_not_resolved PASSED [ 1%] +tests/cli/test_cli_reopen.py::test_resolve_on_a_closed_item_with_different_text_exits_nonzero_and_writes_nothing PASSED [ 1%] +tests/cli/test_cli_reopen.py::test_resolve_with_identical_text_exits_zero_and_says_it_was_idempotent PASSED [ 1%] +tests/cli/test_cli_status.py::test_status_breakdown_matches_manual_count PASSED [ 1%] +tests/cli/test_cli_status.py::test_instances_json_gains_blocked_deferred_resolved_counts PASSED [ 1%] +tests/cli/test_cli_status.py::test_status_on_unknown_project_gives_distinct_error PASSED [ 1%] +tests/cli/test_cli_status.py::test_status_never_mutates_project_state PASSED [ 2%] +tests/cli/test_cli_status.py::test_status_on_project_stuck_creating_reports_creating_not_a_healthy_zero PASSED [ 2%] +tests/cli/test_cli_surface.py::test_help_lists_every_subcommand PASSED [ 2%] +tests/cli/test_cli_surface.py::test_each_subcommand_is_recognized_by_argparse[doctor] PASSED [ 2%] +tests/cli/test_cli_surface.py::test_each_subcommand_is_recognized_by_argparse[new] PASSED [ 2%] +tests/cli/test_cli_surface.py::test_each_subcommand_is_recognized_by_argparse[remove] PASSED [ 2%] +tests/cli/test_cli_surface.py::test_each_subcommand_is_recognized_by_argparse[add] PASSED [ 2%] +tests/cli/test_cli_surface.py::test_each_subcommand_is_recognized_by_argparse[instances] PASSED [ 2%] +tests/cli/test_cli_surface.py::test_each_subcommand_is_recognized_by_argparse[status] PASSED [ 2%] +tests/cli/test_cli_surface.py::test_each_subcommand_is_recognized_by_argparse[list] PASSED [ 2%] +tests/cli/test_cli_surface.py::test_each_subcommand_is_recognized_by_argparse[claim] PASSED [ 2%] +tests/cli/test_cli_surface.py::test_each_subcommand_is_recognized_by_argparse[custody] PASSED [ 2%] +tests/cli/test_cli_surface.py::test_each_subcommand_is_recognized_by_argparse[reap] PASSED [ 3%] +tests/cli/test_cli_surface.py::test_each_subcommand_is_recognized_by_argparse[resolve] PASSED [ 3%] +tests/cli/test_cli_surface.py::test_each_subcommand_is_recognized_by_argparse[notify] PASSED [ 3%] +tests/cli/test_cli_surface.py::test_capabilities_probe_matches_the_installed_bd_binary PASSED [ 3%] +tests/cli/test_cli_surface.py::test_new_rejects_dotted_name_with_nonzero_exit PASSED [ 3%] +tests/cli/test_cli_surface.py::test_new_is_idempotent_on_a_valid_name PASSED [ 3%] +tests/cli/test_cli_surface.py::test_new_reports_created_not_adopted_for_a_genuinely_fresh_project PASSED [ 3%] +tests/cli/test_cli_surface.py::test_new_reports_adoption_loudly_when_directory_gone_but_database_survives PASSED [ 3%] +tests/cli/test_cli_surface.py::test_remove_without_yes_exits_nonzero PASSED [ 3%] +tests/cli/test_cli_surface.py::test_remove_with_yes_drops_both_directory_and_database PASSED [ 3%] +tests/cli/test_cli_surface.py::test_remove_refuses_via_cli_while_an_item_is_held PASSED [ 3%] +tests/cli/test_cli_surface.py::test_remove_of_nonexistent_project_gives_distinct_error PASSED [ 3%] +tests/cli/test_cli_surface.py::test_instances_on_a_fresh_empty_root_exits_zero PASSED [ 4%] +tests/cli/test_cli_surface.py::test_instances_json_is_well_formed PASSED [ 4%] +tests/cli/test_cli_surface.py::test_list_shows_mixed_states_with_id_title_status_holder_resolution PASSED [ 4%] +tests/cli/test_cli_surface.py::test_list_status_filter_returns_only_matching_status PASSED [ 4%] +tests/cli/test_cli_surface.py::test_list_rejects_unknown_status_via_argparse_choices PASSED [ 4%] +tests/cli/test_cli_surface.py::test_list_never_mutates_project_state PASSED [ 4%] +tests/cli/test_cli_surface.py::test_list_on_a_project_with_no_matching_items_exits_zero_with_empty_list PASSED [ 4%] +tests/cli/test_cli_surface.py::test_list_on_nonexistent_project_gives_distinct_error PASSED [ 4%] +tests/cli/test_cli_surface.py::test_list_truncates_and_reports_it_explicitly PASSED [ 4%] +tests/cli/test_cli_surface.py::test_list_dash_dash_id_reads_full_body_without_claiming PASSED [ 4%] +tests/cli/test_cli_surface.py::test_list_dash_dash_id_human_readable_output_includes_body_fields PASSED [ 4%] +tests/cli/test_cli_surface.py::test_list_dash_dash_id_on_nonexistent_item_gives_distinct_error PASSED [ 4%] +tests/cli/test_cli_surface.py::test_list_dash_dash_id_with_id_from_a_different_project_gives_distinct_wrong_project_error PASSED [ 5%] +tests/cli/test_cli_surface.py::test_list_dash_dash_id_never_mutates_the_item PASSED [ 5%] +tests/cli/test_cli_surface.py::test_list_dash_dash_id_ignores_status_and_limit PASSED [ 5%] +tests/cli/test_cli_surface.py::test_add_creates_a_claimable_item_without_needing_lane_vocabulary PASSED [ 5%] +tests/cli/test_cli_surface.py::test_claim_on_empty_queue_exits_3_and_prints_no_error PASSED [ 5%] +tests/cli/test_cli_surface.py::test_claim_dash_dash_id_directs_a_claim_to_a_specific_item PASSED [ 5%] +tests/cli/test_cli_surface.py::test_claim_dash_dash_id_on_an_already_held_item_exits_nonzero_naming_the_holder PASSED [ 5%] +tests/cli/test_cli_surface.py::test_claim_dash_dash_id_on_nonexistent_id_exits_nonzero_with_distinct_error PASSED [ 5%] +tests/cli/test_cli_surface.py::test_claim_then_resolve_then_notify_full_cli_flow PASSED [ 5%] +tests/cli/test_cli_surface.py::test_resolve_by_a_reclaimed_stale_holder_exits_nonzero PASSED [ 5%] +tests/cli/test_cli_surface.py::test_reap_on_a_clean_queue_exits_zero_with_no_error_text PASSED [ 5%] +tests/cli/test_cli_surface.py::test_reap_reclaims_an_item_with_forged_stale_custody PASSED [ 5%] +tests/cli/test_cli_surface.py::test_custody_exits_nonzero_when_watched_pid_is_already_dead PASSED [ 6%] +tests/cli/test_cli_surface.py::test_custody_establishes_and_exits_cleanly_when_watched_pid_dies PASSED [ 6%] +tests/cli/test_cli_surface.py::test_commands_fail_loudly_when_bd_binary_is_entirely_absent[args0] PASSED [ 6%] +tests/cli/test_cli_surface.py::test_commands_fail_loudly_when_bd_binary_is_entirely_absent[args1] PASSED [ 6%] +tests/cli/test_cli_surface.py::test_commands_fail_loudly_when_bd_binary_is_entirely_absent[args2] PASSED [ 6%] +tests/cli/test_cli_surface.py::test_doctor_quick_succeeds_against_the_real_installed_bd FAILED [ 6%] +tests/cli/test_cli_unclaim.py::test_unclaim_releases_held_item_end_to_end PASSED [ 6%] +tests/cli/test_cli_unclaim.py::test_unclaim_sets_no_resolution_unlike_resolve PASSED [ 6%] +tests/cli/test_cli_unclaim.py::test_unclaim_not_held_fails_loudly_and_mutates_nothing PASSED [ 6%] +tests/cli/test_cli_unclaim.py::test_unclaim_missing_item_fails_loudly PASSED [ 6%] +tests/integration/test_blocker_chain_and_activity.py::test_get_with_links_reports_full_blocker_detail PASSED [ 6%] +tests/integration/test_blocker_chain_and_activity.py::test_get_with_links_blocking_clears_once_blocker_resolved PASSED [ 6%] +tests/integration/test_blocker_chain_and_activity.py::test_get_with_links_reports_discovered_from_both_directions PASSED [ 7%] +tests/integration/test_blocker_chain_and_activity.py::test_get_with_links_blocks_inverse_is_present_but_lean PASSED [ 7%] +tests/integration/test_blocker_chain_and_activity.py::test_activity_reports_created_claimed_commented_and_resolved PASSED [ 7%] +tests/integration/test_blocker_chain_and_activity.py::test_activity_on_a_fresh_item_is_just_created PASSED [ 7%] +tests/integration/test_blocker_chain_and_activity.py::test_activity_is_read_only_and_does_not_touch_status_or_holder PASSED [ 7%] +tests/integration/test_contention_hardening.py::test_project_summary_survives_concurrent_writes PASSED [ 7%] +tests/integration/test_contention_hardening.py::test_20_concurrent_resolves_land_cleanly_with_zero_caller_spacing PASSED [ 7%] +tests/integration/test_contention_hardening.py::test_reported_write_failures_never_silently_land PASSED [ 7%] +tests/integration/test_contract_assumptions.py::test_bd_version_is_within_the_supported_window PASSED [ 7%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[capabilities] PASSED [ 7%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[resolve.fenced] PASSED [ 7%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[resolve.divergent_text_refused] PASSED [ 7%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[resolve.identical_text_idempotent] PASSED [ 8%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[reopen.reopens] PASSED [ 8%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[reopen.clears_closed_at] PASSED [ 8%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[reopen.close_reason_disposition] PASSED [ 8%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[reopen.emits_event] PASSED [ 8%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[release.reopens_unresolved] PASSED [ 8%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[claim.subcommand] PASSED [ 8%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[claim.atomic] PASSED [ 8%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[claim.directed_atomic] PASSED [ 8%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[link.nonblocking] PASSED [ 8%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[list.includes_closed] PASSED [ 8%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[list.status_filter_includes_closed] PASSED [ 8%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[show.dependents] PASSED [ 9%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[read.no_mutation] PASSED [ 9%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[resolution.readable] PASSED [ 9%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[timestamps.readable] PASSED [ 9%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[metadata.roundtrip] PASSED [ 9%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[project.name_rules] PASSED [ 9%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[custody.fresh_survives] PASSED [ 9%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[custody.stale_reclaimed] PASSED [ 9%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[custody.idle_not_exempt] PASSED [ 9%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[custody.fenced] PASSED [ 9%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[project.removal] PASSED [ 9%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[project.create_atomic] PASSED [ 9%] +tests/integration/test_contract_assumptions.py::test_contract_assumption_holds[project.creation_state_reporting] PASSED [ 10%] +tests/integration/test_create_related.py::test_create_with_relates_to_records_a_visible_edge PASSED [ 10%] +tests/integration/test_create_related.py::test_create_with_supersedes_records_a_visible_edge PASSED [ 10%] +tests/integration/test_create_related.py::test_create_with_follow_up_of_maps_to_discovered_from PASSED [ 10%] +tests/integration/test_create_related.py::test_create_with_multiple_related_entries_records_all PASSED [ 10%] +tests/integration/test_create_related.py::test_create_refuses_whole_create_on_unknown_relation_kind PASSED [ 10%] +tests/integration/test_create_related.py::test_create_without_related_is_unchanged PASSED [ 10%] +tests/integration/test_defer_block.py::test_defer_moves_status_and_stores_reason PASSED [ 10%] +tests/integration/test_defer_block.py::test_deferred_item_stays_visible_in_default_list_and_by_explicit_status PASSED [ 10%] +tests/integration/test_defer_block.py::test_deferred_item_is_skipped_by_claim_next PASSED [ 10%] +tests/integration/test_defer_block.py::test_undefer_moves_item_back_to_open_and_clears_reason PASSED [ 10%] +tests/integration/test_defer_block.py::test_undefer_refuses_when_not_deferred PASSED [ 10%] +tests/integration/test_defer_block.py::test_defer_refuses_without_a_reason PASSED [ 11%] +tests/integration/test_defer_block.py::test_block_moves_status_and_stores_reason PASSED [ 11%] +tests/integration/test_defer_block.py::test_blocked_item_is_skipped_by_claim_next PASSED [ 11%] +tests/integration/test_defer_block.py::test_unblock_moves_item_back_to_open_and_clears_reason PASSED [ 11%] +tests/integration/test_defer_block.py::test_unblock_refuses_when_not_blocked PASSED [ 11%] +tests/integration/test_defer_block.py::test_defer_and_block_reasons_never_collide PASSED [ 11%] +tests/integration/test_dependency.py::test_add_dependency_creates_edge_visible_via_get_with_links PASSED [ 11%] +tests/integration/test_dependency.py::test_get_readonly_with_links_displays_the_same_edge PASSED [ 11%] +tests/integration/test_dependency.py::test_claim_refuses_naming_the_dependency_created_via_add_dependency PASSED [ 11%] +tests/integration/test_dependency.py::test_resolving_the_blocker_makes_the_blocked_item_claimable PASSED [ 11%] +tests/integration/test_dependency.py::test_add_dependency_with_non_blocking_type_is_not_a_claim_blocker PASSED [ 11%] +tests/integration/test_dependency.py::test_add_dependency_refuses_on_nonexistent_target PASSED [ 11%] +tests/integration/test_directed_claim.py::test_claim_item_succeeds_on_a_free_item PASSED [ 12%] +tests/integration/test_directed_claim.py::test_claim_item_is_idempotent_for_the_same_actor PASSED [ 12%] +tests/integration/test_directed_claim.py::test_claim_item_refuses_when_already_held_by_someone_else PASSED [ 12%] +tests/integration/test_directed_claim.py::test_claim_item_refuses_on_nonexistent_id PASSED [ 12%] +tests/integration/test_directed_claim.py::test_claim_item_refuses_when_blocked_by_an_open_dependency PASSED [ 12%] +tests/integration/test_directed_claim.py::test_claim_item_succeeds_once_the_blocker_is_closed PASSED [ 12%] +tests/integration/test_directed_claim.py::test_claim_next_queue_path_is_unaffected_by_claim_item_existing PASSED [ 12%] +tests/integration/test_gateway_authz.py::test_no_token_is_401 PASSED [ 12%] +tests/integration/test_gateway_authz.py::test_bad_token_is_401 PASSED [ 12%] +tests/integration/test_gateway_authz.py::test_identity_spoof_via_query_param_is_403 PASSED [ 12%] +tests/integration/test_gateway_authz.py::test_identity_spoof_via_body_field_is_403 PASSED [ 12%] +tests/integration/test_gateway_authz.py::test_cross_reporter_read_is_404_not_403 PASSED [ 12%] +tests/integration/test_gateway_authz.py::test_redaction_is_applied_at_the_storage_layer_not_just_the_api_echo PASSED [ 13%] +tests/integration/test_gateway_authz.py::test_reporter_only_sees_their_own_reports_in_the_list_view PASSED [ 13%] +tests/integration/test_gateway_authz.py::test_healthz_requires_no_auth PASSED [ 13%] +tests/integration/test_get_via_sql_equivalence.py::test_get_open_item_matches_old_path_exactly PASSED [ 13%] +tests/integration/test_get_via_sql_equivalence.py::test_get_held_item_matches_old_path_exactly PASSED [ 13%] +tests/integration/test_get_via_sql_equivalence.py::test_get_resolved_item_matches_old_path_exactly PASSED [ 13%] +tests/integration/test_get_via_sql_equivalence.py::test_get_unknown_item_raises_same_way_as_old_path PASSED [ 13%] +tests/integration/test_get_via_sql_equivalence.py::test_get_free_text_with_commas_and_newlines_survives_intact PASSED [ 13%] +tests/integration/test_get_via_sql_equivalence.py::test_get_metadata_dict_round_trips_via_sql_path PASSED [ 13%] +tests/integration/test_get_via_sql_equivalence.py::test_get_priority_is_int_not_string_via_sql_path PASSED [ 13%] +tests/integration/test_get_via_sql_equivalence.py::test_get_via_sql_never_mutates_anything PASSED [ 13%] +tests/integration/test_get_via_sql_equivalence.py::test_get_readonly_real_missing_item_reports_not_found PASSED [ 13%] +tests/integration/test_get_via_sql_equivalence.py::test_get_readonly_real_wrong_project_prefix_reports_mismatch PASSED [ 14%] +tests/integration/test_get_via_sql_equivalence.py::test_get_with_links_still_returns_dependency_graph PASSED [ 14%] +tests/integration/test_item_edit.py::test_edit_item_changes_fields_and_leaves_audit_comment PASSED [ 14%] +tests/integration/test_item_edit.py::test_edit_item_refuses_with_no_fields PASSED [ 14%] +tests/integration/test_item_edit.py::test_edit_item_only_names_fields_that_actually_changed PASSED [ 14%] +tests/integration/test_item_edit.py::test_comment_appends_and_is_readable PASSED [ 14%] +tests/integration/test_item_edit.py::test_supersede_closes_original_with_structural_reference PASSED [ 14%] +tests/integration/test_item_edit.py::test_supersede_refuses_when_replacement_missing PASSED [ 14%] +tests/integration/test_item_move.py::test_move_moves_item_preserves_id_and_body PASSED [ 14%] +tests/integration/test_item_move.py::test_move_refuses_while_item_is_held PASSED [ 14%] +tests/integration/test_item_move.py::test_move_refuses_when_item_missing PASSED [ 14%] +tests/integration/test_item_move.py::test_move_twice_raises_cleanly_the_second_time PASSED [ 15%] +tests/integration/test_item_move.py::test_move_refuses_when_src_missing PASSED [ 15%] +tests/integration/test_item_move.py::test_move_refuses_when_dst_missing PASSED [ 15%] +tests/integration/test_item_move.py::test_move_refuses_when_src_equals_dst PASSED [ 15%] +tests/integration/test_item_move.py::test_move_rejects_invalid_project_names PASSED [ 15%] +tests/integration/test_item_move.py::test_move_refuses_when_item_already_exists_at_destination PASSED [ 15%] +tests/integration/test_item_move.py::test_move_drops_cross_project_dependency_edge PASSED [ 15%] +tests/integration/test_item_move.py::test_move_preserves_dependency_edge_to_non_issue_target PASSED [ 15%] +tests/integration/test_list_via_sql_equivalence.py::test_list_default_matches_old_path_excludes_only_closed PASSED [ 15%] +tests/integration/test_list_via_sql_equivalence.py::test_list_include_resolved_matches_old_path_exactly PASSED [ 15%] +tests/integration/test_list_via_sql_equivalence.py::test_list_ordering_matches_old_path_created_at_desc PASSED [ 15%] +tests/integration/test_list_via_sql_equivalence.py::test_list_ordering_prefers_lower_priority_number_over_creation_order PASSED [ 15%] +tests/integration/test_list_via_sql_equivalence.py::test_list_status_filter_matches_old_path[blocked] PASSED [ 16%] +tests/integration/test_list_via_sql_equivalence.py::test_list_status_filter_matches_old_path[deferred] PASSED [ 16%] +tests/integration/test_list_via_sql_equivalence.py::test_list_status_filter_matches_old_path[held] PASSED [ 16%] +tests/integration/test_list_via_sql_equivalence.py::test_list_status_filter_matches_old_path[open] PASSED [ 16%] +tests/integration/test_list_via_sql_equivalence.py::test_list_status_filter_matches_old_path[resolved] PASSED [ 16%] +tests/integration/test_list_via_sql_equivalence.py::test_list_unknown_status_raises_same_way_as_old_path PASSED [ 16%] +tests/integration/test_list_via_sql_equivalence.py::test_list_lane_filter_matches_old_path PASSED [ 16%] +tests/integration/test_list_via_sql_equivalence.py::test_list_lane_plus_include_resolved_matches_old_path PASSED [ 16%] +tests/integration/test_list_via_sql_equivalence.py::test_list_limit_zero_is_unlimited_like_old_path PASSED [ 16%] +tests/integration/test_list_via_sql_equivalence.py::test_list_explicit_limit_matches_old_path PASSED [ 16%] +tests/integration/test_list_via_sql_equivalence.py::test_list_default_limit_is_50_like_bd PASSED [ 16%] +tests/integration/test_list_via_sql_equivalence.py::test_list_free_text_with_commas_and_newlines_survives_intact PASSED [ 16%] +tests/integration/test_list_via_sql_equivalence.py::test_list_metadata_dict_round_trips_via_sql_path PASSED [ 17%] +tests/integration/test_list_via_sql_equivalence.py::test_list_priority_is_int_not_string_via_sql_path PASSED [ 17%] +tests/integration/test_list_via_sql_equivalence.py::test_list_unset_optional_fields_are_none_not_empty_string PASSED [ 17%] +tests/integration/test_list_via_sql_equivalence.py::test_list_via_sql_never_mutates_anything PASSED [ 17%] +tests/integration/test_list_via_sql_equivalence.py::test_list_on_empty_project_returns_empty_not_an_error PASSED [ 17%] +tests/integration/test_no_database_residue.py::test_probe_drops_its_database_on_exit PASSED [ 17%] +tests/integration/test_no_database_residue.py::test_probe_drops_databases_registered_by_a_check PASSED [ 17%] +tests/integration/test_no_database_residue.py::test_probe_exit_is_idempotent_over_an_already_dropped_database PASSED [ 17%] +tests/integration/test_no_database_residue.py::test_drop_project_removes_both_halves PASSED [ 17%] +tests/integration/test_no_database_residue.py::test_drop_project_is_a_no_op_for_a_project_that_was_never_created PASSED [ 17%] +tests/integration/test_observatory_aggregates.py::test_velocity_series_zero_fills_and_buckets_by_calendar_day PASSED [ 17%] +tests/integration/test_observatory_aggregates.py::test_velocity_series_reports_real_zero_for_wholly_quiet_project PASSED [ 17%] +tests/integration/test_observatory_aggregates.py::test_velocity_windows_current_vs_previous_and_delta PASSED [ 18%] +tests/integration/test_observatory_aggregates.py::test_velocity_windows_delta_pct_none_when_previous_is_zero PASSED [ 18%] +tests/integration/test_observatory_aggregates.py::test_reopened_count_counts_real_reopen_events PASSED [ 18%] +tests/integration/test_observatory_aggregates.py::test_reopened_count_zero_for_project_with_no_reopens PASSED [ 18%] +tests/integration/test_observatory_aggregates.py::test_reopened_count_also_counts_reopen_via_plain_status_update PASSED [ 18%] +tests/integration/test_observatory_aggregates.py::test_reopened_count_respects_window_boundary PASSED [ 18%] +tests/integration/test_observatory_aggregates.py::test_project_agents_reports_fresh_holder PASSED [ 18%] +tests/integration/test_observatory_aggregates.py::test_project_agents_reports_stale_holder_with_overage PASSED [ 18%] +tests/integration/test_observatory_aggregates.py::test_project_agents_no_custody_record_counts_as_stale_unmeasurable PASSED [ 18%] +tests/integration/test_observatory_aggregates.py::test_project_agents_excludes_unheld_items PASSED [ 18%] +tests/integration/test_observatory_aggregates.py::test_project_agents_sorts_stale_first_then_by_freshness PASSED [ 18%] +tests/integration/test_observatory_aggregates.py::test_agents_snapshot_spans_every_project PASSED [ 18%] +tests/integration/test_observatory_aggregates.py::test_agents_snapshot_from_rows_matches_agents_snapshot PASSED [ 19%] +tests/integration/test_observatory_aggregates.py::test_agent_stats_single_project_counts_resolved_and_held PASSED [ 19%] +tests/integration/test_observatory_aggregates.py::test_agent_stats_resolved_respects_window PASSED [ 19%] +tests/integration/test_observatory_aggregates.py::test_agent_stats_across_whole_workspace PASSED [ 19%] +tests/integration/test_observatory_aggregates.py::test_agent_stats_zero_for_unknown_agent PASSED [ 19%] +tests/integration/test_observatory_aggregates.py::test_attention_items_ranks_stale_custody_first PASSED [ 19%] +tests/integration/test_observatory_aggregates.py::test_attention_items_ranks_blocked_second PASSED [ 19%] +tests/integration/test_observatory_aggregates.py::test_attention_items_ranks_aging_ready_third_oldest_first PASSED [ 19%] +tests/integration/test_observatory_aggregates.py::test_attention_items_ordering_across_reasons_and_limit PASSED [ 19%] +tests/integration/test_observatory_aggregates.py::test_attention_items_aging_threshold_is_a_module_constant PASSED [ 19%] +tests/integration/test_observatory_aggregates.py::test_stale_attention_rows_matches_attention_items_stale_tier PASSED [ 19%] +tests/integration/test_observatory_aggregates.py::test_attention_items_from_rows_matches_attention_items PASSED [ 19%] +tests/integration/test_observatory_aggregates.py::test_velocity_series_and_windows_matches_separate_calls PASSED [ 20%] +tests/integration/test_observatory_aggregates.py::test_project_summary_held_stale_reflects_real_custody_state PASSED [ 20%] +tests/integration/test_observatory_aggregates.py::test_project_summary_held_stale_zero_and_none_when_nothing_held PASSED [ 20%] +tests/integration/test_observatory_aggregates.py::test_project_summary_held_stale_all_fresh_is_zero_not_fabricated PASSED [ 20%] +tests/integration/test_observatory_web.py::test_l0_renders_environment_kpis_and_fleet_from_real_data PASSED [ 20%] +tests/integration/test_observatory_web.py::test_l0_window_tabs_are_real_server_rendered_links_with_active_state PASSED [ 20%] +tests/integration/test_observatory_web.py::test_l0_unknown_window_param_falls_back_to_7d_not_a_500 PASSED [ 20%] +tests/integration/test_observatory_web.py::test_l0_page_declares_dark_theme_by_default PASSED [ 20%] +tests/integration/test_observatory_web.py::test_l0_new_project_nav_action_is_a_quiet_icon_button PASSED [ 20%] +tests/integration/test_observatory_web.py::test_l1_status_tab_changes_server_side_filter_state PASSED [ 20%] +tests/integration/test_observatory_web.py::test_resolve_post_without_confirm_field_is_refused PASSED [ 20%] +tests/integration/test_observatory_web.py::test_resolve_post_with_wrong_confirm_value_is_refused PASSED [ 20%] +tests/integration/test_observatory_web.py::test_resolve_post_with_confirm_yes_succeeds PASSED [ 21%] +tests/integration/test_observatory_web.py::test_l2_confirm_resolve_query_param_reveals_the_confirm_form PASSED [ 21%] +tests/integration/test_observatory_web.py::test_l0_every_icon_ref_has_a_matching_sprite_symbol PASSED [ 21%] +tests/integration/test_observatory_web.py::test_l1_every_icon_ref_has_a_matching_sprite_symbol PASSED [ 21%] +tests/integration/test_observatory_web.py::test_l2_every_icon_ref_has_a_matching_sprite_symbol PASSED [ 21%] +tests/integration/test_observatory_web.py::test_login_page_every_icon_ref_has_a_matching_sprite_symbol PASSED [ 21%] +tests/integration/test_phantom_conflict_recovery.py::test_resolve_verifies_by_readback_when_wrapper_reports_conflict_after_a_landed_close PASSED [ 21%] +tests/integration/test_phantom_conflict_recovery.py::test_resolve_still_raises_when_readback_shows_the_close_genuinely_did_not_land PASSED [ 21%] +tests/integration/test_phantom_conflict_recovery.py::test_release_verifies_by_readback_when_wrapper_reports_conflict_after_a_landed_release PASSED [ 21%] +tests/integration/test_phantom_conflict_recovery.py::test_release_on_an_already_resolved_item_writes_nothing_and_reports_already_closed PASSED [ 21%] +tests/integration/test_project_removal.py::test_remove_of_nonexistent_project_gives_a_distinct_error PASSED [ 21%] +tests/integration/test_project_removal.py::test_remove_drops_both_the_directory_and_the_database PASSED [ 21%] +tests/integration/test_project_removal.py::test_remove_refuses_while_an_item_is_held_naming_holder_and_item PASSED [ 22%] +tests/integration/test_project_removal.py::test_remove_leaves_non_beads_content_intact_and_reports_it PASSED [ 22%] +tests/integration/test_project_removal.py::test_remove_of_orphaned_database_after_directory_already_deleted PASSED [ 22%] +tests/integration/test_project_removal.py::test_remove_of_orphaned_database_with_a_held_item_still_refuses PASSED [ 22%] +tests/integration/test_project_removal.py::test_new_after_directory_deleted_reattaches_and_workspace_create_reports_it PASSED [ 22%] +tests/integration/test_project_rename.py::test_rename_moves_dir_and_database_and_preserves_items PASSED [ 22%] +tests/integration/test_project_rename.py::test_rename_refuses_when_new_name_already_exists PASSED [ 22%] +tests/integration/test_project_rename.py::test_rename_refuses_when_old_missing PASSED [ 22%] +tests/integration/test_project_rename.py::test_rename_refuses_while_an_item_is_held PASSED [ 22%] +tests/integration/test_project_rename.py::test_rename_rejects_invalid_new_name PASSED [ 22%] +tests/integration/test_project_rename.py::test_rename_to_itself_is_refused PASSED [ 22%] +tests/integration/test_reopen_roundtrip.py::test_full_correction_cycle_reopen_claim_resolve_reads_back_corrected_text PASSED [ 22%] +tests/integration/test_reopen_roundtrip.py::test_reopen_clears_closed_at_and_the_cost_is_visible PASSED [ 23%] +tests/integration/test_reopen_roundtrip.py::test_reopen_clears_the_stale_assignee_bd_leaves_behind PASSED [ 23%] +tests/integration/test_reopen_roundtrip.py::test_resolve_on_a_closed_item_with_divergent_text_refuses_and_writes_nothing PASSED [ 23%] +tests/integration/test_reopen_roundtrip.py::test_resolve_on_a_closed_item_with_identical_text_is_idempotent PASSED [ 23%] +tests/integration/test_reopen_roundtrip.py::test_reopen_refuses_an_item_that_is_not_resolved PASSED [ 23%] +tests/integration/test_reopen_roundtrip.py::test_reopen_twice_refuses_the_second_time PASSED [ 23%] +tests/integration/test_reopen_roundtrip.py::test_measured_close_reason_disposition_across_a_reopen PASSED [ 23%] +tests/integration/test_resolve_fence.py::test_resolve_succeeds_single_call_on_unheld_item_with_stale_custody PASSED [ 23%] +tests/integration/test_resolve_fence.py::test_resolve_succeeds_on_item_filed_by_someone_else_never_held PASSED [ 23%] +tests/integration/test_resolve_fence.py::test_resolve_still_refuses_and_names_holder_when_actively_held_by_someone_else PASSED [ 23%] +tests/integration/test_resolve_fence.py::test_resolve_still_refuses_with_custody_takeover_mismatch_while_held PASSED [ 23%] +tests/integration/test_roundtrip.py::test_create_claim_resolve_roundtrip PASSED [ 23%] +tests/integration/test_roundtrip.py::test_claim_returns_none_on_an_empty_lane PASSED [ 24%] +tests/integration/test_roundtrip.py::test_notifier_flips_linked_report_and_reporter_reads_back_the_resolution PASSED [ 24%] +tests/integration/test_web.py::test_unauthenticated_request_to_dashboard_is_refused_json PASSED [ 24%] +tests/integration/test_web.py::test_unauthenticated_request_to_dashboard_redirects_browser PASSED [ 24%] +tests/integration/test_web.py::test_healthz_is_exempt_from_auth PASSED [ 24%] +tests/integration/test_web.py::test_login_wrong_password_is_rejected_and_sets_no_cookie PASSED [ 24%] +tests/integration/test_web.py::test_login_success_sets_cookie_and_grants_dashboard_access PASSED [ 24%] +tests/integration/test_web.py::test_logout_clears_session PASSED [ 24%] +tests/integration/test_web.py::test_dashboard_shows_real_project_from_the_shared_workspace PASSED [ 24%] +tests/integration/test_web.py::test_project_view_shows_items_with_holder_and_status PASSED [ 24%] +tests/integration/test_web.py::test_full_write_flow_create_add_resolve_remove PASSED [ 24%] +tests/integration/test_web.py::test_remove_refuses_when_item_is_held_and_project_survives PASSED [ 24%] +tests/integration/test_web.py::test_remove_requires_typed_name_to_match PASSED [ 25%] +tests/integration/test_web.py::test_no_claim_route_exists PASSED [ 25%] +tests/integration/test_web.py::test_item_detail_shows_description_and_acceptance_criteria PASSED [ 25%] +tests/integration/test_web.py::test_item_detail_reachable_from_project_listing PASSED [ 25%] +tests/integration/test_web.py::test_item_detail_open_item_shows_no_lifecycle_action PASSED [ 25%] +tests/integration/test_web.py::test_item_detail_held_item_shows_resolve_not_claim PASSED [ 25%] +tests/integration/test_web.py::test_item_detail_resolved_item_shows_resolution_and_no_action_controls PASSED [ 25%] +tests/integration/test_web.py::test_item_detail_nonexistent_item_shows_friendly_error PASSED [ 25%] +tests/integration/test_web.py::test_item_detail_shows_blocked_by_chain_with_status_and_holder PASSED [ 25%] +tests/integration/test_web.py::test_item_detail_blocker_chain_clears_once_blocker_resolved PASSED [ 25%] +tests/integration/test_web.py::test_item_detail_shows_discovered_from_provenance PASSED [ 25%] +tests/integration/test_web.py::test_item_detail_shows_blocks_inverse PASSED [ 25%] +tests/integration/test_web.py::test_item_detail_with_no_dependencies_shows_no_open_blockers_empty_state PASSED [ 26%] +tests/integration/test_web.py::test_item_detail_with_unsatisfied_blocker_does_not_also_show_no_open_blockers PASSED [ 26%] +tests/integration/test_web.py::test_item_detail_shows_activity_feed_with_real_events PASSED [ 26%] +tests/integration/test_web.py::test_item_detail_fresh_item_activity_feed_shows_only_created PASSED [ 26%] +tests/integration/test_web.py::test_no_claim_affordance_anywhere_in_the_web_ui PASSED [ 26%] +tests/integration/test_web.py::test_dashboard_held_item_raises_the_custody_reading PASSED [ 26%] +tests/integration/test_web.py::test_dashboard_never_shows_a_static_health_ok_badge PASSED [ 26%] +tests/integration/test_web.py::test_project_view_empty_filter_state_names_the_filter_and_offers_clear PASSED [ 26%] +tests/integration/test_web.py::test_add_item_error_on_nonexistent_project_does_not_leak_path_or_cli PASSED [ 26%] +tests/integration/test_web.py::test_project_view_pagination_reachability_and_no_cli_flag_leak PASSED [ 26%] +tests/integration/test_web.py::test_dashboard_kpi_values_are_tabular_numerals PASSED [ 26%] +tests/integration/test_web.py::test_dashboard_fleet_row_is_a_real_link_to_the_project PASSED [ 26%] +tests/integration/test_web.py::test_item_detail_humanizes_the_reported_by_identity_end_to_end SKIPPED [ 27%] +tests/integration/test_web.py::test_remove_confirmation_page_is_real_and_get_is_side_effect_free PASSED [ 27%] +tests/integration/test_web.py::test_remove_held_refusal_is_rendered_as_visible_text_on_the_confirm_page PASSED [ 27%] +tests/integration/test_web.py::test_item_detail_edit_form_saves_and_persists_on_reload PASSED [ 27%] +tests/integration/test_web.py::test_item_detail_edit_form_is_present_and_prefilled PASSED [ 27%] +tests/integration/test_web.py::test_item_detail_edit_does_not_touch_status_or_holder PASSED [ 27%] +tests/integration/test_web.py::test_item_detail_edit_blank_fields_leave_existing_values_unchanged PASSED [ 27%] +tests/integration/test_web.py::test_item_detail_edit_nonexistent_item_reports_error PASSED [ 27%] +tests/integration/test_web.py::test_rename_project_success_redirects_to_new_name PASSED [ 27%] +tests/integration/test_web.py::test_rename_project_rejects_invalid_new_name PASSED [ 27%] +tests/integration/test_web.py::test_rename_project_refuses_when_target_name_already_exists PASSED [ 27%] +tests/integration/test_web.py::test_rename_project_refuses_while_item_is_held PASSED [ 27%] +tests/integration/test_web.py::test_danger_zone_has_rename_form_and_no_claim_control PASSED [ 28%] +tests/integration/test_web.py::test_danger_zone_rename_affordance_is_unambiguous_reveal_save_cancel PASSED [ 28%] +tests/integration/test_web.py::test_resolved_item_row_shows_no_holder_chip_though_it_has_a_stale_assignee PASSED [ 28%] +tests/integration/test_web.py::test_resolved_item_detail_shows_no_held_by_chip PASSED [ 28%] +tests/integration/test_web.py::test_dashboard_includes_auto_refresh_script PASSED [ 28%] +tests/integration/test_web.py::test_project_view_includes_auto_refresh_script PASSED [ 28%] +tests/integration/test_web.py::test_item_detail_never_includes_auto_refresh_script PASSED [ 28%] +tests/integration/test_web.py::test_login_page_never_includes_auto_refresh_script PASSED [ 28%] +tests/integration/test_web.py::test_remove_confirm_page_never_includes_auto_refresh_script PASSED [ 28%] +tests/integration/test_web.py::test_project_view_status_tabs_show_real_counts PASSED [ 28%] +tests/integration/test_web.py::test_project_view_clicking_a_status_tab_filters_the_list PASSED [ 28%] +tests/integration/test_web.py::test_project_view_no_longer_ships_a_status_select_dropdown PASSED [ 29%] +tests/integration/test_web.py::test_project_view_health_banner_absent_when_calm PASSED [ 29%] +tests/integration/test_web.py::test_project_view_health_banner_present_when_blocked PASSED [ 29%] +tests/integration/test_web.py::test_project_view_health_banner_calm_when_held_but_fresh PASSED [ 29%] +tests/integration/test_web.py::test_project_view_item_rows_include_priority_bar_and_status_icon PASSED [ 29%] +tests/integration/test_web.py::test_item_detail_created_and_updated_use_the_compact_age_format PASSED [ 29%] +tests/integration/test_web.py::test_project_view_search_placeholder_uses_the_new_filter_hint PASSED [ 29%] +tests/integration/test_web_pwa.py::test_pwa_asset_is_reachable_without_authentication[/manifest.json] PASSED [ 29%] +tests/integration/test_web_pwa.py::test_pwa_asset_is_reachable_without_authentication[/sw.js] PASSED [ 29%] +tests/integration/test_web_pwa.py::test_pwa_asset_is_reachable_without_authentication[/pwa-192.png] PASSED [ 29%] +tests/integration/test_web_pwa.py::test_pwa_asset_is_reachable_without_authentication[/pwa-512.png] PASSED [ 29%] +tests/integration/test_web_pwa.py::test_pwa_asset_is_reachable_without_authentication[/apple-touch-icon.png] PASSED [ 29%] +tests/integration/test_web_pwa.py::test_pwa_asset_is_reachable_without_authentication[/favicon.ico] PASSED [ 30%] +tests/integration/test_web_pwa.py::test_pwa_asset_is_reachable_without_authentication[/favicon-32.png] PASSED [ 30%] +tests/integration/test_web_pwa.py::test_pwa_asset_is_reachable_without_authentication[/og-dark.png] PASSED [ 30%] +tests/integration/test_web_pwa.py::test_manifest_content_type_and_cache_header PASSED [ 30%] +tests/integration/test_web_pwa.py::test_manifest_is_valid_json_with_scope_root_and_standalone_display PASSED [ 30%] +tests/integration/test_web_pwa.py::test_manifest_lists_both_icon_sizes_with_a_maskable_purpose PASSED [ 30%] +tests/integration/test_web_pwa.py::test_service_worker_content_type_and_cache_header PASSED [ 30%] +tests/integration/test_web_pwa.py::test_service_worker_caches_nothing PASSED [ 30%] +tests/integration/test_web_pwa.py::test_service_worker_passes_every_fetch_straight_to_the_network PASSED [ 30%] +tests/integration/test_web_pwa.py::test_service_worker_skips_waiting_and_claims_clients PASSED [ 30%] +tests/integration/test_web_pwa.py::test_icon_is_a_real_png_with_correct_content_type_and_cache_header[/pwa-192.png-\x89PNG\r\n\x1a\n] PASSED [ 30%] +tests/integration/test_web_pwa.py::test_icon_is_a_real_png_with_correct_content_type_and_cache_header[/pwa-512.png-\x89PNG\r\n\x1a\n] PASSED [ 30%] +tests/integration/test_web_pwa.py::test_icon_is_a_real_png_with_correct_content_type_and_cache_header[/apple-touch-icon.png-\x89PNG\r\n\x1a\n] PASSED [ 31%] +tests/integration/test_web_pwa.py::test_favicon_ico_content_type_cache_header_and_real_ico_magic PASSED [ 31%] +tests/integration/test_web_pwa.py::test_favicon_ico_bundles_all_three_resolutions PASSED [ 31%] +tests/integration/test_web_pwa.py::test_favicon_32_png_is_a_real_png_with_correct_content_type_and_cache_header PASSED [ 31%] +tests/integration/test_web_pwa.py::test_og_card_is_a_real_png_with_correct_content_type_and_cache_header PASSED [ 31%] +tests/integration/test_web_pwa.py::test_pwa_512_and_apple_touch_icon_are_opaque_maskable_safe_renders SKIPPED [ 31%] +tests/integration/test_web_pwa.py::test_pwa_192_keeps_the_source_icons_native_transparent_corners SKIPPED [ 31%] +tests/integration/test_web_pwa.py::test_authenticated_dashboard_head_includes_pwa_tags PASSED [ 31%] +tests/integration/test_web_pwa.py::test_login_page_head_also_includes_pwa_tags PASSED [ 31%] +tests/integration/test_webbrowse_route.py::test_retired_browse_route_redirects_to_l1_without_item_param PASSED [ 31%] +tests/integration/test_webbrowse_route.py::test_retired_browse_route_redirects_to_l2_with_item_param PASSED [ 31%] +tests/integration/test_webbrowse_route.py::test_l1_lists_items_as_direct_links_to_l2 PASSED [ 31%] +tests/integration/test_webbrowse_route.py::test_l2_shows_the_real_item_content PASSED [ 32%] +tests/integration/test_webbrowse_route.py::test_l2_unknown_item_is_graceful_not_500 PASSED [ 32%] +tests/integration/test_webbrowse_route.py::test_l1_unknown_project_is_graceful PASSED [ 32%] +tests/integration/test_webbrowse_route.py::test_l1_and_l2_ship_the_auto_refresh_poller PASSED [ 32%] +tests/integration/test_webbrowse_route.py::test_l1_and_l2_reflect_status_transitions_live PASSED [ 32%] +tests/integration/test_work_list.py::test_list_bounded_reports_id_title_status_for_an_open_item PASSED [ 32%] +tests/integration/test_work_list.py::test_list_bounded_populates_holder_for_a_held_item PASSED [ 32%] +tests/integration/test_work_list.py::test_list_bounded_shows_closed_items_and_their_resolution PASSED [ 32%] +tests/integration/test_work_list.py::test_list_bounded_mixed_states_in_one_project PASSED [ 32%] +tests/integration/test_work_list.py::test_list_bounded_status_filter_returns_only_matching_status[blocked] PASSED [ 32%] +tests/integration/test_work_list.py::test_list_bounded_status_filter_returns_only_matching_status[deferred] PASSED [ 32%] +tests/integration/test_work_list.py::test_list_bounded_status_filter_returns_only_matching_status[held] PASSED [ 32%] +tests/integration/test_work_list.py::test_list_bounded_status_filter_returns_only_matching_status[open] PASSED [ 33%] +tests/integration/test_work_list.py::test_list_bounded_status_filter_returns_only_matching_status[resolved] PASSED [ 33%] +tests/integration/test_work_list.py::test_list_bounded_calling_it_does_not_mutate_anything PASSED [ 33%] +tests/integration/test_work_list.py::test_list_bounded_truncates_and_reports_honestly PASSED [ 33%] +tests/integration/test_work_list.py::test_list_bounded_on_empty_project_returns_empty_not_an_error PASSED [ 33%] +tests/integration/test_work_list.py::test_list_bounded_on_nonexistent_project_raises_distinct_not_found PASSED [ 33%] +tests/integration/test_work_list.py::test_list_bounded_rows_are_lean_by_default_no_body_fields PASSED [ 33%] +tests/integration/test_work_list.py::test_get_readonly_reads_the_real_full_body_without_claiming PASSED [ 33%] +tests/integration/test_work_list.py::test_get_readonly_on_resolved_item_shows_resolution_too PASSED [ 33%] +tests/integration/test_work_list.py::test_get_readonly_never_mutates_the_item PASSED [ 33%] +tests/integration/test_work_list.py::test_get_readonly_on_nonexistent_item_in_this_project_raises_not_found PASSED [ 33%] +tests/integration/test_work_list.py::test_get_readonly_on_id_from_a_different_project_raises_distinct_wrong_project_error PASSED [ 33%] +tests/unit/test_adapter_mapping.py::test_field_mapping_renames_every_declared_field PASSED [ 34%] +tests/unit/test_adapter_mapping.py::test_raw_dict_is_preserved_verbatim PASSED [ 34%] +tests/unit/test_adapter_mapping.py::test_known_statuses_are_mapped PASSED [ 34%] +tests/unit/test_adapter_mapping.py::test_unknown_status_passes_through_unchanged PASSED [ 34%] +tests/unit/test_adapter_mapping.py::test_missing_status_defaults_to_unknown PASSED [ 34%] +tests/unit/test_adapter_mapping.py::test_tags_and_meta_default_to_empty_containers_when_absent PASSED [ 34%] +tests/unit/test_adapter_mapping.py::test_tags_and_meta_default_to_empty_containers_when_explicitly_null PASSED [ 34%] +tests/unit/test_adapter_mapping.py::test_missing_id_defaults_to_empty_string PASSED [ 34%] +tests/unit/test_adapter_mapping.py::test_retryable_detects_dolt_conflict_codes PASSED [ 34%] +tests/unit/test_adapter_mapping.py::test_retryable_is_case_insensitive PASSED [ 34%] +tests/unit/test_adapter_mapping.py::test_retryable_false_for_unrelated_errors PASSED [ 34%] +tests/unit/test_adapter_mapping.py::test_retryable_false_for_connection_errors PASSED [ 34%] +tests/unit/test_adapter_mapping.py::test_connection_retryable_detects_real_bd_unreachable_wording PASSED [ 35%] +tests/unit/test_adapter_mapping.py::test_connection_retryable_detects_transport_signatures PASSED [ 35%] +tests/unit/test_adapter_mapping.py::test_connection_retryable_is_case_insensitive PASSED [ 35%] +tests/unit/test_adapter_mapping.py::test_connection_retryable_false_for_domain_and_serialization_errors PASSED [ 35%] +tests/unit/test_adapter_mapping.py::test_run_returns_a_successful_response_even_if_its_text_matches_retryable PASSED [ 35%] +tests/unit/test_adapter_mapping.py::test_run_still_retries_and_raises_for_a_genuine_persistent_conflict PASSED [ 35%] +tests/unit/test_adapter_mapping.py::test_run_retries_a_real_conflict_then_returns_the_eventual_success PASSED [ 35%] +tests/unit/test_adapter_mapping.py::test_active_blockers_empty_when_no_dependencies PASSED [ 35%] +tests/unit/test_adapter_mapping.py::test_active_blockers_ignores_non_blocks_dependency_types PASSED [ 35%] +tests/unit/test_adapter_mapping.py::test_active_blockers_ignores_closed_blocker PASSED [ 35%] +tests/unit/test_adapter_mapping.py::test_active_blockers_reports_open_blocks_dependency PASSED [ 35%] +tests/unit/test_adapter_mapping.py::test_active_blockers_treats_blocked_and_deferred_blockers_as_still_active PASSED [ 35%] +tests/unit/test_adapter_mapping.py::test_active_blockers_handles_missing_dependencies_key PASSED [ 36%] +tests/unit/test_adapter_mapping.py::test_map_status_translates_every_known_bd_status PASSED [ 36%] +tests/unit/test_adapter_mapping.py::test_map_status_passes_through_unknown_value_rather_than_coercing PASSED [ 36%] +tests/unit/test_adapter_mapping.py::test_map_status_handles_none_and_empty PASSED [ 36%] +tests/unit/test_adapter_mapping.py::test_is_active_blocker_true_only_for_open_blocks_type PASSED [ 36%] +tests/unit/test_adapter_mapping.py::test_is_active_blocker_false_for_closed_blocks_type PASSED [ 36%] +tests/unit/test_adapter_mapping.py::test_is_active_blocker_false_for_non_blocks_type_regardless_of_status PASSED [ 36%] +tests/unit/test_adapter_mapping.py::test_get_enriched_links_include_title_status_holder_for_forward_direction PASSED [ 36%] +tests/unit/test_adapter_mapping.py::test_get_enriched_links_satisfied_blocker_is_not_blocking PASSED [ 36%] +tests/unit/test_adapter_mapping.py::test_name_re_accepts_simple_lowercase_name PASSED [ 36%] +tests/unit/test_adapter_mapping.py::test_name_re_rejects_dotted_name PASSED [ 36%] +tests/unit/test_adapter_mapping.py::test_name_re_rejects_uppercase PASSED [ 36%] +tests/unit/test_adapter_mapping.py::test_name_re_rejects_single_character PASSED [ 37%] +tests/unit/test_adapter_mapping.py::test_name_re_accepts_underscores_and_digits PASSED [ 37%] +tests/unit/test_adapter_mapping.py::test_workspace_create_rejects_dotted_name_before_touching_disk PASSED [ 37%] +tests/unit/test_adapter_mapping.py::test_workspace_create_rejects_uppercase_name_before_touching_disk PASSED [ 37%] +tests/unit/test_adapter_mapping.py::test_workspace_create_refuses_to_report_success_on_dead_residue PASSED [ 37%] +tests/unit/test_adapter_mapping.py::test_workspace_create_returns_cleanly_when_beads_dir_already_works PASSED [ 37%] +tests/unit/test_adapter_mapping.py::test_env_always_sets_bd_non_interactive PASSED [ 37%] +tests/unit/test_adapter_mapping.py::test_env_sets_bd_non_interactive_even_when_absent_from_environment PASSED [ 37%] +tests/unit/test_adapter_mapping.py::test_env_overrides_a_falsy_ambient_value PASSED [ 37%] +tests/unit/test_adapter_mapping.py::test_env_no_longer_sets_the_ineffective_telemetry_disable_var PASSED [ 37%] +tests/unit/test_adapter_mapping.py::test_disable_telemetry_once_is_cached_per_process PASSED [ 37%] +tests/unit/test_adapter_mapping.py::test_disable_telemetry_once_never_raises_on_subprocess_failure PASSED [ 37%] +tests/unit/test_adapter_mapping.py::test_statuses_public_tuple_covers_every_domain_status PASSED [ 38%] +tests/unit/test_adapter_mapping.py::test_status_reverse_map_is_the_exact_inverse_of_the_forward_map PASSED [ 38%] +tests/unit/test_adapter_mapping.py::test_list_rejects_unknown_status_before_any_subprocess_call PASSED [ 38%] +tests/unit/test_adapter_mapping.py::test_list_bounded_clamps_requested_limit_above_the_max PASSED [ 38%] +tests/unit/test_adapter_mapping.py::test_list_bounded_clamps_a_nonpositive_requested_limit_to_one PASSED [ 38%] +tests/unit/test_adapter_mapping.py::test_list_bounded_uses_default_limit_when_omitted PASSED [ 38%] +tests/unit/test_adapter_mapping.py::test_list_bounded_reports_truncation_honestly PASSED [ 38%] +tests/unit/test_adapter_mapping.py::test_list_bounded_reports_no_truncation_when_everything_fits PASSED [ 38%] +tests/unit/test_adapter_mapping.py::test_summary_default_is_lean_and_omits_body_fields PASSED [ 38%] +tests/unit/test_adapter_mapping.py::test_summary_full_adds_the_same_body_fields_claim_returns PASSED [ 38%] +tests/unit/test_adapter_mapping.py::test_summary_full_on_an_item_with_no_body_reports_none_not_missing PASSED [ 38%] +tests/unit/test_adapter_mapping.py::test_get_readonly_project_name_is_inferred_from_the_beads_dir_parent PASSED [ 38%] +tests/unit/test_adapter_mapping.py::test_get_readonly_wrong_project_prefix_raises_distinct_error PASSED [ 39%] +tests/unit/test_adapter_mapping.py::test_get_readonly_correct_prefix_but_missing_raises_plain_not_found PASSED [ 39%] +tests/unit/test_adapter_mapping.py::test_get_readonly_delegates_to_get_and_returns_the_item_unmodified PASSED [ 39%] +tests/unit/test_adapter_mapping.py::test_list_bounded_offset_defaults_to_zero_and_matches_prior_behavior PASSED [ 39%] +tests/unit/test_adapter_mapping.py::test_list_bounded_offset_shifts_the_returned_window PASSED [ 39%] +tests/unit/test_adapter_mapping.py::test_list_bounded_offset_past_the_end_reports_no_truncation PASSED [ 39%] +tests/unit/test_adapter_mapping.py::test_list_bounded_negative_offset_clamps_to_zero PASSED [ 39%] +tests/unit/test_adapter_mapping.py::test_history_events_oldest_entry_becomes_created PASSED [ 39%] +tests/unit/test_adapter_mapping.py::test_history_events_collapses_consecutive_identical_signatures PASSED [ 39%] +tests/unit/test_adapter_mapping.py::test_history_events_generic_transition_names_both_states PASSED [ 39%] +tests/unit/test_adapter_mapping.py::test_history_events_sorted_ascending_regardless_of_input_order PASSED [ 39%] +tests/unit/test_adapter_mapping.py::test_history_events_skips_entries_with_no_commit_date PASSED [ 39%] +tests/unit/test_adapter_mapping.py::test_history_events_empty_input_returns_empty PASSED [ 40%] +tests/unit/test_adapter_mapping.py::test_daily_resolved_counts_buckets_by_day_oldest_to_newest PASSED [ 40%] +tests/unit/test_adapter_mapping.py::test_daily_resolved_counts_none_when_unmeasurable PASSED [ 40%] +tests/unit/test_adapter_mapping.py::test_daily_resolved_counts_real_zero_when_nothing_resolved PASSED [ 40%] +tests/unit/test_adapter_mapping.py::test_daily_resolved_counts_out_of_window_is_dropped_not_errored PASSED [ 40%] +tests/unit/test_adapter_mapping.py::test_parse_bootstrap_metadata_block_style_lists PASSED [ 40%] +tests/unit/test_adapter_mapping.py::test_parse_bootstrap_metadata_inline_flow_style PASSED [ 40%] +tests/unit/test_adapter_mapping.py::test_parse_bootstrap_metadata_strips_matching_quotes PASSED [ 40%] +tests/unit/test_adapter_mapping.py::test_parse_bootstrap_metadata_only_one_key_present PASSED [ 40%] +tests/unit/test_adapter_mapping.py::test_parse_bootstrap_metadata_yml_tag_and_crlf PASSED [ 40%] +tests/unit/test_adapter_mapping.py::test_parse_bootstrap_metadata_no_block_is_empty_not_error PASSED [ 40%] +tests/unit/test_adapter_mapping.py::test_parse_bootstrap_metadata_none_and_empty_are_empty PASSED [ 40%] +tests/unit/test_adapter_mapping.py::test_parse_bootstrap_metadata_ignores_a_nested_list_item_named_like_a_key PASSED [ 41%] +tests/unit/test_adapter_mapping.py::test_parse_bootstrap_metadata_only_first_yaml_block_consulted PASSED [ 41%] +tests/unit/test_adapter_mapping.py::test_from_beads_populates_repos_and_context_from_description PASSED [ 41%] +tests/unit/test_adapter_mapping.py::test_from_beads_no_yaml_block_yields_empty_lists_backward_compatible PASSED [ 41%] +tests/unit/test_adapter_mapping.py::test_summary_full_includes_repos_and_context PASSED [ 41%] +tests/unit/test_adapter_mapping.py::test_summary_lean_omits_repos_and_context PASSED [ 41%] +tests/unit/test_adapter_mapping.py::test_summary_full_repos_context_empty_for_plain_item PASSED [ 41%] +tests/unit/test_bd_telemetry_env_audit.py::test_every_bd_subprocess_call_routes_through_the_telemetry_env_helper PASSED [ 41%] +tests/unit/test_bd_telemetry_env_audit.py::test_helper_itself_is_found_by_the_audit_in_at_least_one_real_call_site PASSED [ 41%] +tests/unit/test_chartsvg.py::test_sparkline_geometry_is_back_computable PASSED [ 41%] +tests/unit/test_chartsvg.py::test_sparkline_flat_series_draws_centre_line PASSED [ 41%] +tests/unit/test_chartsvg.py::test_sparkline_empty_is_valid_and_accessible PASSED [ 41%] +tests/unit/test_chartsvg.py::test_sparkline_single_value_draws_one_dot PASSED [ 42%] +tests/unit/test_chartsvg.py::test_sparkline_display_dimensions_are_separate_attrs PASSED [ 42%] +tests/unit/test_chartsvg.py::test_velocity_chart_geometry_is_back_computable PASSED [ 42%] +tests/unit/test_chartsvg.py::test_velocity_chart_empty_is_valid_and_accessible PASSED [ 42%] +tests/unit/test_chartsvg.py::test_velocity_chart_all_zero_values_do_not_divide_by_zero PASSED [ 42%] +tests/unit/test_chartsvg.py::test_velocity_chart_all_zero_renders_caption_not_isolated_zero_labels PASSED [ 42%] +tests/unit/test_chartsvg.py::test_velocity_chart_nonzero_data_has_no_caption PASSED [ 42%] +tests/unit/test_chartsvg.py::test_status_donut_segment_lengths_sum_to_circumference PASSED [ 42%] +tests/unit/test_chartsvg.py::test_status_donut_zero_total_draws_only_track PASSED [ 42%] +tests/unit/test_chartsvg.py::test_status_donut_skips_zero_count_statuses PASSED [ 42%] +tests/unit/test_chartsvg.py::test_status_donut_single_full_segment_renders_cleanly PASSED [ 42%] +tests/unit/test_chartsvg.py::test_status_donut_unique_pattern_id_is_respected PASSED [ 43%] +tests/unit/test_chartsvg.py::test_age_histogram_geometry_is_back_computable PASSED [ 43%] +tests/unit/test_chartsvg.py::test_age_histogram_empty_is_valid_and_accessible PASSED [ 43%] +tests/unit/test_chartsvg.py::test_age_histogram_all_zero_counts_do_not_divide_by_zero PASSED [ 43%] +tests/unit/test_chartsvg.py::test_age_histogram_zero_bucket_draws_a_deliberate_stub_no_value_label PASSED [ 43%] +tests/unit/test_cli_doctor.py::test_not_installed_is_skipped_not_failed PASSED [ 43%] +tests/unit/test_cli_doctor.py::test_unsupported_platform_is_skipped_not_failed PASSED [ 43%] +tests/unit/test_cli_doctor.py::test_installed_but_not_active_is_skipped_service_check_already_failed PASSED [ 43%] +tests/unit/test_cli_doctor.py::test_installed_and_active_with_fresh_heartbeats_passes PASSED [ 43%] +tests/unit/test_cli_doctor.py::test_installed_and_active_with_stale_reap_heartbeat_fails PASSED [ 43%] +tests/unit/test_cli_doctor.py::test_installed_and_active_startup_window_no_sweeps_yet_passes PASSED [ 43%] +tests/unit/test_cli_doctor.py::test_installed_and_active_no_heartbeat_file_at_all_fails PASSED [ 43%] +tests/unit/test_cli_doctor.py::test_restart_policy_skipped_when_service_not_installed PASSED [ 44%] +tests/unit/test_cli_doctor.py::test_restart_policy_skipped_when_platform_unsupported PASSED [ 44%] +tests/unit/test_cli_doctor.py::test_restart_policy_skipped_on_non_linux_platform_with_no_unit_file PASSED [ 44%] +tests/unit/test_cli_doctor.py::test_restart_policy_passes_when_unit_has_restart_always PASSED [ 44%] +tests/unit/test_cli_doctor.py::test_restart_policy_fails_when_unit_still_has_restart_on_failure PASSED [ 44%] +tests/unit/test_cli_doctor.py::test_restart_policy_fails_when_unit_has_no_restart_line_at_all PASSED [ 44%] +tests/unit/test_cli_unclaim.py::test_happy_path_releases_and_reports_open PASSED [ 44%] +tests/unit/test_cli_unclaim.py::test_refuses_when_not_held_and_mutates_nothing PASSED [ 44%] +tests/unit/test_cli_unclaim.py::test_reports_missing_item_without_mutating PASSED [ 44%] +tests/unit/test_cli_unclaim.py::test_refuses_if_readback_still_held PASSED [ 44%] +tests/unit/test_cli_update.py::test_builds_uv_tool_upgrade PASSED [ 44%] +tests/unit/test_cli_update.py::test_reinstall_flag_adds_reinstall PASSED [ 44%] +tests/unit/test_cli_update.py::test_missing_uv_fails_loud_and_runs_nothing PASSED [ 45%] +tests/unit/test_cli_update.py::test_nonzero_uv_exit_propagates_code PASSED [ 45%] +tests/unit/test_custody.py::test_age_seconds_of_a_fresh_timestamp_is_small PASSED [ 45%] +tests/unit/test_custody.py::test_age_seconds_never_negative_on_clock_skew PASSED [ 45%] +tests/unit/test_custody.py::test_age_seconds_of_empty_timestamp_is_infinite PASSED [ 45%] +tests/unit/test_custody.py::test_is_fresh_true_within_ttl PASSED [ 45%] +tests/unit/test_custody.py::test_is_fresh_false_beyond_ttl PASSED [ 45%] +tests/unit/test_custody.py::test_is_fresh_none_record_is_not_fresh PASSED [ 45%] +tests/unit/test_custody.py::test_is_fresh_ignores_declared_state PASSED [ 45%] +tests/unit/test_custody.py::test_reclaim_eligible_no_record_at_all PASSED [ 45%] +tests/unit/test_custody.py::test_reclaim_eligible_fresh_survives_a_long_total_hold PASSED [ 45%] +tests/unit/test_custody.py::test_reclaim_eligible_stale_after_ttl_lapses PASSED [ 45%] +tests/unit/test_custody.py::test_reclaim_eligible_escalation_ceiling_exceeded PASSED [ 46%] +tests/unit/test_custody.py::test_reclaim_eligible_awaiting_human_below_ceiling_is_not_eligible PASSED [ 46%] +tests/unit/test_custody.py::test_reclaim_eligible_idle_declaration_never_exempts_from_staleness PASSED [ 46%] +tests/unit/test_custody.py::test_should_notify_working_state PASSED [ 46%] +tests/unit/test_custody.py::test_should_notify_awaiting_human_is_suppressed PASSED [ 46%] +tests/unit/test_custody.py::test_should_notify_none_record PASSED [ 46%] +tests/unit/test_custody.py::test_should_notify_is_never_consulted_by_reclaim_eligible PASSED [ 46%] +tests/unit/test_custody.py::test_custody_roundtrip_through_dict PASSED [ 46%] +tests/unit/test_custody.py::test_now_iso_matches_expected_format PASSED [ 46%] +tests/unit/test_dashboard_ledger.py::test_state_bar_zero_state_renders_as_seam_not_absent PASSED [ 46%] +tests/unit/test_dashboard_ledger.py::test_state_bar_fixed_slot_order_is_always_the_same PASSED [ 46%] +tests/unit/test_dashboard_ledger.py::test_state_legend_zero_count_shows_real_number_not_hidden PASSED [ 46%] +tests/unit/test_dashboard_ledger.py::test_state_legend_nonzero_states_use_their_dedicated_fill PASSED [ 47%] +tests/unit/test_dashboard_ledger.py::test_state_bar_calm_zero_alarm_states_have_no_min_width_floor PASSED [ 47%] +tests/unit/test_dashboard_ledger.py::test_state_bar_tiny_held_count_among_huge_total_still_gets_alarm_floor PASSED [ 47%] +tests/unit/test_dashboard_ledger.py::test_state_bar_blocked_and_deferred_also_get_the_alarm_floor PASSED [ 47%] +tests/unit/test_dashboard_ledger.py::test_dashboard_sort_key_orders_ready_descending PASSED [ 47%] +tests/unit/test_dashboard_ledger.py::test_dashboard_sort_key_ties_break_by_name PASSED [ 47%] +tests/unit/test_dashboard_ledger.py::test_dashboard_sort_key_broken_queues_sort_first_regardless_of_count PASSED [ 47%] +tests/unit/test_dashboard_ledger.py::test_ledger_hero_unreadable_workspace_renders_honest_dash PASSED [ 47%] +tests/unit/test_dashboard_ledger.py::test_ledger_hero_zero_projects_says_so_plainly PASSED [ 47%] +tests/unit/test_dashboard_ledger.py::test_ledger_hero_normal_case_shows_count_and_burn_rate PASSED [ 47%] +tests/unit/test_dashboard_ledger.py::test_ledger_hero_no_throughput_is_an_honest_gap_not_a_fabricated_rate PASSED [ 47%] +tests/unit/test_dashboard_ledger.py::test_secondary_readings_no_ready_items_is_honest_dash_for_concentration PASSED [ 47%] +tests/unit/test_dashboard_ledger.py::test_secondary_readings_concentration_links_to_the_project PASSED [ 48%] +tests/unit/test_dashboard_ledger.py::test_secondary_readings_waiting_7d_uses_amber_only_when_nonzero PASSED [ 48%] +tests/unit/test_dashboard_ledger.py::test_secondary_readings_custody_reports_blocked_needing_attention PASSED [ 48%] +tests/unit/test_dashboard_ledger.py::test_throughput_no_prior_rate_is_honest_not_a_fabricated_delta PASSED [ 48%] +tests/unit/test_dashboard_ledger.py::test_throughput_reports_trend_percentage_when_measurable PASSED [ 48%] +tests/unit/test_dashboard_ledger.py::test_throughput_names_coverage_gap_when_some_queues_unmeasurable PASSED [ 48%] +tests/unit/test_dashboard_ledger.py::test_throughput_no_coverage_footnote_when_fully_measurable PASSED [ 48%] +tests/unit/test_dashboard_ledger.py::test_workspace_composition_computes_percent_resolved PASSED [ 48%] +tests/unit/test_dashboard_ledger.py::test_workspace_composition_zero_total_never_divides_by_zero PASSED [ 48%] +tests/unit/test_dashboard_ledger.py::test_dashboard_row_broken_project_is_unmissable_alarm_row PASSED [ 48%] +tests/unit/test_dashboard_ledger.py::test_dashboard_row_zero_resolved_shows_dash_not_fabricated_zero_percent PASSED [ 48%] +tests/unit/test_dashboard_ledger.py::test_dashboard_row_real_resolved_shows_count_and_percent PASSED [ 48%] +tests/unit/test_dashboard_ledger.py::test_dashboard_row_calm_project_has_no_alarm_styling PASSED [ 49%] +tests/unit/test_dashboard_ledger.py::test_dashboard_row_held_item_flags_the_row_amber PASSED [ 49%] +tests/unit/test_dashboard_ledger.py::test_dashboard_row_blocked_item_flags_the_row_crimson_outranking_held PASSED [ 49%] +tests/unit/test_dashboard_ledger.py::test_dashboard_row_deferred_item_also_flags_the_row PASSED [ 49%] +tests/unit/test_dashboard_ledger.py::test_dashboard_totals_sums_every_readable_project PASSED [ 49%] +tests/unit/test_dashboard_ledger.py::test_attention_signal_absent_entirely_when_calm PASSED [ 49%] +tests/unit/test_dashboard_ledger.py::test_attention_signal_present_and_amber_when_only_held PASSED [ 49%] +tests/unit/test_dashboard_ledger.py::test_attention_signal_crimson_when_anything_is_blocked PASSED [ 49%] +tests/unit/test_heartbeat.py::test_record_loop_started_then_read_shows_no_completion_yet PASSED [ 49%] +tests/unit/test_heartbeat.py::test_record_sweep_completed_sets_last_completed_and_keeps_loop_started_at PASSED [ 49%] +tests/unit/test_heartbeat.py::test_record_sweep_completed_without_prior_started_still_works PASSED [ 49%] +tests/unit/test_heartbeat.py::test_reap_and_notify_records_are_independent PASSED [ 49%] +tests/unit/test_heartbeat.py::test_read_loop_heartbeat_missing_file_is_none PASSED [ 50%] +tests/unit/test_heartbeat.py::test_read_loop_heartbeat_corrupt_file_is_none PASSED [ 50%] +tests/unit/test_heartbeat.py::test_record_loop_started_overwrites_a_previous_runs_completion PASSED [ 50%] +tests/unit/test_heartbeat.py::test_pid_alive_true_for_current_process PASSED [ 50%] +tests/unit/test_heartbeat.py::test_pid_alive_false_for_a_really_dead_process PASSED [ 50%] +tests/unit/test_heartbeat.py::test_fresh_completion_passes PASSED [ 50%] +tests/unit/test_heartbeat.py::test_stale_completion_fails_and_names_loop_and_fix PASSED [ 50%] +tests/unit/test_heartbeat.py::test_no_record_at_all_fails_and_names_loop PASSED [ 50%] +tests/unit/test_heartbeat.py::test_startup_window_no_completion_yet_but_recent_start_passes PASSED [ 50%] +tests/unit/test_heartbeat.py::test_startup_window_exceeded_with_no_completion_fails PASSED [ 50%] +tests/unit/test_heartbeat.py::test_dead_pid_with_recent_completion_does_not_read_as_fresh PASSED [ 50%] +tests/unit/test_heartbeat.py::test_dead_pid_check_uses_real_pid_alive_by_default PASSED [ 50%] +tests/unit/test_heartbeat.py::test_threshold_is_interval_times_stale_multiple PASSED [ 51%] +tests/unit/test_observatory_widgets.py::test_verdict_line_environment_alarm PASSED [ 51%] +tests/unit/test_observatory_widgets.py::test_verdict_line_environment_calm PASSED [ 51%] +tests/unit/test_observatory_widgets.py::test_verdict_line_environment_idle PASSED [ 51%] +tests/unit/test_observatory_widgets.py::test_verdict_line_project_alarm PASSED [ 51%] +tests/unit/test_observatory_widgets.py::test_verdict_line_project_calm PASSED [ 51%] +tests/unit/test_observatory_widgets.py::test_verdict_line_project_idle PASSED [ 51%] +tests/unit/test_observatory_widgets.py::test_verdict_line_environment_alarm_pluralization[1-1 item needs you] PASSED [ 51%] +tests/unit/test_observatory_widgets.py::test_verdict_line_environment_alarm_pluralization[2-2 items need you] PASSED [ 51%] +tests/unit/test_observatory_widgets.py::test_verdict_line_project_alarm_pluralization[1-Needs you \u2014 1 item requires attention] PASSED [ 51%] +tests/unit/test_observatory_widgets.py::test_verdict_line_project_alarm_pluralization[2-Needs you \u2014 2 items require attention] PASSED [ 51%] +tests/unit/test_observatory_widgets.py::test_verdict_line_single_agent_is_not_pluralized PASSED [ 51%] +tests/unit/test_observatory_widgets.py::test_verdict_line_alarm_requires_reasons PASSED [ 52%] +tests/unit/test_observatory_widgets.py::test_all_nine_observatory_widgets_are_registered PASSED [ 52%] +tests/unit/test_observatory_widgets.py::test_get_observatory_widget_unknown_id_names_known_ids PASSED [ 52%] +tests/unit/test_observatory_widgets.py::test_get_observatory_widget_roundtrip PASSED [ 52%] +tests/unit/test_observatory_widgets.py::test_register_observatory_duplicate_id_fails_loud PASSED [ 52%] +tests/unit/test_observatory_widgets.py::test_render_verdict_hero_alarm PASSED [ 52%] +tests/unit/test_observatory_widgets.py::test_render_verdict_hero_calm_with_meta_row PASSED [ 52%] +tests/unit/test_observatory_widgets.py::test_split_meta_value[465-expected0] PASSED [ 52%] +tests/unit/test_observatory_widgets.py::test_split_meta_value[0-expected1] PASSED [ 52%] +tests/unit/test_observatory_widgets.py::test_split_meta_value[\u2014-expected2] PASSED [ 52%] +tests/unit/test_observatory_widgets.py::test_split_meta_value[6d-expected3] PASSED [ 52%] +tests/unit/test_observatory_widgets.py::test_split_meta_value[3h ago-expected4] PASSED [ 52%] +tests/unit/test_observatory_widgets.py::test_split_meta_value[-2d-expected5] PASSED [ 53%] +tests/unit/test_observatory_widgets.py::test_render_verdict_hero_meta_row_splits_suffix_into_its_own_span PASSED [ 53%] +tests/unit/test_observatory_widgets.py::test_render_verdict_hero_idle PASSED [ 53%] +tests/unit/test_observatory_widgets.py::test_render_kpi_strip_blocked_zero_gets_quiet_class PASSED [ 53%] +tests/unit/test_observatory_widgets.py::test_render_kpi_strip_blocked_nonzero_has_no_is_zero PASSED [ 53%] +tests/unit/test_observatory_widgets.py::test_render_attention_queue_ranked_rows PASSED [ 53%] +tests/unit/test_observatory_widgets.py::test_render_attention_queue_truncation_note_when_capped PASSED [ 53%] +tests/unit/test_observatory_widgets.py::test_render_attention_queue_no_truncation_note_when_not_capped PASSED [ 53%] +tests/unit/test_observatory_widgets.py::test_render_fleet_table_mix_bar_and_dormant_section PASSED [ 53%] +tests/unit/test_observatory_widgets.py::test_render_fleet_table_no_dormant_omits_section PASSED [ 53%] +tests/unit/test_observatory_widgets.py::test_render_agents_now_stale_row PASSED [ 53%] +tests/unit/test_observatory_widgets.py::test_render_activity_feed_links_and_window_tabs PASSED [ 53%] +tests/unit/test_observatory_widgets.py::test_render_status_breakdown_full_legend PASSED [ 54%] +tests/unit/test_observatory_widgets.py::test_render_status_breakdown_zero_total_has_zero_percent PASSED [ 54%] +tests/unit/test_observatory_widgets.py::test_render_ready_age_histogram_with_flagged_note PASSED [ 54%] +tests/unit/test_observatory_widgets.py::test_render_ready_age_histogram_without_flagged_note PASSED [ 54%] +tests/unit/test_observatory_widgets.py::test_render_agents_panel_stale_and_fresh_rows PASSED [ 54%] +tests/unit/test_overview_needs_you.py::test_blocked_stale_counts_only_needlessly_blocked PASSED [ 54%] +tests/unit/test_overview_needs_you.py::test_blocked_stale_is_safe_when_upstream_status_unreadable PASSED [ 54%] +tests/unit/test_overview_needs_you.py::test_held_stale_oldest_age_uses_worst_breach_with_a_record PASSED [ 54%] +tests/unit/test_overview_needs_you.py::test_held_stale_oldest_age_none_when_nothing_stale PASSED [ 54%] +tests/unit/test_overview_needs_you.py::test_held_stale_oldest_age_none_when_only_recordless_holds PASSED [ 54%] +tests/unit/test_overview_needs_you.py::test_attention_for_none_when_calm_or_unreadable PASSED [ 54%] +tests/unit/test_overview_needs_you.py::test_attention_entries_rank_custody_over_blocker_over_age PASSED [ 54%] +tests/unit/test_overview_needs_you.py::test_attention_entry_carries_all_live_conditions_sorted PASSED [ 55%] +tests/unit/test_overview_needs_you.py::test_attention_entries_break_ties_by_count PASSED [ 55%] +tests/unit/test_overview_needs_you.py::test_verdict_idle_when_nothing_running_but_work_waits PASSED [ 55%] +tests/unit/test_overview_needs_you.py::test_verdict_idle_notes_zero_throughput_today PASSED [ 55%] +tests/unit/test_overview_needs_you.py::test_verdict_stalled_when_no_movement_and_holds_exist PASSED [ 55%] +tests/unit/test_overview_needs_you.py::test_verdict_all_clear_only_when_genuinely_calm PASSED [ 55%] +tests/unit/test_overview_needs_you.py::test_verdict_all_clear_no_open_work PASSED [ 55%] +tests/unit/test_overview_needs_you.py::test_verdict_alarm_amber_for_custody_only_fleet PASSED [ 55%] +tests/unit/test_overview_needs_you.py::test_verdict_blocked_crimson_and_plural_keyword PASSED [ 55%] +tests/unit/test_overview_needs_you.py::test_verdict_html_calm_uses_no_status_hue PASSED [ 55%] +tests/unit/test_overview_needs_you.py::test_verdict_html_alarm_carries_amber_not_crimson PASSED [ 55%] +tests/unit/test_overview_needs_you.py::test_verdict_html_is_flat_never_glass PASSED [ 55%] +tests/unit/test_overview_needs_you.py::test_needs_you_html_absent_when_no_entries PASSED [ 56%] +tests/unit/test_overview_needs_you.py::test_needs_you_html_marks_severity_and_since_and_dispatch PASSED [ 56%] +tests/unit/test_overview_needs_you.py::test_needs_you_blocked_condition_has_no_fabricated_since PASSED [ 56%] +tests/unit/test_overview_needs_you.py::test_dispatch_pick_prefers_aged_then_deep_queue PASSED [ 56%] +tests/unit/test_overview_needs_you.py::test_dispatch_html_absent_when_nothing_ready PASSED [ 56%] +tests/unit/test_overview_needs_you.py::test_dispatch_html_names_project_and_verb PASSED [ 56%] +tests/unit/test_overview_needs_you.py::test_units_legend_defines_one_vocabulary PASSED [ 56%] +tests/unit/test_overview_needs_you.py::test_sidebar_badge_spells_out_denominator PASSED [ 56%] +tests/unit/test_prereqs.py::test_os_arch_recognizes_supported_combinations[Linux-x86_64-expected0] PASSED [ 56%] +tests/unit/test_prereqs.py::test_os_arch_recognizes_supported_combinations[Linux-aarch64-expected1] PASSED [ 56%] +tests/unit/test_prereqs.py::test_os_arch_recognizes_supported_combinations[Darwin-arm64-expected2] PASSED [ 56%] +tests/unit/test_prereqs.py::test_os_arch_recognizes_supported_combinations[Darwin-x86_64-expected3] PASSED [ 56%] +tests/unit/test_prereqs.py::test_os_arch_raises_on_unknown_os PASSED [ 57%] +tests/unit/test_prereqs.py::test_os_arch_raises_on_unknown_arch PASSED [ 57%] +tests/unit/test_prereqs.py::test_bd_install_version_is_derived_from_min_version_not_duplicated PASSED [ 57%] +tests/unit/test_prereqs.py::test_bd_install_command_linux_amd64 PASSED [ 57%] +tests/unit/test_prereqs.py::test_bd_install_command_never_contains_rm PASSED [ 57%] +tests/unit/test_prereqs.py::test_dolt_install_command_never_contains_rm PASSED [ 57%] +tests/unit/test_prereqs.py::test_bd_install_command_linux_arm64 PASSED [ 57%] +tests/unit/test_prereqs.py::test_bd_install_command_darwin_arm64 PASSED [ 57%] +tests/unit/test_prereqs.py::test_bd_install_command_darwin_amd64_has_no_published_asset PASSED [ 57%] +tests/unit/test_prereqs.py::test_dolt_install_command_linux_amd64_matches_ci_asset_shape PASSED [ 57%] +tests/unit/test_prereqs.py::test_dolt_install_command_darwin_arm64 PASSED [ 57%] +tests/unit/test_prereqs.py::test_check_returns_none_when_bd_and_dolt_both_satisfied PASSED [ 58%] +tests/unit/test_prereqs.py::test_check_reports_bd_missing_when_path_has_neither_binary PASSED [ 58%] +tests/unit/test_prereqs.py::test_check_prefers_bd_missing_over_dolt_missing PASSED [ 58%] +tests/unit/test_prereqs.py::test_check_reports_bd_too_old_via_forged_version_string PASSED [ 58%] +tests/unit/test_prereqs.py::test_check_reports_bd_too_old_when_version_unparseable PASSED [ 58%] +tests/unit/test_prereqs.py::test_check_reports_dolt_missing_when_bd_ok_but_dolt_absent PASSED [ 58%] +tests/unit/test_prereqs.py::test_check_never_raises_for_a_missing_binary PASSED [ 58%] +tests/unit/test_prereqs.py::test_ci_workflow_pins_match_our_constants PASSED [ 58%] +tests/unit/test_project_summary_data.py::test_ready_age_buckets_sum_equals_ready_including_fractional_days PASSED [ 58%] +tests/unit/test_project_summary_data.py::test_ready_age_buckets_bands_are_floor_day_and_contiguous PASSED [ 58%] +tests/unit/test_project_summary_data.py::test_ready_age_buckets_undated_item_goes_to_unknown_not_dropped PASSED [ 58%] +tests/unit/test_project_summary_data.py::test_ready_age_buckets_counts_only_open_work_lane_items PASSED [ 58%] +tests/unit/test_project_summary_data.py::test_resolved_throughput_counts_within_windows PASSED [ 59%] +tests/unit/test_project_summary_data.py::test_resolved_throughput_honest_zero_when_no_resolutions PASSED [ 59%] +tests/unit/test_project_summary_data.py::test_resolved_throughput_honest_zero_when_all_resolutions_are_old PASSED [ 59%] +tests/unit/test_project_summary_data.py::test_resolved_throughput_none_when_resolved_but_undated PASSED [ 59%] +tests/unit/test_project_summary_data.py::test_last_activity_uses_most_recent_timestamp_of_any_kind PASSED [ 59%] +tests/unit/test_project_summary_data.py::test_last_activity_none_when_no_timestamps_anywhere PASSED [ 59%] +tests/unit/test_project_summary_data.py::test_project_summary_creating_is_distinct_and_counts_none PASSED [ 59%] +tests/unit/test_project_summary_data.py::test_project_summary_broken_is_distinct_and_counts_none PASSED [ 59%] +tests/unit/test_project_summary_data.py::test_parse_dolt_timestamp_matches_the_bd_iso_parse_for_the_same_instant PASSED [ 59%] +tests/unit/test_project_summary_data.py::test_parse_dolt_timestamp_is_aware_utc_so_summary_arithmetic_never_raises PASSED [ 59%] +tests/unit/test_project_summary_data.py::test_parse_dolt_timestamp_none_for_empty_null_and_garbage PASSED [ 59%] +tests/unit/test_redaction.py::test_redact_email PASSED [ 59%] +tests/unit/test_redaction.py::test_redact_path_home PASSED [ 60%] +tests/unit/test_redaction.py::test_redact_path_users PASSED [ 60%] +tests/unit/test_redaction.py::test_redact_ssn PASSED [ 60%] +tests/unit/test_redaction.py::test_redact_card_number PASSED [ 60%] +tests/unit/test_redaction.py::test_redact_phone_number PASSED [ 60%] +tests/unit/test_redaction.py::test_redact_secret_looking_token PASSED [ 60%] +tests/unit/test_redaction.py::test_redact_empty_string_is_a_noop PASSED [ 60%] +tests/unit/test_redaction.py::test_redact_clean_text_has_no_placeholders_and_no_counts PASSED [ 60%] +tests/unit/test_redaction.py::test_redact_multiple_pii_classes_in_one_string_all_counted PASSED [ 60%] +tests/unit/test_redaction.py::test_redact_repeated_same_class_counts_all_occurrences PASSED [ 60%] +tests/unit/test_redaction.py::test_redact_context_flat_string_field PASSED [ 60%] +tests/unit/test_redaction.py::test_redact_context_nested_dict_field_is_redacted PASSED [ 60%] +tests/unit/test_redaction.py::test_redact_context_list_of_strings_is_redacted PASSED [ 61%] +tests/unit/test_redaction.py::test_redact_context_non_string_values_pass_through_untouched PASSED [ 61%] +tests/unit/test_redaction.py::test_redact_context_aggregates_counts_across_nested_and_sibling_fields PASSED [ 61%] +tests/unit/test_redaction.py::test_redact_context_deeply_nested_dict_still_redacted PASSED [ 61%] +tests/unit/test_reopen_preconditions.py::test_reopen_refuses_anything_that_is_not_resolved[open] PASSED [ 61%] +tests/unit/test_reopen_preconditions.py::test_reopen_refuses_anything_that_is_not_resolved[held] PASSED [ 61%] +tests/unit/test_reopen_preconditions.py::test_reopen_refuses_anything_that_is_not_resolved[blocked] PASSED [ 61%] +tests/unit/test_reopen_preconditions.py::test_reopen_refuses_anything_that_is_not_resolved[deferred] PASSED [ 61%] +tests/unit/test_reopen_preconditions.py::test_reopen_refuses_an_empty_reason_before_reading_anything[] PASSED [ 61%] +tests/unit/test_reopen_preconditions.py::test_reopen_refuses_an_empty_reason_before_reading_anything[ ] PASSED [ 61%] +tests/unit/test_reopen_preconditions.py::test_reopen_refuses_an_empty_reason_before_reading_anything[\n\t ] PASSED [ 61%] +tests/unit/test_reopen_preconditions.py::test_reopen_archives_the_verbatim_previous_record_before_transitioning PASSED [ 61%] +tests/unit/test_reopen_preconditions.py::test_reopen_refuses_to_report_success_if_the_item_is_still_resolved PASSED [ 62%] +tests/unit/test_reopen_preconditions.py::test_reopen_archives_a_blank_previous_resolution_explicitly PASSED [ 62%] +tests/unit/test_resolve_text_compare.py::test_norm_resolution_unifies_line_endings_and_strips_outer_whitespace PASSED [ 62%] +tests/unit/test_resolve_text_compare.py::test_norm_resolution_keeps_case_and_internal_whitespace_significant PASSED [ 62%] +tests/unit/test_resolve_text_compare.py::test_resolution_landed_is_true_only_for_the_same_text PASSED [ 62%] +tests/unit/test_resolve_text_compare.py::test_echo_resolution_truncates_loudly_never_silently PASSED [ 62%] +tests/unit/test_resolve_text_compare.py::test_divergent_error_message_carries_everything_a_caller_needs PASSED [ 62%] +tests/unit/test_resolve_text_compare.py::test_divergent_text_on_a_closed_item_refuses_and_writes_nothing PASSED [ 62%] +tests/unit/test_resolve_text_compare.py::test_identical_text_on_a_closed_item_is_an_idempotent_success_with_no_write PASSED [ 62%] +tests/unit/test_resolve_text_compare.py::test_resolving_an_open_item_is_unchanged PASSED [ 62%] +tests/unit/test_resolve_text_compare.py::test_post_write_readback_refuses_when_the_stored_text_is_not_ours PASSED [ 62%] +tests/unit/test_resolve_text_compare.py::test_contended_path_reports_success_only_when_our_own_text_landed PASSED [ 62%] +tests/unit/test_resolve_text_compare.py::test_contended_path_raises_when_the_readback_text_is_not_ours PASSED [ 63%] +tests/unit/test_resolve_text_compare.py::test_contended_path_still_reraises_when_the_item_never_closed PASSED [ 63%] +tests/unit/test_resolve_text_compare.py::test_resolve_returns_an_item_for_every_existing_caller PASSED [ 63%] +tests/unit/test_service.py::test_resolve_root_expands_and_resolves PASSED [ 63%] +tests/unit/test_service.py::test_resolve_root_accepts_path_object PASSED [ 63%] +tests/unit/test_service.py::test_serve_argv_tail_bakes_root_as_argument_not_env PASSED [ 63%] +tests/unit/test_service.py::test_serve_argv_tail_includes_optional_dolt_host_and_port PASSED [ 63%] +tests/unit/test_service.py::test_serve_argv_tail_omits_dolt_flags_when_not_given PASSED [ 63%] +tests/unit/test_service.py::test_serve_argv_tail_omits_every_web_flag_when_web_port_not_given PASSED [ 63%] +tests/unit/test_service.py::test_serve_argv_tail_bakes_web_port_and_defaults PASSED [ 63%] +tests/unit/test_service.py::test_serve_argv_tail_bakes_every_web_flag_when_given PASSED [ 63%] +tests/unit/test_service.py::test_serve_argv_tail_omits_web_host_public_auth_ttl_when_only_web_port_given PASSED [ 63%] +tests/unit/test_service.py::test_systemd_unit_content_bakes_web_flags_into_exec_start PASSED [ 64%] +tests/unit/test_service.py::test_systemd_unit_content_omits_web_flags_when_web_port_not_given PASSED [ 64%] +tests/unit/test_service.py::test_resolve_web_tls_returns_none_none_when_neither_given_and_no_default_cert PASSED [ 64%] +tests/unit/test_service.py::test_resolve_web_tls_auto_detects_setup_tls_defaults_when_present PASSED [ 64%] +tests/unit/test_service.py::test_resolve_web_tls_validates_explicit_paths_exist PASSED [ 64%] +tests/unit/test_service.py::test_resolve_web_tls_raises_for_missing_explicit_cert PASSED [ 64%] +tests/unit/test_service.py::test_resolve_web_tls_raises_when_only_cert_given PASSED [ 64%] +tests/unit/test_service.py::test_resolve_web_tls_raises_when_only_key_given PASSED [ 64%] +tests/unit/test_service.py::test_serve_argv_tail_bakes_web_tls_flags_when_given PASSED [ 64%] +tests/unit/test_service.py::test_serve_argv_tail_omits_web_tls_flags_when_not_given PASSED [ 64%] +tests/unit/test_service.py::test_serve_argv_tail_omits_web_tls_flags_even_with_web_port_none PASSED [ 64%] +tests/unit/test_service.py::test_systemd_unit_content_bakes_web_tls_flags_into_exec_start PASSED [ 64%] +tests/unit/test_service.py::test_serve_argv_tail_bakes_web_http_port_when_given PASSED [ 65%] +tests/unit/test_service.py::test_serve_argv_tail_omits_web_http_port_when_not_given PASSED [ 65%] +tests/unit/test_service.py::test_serve_argv_tail_omits_web_http_port_even_with_web_port_none PASSED [ 65%] +tests/unit/test_service.py::test_systemd_unit_content_bakes_web_http_port_into_exec_start PASSED [ 65%] +tests/unit/test_service.py::test_systemd_analyze_verify_clean_with_web_http_port_baked_in PASSED [ 65%] +tests/unit/test_service.py::test_systemd_analyze_verify_clean_with_web_tls_flags_baked_in PASSED [ 65%] +tests/unit/test_service.py::test_service_install_raises_tls_config_error_for_incomplete_tls_pair PASSED [ 65%] +tests/unit/test_service.py::test_systemd_analyze_verify_clean_with_web_flags_baked_in PASSED [ 65%] +tests/unit/test_service.py::test_resolve_bin_tokens_never_returns_a_single_shell_string PASSED [ 65%] +tests/unit/test_service.py::test_systemd_unit_template_has_no_environment_line_for_root PASSED [ 65%] +tests/unit/test_service.py::test_systemd_unit_template_uses_restart_always_not_on_failure PASSED [ 65%] +tests/unit/test_service.py::test_windows_is_reported_as_unsupported_not_raised PASSED [ 65%] +tests/unit/test_service.py::test_service_install_raises_service_unsupported_on_windows PASSED [ 66%] +tests/unit/test_service.py::test_no_systemctl_is_reported_as_unsupported_on_linux PASSED [ 66%] +tests/unit/test_service.py::test_darwin_describe_dispatches_to_launchd PASSED [ 66%] +tests/unit/test_service.py::test_resolve_bin_tokens_prefers_console_script_when_present PASSED [ 66%] +tests/unit/test_service.py::test_resolve_console_script_reports_nothing_when_on_path PASSED [ 66%] +tests/unit/test_service.py::test_resolve_console_script_finds_unlinked_uv_tool_install PASSED [ 66%] +tests/unit/test_service.py::test_resolve_console_script_reports_nothing_when_truly_absent PASSED [ 66%] +tests/unit/test_service.py::test_resolve_bin_tokens_falls_back_to_module_invocation_as_separate_tokens PASSED [ 66%] +tests/unit/test_service.py::test_systemd_exec_start_never_quotes_the_module_fallback_as_one_token PASSED [ 66%] +tests/unit/test_service.py::test_systemd_analyze_verify_clean_for_console_script_resolution_path PASSED [ 66%] +tests/unit/test_service.py::test_systemd_analyze_verify_clean_for_module_fallback_resolution_path PASSED [ 66%] +tests/unit/test_service.py::test_systemd_install_rolls_back_unit_file_when_systemctl_fails PASSED [ 66%] +tests/unit/test_service.py::test_systemd_install_attaches_observed_rollback_detail_on_success PASSED [ 67%] +tests/unit/test_service.py::test_systemd_install_rollback_detail_reports_a_failed_rollback_step_honestly PASSED [ 67%] +tests/unit/test_service.py::test_service_install_propagates_the_failure_after_rollback PASSED [ 67%] +tests/unit/test_service.py::test_resolve_console_script_interpreter_reads_the_shebang PASSED [ 67%] +tests/unit/test_service.py::test_resolve_console_script_interpreter_returns_sys_executable_for_module_fallback PASSED [ 67%] +tests/unit/test_service.py::test_resolve_console_script_interpreter_returns_none_when_no_shebang PASSED [ 67%] +tests/unit/test_service.py::test_probe_web_extra_importable_true_for_the_real_test_interpreter PASSED [ 67%] +tests/unit/test_service.py::test_probe_web_extra_importable_false_when_the_target_cannot_import PASSED [ 67%] +tests/unit/test_service.py::test_probe_web_extra_importable_false_when_interpreter_cannot_be_resolved PASSED [ 67%] +tests/unit/test_service.py::test_service_install_refuses_with_remedy_when_web_extra_not_importable PASSED [ 67%] +tests/unit/test_service.py::test_service_install_skips_the_web_extra_check_when_web_port_not_given PASSED [ 67%] +tests/unit/test_service.py::test_service_install_proceeds_when_web_extra_importable PASSED [ 67%] +tests/unit/test_supervisor.py::test_no_holders_means_proceed PASSED [ 68%] +tests/unit/test_supervisor.py::test_holders_not_responding_means_kill_stale PASSED [ 68%] +tests/unit/test_supervisor.py::test_holders_not_responding_ignores_owned_pid PASSED [ 68%] +tests/unit/test_supervisor.py::test_healthy_and_owned_means_refuse_ours PASSED [ 68%] +tests/unit/test_supervisor.py::test_healthy_and_owned_pid_present_among_multiple_holders PASSED [ 68%] +tests/unit/test_supervisor.py::test_healthy_but_not_owned_means_refuse_foreign PASSED [ 68%] +tests/unit/test_supervisor.py::test_healthy_owned_pid_recorded_but_holder_is_someone_else PASSED [ 68%] +tests/unit/test_supervisor.py::test_classification_is_exhaustive_and_returns_only_known_actions PASSED [ 68%] +tests/unit/test_supervisor.py::test_ensure_port_available_proceeds_silently_when_free PASSED [ 68%] +tests/unit/test_supervisor.py::test_ensure_port_available_kills_stale_holder PASSED [ 68%] +tests/unit/test_supervisor.py::test_ensure_port_available_refuses_ours_without_killing PASSED [ 68%] +tests/unit/test_supervisor.py::test_ensure_port_available_refuses_foreign_without_killing PASSED [ 68%] +tests/unit/test_supervisor.py::test_ensure_port_available_force_kills_unconditionally PASSED [ 69%] +tests/unit/test_supervisor.py::test_read_owned_pid_missing_file_is_none PASSED [ 69%] +tests/unit/test_supervisor.py::test_read_owned_pid_garbage_contents_is_none PASSED [ 69%] +tests/unit/test_supervisor.py::test_read_owned_pid_reads_back_written_value PASSED [ 69%] +tests/unit/test_supervisor.py::test_budget_not_exceeded_below_the_count PASSED [ 69%] +tests/unit/test_supervisor.py::test_budget_exceeded_at_the_count_within_the_window PASSED [ 69%] +tests/unit/test_supervisor.py::test_budget_never_exceeded_when_exits_are_spaced_beyond_the_window PASSED [ 69%] +tests/unit/test_supervisor.py::test_budget_trims_old_entries_before_counting PASSED [ 69%] +tests/unit/test_supervisor.py::test_dolt_supervisor_loop_gives_up_loudly_after_budget_exhausted PASSED [ 69%] +tests/unit/test_supervisor.py::test_dolt_supervisor_loop_stops_cleanly_without_raising_when_stop_requested PASSED [ 69%] +tests/unit/test_supervisor.py::test_reap_project_reclaims_stale_and_keeps_fresh PASSED [ 69%] +tests/unit/test_supervisor.py::test_reap_sweep_isolates_a_broken_project_from_the_others PASSED [ 69%] +tests/unit/test_supervisor.py::test_notify_project_flips_only_linked_unresolved_reports PASSED [ 70%] +tests/unit/test_supervisor.py::test_notify_sweep_isolates_a_broken_project_from_the_others PASSED [ 70%] +tests/unit/test_supervisor.py::test_reap_loop_records_start_before_its_first_sweep_completes PASSED [ 70%] +tests/unit/test_supervisor.py::test_reap_loop_records_completion_after_a_sweep PASSED [ 70%] +tests/unit/test_supervisor.py::test_notify_loop_records_completion_after_a_sweep PASSED [ 70%] +tests/unit/test_supervisor.py::test_reap_and_notify_loops_use_independent_heartbeat_records PASSED [ 70%] +tests/unit/test_supervisor_web.py::test_import_web_modules_returns_the_webapp_module PASSED [ 70%] +tests/unit/test_supervisor_web.py::test_import_web_modules_wraps_import_error_with_actionable_hint PASSED [ 70%] +tests/unit/test_supervisor_web.py::test_web_stop_watcher_mirrors_stop_event_into_should_exit PASSED [ 70%] +tests/unit/test_supervisor_web.py::test_web_server_loop_serves_a_reachable_dashboard_and_drains_on_stop_event PASSED [ 70%] +tests/unit/test_supervisor_web.py::test_web_server_loop_serves_https_when_tls_cert_and_key_are_given PASSED [ 70%] +tests/unit/test_supervisor_web.py::test_web_server_loop_runs_trust_bootstrap_companion_listener_when_tls_active PASSED [ 70%] +tests/unit/test_supervisor_web.py::test_web_server_loop_omits_trust_bootstrap_without_http_port PASSED [ 71%] +tests/unit/test_supervisor_web.py::test_web_server_loop_raises_web_server_startup_error_for_rejected_config PASSED [ 71%] +tests/unit/test_supervisor_web.py::test_web_server_loop_raises_web_server_startup_error_on_bind_failure PASSED [ 71%] +tests/unit/test_supervisor_web.py::test_async_serve_without_web_never_touches_web_modules PASSED [ 71%] +tests/unit/test_supervisor_web.py::test_async_serve_with_web_runs_all_four_tasks PASSED [ 71%] +tests/unit/test_supervisor_web.py::test_web_server_loop_wraps_missing_web_extra_as_web_server_startup_error PASSED [ 71%] +tests/unit/test_supervisor_web.py::test_async_serve_fails_loud_and_terminates_real_dolt_child_on_missing_web_extra PASSED [ 71%] +tests/unit/test_supervisor_web.py::test_serve_returns_1_and_prints_remedy_on_missing_web_extra PASSED [ 71%] +tests/unit/test_webapp_held_staleness.py::test_custody_reading_none_when_not_held PASSED [ 71%] +tests/unit/test_webapp_held_staleness.py::test_custody_reading_fresh_hold_uses_started_at_for_age_and_is_not_stale PASSED [ 71%] +tests/unit/test_webapp_held_staleness.py::test_custody_reading_stale_when_renewal_lapsed_past_ttl PASSED [ 71%] +tests/unit/test_webapp_held_staleness.py::test_custody_reading_ttl_boundary_exactly_at_ttl_is_still_fresh PASSED [ 72%] +tests/unit/test_webapp_held_staleness.py::test_custody_reading_no_custody_record_is_stale_and_proxied_from_updated_at PASSED [ 72%] +tests/unit/test_webapp_held_staleness.py::test_custody_reading_no_custody_record_and_no_updated_at_has_no_age_at_all PASSED [ 72%] +tests/unit/test_webapp_held_staleness.py::test_custody_reading_awaiting_human_fresh_is_not_stale_but_reports_declared_state PASSED [ 72%] +tests/unit/test_webapp_held_staleness.py::test_custody_reading_awaiting_human_past_escalation_ceiling_is_stale PASSED [ 72%] +tests/unit/test_webapp_held_staleness.py::test_custody_html_none_reading_renders_nothing PASSED [ 72%] +tests/unit/test_webapp_held_staleness.py::test_custody_html_fresh_reading_is_neutral_not_amber PASSED [ 72%] +tests/unit/test_webapp_held_staleness.py::test_custody_html_stale_reading_is_amber_and_carries_the_real_reason_as_title PASSED [ 72%] +tests/unit/test_webapp_held_staleness.py::test_custody_html_no_age_renders_held_with_no_duration PASSED [ 72%] +tests/unit/test_webapp_held_staleness.py::test_custody_html_proxy_age_is_labeled_as_a_proxy_not_a_real_duration PASSED [ 72%] +tests/unit/test_webapp_held_staleness.py::test_custody_html_fresh_awaiting_human_notes_the_ttl_clock_still_runs PASSED [ 72%] +tests/unit/test_webapp_held_staleness.py::test_custody_html_unknown_holder_degrades_honestly PASSED [ 72%] +tests/unit/test_webapp_held_staleness.py::test_item_row_held_item_shows_custody_reading_not_bare_identity PASSED [ 73%] +tests/unit/test_webapp_held_staleness.py::test_item_row_stale_held_item_shows_amber_custody_class PASSED [ 73%] +tests/unit/test_webapp_held_staleness.py::test_attention_signal_held_stale_default_is_byte_identical_to_before PASSED [ 73%] +tests/unit/test_webapp_held_staleness.py::test_attention_signal_held_stale_adds_a_parenthetical_when_nonzero PASSED [ 73%] +tests/unit/test_webapp_held_staleness.py::test_attention_signal_held_stale_zero_is_absent_not_a_dimmed_zero PASSED [ 73%] +tests/unit/test_webapp_held_staleness.py::test_attention_signal_held_stale_never_escalates_to_crimson_alone PASSED [ 73%] +tests/unit/test_webapp_held_staleness.py::test_attention_signal_held_stale_never_double_counts_the_total PASSED [ 73%] +tests/unit/test_webapp_held_staleness.py::test_held_stale_count_counts_only_reclaim_eligible_items PASSED [ 73%] +tests/unit/test_webapp_held_staleness.py::test_held_stale_count_zero_when_every_hold_is_fresh PASSED [ 73%] +tests/unit/test_webapp_held_staleness.py::test_held_stale_count_empty_list_is_zero PASSED [ 73%] +tests/unit/test_webapp_identity.py::test_humanize_identity_reduces_a_github_noreply_address_to_the_username PASSED [ 73%] +tests/unit/test_webapp_identity.py::test_humanize_identity_handles_a_hyphenated_username PASSED [ 73%] +tests/unit/test_webapp_identity.py::test_humanize_identity_leaves_an_ordinary_actor_name_unchanged PASSED [ 74%] +tests/unit/test_webapp_identity.py::test_humanize_identity_leaves_a_non_noreply_email_unchanged PASSED [ 74%] +tests/unit/test_webapp_identity.py::test_humanize_identity_handles_empty_and_none PASSED [ 74%] +tests/unit/test_webapp_identity.py::test_humanize_identity_strips_surrounding_whitespace PASSED [ 74%] +tests/unit/test_webapp_identity.py::test_identity_html_wraps_a_humanized_noreply_identity_with_a_raw_tooltip PASSED [ 74%] +tests/unit/test_webapp_identity.py::test_identity_html_renders_an_ordinary_identity_as_plain_escaped_text_only PASSED [ 74%] +tests/unit/test_webapp_identity.py::test_identity_html_escapes_html_special_characters PASSED [ 74%] +tests/unit/test_webapp_identity.py::test_identity_html_returns_empty_string_for_missing_identity PASSED [ 74%] +tests/unit/test_webapp_item_render.py::test_render_item_markdown_converts_bold PASSED [ 74%] +tests/unit/test_webapp_item_render.py::test_render_item_markdown_converts_inline_code PASSED [ 74%] +tests/unit/test_webapp_item_render.py::test_render_item_markdown_converts_fenced_code_block_and_preserves_alignment PASSED [ 74%] +tests/unit/test_webapp_item_render.py::test_render_item_markdown_converts_headings_to_subordinate_tags PASSED [ 74%] +tests/unit/test_webapp_item_render.py::test_render_item_markdown_leaves_plain_text_unchanged PASSED [ 75%] +tests/unit/test_webapp_item_render.py::test_render_item_markdown_escapes_html_before_processing_markdown PASSED [ 75%] +tests/unit/test_webapp_item_render.py::test_render_item_markdown_does_not_process_markdown_inside_code_blocks PASSED [ 75%] +tests/unit/test_webapp_item_render.py::test_render_item_markdown_preserves_newlines_for_the_pre_wrap_container PASSED [ 75%] +tests/unit/test_webapp_item_render.py::test_content_block_html_shows_empty_message_when_text_is_none PASSED [ 75%] +tests/unit/test_webapp_item_render.py::test_content_block_html_shows_empty_message_when_text_is_empty_string PASSED [ 75%] +tests/unit/test_webapp_item_render.py::test_content_block_html_renders_provided_text_with_monospace_and_measure PASSED [ 75%] +tests/unit/test_webapp_item_render.py::test_content_block_html_renders_markdown_inside_the_block PASSED [ 75%] +tests/unit/test_webapp_item_render.py::test_fact_value_html_escapes_and_is_non_interactive PASSED [ 75%] +tests/unit/test_webapp_item_render.py::test_fact_value_html_escapes_html_special_characters PASSED [ 75%] +tests/unit/test_webapp_item_render.py::test_item_row_never_concatenates_id_and_title_without_a_separator PASSED [ 75%] +tests/unit/test_webapp_item_render.py::test_item_row_has_separate_id_and_title_cells PASSED [ 75%] +tests/unit/test_webapp_item_render.py::test_dependency_sections_empty_links_renders_nothing PASSED [ 76%] +tests/unit/test_webapp_item_render.py::test_dependency_sections_unsatisfied_blocker_is_crimson_and_shows_holder PASSED [ 76%] +tests/unit/test_webapp_item_render.py::test_dependency_sections_unsatisfied_blocker_falls_back_to_reporter_when_not_held PASSED [ 76%] +tests/unit/test_webapp_item_render.py::test_dependency_sections_satisfied_blocker_is_neutral_with_check_mark PASSED [ 76%] +tests/unit/test_webapp_item_render.py::test_dependency_sections_discovered_from_is_a_neutral_note_not_a_blocker PASSED [ 76%] +tests/unit/test_webapp_item_render.py::test_dependency_sections_blocks_inverse_is_cheap_and_neutral PASSED [ 76%] +tests/unit/test_webapp_item_render.py::test_dependency_sections_other_type_falls_back_to_generic_links_list PASSED [ 76%] +tests/unit/test_webapp_item_render.py::test_dependency_sections_missing_id_is_skipped_not_rendered_as_broken_link PASSED [ 76%] +tests/unit/test_webapp_item_render.py::test_dependency_sections_blocks_uses_link_chip_grid PASSED [ 76%] +tests/unit/test_webapp_item_render.py::test_dependency_sections_related_type_gets_its_own_column PASSED [ 76%] +tests/unit/test_webapp_item_render.py::test_dependency_sections_no_blocks_or_related_renders_no_links_grid PASSED [ 76%] +tests/unit/test_webapp_item_render.py::test_activity_feed_empty_list_renders_nothing PASSED [ 76%] +tests/unit/test_webapp_item_render.py::test_activity_feed_renders_summary_actor_and_detail PASSED [ 77%] +tests/unit/test_webapp_item_render.py::test_activity_feed_does_not_render_its_own_heading PASSED [ 77%] +tests/unit/test_webapp_item_render.py::test_activity_feed_preserves_caller_supplied_order PASSED [ 77%] +tests/unit/test_webapp_list_polish.py::test_status_tab_counts_mirrors_the_real_project_summary PASSED [ 77%] +tests/unit/test_webapp_list_polish.py::test_status_tab_counts_all_zero_for_a_broken_or_creating_project PASSED [ 77%] +tests/unit/test_webapp_list_polish.py::test_status_tab_counts_none_fields_become_zero_not_none PASSED [ 77%] +tests/unit/test_webapp_list_polish.py::test_status_tabs_html_shows_all_six_tabs_with_real_counts PASSED [ 77%] +tests/unit/test_webapp_list_polish.py::test_status_tabs_html_zero_count_is_dimmed_not_hidden PASSED [ 77%] +tests/unit/test_webapp_list_polish.py::test_status_tabs_html_held_turns_amber_when_nonzero PASSED [ 77%] +tests/unit/test_webapp_list_polish.py::test_status_tabs_html_blocked_turns_crimson_when_nonzero PASSED [ 77%] +tests/unit/test_webapp_list_polish.py::test_status_tabs_html_ready_and_resolved_never_get_an_alarm_class_even_when_large PASSED [ 77%] +tests/unit/test_webapp_list_polish.py::test_status_tabs_html_active_tab_is_marked PASSED [ 77%] +tests/unit/test_webapp_list_polish.py::test_status_tabs_html_all_tab_is_active_when_no_status_filter PASSED [ 78%] +tests/unit/test_webapp_list_polish.py::test_status_tabs_html_clicking_a_tab_filters_via_status_query_param PASSED [ 78%] +tests/unit/test_webapp_list_polish.py::test_status_tabs_html_carries_an_active_search_through PASSED [ 78%] +tests/unit/test_webapp_list_polish.py::test_tab_href_all_tab_with_no_search_has_no_query_string PASSED [ 78%] +tests/unit/test_webapp_list_polish.py::test_tab_href_all_tab_with_a_search_carries_only_q PASSED [ 78%] +tests/unit/test_webapp_list_polish.py::test_item_age_html_none_renders_the_shared_empty_glyph PASSED [ 78%] +tests/unit/test_webapp_list_polish.py::test_item_age_html_fresh_item_reads_now_not_0m PASSED [ 78%] +tests/unit/test_webapp_list_polish.py::test_item_age_html_uses_the_same_compact_units_as_the_row_age_column PASSED [ 78%] +tests/unit/test_webapp_list_polish.py::test_item_age_html_days_matches_age_short PASSED [ 78%] +tests/unit/test_webapp_list_polish.py::test_item_age_html_carries_the_real_iso_timestamp_as_a_title PASSED [ 78%] +tests/unit/test_webapp_list_polish.py::test_item_age_html_never_escalates_to_the_amber_alarm_tier PASSED [ 78%] +tests/unit/test_webapp_list_polish.py::test_item_age_html_moderately_old_still_reads_a2 PASSED [ 78%] +tests/unit/test_webapp_list_polish.py::test_priority_bar_html_maps_each_bd_priority_to_its_ramp_step[0-p0] PASSED [ 79%] +tests/unit/test_webapp_list_polish.py::test_priority_bar_html_maps_each_bd_priority_to_its_ramp_step[1-p1] PASSED [ 79%] +tests/unit/test_webapp_list_polish.py::test_priority_bar_html_maps_each_bd_priority_to_its_ramp_step[2-p2] PASSED [ 79%] +tests/unit/test_webapp_list_polish.py::test_priority_bar_html_maps_each_bd_priority_to_its_ramp_step[3-p3] PASSED [ 79%] +tests/unit/test_webapp_list_polish.py::test_priority_bar_html_maps_each_bd_priority_to_its_ramp_step[4-p4] PASSED [ 79%] +tests/unit/test_webapp_list_polish.py::test_priority_bar_html_none_degrades_honestly_to_the_faint_neutral PASSED [ 79%] +tests/unit/test_webapp_list_polish.py::test_priority_bar_html_out_of_range_value_also_degrades_honestly PASSED [ 79%] +tests/unit/test_webapp_list_polish.py::test_priority_bar_html_never_uses_the_reserved_amber_or_crimson_hues PASSED [ 79%] +tests/unit/test_webapp_list_polish.py::test_status_icon_html_reuses_the_same_colour_class_as_the_text_badge[open-st-open] PASSED [ 79%] +tests/unit/test_webapp_list_polish.py::test_status_icon_html_reuses_the_same_colour_class_as_the_text_badge[held-st-held] PASSED [ 79%] +tests/unit/test_webapp_list_polish.py::test_status_icon_html_reuses_the_same_colour_class_as_the_text_badge[blocked-st-blkd] PASSED [ 79%] +tests/unit/test_webapp_list_polish.py::test_status_icon_html_reuses_the_same_colour_class_as_the_text_badge[deferred-st-deferred] PASSED [ 79%] +tests/unit/test_webapp_list_polish.py::test_status_icon_html_reuses_the_same_colour_class_as_the_text_badge[resolved-st-done] PASSED [ 80%] +tests/unit/test_webapp_list_polish.py::test_item_row_includes_a_priority_bar_and_status_icon_gutter_cell PASSED [ 80%] +tests/unit/test_webapp_list_polish.py::test_item_row_gutter_degrades_honestly_when_priority_is_missing PASSED [ 80%] +tests/unit/test_webapp_nav_density.py::test_sidebar_open_total_is_total_minus_resolved PASSED [ 80%] +tests/unit/test_webapp_nav_density.py::test_sidebar_open_total_none_for_broken_project PASSED [ 80%] +tests/unit/test_webapp_nav_density.py::test_sidebar_open_total_none_for_missing_summary PASSED [ 80%] +tests/unit/test_webapp_nav_density.py::test_sidebar_open_total_never_goes_negative PASSED [ 80%] +tests/unit/test_webapp_nav_density.py::test_sidebar_open_total_none_fields_become_zero PASSED [ 80%] +tests/unit/test_webapp_nav_density.py::test_sidebar_alarm_class_blank_when_calm PASSED [ 80%] +tests/unit/test_webapp_nav_density.py::test_sidebar_alarm_class_amber_when_held PASSED [ 80%] +tests/unit/test_webapp_nav_density.py::test_sidebar_alarm_class_crimson_when_blocked PASSED [ 80%] +tests/unit/test_webapp_nav_density.py::test_sidebar_alarm_class_blocked_outranks_held PASSED [ 80%] +tests/unit/test_webapp_nav_density.py::test_sidebar_alarm_class_blank_for_broken_project PASSED [ 81%] +tests/unit/test_webapp_nav_density.py::test_sidebar_alarm_class_blank_for_missing_summary PASSED [ 81%] +tests/unit/test_webapp_nav_density.py::test_sidebar_html_lists_every_project_alphabetically PASSED [ 81%] +tests/unit/test_webapp_nav_density.py::test_sidebar_html_rollup_shows_real_summed_open_total PASSED [ 81%] +tests/unit/test_webapp_nav_density.py::test_sidebar_html_rollup_excludes_broken_projects_from_the_total PASSED [ 81%] +tests/unit/test_webapp_nav_density.py::test_sidebar_html_shows_open_over_total_badge_per_row PASSED [ 81%] +tests/unit/test_webapp_nav_density.py::test_sidebar_html_broken_project_badge_is_an_honest_dash PASSED [ 81%] +tests/unit/test_webapp_nav_density.py::test_sidebar_html_marks_current_project_row_not_the_rollup PASSED [ 81%] +tests/unit/test_webapp_nav_density.py::test_sidebar_html_marks_rollup_current_on_the_dashboard PASSED [ 81%] +tests/unit/test_webapp_nav_density.py::test_sidebar_html_alarm_marker_reaches_the_row_class PASSED [ 81%] +tests/unit/test_webapp_nav_density.py::test_sidebar_html_calm_project_carries_no_alarm_class PASSED [ 81%] +tests/unit/test_webapp_nav_density.py::test_sidebar_html_empty_workspace_renders_a_zero_rollup_and_no_rows PASSED [ 81%] +tests/unit/test_webapp_nav_density.py::test_sidebar_html_escapes_project_names PASSED [ 82%] +tests/unit/test_webapp_nav_density.py::test_sidebar_html_includes_the_narrow_width_checkbox_toggle PASSED [ 82%] +tests/unit/test_webapp_nav_density.py::test_search_field_shows_a_slash_shortcut_hint_by_default PASSED [ 82%] +tests/unit/test_webapp_nav_density.py::test_search_field_aria_label_never_carries_the_shortcut_hint PASSED [ 82%] +tests/unit/test_webapp_nav_density.py::test_search_field_shortcut_can_be_suppressed PASSED [ 82%] +tests/unit/test_webapp_nav_density.py::test_density_toggle_html_default_is_unpressed PASSED [ 82%] +tests/unit/test_webapp_nav_density.py::test_list_controls_js_uses_the_dedicated_localstorage_key PASSED [ 82%] +tests/unit/test_webapp_nav_density.py::test_list_controls_js_has_its_own_dedicated_bind_once_guard PASSED [ 82%] +tests/unit/test_webapp_nav_density.py::test_list_controls_js_guards_row_nav_keys_against_focused_fields PASSED [ 82%] +tests/unit/test_webapp_nav_density.py::test_list_controls_js_respects_reduced_motion_for_scrolling PASSED [ 82%] +tests/unit/test_webapp_nav_density.py::test_list_controls_js_targets_the_shared_row_selector PASSED [ 82%] +tests/unit/test_webapp_setup.py::test_unauthenticated_get_setup_redirects_to_login PASSED [ 82%] +tests/unit/test_webapp_setup.py::test_unauthenticated_get_setup_refused_json PASSED [ 83%] +tests/unit/test_webapp_setup.py::test_unauthenticated_post_setup_tls_refused_json PASSED [ 83%] +tests/unit/test_webapp_setup.py::test_unauthenticated_get_ca_crt_refused_json PASSED [ 83%] +tests/unit/test_webapp_setup.py::test_authenticated_get_setup_succeeds PASSED [ 83%] +tests/unit/test_webapp_setup.py::test_dashboard_chrome_links_to_setup_when_authenticated PASSED [ 83%] +tests/unit/test_webapp_setup.py::test_setup_status_shows_http_and_no_cert_note_when_nothing_configured PASSED [ 83%] +tests/unit/test_webapp_setup.py::test_setup_status_reports_https_scheme_from_the_real_request PASSED [ 83%] +tests/unit/test_webapp_setup.py::test_setup_status_labels_self_signed_certificate PASSED [ 83%] +tests/unit/test_webapp_setup.py::test_setup_status_flags_stale_cert_when_scheme_is_still_http PASSED [ 83%] +tests/unit/test_webapp_setup.py::test_setup_status_labels_local_ca_signed_certificate_and_offers_download PASSED [ 83%] +tests/unit/test_webapp_setup.py::test_setup_status_expiring_soon_certificate_is_flagged PASSED [ 83%] +tests/unit/test_webapp_setup.py::test_setup_status_expired_certificate_is_flagged PASSED [ 83%] +tests/unit/test_webapp_setup.py::test_setup_shows_all_three_real_methods_and_never_mkcert PASSED [ 84%] +tests/unit/test_webapp_setup.py::test_setup_shows_tailscale_disabled_when_unavailable PASSED [ 84%] +tests/unit/test_webapp_setup.py::test_setup_shows_tailscale_available_with_detected_hostname PASSED [ 84%] +tests/unit/test_webapp_setup.py::test_post_setup_tls_selfsigned_generates_a_real_cert_in_the_isolated_home PASSED [ 84%] +tests/unit/test_webapp_setup.py::test_post_setup_tls_ca_generates_both_ca_and_leaf PASSED [ 84%] +tests/unit/test_webapp_setup.py::test_post_setup_tls_unknown_method_is_refused_with_400 PASSED [ 84%] +tests/unit/test_webapp_setup.py::test_post_setup_tls_tailscale_unavailable_is_refused_with_400 PASSED [ 84%] +tests/unit/test_webapp_setup.py::test_post_setup_tls_does_not_touch_the_real_developer_home PASSED [ 84%] +tests/unit/test_webapp_setup.py::test_ca_crt_route_404s_when_no_ca_is_configured PASSED [ 84%] +tests/unit/test_webapp_setup.py::test_ca_crt_route_serves_a_valid_pem_when_ca_is_configured PASSED [ 84%] +tests/unit/test_webapp_setup.py::test_recommended_method_is_tailscale_when_available PASSED [ 84%] +tests/unit/test_webapp_setup.py::test_recommended_method_is_local_ca_when_tailscale_unavailable PASSED [ 84%] +tests/unit/test_webapp_setup.py::test_setup_shows_friction_spectrum_framing PASSED [ 85%] +tests/unit/test_webapp_setup.py::test_setup_recommends_tailscale_when_available PASSED [ 85%] +tests/unit/test_webapp_setup.py::test_setup_recommends_local_ca_when_tailscale_unavailable PASSED [ 85%] +tests/unit/test_webapp_setup.py::test_trust_bootstrap_url_uses_configured_web_http_port_when_known PASSED [ 85%] +tests/unit/test_webapp_setup.py::test_trust_bootstrap_url_falls_back_to_https_port_plus_one_pattern PASSED [ 85%] +tests/unit/test_webapp_setup.py::test_trust_bootstrap_url_pattern_uses_explicit_https_port PASSED [ 85%] +tests/unit/test_webapp_setup.py::test_setup_ca_section_omits_trust_cross_link_when_no_ca_configured PASSED [ 85%] +tests/unit/test_webapp_tls.py::test_resolve_web_config_defaults_to_no_tls_when_nothing_configured PASSED [ 85%] +tests/unit/test_webapp_tls.py::test_resolve_web_config_uses_explicit_tls_cert_and_key PASSED [ 85%] +tests/unit/test_webapp_tls.py::test_resolve_web_config_raises_for_missing_explicit_cert PASSED [ 85%] +tests/unit/test_webapp_tls.py::test_resolve_web_config_raises_for_missing_explicit_key PASSED [ 85%] +tests/unit/test_webapp_tls.py::test_resolve_web_config_raises_when_only_tls_cert_given PASSED [ 86%] +tests/unit/test_webapp_tls.py::test_resolve_web_config_raises_when_only_tls_key_given PASSED [ 86%] +tests/unit/test_webapp_tls.py::test_resolve_web_config_never_silently_falls_back_to_http_for_missing_explicit_cert PASSED [ 86%] +tests/unit/test_webapp_tls.py::test_resolve_web_config_raises_for_unreadable_explicit_cert PASSED [ 86%] +tests/unit/test_webapp_tls.py::test_resolve_web_config_auto_detects_setup_tls_default_cert PASSED [ 86%] +tests/unit/test_webapp_tls.py::test_resolve_web_config_ignores_a_half_present_default_cert PASSED [ 86%] +tests/unit/test_webapp_tls.py::test_resolve_web_config_explicit_paths_take_priority_over_auto_detected PASSED [ 86%] +tests/unit/test_webapp_tls.py::test_run_passes_ssl_kwargs_to_uvicorn_when_tls_configured PASSED [ 86%] +tests/unit/test_webapp_tls.py::test_run_omits_ssl_kwargs_when_no_tls_configured PASSED [ 86%] +tests/unit/test_webapp_tls.py::test_resolve_http_bootstrap_port_none_when_no_tls PASSED [ 86%] +tests/unit/test_webapp_tls.py::test_resolve_http_bootstrap_port_defaults_to_port_plus_one_when_tls_active PASSED [ 86%] +tests/unit/test_webapp_tls.py::test_resolve_http_bootstrap_port_uses_explicit_value_when_tls_active PASSED [ 86%] +tests/unit/test_webapp_tls.py::test_resolve_http_bootstrap_port_raises_on_collision_with_https_port PASSED [ 87%] +tests/unit/test_webapp_tls.py::test_resolve_web_config_no_trust_bootstrap_message_without_tls PASSED [ 87%] +tests/unit/test_webapp_tls.py::test_resolve_web_config_defaults_trust_bootstrap_port_when_tls_active PASSED [ 87%] +tests/unit/test_webapp_tls.py::test_resolve_web_config_uses_explicit_http_port_when_tls_active PASSED [ 87%] +tests/unit/test_webapp_tls.py::test_resolve_web_config_ignores_http_port_without_tls_but_notes_it PASSED [ 87%] +tests/unit/test_webapp_tls.py::test_resolve_web_config_raises_on_http_port_colliding_with_https_port PASSED [ 87%] +tests/unit/test_webapp_tls.py::test_run_starts_both_servers_when_http_port_is_set PASSED [ 87%] +tests/unit/test_webbrowse_render.py::test_item_row_links_directly_to_l2_and_strips_project_prefix PASSED [ 87%] +tests/unit/test_webbrowse_render.py::test_item_row_status_chip_differs_by_status PASSED [ 87%] +tests/unit/test_webbrowse_render.py::test_item_row_holder_shows_blocked_by_id_when_blocked PASSED [ 87%] +tests/unit/test_webbrowse_render.py::test_item_row_holder_absent_for_resolved_item_with_leftover_holder PASSED [ 87%] +tests/unit/test_webbrowse_render.py::test_status_tabs_render_all_seven_with_real_counts PASSED [ 87%] +tests/unit/test_webbrowse_render.py::test_status_tabs_marks_the_active_one PASSED [ 88%] +tests/unit/test_webbrowse_render.py::test_status_tab_counts_zero_for_impaired_summary PASSED [ 88%] +tests/unit/test_webbrowse_render.py::test_agent_panel_groups_by_agent_stalest_first PASSED [ 88%] +tests/unit/test_webbrowse_render.py::test_ready_age_histogram_data_flags_the_7_plus_bucket PASSED [ 88%] +tests/unit/test_webbrowse_render.py::test_ready_age_histogram_omits_flag_note_when_nothing_aging PASSED [ 88%] +tests/unit/test_webpush.py::test_push_send_alarm_request_shape_and_headers PASSED [ 88%] +tests/unit/test_webpush.py::test_push_default_priority_is_urgent PASSED [ 88%] +tests/unit/test_webpush.py::test_push_bearer_absent_when_no_token PASSED [ 88%] +tests/unit/test_webpush.py::test_push_utf8_body_is_encoded PASSED [ 88%] +tests/unit/test_webpush.py::test_push_omits_tags_and_click_when_absent PASSED [ 88%] +tests/unit/test_webpush.py::test_push_disabled_channel_is_noop PASSED [ 88%] +tests/unit/test_webpush.py::test_push_enabled_without_topic_raises_config_error PASSED [ 88%] +tests/unit/test_webpush.py::test_push_retries_on_5xx_then_succeeds PASSED [ 89%] +tests/unit/test_webpush.py::test_push_retries_on_429_then_succeeds PASSED [ 89%] +tests/unit/test_webpush.py::test_push_retries_on_network_error_then_succeeds PASSED [ 89%] +tests/unit/test_webpush.py::test_push_loud_fail_after_exhausting_retries PASSED [ 89%] +tests/unit/test_webpush.py::test_push_non_transient_4xx_fails_immediately_without_retry PASSED [ 89%] +tests/unit/test_webpush.py::test_push_loud_fail_on_persistent_network_error PASSED [ 89%] +tests/unit/test_webpush.py::test_push_max_attempts_one_does_not_retry PASSED [ 89%] +tests/unit/test_webpush.py::test_push_resolve_config_defaults_and_secrets_env_only PASSED [ 89%] +tests/unit/test_webpush.py::test_push_resolve_config_overrides_and_url_join PASSED [ 89%] +tests/unit/test_webpush.py::test_push_resolve_config_disabled_when_flag_absent_or_falsey PASSED [ 89%] +tests/unit/test_webpush.py::test_push_resolve_config_bad_numbers_fall_back_to_defaults PASSED [ 89%] +tests/unit/test_webpush.py::test_push_dashboard_link_none_without_base PASSED [ 89%] +tests/unit/test_webpush.py::test_push_reclaim_alarm_payload_carries_id_reason_and_urgent_tags PASSED [ 90%] +tests/unit/test_webpush.py::test_push_fires_on_custody_ttl_breach_simulated_item PASSED [ 90%] +tests/unit/test_webpush.py::test_push_does_not_fire_when_custody_is_fresh PASSED [ 90%] +tests/unit/test_webpush.py::test_push_fire_reclaim_alarm_disabled_is_noop PASSED [ 90%] +tests/unit/test_webpush.py::test_push_fire_reclaim_alarm_swallows_config_error PASSED [ 90%] +tests/unit/test_webpush.py::test_push_fire_reclaim_alarm_swallows_delivery_error PASSED [ 90%] +tests/unit/test_webtls.py::test_common_name_passes_short_hostname_through_unchanged PASSED [ 90%] +tests/unit/test_webtls.py::test_common_name_truncates_long_hostname_to_64_chars PASSED [ 90%] +tests/unit/test_webtls.py::test_common_name_truncation_is_exercised_by_a_real_cert PASSED [ 90%] +tests/unit/test_webtls.py::test_default_hostnames_includes_hostname_local_and_localhost PASSED [ 90%] +tests/unit/test_webtls.py::test_default_lan_ip_returns_a_valid_ipv4_or_none PASSED [ 90%] +tests/unit/test_webtls.py::test_default_tailnet_name_returns_none_when_tailscale_not_on_path PASSED [ 90%] +tests/unit/test_webtls.py::test_default_leaf_sans_includes_loopback_and_default_hostnames PASSED [ 91%] +tests/unit/test_webtls.py::test_default_leaf_sans_folds_in_tailnet_name_and_lan_ip_when_present PASSED [ 91%] +tests/unit/test_webtls.py::test_default_paths_live_under_config_amplifier_work_tracker_tls PASSED [ 91%] +tests/unit/test_webtls.py::test_default_tls_dir_is_created_with_restricted_permissions PASSED [ 91%] +tests/unit/test_webtls.py::test_generate_self_signed_writes_cert_and_key_with_restricted_key_perms PASSED [ 91%] +tests/unit/test_webtls.py::test_generate_self_signed_san_covers_hostname_local_localhost_loopback_and_lan_ip PASSED [ 91%] +tests/unit/test_webtls.py::test_generate_self_signed_deduplicates_loopback_ip_addresses PASSED [ 91%] +tests/unit/test_webtls.py::test_generate_self_signed_skips_invalid_ip_strings_silently PASSED [ 91%] +tests/unit/test_webtls.py::test_generate_local_ca_writes_ca_cert_and_key PASSED [ 91%] +tests/unit/test_webtls.py::test_generate_local_ca_is_idempotent_and_reuses_existing_ca PASSED [ 91%] +tests/unit/test_webtls.py::test_generate_leaf_signed_by_ca_produces_a_cert_chained_to_the_ca PASSED [ 91%] +tests/unit/test_webtls.py::test_generate_leaf_signed_by_ca_requires_at_least_one_hostname PASSED [ 91%] +tests/unit/test_webtls.py::test_get_cert_info_returns_none_for_missing_file PASSED [ 92%] +tests/unit/test_webtls.py::test_get_cert_info_returns_none_for_unparseable_file PASSED [ 92%] +tests/unit/test_webtls.py::test_get_cert_info_reports_expiry_and_serial PASSED [ 92%] +tests/unit/test_webtls.py::test_detect_tailscale_returns_none_when_binary_absent PASSED [ 92%] +tests/unit/test_webtls.py::test_generate_tailscale_returns_none_when_binary_absent PASSED [ 92%] +tests/unit/test_webtls.py::test_get_cert_info_reports_self_signed_true_for_a_self_signed_cert PASSED [ 92%] +tests/unit/test_webtls.py::test_get_cert_info_reports_self_signed_false_for_a_ca_signed_leaf PASSED [ 92%] +tests/unit/test_webtls.py::test_is_signed_by_ca_true_for_a_real_matching_chain PASSED [ 92%] +tests/unit/test_webtls.py::test_is_signed_by_ca_false_for_a_self_signed_cert_against_an_unrelated_ca PASSED [ 92%] +tests/unit/test_webtls.py::test_is_signed_by_ca_returns_false_never_raises_for_missing_files PASSED [ 92%] +tests/unit/test_webtrust.py::test_detect_os[Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1-ios] PASSED [ 92%] +tests/unit/test_webtrust.py::test_detect_os[Mozilla/5.0 (iPad; CPU OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1-ios] PASSED [ 92%] +tests/unit/test_webtrust.py::test_detect_os[Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36-android] PASSED [ 93%] +tests/unit/test_webtrust.py::test_detect_os[Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36-windows] PASSED [ 93%] +tests/unit/test_webtrust.py::test_detect_os[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15-macos] PASSED [ 93%] +tests/unit/test_webtrust.py::test_detect_os[Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36-linux] PASSED [ 93%] +tests/unit/test_webtrust.py::test_detect_os[-unknown] PASSED [ 93%] +tests/unit/test_webtrust.py::test_detect_os[some-unrecognizable-bot/1.0-unknown] PASSED [ 93%] +tests/unit/test_webtrust.py::test_detect_os_checks_android_before_linux PASSED [ 93%] +tests/unit/test_webtrust.py::test_classify_trust_state_none_when_no_cert_path_given PASSED [ 93%] +tests/unit/test_webtrust.py::test_classify_trust_state_none_when_cert_file_missing PASSED [ 93%] +tests/unit/test_webtrust.py::test_classify_trust_state_selfsigned PASSED [ 93%] +tests/unit/test_webtrust.py::test_classify_trust_state_public_when_not_self_signed_and_no_ca PASSED [ 93%] +tests/unit/test_webtrust.py::test_classify_trust_state_ca PASSED [ 93%] +tests/unit/test_webtrust.py::test_build_mobileconfig_produces_a_parseable_plist PASSED [ 94%] +tests/unit/test_webtrust.py::test_build_mobileconfig_carries_a_root_cert_payload_with_the_real_ca_bytes PASSED [ 94%] +tests/unit/test_webtrust.py::test_build_mobileconfig_is_idempotent_across_downloads PASSED [ 94%] +tests/unit/test_webtrust.py::test_build_mobileconfig_differs_for_a_different_ca PASSED [ 94%] +tests/unit/test_webtrust.py::test_trust_page_is_reachable_unauthenticated_over_plain_http PASSED [ 94%] +tests/unit/test_webtrust.py::test_trust_page_offers_install_profile_button_for_ios_ua PASSED [ 94%] +tests/unit/test_webtrust.py::test_trust_page_honest_about_selfsigned_no_ca_to_install PASSED [ 94%] +tests/unit/test_webtrust.py::test_trust_page_honest_about_no_cert_configured PASSED [ 94%] +tests/unit/test_webtrust.py::test_trust_page_continue_link_points_at_https_origin PASSED [ 94%] +tests/unit/test_webtrust.py::test_ca_crt_download_unauthenticated_when_ca_active PASSED [ 94%] +tests/unit/test_webtrust.py::test_ca_crt_404_honest_when_no_ca PASSED [ 94%] +tests/unit/test_webtrust.py::test_ca_crt_404_when_no_cert_at_all PASSED [ 94%] +tests/unit/test_webtrust.py::test_trust_mobileconfig_download_unauthenticated_when_ca_active PASSED [ 95%] +tests/unit/test_webtrust.py::test_trust_mobileconfig_404_honest_when_no_ca PASSED [ 95%] +tests/unit/test_webtrust.py::test_redirect_for_arbitrary_path_to_https_origin PASSED [ 95%] +tests/unit/test_webtrust.py::test_redirect_preserves_query_string PASSED [ 95%] +tests/unit/test_webtrust.py::test_redirect_for_bare_root PASSED [ 95%] +tests/unit/test_webtrust.py::test_redirect_never_fires_for_the_three_trust_routes PASSED [ 95%] +tests/unit/test_widgets_contract.py::test_register_and_get_roundtrip PASSED [ 95%] +tests/unit/test_widgets_contract.py::test_register_duplicate_id_fails_loud PASSED [ 95%] +tests/unit/test_widgets_contract.py::test_get_unknown_id_names_known_ids PASSED [ 95%] +tests/unit/test_widgets_contract.py::test_registry_preserves_registration_order PASSED [ 95%] +tests/unit/test_widgets_contract.py::test_render_passes_context_and_returns_fragment PASSED [ 95%] +tests/unit/test_widgets_contract.py::test_firewall_flags_raw_colour_and_gloss[] PASSED [ 95%] +tests/unit/test_widgets_contract.py::test_firewall_flags_raw_colour_and_gloss[] PASSED [ 96%] +tests/unit/test_widgets_contract.py::test_firewall_flags_raw_colour_and_gloss[] PASSED [ 96%] +tests/unit/test_widgets_contract.py::test_firewall_flags_raw_colour_and_gloss[] PASSED [ 96%] +tests/unit/test_widgets_contract.py::test_firewall_flags_raw_colour_and_gloss[] PASSED [ 96%] +tests/unit/test_widgets_contract.py::test_firewall_flags_raw_colour_and_gloss[] PASSED [ 96%] +tests/unit/test_widgets_contract.py::test_firewall_flags_raw_colour_and_gloss[] PASSED [ 96%] +tests/unit/test_widgets_contract.py::test_firewall_flags_raw_colour_and_gloss[] PASSED [ 96%] +tests/unit/test_widgets_contract.py::test_firewall_flags_raw_colour_and_gloss[] PASSED [ 96%] +tests/unit/test_widgets_contract.py::test_firewall_passes_token_only_and_avoids_false_positives[] PASSED [ 96%] +tests/unit/test_widgets_contract.py::test_firewall_passes_token_only_and_avoids_false_positives[x] PASSED [ 96%] +tests/unit/test_widgets_contract.py::test_firewall_passes_token_only_and_avoids_false_positives[] PASSED [ 96%] +tests/unit/test_widgets_contract.py::test_firewall_passes_token_only_and_avoids_false_positives[a ’ b · c] PASSED [ 96%] +tests/unit/test_widgets_contract.py::test_firewall_passes_token_only_and_avoids_false_positives[y] PASSED [ 97%] +tests/unit/test_widgets_contract.py::test_firewall_passes_token_only_and_avoids_false_positives[
4
] PASSED [ 97%] +tests/unit/test_widgets_contract.py::test_render_enforce_raises_on_violation PASSED [ 97%] +tests/unit/test_widgets_contract.py::test_dashboard_registry_has_the_five_v2_panels PASSED [ 97%] +tests/unit/test_widgets_contract.py::test_dashboard_widget_needs_are_real_context_fields PASSED [ 97%] +tests/unit/test_widgets_contract.py::test_every_dashboard_widget_obeys_the_firewall_when_populated PASSED [ 97%] +tests/unit/test_widgets_contract.py::test_every_dashboard_widget_obeys_the_firewall_when_empty PASSED [ 97%] +tests/unit/test_widgets_contract.py::test_routed_output_is_byte_identical_to_inline_builder[empty] PASSED [ 97%] +tests/unit/test_widgets_contract.py::test_routed_output_is_byte_identical_to_inline_builder[populated] PASSED [ 97%] +tests/unit/test_workspace_remove.py::test_remove_without_force_refuses_before_touching_disk PASSED [ 97%] +tests/unit/test_workspace_remove.py::test_remove_with_force_false_explicitly_still_refuses PASSED [ 97%] +tests/unit/test_workspace_remove.py::test_remove_rejects_invalid_name_before_touching_disk PASSED [ 97%] +ledger/checks/test_custody_rows.py::test_row_ccv1_000 PASSED [ 98%] +ledger/checks/test_custody_rows.py::test_row_ccv1_003 PASSED [ 98%] +ledger/checks/test_custody_rows.py::test_row_ccv1_004 PASSED [ 98%] +ledger/checks/test_custody_rows.py::test_row_ccv1_005 PASSED [ 98%] +ledger/checks/test_custody_rows.py::test_row_ccv1_008 PASSED [ 98%] +ledger/checks/test_custody_rows.py::test_row_ccv1_009 PASSED [ 98%] +ledger/checks/test_custody_rows.py::test_row_ccv1_011 PASSED [ 98%] +ledger/checks/test_custody_rows.py::test_row_ccv1_012 PASSED [ 98%] +ledger/checks/test_custody_rows.py::test_row_ccv1_013 PASSED [ 98%] +ledger/checks/test_custody_rows.py::test_row_ccv1_015 PASSED [ 98%] +ledger/checks/test_custody_rows.py::test_row_ccv1_016 PASSED [ 98%] +ledger/checks/test_custody_rows.py::test_row_ccv1_017 PASSED [ 98%] +ledger/checks/test_custody_rows.py::test_row_ccv1_021 PASSED [ 99%] +ledger/checks/test_custody_rows.py::test_row_ccv1_022 PASSED [ 99%] +ledger/checks/test_custody_rows.py::test_row_ccv1_023 PASSED [ 99%] +ledger/checks/test_ledger_integrity.py::test_rows_parse_as_a_top_level_list_with_the_sync_row_first PASSED [ 99%] +ledger/checks/test_ledger_integrity.py::test_row_ids_are_well_formed_unique_and_ordered PASSED [ 99%] +ledger/checks/test_ledger_integrity.py::test_every_row_has_a_legal_disposition_and_its_required_fields PASSED [ 99%] +ledger/checks/test_ledger_integrity.py::test_every_row_quote_verifies_against_the_contract_bytes PASSED [ 99%] +ledger/checks/test_ledger_integrity.py::test_every_clause_id_is_a_bare_identifier_the_contract_actually_names PASSED [ 99%] +ledger/checks/test_ledger_integrity.py::test_every_core_clause_is_cited_by_at_least_one_row PASSED [ 99%] +ledger/checks/test_ledger_integrity.py::test_every_assertion_ref_resolves PASSED [ 99%] +ledger/checks/test_ledger_integrity.py::test_every_probe_belongs_to_a_row PASSED [ 99%] +ledger/checks/test_ledger_integrity.py::test_indexed_cites_are_reserved_for_measured_rows PASSED [100%] + +=================================== FAILURES =================================== +___________ test_doctor_quick_succeeds_against_the_real_installed_bd ___________ + +run_cli = ._run at 0xf76b81f3cfe0> + + def test_doctor_quick_succeeds_against_the_real_installed_bd(run_cli): + result = run_cli(["doctor", "--quick"]) +> assert result.returncode == 0, result.stdout + result.stderr +E AssertionError: [PASS] version bd 1.1.2 +E [PASS] capabilities all required bd commands present +E [PASS] resolve.fenced stale holder refused, as required +E [PASS] resolve.divergent_text_refused resolving a closed item with different text refuses and writes nothing +E [PASS] resolve.identical_text_idempotent re-sending identical resolution text is an idempotent success +E [PASS] reopen.reopens a resolved item reopens unassigned and is directly claimable again +E [PASS] reopen.clears_closed_at reopen clears closed_at (the documented, surfaced accounting cost) +E [PASS] reopen.close_reason_disposition reopen clears close_reason (measured), and the wrapper's archive comment preserves the previous resolution regardless +E [PASS] reopen.emits_event bd records a `reopened` events row, attributed +E [PASS] release.reopens_unresolved release reopens a held item with no resolution, and it is re-claimable +E [PASS] claim.subcommand --claim present, rejects --assignee as expected +E [PASS] claim.atomic skipped (--quick); run full doctor before trusting parallel agents +E [PASS] claim.directed_atomic skipped (--quick); run full doctor before trusting parallel agents +E [PASS] link.nonblocking discovered-from is non-blocking +E [PASS] list.includes_closed all-flag required and working +E [PASS] list.status_filter_includes_closed an explicit --status filter shows closed items without --all +E [PASS] show.dependents reverse link visible (1 links) +E [PASS] read.no_mutation repeated reads (including not-found/wrong-project misses) leave status, holder, and metadata unchanged +E [PASS] resolution.readable resolution text round-trips +E [PASS] timestamps.readable created_at/updated_at/closed_at all round-trip as real datetimes +E [PASS] metadata.roundtrip arbitrary JSON metadata round-trips +E [PASS] project.name_rules dotted names appear usable now; validator may be relaxed +E [PASS] custody.fresh_survives a fresh renewal survives regardless of total hold duration +E [PASS] custody.stale_reclaimed stale custody is reclaimed: custody stale -- last seen 3601s ago (ttl 900s) +E [PASS] custody.idle_not_exempt awaiting_human with stale custody is still reclaimed: custody stale -- last seen 3601s ago (ttl 900s) +E [PASS] custody.fenced old holder's renew and resolve are both refused after takeover +E [PASS] project.removal remove() drops both the directory and database; re-create afterward is genuinely empty +E [PASS] project.create_atomic an abandoned creation lock (dead pid) is healed automatically and create() completes fresh in the same call; path=/tmp/awtcontract_4zcrll38/projects/contract1788405986340atomic +E [PASS] project.creation_state_reporting creation_state distinguishes none/creating/abandoned correctly +E [PASS] service.installed installed and active (unit: /home/bkrabach/.config/systemd/user/amplifier-work-tracker.service) +E [PASS] dolt.reachable dolt sql-server responds on 127.0.0.1:43191 +E [FAIL] sweeps.alive no heartbeat ever recorded for the reap sweep loop -- it may never have started, or the heartbeat file was removed; restart the service (`amplifier-work-tracker service restart`); no heartbeat ever recorded for the notify sweep loop -- it may never have started, or the heartbeat file was removed; restart the service (`amplifier-work-tracker service restart`) +E [PASS] service.restart_policy installed unit has Restart=always -- survives a clean/unintended exit +E +E 1 assumption(s) VIOLATED. Beads has changed underneath us. +E Fix scope: amplifier_work_tracker/adapter.py only -- nothing above the seam encodes Beads behaviour. +E project 'contract1788405986340atomic': healing an abandoned creation attempt (lock /tmp/awtcontract_4zcrll38/projects/contract1788405986340atomic/.create.lock named a dead pid) before retrying +E +E assert 1 == 0 +E + where 1 = CompletedProcess(args=['/home/bkrabach/dev/hw-model-performance/lanes/f5c-work-tracker-reopen/amplifier-work-tracker/.venv/bin/python', '-m', 'amplifier_work_tracker.cli', 'doctor', '--quick'], returncode=1, stdout=" [PASS] version bd 1.1.2\n [PASS] capabilities all required bd commands present\n [PASS] resolve.fenced stale holder refused, as required\n [PASS] resolve.divergent_text_refused resolving a closed item with different text refuses and writes nothing\n [PASS] resolve.identical_text_idempotent re-sending identical resolution text is an idempotent success\n [PASS] reopen.reopens a resolved item reopens unassigned and is directly claimable again\n [PASS] reopen.clears_closed_at reopen clears closed_at (the documented, surfaced accounting cost)\n [PASS] reopen.close_reason_disposition reopen clears close_reason (measured), and the wrapper's archive comment preserves the previous resolution regardless\n [PASS] reopen.emits_event bd records a `reopened` events row, attributed\n [PASS] release.reopens_unresolved release reopens...rting creation_state distinguishes none/creating/abandoned correctly\n [PASS] service.installed installed and active (unit: /home/bkrabach/.config/systemd/user/amplifier-work-tracker.service)\n [PASS] dolt.reachable dolt sql-server responds on 127.0.0.1:43191\n [FAIL] sweeps.alive no heartbeat ever recorded for the reap sweep loop -- it may never have started, or the heartbeat file was removed; restart the service (`amplifier-work-tracker service restart`); no heartbeat ever recorded for the notify sweep loop -- it may never have started, or the heartbeat file was removed; restart the service (`amplifier-work-tracker service restart`)\n [PASS] service.restart_policy installed unit has Restart=always -- survives a clean/unintended exit\n\n1 assumption(s) VIOLATED. Beads has changed underneath us.\nFix scope: amplifier_work_tracker/adapter.py only -- nothing above the seam encodes Beads behaviour.\n", stderr="project 'contract1788405986340atomic': healing an abandoned creation attempt (lock /tmp/awtcontract_4zcrll38/projects/contract1788405986340atomic/.create.lock named a dead pid) before retrying\n").returncode + +tests/cli/test_cli_surface.py:831: AssertionError +----------------------------- Captured stdout call ----------------------------- + + +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:26:26-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1649 +time="2026-09-02T20:26:26-07:00" level=info msg=ConnectionClosed connectionID=1649 +time="2026-09-02T20:26:26-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1650 +time="2026-09-02T20:26:26-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1651 +time="2026-09-02T20:26:26-07:00" level=info msg=ConnectionClosed connectionID=1650 +time="2026-09-02T20:26:27-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1652 +time="2026-09-02T20:26:27-07:00" level=info msg=ConnectionClosed connectionID=1651 +time="2026-09-02T20:26:27-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:27.012531065 -0700 PDT m=+183.665670382" connectionDb=contract1788405986340 connectionID=1652 error="table not found: schema_migrations" queryTime="2026-09-02 20:26:27.013725638 -0700 PDT m=+183.666864971" +time="2026-09-02T20:26:27-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1653 +time="2026-09-02T20:26:27-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:27.014307364 -0700 PDT m=+183.667446681" connectionDb=contract1788405986340 connectionID=1653 error="table not found: schema_migrations" queryTime="2026-09-02 20:26:27.014840195 -0700 PDT m=+183.667979512" +time="2026-09-02T20:26:27-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:27.014307364 -0700 PDT m=+183.667446681" connectionDb=contract1788405986340 connectionID=1653 error="table not found: schema_migrations" queryTime="2026-09-02 20:26:27.016725166 -0700 PDT m=+183.669864483" +time="2026-09-02T20:26:27-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:27.014307364 -0700 PDT m=+183.667446681" connectionDb=contract1788405986340 connectionID=1653 error="table not found: schema_migrations" queryTime="2026-09-02 20:26:27.018891176 -0700 PDT m=+183.672030493" +time="2026-09-02T20:26:29-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:27.014307364 -0700 PDT m=+183.667446681" connectionDb=contract1788405986340 connectionID=1653 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:26:29.029302545 -0700 PDT m=+185.682441862" +time="2026-09-02T20:26:29-07:00" level=info msg=ConnectionClosed connectionID=1653 +time="2026-09-02T20:26:29-07:00" level=info msg=ConnectionClosed connectionID=1652 +time="2026-09-02T20:26:29-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1654 +time="2026-09-02T20:26:29-07:00" level=info msg=ConnectionClosed connectionID=1654 +time="2026-09-02T20:26:29-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1655 +time="2026-09-02T20:26:29-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1656 +time="2026-09-02T20:26:29-07:00" level=info msg=ConnectionClosed connectionID=1655 +time="2026-09-02T20:26:30-07:00" level=info msg=ConnectionClosed connectionID=1656 +time="2026-09-02T20:26:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1657 +time="2026-09-02T20:26:30-07:00" level=info msg=ConnectionClosed connectionID=1657 +time="2026-09-02T20:26:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1658 +time="2026-09-02T20:26:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1659 +time="2026-09-02T20:26:30-07:00" level=info msg=ConnectionClosed connectionID=1658 +time="2026-09-02T20:26:30-07:00" level=info msg=ConnectionClosed connectionID=1659 +time="2026-09-02T20:26:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1660 +time="2026-09-02T20:26:30-07:00" level=info msg=ConnectionClosed connectionID=1660 +time="2026-09-02T20:26:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1661 +time="2026-09-02T20:26:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1662 +time="2026-09-02T20:26:30-07:00" level=info msg=ConnectionClosed connectionID=1661 +time="2026-09-02T20:26:30-07:00" level=info msg=ConnectionClosed connectionID=1662 +time="2026-09-02T20:26:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1663 +time="2026-09-02T20:26:30-07:00" level=info msg=ConnectionClosed connectionID=1663 +time="2026-09-02T20:26:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1664 +time="2026-09-02T20:26:30-07:00" level=info msg=ConnectionClosed connectionID=1664 +time="2026-09-02T20:26:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1665 +time="2026-09-02T20:26:30-07:00" level=info msg=ConnectionClosed connectionID=1665 +time="2026-09-02T20:26:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1666 +time="2026-09-02T20:26:30-07:00" level=info msg=ConnectionClosed connectionID=1666 +time="2026-09-02T20:26:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1667 +time="2026-09-02T20:26:30-07:00" level=info msg=ConnectionClosed connectionID=1667 +time="2026-09-02T20:26:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1668 +time="2026-09-02T20:26:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1669 +time="2026-09-02T20:26:30-07:00" level=info msg=ConnectionClosed connectionID=1668 +time="2026-09-02T20:26:30-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1670 +time="2026-09-02T20:26:30-07:00" level=info msg=ConnectionClosed connectionID=1670 +time="2026-09-02T20:26:30-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:30.769566304 -0700 PDT m=+187.422705637" connectionDb=contract1788405986340 connectionID=1669 error="backup 'backup_export' not found" queryTime="2026-09-02 20:26:30.892291862 -0700 PDT m=+187.545431195" +time="2026-09-02T20:26:30-07:00" level=info msg=ConnectionClosed connectionID=1669 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1671 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1671 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1672 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1673 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1672 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1673 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1674 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1674 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1675 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1675 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1676 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1676 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1677 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1677 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1678 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1679 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1678 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1680 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1680 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1679 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1681 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1681 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1682 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1683 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1682 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1683 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1684 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1684 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1685 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1685 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1686 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1686 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1687 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1687 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1688 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1689 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1688 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1690 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1690 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1689 +time="2026-09-02T20:26:31-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1691 +time="2026-09-02T20:26:31-07:00" level=info msg=ConnectionClosed connectionID=1691 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1692 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1692 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1693 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1693 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1694 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1694 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1695 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1696 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1695 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1697 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1697 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1696 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1698 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1698 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1699 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1699 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1700 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1700 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1701 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1701 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1702 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1702 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1703 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1703 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1704 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1704 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1705 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1705 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1706 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1706 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1707 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1707 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1708 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1709 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1708 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1710 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1710 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1709 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1711 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1711 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1712 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1712 +time="2026-09-02T20:26:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1713 +time="2026-09-02T20:26:32-07:00" level=info msg=ConnectionClosed connectionID=1713 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1714 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1714 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1715 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1716 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1715 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1717 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1717 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1716 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1718 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1718 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1719 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1719 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1720 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1720 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1721 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1721 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1722 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1722 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1723 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1723 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1724 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1724 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1725 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1726 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1725 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1727 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1727 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1726 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1728 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1728 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1729 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1729 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1730 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1730 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1731 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1731 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1732 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1733 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1732 +time="2026-09-02T20:26:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1734 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1734 +time="2026-09-02T20:26:33-07:00" level=info msg=ConnectionClosed connectionID=1733 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1735 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1735 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1736 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1736 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1737 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1737 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1738 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1738 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1739 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1739 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1740 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1740 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1741 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1741 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1742 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1743 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1742 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1744 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1744 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1743 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1745 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1745 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1746 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1747 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1746 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1748 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1748 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1747 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1749 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1749 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1750 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1750 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1751 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1751 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1752 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1752 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1753 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1753 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1754 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1754 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1755 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1755 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1756 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1756 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1757 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1757 +time="2026-09-02T20:26:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1758 +time="2026-09-02T20:26:34-07:00" level=info msg=ConnectionClosed connectionID=1758 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1759 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1759 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1760 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1761 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1760 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1762 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1762 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1761 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1763 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1763 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1764 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1765 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1764 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1766 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1766 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1765 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1767 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1767 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1768 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1768 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1769 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1769 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1770 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1770 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1771 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1772 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1771 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1773 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1773 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1772 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1774 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1774 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1775 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1775 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1776 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1776 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1777 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1777 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1778 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1778 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1779 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1779 +time="2026-09-02T20:26:35-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1780 +time="2026-09-02T20:26:35-07:00" level=info msg=ConnectionClosed connectionID=1780 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1781 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1781 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1782 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1782 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1783 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1783 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1784 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1785 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1784 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1786 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1786 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1785 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1787 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1787 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1788 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1789 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1788 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1790 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1790 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1789 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1791 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1791 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1792 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1792 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1793 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1793 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1794 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1794 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1795 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1796 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1795 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1797 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1797 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1796 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1798 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1798 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1799 +time="2026-09-02T20:26:36-07:00" level=info msg=ConnectionClosed connectionID=1799 +time="2026-09-02T20:26:36-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1800 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1800 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1802 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1801 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1801 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1803 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1802 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1804 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1804 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1803 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1805 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1805 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1806 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1806 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1807 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1807 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1808 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1808 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1809 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1809 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1810 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1810 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1811 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1811 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1812 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1813 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1812 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1814 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1814 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1813 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1815 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1815 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1816 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1817 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1816 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1818 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1818 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1817 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1819 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1819 +time="2026-09-02T20:26:37-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1820 +time="2026-09-02T20:26:37-07:00" level=info msg=ConnectionClosed connectionID=1820 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1821 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1821 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1822 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1822 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1823 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1824 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1823 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1825 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1825 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1824 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1826 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1827 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1826 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1828 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1827 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1828 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1829 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1829 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1830 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1831 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1830 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1832 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1832 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1831 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1833 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1833 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1834 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1834 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1835 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1835 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1836 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1836 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1837 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1838 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1837 +time="2026-09-02T20:26:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1839 +time="2026-09-02T20:26:38-07:00" level=info msg=ConnectionClosed connectionID=1839 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1838 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1840 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1840 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1841 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1841 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1842 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1842 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1843 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1843 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1844 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1844 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1845 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1845 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1846 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1846 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1847 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1848 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1847 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1849 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1849 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1848 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1850 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1850 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1851 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1852 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1851 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1853 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1853 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1852 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1854 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1854 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1855 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1855 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1856 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1856 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1857 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1857 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1858 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1858 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1859 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1860 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1859 +time="2026-09-02T20:26:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1861 +time="2026-09-02T20:26:39-07:00" level=info msg=ConnectionClosed connectionID=1861 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1860 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1862 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1862 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1863 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1864 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1863 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1864 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1865 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1865 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1866 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1866 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1867 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1867 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1868 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1868 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1869 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1870 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1869 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1871 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1871 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1870 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1872 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1872 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1873 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1873 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1874 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1874 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1875 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1875 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1876 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1877 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1876 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1877 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1878 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1878 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1879 +time="2026-09-02T20:26:40-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1880 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1879 +time="2026-09-02T20:26:40-07:00" level=info msg=ConnectionClosed connectionID=1880 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1881 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1881 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1882 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1883 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1882 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1884 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1884 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1883 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1885 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1885 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1886 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1887 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1886 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1888 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1888 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1887 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1889 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1889 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1890 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1890 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1891 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1892 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1891 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1893 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1892 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1894 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1894 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1893 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1895 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1895 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1896 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1896 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1897 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1897 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1898 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1898 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1899 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1900 +time="2026-09-02T20:26:41-07:00" level=info msg=ConnectionClosed connectionID=1899 +time="2026-09-02T20:26:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1901 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1901 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1900 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1902 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1902 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1903 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1903 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1904 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1904 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1905 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1905 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1906 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1906 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1907 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1907 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1908 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1908 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1909 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1909 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1910 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1911 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1910 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1912 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1912 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1911 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1913 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1913 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1914 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1914 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1915 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1915 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1916 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1916 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1917 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1918 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1917 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1919 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1919 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1918 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1920 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1920 +time="2026-09-02T20:26:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1921 +time="2026-09-02T20:26:42-07:00" level=info msg=ConnectionClosed connectionID=1921 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1922 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1922 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1923 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1923 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1924 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1924 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1925 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1925 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1926 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1927 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1926 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1928 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1928 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1927 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1929 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1929 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1930 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1931 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1930 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1932 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1932 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1931 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1933 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1933 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1934 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1935 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1934 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1935 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1936 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1936 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1937 +time="2026-09-02T20:26:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1938 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1937 +time="2026-09-02T20:26:43-07:00" level=info msg=ConnectionClosed connectionID=1938 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1939 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1939 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1940 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1941 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1940 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1942 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1942 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1941 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1943 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1943 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1944 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1944 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1945 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1945 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1946 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1946 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1947 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1947 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1948 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1948 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1949 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1949 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1950 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1950 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1951 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1951 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1952 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1952 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1953 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1953 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1954 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1954 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1955 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1955 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1956 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1956 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1957 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1957 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1958 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1958 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1959 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1959 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1960 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1960 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1961 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1961 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1962 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1962 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1963 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1963 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1964 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1964 +time="2026-09-02T20:26:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1965 +time="2026-09-02T20:26:44-07:00" level=info msg=ConnectionClosed connectionID=1965 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1966 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1966 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1967 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1967 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1968 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1968 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1969 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1969 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1970 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1970 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1971 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1971 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1972 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1973 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1972 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1974 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1974 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1973 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1975 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1975 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1976 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1976 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1977 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1977 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1978 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1978 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1979 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1980 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1979 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1981 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1981 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1980 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1982 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1982 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1983 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1983 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1984 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1984 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1985 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1985 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1986 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1986 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1987 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1987 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1988 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1988 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1989 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1990 +time="2026-09-02T20:26:45-07:00" level=info msg=ConnectionClosed connectionID=1989 +time="2026-09-02T20:26:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1991 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=1991 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=1990 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1992 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=1992 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1993 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=1993 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1994 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=1994 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1995 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=1995 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1996 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=1996 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1997 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=1997 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1998 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=1998 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1999 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2000 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=1999 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2001 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=2001 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=2000 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2002 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=2002 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2003 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=2003 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2004 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=2004 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2005 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=2005 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2006 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=2006 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2007 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=2007 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2008 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=2008 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2009 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2010 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=2009 +time="2026-09-02T20:26:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2011 +time="2026-09-02T20:26:46-07:00" level=info msg=ConnectionClosed connectionID=2011 +time="2026-09-02T20:26:47-07:00" level=info msg=ConnectionClosed connectionID=2010 +time="2026-09-02T20:26:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2012 +time="2026-09-02T20:26:47-07:00" level=info msg=ConnectionClosed connectionID=2012 +time="2026-09-02T20:26:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2013 +time="2026-09-02T20:26:47-07:00" level=info msg=ConnectionClosed connectionID=2013 +time="2026-09-02T20:26:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2014 +time="2026-09-02T20:26:47-07:00" level=info msg=ConnectionClosed connectionID=2014 +time="2026-09-02T20:26:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2015 +time="2026-09-02T20:26:48-07:00" level=info msg=ConnectionClosed connectionID=2015 +time="2026-09-02T20:26:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2016 +time="2026-09-02T20:26:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2017 +time="2026-09-02T20:26:48-07:00" level=info msg=ConnectionClosed connectionID=2016 +time="2026-09-02T20:26:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2018 +time="2026-09-02T20:26:48-07:00" level=info msg=ConnectionClosed connectionID=2018 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2017 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2019 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2019 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2020 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2021 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2020 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2021 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2022 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2022 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2023 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2023 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2024 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2024 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2025 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2025 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2026 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2027 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2026 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2028 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2028 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2027 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2029 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2029 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2030 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2030 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2031 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2031 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2032 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2032 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2033 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2033 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2034 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2034 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2035 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2035 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2036 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2037 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2036 +time="2026-09-02T20:26:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2038 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2038 +time="2026-09-02T20:26:49-07:00" level=info msg=ConnectionClosed connectionID=2037 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2039 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2039 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2040 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2041 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2040 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2041 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2042 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2042 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2043 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2043 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2044 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2044 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2045 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2045 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2046 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2047 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2046 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2048 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2048 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2047 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2049 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2049 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2050 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2050 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2051 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2051 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2052 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2052 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2053 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2053 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2054 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2054 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2055 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2055 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2056 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2056 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2057 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2057 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2058 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2058 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2059 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2059 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2060 +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2061 +time="2026-09-02T20:26:50-07:00" level=info msg=ConnectionClosed connectionID=2060 +time="2026-09-02T20:26:50-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:50.887253422 -0700 PDT m=+207.540392755" connectionDb=contract1788405986340rm connectionID=2061 error="table not found: schema_migrations" queryTime="2026-09-02 20:26:50.888598315 -0700 PDT m=+207.541737632" +time="2026-09-02T20:26:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2062 +time="2026-09-02T20:26:50-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:50.88906905 -0700 PDT m=+207.542208383" connectionDb=contract1788405986340rm connectionID=2062 error="table not found: schema_migrations" queryTime="2026-09-02 20:26:50.890174823 -0700 PDT m=+207.543314124" +time="2026-09-02T20:26:50-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:50.88906905 -0700 PDT m=+207.542208383" connectionDb=contract1788405986340rm connectionID=2062 error="table not found: schema_migrations" queryTime="2026-09-02 20:26:50.891695714 -0700 PDT m=+207.544835031" +time="2026-09-02T20:26:50-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:50.88906905 -0700 PDT m=+207.542208383" connectionDb=contract1788405986340rm connectionID=2062 error="table not found: schema_migrations" queryTime="2026-09-02 20:26:50.894128844 -0700 PDT m=+207.547268161" +time="2026-09-02T20:26:53-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:50.88906905 -0700 PDT m=+207.542208383" connectionDb=contract1788405986340rm connectionID=2062 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:26:53.035347099 -0700 PDT m=+209.688486400" +time="2026-09-02T20:26:53-07:00" level=info msg=ConnectionClosed connectionID=2062 +time="2026-09-02T20:26:53-07:00" level=info msg=ConnectionClosed connectionID=2061 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2063 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2063 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2064 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2065 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2064 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2065 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2066 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2066 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2067 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2068 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2067 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2068 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2069 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2069 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2070 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2071 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2070 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2071 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2072 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2072 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2073 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2073 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2074 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2074 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2075 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2075 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2076 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2076 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2077 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2078 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2077 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2079 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2079 +time="2026-09-02T20:26:54-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:54.473802103 -0700 PDT m=+211.126941468" connectionDb=contract1788405986340rm connectionID=2078 error="backup 'backup_export' not found" queryTime="2026-09-02 20:26:54.598083658 -0700 PDT m=+211.251222975" +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2078 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2080 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2080 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2081 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2081 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2082 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2082 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2083 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2083 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2084 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2084 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2085 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2085 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2086 +time="2026-09-02T20:26:54-07:00" level=info msg=ConnectionClosed connectionID=2086 +time="2026-09-02T20:26:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2087 +time="2026-09-02T20:26:55-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2088 +time="2026-09-02T20:26:55-07:00" level=info msg=ConnectionClosed connectionID=2087 +time="2026-09-02T20:26:55-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:55.044360268 -0700 PDT m=+211.697499585" connectionDb=contract1788405986340rm connectionID=2088 error="table not found: schema_migrations" queryTime="2026-09-02 20:26:55.045859592 -0700 PDT m=+211.698998925" +time="2026-09-02T20:26:55-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2089 +time="2026-09-02T20:26:55-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:55.046292887 -0700 PDT m=+211.699432188" connectionDb=contract1788405986340rm connectionID=2089 error="table not found: schema_migrations" queryTime="2026-09-02 20:26:55.047169781 -0700 PDT m=+211.700309098" +time="2026-09-02T20:26:55-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:55.046292887 -0700 PDT m=+211.699432188" connectionDb=contract1788405986340rm connectionID=2089 error="table not found: schema_migrations" queryTime="2026-09-02 20:26:55.048635073 -0700 PDT m=+211.701774374" +time="2026-09-02T20:26:55-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:55.046292887 -0700 PDT m=+211.699432188" connectionDb=contract1788405986340rm connectionID=2089 error="table not found: schema_migrations" queryTime="2026-09-02 20:26:55.050735243 -0700 PDT m=+211.703874560" +time="2026-09-02T20:26:57-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:55.046292887 -0700 PDT m=+211.699432188" connectionDb=contract1788405986340rm connectionID=2089 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:26:57.237856016 -0700 PDT m=+213.890995333" +time="2026-09-02T20:26:57-07:00" level=info msg=ConnectionClosed connectionID=2089 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2088 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2090 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2090 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2091 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2092 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2091 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2092 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2093 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2093 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2094 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2095 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2094 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2095 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2096 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2096 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2097 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2098 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2097 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2098 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2099 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2099 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2100 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2100 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2101 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2101 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2102 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2102 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2103 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2103 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2104 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2104 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2105 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2105 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2106 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2106 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2107 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2107 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2108 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2108 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2109 +time="2026-09-02T20:26:58-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:58.799188803 -0700 PDT m=+215.452328136" connectionID=2109 error="database not found: contract1788405986340atomic" queryTime="2026-09-02 20:26:58.801950652 -0700 PDT m=+215.455089969" +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2109 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2110 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2110 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2111 +time="2026-09-02T20:26:58-07:00" level=info msg=ConnectionClosed connectionID=2111 +time="2026-09-02T20:26:58-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2112 +time="2026-09-02T20:26:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2113 +time="2026-09-02T20:26:59-07:00" level=info msg=ConnectionClosed connectionID=2112 +time="2026-09-02T20:26:59-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:59.03358755 -0700 PDT m=+215.686726883" connectionDb=contract1788405986340atomic connectionID=2113 error="table not found: schema_migrations" queryTime="2026-09-02 20:26:59.03511505 -0700 PDT m=+215.688254383" +time="2026-09-02T20:26:59-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2114 +time="2026-09-02T20:26:59-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:59.035691001 -0700 PDT m=+215.688830318" connectionDb=contract1788405986340atomic connectionID=2114 error="table not found: schema_migrations" queryTime="2026-09-02 20:26:59.036602118 -0700 PDT m=+215.689741435" +time="2026-09-02T20:26:59-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:59.035691001 -0700 PDT m=+215.688830318" connectionDb=contract1788405986340atomic connectionID=2114 error="table not found: schema_migrations" queryTime="2026-09-02 20:26:59.038269106 -0700 PDT m=+215.691408423" +time="2026-09-02T20:26:59-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:59.035691001 -0700 PDT m=+215.688830318" connectionDb=contract1788405986340atomic connectionID=2114 error="table not found: schema_migrations" queryTime="2026-09-02 20:26:59.040824635 -0700 PDT m=+215.693963936" +time="2026-09-02T20:27:01-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:26:59.035691001 -0700 PDT m=+215.688830318" connectionDb=contract1788405986340atomic connectionID=2114 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:27:01.181234525 -0700 PDT m=+217.834373842" +time="2026-09-02T20:27:01-07:00" level=info msg=ConnectionClosed connectionID=2114 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2113 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2115 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2115 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2116 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2117 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2116 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2117 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2118 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2118 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2119 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2120 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2119 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2120 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2121 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2121 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2122 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2123 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2122 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2123 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2124 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2124 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2125 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2125 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2126 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2126 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2127 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2127 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2128 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2128 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2129 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2129 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2130 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2130 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2131 +time="2026-09-02T20:27:02-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:27:02.562198565 -0700 PDT m=+219.215337882" connectionID=2131 error="database not found: contract1788405986340rm" queryTime="2026-09-02 20:27:02.563903776 -0700 PDT m=+219.217043077" +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2131 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2132 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2132 +time="2026-09-02T20:27:02-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2133 +time="2026-09-02T20:27:02-07:00" level=info msg=ConnectionClosed connectionID=2133 +=============================== warnings summary =============================== +tests/integration/test_observatory_web.py:20 + /home/bkrabach/dev/hw-model-performance/lanes/f5c-work-tracker-reopen/amplifier-work-tracker/tests/integration/test_observatory_web.py:20: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead. + from starlette.testclient import TestClient # noqa: E402 + +.venv/lib/python3.12/site-packages/starlette/testclient.py:53 + /home/bkrabach/dev/hw-model-performance/lanes/f5c-work-tracker-reopen/amplifier-work-tracker/.venv/lib/python3.12/site-packages/starlette/testclient.py:53: DeprecationWarning: The anyio.abc.BlockingPortal alias is deprecated, use anyio.from_thread.BlockingPortal instead. + _PortalFactoryType = Callable[[], AbstractContextManager[anyio.abc.BlockingPortal]] + +-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html +=========================== short test summary info ============================ +SKIPPED [1] tests/integration/test_web.py:699: bd set no `owner` on this item -- happens where the environment has no git identity (e.g. a bare CI container with no `git config user.email`). `owner` is an environment-provided value, not a code invariant; the environment-independent humanization guarantees are covered by test_humanize_identity_* in tests/unit. +SKIPPED [1] tests/integration/test_web_pwa.py:234: Pillow not installed (dev/build-only tool) +SKIPPED [1] tests/integration/test_web_pwa.py:249: Pillow not installed (dev/build-only tool) +FAILED tests/cli/test_cli_surface.py::test_doctor_quick_succeeds_against_the_real_installed_bd +====== 1 failed, 1189 passed, 3 skipped, 2 warnings in 1104.09s (0:18:24) ====== +make: *** [Makefile:35: test] Error 1 +EXIT=2 diff --git a/docs/lanes/f5c-work-tracker-reopen/evidence/modules-suite.log b/docs/lanes/f5c-work-tracker-reopen/evidence/modules-suite.log new file mode 100644 index 0000000..120f04c --- /dev/null +++ b/docs/lanes/f5c-work-tracker-reopen/evidence/modules-suite.log @@ -0,0 +1,145 @@ +..F..................................................................... [ 76%] +...................... [100%] +=================================== FAILURES =================================== +__ test_explicit_resolve_refusal_after_reap_clears_held_and_allows_new_claim ___ +tests/test_reap_recovery.py:71: in test_explicit_resolve_refusal_after_reap_clears_held_and_allows_new_claim + assert resolved.success is False +E AssertionError: assert True is False +E + where True = ToolResult(success=True, output={'resolved': 'reapproje39afbee2e-1es', 'resolution': 'trying to close after being reclaimed'}, error=None).success +---------------------------- Captured stderr setup ----------------------------- +time="2026-09-02T20:45:12-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=145 +time="2026-09-02T20:45:12-07:00" level=info msg=ConnectionClosed connectionID=145 +time="2026-09-02T20:45:12-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=146 +time="2026-09-02T20:45:12-07:00" level=info msg=ConnectionClosed connectionID=146 +time="2026-09-02T20:45:12-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=147 +time="2026-09-02T20:45:13-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=148 +time="2026-09-02T20:45:13-07:00" level=info msg=ConnectionClosed connectionID=147 +time="2026-09-02T20:45:13-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:45:13.251337176 -0700 PDT m=+13.067596027" connectionDb=reapproje39afbee2e connectionID=148 error="table not found: schema_migrations" queryTime="2026-09-02 20:45:13.252184886 -0700 PDT m=+13.068443769" +time="2026-09-02T20:45:13-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=149 +time="2026-09-02T20:45:13-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:45:13.252453861 -0700 PDT m=+13.068712728" connectionDb=reapproje39afbee2e connectionID=149 error="table not found: schema_migrations" queryTime="2026-09-02 20:45:13.25331594 -0700 PDT m=+13.069574807" +time="2026-09-02T20:45:13-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:45:13.252453861 -0700 PDT m=+13.068712728" connectionDb=reapproje39afbee2e connectionID=149 error="table not found: schema_migrations" queryTime="2026-09-02 20:45:13.254763584 -0700 PDT m=+13.071022451" +time="2026-09-02T20:45:13-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:45:13.252453861 -0700 PDT m=+13.068712728" connectionDb=reapproje39afbee2e connectionID=149 error="table not found: schema_migrations" queryTime="2026-09-02 20:45:13.25613483 -0700 PDT m=+13.072393697" +time="2026-09-02T20:45:15-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:45:13.252453861 -0700 PDT m=+13.068712728" connectionDb=reapproje39afbee2e connectionID=149 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:45:15.268264115 -0700 PDT m=+15.084522982" +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=149 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=148 +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=150 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=150 +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=151 +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=152 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=151 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=152 +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=153 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=153 +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=154 +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=155 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=154 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=155 +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=156 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=156 +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=157 +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=158 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=157 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=158 +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=159 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=159 +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=160 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=160 +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=161 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=161 +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=162 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=162 +----------------------------- Captured stdout call ----------------------------- + +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=163 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=163 +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=164 +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=165 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=164 +time="2026-09-02T20:45:16-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=166 +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=166 +time="2026-09-02T20:45:16-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:45:16.721483823 -0700 PDT m=+16.537742706" connectionDb=reapproje39afbee2e connectionID=165 error="backup 'backup_export' not found" queryTime="2026-09-02 20:45:16.832804602 -0700 PDT m=+16.649063469" +time="2026-09-02T20:45:16-07:00" level=info msg=ConnectionClosed connectionID=165 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=167 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=167 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=168 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=169 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=168 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=169 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=170 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=170 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=171 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=171 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=172 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=172 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=173 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=173 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=174 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=175 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=174 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=176 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=176 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=175 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=177 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=177 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=178 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=178 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=179 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=179 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=180 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=180 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=181 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=181 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=182 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=182 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=183 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=183 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=184 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=184 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=185 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=185 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=186 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=187 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=186 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=188 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=188 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=187 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=189 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=189 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=190 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=190 +time="2026-09-02T20:45:17-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=191 +time="2026-09-02T20:45:17-07:00" level=info msg=ConnectionClosed connectionID=191 +time="2026-09-02T20:45:18-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=192 +time="2026-09-02T20:45:18-07:00" level=info msg=ConnectionClosed connectionID=192 +time="2026-09-02T20:45:18-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=193 +time="2026-09-02T20:45:18-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=194 +time="2026-09-02T20:45:18-07:00" level=info msg=ConnectionClosed connectionID=193 +time="2026-09-02T20:45:18-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=195 +time="2026-09-02T20:45:18-07:00" level=info msg=ConnectionClosed connectionID=195 +time="2026-09-02T20:45:18-07:00" level=info msg=ConnectionClosed connectionID=194 +time="2026-09-02T20:45:18-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=196 +time="2026-09-02T20:45:18-07:00" level=info msg=ConnectionClosed connectionID=196 +time="2026-09-02T20:45:18-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=197 +time="2026-09-02T20:45:18-07:00" level=info msg=ConnectionClosed connectionID=197 +time="2026-09-02T20:45:18-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=198 +time="2026-09-02T20:45:18-07:00" level=info msg=ConnectionClosed connectionID=198 +------------------------------ Captured log call ------------------------------- +ERROR amplifier_work_tracker.webpush:webpush.py:435 ntfy alarm unexpected failure for reclaimed reapproje39afbee2e-1es: asyncio.run() cannot be called from a running event loop +--------------------------- Captured stderr teardown --------------------------- +time="2026-09-02T20:45:18-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=199 +time="2026-09-02T20:45:18-07:00" level=info msg="stats stopped: context canceled" +time="2026-09-02T20:45:18-07:00" level=info msg=ConnectionClosed connectionID=199 +=============================== warnings summary =============================== +modules/tool-work-tracker/tests/test_reap_recovery.py::test_explicit_resolve_refusal_after_reap_clears_held_and_allows_new_claim +modules/tool-work-tracker/tests/test_reap_recovery.py::test_explicit_declare_refusal_after_reap_clears_held_and_allows_new_claim +modules/tool-work-tracker/tests/test_reap_recovery.py::test_background_renew_loop_detects_reap_and_clears_held_state + /home/bkrabach/dev/hw-model-performance/lanes/f5c-work-tracker-reopen/amplifier-work-tracker/modules/tool-work-tracker/.venv/lib/python3.12/site-packages/_pytest/stash.py:108: RuntimeWarning: coroutine 'alarm_for_reclaimed_item' was never awaited + del self._storage[key] + Enable tracemalloc to get traceback where the object was allocated. + See https://docs.pytest.org/en/stable/how-to/capture-warnings.html#resource-warnings for more info. + +-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html +=========================== short test summary info ============================ +FAILED tests/test_reap_recovery.py::test_explicit_resolve_refusal_after_reap_clears_held_and_allows_new_claim +1 failed, 93 passed, 3 warnings in 371.20s (0:06:11) diff --git a/docs/lanes/f5c-work-tracker-reopen/evidence/parent-commit-doctor-cli-preexisting-failure.log b/docs/lanes/f5c-work-tracker-reopen/evidence/parent-commit-doctor-cli-preexisting-failure.log new file mode 100644 index 0000000..abcdfc1 --- /dev/null +++ b/docs/lanes/f5c-work-tracker-reopen/evidence/parent-commit-doctor-cli-preexisting-failure.log @@ -0,0 +1,674 @@ +.F [100%] +=================================== FAILURES =================================== +E AssertionError: [PASS] version bd 1.1.2 + [PASS] capabilities all required bd commands present + [PASS] resolve.fenced stale holder refused, as required + [PASS] release.reopens_unresolved release reopens a held item with no resolution, and it is re-claimable + [PASS] claim.subcommand --claim present, rejects --assignee as expected + [PASS] claim.atomic skipped (--quick); run full doctor before trusting parallel agents + [PASS] claim.directed_atomic skipped (--quick); run full doctor before trusting parallel agents + [PASS] link.nonblocking discovered-from is non-blocking + [PASS] list.includes_closed all-flag required and working + [PASS] list.status_filter_includes_closed an explicit --status filter shows closed items without --all + [PASS] show.dependents reverse link visible (1 links) + [PASS] read.no_mutation repeated reads (including not-found/wrong-project misses) leave status, holder, and metadata unchanged + [PASS] resolution.readable resolution text round-trips + [PASS] timestamps.readable created_at/updated_at/closed_at all round-trip as real datetimes + [PASS] metadata.roundtrip arbitrary JSON metadata round-trips + [PASS] project.name_rules dotted names appear usable now; validator may be relaxed + [PASS] custody.fresh_survives a fresh renewal survives regardless of total hold duration + [PASS] custody.stale_reclaimed stale custody is reclaimed: custody stale -- last seen 3600s ago (ttl 900s) + [PASS] custody.idle_not_exempt awaiting_human with stale custody is still reclaimed: custody stale -- last seen 3600s ago (ttl 900s) + [PASS] custody.fenced old holder's renew and resolve are both refused after takeover + [PASS] project.removal remove() drops both the directory and database; re-create afterward is genuinely empty + [PASS] project.create_atomic an abandoned creation lock (dead pid) is healed automatically and create() completes fresh in the same call; path=/tmp/awtcontract_tqtyd9us/projects/contract1788405578811atomic + [PASS] project.creation_state_reporting creation_state distinguishes none/creating/abandoned correctly + [PASS] service.installed installed and active (unit: /home/bkrabach/.config/systemd/user/amplifier-work-tracker.service) + [PASS] dolt.reachable dolt sql-server responds on 127.0.0.1:49641 + [FAIL] sweeps.alive no heartbeat ever recorded for the reap sweep loop -- it may never have started, or the heartbeat file was removed; restart the service (`amplifier-work-tracker service restart`); no heartbeat ever recorded for the notify sweep loop -- it may never have started, or the heartbeat file was removed; restart the service (`amplifier-work-tracker service restart`) + [PASS] service.restart_policy installed unit has Restart=always -- survives a clean/unintended exit + + 1 assumption(s) VIOLATED. Beads has changed underneath us. + Fix scope: amplifier_work_tracker/adapter.py only -- nothing above the seam encodes Beads behaviour. + project 'contract1788405578811atomic': healing an abandoned creation attempt (lock /tmp/awtcontract_tqtyd9us/projects/contract1788405578811atomic/.create.lock named a dead pid) before retrying + + assert 1 == 0 + + where 1 = CompletedProcess(args=['/home/bkrabach/dev/hw-model-performance/lanes/f5c-work-tracker-reopen/amplifier-work-tracker/....(lock /tmp/awtcontract_tqtyd9us/projects/contract1788405578811atomic/.create.lock named a dead pid) before retrying\n").returncode +----------------------------- Captured stdout call ----------------------------- + + +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:19:38-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2 +time="2026-09-02T20:19:38-07:00" level=info msg=ConnectionClosed connectionID=2 +time="2026-09-02T20:19:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=3 +time="2026-09-02T20:19:39-07:00" level=info msg=ConnectionClosed connectionID=3 +time="2026-09-02T20:19:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=4 +time="2026-09-02T20:19:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=5 +time="2026-09-02T20:19:39-07:00" level=info msg=ConnectionClosed connectionID=4 +time="2026-09-02T20:19:39-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:39.225952903 -0700 PDT m=+0.642133758" connectionDb=contract1788405578811 connectionID=5 error="table not found: schema_migrations" queryTime="2026-09-02 20:19:39.227179844 -0700 PDT m=+0.643360715" +time="2026-09-02T20:19:39-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=6 +time="2026-09-02T20:19:39-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:39.227569587 -0700 PDT m=+0.643750458" connectionDb=contract1788405578811 connectionID=6 error="table not found: schema_migrations" queryTime="2026-09-02 20:19:39.228468448 -0700 PDT m=+0.644649319" +time="2026-09-02T20:19:39-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:39.227569587 -0700 PDT m=+0.643750458" connectionDb=contract1788405578811 connectionID=6 error="table not found: schema_migrations" queryTime="2026-09-02 20:19:39.229670589 -0700 PDT m=+0.645851444" +time="2026-09-02T20:19:39-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:39.227569587 -0700 PDT m=+0.643750458" connectionDb=contract1788405578811 connectionID=6 error="table not found: schema_migrations" queryTime="2026-09-02 20:19:39.231568551 -0700 PDT m=+0.647749422" +time="2026-09-02T20:19:40-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:39.227569587 -0700 PDT m=+0.643750458" connectionDb=contract1788405578811 connectionID=6 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:19:40.976721535 -0700 PDT m=+2.392902390" +time="2026-09-02T20:19:41-07:00" level=info msg=ConnectionClosed connectionID=6 +time="2026-09-02T20:19:41-07:00" level=info msg=ConnectionClosed connectionID=5 +time="2026-09-02T20:19:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=7 +time="2026-09-02T20:19:41-07:00" level=info msg=ConnectionClosed connectionID=7 +time="2026-09-02T20:19:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=8 +time="2026-09-02T20:19:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=9 +time="2026-09-02T20:19:41-07:00" level=info msg=ConnectionClosed connectionID=8 +time="2026-09-02T20:19:41-07:00" level=info msg=ConnectionClosed connectionID=9 +time="2026-09-02T20:19:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=10 +time="2026-09-02T20:19:41-07:00" level=info msg=ConnectionClosed connectionID=10 +time="2026-09-02T20:19:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=11 +time="2026-09-02T20:19:41-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=12 +time="2026-09-02T20:19:41-07:00" level=info msg=ConnectionClosed connectionID=11 +time="2026-09-02T20:19:41-07:00" level=info msg=ConnectionClosed connectionID=12 +time="2026-09-02T20:19:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=13 +time="2026-09-02T20:19:42-07:00" level=info msg=ConnectionClosed connectionID=13 +time="2026-09-02T20:19:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=14 +time="2026-09-02T20:19:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=15 +time="2026-09-02T20:19:42-07:00" level=info msg=ConnectionClosed connectionID=14 +time="2026-09-02T20:19:42-07:00" level=info msg=ConnectionClosed connectionID=15 +time="2026-09-02T20:19:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=16 +time="2026-09-02T20:19:42-07:00" level=info msg=ConnectionClosed connectionID=16 +time="2026-09-02T20:19:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=17 +time="2026-09-02T20:19:42-07:00" level=info msg=ConnectionClosed connectionID=17 +time="2026-09-02T20:19:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=18 +time="2026-09-02T20:19:42-07:00" level=info msg=ConnectionClosed connectionID=18 +time="2026-09-02T20:19:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=19 +time="2026-09-02T20:19:42-07:00" level=info msg=ConnectionClosed connectionID=19 +time="2026-09-02T20:19:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=20 +time="2026-09-02T20:19:42-07:00" level=info msg=ConnectionClosed connectionID=20 +time="2026-09-02T20:19:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=21 +time="2026-09-02T20:19:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=22 +time="2026-09-02T20:19:42-07:00" level=info msg=ConnectionClosed connectionID=21 +time="2026-09-02T20:19:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=23 +time="2026-09-02T20:19:42-07:00" level=info msg=ConnectionClosed connectionID=23 +time="2026-09-02T20:19:42-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:42.691515019 -0700 PDT m=+4.107695906" connectionDb=contract1788405578811 connectionID=22 error="backup 'backup_export' not found" queryTime="2026-09-02 20:19:42.783267791 -0700 PDT m=+4.199448678" +time="2026-09-02T20:19:42-07:00" level=info msg=ConnectionClosed connectionID=22 +time="2026-09-02T20:19:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=24 +time="2026-09-02T20:19:42-07:00" level=info msg=ConnectionClosed connectionID=24 +time="2026-09-02T20:19:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=25 +time="2026-09-02T20:19:42-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=26 +time="2026-09-02T20:19:42-07:00" level=info msg=ConnectionClosed connectionID=25 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=26 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=27 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=27 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=28 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=28 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=29 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=29 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=30 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=30 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=31 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=32 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=31 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=33 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=33 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=32 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=34 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=34 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=35 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=36 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=35 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=36 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=37 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=37 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=38 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=38 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=39 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=39 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=40 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=40 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=41 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=42 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=41 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=43 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=43 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=42 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=44 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=44 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=45 +time="2026-09-02T20:19:43-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=46 +time="2026-09-02T20:19:43-07:00" level=info msg=ConnectionClosed connectionID=45 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=46 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=47 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=47 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=48 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=48 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=49 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=49 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=50 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=50 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=51 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=52 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=51 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=53 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=53 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=52 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=54 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=54 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=55 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=55 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=56 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=56 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=57 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=57 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=58 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=59 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=58 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=59 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=60 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=60 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=61 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=62 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=61 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=62 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=63 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=63 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=64 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=65 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=64 +time="2026-09-02T20:19:44-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=66 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=66 +time="2026-09-02T20:19:44-07:00" level=info msg=ConnectionClosed connectionID=65 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=67 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=67 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=68 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=69 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=68 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=70 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=70 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=69 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=71 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=71 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=72 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=72 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=73 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=73 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=74 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=75 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=74 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=76 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=76 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=75 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=77 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=77 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=78 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=79 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=78 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=80 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=80 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=79 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=81 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=81 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=82 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=82 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=83 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=83 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=84 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=84 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=85 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=85 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=86 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=86 +time="2026-09-02T20:19:45-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=87 +time="2026-09-02T20:19:45-07:00" level=info msg=ConnectionClosed connectionID=87 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=88 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=88 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=89 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=90 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=89 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=91 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=91 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=90 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=92 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=92 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=93 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=94 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=93 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=95 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=95 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=94 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=96 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=96 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=97 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=97 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=98 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=98 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=99 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=99 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=100 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=100 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=101 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=101 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=102 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=103 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=102 +time="2026-09-02T20:19:46-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=104 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=104 +time="2026-09-02T20:19:46-07:00" level=info msg=ConnectionClosed connectionID=103 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=105 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=105 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=106 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=107 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=106 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=108 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=108 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=107 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=109 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=109 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=110 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=111 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=110 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=111 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=112 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=112 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=113 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=114 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=113 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=114 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=115 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=115 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=116 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=117 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=116 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=118 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=118 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=117 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=119 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=119 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=120 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=120 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=121 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=121 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=122 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=122 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=123 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=123 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=124 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=124 +time="2026-09-02T20:19:47-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=125 +time="2026-09-02T20:19:47-07:00" level=info msg=ConnectionClosed connectionID=125 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=126 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=126 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=127 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=127 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=128 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=128 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=129 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=129 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=130 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=130 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=131 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=131 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=132 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=132 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=133 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=133 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=134 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=134 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=135 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=135 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=136 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=136 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=137 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=137 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=138 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=138 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=139 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=139 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=140 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=140 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=141 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=141 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=142 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=142 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=143 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=143 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=144 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=144 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=145 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=145 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=146 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=146 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=147 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=147 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=148 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=149 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=148 +time="2026-09-02T20:19:48-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=150 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=150 +time="2026-09-02T20:19:48-07:00" level=info msg=ConnectionClosed connectionID=149 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=151 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=151 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=152 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=153 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=152 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=154 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=154 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=153 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=155 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=155 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=156 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=156 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=157 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=157 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=158 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=158 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=159 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=159 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=160 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=160 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=161 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=161 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=162 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=163 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=162 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=164 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=164 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=163 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=165 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=165 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=166 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=166 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=167 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=167 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=168 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=168 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=169 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=170 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=169 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=171 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=171 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=170 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=172 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=172 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=173 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=173 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=174 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=174 +time="2026-09-02T20:19:49-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=175 +time="2026-09-02T20:19:49-07:00" level=info msg=ConnectionClosed connectionID=175 +time="2026-09-02T20:19:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=176 +time="2026-09-02T20:19:50-07:00" level=info msg=ConnectionClosed connectionID=176 +time="2026-09-02T20:19:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=177 +time="2026-09-02T20:19:50-07:00" level=info msg=ConnectionClosed connectionID=177 +time="2026-09-02T20:19:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=178 +time="2026-09-02T20:19:50-07:00" level=info msg=ConnectionClosed connectionID=178 +time="2026-09-02T20:19:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=179 +time="2026-09-02T20:19:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=180 +time="2026-09-02T20:19:50-07:00" level=info msg=ConnectionClosed connectionID=179 +time="2026-09-02T20:19:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=181 +time="2026-09-02T20:19:50-07:00" level=info msg=ConnectionClosed connectionID=181 +time="2026-09-02T20:19:50-07:00" level=info msg=ConnectionClosed connectionID=180 +time="2026-09-02T20:19:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=182 +time="2026-09-02T20:19:50-07:00" level=info msg=ConnectionClosed connectionID=182 +time="2026-09-02T20:19:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=183 +time="2026-09-02T20:19:50-07:00" level=info msg=ConnectionClosed connectionID=183 +time="2026-09-02T20:19:50-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=184 +time="2026-09-02T20:19:50-07:00" level=info msg=ConnectionClosed connectionID=184 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=185 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=185 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=186 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=187 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=186 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=188 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=188 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=187 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=189 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=189 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=190 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=191 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=190 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=191 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=192 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=192 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=193 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=193 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=194 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=194 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=195 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=195 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=196 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=197 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=196 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=198 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=198 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=197 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=199 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=199 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=200 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=200 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=201 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=201 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=202 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=202 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=203 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=203 +time="2026-09-02T20:19:52-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=204 +time="2026-09-02T20:19:52-07:00" level=info msg=ConnectionClosed connectionID=204 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=205 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=205 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=206 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=207 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=206 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=208 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=208 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=207 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=209 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=209 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=210 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=211 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=210 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=211 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=212 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=212 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=213 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=213 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=214 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=214 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=215 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=215 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=216 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=217 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=216 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=218 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=218 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=217 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=219 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=219 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=220 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=220 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=221 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=221 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=222 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=222 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=223 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=223 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=224 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=224 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=225 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=225 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=226 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=226 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=227 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=227 +time="2026-09-02T20:19:53-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=228 +time="2026-09-02T20:19:53-07:00" level=info msg=ConnectionClosed connectionID=228 +time="2026-09-02T20:19:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=229 +time="2026-09-02T20:19:54-07:00" level=info msg=ConnectionClosed connectionID=229 +time="2026-09-02T20:19:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=230 +time="2026-09-02T20:19:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=231 +time="2026-09-02T20:19:54-07:00" level=info msg=ConnectionClosed connectionID=230 +time="2026-09-02T20:19:54-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:54.112926827 -0700 PDT m=+15.529107698" connectionDb=contract1788405578811rm connectionID=231 error="table not found: schema_migrations" queryTime="2026-09-02 20:19:54.113880553 -0700 PDT m=+15.530061424" +time="2026-09-02T20:19:54-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=232 +time="2026-09-02T20:19:54-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:54.114364455 -0700 PDT m=+15.530545310" connectionDb=contract1788405578811rm connectionID=232 error="table not found: schema_migrations" queryTime="2026-09-02 20:19:54.11501519 -0700 PDT m=+15.531196045" +time="2026-09-02T20:19:54-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:54.114364455 -0700 PDT m=+15.530545310" connectionDb=contract1788405578811rm connectionID=232 error="table not found: schema_migrations" queryTime="2026-09-02 20:19:54.116270146 -0700 PDT m=+15.532451033" +time="2026-09-02T20:19:54-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:54.114364455 -0700 PDT m=+15.530545310" connectionDb=contract1788405578811rm connectionID=232 error="table not found: schema_migrations" queryTime="2026-09-02 20:19:54.118223149 -0700 PDT m=+15.534404036" +time="2026-09-02T20:19:56-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:54.114364455 -0700 PDT m=+15.530545310" connectionDb=contract1788405578811rm connectionID=232 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:19:56.023742674 -0700 PDT m=+17.439923561" +time="2026-09-02T20:19:56-07:00" level=info msg=ConnectionClosed connectionID=232 +time="2026-09-02T20:19:56-07:00" level=info msg=ConnectionClosed connectionID=231 +time="2026-09-02T20:19:56-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=233 +time="2026-09-02T20:19:56-07:00" level=info msg=ConnectionClosed connectionID=233 +time="2026-09-02T20:19:56-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=234 +time="2026-09-02T20:19:56-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=235 +time="2026-09-02T20:19:56-07:00" level=info msg=ConnectionClosed connectionID=234 +time="2026-09-02T20:19:56-07:00" level=info msg=ConnectionClosed connectionID=235 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=236 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=236 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=237 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=238 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=237 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=238 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=239 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=239 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=240 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=241 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=240 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=241 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=242 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=242 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=243 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=243 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=244 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=244 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=245 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=245 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=246 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=246 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=247 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=248 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=247 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=249 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=249 +time="2026-09-02T20:19:57-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:57.369236056 -0700 PDT m=+18.785416943" connectionDb=contract1788405578811rm connectionID=248 error="backup 'backup_export' not found" queryTime="2026-09-02 20:19:57.488358658 -0700 PDT m=+18.904539545" +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=248 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=250 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=250 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=251 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=251 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=252 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=252 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=253 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=253 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=254 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=254 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=255 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=255 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=256 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=256 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=257 +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=258 +time="2026-09-02T20:19:57-07:00" level=info msg=ConnectionClosed connectionID=257 +time="2026-09-02T20:19:57-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:57.919089204 -0700 PDT m=+19.335270075" connectionDb=contract1788405578811rm connectionID=258 error="table not found: schema_migrations" queryTime="2026-09-02 20:19:57.920337345 -0700 PDT m=+19.336518216" +time="2026-09-02T20:19:57-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=259 +time="2026-09-02T20:19:57-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:57.920935055 -0700 PDT m=+19.337115958" connectionDb=contract1788405578811rm connectionID=259 error="table not found: schema_migrations" queryTime="2026-09-02 20:19:57.922267068 -0700 PDT m=+19.338447955" +time="2026-09-02T20:19:57-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:57.920935055 -0700 PDT m=+19.337115958" connectionDb=contract1788405578811rm connectionID=259 error="table not found: schema_migrations" queryTime="2026-09-02 20:19:57.925548099 -0700 PDT m=+19.341728970" +time="2026-09-02T20:19:57-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:57.920935055 -0700 PDT m=+19.337115958" connectionDb=contract1788405578811rm connectionID=259 error="table not found: schema_migrations" queryTime="2026-09-02 20:19:57.928564442 -0700 PDT m=+19.344745313" +time="2026-09-02T20:20:00-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:19:57.920935055 -0700 PDT m=+19.337115958" connectionDb=contract1788405578811rm connectionID=259 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:20:00.107027813 -0700 PDT m=+21.523208684" +time="2026-09-02T20:20:00-07:00" level=info msg=ConnectionClosed connectionID=259 +time="2026-09-02T20:20:00-07:00" level=info msg=ConnectionClosed connectionID=258 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=260 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=260 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=261 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=262 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=261 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=262 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=263 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=263 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=264 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=265 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=264 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=265 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=266 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=266 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=267 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=268 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=267 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=268 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=269 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=269 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=270 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=270 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=271 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=271 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=272 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=272 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=273 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=273 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=274 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=274 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=275 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=275 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=276 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=276 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=277 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=277 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=278 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=278 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=279 +time="2026-09-02T20:20:01-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:20:01.575275499 -0700 PDT m=+22.991456354" connectionID=279 error="database not found: contract1788405578811atomic" queryTime="2026-09-02 20:20:01.576922119 -0700 PDT m=+22.993102990" +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=279 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=280 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=280 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=281 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=281 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=282 +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=283 +time="2026-09-02T20:20:01-07:00" level=info msg=ConnectionClosed connectionID=282 +time="2026-09-02T20:20:01-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:20:01.837452717 -0700 PDT m=+23.253633572" connectionDb=contract1788405578811atomic connectionID=283 error="table not found: schema_migrations" queryTime="2026-09-02 20:20:01.838466618 -0700 PDT m=+23.254647489" +time="2026-09-02T20:20:01-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=284 +time="2026-09-02T20:20:01-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:20:01.838950761 -0700 PDT m=+23.255131616" connectionDb=contract1788405578811atomic connectionID=284 error="table not found: schema_migrations" queryTime="2026-09-02 20:20:01.839869846 -0700 PDT m=+23.256050717" +time="2026-09-02T20:20:01-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:20:01.838950761 -0700 PDT m=+23.255131616" connectionDb=contract1788405578811atomic connectionID=284 error="table not found: schema_migrations" queryTime="2026-09-02 20:20:01.840863459 -0700 PDT m=+23.257044362" +time="2026-09-02T20:20:01-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:20:01.838950761 -0700 PDT m=+23.255131616" connectionDb=contract1788405578811atomic connectionID=284 error="table not found: schema_migrations" queryTime="2026-09-02 20:20:01.843056797 -0700 PDT m=+23.259237668" +time="2026-09-02T20:20:03-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:20:01.838950761 -0700 PDT m=+23.255131616" connectionDb=contract1788405578811atomic connectionID=284 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:20:03.847741606 -0700 PDT m=+25.263922477" +time="2026-09-02T20:20:04-07:00" level=info msg=ConnectionClosed connectionID=284 +time="2026-09-02T20:20:04-07:00" level=info msg=ConnectionClosed connectionID=283 +time="2026-09-02T20:20:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=285 +time="2026-09-02T20:20:04-07:00" level=info msg=ConnectionClosed connectionID=285 +time="2026-09-02T20:20:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=286 +time="2026-09-02T20:20:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=287 +time="2026-09-02T20:20:04-07:00" level=info msg=ConnectionClosed connectionID=286 +time="2026-09-02T20:20:04-07:00" level=info msg=ConnectionClosed connectionID=287 +time="2026-09-02T20:20:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=288 +time="2026-09-02T20:20:04-07:00" level=info msg=ConnectionClosed connectionID=288 +time="2026-09-02T20:20:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=289 +time="2026-09-02T20:20:04-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=290 +time="2026-09-02T20:20:04-07:00" level=info msg=ConnectionClosed connectionID=289 +time="2026-09-02T20:20:04-07:00" level=info msg=ConnectionClosed connectionID=290 +time="2026-09-02T20:20:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=291 +time="2026-09-02T20:20:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=292 +time="2026-09-02T20:20:05-07:00" level=info msg=ConnectionClosed connectionID=291 +time="2026-09-02T20:20:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=293 +time="2026-09-02T20:20:05-07:00" level=info msg=ConnectionClosed connectionID=292 +time="2026-09-02T20:20:05-07:00" level=info msg=ConnectionClosed connectionID=293 +time="2026-09-02T20:20:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=294 +time="2026-09-02T20:20:05-07:00" level=info msg=ConnectionClosed connectionID=294 +time="2026-09-02T20:20:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=295 +time="2026-09-02T20:20:05-07:00" level=info msg=ConnectionClosed connectionID=295 +time="2026-09-02T20:20:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=296 +time="2026-09-02T20:20:05-07:00" level=info msg=ConnectionClosed connectionID=296 +time="2026-09-02T20:20:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=297 +time="2026-09-02T20:20:05-07:00" level=info msg=ConnectionClosed connectionID=297 +time="2026-09-02T20:20:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=298 +time="2026-09-02T20:20:05-07:00" level=info msg=ConnectionClosed connectionID=298 +time="2026-09-02T20:20:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=299 +time="2026-09-02T20:20:05-07:00" level=info msg=ConnectionClosed connectionID=299 +time="2026-09-02T20:20:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=300 +time="2026-09-02T20:20:05-07:00" level=info msg="stats stopped: context canceled" +time="2026-09-02T20:20:05-07:00" level=info msg=ConnectionClosed connectionID=300 +time="2026-09-02T20:20:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=301 +time="2026-09-02T20:20:05-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:20:05.303750223 -0700 PDT m=+26.719931078" connectionID=301 error="database not found: contract1788405578811rm" queryTime="2026-09-02 20:20:05.305306443 -0700 PDT m=+26.721487314" +time="2026-09-02T20:20:05-07:00" level=info msg=ConnectionClosed connectionID=301 +time="2026-09-02T20:20:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=302 +time="2026-09-02T20:20:05-07:00" level=info msg="stats stopped: context canceled" +time="2026-09-02T20:20:05-07:00" level=info msg=ConnectionClosed connectionID=302 +time="2026-09-02T20:20:05-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=303 +time="2026-09-02T20:20:05-07:00" level=info msg=ConnectionClosed connectionID=303 +/tmp/f5c-before/tests/cli/test_cli_surface.py:831: AssertionError: [PASS] version bd 1.1.2 +=========================== short test summary info ============================ +FAILED tests/cli/test_cli_surface.py::test_doctor_quick_succeeds_against_the_real_installed_bd +1 failed, 1 passed, 50 deselected in 26.91s diff --git a/docs/lanes/f5c-work-tracker-reopen/evidence/parent-commit-modules-reap-preexisting-failure.log b/docs/lanes/f5c-work-tracker-reopen/evidence/parent-commit-modules-reap-preexisting-failure.log new file mode 100644 index 0000000..f0e5d42 --- /dev/null +++ b/docs/lanes/f5c-work-tracker-reopen/evidence/parent-commit-modules-reap-preexisting-failure.log @@ -0,0 +1,153 @@ +F... [100%] +=================================== FAILURES =================================== +__ test_explicit_resolve_refusal_after_reap_clears_held_and_allows_new_claim ___ +tests/test_reap_recovery.py:71: in test_explicit_resolve_refusal_after_reap_clears_held_and_allows_new_claim + assert resolved.success is False +E AssertionError: assert True is False +E + where True = ToolResult(success=True, output={'resolved': 'reapproj57b1e1938c-r5b', 'resolution': 'trying to close after being reclaimed'}, error=None).success +---------------------------- Captured stdout setup ----------------------------- +Starting server with Config HP="127.0.0.1:36761"|T="28800000"|R="false"|L="info" +---------------------------- Captured stderr setup ----------------------------- +time="2026-09-02T20:52:28-07:00" level=info msg="Creating root@localhost superuser" +time="2026-09-02T20:52:28-07:00" level=info msg="Server ready. Accepting connections." +time="2026-09-02T20:52:28-07:00" level=warning msg="secure_file_priv is set to \"\", which is insecure." +time="2026-09-02T20:52:28-07:00" level=warning msg="Any user with GRANT FILE privileges will be able to read any file which the sql-server process can read." +time="2026-09-02T20:52:28-07:00" level=warning msg="Please consider restarting the server with secure_file_priv set to a safe (or non-existent) directory." +time="2026-09-02T20:52:28-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=1 +time="2026-09-02T20:52:28-07:00" level=info msg=ConnectionClosed connectionID=1 +time="2026-09-02T20:52:28-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=2 +time="2026-09-02T20:52:28-07:00" level=info msg=ConnectionClosed connectionID=2 +time="2026-09-02T20:52:28-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=3 +time="2026-09-02T20:52:28-07:00" level=info msg=ConnectionClosed connectionID=3 +time="2026-09-02T20:52:28-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=4 +time="2026-09-02T20:52:29-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=5 +time="2026-09-02T20:52:29-07:00" level=info msg=ConnectionClosed connectionID=4 +time="2026-09-02T20:52:29-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:52:29.136038999 -0700 PDT m=+0.548396177" connectionDb=reapproj57b1e1938c connectionID=5 error="table not found: schema_migrations" queryTime="2026-09-02 20:52:29.137213189 -0700 PDT m=+0.549570367" +time="2026-09-02T20:52:29-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=6 +time="2026-09-02T20:52:29-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:52:29.137738291 -0700 PDT m=+0.550095517" connectionDb=reapproj57b1e1938c connectionID=6 error="table not found: schema_migrations" queryTime="2026-09-02 20:52:29.138494642 -0700 PDT m=+0.550851804" +time="2026-09-02T20:52:29-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:52:29.137738291 -0700 PDT m=+0.550095517" connectionDb=reapproj57b1e1938c connectionID=6 error="table not found: schema_migrations" queryTime="2026-09-02 20:52:29.139568879 -0700 PDT m=+0.551926057" +time="2026-09-02T20:52:29-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:52:29.137738291 -0700 PDT m=+0.550095517" connectionDb=reapproj57b1e1938c connectionID=6 error="table not found: schema_migrations" queryTime="2026-09-02 20:52:29.140543453 -0700 PDT m=+0.552900631" +time="2026-09-02T20:52:31-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:52:29.137738291 -0700 PDT m=+0.550095517" connectionDb=reapproj57b1e1938c connectionID=6 error="table not found: ignored_schema_migrations" queryTime="2026-09-02 20:52:31.525067552 -0700 PDT m=+2.937424810" +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=6 +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=5 +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=7 +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=7 +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=8 +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=9 +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=8 +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=9 +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=10 +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=10 +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=11 +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=12 +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=11 +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=12 +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=13 +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=13 +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=14 +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=15 +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=14 +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=15 +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=16 +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=16 +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=17 +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=17 +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=18 +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=18 +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=19 +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=19 +----------------------------- Captured stdout call ----------------------------- + +----------------------------- Captured stderr call ----------------------------- +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=20 +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=20 +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=21 +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=22 +time="2026-09-02T20:52:32-07:00" level=info msg=ConnectionClosed connectionID=21 +time="2026-09-02T20:52:32-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=23 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=23 +time="2026-09-02T20:52:33-07:00" level=warning msg="error running query" connectTime="2026-09-02 20:52:32.985874606 -0700 PDT m=+4.398231800" connectionDb=reapproj57b1e1938c connectionID=22 error="backup 'backup_export' not found" queryTime="2026-09-02 20:52:33.114670017 -0700 PDT m=+4.527027211" +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=22 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=24 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=24 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=25 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=26 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=25 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=26 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=27 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=27 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=28 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=28 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=29 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=29 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=30 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=30 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=31 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=32 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=31 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=33 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=33 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=32 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=34 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=34 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=35 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=35 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=36 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=36 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=37 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=37 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=38 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=38 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=39 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=39 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=40 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=40 +time="2026-09-02T20:52:33-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=41 +time="2026-09-02T20:52:33-07:00" level=info msg=ConnectionClosed connectionID=41 +time="2026-09-02T20:52:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=42 +time="2026-09-02T20:52:34-07:00" level=info msg=ConnectionClosed connectionID=42 +time="2026-09-02T20:52:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=43 +time="2026-09-02T20:52:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=44 +time="2026-09-02T20:52:34-07:00" level=info msg=ConnectionClosed connectionID=43 +time="2026-09-02T20:52:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=45 +time="2026-09-02T20:52:34-07:00" level=info msg=ConnectionClosed connectionID=45 +time="2026-09-02T20:52:34-07:00" level=info msg=ConnectionClosed connectionID=44 +time="2026-09-02T20:52:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=46 +time="2026-09-02T20:52:34-07:00" level=info msg=ConnectionClosed connectionID=46 +time="2026-09-02T20:52:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=47 +time="2026-09-02T20:52:34-07:00" level=info msg=ConnectionClosed connectionID=47 +time="2026-09-02T20:52:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=48 +time="2026-09-02T20:52:34-07:00" level=info msg=ConnectionClosed connectionID=48 +time="2026-09-02T20:52:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=49 +time="2026-09-02T20:52:34-07:00" level=info msg=ConnectionClosed connectionID=49 +time="2026-09-02T20:52:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=50 +time="2026-09-02T20:52:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=51 +time="2026-09-02T20:52:34-07:00" level=info msg=ConnectionClosed connectionID=50 +time="2026-09-02T20:52:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=52 +time="2026-09-02T20:52:34-07:00" level=info msg=ConnectionClosed connectionID=52 +time="2026-09-02T20:52:34-07:00" level=info msg=ConnectionClosed connectionID=51 +time="2026-09-02T20:52:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=53 +time="2026-09-02T20:52:34-07:00" level=info msg=ConnectionClosed connectionID=53 +time="2026-09-02T20:52:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=54 +time="2026-09-02T20:52:34-07:00" level=info msg=ConnectionClosed connectionID=54 +time="2026-09-02T20:52:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=55 +time="2026-09-02T20:52:34-07:00" level=info msg=ConnectionClosed connectionID=55 +------------------------------ Captured log call ------------------------------- +ERROR amplifier_work_tracker.webpush:webpush.py:435 ntfy alarm unexpected failure for reclaimed reapproj57b1e1938c-r5b: asyncio.run() cannot be called from a running event loop +--------------------------- Captured stderr teardown --------------------------- +time="2026-09-02T20:52:34-07:00" level=info msg=NewConnection DisableClientMultiStatements=false connectionID=56 +time="2026-09-02T20:52:34-07:00" level=info msg="stats stopped: context canceled" +time="2026-09-02T20:52:34-07:00" level=info msg=ConnectionClosed connectionID=56 +=============================== warnings summary =============================== +modules/tool-work-tracker/tests/test_reap_recovery.py::test_explicit_resolve_refusal_after_reap_clears_held_and_allows_new_claim +modules/tool-work-tracker/tests/test_reap_recovery.py::test_explicit_declare_refusal_after_reap_clears_held_and_allows_new_claim +modules/tool-work-tracker/tests/test_reap_recovery.py::test_background_renew_loop_detects_reap_and_clears_held_state + /home/bkrabach/dev/hw-model-performance/lanes/f5c-work-tracker-reopen/amplifier-work-tracker/modules/tool-work-tracker/.venv/lib/python3.12/site-packages/_pytest/stash.py:108: RuntimeWarning: coroutine 'alarm_for_reclaimed_item' was never awaited + del self._storage[key] + Enable tracemalloc to get traceback where the object was allocated. + See https://docs.pytest.org/en/stable/how-to/capture-warnings.html#resource-warnings for more info. + +-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html +=========================== short test summary info ============================ +FAILED tests/test_reap_recovery.py::test_explicit_resolve_refusal_after_reap_clears_held_and_allows_new_claim +1 failed, 3 passed, 3 warnings in 24.90s diff --git a/ledger/checks/test_custody_rows.py b/ledger/checks/test_custody_rows.py index fba0461..d48a3f0 100644 --- a/ledger/checks/test_custody_rows.py +++ b/ledger/checks/test_custody_rows.py @@ -158,13 +158,18 @@ def test_row_ccv1_009() -> None: the released state (a legitimate fix shape that keeps the existing gate) also flips this probe: every `raise FencedError` in resolve's pre-write region must still sit inside the `status == "held"` block. + + The pre-write region is delimited by the `close` write itself rather + than by "the first `try:`", and the gate is matched on its condition + rather than a whole line: the close path acquired a pre-write read of + its own (the already-resolved rule, item model_performance-f5c), which + moved both landmarks without touching this row's claim. The fence is + still gated on `held` and this row is still a VIOLATION. """ src = read(ADAPTER) - body = src[ - src.index(" def resolve(self, item_id: str") : src.index(" def _read_back_or_none") - ] - pre_write = body[: body.index(" try:")] - gate = ' if current.status == "held":' + body = src[src.index(" def resolve_outcome(") : src.index(" def _read_back_or_none")] + pre_write = body[: body.index('p = self._run(["close"')] + gate = 'current.status == "held":' assert gate in pre_write, "CCV1-009 pin: the status gate is gone" fences = [m.start() for m in re.finditer(r"raise FencedError", pre_write)] assert fences and all(pos > pre_write.index(gate) for pos in fences), ( @@ -256,17 +261,23 @@ def test_row_ccv1_013() -> None: def test_row_ccv1_015() -> None: """Core 11 GAP pin: the conflicted-write read-back helper has exactly - three occurrences -- its definition and two call sites (`resolve`, - `release`). Every other write verb still propagates an exhausted-retry - exception directly, so a landed write can still surface as a reported - failure there. + four occurrences -- its definition and three call sites (`resolve`, + `release`, `reopen`). Every other write verb still propagates an + exhausted-retry exception directly, so a landed write can still surface + as a reported failure there. + + Was three (resolve, release). `reopen` (item model_performance-f5c) + adopted the same verify-on-conflict discipline when it shipped -- real + movement TOWARD the clause, recorded here rather than absorbed + silently. Still a GAP: the two writes that matter most for custody, + `take_custody` and `renew_custody`, remain uncovered. """ occurrences = count(ADAPTER, "_read_back_or_none") - assert occurrences == 3, ( - f"CCV1-015 (Core 11, GAP) pin: expected 3 occurrences of `_read_back_or_none` " - f"(1 definition + 2 call sites: resolve, release), found {occurrences}. If a " - f"third write verb adopted verify-on-conflict, update the row's coverage list " - f"(and resolve work_item_pipeline-2x3 when the custody-relevant writes -- " + assert occurrences == 4, ( + f"CCV1-015 (Core 11, GAP) pin: expected 4 occurrences of `_read_back_or_none` " + f"(1 definition + 3 call sites: resolve, release, reopen), found {occurrences}. " + f"If a fourth write verb adopted verify-on-conflict, update the row's coverage " + f"list (and resolve work_item_pipeline-2x3 when the custody-relevant writes -- " f"take_custody, renew_custody -- are covered)." ) @@ -358,18 +369,30 @@ def test_row_ccv1_023() -> None: f"are implemented-and-runnable, update the row, and resolve " f"work_item_pipeline-qmj when all four are." ) - # Fixture 4 (single-hold) is asserted by no test anywhere in either suite. + # Fixture 4 (single-hold) is asserted by NO test in the root suite -- the + # only suite `make test` runs, which is what the Freeze Bar clause + # actually requires ("executable via `make test`"). hits = [ p for p in (REPO_ROOT / "tests").rglob("test_*.py") if "single_hold" in read(p) or "already holding" in read(p) ] - hits += [ - p + assert not hits, f"CCV1-023 pin: a single-hold fixture now exists ({hits}) -- update the row" + # In the MODULES suite (which `make test` does not run -- CCV1-022) the + # single-hold refusal is now asserted, but only incidentally: as one + # branch of `work_reopen`'s claim-degradation path (item + # model_performance-f5c), not as the dedicated fixture the contract + # names. Pinned by exact file set so a REAL Fixture 4 appearing there + # still flips this probe rather than hiding behind the incidental hit. + module_hits = { + p.name for p in (REPO_ROOT / "modules" / "tool-work-tracker" / "tests").rglob("test_*.py") if "single_hold" in read(p) or "already holding" in read(p) - ] - assert not hits, f"CCV1-023 pin: a single-hold fixture now exists ({hits}) -- update the row" + } + assert module_hits == {"test_work_reopen.py"}, ( + f"CCV1-023 pin: the modules-suite single-hold assertions changed ({module_hits}) " + f"-- re-check whether Fixture 4 now exists as a dedicated fixture and update the row" + ) # The contract still names those non-existent locations (drift the row records). assert contains( CONTRACT_PATH, "**Test location:** `tests/test_single_hold.py` (to be added)." diff --git a/ledger/rows.yaml b/ledger/rows.yaml index ac2805f..9df72c9 100644 --- a/ledger/rows.yaml +++ b/ledger/rows.yaml @@ -256,6 +256,12 @@ ratified Call 3 (option A). A correct fix must keep BOTH halves: refuse the stale holder, and still allow an integrator's single-call resolve of an item nobody holds. + 2026-09-02 (item model_performance-f5c): the close path grew a pre-write + read of its own (the already-resolved rule) and the fence moved from + `resolve` into `resolve_outcome`, which `resolve` now projects. The + probe's landmarks were re-pointed to follow it; the CLAIM is unchanged + and re-verified -- the fence still runs only under `status == "held"`, + so a post-reclaim close is still unfenced. Disposition stays VIOLATION. - id: CCV1-010 title: a session that lost custody can discover it and recover in-process @@ -402,7 +408,8 @@ kind: probe ref: test_row_ccv1_015 notes: > - `_read_back_or_none` has exactly two call sites. Every other write verb + `_read_back_or_none` has three call sites: resolve, release, and (since + 2026-09-02, item model_performance-f5c) reopen. Every other write verb -- take_custody, renew_custody, claim_item, defer/block, supersede, update/edit, add_dependency, comment -- still propagates an exhausted-retry BeadsError directly, and exhaustion does not prove the @@ -410,6 +417,9 @@ take_custody (a false failure produces exactly the CCV1-003 held-without-custody state) and renew_custody (a false failure ends renewal one-strike and dooms a live hold). + DRIFT TOWARD SPEC, recorded not absorbed: reopen adopting the discipline + is real movement, and the count moved 3 -> 4. The row stays GAP because + neither custody-relevant write is covered. - id: CCV1-016 title: awareness.md still asserts a reported conflict means the write did not land @@ -594,6 +604,13 @@ session latch) rather than the ADAPTER-layer gap CCV1-009 pins. FIXTURE 3 (in-process recovery): tests/test_recovery.py does not exist; the adapter half is covered elsewhere (CCV1-010), the tool-seam half is in - the unrun suite. FIXTURE 4 (single-hold): does not exist in any suite; - `already holding` appears only at its own enforcement site. Blocked on + the unrun suite. FIXTURE 4 (single-hold): still not implemented as a + dedicated fixture, and still not executable via `make test`. As of + 2026-09-02 (item model_performance-f5c) the refusal IS now asserted + INCIDENTALLY in the modules suite -- + modules/tool-work-tracker/tests/test_work_reopen.py exercises it as one + branch of work_reopen's claim-degradation path -- but that suite is the + one `make test` does not run, so the Freeze Bar clause quoted above is + still unmet. Recorded here rather than absorbed silently; the probe now + pins that exact file set so a real Fixture 4 still flips it. Blocked on CCV1-022 for anything that must live in the modules suite.