Files
ss-tools/scripts/semantic_gate_validation.py

114 lines
6.5 KiB
Python

# #region Tooling.SemanticGateValidation [C:3] [TYPE Module] [SEMANTICS semantic,provenance,validation]
# @defgroup SemanticGateValidation Validate the reviewed configuration and complete same-process audit evidence.
# @RELATION CALLED_BY -> [Tooling.SemanticParseGate.Module]
import hashlib
import json
from pathlib import Path
# #region Tooling.SemanticGateValidation.Baseline [C:1] [TYPE Block]
# @BRIEF Reviewed coordinates from audit-roundtrip.json; no attestation exists for other configurations.
BASELINE_HASH = '8528079168045348670'
BASELINE_SHA = '642b5b05e810f9d3a0c413b61d1a7f975c247aff48db83ff896be067b5ec55c3'
# #endregion Tooling.SemanticGateValidation.Baseline
# #region Tooling.SemanticGateValidation.Require [C:1] [TYPE Function]
# @BRIEF Reject unavailable or contradictory protocol evidence.
def require(condition, message):
if not condition:
raise RuntimeError(message)
# #endregion Tooling.SemanticGateValidation.Require
# #region Tooling.SemanticGateValidation.Config [C:2] [TYPE Function]
# @BRIEF Require an explicit exact semantic pin and unchanged reviewed YAML bytes.
# @REJECTED A nonzero hash alone cannot prove effective configuration because the server falls back on invalid YAML.
def verify_config(workspace, expected):
require(expected == BASELINE_HASH, '[NEED_CONTEXT: trusted effective-config identity; supply reviewed --expected-config-hash]')
raw = (Path(workspace) / '.axiom/axiom_config.yaml').read_bytes()
require(hashlib.sha256(raw).hexdigest() == BASELINE_SHA,
'[NEED_CONTEXT: reviewed raw configuration SHA256]')
# #endregion Tooling.SemanticGateValidation.Config
# #region Tooling.SemanticGateValidation.Decode [C:3] [TYPE Function]
# @BRIEF Reject failed MCP envelopes and decode raw JSON without losing Rust u64 precision.
def decode_tool(result):
require(isinstance(result, dict), 'tool response must be an object')
require(result.get('isError', False) is False, 'MCP tool error')
content = result.get('content')
require(isinstance(content, list) and len(content) == 1, 'expected one JSON content block')
block = content[0]
require(isinstance(block, dict) and block.get('type') == 'text', 'expected text content')
payload = json.loads(block.get('text', ''))
require(isinstance(payload, dict) and bool(payload), 'missing object payload')
if 'structuredContent' in result:
require(result['structuredContent'] == payload, 'contradictory structured and raw tool payloads')
require(payload.get('success') is True, 'tool success must be true')
return payload
# #endregion Tooling.SemanticGateValidation.Decode
# #region Tooling.SemanticGateValidation.Rebuild [C:3] [TYPE Function]
# @BRIEF Require an explicitly completed full rebuild for the requested workspace.
def validate_rebuild(result, workspace):
require(isinstance(result, dict) and result.get('success') is True, 'rebuild failed')
require(result.get('effective_rebuild_mode') == 'full', 'full rebuild required')
generation = result.get('index_generation_id')
require(isinstance(generation, str) and bool(generation), 'missing rebuild generation')
provenance = result.get('provenance', {})
require(provenance.get('index_generation_id') == generation, 'rebuild generation mismatch')
require(provenance.get('requested_rebuild_mode') == 'full', 'requested rebuild mode mismatch')
require(provenance.get('effective_rebuild_mode') == 'full', 'effective rebuild mode mismatch')
require(isinstance(provenance.get('completed_at'), str) and bool(provenance['completed_at']), 'rebuild incomplete')
require(result.get('semantic_index_rebuild_result', {}).get('status') == 'success', 'rebuild not completed')
require(result.get('workspace_policy', {}).get('workspace_root') == workspace, 'foreign rebuild workspace')
# #endregion Tooling.SemanticGateValidation.Rebuild
# #region Tooling.SemanticGateValidation.Counter [C:1] [TYPE Function]
# @BRIEF Counts are nonnegative integers, never booleans, strings or floats.
def counter(value):
require(type(value) is int and value >= 0, 'invalid nonnegative integer counter')
return value
# #endregion Tooling.SemanticGateValidation.Counter
# #region Tooling.SemanticGateValidation.Pagination [C:3] [TYPE Function]
# @BRIEF Verify a complete severity aggregate and coherent first-page warning metadata.
def validate_counts(audit):
severity = audit.get('severity_breakdown')
require(isinstance(severity, dict), 'missing severity breakdown')
for code, count in severity.items():
require(isinstance(code, str) and bool(code), 'invalid warning code')
counter(count)
page = audit.get('pagination', {})
total = counter(page.get('total_warnings'))
returned = counter(page.get('returned'))
require(counter(page.get('offset')) == 0 and counter(page.get('limit')) == 1, 'unexpected pagination')
require(total == sum(severity.values()), 'severity total mismatch')
require(returned == min(total, 1), 'returned count mismatch')
require(type(page.get('has_more')) is bool and page['has_more'] == (total > returned), 'has_more mismatch')
require(isinstance(audit.get('warnings'), list) and len(audit['warnings']) == returned, 'warnings page mismatch')
# #endregion Tooling.SemanticGateValidation.Pagination
# #region Tooling.SemanticGateValidation.Audit [C:3] [TYPE Function]
# @BRIEF Refuse missing scope, unknown config and generation drift before interpreting sparse warning codes.
def validate_audit(audit, rebuild, expected):
require(isinstance(audit, dict) and audit.get('success') is True, 'audit failed')
scope = audit.get('applied_scope', {})
require(scope.get('mode') == 'workspace' and scope.get('file_path') is None, 'filtered audit unavailable')
require(scope.get('target_scope') == 'workspace', 'foreign audit scope')
provenance = audit.get('index_provenance', {})
require(provenance.get('source') == 'memory', 'unknown audit source')
require(provenance.get('index_generation_id') == rebuild['index_generation_id'], 'audit generation mismatch')
config = provenance.get('config_hash')
require(type(config) is int and 0 < config < 2**64, 'unknown exact config hash')
require(str(config) == expected, 'foreign config hash')
require(provenance.get('contract_count') == rebuild.get('contract_count'), 'contract count mismatch')
require(provenance.get('edge_count') == rebuild.get('edge_count'), 'edge count mismatch')
validate_counts(audit)
# #endregion Tooling.SemanticGateValidation.Audit
# #endregion Tooling.SemanticGateValidation