fix(agent): persist no-write learning receipts
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 1m19s
CD Pipeline / build-and-deploy (push) Successful in 9m4s
CD Pipeline / post-deploy-checks (push) Successful in 2m0s

This commit is contained in:
ogt
2026-07-14 15:18:56 +08:00
parent 623e9aa578
commit e53bbc94e8
4 changed files with 49 additions and 8 deletions

View File

@@ -3264,7 +3264,7 @@ jobs:
}
echo "executor_boundary_stage=live_socket_boundary_verified"
read_workload_db_identity() {
read_workload_db_identity_once() {
workload="$1"
container="$2"
representative_probe_count="$3"
@@ -3412,6 +3412,23 @@ jobs:
asyncio.run(main())
PY
}
read_workload_db_identity() {
workload="$1"
attempt=1
while [ "$attempt" -le 3 ]; do
if identity_output=$(read_workload_db_identity_once "$@"); then
printf '%s\n' "$identity_output"
return 0
fi
echo "workload_db_identity_exec_retry=$attempt/3;workload=$workload" >&2
if [ "$attempt" -lt 3 ]; then
sleep $((attempt * 3))
fi
attempt=$((attempt + 1))
done
echo "workload_db_identity_exec_exhausted=3;workload=$workload" >&2
return 1
}
json_field() {
field="$1"
python3 -c \

View File

@@ -153,6 +153,16 @@ _ENUM_FALLBACKS = {
}
def _knowledge_enum_db_label(value):
"""Match the mixed-case labels in the deployed PostgreSQL enums."""
if isinstance(value, EntryStatus) and value is EntryStatus.PUBLISHED:
return value.value
if isinstance(value, EntryType | EntrySource | EntryStatus):
return value.name
return value
def _enum_member(value, enum_cls):
if value is None:
return _ENUM_FALLBACKS.get(enum_cls)
@@ -287,11 +297,11 @@ class KnowledgeDBRepository:
values = {
"title": data.title,
"content": data.content,
"entry_type": data.entry_type.value if hasattr(data.entry_type, "value") else data.entry_type,
"entry_type": _knowledge_enum_db_label(data.entry_type),
"category": data.category,
"tags": data.tags,
"source": data.source.value if hasattr(data.source, "value") else data.source,
"status": data.status.value if hasattr(data.status, "value") else data.status,
"source": _knowledge_enum_db_label(data.source),
"status": _knowledge_enum_db_label(data.status),
"related_incident_id": data.related_incident_id,
"related_playbook_id": data.related_playbook_id,
"related_approval_id": data.related_approval_id,
@@ -313,7 +323,7 @@ class KnowledgeDBRepository:
"title": data.title,
"content": data.content,
"tags": data.tags,
"status": data.status.value if hasattr(data.status, "value") else data.status,
"status": _knowledge_enum_db_label(data.status),
"related_approval_id": data.related_approval_id,
},
)
@@ -339,12 +349,12 @@ class KnowledgeDBRepository:
record = KnowledgeEntryRecord(
title=data.title,
content=data.content,
entry_type=data.entry_type,
entry_type=_knowledge_enum_db_label(data.entry_type),
category=data.category,
tags=data.tags,
source=data.source,
source=_knowledge_enum_db_label(data.source),
# 2026-04-04 ogt: Phase 25 P1 — 支援指定 statusANTI_PATTERN 直接 PUBLISHED
status=data.status,
status=_knowledge_enum_db_label(data.status),
related_incident_id=data.related_incident_id,
related_playbook_id=data.related_playbook_id,
related_approval_id=data.related_approval_id,

View File

@@ -12,6 +12,7 @@ from src.repositories.knowledge_repository import (
_ASSET_TAXONOMY_KEYS,
KnowledgeDBRepository,
_enum_text,
_knowledge_enum_db_label,
)
@@ -263,3 +264,12 @@ def test_enum_text_helper_casts_status_to_lowercase_text() -> None:
assert "lower(cast(knowledge_entries.status as varchar))" in compiled
assert "archived" in compiled
def test_knowledge_enum_db_labels_match_deployed_postgresql_contract() -> None:
assert _knowledge_enum_db_label(EntryType.INCIDENT_CASE) == "INCIDENT_CASE"
assert _knowledge_enum_db_label(EntryType.ANTI_PATTERN) == "ANTI_PATTERN"
assert _knowledge_enum_db_label(EntrySource.AI_EXTRACTED) == "AI_EXTRACTED"
assert _knowledge_enum_db_label(EntrySource.HUMAN) == "HUMAN"
assert _knowledge_enum_db_label(EntryStatus.DRAFT) == "DRAFT"
assert _knowledge_enum_db_label(EntryStatus.PUBLISHED) == "published"

View File

@@ -264,6 +264,10 @@ def test_cd_prunes_and_verifies_api_executor_boundary_in_production() -> None:
assert "read_workload_db_identity awoooi-api api 1 8" in workflow
assert "read_workload_db_identity awoooi-worker worker 1 5" in workflow
assert "awoooi-ansible-executor-broker broker 1 2" in workflow
assert "read_workload_db_identity_once" in workflow
assert 'while [ "$attempt" -le 3 ]' in workflow
assert "workload_db_identity_exec_retry=$attempt/3" in workflow
assert "workload_db_identity_exec_exhausted=3" in workflow
assert "AWOOOI_DB_REPRESENTATIVE_PROBE_COUNT" in workflow
assert "AWOOOI_DB_REQUIRED_CONNECTION_BUDGET" in workflow
assert "api_http_concurrency_probe_passed" in workflow