A request to polish a service description should not quietly turn a $250 offer into a $25 offer. If an AI coding workflow edits structured business data, a valid JSON file is only the first check. You also need to see what changed against the owner’s trusted baseline.
This build produces a small read-only review report: added and removed services, changed labels, prices and active flags, plus hashes identifying the exact two files examined. It never applies a change. The operator gets a concrete diff instead of a vague “looks good.”
Fictional example: Nova Workshop and both service offers below are authored sample data. No model generated or edited these files. The candidate intentionally includes one copy edit and one unintended price change so the review behavior can be exercised. Dollar amounts in this example are USD; the deliberately narrow schema represents one currency only.
Syntax can pass while the business change is wrong
Both 25000 and 2500 are valid integer values. A structural validator cannot decide whether the owner authorized changing the price. Compare the approved baseline to the proposed file, identify every changed field and require a separate decision before any system uses the candidate.
This complements validating AI output structure. It addresses a different question: what changed from the known business state? It does not prove either file is truthful or that an unchanged price is correct.
The example’s before-and-after picture
| Field | Trusted baseline | Proposed candidate | Report |
|---|---|---|---|
| site-check.label | Website check | Website health check | Review copy change |
| workflow-map.price_cents | 25000 ($250) | 2500 ($25) | Review price change |
The table is an explanatory visual derived from the actual fixtures, not an AI-generated screenshot. The featured cover is conceptual artwork.
Build a deliberately small read-only reviewer
Prerequisite: Python 3.14.3 was used for the executed example on Windows. The implementation uses the standard library only; no package installation, API key or model call is needed. Put the following files in a disposable folder while learning the workflow.
Python’s JSON documentation describes decoding hooks and cautions about untrusted input size. We bound each file to 100,000 bytes and reject duplicate keys and non-finite numbers. The pinned CPython 3.14.3 decoder implementation supplies the corresponding hooks. These limits are a narrow input policy, not a general parser sandbox.
Save as review_catalog.py:
"""Read-only semantic review of a small, trusted baseline and proposed catalog."""
import argparse
import hashlib
import json
from pathlib import Path
MAX_BYTES = 100_000
FIELDS = {'id', 'label', 'price_cents', 'active'}
def unique_object(pairs):
result = {}
for key, value in pairs:
if key in result:
raise ValueError('Duplicate JSON key: ' + key)
result[key] = value
return result
def reject_constant(value):
raise ValueError('Non-finite JSON number: ' + value)
def load_catalog(path):
# Read only a bounded input, including one byte to detect overflow.
with Path(path).open('rb') as stream:
raw = stream.read(MAX_BYTES + 1)
if len(raw) > MAX_BYTES:
raise ValueError('Catalog exceeds input limit')
data = json.loads(raw.decode('utf-8'), object_pairs_hook=unique_object,
parse_constant=reject_constant)
if type(data) is not list or not 1 <= len(data) <= 100:
raise ValueError('Expected 1 to 100 service records')
records = {}
for row in data:
if type(row) is not dict or set(row) != FIELDS:
raise ValueError('Unexpected service fields')
identity = row['id']
if type(identity) is not str or not identity or len(identity) > 64:
raise ValueError('Invalid service ID')
if identity in records:
raise ValueError('Duplicate service ID')
if type(row['label']) is not str or not row['label'].strip() or len(row['label']) > 200:
raise ValueError('Invalid service label')
if type(row['price_cents']) is not int or not 0 <= row['price_cents'] <= 10_000_000:
raise ValueError('Expected bounded integer cents')
if type(row['active']) is not bool:
raise ValueError('Expected Boolean active flag')
records[identity] = row
return records, hashlib.sha256(raw).hexdigest()
def review(baseline_path, candidate_path):
baseline, before_hash = load_catalog(baseline_path)
candidate, after_hash = load_catalog(candidate_path)
changes = []
for identity in sorted(baseline.keys() | candidate.keys()):
if identity not in baseline:
changes.append({'id': identity, 'change': 'added', 'after': candidate[identity]})
elif identity not in candidate:
changes.append({'id': identity, 'change': 'removed', 'before': baseline[identity]})
else:
for field in sorted(FIELDS - {'id'}):
if baseline[identity][field] != candidate[identity][field]:
changes.append({'id': identity, 'change': 'field', 'field': field,
'before': baseline[identity][field], 'after': candidate[identity][field]})
return {'status': 'review_required' if changes else 'no_semantic_change',
'baseline_sha256': before_hash, 'candidate_sha256': after_hash,
'changes': changes, 'applied': False}
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('baseline', type=Path)
parser.add_argument('candidate', type=Path)
args = parser.parse_args()
print(json.dumps(review(args.baseline, args.candidate), indent=2, ensure_ascii=False))
Each record has exactly four fields. Prices use integer cents, Boolean values cannot masquerade as integer prices, IDs must be unique and the catalog must contain 1–100 records. Unknown fields are refused: extending the schema is an explicit engineering change, not something a proposed edit can silently introduce.
The review aligns services by stable ID rather than list position. Reordering services or object keys does not create a semantic change. Changing an ID appears as a removal and an addition; the tool does not guess that two differently identified services are the same.
Run the fictional price-list edit
Save the trusted fixture as baseline.json:
[
{"id": "site-check", "label": "Website check", "price_cents": 15000, "active": true},
{"id": "workflow-map", "label": "Workflow map", "price_cents": 25000, "active": true}
]
Save the proposed fixture as candidate.json:
[
{"id": "site-check", "label": "Website health check", "price_cents": 15000, "active": true},
{"id": "workflow-map", "label": "Workflow map", "price_cents": 2500, "active": true}
]
From that folder, run:
python -X utf8 review_catalog.py baseline.json candidate.json
The executed command returned:
{
"status": "review_required",
"baseline_sha256": "f857cbe9597c6f02651b163c1e3db5734c969772320d823f050843b7d63f6f2f",
"candidate_sha256": "cbb12d0445ada91f7890f197a7e96d40ca53b2b60cef8c7628882b09f298c81b",
"changes": [
{
"id": "site-check",
"change": "field",
"field": "label",
"before": "Website check",
"after": "Website health check"
},
{
"id": "workflow-map",
"change": "field",
"field": "price_cents",
"before": 25000,
"after": 2500
}
],
"applied": false
}
The label and price changes are both listed, and applied remains false. There is no hidden “safe copy edit” auto-approval rule: a label can contain an unsupported promise or affect an integration too.
The SHA-256 fields identify the raw bytes read, using Python’s hashlib interface. Whitespace changes can alter those hashes without changing the semantic report. A hash here is not a signature, proof of approval, or protection against someone replacing both files and the report.
Test the claims rather than trusting the example
Save this as test_catalog.py beside the module:
import json
from pathlib import Path
import tempfile
import unittest
from review_catalog import MAX_BYTES, load_catalog, review
class CatalogTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.addCleanup(self.temp.cleanup)
self.p = Path(self.temp.name)
self.rows = [{'id':'service-a','label':'Fictional service','price_cents':10000,'active':True}]
def write(self, name, rows):
p = self.p/name
p.write_text(json.dumps(rows), encoding='utf-8')
return p
def compare(self, candidate):
return review(self.write('before.json', self.rows), self.write('after.json', candidate))
def invalid(self, rows):
with self.assertRaises(ValueError): load_catalog(self.write('bad.json',rows))
def test_equal(self):
self.assertEqual(self.compare(self.rows)['status'],'no_semantic_change')
def test_price_change_needs_review(self):
r = self.compare([dict(self.rows[0],price_cents=1000)])
self.assertEqual(r['changes'][0]['field'],'price_cents')
self.assertEqual(r['status'],'review_required')
self.assertFalse(r['applied'])
def test_copy_change_needs_review(self):
self.assertEqual(self.compare([dict(self.rows[0],label='Different copy')])['changes'][0]['field'],'label')
def test_activation_change(self):
self.assertEqual(self.compare([dict(self.rows[0],active=False)])['changes'][0]['field'],'active')
def test_addition(self):
r=self.compare(self.rows+[dict(self.rows[0],id='service-b')])
self.assertEqual(r['changes'][0]['change'],'added')
def test_removal(self):
self.rows.append(dict(self.rows[0],id='service-b'))
self.assertEqual(self.compare(self.rows[:1])['changes'][0]['change'],'removed')
def test_reordering_is_not_change(self):
self.rows.append(dict(self.rows[0],id='service-b'))
self.assertEqual(self.compare(list(reversed(self.rows)))['changes'],[])
def test_bool_is_not_price(self): self.invalid([dict(self.rows[0],price_cents=True)])
def test_float_is_not_price(self): self.invalid([dict(self.rows[0],price_cents=10.0)])
def test_negative_price(self): self.invalid([dict(self.rows[0],price_cents=-1)])
def test_large_price(self): self.invalid([dict(self.rows[0],price_cents=10_000_001)])
def test_unknown_field(self): self.invalid([dict(self.rows[0],admin=True)])
def test_missing_field(self): self.invalid([{'id':'service-a'}])
def test_duplicate_ids(self): self.invalid(self.rows+self.rows)
def test_duplicate_json_keys(self):
p=self.p/'duplicate.json';p.write_text('[{"id":"a","id":"b"}]')
with self.assertRaises(ValueError):load_catalog(p)
def test_nonfinite(self):
p=self.p/'nan.json';p.write_text('[NaN]')
with self.assertRaises(ValueError):load_catalog(p)
def test_empty_catalog(self): self.invalid([])
def test_excessive_records(self): self.invalid(self.rows*101)
def test_oversized_input(self):
p=self.p/'large.json';p.write_bytes(b' '*(MAX_BYTES+1))
with self.assertRaises(ValueError):load_catalog(p)
def test_no_input_mutation(self):
a=self.write('before.json',self.rows);b=self.write('after.json',[dict(self.rows[0],price_cents=2)])
before=(a.read_bytes(),b.read_bytes());review(a,b)
self.assertEqual(before,(a.read_bytes(),b.read_bytes()))
def test_unicode_preserved(self):
r=self.compare([dict(self.rows[0],label='Café 東京')])
self.assertEqual(r['changes'][0]['after'],'Café 東京')
def test_raw_byte_change_is_traceable(self):
a=self.write('before.json',self.rows);b=self.p/'after.json';b.write_text(json.dumps(self.rows,indent=2))
r=review(a,b);self.assertEqual(r['changes'],[]);self.assertNotEqual(r['baseline_sha256'],r['candidate_sha256'])
if __name__=='__main__':unittest.main(verbosity=2)
python -X utf8 -m unittest test_catalog -v
All 22 isolated tests passed on Python 3.14.3. They exercise price, copy and activation changes; additions and removals; reordering; duplicate keys and IDs; missing and extra fields; Boolean, fractional, negative and oversized prices; empty and oversized inputs; Unicode; byte-level traceability; and unchanged input files. The final article’s runnable files and commands were also reproduced from its code blocks in a separate folder.
Those checks establish local review behavior on authored fixtures. They do not test a live AI assistant, deployment pipeline, payment system, authorization service or production workload. The documentation consulted is the current Python 3.14 branch; execution and source inspection used the stated 3.14.3 runtime.
The report is not the approval gate
Every report-only run exits normally, even when review is required. Do not treat process exit code zero as permission to deploy. A future pipeline must inspect the status and connect it to a real review decision. This CLI deliberately stops at reporting and does not implement that integration.
Own the baseline. Keep it in an owner-controlled repository or other trusted location. An AI agent allowed to replace the baseline can redefine what “unchanged” means. The local tool neither sets filesystem permissions nor proves that the supplied baseline was approved.
Bind later approval to the candidate. A production adapter would need an authenticated reviewer, an explicit approval record for the candidate hash and a check of the exact candidate again immediately before application. Concurrent file changes and deployment-time race handling were not tested here. Do not merely add an approved: true field to agent-controlled JSON.
Stay within the schema. There is no support for discounts, tax, currencies, descriptions, nested configuration or emptying the entire catalog. Deactivating the last service is reported, but a separate business rule would be needed to prohibit it. Invalid inputs raise errors rather than producing a misleading no-change report. Sensitive baseline and candidate values are printed in the diff, so keep reports out of public logs when adapting this to real data.
The deliverable is a readable change list and reproducible input identifiers. Pair it with an actual human decision and appropriate downstream controls before it becomes part of a business application. The retryable CRM handoff example covers a separate stage after an action has been approved; it was not integrated with this reviewer.
Published by Jason Ead for AlgoThoughts AI News. My Biz Heroes connects this practical approach to business websites, automation, workflows, AI tools and training. These fictional prices are not My Biz Heroes offers or client results. Be Your Evolution. Advance yourself with AI.
