One useful idea
A guard clause rejects a refused input before later code relies on it. This pure function accepts a dictionary with exactly source, width, codec, frames, fps and model. A wrong container raises TypeError; bad fields or keys raise ValidationError with an actionable message and code invalid_metadata.
Source must retain canonical relative path text. Width is a non-boolean integer from 1 to 16384. Codec/model contain 1–80 trimmed characters without remaining controls. Frames is a non-boolean integer from 1 to one billion; fps is a finite non-boolean int/float from 0.001 to 1000. Their duration must be positive and no more than 86400 seconds. Use the reviewed path and seconds helpers; zero frames is refused here even though Module 1 could represent zero elapsed time.
Return a new dictionary. Strip/casefold codec for comparison, but preserve the original model label, source and numeric units. Unknown labels can be structurally valid; separate delivery rules and known-model lookup decide what they mean. Never guess an alias, replace a missing rate with 24, round fps early or mutate the caller.
Refresh first: Expected metadata failures, Frames, rates and finiteness, Dictionaries and exact fields.
Trace a finished example
from asset_intelligence.core import validate_ingest
record = {"source": "camera/detail.mov", "width": 1920,
"codec": " H264 ", "frames": 2997, "fps": 29.97,
"model": " Google Veo "}
cleaned = validate_ingest(record)
print(cleaned["codec"])
print(repr(cleaned["model"]))
print(cleaned["frames"] / cleaned["fps"])
print(record["codec"] == " H264 ")
# h264
# ' Google Veo '
# 100.0
# TrueValidation checks all fields and computes duration only as a constraint. A new result holds normalized codec and original model/rate/frame evidence. The caller still contains its original codec string.
The finished implementation is in asset_intelligence/core.py. Reading it is guided practice, not independent evidence.
Predict the preserved value
Does model " Google Veo " become the canonical alias veo?
Compare your answer · self-reviewed
No. Validate its trimmed label length, but preserve the original model text. Alias lookup belongs to the separate Module 2 policy.
Find the numeric loophole
Why reject width=True even though isinstance(True, int) succeeds?
Compare your answer · self-reviewed
bool is a subclass of int, but this schema requires a real width measurement. Explicitly exclude booleans before range checks.
Recall the units
Why preserve fps=29.97 instead of converting it to int?
Compare your answer · self-reviewed
Changing the rate changes duration. Keep the original numeric value; presentation and delivery classification are separate operations.
Try the idea in this browser
Runs in this browser · optional preparation · local project checks remain separate
Try a small function before opening your local files. Python downloads when you choose Run; if it cannot load, your code stays here and the local kit still works. The worker executes on your device, not on a DVP server. Only run code you trust: this is not a hostile-code security sandbox.
JavaScript loads the practice controls. Python starts only after Run.
The tutor button only prepares a question locally. Review it and choose Send yourself; no code is sent merely by running or opening a lesson.
Output
Errors and check feedback
Read the browser task briefs without running Python
Trace the declared failure boundary
Read the function, predict a changed normal/refused case, then Run. Implement the exact six-field ingest contract from the lesson/README. Wrong container is TypeError; field errors are ValidationError. Exclude bool, refuse nonfinite/out-of-range numbers and nonpositive/excess duration, normalize only codec, preserve evidence and fresh ownership. Reviewed path/seconds helpers are supplied; no files are inspected.
Build the boundary on changed inputs
Implement the exact six-field ingest contract from the lesson/README. Wrong container is TypeError; field errors are ValidationError. Exclude bool, refuse nonfinite/out-of-range numbers and nonpositive/excess duration, normalize only codec, preserve evidence and fresh ownership. Reviewed path/seconds helpers are supplied; no files are inspected.
Change it, then build your own
One controlled change
Change source, codec case and fractional fps. Then try an extra key, width=True, frames=0 and fps=float("nan"). Predict which fail and whether the original record changes.
Your independent task
Implement validate_ingest(record) in practice.py under the exact README schema. Use provided relative_asset_path and seconds_from_frames; wrap field-validation errors in ValidationError without silently replacing data. Return a fresh six-field dictionary with only codec normalized. Restore this function as the validator used by your Build 1 implementation.
What success looks like
The build2 group passes ten named refusal cases plus type/range, duration-limit and fresh-output checks. Then rerun build1 to verify integration with your validator. Unknown codec/model metadata may validate but still fail a separate delivery rule.
Hint 1 · a question
Write the six-field contract and decide which failures are container errors versus field errors.
Hint 2 · a concept cue
Validate type before range. Catch only the helper errors you deliberately translate to ValidationError; preserve source/model and numeric units.
Hint 3 · a localized example
A normalized codec can use record["codec"].strip().casefold(). Put it in a new dictionary rather than assigning into record. This alone is not the complete validator.
Need the complete worked solution?
Open asset_intelligence/core.py from the kit. Trace it, close it, then try fresh inputs in your own files. Treat the attempt as guided; seeing the solution does not award a practical pass.
Course help is guidance, not independent evidence. With JavaScript, opening help records guidance locally; otherwise note it in your README. Reset does not erase that history.
Repair a failed check
If extra keys pass, compare the complete key set. If booleans or NaN pass, perform explicit type/finiteness checks before arithmetic. If a caller record changes, construct a new result instead of normalizing it in place. If unknown labels are silently replaced, remove the fallback.
NotImplementedError means a practice stub is still unfinished. Read the failing test name and the last error line. Change one behavior, rerun that build, then rerun all implemented builds.
Show it works on new inputs
Create ten different malformed records and two valid boundaries. Show exact error categories, unchanged input and a new result object. Add a valid unknown model and explain why structural acceptance is not a delivery pass.
Self-review: name the input, result, refused case and reason. Your local test output and explanation are separate from a quiz score; this page does not certify a pass.
Keep the idea
Validation protects the meaning of data. Explicit refusal is more honest than a convenient default that erases missing or malformed evidence.