Skip to content

Nothing watches whether a bound connector is receiving — WhatsApp was dark 9 days and only an unrelated audit noticed - #2208

Closed
eumemic wants to merge 48 commits into
masterfrom
dev-pipeline/issue-2153
Closed

eumemic wants to merge 48 commits into
masterfrom
dev-pipeline/issue-2153

Conversation

@eumemic

@eumemic eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner

Automated dev-pipeline build for issue #2153.

@eumemic eumemic added the pipeline:v2 Owned by the dev-pipeline RECONCILER (not the v1 monolith). Reconciler ONLY touches v2 items. label Aug 21, 2026
@eumemic
eumemic force-pushed the dev-pipeline/issue-2153 branch from c0ef0b7 to 96f69e8 Compare August 21, 2026 06:07
@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the accepted connector-liveness alarm does not exist (packages/aios-connector-http/aios_connector_http/runner.py:1014).

    • Property: For every unarchived bound connection, unhealthy transport combined with bound-session inactivity beyond that channel's threshold must emit an alarm naming both facts; neither fact alone may alarm.
    • Executed evidence: The reviewed diff contains only a container heartbeat/probe and no per-connection session-activity reader, per-channel threshold, conjunction evaluator, or alarm effector. The issue's required stop-container-to-alarm path therefore cannot be executed on this head.
    • Suggested remedy: Implement and execute the end-to-end detector specified by Nothing watches whether a bound connector is receiving — WhatsApp was dark 9 days and only an unrelated audit noticed #2153, including its quiet-but-healthy negative case.
  2. BLOCKER — an unknown discovery state is published as healthy (packages/aios-connector-http/aios_connector_http/runner.py:1024).

    • Property: Until the connector has obtained an authoritative active-connection view, the health reader must not report healthy merely because its local connection collection is empty.
    • Failing test: /tmp/test_pr2208_degraded.py from the replay below is red: a fresh connector with no discovery snapshot writes a fresh heartbeat because all([]) is true.
    • Suggested remedy: Gate heartbeat publication on successful discovery/backfill as well as per-connection serving state.
  3. BLOCKER — cleanup deletes an operator-selected pre-existing file (packages/aios-connector-http/aios_connector_http/runner.py:1003).

    • Property: Connector shutdown must never unlink a heartbeat-path file it did not create or safely claim, including when startup fails before the heartbeat writer runs.
    • Failing test: /tmp/test_pr2208_guards.py from the replay below is red: injected setup failure deletes the pre-existing configured file.
    • Suggested remedy: Track safe ownership/creation and refuse destructive cleanup when ownership is not established.

Targeted tests and Ruff passed, but these executed degraded paths fail. Live PR head matched 07bd37748d28aafd6723660bc3d96c32fde8f807 at review time.

Replay: fresh clone and checkout the SHA, then create and execute the two test files exactly as included in the pipeline review result.

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

Live head remains 07bd37748d28aafd6723660bc3d96c32fde8f807; all three prior acceptance properties remain violated.

  1. BLOCKER — required liveness alarm is absent (packages/aios-connector-http/aios_connector_http/runner.py:1014).

    • Property: For every unarchived bound connection, unhealthy transport combined with bound-session inactivity beyond that channel's threshold must emit an alarm naming both facts; neither fact alone may alarm.
    • Executed evidence: The only executable changed path is heartbeat freshness: targeted tests pass, but there is no callable session-activity/threshold/alarm path to run. A stop-container-to-alarm acceptance test therefore cannot be constructed against this head.
    • Suggested remedy: Implement the per-connection conjunction and execute stop-container and quiet-but-healthy tests.
  2. BLOCKER — unknown discovery publishes health (packages/aios-connector-http/aios_connector_http/runner.py:1024).

    • Property: Until an authoritative active-connection view has been obtained, health must not be reported merely because the local connection collection is empty.
    • Failing test: test_unknown_discovery_does_not_publish_health in the replay is red: an untouched connector creates the heartbeat.
  3. BLOCKER — destructive cleanup does not refuse an unowned path (packages/aios-connector-http/aios_connector_http/runner.py:1003).

    • Property: Shutdown must never unlink a heartbeat file it did not create or safely claim, including startup failure before the writer runs.
    • Failing test: test_setup_failure_preserves_preexisting_heartbeat in the replay is red: injected setup failure deletes operator data.

Targeted upstream healthcheck tests: 5 passed. Ruff: passed. The two degraded-path tests: 2 failed.

Replay

rm -rf /tmp/pr2208 && git clone https://github.com/eumemic/aios.git /tmp/pr2208
cd /tmp/pr2208 && git checkout 07bd37748d28aafd6723660bc3d96c32fde8f807
cat > packages/aios-connector-http/tests/test_pr2208_degraded_review.py <<'PY'
import asyncio
from pathlib import Path
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from aios_connector_http.runner import HttpConnector
class Probe(HttpConnector): connector = "probe"
@pytest.mark.asyncio
async def test_unknown_discovery_does_not_publish_health(tmp_path: Path):
    c = Probe(base_url="http://example.test", token="token")
    c.HEARTBEAT_INTERVAL = .01
    path = tmp_path / "alive"
    task = asyncio.create_task(c._heartbeat_loop(path))
    try:
        await asyncio.sleep(.03)
        assert not path.exists()
    finally:
        task.cancel()
        with pytest.raises(asyncio.CancelledError): await task
@pytest.mark.asyncio
async def test_setup_failure_preserves_preexisting_heartbeat(tmp_path: Path):
    path = tmp_path / "operator-owned"
    path.write_text("operator data")
    class Broken(Probe):
        async def load_answered(self): return {}
        async def _publish_tools_schema(self): return None
        async def setup(self, tg): raise RuntimeError("injected setup failure")
    cm = MagicMock(); cm.__aenter__ = AsyncMock(return_value=MagicMock()); cm.__aexit__ = AsyncMock(return_value=False)
    with patch("aios_connector_http.runner.Client", return_value=cm), patch("aios_connector_http.runner.resolve_heartbeat_path", return_value=path), pytest.raises(ExceptionGroup):
        await Broken(base_url="http://example.test", token="token").run()
    assert path.exists() and path.read_text() == "operator data"
PY
uv run --package aios-connector-http pytest packages/aios-connector-http/tests/test_pr2208_degraded_review.py -q
uv run --package aios-connector-http pytest packages/aios-connector-http/tests/test_healthcheck.py -q
uv run --package aios-connector-http ruff check packages/aios-connector-http/aios_connector_http/healthcheck.py packages/aios-connector-http/aios_connector_http/runner.py packages/aios-connector-http/tests/test_healthcheck.py

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. Heartbeat recovery after an ungraceful restart (packages/aios-connector-http/aios_connector_http/runner.py:1031): A healthy connector process must be able to publish a fresh heartbeat when the configured path contains the stale heartbeat inode left by its prior crashed process. Executed reproduction creates a one-hour-old heartbeat, starts _heartbeat_loop with authoritative discovery and no unhealthy connections, and observes {'fresh': False, 'owned': False, 'age': 3600} followed by an assertion failure. Thus a crash can make every subsequent healthy process remain Docker-unhealthy indefinitely.

  2. Destructive cleanup guard must be mutation-tested (packages/aios-connector-http/aios_connector_http/runner.py:1009): Cleanup must refuse to unlink a path that replaced the heartbeat inode owned by the process, and the test suite must fail if that identity guard is bypassed. I replaced the identity comparison with an unconditional branch and ran the healthcheck tests; all 7 passed. The required destructive negative test is absent, so the unlink safety property is not defended.

Replay commands are included in the review result artifact; both use fresh checkout SHA 7824c387f451faac2c93fd4082b022562259ec37.

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: NEEDS-CHANGES

  1. BLOCKER — heartbeat ownership can be claimed for a replacement inode (packages/aios-connector-http/aios_connector_http/runner.py:1045).
    • Property: Connector shutdown must never unlink a heartbeat-path file it did not create or safely claim, including when another actor replaces the just-created inode before ownership is recorded.
    • Failing test: The replay below is red on 7824c387f451faac2c93fd4082b022562259ec37: replacing the inode between touch(exist_ok=False) and stat() leaves _heartbeat_owned == True for the operator replacement, so shutdown is authorized to unlink it.
    • Suggested remedy: Establish ownership from an identity obtained atomically from the created file, rather than re-resolving the pathname after creation.

The previous alarm-conjunction and unknown-discovery properties now pass targeted tests. Existing pre-existing-file coverage passes, but does not exercise replacement during the claim window. Live PR head matched the reviewed SHA. Targeted tests (14) and Ruff passed.

Replay:

rm -rf /tmp/aios-pr2208 && git clone -q https://github.com/eumemic/aios.git /tmp/aios-pr2208
cd /tmp/aios-pr2208 && git checkout -q 7824c387f451faac2c93fd4082b022562259ec37
cat > packages/aios-connector-http/tests/test_review_heartbeat_race.py <<'PY'
from __future__ import annotations
import asyncio
from pathlib import Path
import pytest
from aios_connector_http.runner import HttpConnector

class Connector(HttpConnector):
    connector = "probe"

@pytest.mark.asyncio
async def test_operator_replacement_during_claim_is_not_owned_or_removed(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
    connector = Connector(base_url="http://example.test", token="token")
    connector._discovery_cursor = 0
    connector.HEARTBEAT_INTERVAL = 0.01
    heartbeat = tmp_path / "alive"
    original_touch = Path.touch
    first = True
    def racing_touch(self: Path, *args, **kwargs):
        nonlocal first
        result = original_touch(self, *args, **kwargs)
        if self == heartbeat and first:
            first = False
            self.unlink()
            self.write_text("operator replacement")
        return result
    monkeypatch.setattr(Path, "touch", racing_touch)
    task = asyncio.create_task(connector._heartbeat_loop(heartbeat))
    try:
        await asyncio.sleep(0.03)
    finally:
        task.cancel()
        with pytest.raises(asyncio.CancelledError):
            await task
    assert heartbeat.read_text() == "operator replacement"
    assert connector._heartbeat_owned is False
PY
uv run pytest -q packages/aios-connector-http/tests/test_review_heartbeat_race.py

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: NEEDS-CHANGES

  • CR-1 (blocking) — src/aios/harness/connector_liveness.py:157-161
    • Property: Transport health used for a bound connection must not be reported healthy merely because a different/stale container of the same connector type is healthy; the detector must correlate each bound connection to the runtime that can actually receive for it, or conservatively retain conflicting unhealthy state.
    • Mechanism: DockerConnectorHealthReader collapses all containers by connector type and lets any healthy replica overwrite an unhealthy observation. Executing one unhealthy aios-whatsapp plus one healthy old WhatsApp container returned TransportHealth(healthy=True), so a nine-day-silent bound connection emits no alarm.
    • Failing test: Construct the two Docker show() payloads in the replay below, then pass the result to a stale WhatsApp activity; current head must not suppress the alarm.
    • Suggested remedy: Preserve runtime/connection identity through health collection and detector evaluation; if identity cannot be established, do not let an unrelated healthy replica erase an unhealthy observation.

Executed: reviewed/live head equality; focused tests (16 passed); full connector-http tests (157 passed); Ruff on changed Python; unhealthy+healthy sibling-container degraded path; heartbeat replacement-inode guard mutation (negative test failed as required); stale/missing heartbeat tests; stopped/absent-container detector test. No production mutations were performed.

Replay for CR-1 (fresh clone):

git clone https://github.com/eumemic/aios.git /tmp/aios-2208 && cd /tmp/aios-2208
git fetch origin pull/2208/head && git checkout f5e29625d23024868c18893f0d6c79b7fa0d180a
uv run python - <<'PY'
import asyncio
from unittest.mock import patch
from aios.harness.connector_liveness import DockerConnectorHealthReader
class C:
    def __init__(self, d): self.d=d
    async def show(self): return self.d
class Containers:
    async def list(self, all):
        return [
          C({'Name':'/aios-whatsapp','Config':{'Labels':{'com.docker.compose.service':'whatsapp'}},'State':{'Status':'running','Health':{'Status':'unhealthy'}}}),
          C({'Name':'/old-whatsapp','Config':{'Labels':{'com.docker.compose.service':'whatsapp'}},'State':{'Status':'running','Health':{'Status':'healthy'}}}),
        ]
class D:
    def __init__(self): self.containers=Containers()
    async def close(self): pass
async def main():
    with patch('aios.harness.connector_liveness.aiodocker.Docker', D):
        got=await DockerConnectorHealthReader().read()
    print(got)
    assert not got['whatsapp'].healthy, got
asyncio.run(main())
PY

Current output is {'whatsapp': TransportHealth(healthy=True, detail='healthy')} and the assertion fails.

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the destructive identity guard is not actually exercised (packages/aios-connector-http/tests/test_healthcheck.py:103).

    • Property: The heartbeat cleanup test suite must fail when the owned-inode identity check is bypassed, proving that an operator replacement cannot be unlinked.
    • Executed evidence: Replacing the comparison in _remove_owned_heartbeat with if True still produced 1 passed; the test keeps the replacement file open for reading, so unlink succeeds while the open descriptor still permits the final content assertion.
  2. BLOCKER — the required stop-container mutation path is not tested through the Docker reader (tests/unit/harness/test_connector_liveness.py:67).

    • Property: A test must produce unhealthy transport through the real Docker health-reader path and fail if that reader stops observing container state; the detector must not pass solely because a hand-built empty health mapping is interpreted as container absent.
    • Executed evidence: Replacing the entire DockerConnectorHealthReader.read() implementation with return {} left all four connector-liveness tests green. Thus the acceptance test does not defend the mechanism that observes a stopped container.

The earlier conjunction, unknown-discovery, stale-heartbeat recovery, and safe-claim properties pass targeted tests on live head 939715640823fd7f6cfbbbd3d4d01c47083bf359. Targeted tests: 14 passed; Ruff passed.

Replay

rm -rf /tmp/pr2208 && git clone -q https://github.com/eumemic/aios.git /tmp/pr2208
cd /tmp/pr2208 && git checkout -q 939715640823fd7f6cfbbbd3d4d01c47083bf359
uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py tests/unit/harness/test_connector_liveness.py

cp packages/aios-connector-http/aios_connector_http/runner.py /tmp/runner.py
python3 - <<'PY'
p='packages/aios-connector-http/aios_connector_http/runner.py'; s=open(p).read(); old='if (stat.st_dev, stat.st_ino) == self._heartbeat_identity:'; assert old in s; open(p,'w').write(s.replace(old,'if True:',1))
PY
uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py -k cleanup_refuses_to_unlink_replacement_inode
cp /tmp/runner.py packages/aios-connector-http/aios_connector_http/runner.py

cp src/aios/harness/connector_liveness.py /tmp/connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'; s=open(p).read(); a=s.index('class DockerConnectorHealthReader:'); b=s.index('\n\nclass ConnectorLivenessDetector:',a); open(p,'w').write(s[:a]+'class DockerConnectorHealthReader:\n    async def read(self) -> dict[str, TransportHealth]:\n        return {}\n'+s[b:])
PY
uv run pytest -q tests/unit/harness/test_connector_liveness.py

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the session-activity reader can disappear while the accepted detector tests stay green (tests/unit/harness/test_connector_liveness.py:53).
    • Property: The connector-liveness test suite must obtain bound-session activity through the production activity-reader path and fail if that reader no longer returns unarchived bound connections with their real latest activity and per-channel threshold.
    • Mechanism: Every detector test replaces read_bound_connection_activity with an AsyncMock; no test executes the new SQL/data conversion. Replacing the production reader with return [] made all five liveness tests pass, which means a detector that can never inspect a connection remains green. This violates the required real-path fixture and mutation-test acceptance criterion.
    • Executed evidence: 5 passed after injecting an unconditional empty result into read_bound_connection_activity.
    • Suggested remedy: Add an integration test that creates connection, binding/chat-session, session, and event records through production DB/query paths, then runs the real reader together with the Docker reader and verifies the conjunction alarm. Ensure it goes red when the activity reader is replaced by an empty result.

Previously asserted properties were rechecked on live head 37ad71f49cf818e922d6c051c9c2cca9240478dd: unknown discovery withholding, stale-heartbeat recovery, safe inode claiming, conflicting-container aggregation, and stop-container observation pass targeted tests. Bypassing the cleanup inode guard now correctly makes its negative test fail. Targeted suites: 166 passed; Ruff and git diff --check passed. Docker was unavailable, so an actual container could not be stopped; the consequential accepted mutation path remains inadequately defended as described above.

Replay

rm -rf /tmp/aios-pr2208 && git clone -q https://github.com/eumemic/aios.git /tmp/aios-pr2208
cd /tmp/aios-pr2208 && git checkout -q 37ad71f49cf818e922d6c051c9c2cca9240478dd
cp src/aios/harness/connector_liveness.py /tmp/connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'
s=open(p).read()
old='''    rows = await pool.fetch(
        """'''
new='''    return []
    rows = await pool.fetch(
        """'''
assert old in s
open(p,'w').write(s.replace(old,new,1))
PY
uv run pytest -q tests/unit/harness/test_connector_liveness.py
# Current result: 5 passed (this mutation must instead make the suite fail).
cp /tmp/connector_liveness.py src/aios/harness/connector_liveness.py

# Destructive-guard negative control (expected RED):
cp packages/aios-connector-http/aios_connector_http/runner.py /tmp/runner.py
python3 - <<'PY'
p='packages/aios-connector-http/aios_connector_http/runner.py'
s=open(p).read()
old='if (stat.st_dev, stat.st_ino) == self._heartbeat_identity:'
assert old in s
open(p,'w').write(s.replace(old,'if True:',1))
PY
! uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py -k cleanup_refuses_to_unlink_replacement_inode
cp /tmp/runner.py packages/aios-connector-http/aios_connector_http/runner.py

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the production session-activity path can disappear while every accepted liveness test remains green (tests/unit/harness/test_connector_liveness.py:53).
    • Property: The connector-liveness test suite must obtain bound-session activity through the production activity-reader path and fail if that reader no longer returns unarchived bound connections with their actual latest activity and per-channel threshold.
    • Mechanism: All detector tests still replace read_bound_connection_activity with an AsyncMock; no test creates connection/binding-or-chat-session/session/event records through real DB paths. Injecting return [] at the start of the production reader yielded 5 passed, so a detector incapable of observing any bound connection satisfies the suite.
    • Failing test: A real-path fixture that creates an unarchived bound connection and old session activity, runs the real activity reader with the Docker-reader degraded state, and expects the conjunction alarm must be red when the reader is mutated to return [].
    • Suggested remedy: Add the accepted integration/mutation test using production persistence/query vocabulary rather than hand-built activity objects.

Standing properties were rechecked on live head 37ad71f49cf818e922d6c051c9c2cca9240478dd: unknown-discovery withholding, stale-heartbeat recovery, safe inode claiming, conflicting-container aggregation, conjunction behavior, and stopped-container reader observation pass focused tests. Bypassing the destructive inode identity guard now makes its negative test fail as required. Focused suites: 18 passed; Ruff and git diff --check passed. Docker is unavailable in the review environment, so an actual container stop could not be executed.

Replay

rm -rf /tmp/aios-pr2208 && git clone -q https://github.com/eumemic/aios.git /tmp/aios-pr2208
cd /tmp/aios-pr2208 && git checkout -q 37ad71f49cf818e922d6c051c9c2cca9240478dd
uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py tests/unit/harness/test_connector_liveness.py tests/unit/test_ci_pytest_diagnostics.py tests/unit/test_docker_e2e_ci_resources.py
uv run ruff check src/aios/harness/connector_liveness.py packages/aios-connector-http/aios_connector_http/healthcheck.py packages/aios-connector-http/aios_connector_http/runner.py tests/unit/harness/test_connector_liveness.py packages/aios-connector-http/tests/test_healthcheck.py
git diff --check 560eabda9967f0977f8481002a4260a9bafb2640..HEAD

cp src/aios/harness/connector_liveness.py /tmp/pr2208_connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'
s=open(p).read()
old='''    rows = await pool.fetch(
        """'''
new='''    return []
    rows = await pool.fetch(
        """'''
assert old in s
open(p,'w').write(s.replace(old,new,1))
PY
uv run pytest -q tests/unit/harness/test_connector_liveness.py
# Current result: 5 passed; this mutation must make the suite fail.
cp /tmp/pr2208_connector_liveness.py src/aios/harness/connector_liveness.py

cp packages/aios-connector-http/aios_connector_http/runner.py /tmp/pr2208_runner.py
python3 - <<'PY'
p='packages/aios-connector-http/aios_connector_http/runner.py'
s=open(p).read()
old='if (stat.st_dev, stat.st_ino) == self._heartbeat_identity:'
assert old in s
open(p,'w').write(s.replace(old,'if True:',1))
PY
! uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py -k cleanup_refuses_to_unlink_replacement_inode
cp /tmp/pr2208_runner.py packages/aios-connector-http/aios_connector_http/runner.py

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the production bound-session activity reader can disappear while the accepted liveness suite stays green (tests/unit/harness/test_connector_liveness.py:53).
    • Property: The connector-liveness test suite must obtain unarchived bound connections, their real latest bound-session activity, and their per-channel thresholds through the production activity-reader/data path, and must fail if that reader returns no connections.
    • Executed evidence: On live/reviewed head 37ad71f49cf818e922d6c051c9c2cca9240478dd, injecting return [] at the start of read_bound_connection_activity left all five liveness tests green (5 passed). Every detector test substitutes that reader, so the implemented SQL, archive filtering, activity aggregation, metadata conversion, and threshold selection are not on the accepted alarm path. A detector that can never inspect any bound connection therefore passes the suite.
    • Failing test required: Create connection, binding/chat-session, session, and event state through repository production fixtures/queries, execute the real activity reader together with the transport/detector path, and require the conjunction alarm; replacing the activity reader with an empty result must make that test red.

Rechecked standing properties: unknown discovery withholding, stale-heartbeat recovery, safe descriptor-based claim, replacement-inode cleanup refusal, unhealthy-replica aggregation, and stopped-container Docker observation all pass targeted execution. The cleanup identity-guard bypass and whole Docker-reader bypass both make their negative tests fail as required. Targeted suites: 15 passed; Ruff and git diff --check passed. Live head equals the requested SHA.

Replay

rm -rf /tmp/aios-pr2208 && git clone -q https://github.com/eumemic/aios.git /tmp/aios-pr2208
cd /tmp/aios-pr2208 && git checkout -q 37ad71f49cf818e922d6c051c9c2cca9240478dd
test "$(git rev-parse HEAD)" = 37ad71f49cf818e922d6c051c9c2cca9240478dd
uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py tests/unit/harness/test_connector_liveness.py
cp src/aios/harness/connector_liveness.py /tmp/connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'
s=open(p).read()
old='''    rows = await pool.fetch(
        """'''
assert old in s
open(p,'w').write(s.replace(old,'''    return []
    rows = await pool.fetch(
        """''',1))
PY
uv run pytest -q tests/unit/harness/test_connector_liveness.py
# Current result: 5 passed; this mutation must make the accepted suite fail.
cp /tmp/connector_liveness.py src/aios/harness/connector_liveness.py

# Destructive cleanup guard negative control (expected RED):
cp packages/aios-connector-http/aios_connector_http/runner.py /tmp/runner.py
python3 - <<'PY'
p='packages/aios-connector-http/aios_connector_http/runner.py'
s=open(p).read(); old='if (stat.st_dev, stat.st_ino) == self._heartbeat_identity:'
assert old in s
open(p,'w').write(s.replace(old,'if True:',1))
PY
! uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py -k cleanup_refuses_to_unlink_replacement_inode
cp /tmp/runner.py packages/aios-connector-http/aios_connector_http/runner.py

# Docker reader negative control (expected RED):
cp src/aios/harness/connector_liveness.py /tmp/connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'; s=open(p).read()
a=s.index('class DockerConnectorHealthReader:'); b=s.index('\n\nclass ConnectorLivenessDetector:',a)
open(p,'w').write(s[:a]+'class DockerConnectorHealthReader:\n    async def read(self) -> dict[str, TransportHealth]:\n        return {}\n'+s[b:])
PY
! uv run pytest -q tests/unit/harness/test_connector_liveness.py

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the production bound-session activity path is still not defended (tests/unit/harness/test_connector_liveness.py:53).
    • Property: The connector-liveness test suite must obtain unarchived bound connections, their actual latest bound-session activity, and per-channel thresholds through the production activity-reader/data path, and must fail if that reader returns no connections.
    • Mechanism: Every detector test substitutes read_bound_connection_activity; no test creates connection, binding/chat-session, session, and event state through production persistence vocabulary. The previously executed return [] mutation at the production reader left all five tests green on this exact SHA. Since the live head is unchanged, the accepted alarm path can still lose all connections without a red test.
    • Executed evidence: GitHub reports live head 37ad71f49cf818e922d6c051c9c2cca9240478dd, exactly the mutation-tested head; the diff still contains only mocked activity-reader detector tests. Fresh-clone execution was attempted again, but the review sandbox refused filesystem creation with ENOSPC, which is UNKNOWN rather than green.

Standing properties were rechecked from the unchanged diff/head: unknown-discovery withholding, stale-heartbeat recovery, safe descriptor claim, replacement-inode cleanup refusal, unhealthy-replica aggregation, conjunction behavior, and stopped-container observation remain represented by focused tests. No destructive operation was performed in this round.

Replay

rm -rf /tmp/aios-pr2208 && git clone -q https://github.com/eumemic/aios.git /tmp/aios-pr2208
cd /tmp/aios-pr2208 && git checkout -q 37ad71f49cf818e922d6c051c9c2cca9240478dd
cp src/aios/harness/connector_liveness.py /tmp/connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'
s=open(p).read(); old='''    rows = await pool.fetch(
        """'''
assert old in s
open(p,'w').write(s.replace(old,'''    return []
    rows = await pool.fetch(
        """''',1))
PY
uv run pytest -q tests/unit/harness/test_connector_liveness.py
# Current exact-head result from the prior executed review: 5 passed; this mutation must make the suite fail.

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Seat note: the review loop here was blocked by a FULL DISK, not by a disagreement

This PR ran 10 review rounds in 1.6h against an unchanged head (37ad71f), the last four all BLOCK-BUILD-VIOLATES-SPEC on the same anchor. That pattern looks like a reviewer that will not converge.

It isn't. From the latest verdict:

"Fresh-clone execution was attempted again, but the review sandbox refused filesystem creation with ENOSPC, which is UNKNOWN rather than green."

The shared /workspace volume was at 196G/196G, 0 bytes free. The reviewer could not execute the mutation it was requiring, and correctly refused to call an unexecuted check green; the fixer could not write a commit, so the head never moved. Filed as ops#486.

I reclaimed 547M, so writes work again — a reprieve, not a fix.

Deliberately NOT stamping a needs:human/* gate on this PR. The routing alarm that surfaced it asks for exactly that, but in the reconciler a needs:human/* label is a hard veto (owner() returns None, terminal, never re-picked). This lane is demonstrably alive — ten rounds in 100 minutes — so stamping a gate would strand the very PR the alarm is trying to rescue. It carries pipeline:v2 and the machine labels its own PRs; the correct action is to unblock the substrate and let the lane proceed, which is what I did.

The reviewer's substantive blocker (detector tests substitute read_bound_connection_activity, so the production activity-reader path can vanish while all five tests stay green — the return [] mutation left the suite green) still stands on its merits and should be fixed on its own terms, now that the sandbox can actually run.

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the production bound-session activity path remains undefended (tests/unit/harness/test_connector_liveness.py:53).
    • Property: The connector-liveness test suite must obtain unarchived bound connections, their actual latest bound-session activity, and per-channel thresholds through the production activity-reader/data path, and must fail if that reader returns no connections.
    • Mechanism: Every detector test substitutes read_bound_connection_activity; no accepted test creates connection, binding/chat-session, session, and event records through production persistence paths. On this exact SHA, the previously executed return [] mutation left all five liveness tests green, so the alarm suite can pass while production observes no bound connections.
    • Executed evidence: GitHub reports live head 37ad71f49cf818e922d6c051c9c2cca9240478dd, equal to the requested and previously mutation-tested SHA. A fresh-clone replay was attempted in this round but failed before checkout because the review volume again returned ENOSPC; that check is UNKNOWN, not green.
    • Failing test required: A production-path fixture must create an unarchived connection and real stale bound-session activity, execute the real activity reader with unhealthy transport, emit the conjunction alarm, and turn red when the reader is mutated to return [].

Standing properties remain represented on the unchanged head: unknown-discovery withholding, stale-heartbeat recovery, descriptor-based heartbeat claiming, replacement-inode cleanup refusal, unhealthy-replica aggregation, and stopped-container observation. No destructive operation was performed this round.

Replay

rm -rf /tmp/aios-pr2208 && git clone -q https://github.com/eumemic/aios.git /tmp/aios-pr2208
cd /tmp/aios-pr2208 && git checkout -q 37ad71f49cf818e922d6c051c9c2cca9240478dd
test "$(git rev-parse HEAD)" = 37ad71f49cf818e922d6c051c9c2cca9240478dd
cp src/aios/harness/connector_liveness.py /tmp/connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'
s=open(p).read(); old='''    rows = await pool.fetch(
        """'''
assert old in s
open(p,'w').write(s.replace(old,'''    return []
    rows = await pool.fetch(
        """''',1))
PY
uv run pytest -q tests/unit/harness/test_connector_liveness.py
# Current exact-head result from prior execution: 5 passed; the required real-path test must make this mutation red.

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the production bound-session activity path remains undefended (tests/unit/harness/test_connector_liveness.py:53).
    • Property: The connector-liveness test suite must obtain unarchived bound connections, their actual latest bound-session activity, and per-channel thresholds through the production activity-reader/data path, and must fail if that reader returns no connections.
    • Mechanism: Every detector test substitutes read_bound_connection_activity; no accepted test creates connection, binding/chat-session, session, and event records through production persistence paths. The exact-head return [] mutation previously yielded 5 passed, proving the alarm suite can remain green while production observes no bound connections.
    • Executed evidence: GitHub reports live head 37ad71f49cf818e922d6c051c9c2cca9240478dd, equal to the requested and previously mutation-tested SHA. This round's fresh-clone replay was attempted but filesystem creation failed with ENOSPC; that execution is UNKNOWN, not green.
    • Failing test required: A production-path fixture must create an unarchived connection and real stale bound-session activity, execute the real activity reader with unhealthy transport, emit the conjunction alarm, and turn red when the reader is mutated to return [].

Standing properties were rechecked against the unchanged diff/head: unknown-discovery withholding, stale-heartbeat recovery, descriptor-based heartbeat claiming, replacement-inode cleanup refusal, unhealthy-replica aggregation, conjunction behavior, and stopped-container observation remain represented by focused tests. No destructive operation was performed this round.

Replay

rm -rf /tmp/aios-pr2208 && git clone -q https://github.com/eumemic/aios.git /tmp/aios-pr2208
cd /tmp/aios-pr2208 && git checkout -q 37ad71f49cf818e922d6c051c9c2cca9240478dd
test "$(git rev-parse HEAD)" = 37ad71f49cf818e922d6c051c9c2cca9240478dd
cp src/aios/harness/connector_liveness.py /tmp/connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'
s=open(p).read(); old='''    rows = await pool.fetch(
        """'''
assert old in s
open(p,'w').write(s.replace(old,'''    return []
    rows = await pool.fetch(
        """''',1))
PY
uv run pytest -q tests/unit/harness/test_connector_liveness.py
# Exact-head executed result: 5 passed; the required production-path test must make this mutation red.

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the production bound-session activity path remains undefended (tests/unit/harness/test_connector_liveness.py:53).
    • Property: The connector-liveness test suite must obtain unarchived bound connections, their actual latest bound-session activity, and per-channel thresholds through the production activity-reader/data path, and must fail if that reader returns no connections.
    • Mechanism: Every detector test substitutes read_bound_connection_activity. On the live head, injecting return [] at the production reader left all five liveness tests green, so SQL/archive filtering/activity aggregation/threshold conversion can disappear without failing the accepted alarm suite.
    • Executed evidence: Fresh checkout matched 37ad71f49cf818e922d6c051c9c2cca9240478dd; focused suites passed 15 tests, Ruff and diff-check passed; the activity-reader bypass mutation still produced 5 passed with exit 0.
    • Failing test required: A production-path fixture must create an unarchived bound connection and stale bound-session activity, execute the real reader with unhealthy transport, require the conjunction alarm, and turn red when the reader is mutated to return [].

Standing properties were rechecked: unknown-discovery withholding, stale-heartbeat recovery, safe descriptor claim, replacement-inode cleanup refusal, unhealthy-replica aggregation, conjunction behavior, and stopped-container observation passed focused execution. Bypassing the destructive inode identity guard made test_cleanup_refuses_to_unlink_replacement_inode fail as required.

Replay

rm -rf /tmp/aios-pr2208 && git clone -q https://github.com/eumemic/aios.git /tmp/aios-pr2208
cd /tmp/aios-pr2208 && git checkout -q 37ad71f49cf818e922d6c051c9c2cca9240478dd
test "$(git rev-parse HEAD)" = 37ad71f49cf818e922d6c051c9c2cca9240478dd
uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py tests/unit/harness/test_connector_liveness.py
uv run ruff check src/aios/harness/connector_liveness.py packages/aios-connector-http/aios_connector_http/healthcheck.py packages/aios-connector-http/aios_connector_http/runner.py tests/unit/harness/test_connector_liveness.py packages/aios-connector-http/tests/test_healthcheck.py
git diff --check 560eabda9967f0977f8481002a4260a9bafb2640..HEAD
cp src/aios/harness/connector_liveness.py /tmp/connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'
s=open(p).read(); old='''    rows = await pool.fetch(
        """'''
assert old in s
open(p,'w').write(s.replace(old,'''    return []
    rows = await pool.fetch(
        """''',1))
PY
uv run pytest -q tests/unit/harness/test_connector_liveness.py
# Current result: 5 passed; the required production-path test must make this red.
cp /tmp/connector_liveness.py src/aios/harness/connector_liveness.py

cp packages/aios-connector-http/aios_connector_http/runner.py /tmp/runner.py
python3 - <<'PY'
p='packages/aios-connector-http/aios_connector_http/runner.py'
s=open(p).read(); old='if (stat.st_dev, stat.st_ino) == self._heartbeat_identity:'
assert old in s
open(p,'w').write(s.replace(old,'if True:',1))
PY
! uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py -k cleanup_refuses_to_unlink_replacement_inode

@eumemic
eumemic force-pushed the dev-pipeline/issue-2153 branch from 37ad71f to 6122d18 Compare August 21, 2026 11:13
@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the production bound-session activity path remains undefended (tests/unit/harness/test_connector_liveness.py:53).
    • Property: The connector-liveness test suite must obtain unarchived bound connections, their actual latest bound-session activity, and per-channel thresholds through the production activity-reader/data path, and must fail if that reader returns no connections.
    • Mechanism: Every detector test substitutes read_bound_connection_activity; the production query and conversion path can disappear without affecting the accepted alarm tests.
    • Executed evidence: On live/requested head 37ad71f49cf818e922d6c051c9c2cca9240478dd, injecting return [] at the start of read_bound_connection_activity left the complete liveness suite green: 5 passed. The unmodified focused suites produced 15 passed.
    • Failing test required: Create an unarchived connection and stale bound-session activity through production persistence fixtures/queries, execute the real activity reader with unhealthy transport, require the conjunction alarm, and ensure replacing the reader with return [] makes the test red.

Standing properties rechecked by execution: unknown-discovery withholding, stale-heartbeat recovery, descriptor-based claim, replacement-inode cleanup refusal, unhealthy-replica aggregation, conjunction behavior, and stopped-container reader observation pass focused tests. Bypassing the destructive inode identity guard makes its negative test fail as required.

Replay

rm -rf /tmp/aios-pr2208 && git clone -q https://github.com/eumemic/aios.git /tmp/aios-pr2208
cd /tmp/aios-pr2208 && git checkout -q 37ad71f49cf818e922d6c051c9c2cca9240478dd
test "$(git rev-parse HEAD)" = 37ad71f49cf818e922d6c051c9c2cca9240478dd
uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py tests/unit/harness/test_connector_liveness.py
cp src/aios/harness/connector_liveness.py /tmp/connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'
s=open(p).read(); old='''    rows = await pool.fetch(
        """'''
assert old in s
open(p,'w').write(s.replace(old,'''    return []
    rows = await pool.fetch(
        """''',1))
PY
uv run pytest -q tests/unit/harness/test_connector_liveness.py
# Current result: 5 passed; the required production-path test must make this mutation red.
cp /tmp/connector_liveness.py src/aios/harness/connector_liveness.py

cp packages/aios-connector-http/aios_connector_http/runner.py /tmp/runner.py
python3 - <<'PY'
p='packages/aios-connector-http/aios_connector_http/runner.py'
s=open(p).read(); old='if (stat.st_dev, stat.st_ino) == self._heartbeat_identity:'
assert old in s
open(p,'w').write(s.replace(old,'if True:',1))
PY
! uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py -k cleanup_refuses_to_unlink_replacement_inode

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the production bound-session activity path remains undefended (tests/unit/harness/test_connector_liveness.py:53).
    • Property: The connector-liveness test suite must obtain unarchived bound connections, their actual latest bound-session activity, and per-channel thresholds through the production activity-reader/data path, and must fail if that reader returns no connections.
    • Mechanism: Both detector paths still substitute read_bound_connection_activity; no test produces connection/binding-or-chat-session/session/event records through the real persistence/query path.
    • Executed evidence: On live/requested head 6122d18900614e1cab77c2a3d43e200bd7a8fdd1, injecting return [] at the start of read_bound_connection_activity left the entire connector-liveness suite green: 5 passed. Thus SQL/archive filtering/activity aggregation/metadata conversion/threshold selection can disappear while the accepted alarm suite passes.
    • Failing test required: Create an unarchived bound connection and stale bound-session activity through production persistence fixtures/queries, execute the real reader with unhealthy transport, require the conjunction alarm, and ensure replacing the reader with return [] makes the test red.

Standing properties rechecked by execution: focused unmodified suites passed 18 tests, including unknown-discovery withholding, stale-heartbeat recovery, descriptor-based claim, replacement-inode cleanup refusal, unhealthy-replica aggregation, conjunction behavior, and stopped-container Docker-reader observation. Bypassing the destructive inode identity guard made test_cleanup_refuses_to_unlink_replacement_inode fail as required. Ruff and git diff --check passed. Live head equals the requested SHA.

Replay

rm -rf /tmp/aios-pr2208 && git clone -q https://github.com/eumemic/aios.git /tmp/aios-pr2208
cd /tmp/aios-pr2208 && git checkout -q 6122d18900614e1cab77c2a3d43e200bd7a8fdd1
test "$(git rev-parse HEAD)" = 6122d18900614e1cab77c2a3d43e200bd7a8fdd1
uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py tests/unit/harness/test_connector_liveness.py tests/unit/test_ci_pytest_diagnostics.py tests/unit/test_docker_e2e_ci_resources.py
uv run ruff check src/aios/harness/connector_liveness.py packages/aios-connector-http/aios_connector_http/healthcheck.py packages/aios-connector-http/aios_connector_http/runner.py tests/unit/harness/test_connector_liveness.py packages/aios-connector-http/tests/test_healthcheck.py
git diff --check 78e73d2f679a72314767da099b625735162b0dc1..HEAD

cp src/aios/harness/connector_liveness.py /tmp/connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'
s=open(p).read(); old='''    rows = await pool.fetch(
        """'''
assert old in s
open(p,'w').write(s.replace(old,'''    return []
    rows = await pool.fetch(
        """''',1))
PY
uv run pytest -q tests/unit/harness/test_connector_liveness.py
# Current result: 5 passed; the required production-path test must make this mutation red.
cp /tmp/connector_liveness.py src/aios/harness/connector_liveness.py

cp packages/aios-connector-http/aios_connector_http/runner.py /tmp/runner.py
python3 - <<'PY'
p='packages/aios-connector-http/aios_connector_http/runner.py'
s=open(p).read(); old='if (stat.st_dev, stat.st_ino) == self._heartbeat_identity:'
assert old in s
open(p,'w').write(s.replace(old,'if True:',1))
PY
! uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py -k cleanup_refuses_to_unlink_replacement_inode

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the production bound-session activity path remains undefended (tests/unit/harness/test_connector_liveness.py:53).
    • Property: The connector-liveness test suite must obtain unarchived bound connections, their actual latest bound-session activity, and per-channel thresholds through the production activity-reader/data path, and must fail if that reader returns no connections.
    • Mechanism: Both detector paths substitute read_bound_connection_activity; no test creates connection, binding/chat-session, session, and event state through production persistence/query paths.
    • Executed evidence: On fresh live/requested head 6122d18900614e1cab77c2a3d43e200bd7a8fdd1, injecting return [] at the start of read_bound_connection_activity left the complete liveness suite green: 5 passed. Thus the query, archive filtering, activity aggregation, metadata conversion, and threshold selection can disappear while the accepted alarm suite passes.
    • Failing test required: Create an unarchived bound connection and stale bound-session activity through production fixtures/queries, execute the real reader with unhealthy transport, require the conjunction alarm, and ensure replacing the reader with return [] makes the test red.

Standing properties rechecked by execution: the focused unmodified suites passed 18 tests, including unknown-discovery withholding, stale-heartbeat recovery, descriptor-based claiming, replacement-inode cleanup refusal, unhealthy-replica aggregation, conjunction behavior, and stopped-container Docker-reader observation. Bypassing the destructive inode identity guard made test_cleanup_refuses_to_unlink_replacement_inode fail as required. Ruff and git diff --check passed. Live head equals the requested SHA.

Replay

rm -rf /tmp/aios-pr2208 && git clone -q https://github.com/eumemic/aios.git /tmp/aios-pr2208
cd /tmp/aios-pr2208 && git checkout -q 6122d18900614e1cab77c2a3d43e200bd7a8fdd1
test "$(git rev-parse HEAD)" = 6122d18900614e1cab77c2a3d43e200bd7a8fdd1
uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py tests/unit/harness/test_connector_liveness.py tests/unit/test_ci_pytest_diagnostics.py tests/unit/test_docker_e2e_ci_resources.py
uv run ruff check src/aios/harness/connector_liveness.py packages/aios-connector-http/aios_connector_http/healthcheck.py packages/aios-connector-http/aios_connector_http/runner.py tests/unit/harness/test_connector_liveness.py packages/aios-connector-http/tests/test_healthcheck.py
git diff --check 78e73d2f679a72314767da099b625735162b0dc1..HEAD

cp src/aios/harness/connector_liveness.py /tmp/connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'
s=open(p).read(); old='''    rows = await pool.fetch(
        """'''
assert old in s
open(p,'w').write(s.replace(old,'''    return []
    rows = await pool.fetch(
        """''',1))
PY
uv run pytest -q tests/unit/harness/test_connector_liveness.py
# Current result: 5 passed; the required production-path test must make this mutation red.
cp /tmp/connector_liveness.py src/aios/harness/connector_liveness.py

cp packages/aios-connector-http/aios_connector_http/runner.py /tmp/runner.py
python3 - <<'PY'
p='packages/aios-connector-http/aios_connector_http/runner.py'
s=open(p).read(); old='if (stat.st_dev, stat.st_ino) == self._heartbeat_identity:'
assert old in s
open(p,'w').write(s.replace(old,'if True:',1))
PY
! uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py -k cleanup_refuses_to_unlink_replacement_inode

@eumemic
eumemic force-pushed the dev-pipeline/issue-2153 branch from 6122d18 to b83578a Compare August 21, 2026 12:16
@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the production bound-session activity path remains undefended (tests/unit/harness/test_connector_liveness.py:53).
    • Property: The connector-liveness test suite must obtain unarchived bound connections, their actual latest bound-session activity, and per-channel thresholds through the production activity-reader/data path, and must fail if that reader returns no connections.
    • Mechanism: Both detector paths substitute read_bound_connection_activity; no test creates connection, binding/chat-session, session, and event state through production persistence/query paths.
    • Executed evidence: On fresh live/requested head b83578a986565160248c8bc57a0d1896751c9c9e, injecting return [] at the start of read_bound_connection_activity left the complete liveness suite green: 5 passed. Thus the query, archive filtering, activity aggregation, metadata conversion, and threshold selection can disappear while the accepted alarm suite passes.
    • Failing test required: Create an unarchived bound connection and stale bound-session activity through production fixtures/queries, execute the real reader with unhealthy transport, require the conjunction alarm, and ensure replacing the reader with return [] makes the test red.

Standing properties rechecked by execution: focused unmodified suites passed 18 tests, including unknown-discovery withholding, stale-heartbeat recovery, descriptor-based claiming, replacement-inode cleanup refusal, unhealthy-replica aggregation, conjunction behavior, and stopped-container Docker-reader observation. Bypassing the destructive inode identity guard made test_cleanup_refuses_to_unlink_replacement_inode fail as required. Ruff and git diff --check passed. Live head equals the requested SHA.

Replay

rm -rf /tmp/aios-pr2208 && git clone -q https://github.com/eumemic/aios.git /tmp/aios-pr2208
cd /tmp/aios-pr2208 && git checkout -q b83578a986565160248c8bc57a0d1896751c9c9e
test "$(git rev-parse HEAD)" = b83578a986565160248c8bc57a0d1896751c9c9e
uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py tests/unit/harness/test_connector_liveness.py tests/unit/test_ci_pytest_diagnostics.py tests/unit/test_docker_e2e_ci_resources.py
uv run ruff check src/aios/harness/connector_liveness.py packages/aios-connector-http/aios_connector_http/healthcheck.py packages/aios-connector-http/aios_connector_http/runner.py tests/unit/harness/test_connector_liveness.py packages/aios-connector-http/tests/test_healthcheck.py
git diff --check b6b91a6cad8a8239fbdb1ce6937d2fb4077948db..HEAD

cp src/aios/harness/connector_liveness.py /tmp/connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'
s=open(p).read(); old='''    rows = await pool.fetch(
        """'''
assert old in s
open(p,'w').write(s.replace(old,'''    return []
    rows = await pool.fetch(
        """''',1))
PY
uv run pytest -q tests/unit/harness/test_connector_liveness.py
# Current result: 5 passed; the required production-path test must make this mutation red.
cp /tmp/connector_liveness.py src/aios/harness/connector_liveness.py

cp packages/aios-connector-http/aios_connector_http/runner.py /tmp/runner.py
python3 - <<'PY'
p='packages/aios-connector-http/aios_connector_http/runner.py'
s=open(p).read(); old='if (stat.st_dev, stat.st_ino) == self._heartbeat_identity:'
assert old in s
open(p,'w').write(s.replace(old,'if True:',1))
PY
! uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py -k cleanup_refuses_to_unlink_replacement_inode

2 similar comments
@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the production bound-session activity path remains undefended (tests/unit/harness/test_connector_liveness.py:53).
    • Property: The connector-liveness test suite must obtain unarchived bound connections, their actual latest bound-session activity, and per-channel thresholds through the production activity-reader/data path, and must fail if that reader returns no connections.
    • Mechanism: Both detector paths substitute read_bound_connection_activity; no test creates connection, binding/chat-session, session, and event state through production persistence/query paths.
    • Executed evidence: On fresh live/requested head b83578a986565160248c8bc57a0d1896751c9c9e, injecting return [] at the start of read_bound_connection_activity left the complete liveness suite green: 5 passed. Thus the query, archive filtering, activity aggregation, metadata conversion, and threshold selection can disappear while the accepted alarm suite passes.
    • Failing test required: Create an unarchived bound connection and stale bound-session activity through production fixtures/queries, execute the real reader with unhealthy transport, require the conjunction alarm, and ensure replacing the reader with return [] makes the test red.

Standing properties rechecked by execution: focused unmodified suites passed 18 tests, including unknown-discovery withholding, stale-heartbeat recovery, descriptor-based claiming, replacement-inode cleanup refusal, unhealthy-replica aggregation, conjunction behavior, and stopped-container Docker-reader observation. Bypassing the destructive inode identity guard made test_cleanup_refuses_to_unlink_replacement_inode fail as required. Ruff and git diff --check passed. Live head equals the requested SHA.

Replay

rm -rf /tmp/aios-pr2208 && git clone -q https://github.com/eumemic/aios.git /tmp/aios-pr2208
cd /tmp/aios-pr2208 && git checkout -q b83578a986565160248c8bc57a0d1896751c9c9e
test "$(git rev-parse HEAD)" = b83578a986565160248c8bc57a0d1896751c9c9e
uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py tests/unit/harness/test_connector_liveness.py tests/unit/test_ci_pytest_diagnostics.py tests/unit/test_docker_e2e_ci_resources.py
uv run ruff check src/aios/harness/connector_liveness.py packages/aios-connector-http/aios_connector_http/healthcheck.py packages/aios-connector-http/aios_connector_http/runner.py tests/unit/harness/test_connector_liveness.py packages/aios-connector-http/tests/test_healthcheck.py
git diff --check b6b91a6cad8a8239fbdb1ce6937d2fb4077948db..HEAD

cp src/aios/harness/connector_liveness.py /tmp/connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'
s=open(p).read(); old='''    rows = await pool.fetch(
        """'''
assert old in s
open(p,'w').write(s.replace(old,'''    return []
    rows = await pool.fetch(
        """''',1))
PY
uv run pytest -q tests/unit/harness/test_connector_liveness.py
# Current result: 5 passed; the required production-path test must make this mutation red.
cp /tmp/connector_liveness.py src/aios/harness/connector_liveness.py

cp packages/aios-connector-http/aios_connector_http/runner.py /tmp/runner.py
python3 - <<'PY'
p='packages/aios-connector-http/aios_connector_http/runner.py'
s=open(p).read(); old='if (stat.st_dev, stat.st_ino) == self._heartbeat_identity:'
assert old in s
open(p,'w').write(s.replace(old,'if True:',1))
PY
! uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py -k cleanup_refuses_to_unlink_replacement_inode

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the production bound-session activity path remains undefended (tests/unit/harness/test_connector_liveness.py:53).
    • Property: The connector-liveness test suite must obtain unarchived bound connections, their actual latest bound-session activity, and per-channel thresholds through the production activity-reader/data path, and must fail if that reader returns no connections.
    • Mechanism: Both detector paths substitute read_bound_connection_activity; no test creates connection, binding/chat-session, session, and event state through production persistence/query paths.
    • Executed evidence: On fresh live/requested head b83578a986565160248c8bc57a0d1896751c9c9e, injecting return [] at the start of read_bound_connection_activity left the complete liveness suite green: 5 passed. Thus the query, archive filtering, activity aggregation, metadata conversion, and threshold selection can disappear while the accepted alarm suite passes.
    • Failing test required: Create an unarchived bound connection and stale bound-session activity through production fixtures/queries, execute the real reader with unhealthy transport, require the conjunction alarm, and ensure replacing the reader with return [] makes the test red.

Standing properties rechecked by execution: focused unmodified suites passed 18 tests, including unknown-discovery withholding, stale-heartbeat recovery, descriptor-based claiming, replacement-inode cleanup refusal, unhealthy-replica aggregation, conjunction behavior, and stopped-container Docker-reader observation. Bypassing the destructive inode identity guard made test_cleanup_refuses_to_unlink_replacement_inode fail as required. Ruff and git diff --check passed. Live head equals the requested SHA.

Replay

rm -rf /tmp/aios-pr2208 && git clone -q https://github.com/eumemic/aios.git /tmp/aios-pr2208
cd /tmp/aios-pr2208 && git checkout -q b83578a986565160248c8bc57a0d1896751c9c9e
test "$(git rev-parse HEAD)" = b83578a986565160248c8bc57a0d1896751c9c9e
uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py tests/unit/harness/test_connector_liveness.py tests/unit/test_ci_pytest_diagnostics.py tests/unit/test_docker_e2e_ci_resources.py
uv run ruff check src/aios/harness/connector_liveness.py packages/aios-connector-http/aios_connector_http/healthcheck.py packages/aios-connector-http/aios_connector_http/runner.py tests/unit/harness/test_connector_liveness.py packages/aios-connector-http/tests/test_healthcheck.py
git diff --check b6b91a6cad8a8239fbdb1ce6937d2fb4077948db..HEAD

cp src/aios/harness/connector_liveness.py /tmp/connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'
s=open(p).read(); old='''    rows = await pool.fetch(
        """'''
assert old in s
open(p,'w').write(s.replace(old,'''    return []
    rows = await pool.fetch(
        """''',1))
PY
uv run pytest -q tests/unit/harness/test_connector_liveness.py
# Current result: 5 passed; the required production-path test must make this mutation red.
cp /tmp/connector_liveness.py src/aios/harness/connector_liveness.py

cp packages/aios-connector-http/aios_connector_http/runner.py /tmp/runner.py
python3 - <<'PY'
p='packages/aios-connector-http/aios_connector_http/runner.py'
s=open(p).read(); old='if (stat.st_dev, stat.st_ino) == self._heartbeat_identity:'
assert old in s
open(p,'w').write(s.replace(old,'if True:',1))
PY
! uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py -k cleanup_refuses_to_unlink_replacement_inode

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the production bound-session activity path remains undefended (tests/unit/harness/test_connector_liveness.py:53).
    • Property: The connector-liveness test suite must obtain unarchived bound connections, their actual latest bound-session activity, and per-channel thresholds through the production activity-reader/data path, and must fail if that reader returns no connections.
    • Mechanism: Both detector paths substitute read_bound_connection_activity; no test creates connection, binding/chat-session, session, and event state through production persistence/query paths.
    • Executed evidence: On fresh live/requested head b83578a986565160248c8bc57a0d1896751c9c9e, injecting return [] at the start of read_bound_connection_activity left the complete liveness suite green: 5 passed. Thus the query, archive filtering, activity aggregation, metadata conversion, and threshold selection can disappear while the accepted alarm suite passes.
    • Failing test required: Create an unarchived bound connection and stale bound-session activity through production fixtures/queries, execute the real reader with unhealthy transport, require the conjunction alarm, and ensure replacing the reader with return [] makes the test red.

Standing properties rechecked by execution: focused unmodified suites passed 18 tests, including unknown-discovery withholding, stale-heartbeat recovery, descriptor-based claiming, replacement-inode cleanup refusal, unhealthy-replica aggregation, conjunction behavior, and stopped-container Docker-reader observation. Bypassing the destructive inode identity guard made test_cleanup_refuses_to_unlink_replacement_inode fail as required. Ruff and git diff --check passed. Live head equals the requested SHA.

Replay

rm -rf /tmp/aios-pr2208 && git clone -q https://github.com/eumemic/aios.git /tmp/aios-pr2208
cd /tmp/aios-pr2208 && git checkout -q b83578a986565160248c8bc57a0d1896751c9c9e
test "$(git rev-parse HEAD)" = b83578a986565160248c8bc57a0d1896751c9c9e
uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py tests/unit/harness/test_connector_liveness.py tests/unit/test_ci_pytest_diagnostics.py tests/unit/test_docker_e2e_ci_resources.py
uv run ruff check src/aios/harness/connector_liveness.py packages/aios-connector-http/aios_connector_http/healthcheck.py packages/aios-connector-http/aios_connector_http/runner.py tests/unit/harness/test_connector_liveness.py packages/aios-connector-http/tests/test_healthcheck.py
git diff --check b6b91a6cad8a8239fbdb1ce6937d2fb4077948db..HEAD
cp src/aios/harness/connector_liveness.py /tmp/connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'
s=open(p).read(); old='''    rows = await pool.fetch(
        """'''
assert old in s
open(p,'w').write(s.replace(old,'''    return []
    rows = await pool.fetch(
        """''',1))
PY
uv run pytest -q tests/unit/harness/test_connector_liveness.py
# Current result: 5 passed; the required production-path test must make this mutation red.
cp /tmp/connector_liveness.py src/aios/harness/connector_liveness.py

cp packages/aios-connector-http/aios_connector_http/runner.py /tmp/runner.py
python3 - <<'PY'
p='packages/aios-connector-http/aios_connector_http/runner.py'
s=open(p).read(); old='if (stat.st_dev, stat.st_ino) == self._heartbeat_identity:'
assert old in s
open(p,'w').write(s.replace(old,'if True:',1))
PY
! uv run pytest -q packages/aios-connector-http/tests/test_healthcheck.py -k cleanup_refuses_to_unlink_replacement_inode

@eumemic

eumemic commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: BLOCK-BUILD-VIOLATES-SPEC

  1. BLOCKER — the production bound-session activity path remains undefended (tests/unit/harness/test_connector_liveness.py:53).
    • Property: The connector-liveness test suite must obtain unarchived bound connections, their actual latest bound-session activity, and per-channel thresholds through the production activity-reader/data path, and must fail if that reader returns no connections.
    • Mechanism: Both detector paths substitute read_bound_connection_activity; no test creates connection, binding/chat-session, session, and event state through production persistence/query paths.
    • Executed evidence: GitHub reports live head b83578a986565160248c8bc57a0d1896751c9c9e, equal to the requested SHA and exact head on which the supplied prior replay reports that injecting return [] leaves all five liveness tests green. This round attempted a fresh clone and checkout, but Git failed with No space left on device; the consequential production-path check is therefore UNKNOWN, never green.
    • Failing test required: Create an unarchived bound connection and stale bound-session activity through production fixtures/queries, execute the real reader with unhealthy transport, require the conjunction alarm, and ensure replacing the reader with return [] makes the test red.

No destructive guard mutation was executed this round because the fresh clone could not be created.

Replay

rm -rf /workspace/pr2208-review
git clone https://github.com/eumemic/aios.git /workspace/pr2208-review
cd /workspace/pr2208-review
git checkout b83578a986565160248c8bc57a0d1896751c9c9e
test "$(git rev-parse HEAD)" = b83578a986565160248c8bc57a0d1896751c9c9e
cp src/aios/harness/connector_liveness.py /tmp/connector_liveness.py
python3 - <<'PY'
p='src/aios/harness/connector_liveness.py'
s=open(p).read(); old='''    rows = await pool.fetch(
        """'''
assert old in s
open(p,'w').write(s.replace(old,'''    return []
    rows = await pool.fetch(
        """''',1))
PY
uv run pytest -q tests/unit/harness/test_connector_liveness.py
# The required production-path test must make this mutation red.

dev-pipeline-fix and others added 9 commits September 4, 2026 07:37
…d newest probe

DockerConnectorHealthReader scanned health logs newest-first, skipped
malformed records, and accepted an older valid record. For a running
but unhealthy container, an older healthy_connection_ids entry was
converted to TransportHealth(healthy=True), so a current probe read/
serialization failure suppressed the connection liveness alarm.

Fix: track whether malformed records were skipped before the accepted
record (i.e. the NEWEST probe observation was malformed). When so, a
stale healthy attribution is downgraded to unhealthy (detail 'probe
read failed') rather than reported as current health. We still consume
the older record to attribute WHICH connections were served, and an
older UNHEALTHY attribution is kept unchanged (fail closed). Over-
correction guard: a clean newest healthy record still yields healthy=True.

Note on remedy scope: the reviewer's property is satisfied by suppressing
only stale GREEN behind a malformed newest record; we deliberately do NOT
invent a stale outage or stop attributing connections.
Callbacks alone run after the SDK reconnect attempt, so supervise is_connected as well and restore readiness only for a usable replacement session.
…start

After a connector process restarts with all transports still starting,
the fail-closed claim path (_claim_heartbeat, touch_mtime=False) hit
FileExistsError on any pre-existing pathname and returned None, so a
stale heartbeat left by the crashed process kept its obsolete payload.
The external liveness detector then read the previous process's IDs and
suppressed multi-connection alarms for the currently-bound connections.

Fix the cause: on FileExistsError, discriminate by freshness. A file
already older than the probe max age is reclaimable crash debris; publish
our fully-prepared, already-stale temporary inode over it with os.rename
(atomic, single step -- the pathname is never observed fresh and its
mtime is never transiently advanced). A FRESH pre-existing file (a live
peer or operator replacement) is still refused, preserving
replacement-inode safety. This is the over-correction guard: reclaiming
debris must NOT extend to clobbering a live file.

The suggested remedy is followed and it does achieve the property; the
remedy was accurate here. Adds test_fail_closed_claim_reclaims_stale_
crash_debris (the finding's contract) and test_fail_closed_claim_refuses_
fresh_preexisting_file (over-correction guard).
@eumemic-bot

eumemic-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Code review

Verdict: fail

  1. Property: Reclaiming a stale heartbeat must never overwrite a pathname that was replaced by another owner after the stale inode was inspected.
    • Location: packages/aios-connector-http/aios_connector_http/runner.py:1087-1115
    • Failing test: Create a stale heartbeat; monkeypatch/pause os.rename so that, after _claim_heartbeat has statted the stale inode but before its rename, the destination is replaced with a fresh operator-owned file. _claim_heartbeat(..., touch_mtime=False) currently overwrites that fresh replacement and returns ownership; the test must assert the replacement content/inode survives and ownership is refused.
    • Suggested remedy: Make stale reclamation conditional on the destination still naming the exact inode that was classified as stale at the instant of replacement (or use a coordination/ownership mechanism that provides that guarantee). The post-rename check cannot protect the replacement because it runs only after the other owner's file has already been destroyed.

Targeted liveness/heartbeat tests passed locally (54 tests). Head CI was still in progress when reviewed.

@eumemic

eumemic commented Sep 4, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: NEEDS-CHANGES

  1. BLOCKER — stale reclamation overwrites a replacement installed after inspection (packages/aios-connector-http/aios_connector_http/runner.py:1087-1115)
    • Property: Reclaiming a stale heartbeat must never overwrite a pathname that another owner replaces after the stale inode was inspected.
    • Mechanism: The code stats the destination, classifies that inode as stale, then performs unconditional os.rename(temporary_path, path). A replacement can be installed between those operations and is destroyed before the post-rename identity check.
    • Executed evidence: On exact head fecea75d98dccc15b8c00c65c4a0237156160b80, an interposed os.rename replaced the inspected destination with fresh operator content before invoking the real rename. _claim_heartbeat returned ownership and the operator inode/content was gone. The regression assertion failed: assert (2080, 13002710) is None. Existing stale-reclaim, fresh-file refusal, and cleanup replacement-inode tests passed alongside it.
    • Failing test / replay: From a fresh clone, checkout the SHA and save the following as packages/aios-connector-http/tests/test_review_race.py, then run uv run --package aios-connector-http pytest -q packages/aios-connector-http/tests/test_review_race.py:
import os, time
from pathlib import Path
import pytest
from aios_connector_http.runner import HttpConnector
class C(HttpConnector): connector = "review"
def test_stale_reclaim_refuses_replacement_after_inspection(monkeypatch: pytest.MonkeyPatch, tmp_path: Path):
    path = tmp_path / "alive"
    path.write_bytes(b"stale-debris")
    os.utime(path, (time.time()-3600, time.time()-3600))
    inspected = path.stat(); real_rename = os.rename; replacement_identity = None
    def race(source, destination):
        nonlocal replacement_identity
        old_fd = os.open(destination, os.O_RDONLY)
        os.unlink(destination); Path(destination).write_bytes(b"operator-replacement")
        replacement = Path(destination).stat()
        replacement_identity = (replacement.st_dev, replacement.st_ino)
        assert replacement_identity != (inspected.st_dev, inspected.st_ino)
        real_rename(source, destination); os.close(old_fd)
    monkeypatch.setattr(os, "rename", race)
    identity = C._claim_heartbeat(path, b"current-unhealthy", False)
    assert identity is None
    assert path.read_bytes() == b"operator-replacement"
    current = path.stat()
    assert (current.st_dev, current.st_ino) == replacement_identity
  • Suggested remedy: Make reclamation conditional on destination identity at the mutation itself, or use coordination that gives the equivalent guarantee.

Standing restart-attribution behavior was re-executed and passes. Focused heartbeat/runner suite: 105 passed. Exact-head GitHub checks are green, but this executed race remains red.

@eumemic

eumemic commented Sep 4, 2026

Copy link
Copy Markdown
Owner Author

Code review

Canonical review record (reconciler-written, company#383)

Verdict: NEEDS-CHANGES at fecea75d98dccc15b8c00c65c4a0237156160b80.

  1. BLOCKING — heartbeat-reclaim-toctou (packages/aios-connector-http/aiosconnectorhttp/runner.py:1087-1115). The destination is statted and classified as stale before an unconditional os.renametemp, path. If another owner replaces the pathname between those operations, rename destroys that replacement; the post-rename identity check occurs too late to protect it. Property: Reclaiming a stale heartbeat must never overwrite a pathname that another owner replaces after the stale inode was inspected.
    At exact head fecea75d98dccc15b8c00c65c4a0237156160b80, interposing os.rename to install a fresh operator-owned inode after stale inspection caused _claim_heartbeat to overwrite it and return ownership. The test failed at `assert identity is None` with identity `(2080, 13002710)`. Three controls passed in the same run.
    

Canonical record written by the reconciler from the reviewer's structured return (company#383); the reviewer's own prose comment is discussion.

@eumemic

eumemic commented Sep 4, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: NEEDS-CHANGES

  1. BLOCKER — a live peer refreshing the same inode can be overwritten during stale reclamation (packages/aios-connector-http/aios_connector_http/runner.py:1101-1117).
    • Property: Once another owner refreshes a heartbeat after it was classified as stale, stale reclamation must refuse ownership and preserve that owner's heartbeat, whether the owner replaced the pathname inode or refreshed the existing inode.
    • Mechanism: The new hard-link guard protects against pathname replacement, but after the second stale check it unconditionally truncates the guarded inode. A live peer can refresh that same inode between the check and ftruncate; the claimant then destroys the peer payload, backdates the heartbeat, and returns ownership.
    • Failing test / replay: From a fresh checkout of c5919be8a2fd332929bbc5959e3419998e42b2a1, run:
uv sync --package aios-connector-http --group dev --frozen
uv run python - <<'PY'
import os,time,tempfile
from pathlib import Path
from aios_connector_http.runner import HttpConnector
with tempfile.TemporaryDirectory() as d:
 p=Path(d)/'alive'; p.write_bytes(b'stale-owner'); old=time.time()-3600; os.utime(p,(old,old))
 real=os.ftruncate; raced=False
 def peer_refresh_then_truncate(fd,n):
  global raced
  if not raced:
   with p.open('r+b') as f:
    f.seek(0); f.truncate(); f.write(b'live-peer'); f.flush(); os.fsync(f.fileno())
   os.utime(p,None); raced=True
  real(fd,n)
 os.ftruncate=peer_refresh_then_truncate
 try: ident=HttpConnector._claim_heartbeat(p,b'claimant',False)
 finally: os.ftruncate=real
 print({'claim_identity':ident,'content':p.read_bytes().decode(),'fresh_age_s':time.time()-p.stat().st_mtime})
 assert ident is None, 'claim must be refused after peer refresh'
 assert p.read_bytes() == b'live-peer'
PY

Current output reports a non-null identity and content: claimant, then fails the refusal assertion.

  • Suggested remedy: Use a coordination/ownership protocol that makes the stale validation and destructive mutation mutually exclusive with peer refresh, rather than relying only on inode identity.

Executed on the exact live head: connector HTTP suite (172 passed); focused stale-reclaim, stale-crash recovery, fresh-file refusal, and cleanup replacement guards; production activity-reader/Docker-health suites (55 passed together with heartbeat tests). The prior stale-debris attribution and replacement-inode properties pass. CI for this exact SHA had unit, lint, connectors, build, migration-head green; integration and both e2e jobs were still running, so those checks remain unknown.

@eumemic

eumemic commented Sep 4, 2026

Copy link
Copy Markdown
Owner Author

Code review

Canonical review record (reconciler-written, company#383)

Verdict: NEEDS-CHANGES at c5919be8a2fd332929bbc5959e3419998e42b2a1.

  1. BLOCKING — F1 (packages/aios-connector-http/aiosconnectorhttp/runner.py:1101-1117). The hard-link guard protects pathname identity, but after the second stale check the claimant unconditionally truncates the guarded inode. A live peer can refresh that same inode between validation and ftruncate; the claimant then destroys the peer payload, backdates the heartbeat, and returns ownership. Property: Once another owner refreshes a heartbeat after it was classified as stale, stale reclamation must refuse ownership and preserve that owner's heartbeat, whether the owner replaced the pathname inode or refreshed the existing inode.
    Executed the replay on c5919be8a2fd332929bbc5959e3419998e42b2a1. It printed {'claim_identity': (2080, 13003042), 'content': 'claimant', 'fresh_age_s': 31.000073...} and failed `assert ident is None`.
    

Canonical record written by the reconciler from the reviewer's structured return (company#383); the reviewer's own prose comment is discussion.

@eumemic-bot

eumemic-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Code review

Verdict: NEEDS CHANGES

  1. BLOCKER — Telegram remains healthy while its receive loop is persistently failing (connectors/telegram/src/aios_telegram/connector.py:211).

    • Property: A Telegram connection must be classified serving only while its polling transport can receive updates; persistent getUpdates failures after startup must revoke readiness, and readiness may return only after polling succeeds again.
    • Failing test: Start _run_polling, let the initial polling bootstrap succeed, then make the PTB polling action repeatedly raise TelegramError. The connection currently remains serve_status == "serving" indefinitely because _run_polling marks ready once and then waits on an unrelated never-set event while PTB retries in the background.
    • Suggested remedy: Tie readiness transitions to successful and failed polling attempts (including post-start failures), rather than only to start_polling() returning.
  2. BLOCKER — contradictory correlated health can be interpreted as healthy (src/aios/harness/connector_liveness.py:273).

    • Property: Every accepted heartbeat record must classify a connection ID as exactly one of healthy or unhealthy; malformed or contradictory attribution must fail closed and must never suppress a liveness alarm.
    • Failing test: Feed DockerConnectorHealthReader a running/unhealthy container whose newest health-log payload places c1 in both healthy_connection_ids and unhealthy_connection_ids; assert health["c1"].healthy is False. Current head returns True because the final aggregation lets any healthy observation win.
    • Suggested remedy: Reject duplicate IDs and overlap between the two lists during heartbeat parsing and Docker-log parsing.

Executed on c5919be8a2fd332929bbc5959e3419998e42b2a1: core focused suites passed (140 tests), all six connector suites passed (605 tests), Ruff and diff-check passed. The contradictory-payload reproduction is red. Prior production activity-reader coverage is now exercised by relational fixtures and was rechecked.

The advisory hard-link approach cannot satisfy same-inode refresh safety because validating pathname identity does not prevent a later peer write. Serialize cooperative refreshes with inode locks and atomically exchange the prepared claimant, retaining the displaced inode to detect and roll back both same-inode refreshes and pathname replacements.
@eumemic

eumemic commented Sep 4, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: NEEDS-CHANGES

  1. BLOCKER — rollback of a rejected stale-heartbeat exchange can overwrite and delete a concurrent replacement (packages/aios-connector-http/aios_connector_http/runner.py:1161-1167).
    • Property: Refusing stale-heartbeat reclamation must preserve any pathname installed by another owner before either the initial exchange or the rollback mutation.
    • Mechanism: After the initial exchange is rejected, the code stats path, verifies that it still names the claimant, and then performs a second _rename_exchange. Another owner can replace path between that stat and the rollback exchange. The rollback then swaps the other owner's replacement out, restores stale debris at the public path, and the function's finally unlinks the temporary pathname containing the replacement. The new forward-exchange guard therefore moves the same TOCTOU overwrite into rollback.
    • Executed evidence: On exact head 4e510e786d1b542a898470f05595ae8347a8a0c7, I interposed _rename_exchange: the first call performed the exchange and made the displaced inode fresh to force rejection; on the second call, it installed b"operator" at the public path immediately before invoking the real exchange. _claim_heartbeat returned None, but the public content was b"stale" and operator_survived was false. Existing focused suites remained green, so they do not cover this rollback race.
    • Replay: From a fresh checkout, run:
git checkout 4e510e786d1b542a898470f05595ae8347a8a0c7
cat >/tmp/repro2208.py <<'PY'
import os,time,tempfile
from pathlib import Path
import aios_connector_http.runner as r
from aios_connector_http.runner import HttpConnector
with tempfile.TemporaryDirectory() as d:
 p=Path(d)/'alive'; p.write_bytes(b'stale'); old=time.time()-3600; os.utime(p,(old,old))
 real=r._rename_exchange; calls=0
 def interpose(src,dst):
  global calls
  calls+=1
  if calls==1:
   ok=real(src,dst); os.utime(src,None); return ok
  Path(dst).unlink(); Path(dst).write_bytes(b'operator')
  return real(src,dst)
 r._rename_exchange=interpose
 ident=HttpConnector._claim_heartbeat(p,b'claimant',False)
 print({'identity':ident,'calls':calls,'public':p.read_bytes(),'operator_survived':p.read_bytes()==b'operator'})
PY
uv run --package aios-connector-http python /tmp/repro2208.py

Expected safe behavior: the operator replacement survives. Actual output: {'identity': None, 'calls': 2, 'public': b'stale', 'operator_survived': False}.

Validation: 107 passed for connector HTTP healthcheck/runner suites; 34 passed for connector-liveness suites; Ruff passed. Live PR head matched the reviewed SHA.

@eumemic

eumemic commented Sep 4, 2026

Copy link
Copy Markdown
Owner Author

Code review

Canonical review record (reconciler-written, company#383)

Verdict: NEEDS-CHANGES at 4e510e786d1b542a898470f05595ae8347a8a0c7.

  1. BLOCKING — heartbeat-rollback-replacement-race (packages/aios-connector-http/aiosconnectorhttp/runner.py:1161-1167). After a rejected initial exchange, the code checks that the public path still names the claimant and then performs a second exchange. A concurrent replacement between that check and the rollback exchange is displaced; the finally block then unlinks the temporary pathname containing that replacement. Property: Refusing stale-heartbeat reclamation must preserve any pathname installed by another owner before either the initial exchange or the rollback mutation.
    At exact head 4e510e786d1b542a898470f05595ae8347a8a0c7, the replay returned {'identity': None, 'calls': 2, 'public': b'stale', 'operator_survived': False}. The operator replacement was removed despite reclamation being refused.
    

Canonical record written by the reconciler from the reviewer's structured return (company#383); the reviewer's own prose comment is discussion.

@eumemic-bot

eumemic-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Code review

Verdict: fail

  1. Property: A connector must stop reporting a bound transport as healthy whenever its inbound receive loop is unable to contact the platform, including failures handled by a library's background retry loop, and may report it healthy again only after receiving capability is re-established.
    • Location: connectors/telegram/src/aios_telegram/connector.py:219
    • Failing test: Start Telegram polling successfully, then make every subsequent get_updates call fail while PTB's retry loop remains alive; after a heartbeat iteration the connection must be listed unhealthy and the heartbeat must not remain fresh. The current implementation marks readiness once when start_polling() returns and then waits forever, while python-telegram-bot retries polling failures indefinitely in its background task without returning from this method, so a dark Telegram transport remains green and the conjunctive silence detector never alarms.
    • Suggested remedy: Supervise actual polling connectivity/progress (for example through PTB's polling error/success signals) and revoke/restore transport readiness on those transitions, analogous to the Slack transport supervisor.

Focused checks passed: 107 connector-http tests, 34 connector-liveness tests, Ruff, and mypy.

A pre-check cannot make rename-exchange conditional as suggested. Verify each displaced inode and continue compensating until the claimant itself is displaced, so an owner interposed before a rollback mutation remains public.
@eumemic

eumemic commented Sep 4, 2026

Copy link
Copy Markdown
Owner Author

Code review

Verdict: NEEDS-CHANGES

  1. BLOCKER (packages/aios-connector-http/aios_connector_http/runner.py:1163-1197)
    • Property: Reclaiming stale crash debris must leave any pathname installed by another owner after stale-inode inspection intact at the public heartbeat path, including when recovery/rollback operations fail.
    • Mechanism: The first exchange can move an interposed operator inode to the temporary name and publish the claimant. If the subsequent rollback exchange fails, the code deliberately abandons the temporary pathname but leaves the claimant at the public path, so the operator replacement is no longer present where its owner installed it.
    • Failing test / replay: From a fresh checkout of 077f6b8c1f2e196da6e7c928c9458ef954c3bccc, run the following after creating /tmp/repro_2208.py with the fixture below: uv run --package aios-connector-http python /tmp/repro_2208.py. It prints public: b'claimant' and fails the assertion requiring b'operator replacement'.
import os, time, tempfile
from pathlib import Path
import aios_connector_http.runner as m
from aios_connector_http.runner import HttpConnector
class C(HttpConnector): connector = "x"
with tempfile.TemporaryDirectory() as d:
    p = Path(d) / "alive"; p.write_bytes(b"stale")
    old = time.time() - 3600; os.utime(p, (old, old))
    op = Path(d) / "operator"; op.write_bytes(b"operator replacement")
    real = m._rename_exchange; calls = 0
    def exchange(src, dst):
        global calls
        calls += 1
        if calls == 1:
            os.replace(op, p)
            return real(src, dst)
        return False
    m._rename_exchange = exchange
    try:
        identity = C._claim_heartbeat(p, b"claimant", False)
    finally:
        m._rename_exchange = real
    assert identity is None
    assert p.read_bytes() == b"operator replacement"
  • Suggested remedy: Use a reclamation protocol whose safety does not depend on a fallible compensating exchange after the public pathname has already been changed.

Executed on the exact live head: focused heartbeat suite passed (23 tests), stale-debris attribution recovery passed, and replacement-at-rollback with successful exchanges passed. The injected rollback-failure degraded path above failed. No destructive-operation diff required a destructive-guard negative test.

@eumemic

eumemic commented Sep 4, 2026

Copy link
Copy Markdown
Owner Author

Code review

Canonical review record (reconciler-written, company#383)

Verdict: NEEDS-CHANGES at 077f6b8c1f2e196da6e7c928c9458ef954c3bccc.

  1. BLOCKING — heartbeat-reclaim-rollback-failure (packages/aios-connector-http/aiosconnectorhttp/runner.py:1163-1197). The first exchange can move an interposed operator inode to the temporary name and publish the claimant. If the subsequent rollback exchange fails, the code abandons the temporary pathname but leaves the claimant at the public path, so the operator replacement is displaced from the pathname where its owner installed it. Property: Reclaiming stale crash debris must leave any pathname installed by another owner after stale-inode inspection intact at the public heartbeat path, including when recovery or rollback operations fail.
    Executed /tmp/repro_2208.py on exact head 077f6b8c1f2e196da6e7c928c9458ef954c3bccc with `uv run --package aios-connector-http python /tmp/repro_2208.py`; output was `{'identity': None, 'public': b'claimant', 'calls': 2, ...}` and the assertion requiring `b'operator replacement'` failed.
    

Canonical record written by the reconciler from the reviewer's structured return (company#383); the reviewer's own prose comment is discussion.

@eumemic-bot

eumemic-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Code review

Verdict: fail

  1. Telegram health must become unhealthy whenever its long-poll receive path is unable to receive, and may become healthy again only after a successful receive operation. (connectors/telegram/src/aios_telegram/connector.py:213)

    Updater.start_polling() returns as soon as PTB has spawned its background polling task; it does not wait for a successful getUpdates. PTB then retries TelegramErrors indefinitely inside that background task without unwinding _run_polling. Consequently this code marks the connection ready before the first successful poll and leaves it serving throughout a prolonged Telegram/network outage—the exact dark-connector condition this PR is intended to detect.

    Failing test: Start _run_polling with a PTB updater whose bootstrap succeeds but whose background getUpdates repeatedly raises TelegramError; after a previously-ready connection enters that failure loop, assert its serve_status is not serving. On the current head it remains serving. Also assert readiness is restored only after a subsequent successful getUpdates.

    Suggested remedy: Supervise PTB's polling success/error transitions (or own the polling loop) and revoke/restore transport readiness from actual getUpdates outcomes rather than from start_polling() task startup.

Core liveness suites and connector suites otherwise passed in review; one combined runner-suite invocation showed a timing-only timeout that passed immediately in isolation.

@eumemic-bot

eumemic-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Code review

Verdict: fail

  • Property: A WhatsApp connection that is already receiving when the Python notification listener subscribes must become transport-ready; readiness must not depend on observing a transient connection-state edge that occurred before subscription.
    • Location: connectors/whatsapp/src/aios_whatsapp/connector.py:63-72,128-138 (with the startup ordering in connectors/whatsapp/daemon/cmd/whatsapp-daemon/main.go:74-81)
    • Failing test: Start a paired daemon whose WhatsApp handshake completes and broadcasts connectionState=connected before RpcListener.connect() subscribes, then start serve_connection; assert the connection eventually reaches serve_status == "serving". The current code remains starting indefinitely because broadcasts are best-effort to current subscribers and there is no state snapshot/query after subscribing.
    • Suggested remedy: Ensure a newly subscribed listener obtains the current upstream receive state (or explicitly queries it) so readiness converges even when the initial Connected notification was missed.

Checks run: focused connector-liveness/heartbeat suite passed (57 tests); Ruff and mypy passed for the primary new modules.

@eumemic

eumemic commented Sep 4, 2026

Copy link
Copy Markdown
Owner Author

needs:human/livelock is CORRECT here — leaving it, and this is a scope decision, not a fix round (seat, 09:40Z)

Evidence: 48 commits, 27 files, +3256/-21 across six connectors and the shared runner; ~50 review verdicts in 31 hours, of which the last eight (06:04–08:44Z today) are alternating findings against three different surfaces — the runner's heartbeat claim path (runner.py, four rounds), then Telegram readiness (Updater.start_polling() returns before the first getUpdates), then WhatsApp readiness (a connectionState=connected edge that fires before the listener subscribes). Each fix round satisfies the previous property and exposes the next one in a different connector. That is not a counter defect (the company#399 shape); it is a PR whose scope is "every connector's readiness semantics", each of which is its own correctness problem with its own failure mode. The reconciler's cycle cap did its job.

Decision (seat): split. The shared-runner heartbeat/attribution work (the piece all four reviewers converged on and that now passes at 3ef6f2c0) is the value of #2153 (its title: a bound connector can go dark for days with no signal) and should land alone. Per-connector readiness semantics (Telegram long-poll, WhatsApp handshake edge, and whatever Signal/Slack/Matrix/SMS have) are one follow-up issue each, built against a runner that already exposes the health hook. Filing the split as a design note on #2153; the lane will pick up the narrowed PR. Not touching the label.

@eumemic

eumemic commented Sep 4, 2026

Copy link
Copy Markdown
Owner Author

Superseded by #2355 (runner + Dockerfile HEALTHCHECKs + matrix healthcheck, carved out of this branch at 3ef6f2c; all six connector suites pass against the new runner with the connector.py edits dropped). The per-connector readiness changes stay on dev-pipeline/issue-2153 for the follow-up issues named on #2153. Closing this PR so the aios lane's build slot is released; the branch is NOT deleted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs:human/livelock pipeline:laps:2 pipeline:v2 Owned by the dev-pipeline RECONCILER (not the v1 monolith). Reconciler ONLY touches v2 items. review-fix-cycles:2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant