touchstone-us 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. touchstone_us-0.1.0/.gitignore +8 -0
  2. touchstone_us-0.1.0/LICENSE +40 -0
  3. touchstone_us-0.1.0/PKG-INFO +9 -0
  4. touchstone_us-0.1.0/PROTOCOL.md +92 -0
  5. touchstone_us-0.1.0/app.js +151 -0
  6. touchstone_us-0.1.0/base.css +128 -0
  7. touchstone_us-0.1.0/examples/cpu-correct.json +44 -0
  8. touchstone_us-0.1.0/examples/cpu-crash.json +44 -0
  9. touchstone_us-0.1.0/examples/cpu-drift.json +44 -0
  10. touchstone_us-0.1.0/examples/cpu-missing.json +44 -0
  11. touchstone_us-0.1.0/examples/cpu-slow.json +44 -0
  12. touchstone_us-0.1.0/examples/cpu-timeout.json +44 -0
  13. touchstone_us-0.1.0/examples/cpu-upgrade.json +44 -0
  14. touchstone_us-0.1.0/examples/cuda-correct.json +44 -0
  15. touchstone_us-0.1.0/examples/cuda-drift.json +44 -0
  16. touchstone_us-0.1.0/examples/cuda-slow.json +44 -0
  17. touchstone_us-0.1.0/examples/cuda-upgrade.json +44 -0
  18. touchstone_us-0.1.0/examples/fixtures.json +651 -0
  19. touchstone_us-0.1.0/examples/workload.py +110 -0
  20. touchstone_us-0.1.0/fixtures.js +48 -0
  21. touchstone_us-0.1.0/index.html +76 -0
  22. touchstone_us-0.1.0/pyproject.toml +65 -0
  23. touchstone_us-0.1.0/responsive.css +21 -0
  24. touchstone_us-0.1.0/rl_examples/bad-reference.json +190 -0
  25. touchstone_us-0.1.0/rl_examples/broken-control.json +190 -0
  26. touchstone_us-0.1.0/rl_examples/cache-leak.json +190 -0
  27. touchstone_us-0.1.0/rl_examples/fixed-grader.json +190 -0
  28. touchstone_us-0.1.0/rl_examples/malformed-grader.json +190 -0
  29. touchstone_us-0.1.0/rl_examples/weak-grader.json +190 -0
  30. touchstone_us-0.1.0/styles.css +44 -0
  31. touchstone_us-0.1.0/touchstone/__init__.py +1 -0
  32. touchstone_us-0.1.0/touchstone/agent.py +423 -0
  33. touchstone_us-0.1.0/touchstone/app.py +272 -0
  34. touchstone_us-0.1.0/touchstone/artifacts.py +31 -0
  35. touchstone_us-0.1.0/touchstone/attest.py +178 -0
  36. touchstone_us-0.1.0/touchstone/catalog.py +67 -0
  37. touchstone_us-0.1.0/touchstone/cli.py +184 -0
  38. touchstone_us-0.1.0/touchstone/compare.py +271 -0
  39. touchstone_us-0.1.0/touchstone/doctor.py +218 -0
  40. touchstone_us-0.1.0/touchstone/models.py +158 -0
  41. touchstone_us-0.1.0/touchstone/packages.py +43 -0
  42. touchstone_us-0.1.0/touchstone/redact.py +68 -0
  43. touchstone_us-0.1.0/touchstone/rl/__init__.py +1 -0
  44. touchstone_us-0.1.0/touchstone/rl/analyze.py +330 -0
  45. touchstone_us-0.1.0/touchstone/rl/answer.py +391 -0
  46. touchstone_us-0.1.0/touchstone/rl/api.py +118 -0
  47. touchstone_us-0.1.0/touchstone/rl/attacks.py +116 -0
  48. touchstone_us-0.1.0/touchstone/rl/catalog.py +72 -0
  49. touchstone_us-0.1.0/touchstone/rl/cli.py +209 -0
  50. touchstone_us-0.1.0/touchstone/rl/diff.py +147 -0
  51. touchstone_us-0.1.0/touchstone/rl/engine.py +380 -0
  52. touchstone_us-0.1.0/touchstone/rl/harnesses/answer.py +97 -0
  53. touchstone_us-0.1.0/touchstone/rl/harnesses/grade.py +102 -0
  54. touchstone_us-0.1.0/touchstone/rl/harnesses/invoke.py +16 -0
  55. touchstone_us-0.1.0/touchstone/rl/models.py +321 -0
  56. touchstone_us-0.1.0/touchstone/rl/onboard.py +234 -0
  57. touchstone_us-0.1.0/touchstone/rl/service.py +266 -0
  58. touchstone_us-0.1.0/touchstone/runner.py +351 -0
  59. touchstone_us-0.1.0/touchstone/safety/__init__.py +1 -0
  60. touchstone_us-0.1.0/touchstone/safety/adapters.py +108 -0
  61. touchstone_us-0.1.0/touchstone/safety/api.py +71 -0
  62. touchstone_us-0.1.0/touchstone/safety/cli.py +166 -0
  63. touchstone_us-0.1.0/touchstone/safety/codex.py +73 -0
  64. touchstone_us-0.1.0/touchstone/safety/compare.py +35 -0
  65. touchstone_us-0.1.0/touchstone/safety/demo.py +58 -0
  66. touchstone_us-0.1.0/touchstone/safety/engine.py +146 -0
  67. touchstone_us-0.1.0/touchstone/safety/execution.py +18 -0
  68. touchstone_us-0.1.0/touchstone/safety/generator.py +42 -0
  69. touchstone_us-0.1.0/touchstone/safety/generator_worker.py +7 -0
  70. touchstone_us-0.1.0/touchstone/safety/models.py +137 -0
  71. touchstone_us-0.1.0/touchstone/safety/store.py +244 -0
  72. touchstone_us-0.1.0/touchstone/safety/sync.py +64 -0
  73. touchstone_us-0.1.0/touchstone/safety/worker.py +31 -0
  74. touchstone_us-0.1.0/touchstone/service.py +329 -0
  75. touchstone_us-0.1.0/touchstone/store.py +206 -0
  76. touchstone_us-0.1.0/web/demo.js +13 -0
  77. touchstone_us-0.1.0/web/docs.css +43 -0
  78. touchstone_us-0.1.0/web/docs.html +226 -0
  79. touchstone_us-0.1.0/web/index.html +469 -0
  80. touchstone_us-0.1.0/web/rl.css +172 -0
  81. touchstone_us-0.1.0/web/rl.html +377 -0
  82. touchstone_us-0.1.0/web/rl.js +741 -0
  83. touchstone_us-0.1.0/web/safety-public.html +38 -0
  84. touchstone_us-0.1.0/web/safety.css +119 -0
  85. touchstone_us-0.1.0/web/safety.html +70 -0
  86. touchstone_us-0.1.0/web/safety.js +481 -0
  87. touchstone_us-0.1.0/web/workspace.css +888 -0
  88. touchstone_us-0.1.0/web/workspace.js +688 -0
@@ -0,0 +1,8 @@
1
+ .local/
2
+ .touchstone/
3
+ node_modules/
4
+ .venv/
5
+ __pycache__/
6
+ *.pyc
7
+ # Podman/conmon may leave this empty marker after a memory-limited workload exits.
8
+ /oom
@@ -0,0 +1,40 @@
1
+ TouchStone Proprietary License
2
+
3
+ Copyright (c) 2026 Merrick Zheng. All rights reserved.
4
+
5
+ This software and its accompanying files (the "Software") are proprietary and
6
+ confidential. The Software is licensed, not sold.
7
+
8
+ 1. Permitted use. Subject to a separate written agreement with the copyright
9
+ holder (such as a pilot, evaluation or subscription agreement), you may
10
+ install and run the Software on infrastructure you control for your own
11
+ internal purposes. If no such agreement exists, you may install and run the
12
+ Software solely to evaluate it for up to thirty (30) days.
13
+
14
+ 2. Restrictions. Except as expressly permitted above or by applicable law that
15
+ cannot be excluded by contract, you may not: (a) copy, distribute, sublicense,
16
+ sell, rent, lease or otherwise make the Software available to any third
17
+ party; (b) modify, translate or create derivative works of the Software;
18
+ (c) remove or alter any copyright, license or attribution notice; or
19
+ (d) use the Software to build a competing product or service.
20
+
21
+ 3. Ownership. The copyright holder retains all right, title and interest in
22
+ the Software. No rights are granted by implication, estoppel or otherwise
23
+ except those expressly stated in this license.
24
+
25
+ 4. Termination. This license terminates automatically if you breach any of its
26
+ terms. On termination you must stop using the Software and delete all
27
+ copies in your possession.
28
+
29
+ 5. Disclaimer of warranty. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY
30
+ OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
31
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32
+ NON-INFRINGEMENT.
33
+
34
+ 6. Limitation of liability. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE
35
+ FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
36
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
37
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38
+
39
+ Third-party components bundled with or depended on by the Software remain
40
+ under their own licenses.
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.5
2
+ Name: touchstone-us
3
+ Version: 0.1.0
4
+ License-Expression: LicenseRef-Proprietary
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.12
7
+ Requires-Dist: cryptography>=46
8
+ Requires-Dist: fastapi>=0.162.0
9
+ Requires-Dist: uvicorn>=0.54.0
@@ -0,0 +1,92 @@
1
+ # Workload contract
2
+
3
+ The runner executes trusted OCI images with a manifest command (an argv array;
4
+ there is no implicit host shell). The frozen workload file and fixture are
5
+ mounted read-only at `/workload`. Images are resolved to local immutable IDs
6
+ before the first measurement. Registry digests are recorded when available.
7
+
8
+ ## Start from the included example
9
+
10
+ 1. Keep `manifest.json`, `workload.py` and `fixtures.json` together.
11
+ 2. Replace the baseline and candidate images/commands with your own trusted
12
+ test implementations. The command must emit the JSON contract below.
13
+ 3. Supply case IDs and expected numeric vectors in the fixture. The `inputs`
14
+ object carries your workload's data; the controller does not interpret it.
15
+ 4. Import the three files in the local workspace, review the policy and run.
16
+
17
+ File basenames in the manifest must match the workload/fixture filenames.
18
+ Input files are limited to 1 MB each. One comparison executes three to ten
19
+ paired trials, alternating baseline-first and candidate-first order. Workloads
20
+ need no network and should not download models during measurement. Put their
21
+ dependencies and model data in your approved image or the bounded fixture.
22
+
23
+ ## Manifest
24
+
25
+ Use the starter's manifest. `baseline` and `candidate` each contain `image`
26
+ and `command`. `device` is `cpu` or `cuda`. `repeats` is 3-10,
27
+ `timeout_seconds` is 5-180, `memory_mb` is 256-8192, and `cpus` is 1-4.
28
+ The policy covers throughput retention, amortized time ratio, absolute output
29
+ error, reported memory, failed samples, minimum samples and timing CV.
30
+ The manifest schema rejects unknown fields and invalid/non-finite values.
31
+
32
+ ## Fixture
33
+
34
+ ```json
35
+ {
36
+ "schema_version": 1,
37
+ "cases": [{"id": "case-01", "values": [0.25, 0.75]}],
38
+ "inputs": {"your_workload_data": "goes here"}
39
+ }
40
+ ```
41
+
42
+ Case IDs must be unique. There are at most 256 cases and 256 numeric values per
43
+ case, with at most 4096 values in total. Values are finite. The controller requires exact ID and vector-length
44
+ coverage from each execution and calculates absolute errors against this file.
45
+
46
+ ## Standard output
47
+
48
+ Emit exactly one JSON object; send diagnostic text to stderr. The example
49
+ below is a schema illustration, not a measurement to reuse.
50
+
51
+ ```json
52
+ {
53
+ "schema_version": 1,
54
+ "device": "cpu",
55
+ "samples": 1000,
56
+ "duration_seconds": 1.5,
57
+ "peak_memory_mb": 28.0,
58
+ "memory_kind": "process_rss",
59
+ "failures": 0,
60
+ "outputs": [{"id": "case-01", "values": [0.25, 0.75]}],
61
+ "runtime": {"python": "3.12", "workload": "your-suite-v1"}
62
+ }
63
+ ```
64
+
65
+ Use `cuda_allocated` for CUDA memory and `process_rss` for CPU memory. CUDA
66
+ workloads must fail if CUDA is unavailable; silent CPU fallback cannot qualify
67
+ the requested contract. Synchronize CUDA before and after the measured region.
68
+ Keep initialization/warmup outside that region. `samples / duration_seconds`
69
+ gives throughput; its reciprocal gives amortized processing time per sample.
70
+ For a batched workload this is not request latency, nor p95 or p99. The v1
71
+ JSON fields `latency_ms` and `max_latency_ratio` retain their original names;
72
+ they represent this derived amortized time and its candidate/baseline ratio.
73
+ These are trusted test-instrumentation measurements, not tamper-proof telemetry.
74
+
75
+ ## Results and boundaries
76
+
77
+ - `eligible`: declared checks pass; a human release owner must still decide.
78
+ - `hold`: at least one policy check fails; inspect the evidence and fix the candidate.
79
+ - `inconclusive`: execution, reference coverage, comparability or repeatability
80
+ is incomplete. A crash, missing output or timeout never becomes a pass.
81
+ - Cancelled/interrupted/error executions retain diagnostic evidence separately.
82
+
83
+ The included examples are small real classifier inference, with deliberately
84
+ injected faults in named variants. They are not a discovered upstream bug,
85
+ representative LLM benchmark, convergence test or customer validation.
86
+
87
+ This MVP uses rootless Podman, a non-root workload user, no container network,
88
+ no capabilities, resource/process limits and bounded logs. CPU root filesystems
89
+ are read-only. NVIDIA CDI needs a temporary writable image layer to initialize
90
+ its loader on this WSL host; GPU workloads still run non-root and inputs remain
91
+ read-only. CUDA GPU memory is not limited by the CPU cgroup memory setting.
92
+ Only run trusted operator code. Containers are not a hostile-code security boundary.
@@ -0,0 +1,151 @@
1
+ import { checks, scenarios, evaluate, disposition } from './fixtures.js';
2
+ const get = id => document.getElementById(id);
3
+ const requestedScenario = new URL(location.href).searchParams.get('scenario');
4
+ let selected = Object.hasOwn(scenarios, requestedScenario) ? requestedScenario : 'throughput';
5
+ const checkList = get('check-list');
6
+ const decision = get('decision');
7
+ const status = get('review-status');
8
+ const format = new Intl.NumberFormat('en-US', { maximumFractionDigits: 1 });
9
+ function checkDetail(key, scenario) {
10
+ const { baseline, candidate } = scenario.fixture;
11
+ if (key === 'hardware') return `${baseline.samples} baseline / ${candidate.samples} candidate requests`;
12
+ if (key === 'throughput') return `${format.format(baseline.throughput)} → ${format.format(candidate.throughput)} tokens/s`;
13
+ if (key === 'fidelity') return `Observed max error: ${candidate.error}`;
14
+ return `${format.format(candidate.memoryGb)} GB peak / ${candidate.failures} failed requests`;
15
+ }
16
+ function renderChecks(results) {
17
+ checkList.replaceChildren(...checks.map(check => {
18
+ const row = document.createElement('div');
19
+ const outcome = !results ? 'pending' : results[check.key] === null ? 'inconclusive' : results[check.key] ? 'pass' : 'fail';
20
+ row.className = `check-row ${outcome}`;
21
+ const symbol = document.createElement('span');
22
+ symbol.className = 'check-symbol';
23
+ symbol.setAttribute('aria-hidden', 'true');
24
+ symbol.textContent = { pass: '✓', fail: '!', pending: '○', inconclusive: '—' }[outcome];
25
+ const label = document.createElement('span');
26
+ label.className = 'check-label';
27
+ const name = document.createElement('strong');
28
+ name.textContent = check.label;
29
+ label.append(name);
30
+ if (results && outcome !== 'inconclusive') {
31
+ const detail = document.createElement('small');
32
+ detail.textContent = checkDetail(check.key, scenarios[selected]);
33
+ label.append(detail);
34
+ }
35
+ const value = document.createElement('span');
36
+ value.textContent = { pass: 'Pass', fail: 'Fail', pending: 'Not run', inconclusive: 'Not qualified' }[outcome];
37
+ row.append(symbol, label, value);
38
+ return row;
39
+ }));
40
+ }
41
+ function selectScenario(key) {
42
+ selected = key;
43
+ const url = new URL(location.href);
44
+ url.searchParams.set('scenario', key);
45
+ history.replaceState(null, '', url);
46
+ const scenario = scenarios[key];
47
+ for (const button of document.querySelectorAll('[data-scenario]')) {
48
+ const active = button.dataset.scenario === key;
49
+ button.classList.toggle('active', active);
50
+ button.setAttribute('aria-pressed', String(active));
51
+ }
52
+ get('release-id').textContent = `Candidate stack ${scenario.release}`;
53
+ get('scenario-title').textContent = scenario.title;
54
+ get('baseline-name').textContent = scenario.baselineName;
55
+ get('candidate-name').textContent = scenario.candidateName;
56
+ get('sample-context').textContent = selected === 'hardware' ? 'H100 baseline / A100 candidate • 100 sampled requests per stack' : 'Matched H100 80 GB host profile • 100 sampled requests per stack';
57
+ status.className = 'status idle';
58
+ status.textContent = 'Not checked';
59
+ decision.className = 'decision';
60
+ decision.querySelector('.decision-symbol').textContent = '○';
61
+ decision.querySelector('strong').textContent = 'Choose a candidate. Run its checks.';
62
+ decision.querySelector('p').textContent = 'The decision and supporting evidence will appear here.';
63
+ get('evidence-details').hidden = true;
64
+ get('evidence-details').open = false;
65
+ get('compare-fixed').hidden = true;
66
+ get('run-checks').textContent = 'Run sample checks ↗';
67
+ renderChecks();
68
+ }
69
+ get('run-checks').addEventListener('click', () => {
70
+ const scenario = scenarios[selected];
71
+ const results = evaluate(scenario.fixture);
72
+ const result = disposition(results);
73
+ renderChecks(results);
74
+ status.className = `status ${result}`;
75
+ status.textContent = { ready: 'Eligible for review', blocked: 'Hold', inconclusive: 'Rerun required' }[result];
76
+ decision.className = `decision ${result}`;
77
+ decision.querySelector('.decision-symbol').textContent = { ready: '✓', blocked: '!', inconclusive: '↺' }[result];
78
+ decision.querySelector('strong').textContent = {
79
+ ready: 'Policy checks pass. Owner approval is next.',
80
+ blocked: selected === 'fidelity' ? 'Hold. The faster candidate fails output fidelity.' : 'Hold. Throughput falls below the release threshold.',
81
+ inconclusive: 'Rerun required. The hardware profiles do not match.',
82
+ }[result];
83
+ decision.querySelector('p').textContent = scenario.explanation;
84
+ get('evidence-details').hidden = false;
85
+ get('evidence-output').textContent = JSON.stringify(scenario.evidence, null, 2);
86
+ get('evidence-explanation').textContent = 'Illustrative evidence only. These image identities, bundles and results are synthetic; no live infrastructure is connected.';
87
+ get('compare-fixed').hidden = selected !== 'throughput' && selected !== 'fidelity';
88
+ get('run-checks').textContent = 'Run sample checks again ↗';
89
+ });
90
+ for (const button of document.querySelectorAll('[data-scenario]')) button.addEventListener('click', () => selectScenario(button.dataset.scenario));
91
+ get('compare-fixed').addEventListener('click', () => {
92
+ selectScenario('ready');
93
+ get('run-checks').click();
94
+ get('run-checks').focus({ preventScroll: true });
95
+ });
96
+ const dialog = get('pilot-dialog');
97
+ get('pilot-brief').addEventListener('click', () => dialog.showModal());
98
+ get('close-pilot').addEventListener('click', () => dialog.close());
99
+ get('pilot-done').addEventListener('click', () => {
100
+ dialog.close();
101
+ get('sample').scrollIntoView({ behavior: scrollBehavior() });
102
+ get('run-checks').focus({ preventScroll: true });
103
+ });
104
+ dialog.addEventListener('click', event => {
105
+ if (event.target === dialog) {
106
+ const bounds = dialog.getBoundingClientRect();
107
+ if (event.clientX < bounds.left || event.clientX > bounds.right || event.clientY < bounds.top || event.clientY > bounds.bottom) dialog.close();
108
+ }
109
+ });
110
+ const scrollBehavior = () => matchMedia('(prefers-reduced-motion: reduce)').matches ? 'instant' : 'smooth';
111
+ for (const link of document.querySelectorAll('[data-jump]')) link.addEventListener('click', event => {
112
+ event.preventDefault();
113
+ selectScenario(link.dataset.jump);
114
+ get('sample').scrollIntoView({ behavior: scrollBehavior() });
115
+ get('run-checks').focus({ preventScroll: true });
116
+ });
117
+ const tabs = [...document.querySelectorAll('[role=tab]')];
118
+ function selectTab(tab) {
119
+ for (const other of tabs) {
120
+ const active = other === tab;
121
+ other.setAttribute('aria-selected', String(active));
122
+ other.tabIndex = active ? 0 : -1;
123
+ get(other.getAttribute('aria-controls')).hidden = !active;
124
+ }
125
+ }
126
+ for (const tab of tabs) {
127
+ tab.addEventListener('click', () => selectTab(tab));
128
+ tab.addEventListener('keydown', event => {
129
+ const step = { ArrowRight: 1, ArrowLeft: -1 }[event.key];
130
+ if (!step) return;
131
+ const next = tabs[(tabs.indexOf(tab) + step + tabs.length) % tabs.length];
132
+ selectTab(next);
133
+ next.focus();
134
+ });
135
+ }
136
+ get('copy-code').addEventListener('click', async () => {
137
+ const panel = document.querySelector('[role=tabpanel]:not([hidden])');
138
+ const note = get('copy-status');
139
+ try {
140
+ await navigator.clipboard.writeText(panel.textContent);
141
+ note.textContent = 'Copied to the clipboard.';
142
+ } catch {
143
+ getSelection().selectAllChildren(panel);
144
+ note.textContent = 'Copy is unavailable here; the command is selected.';
145
+ }
146
+ });
147
+ const header = document.querySelector('.site-header');
148
+ const markScrolled = () => header.classList.toggle('scrolled', scrollY > 8);
149
+ addEventListener('scroll', markScrolled, { passive: true });
150
+ markScrolled();
151
+ selectScenario(selected);
@@ -0,0 +1,128 @@
1
+ @font-face {
2
+ font-family:TouchStone Sans;
3
+ src:local("Bahnschrift"),local("Arial");
4
+ font-display:swap;
5
+ }
6
+ :root {
7
+ --ink:#142338;
8
+ --muted:#58687c;
9
+ --cobalt:#254f9b;
10
+ --cobalt-deep:#213caf;
11
+ --ice:#f1f5fa;
12
+ --line:#dce3ec;
13
+ --pale:#e9edff;
14
+ --green:#227b59;
15
+ --amber:#9c6411;
16
+ --white:#fff;
17
+ --radius:12px;
18
+ }
19
+ * {
20
+ box-sizing:border-box;
21
+ }
22
+ html {
23
+ scroll-behavior:smooth;
24
+ scroll-padding-top:96px;
25
+ }
26
+ body {
27
+ margin:0;
28
+ background:var(--white);
29
+ color:var(--ink);
30
+ font-family:"TouchStone Sans","Segoe UI",Arial,sans-serif;
31
+ font-size:16px;
32
+ line-height:1.65;
33
+ -webkit-font-smoothing:antialiased;
34
+ }
35
+ button,a {
36
+ -webkit-tap-highlight-color:transparent;
37
+ }
38
+ button {
39
+ font:inherit;
40
+ cursor:pointer;
41
+ }
42
+ a {
43
+ color:inherit;
44
+ text-decoration:none;
45
+ }
46
+ a,button,summary {
47
+ touch-action:manipulation;
48
+ }
49
+ a:focus-visible,button:focus-visible,summary:focus-visible {
50
+ outline:3px solid #b25816;
51
+ outline-offset:5px;
52
+ }
53
+ h1,h2,h3,p {
54
+ margin:0;
55
+ }
56
+ h1,h2,h3 {
57
+ text-wrap:balance;
58
+ }
59
+ p {
60
+ max-width:68ch;
61
+ }
62
+ h1 {
63
+ font-size:clamp(48px,5.2vw,78px);
64
+ line-height:1.06;
65
+ letter-spacing:-.055em;
66
+ font-weight:650;
67
+ }
68
+ h2 {
69
+ font-size:clamp(34px,3.1vw,48px);
70
+ line-height:1.15;
71
+ letter-spacing:-.04em;
72
+ font-weight:650;
73
+ }
74
+ h3 {
75
+ font-size:19px;
76
+ line-height:1.35;
77
+ font-weight:650;
78
+ letter-spacing:-.015em;
79
+ }
80
+ .wrap {
81
+ width:min(1200px,calc(100% - 96px));
82
+ margin-inline:auto;
83
+ }
84
+ .site-header {
85
+ display:flex;
86
+ align-items:center;
87
+ justify-content:space-between;
88
+ min-height:104px;
89
+ }
90
+ .brand {
91
+ display:inline-flex;
92
+ align-items:center;
93
+ gap:10px;
94
+ font-size:24px;
95
+ font-weight:680;
96
+ letter-spacing:-.055em;
97
+ line-height:1;
98
+ }
99
+ .brand svg {
100
+ height:34px;
101
+ width:34px;
102
+ stroke:var(--cobalt);
103
+ fill:none;
104
+ stroke-width:3.4;
105
+ stroke-linejoin:round;
106
+ stroke-linecap:round;
107
+ }
108
+ .site-header nav {
109
+ display:flex;
110
+ align-items:center;
111
+ gap:31px;
112
+ font-size:14px;
113
+ font-weight:550;
114
+ }
115
+ .site-header nav a {
116
+ padding:8px 0;
117
+ }
118
+ .site-header nav a:hover,.text-link:hover,.site-footer>a:last-child:hover {
119
+ color:var(--cobalt);
120
+ }
121
+ .site-header nav .nav-cta {
122
+ padding:10px 17px;
123
+ border:1px solid var(--line);
124
+ border-radius:6px;
125
+ }
126
+ .nav-cta:hover {
127
+ background:var(--ice);
128
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "schema_version": 1,
3
+ "name": "CPU / Reference match",
4
+ "description": "Measured inference with identical correct implementations. Performance can still be noisy.",
5
+ "demonstration": true,
6
+ "device": "cpu",
7
+ "baseline": {
8
+ "image": "docker.io/library/python:3.12-slim",
9
+ "command": [
10
+ "python",
11
+ "/workload/workload.py",
12
+ "--device",
13
+ "cpu",
14
+ "--variant",
15
+ "correct"
16
+ ]
17
+ },
18
+ "candidate": {
19
+ "image": "docker.io/library/python:3.12-slim",
20
+ "command": [
21
+ "python",
22
+ "/workload/workload.py",
23
+ "--device",
24
+ "cpu",
25
+ "--variant",
26
+ "correct"
27
+ ]
28
+ },
29
+ "workload_file": "workload.py",
30
+ "fixture_file": "fixtures.json",
31
+ "repeats": 3,
32
+ "timeout_seconds": 60,
33
+ "memory_mb": 512,
34
+ "cpus": 2,
35
+ "policy": {
36
+ "min_throughput_ratio": 0.8,
37
+ "max_latency_ratio": 1.3,
38
+ "max_abs_error": 1e-05,
39
+ "max_peak_memory_mb": 1024.0,
40
+ "max_failures": 0,
41
+ "min_samples": 100,
42
+ "max_timing_cv": 0.3
43
+ }
44
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "schema_version": 1,
3
+ "name": "CPU / Injected execution failure",
4
+ "description": "Deliberately exits with status 3. The result must remain inconclusive.",
5
+ "demonstration": true,
6
+ "device": "cpu",
7
+ "baseline": {
8
+ "image": "docker.io/library/python:3.12-slim",
9
+ "command": [
10
+ "python",
11
+ "/workload/workload.py",
12
+ "--device",
13
+ "cpu",
14
+ "--variant",
15
+ "correct"
16
+ ]
17
+ },
18
+ "candidate": {
19
+ "image": "docker.io/library/python:3.12-slim",
20
+ "command": [
21
+ "python",
22
+ "/workload/workload.py",
23
+ "--device",
24
+ "cpu",
25
+ "--variant",
26
+ "crash"
27
+ ]
28
+ },
29
+ "workload_file": "workload.py",
30
+ "fixture_file": "fixtures.json",
31
+ "repeats": 3,
32
+ "timeout_seconds": 60,
33
+ "memory_mb": 512,
34
+ "cpus": 2,
35
+ "policy": {
36
+ "min_throughput_ratio": 0.8,
37
+ "max_latency_ratio": 1.3,
38
+ "max_abs_error": 1e-05,
39
+ "max_peak_memory_mb": 1024.0,
40
+ "max_failures": 0,
41
+ "min_samples": 100,
42
+ "max_timing_cv": 0.3
43
+ }
44
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "schema_version": 1,
3
+ "name": "CPU / Injected output regression",
4
+ "description": "Deliberately changes one probability by 0.05. A fault demonstration, not a discovered framework defect.",
5
+ "demonstration": true,
6
+ "device": "cpu",
7
+ "baseline": {
8
+ "image": "docker.io/library/python:3.12-slim",
9
+ "command": [
10
+ "python",
11
+ "/workload/workload.py",
12
+ "--device",
13
+ "cpu",
14
+ "--variant",
15
+ "correct"
16
+ ]
17
+ },
18
+ "candidate": {
19
+ "image": "docker.io/library/python:3.12-slim",
20
+ "command": [
21
+ "python",
22
+ "/workload/workload.py",
23
+ "--device",
24
+ "cpu",
25
+ "--variant",
26
+ "drift"
27
+ ]
28
+ },
29
+ "workload_file": "workload.py",
30
+ "fixture_file": "fixtures.json",
31
+ "repeats": 3,
32
+ "timeout_seconds": 60,
33
+ "memory_mb": 512,
34
+ "cpus": 2,
35
+ "policy": {
36
+ "min_throughput_ratio": 0.8,
37
+ "max_latency_ratio": 1.3,
38
+ "max_abs_error": 1e-05,
39
+ "max_peak_memory_mb": 1024.0,
40
+ "max_failures": 0,
41
+ "min_samples": 100,
42
+ "max_timing_cv": 0.3
43
+ }
44
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "schema_version": 1,
3
+ "name": "CPU / Incomplete output coverage",
4
+ "description": "Deliberately omits a fixture case. Incomplete evidence cannot qualify a release.",
5
+ "demonstration": true,
6
+ "device": "cpu",
7
+ "baseline": {
8
+ "image": "docker.io/library/python:3.12-slim",
9
+ "command": [
10
+ "python",
11
+ "/workload/workload.py",
12
+ "--device",
13
+ "cpu",
14
+ "--variant",
15
+ "correct"
16
+ ]
17
+ },
18
+ "candidate": {
19
+ "image": "docker.io/library/python:3.12-slim",
20
+ "command": [
21
+ "python",
22
+ "/workload/workload.py",
23
+ "--device",
24
+ "cpu",
25
+ "--variant",
26
+ "missing"
27
+ ]
28
+ },
29
+ "workload_file": "workload.py",
30
+ "fixture_file": "fixtures.json",
31
+ "repeats": 3,
32
+ "timeout_seconds": 60,
33
+ "memory_mb": 512,
34
+ "cpus": 2,
35
+ "policy": {
36
+ "min_throughput_ratio": 0.8,
37
+ "max_latency_ratio": 1.3,
38
+ "max_abs_error": 1e-05,
39
+ "max_peak_memory_mb": 1024.0,
40
+ "max_failures": 0,
41
+ "min_samples": 100,
42
+ "max_timing_cv": 0.3
43
+ }
44
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "schema_version": 1,
3
+ "name": "CPU / Injected performance regression",
4
+ "description": "Deliberately sleeps during inference. Actual timing is measured; the slowdown is intentional.",
5
+ "demonstration": true,
6
+ "device": "cpu",
7
+ "baseline": {
8
+ "image": "docker.io/library/python:3.12-slim",
9
+ "command": [
10
+ "python",
11
+ "/workload/workload.py",
12
+ "--device",
13
+ "cpu",
14
+ "--variant",
15
+ "correct"
16
+ ]
17
+ },
18
+ "candidate": {
19
+ "image": "docker.io/library/python:3.12-slim",
20
+ "command": [
21
+ "python",
22
+ "/workload/workload.py",
23
+ "--device",
24
+ "cpu",
25
+ "--variant",
26
+ "slow"
27
+ ]
28
+ },
29
+ "workload_file": "workload.py",
30
+ "fixture_file": "fixtures.json",
31
+ "repeats": 3,
32
+ "timeout_seconds": 60,
33
+ "memory_mb": 512,
34
+ "cpus": 2,
35
+ "policy": {
36
+ "min_throughput_ratio": 0.8,
37
+ "max_latency_ratio": 1.3,
38
+ "max_abs_error": 1e-05,
39
+ "max_peak_memory_mb": 1024.0,
40
+ "max_failures": 0,
41
+ "min_samples": 100,
42
+ "max_timing_cv": 0.3
43
+ }
44
+ }