Definition
Be liberal in what you accept and conservative in what you send. The system tolerates messy, varied, and even malformed input from users while producing strict, well-formed output to other systems. Resilience lives at the boundary.
Why it matters for ShurIQ reports
Search inputs, date filters, and natural-language queries on the viz hub should accept any plausible reader input — uppercase, lowercase, partial spellings, multiple languages — and resolve to canonical results. Likewise, evidence-trail data ingested from messy public sources must be normalized before it lands in a stack-rank cell. Tolerant inputs and disciplined outputs are what make the brief feel intelligent rather than brittle.
Takeaways
- Accept any plausible input shape; coerce, never reject without clear remediation.
- Validate at the boundary, not throughout; once normalized, internal data assumes a clean shape.
- Provide visible feedback when input is interpreted, so the reader sees the system understanding them.
- Define the boundary of acceptable input explicitly — Postel's Law is permissive, not infinite.
Visual motion language
Inputs animate from raw to normalized form (e.g., "BMW " becomes "BMW Group" with a magnetic-pull and a soft fade-in). The reader sees their input land in canonical state.
Origins
Jon Postel — formulated as the Robustness Principle for early TCP/IP implementations.
Cavalry scene
The script below builds this concept's motion in Cavalry through the Stallion bridge. Pipe to cavalry_run_script via MCP, or paste into Cavalry's JavaScript Editor.
// Laws of UX · postels-law · Cavalry scene
// CORRECTED 2026-04-30 · verified from production page
// Motion family: opacity-stepped horizontal bands (12 downward triangles in 4 rows x 3 cols)
// Row-stepped opacity 1.0/0.8/0.6/0.4; row-by-row reveal, all 3 in a row enter together
// Palette: forest-green + teals/cream
// To run: pipe to cavalry_run_script tool, or paste into Cavalry's JavaScript Editor
// Built 2026-04-30 by ShurAI
(function () {
var PREFIX = "claude_lawofux_postels-law_";
var existing = api.getAllSceneLayers();
for (var i = 0; i < existing.length; i++) {
try {
var nm = api.getNiceName(existing[i]);
if (nm && nm.indexOf("claude_lawofux_") === 0) api.deleteLayer(existing[i]);
} catch (e) {}
}
var BG = "#2D5A3F";
var CREAM = "#D6CDB0";
var bg = api.primitive("rectangle", PREFIX + "bg");
api.set(bg, { "generator.dimensions": [1080, 1080] });
api.setFill(bg, true);
api.set(bg, { "material.materialColor": BG });
// 4 rows x 3 cols = 12 downward-pointing triangles, scaled into 1080 canvas.
// Cell dimensions: ~290 wide x 220 tall. Triangle fits cell.
// Rotation.z = 180 to flip apex down.
var triRadius = 145; // polygon outer radius -> ~290px wide
var rowOpacities = [100, 80, 60, 40];
var rowBegin = [0, 8, 16, 24]; // ~250ms per row at 30fps
var COL_STEP = 290;
var ROW_STEP = 220;
var startX = -COL_STEP; // -290, 0, +290
var startY = (3 * ROW_STEP) / 2 - ROW_STEP / 2; // top row Y (positive=up)
for (var r = 0; r < 4; r++) {
for (var c = 0; c < 3; c++) {
var tri = api.primitive("polygon", PREFIX + "r" + (r+1) + "c" + (c+1));
api.set(tri, {
"generator.sides": 3,
"generator.radius": triRadius,
"position.x": startX + c * COL_STEP,
"position.y": startY - r * ROW_STEP,
"rotation.z": 180,
"opacity": 0
});
api.setFill(tri, true);
api.set(tri, { "material.materialColor": CREAM });
var t0 = rowBegin[r];
var t1 = t0 + 10;
api.keyframe(tri, t0, { "opacity": 0 });
api.keyframe(tri, t1, { "opacity": rowOpacities[r] });
api.magicEasing(tri, "opacity", t1, "EaseOut", "");
}
}
var layerCount = api.getAllSceneLayers().length;
console.log("scene built: postels-law (" + layerCount + " layers)");
})();