feat(ai): verify canonical learning writeback
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m42s
CD Pipeline / build-and-deploy (push) Successful in 6m29s
CD Pipeline / post-deploy-checks (push) Successful in 1m48s
AI 技術雷達監控 / ai-technology-watch (push) Successful in 45s
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 1s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Successful in 50s
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m42s
CD Pipeline / build-and-deploy (push) Successful in 6m29s
CD Pipeline / post-deploy-checks (push) Successful in 1m48s
AI 技術雷達監控 / ai-technology-watch (push) Successful in 45s
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 1s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Successful in 50s
This commit is contained in:
@@ -1316,6 +1316,129 @@ def test_independent_post_verifier_requires_same_run_and_deployed_source() -> No
|
||||
]
|
||||
|
||||
|
||||
def test_canonical_learning_requires_row_readback_and_deployed_source() -> None:
|
||||
run_id = "11111111-1111-4111-8111-111111111111"
|
||||
apply_op_id = "33333333-3333-4333-8333-333333333333"
|
||||
catalog_id = "ansible:188-momo-backup-user"
|
||||
canonical_playbook_id = "PB-ANSIBLE-188-MOMO-BACKUP-USER"
|
||||
playbook_path = "infra/ansible/playbooks/188-momo-backup-user.yml"
|
||||
km_detail = {
|
||||
"schema_version": "ansible_km_writeback_v1",
|
||||
"knowledge_entry_id": "km-p0-004",
|
||||
"canonical_playbook_id": canonical_playbook_id,
|
||||
"catalog_id": catalog_id,
|
||||
"km_row_version": "2026-07-11T02:00:00+00:00",
|
||||
"repository_write_acknowledged": True,
|
||||
"repository_readback_verified": True,
|
||||
"durable_write_acknowledged": True,
|
||||
"writer_source_sha": "source123",
|
||||
"raw_log_payload_stored": False,
|
||||
"secret_value_stored": False,
|
||||
}
|
||||
trust_detail = {
|
||||
"schema_version": "ansible_playbook_trust_writeback_v2",
|
||||
"identity_schema_version": "ansible_playbook_identity_v1",
|
||||
"identity_fingerprint": "a" * 64,
|
||||
"canonical_playbook_id": canonical_playbook_id,
|
||||
"catalog_id": catalog_id,
|
||||
"playbook_path": playbook_path,
|
||||
"playbook_row_version": 2,
|
||||
"playbook_row_updated_at": "2026-07-11T02:00:00+00:00",
|
||||
"playbook_row_fingerprint": "b" * 64,
|
||||
"trust_observation_count": 13,
|
||||
"learning_recorded": True,
|
||||
"trust_updated": True,
|
||||
"repository_write_acknowledged": True,
|
||||
"repository_readback_verified": True,
|
||||
"operation_receipt_readback_verified": True,
|
||||
"durable_write_acknowledged": True,
|
||||
"writer_source_sha": "source123",
|
||||
"raw_log_payload_stored": False,
|
||||
"secret_value_stored": False,
|
||||
}
|
||||
runtime = runtime_control_module._build_canonical_learning_runtime_readback(
|
||||
operation_latest_rows=[
|
||||
{
|
||||
"op_id": "learning-p0-004",
|
||||
"operation_type": "ansible_learning_writeback_recorded",
|
||||
"status": "success",
|
||||
"parent_op_id": apply_op_id,
|
||||
"automation_run_id": run_id,
|
||||
}
|
||||
],
|
||||
loop_ledger={
|
||||
"automation_run_id": run_id,
|
||||
"apply_op_id": apply_op_id,
|
||||
"catalog_id": catalog_id,
|
||||
"playbook_path": playbook_path,
|
||||
"same_run_stage_receipts": [
|
||||
{
|
||||
"stage_id": "km_playbook_writeback",
|
||||
"detail": km_detail,
|
||||
},
|
||||
{"stage_id": "playbook_trust", "detail": trust_detail},
|
||||
],
|
||||
},
|
||||
)
|
||||
assert runtime["runtime_evidence_ready"] is True
|
||||
assert all(runtime["controls"].values())
|
||||
|
||||
payload = {
|
||||
"strict_runtime_completion": {
|
||||
"automation_run_id": run_id,
|
||||
"closed": True,
|
||||
},
|
||||
"rollups": {},
|
||||
}
|
||||
source_controls = {
|
||||
"canonical_playbook_resolver_complete": True,
|
||||
"km_row_readback_required": True,
|
||||
"playbook_row_readback_required": True,
|
||||
"learning_failure_fail_closed": True,
|
||||
"trust_failure_fail_closed": True,
|
||||
"learning_receipts_public_safe": True,
|
||||
}
|
||||
runtime_control_module._attach_canonical_learning_readback(
|
||||
payload,
|
||||
readback={"canonical_learning_runtime": runtime},
|
||||
boundary_readback={
|
||||
"deployed_source_sha": "source123",
|
||||
"canonical_learning_source_boundary": {
|
||||
"receipt_ref": "configmap:awoooi-prod/boundary",
|
||||
"verifier": "cd_tests_and_production_source_sha_v1",
|
||||
"controls": source_controls,
|
||||
"active_blockers": [],
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
learning = payload["autonomous_canonical_learning_writeback"]
|
||||
assert learning["closed"] is True
|
||||
assert learning["active_blockers"] == []
|
||||
assert learning["controls"]["learning_receipts_public_safe"] is True
|
||||
assert learning["controls"]["source_learning_receipts_public_safe"] is True
|
||||
assert payload["rollups"][
|
||||
"autonomous_canonical_learning_writeback_closed_count"
|
||||
] == 1
|
||||
|
||||
runtime_control_module._attach_canonical_learning_readback(
|
||||
payload,
|
||||
readback={"canonical_learning_runtime": runtime},
|
||||
boundary_readback={
|
||||
"deployed_source_sha": "different-source",
|
||||
"canonical_learning_source_boundary": {
|
||||
"controls": source_controls,
|
||||
"active_blockers": [],
|
||||
},
|
||||
},
|
||||
)
|
||||
learning = payload["autonomous_canonical_learning_writeback"]
|
||||
assert learning["closed"] is False
|
||||
assert "writer_source_sha_matches_deployment_not_verified" in learning[
|
||||
"active_blockers"
|
||||
]
|
||||
|
||||
|
||||
def test_ai_agent_autonomous_runtime_control_uses_current_owner_directive():
|
||||
data = build_ai_agent_autonomous_runtime_control()
|
||||
|
||||
@@ -2103,16 +2226,53 @@ def test_strict_learning_receipts_require_terminal_proof():
|
||||
"chunk_index_verified": True,
|
||||
},
|
||||
}) is False
|
||||
assert _runtime_stage_receipt_has_required_proof({
|
||||
"stage_id": "km_playbook_writeback",
|
||||
"detail": {
|
||||
"schema_version": "ansible_km_writeback_v1",
|
||||
"knowledge_entry_id": "km-entry-1",
|
||||
"canonical_playbook_id": "PB-ANSIBLE-188-AI-WEB",
|
||||
"km_row_version": "2026-07-11T02:00:00+00:00",
|
||||
"repository_write_acknowledged": True,
|
||||
"repository_readback_verified": True,
|
||||
"durable_write_acknowledged": True,
|
||||
"writer_source_sha": "source123",
|
||||
"raw_log_payload_stored": False,
|
||||
"secret_value_stored": False,
|
||||
},
|
||||
}) is True
|
||||
assert _runtime_stage_receipt_has_required_proof({
|
||||
"stage_id": "playbook_trust",
|
||||
"detail": {
|
||||
"schema_version": "ansible_playbook_trust_writeback_v2",
|
||||
"identity_schema_version": "ansible_playbook_identity_v1",
|
||||
"identity_fingerprint": "a" * 64,
|
||||
"durable_write_acknowledged": True,
|
||||
"canonical_playbook_id": "PB-ANSIBLE-188-AI-WEB",
|
||||
"playbook_row_version": 2,
|
||||
"playbook_row_updated_at": "2026-07-11T02:00:00+00:00",
|
||||
"playbook_row_fingerprint": "b" * 64,
|
||||
"trust_score": 0.37,
|
||||
"trust_observation_count": 1,
|
||||
"learning_recorded": True,
|
||||
"trust_updated": True,
|
||||
"repository_write_acknowledged": True,
|
||||
"repository_readback_verified": True,
|
||||
"operation_receipt_readback_verified": True,
|
||||
"writer_source_sha": "source123",
|
||||
"raw_log_payload_stored": False,
|
||||
"secret_value_stored": False,
|
||||
},
|
||||
}) is True
|
||||
assert _runtime_stage_receipt_has_required_proof({
|
||||
"stage_id": "playbook_trust",
|
||||
"detail": {
|
||||
"schema_version": "ansible_playbook_trust_writeback_v1",
|
||||
"durable_write_acknowledged": True,
|
||||
"canonical_playbook_id": "PB-ANSIBLE-188-AI-WEB",
|
||||
"trust_score": 0.37,
|
||||
"success_count": 1,
|
||||
"failure_count": 0,
|
||||
},
|
||||
}) is True
|
||||
}) is False
|
||||
|
||||
|
||||
def test_strict_runtime_completion_rejects_cross_run_receipt_mix():
|
||||
|
||||
Reference in New Issue
Block a user