S175 Closure Verify Report
S175 Closure Verify Report
Date: 2026-04-09 Mode: READ-ONLY Agent: Claude Code Goal: Verify S175 fix is permanent and complete
Result: PARTIAL PASS
4 of 5 verify points fully PASS. C3 found 1 BYPASS path (reconcile-knowledge.py) — risk MEDIUM, no immediate impact since not on automated trigger.
C1 — Code fix in runtime image: PASS
Evidence
Container vs source file checksum match:
docker exec incomex-agent-data md5sum /app/agent_data/directus_sync.py
→ f6eb710a67e2f9eb393886a1db30a9a6 /app/agent_data/directus_sync.py
md5sum /opt/incomex/docker/agent-data-repo/agent_data/directus_sync.py
→ f6eb710a67e2f9eb393886a1db30a9a6 /opt/incomex/docker/.../directus_sync.py
_db_conn() in runtime container has commit:
@contextmanager
def _db_conn():
conn = psycopg2.connect(_db_dsn())
conn.autocommit = False
try:
yield conn
conn.commit() # ← S175 P3 fix present
except Exception:
conn.rollback()
raise
finally:
conn.close()
Image ID matches build:
docker inspect incomex-agent-data --format '{{.Image}}'
→ sha256:bfe092449032e23ee9ad091f5a327e11b29f4b5d9757aa9c40cace5a588dd5b7
docker images agent-data-local:latest --format '{{.ID}}'
→ bfe092449032
Runtime image = built image. Code change deployed correctly.
C2 — Schema constraint complete: PASS
Index definition
SELECT indexdef FROM pg_indexes WHERE indexname = 'idx_kd_current_source_id_unique';
CREATE UNIQUE INDEX idx_kd_current_source_id_unique
ON public.knowledge_documents USING btree (source_id)
WHERE ((is_current_version = true) AND (source_id IS NOT NULL))
Predicate exactly: is_current_version=true AND source_id IS NOT NULL ✓
Reject test (in transaction, rolled back)
BEGIN;
INSERT INTO knowledge_documents (..., source_id) VALUES (...,
'agentdata:knowledge/current-state/reports/agent-data-connectivity-check-gpt-2026-03-31.md');
ROLLBACK;
Output:
BEGIN
ROLLBACK
ERROR: duplicate key value violates unique constraint "idx_kd_current_source_id_unique"
DETAIL: Key (source_id)=(agentdata:...) already exists.
PG correctly rejects. Constraint working.
C3 — Bypass writer paths: PARTIAL — 1 BYPASS FOUND
Search
grep -rn 'INSERT INTO knowledge_documents\|UPDATE knowledge_documents' /opt/incomex/docker/agent-data-repo/
→ (no direct SQL writes outside _sync_document_atomic)
grep -rn 'items/knowledge_documents' /opt/incomex/docker/agent-data-repo/
→ /scripts/reconcile-knowledge.py:71 GET (read only — OK)
/scripts/reconcile-knowledge.py:149 POST (CREATE — bypass)
/scripts/reconcile-knowledge.py:171 PATCH (UPDATE — bypass)
/scripts/test-agent-connections.sh:142 POST (test — low risk)
/webhook_config.json:23 (webhook config — read only)
BYPASS #1: reconcile-knowledge.py
File: /opt/incomex/docker/agent-data-repo/scripts/reconcile-knowledge.py
Lines 149 (POST), 171 (PATCH): Direct REST API writes to Directus, bypassing the atomic writer.
Code path:
def create_directus_doc(token, doc_id, content, metadata):
payload = {
"title": title, "slug": slug, "file_path": doc_id,
"source_id": f"agentdata:{doc_id}", ...
"version_group_id": str(uuid.uuid4()),
}
api("POST", f"{DIRECTUS}/items/knowledge_documents", payload, ...)
Risk: This script does its own slug/version_group_id generation and POST to Directus REST API. It does NOT:
- Lock by source_id (no
pg_advisory_xact_lock) - Run in a single PG transaction
- Mark old current rows as
is_current_version=falsebefore inserting new
However, the partial UNIQUE constraint idx_kd_current_source_id_unique (S175 P2) WILL reject any attempt to create a duplicate current row. So the schema serves as last-line defense.
Impact assessment:
- Not on cron/automated trigger (manual run only)
- Schema constraint prevents data corruption
- Could fail with cryptic error if run today (would hit UNIQUE violation on existing rows)
- Risk: MEDIUM — flag for cleanup but no immediate corruption
BYPASS #2: test-agent-connections.sh line 142
curl -X POST "$OPS_URL/items/knowledge_documents" -d '{"test":1}'
This is a test/probe script. Risk LOW (one-off, not in production cron).
Webhook config
webhook_config.json line 23 is config-only, declaring a webhook target. Not a write path.
C4 — 2-worker listener registration: PASS (with metric caveat)
Container exec
docker inspect incomex-agent-data --format '{{.Path}} {{join .Args " "}}'
→ bash -lc uvicorn agent_data.server:app --host 0.0.0.0 --port ${PORT:-8080} --workers 2
2 workers confirmed.
EventBus singleton pattern (per process)
File event_system.py:
# Line 424
_event_bus: EventBus | None = None
# Line 427-432
def get_event_bus() -> EventBus:
global _event_bus
if _event_bus is None:
_event_bus = _build_event_bus()
return _event_bus
# Line 466-468
from agent_data.directus_sync import directus_sync_listener
bus.add_listener(directus_sync_listener)
Each uvicorn worker = separate Python process = separate _event_bus singleton.
Both workers register directus_sync_listener independently.
events_logged sampling (5x)
events: 3 listeners: 1
events: 3 listeners: 1
events: 3 listeners: 1
events: 1 listeners: 1 ← worker B
events: 3 listeners: 1
Interpretation: events_logged is per-worker counter. Most /health calls hit worker A (count=3), one hit worker B (count=1). This is a metric inconsistency, NOT a functional bug.
Functional impact: NONE. Each request is handled end-to-end by 1 worker:
- PUT /documents → routed to worker (e.g., A)
- Worker A's listener fires → calls atomic writer → writes Directus PG
- Worker B doesn't need to know — DB is the SSOT
Caveat for operators: events_logged from /health is misleading; should be aggregated across workers for accurate metric. Out of S175 scope.
C5 — Backfill & smoke test integrity: PASS
NULL source_id count
SELECT COUNT(*), array_agg(id) FROM knowledge_documents
WHERE is_current_version=true AND source_id IS NULL;
→ count=3, ids={298,299,301}
3 NULLs remaining = exactly the 3 README dup NULLs deferred to followup. ✓
Spot check 3 backfilled rows (random)
id | file_path | source_id | pattern_ok
-----+--------------------------------------------------------------+------------------------------------------------------------------------+------------
302 | knowledge/current-tasks/task-list.md | agentdata:knowledge/current-tasks/task-list.md | t
980 | knowledge/current-state/reports/s155-p1c-close-loop-report | agentdata:knowledge/current-state/reports/s155-p1c-close-loop-report | t
983 | knowledge/current-state/reports/s150-p0-investigation-report | agentdata:knowledge/current-state/reports/s150-p0-investigation-report | t
All 3 follow exact pattern agentdata:<file_path>. ✓
Smoke test doc 964 still consistent
id=964 | version_number=3 | date_updated=2026-04-09 09:28:14.72428
length(content)=1356 | is_current_version=t
Matches end state from VIỆC 4 (version=3 after restore, original content). ✓
Overall Verdict: PARTIAL PASS — 4/5 fully clean, 1 bypass flagged
| Check | Status | Notes |
|---|---|---|
| C1 Code fix in runtime | PASS | md5 match, image ID match |
| C2 Schema constraint | PASS | Index correct, INSERT rejected |
| C3 No bypass | PARTIAL | reconcile-knowledge.py is BYPASS (MEDIUM risk) |
| C4 Worker listeners | PASS | Both register, metric caveat |
| C5 Backfill integrity | PASS | 3 NULLs as planned, spot check OK |
Risks Still Open
-
reconcile-knowledge.pybypass — Script can be invoked manually, would create duplicates if not for the partial UNIQUE constraint catching it. Recommended: refactor to call atomic writer or document as deprecated. -
3 README NULL rows — Already in followup
s175-readme-duplicates-followup.md. -
Move endpoint deprecated (S170) — Cross-path renames are 2-step (upload + delete), no atomicity. Out of S175 scope.
-
Worker metric inconsistency —
events_loggedper-worker. Cosmetic. Out of S175 scope.
Unknowns / Need clarification
None. All 5 checks have evidence.