-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsubmit-validation.html
More file actions
336 lines (316 loc) · 21.5 KB
/
Copy pathsubmit-validation.html
File metadata and controls
336 lines (316 loc) · 21.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
<!DOCTYPE html>
<html lang="en">
<head>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NVYHJ7BJ92"></script>
<script>
// STUDY CLOSURE 2026-08-21, SCOPED BY CONTRIBUTOR RATHER THAN WHOLESALE.
//
// The owner closed the validation studies but kept the public-records study
// open, because a reviewer holds a live link to submit cases against it. This
// page serves BOTH real-case domains and writes them to the same table, so a
// blanket close here would have shut the one study meant to stay open.
//
// OPEN_CONTRIBUTORS is the allowlist. A code on it submits normally. Every
// other code, and a missing code, is refused with the closure notice. Closing
// the public-records study later means emptying this array; no other change.
//
// This is a front-door close. The page writes straight to the REST API with the
// anon key, so it stops the reviewer who opens the page, not a direct POST.
// api/_study-status.js records the database revoke that would make it absolute.
var OPEN_CONTRIBUTORS = ['E-08'];
var CLOSED_AT = '21 August 2026';
function studyOpenFor(code){
return OPEN_CONTRIBUTORS.indexOf(String(code || '').trim().toUpperCase()) >= 0;
}
window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','G-NVYHJ7BJ92');</script>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex,nofollow">
<title>Submit a Validated Case | JRS</title>
<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Bodoni+Moda:wght@400;500&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
:root{--bg:#050505;--surface:#121212;--surface2:#1A1A1A;--rule:#2A2A2A;--text:#F2F2F2;--muted:#B3B3B3;--muted-soft:#8A8A8A;--accent:#BE9447;--accent-dim:#7A5E28;--ready-text:#5DBF82;--review-text:#D4A055;--stop-text:#E88080}
html,body{background:var(--bg);color:var(--text);font-family:'Inter',sans-serif;line-height:1.6;-webkit-font-smoothing:antialiased}
.wrap{max-width:720px;margin:0 auto;padding:0 20px}
.hd{border-bottom:1px solid var(--rule);padding:16px 20px}
.hd-in{max-width:720px;margin:0 auto;display:flex;justify-content:space-between;align-items:center}
.wm{font-family:'Bodoni Moda',serif;font-size:22px;color:var(--accent);text-decoration:none}
.meta{font-family:'JetBrains Mono',monospace;font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted-soft)}
h1{font-family:'Bodoni Moda',serif;font-weight:400;font-size:27px;margin:24px 0 8px}
.sub{font-size:14px;color:var(--muted);max-width:640px;margin-bottom:8px}
.f{display:block;font-family:'JetBrains Mono',monospace;font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--accent-dim);margin:16px 0 6px}
input,select,textarea{width:100%;background:var(--surface);border:1px solid var(--rule);color:var(--text);font-family:'Inter',sans-serif;font-size:14px;padding:11px 12px}
textarea{min-height:140px;resize:vertical;line-height:1.6}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--accent-dim)}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:12px}
@media(max-width:560px){.row2{grid-template-columns:1fr}}
.hint{font-size:11.5px;color:var(--muted-soft);margin-top:4px}
.btn{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.14em;text-transform:uppercase;padding:13px 18px;border:1px solid var(--accent);color:var(--accent);background:none;cursor:pointer}
.btn.solid{background:var(--accent);color:#050505;font-weight:600}
.status{font-family:'JetBrains Mono',monospace;font-size:11px;margin-left:10px}
.note{font-size:12.5px;color:var(--muted-soft);line-height:1.6;border-left:2px solid var(--rule);padding:12px 15px;background:var(--surface);margin:14px 0}
.note b{color:var(--text)}
.warn{border-left-color:var(--review-text)}
.ft{border-top:1px solid var(--rule);padding:18px 20px;margin-top:26px;font-family:'JetBrains Mono',monospace;font-size:9px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted-soft)}
.elig{border:1px solid var(--accent-dim);background:rgba(190,148,71,.06);padding:14px 16px;margin:16px 0}
.elig-h{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--accent);margin-bottom:8px}
.elig-lead{font-size:13px;color:var(--text);margin-bottom:11px;line-height:1.6}
.elig-item{display:grid;grid-template-columns:24px 1fr;gap:10px;align-items:start;margin-bottom:9px;font-size:13px;color:var(--muted);line-height:1.55}
.elig-item b{color:var(--text)}
.elig-n{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--accent);background:var(--surface2);border:1px solid var(--rule);width:22px;height:22px;display:flex;align-items:center;justify-content:center}
.elig-foot{font-size:12px;color:var(--review-text);margin-top:8px;line-height:1.55}
</style>
</head>
<body>
<div id="studies-closed" style="display:none;background:#1A1A1A;color:#D4A055;border:1px solid #7A5E28;padding:14px 16px;margin:14px auto;max-width:900px;line-height:1.6;font-size:14px"><strong>This study is closed.</strong> The validation studies stopped accepting cases on 21 August 2026. Nothing submitted from this page will be recorded. Thank you to everyone who took part. Questions: <a href="mailto:info@jrsstandard.com" style="color:#BE9447">info@jrsstandard.com</a></div>
<header class="hd"><div class="hd-in"><a href="/" class="wm">JRS<span style="font-size:9px;vertical-align:super">™</span></a><div class="meta">Validation · Rung 3</div></div></header>
<main><div class="wrap">
<h1>Submit a Validated Case</h1>
<p class="sub">Rung 3 (validation) tests whether a JRS verdict predicts what actually happened to a record when it was challenged. Each case pairs a de-identified record with its <b>documented real-world outcome</b>, so we can compare the JRS read against reality.</p>
<p class="sub" style="margin-top:8px"><b style="color:var(--text)">How many to aim for:</b> a first set of 5 cases, then 20 to 30 in total, entered in small batches over time. There is no need to do them all at once; submit each case as you complete it.</p>
<div class="elig">
<div class="elig-h">Quick eligibility check · read before you start</div>
<p class="elig-lead">A case belongs in this study only if you can answer <b>yes</b> to all three questions. If any answer is no, do not enter it.</p>
<div class="elig-item"><span class="elig-n">1</span><div><b>Is it public?</b> A published decision, opinion, ruling, or award that anyone could look up. Never an internal company file, even with the names removed.</div></div>
<div class="elig-item"><span class="elig-n">2</span><div><b>Does it show the record?</b> The decision quotes the actual record, or the part that mattered: a termination, a write-up, an investigation note, a determination.</div></div>
<div class="elig-item"><span class="elig-n">3</span><div><b>Is the outcome written down?</b> The decision states what happened when the record was challenged: upheld, overturned, failed an audit, and so on.</div></div>
<p class="elig-foot">When in doubt, leave it out. Your own workplace records do not qualify, no matter how they are edited.</p>
</div>
<div class="note warn">
<b>Good public sources.</b> Published FOIL appeal determinations, Committee on Open Government opinions, Article 78 and other court rulings, labor arbitration awards, unemployment appeal decisions, EEOC determinations, audit findings, and administrative-hearing decisions where the record was quoted and the outcome is in writing. Remove all names, identifiers, and case numbers that are not part of a public citation.
</div>
<label class="f">The record (de-identified text)</label>
<textarea id="record" placeholder="Paste the de-identified record or the portion quoted in the public decision. No names, no identifying details."></textarea>
<div class="hint">20 to 8000 characters. This is screened for personal identifiers before it is sent.</div>
<div class="row2">
<div>
<label class="f">Domain</label>
<select id="domain">
<option value="">Select…</option>
<option>Public records / FOIL</option>
<option>HR / Employment</option>
<option>Industrial Relations / Labor</option>
<option>Compliance / Audit</option>
<option>Investigations</option>
<option>Due-process / Administrative</option>
<option>Legal / Litigation</option>
<option>Other</option>
</select>
</div>
<div>
<label class="f">JRS read (your assessment)</label>
<select id="jrs">
<option value="">Not assessed</option>
<option value="ready">Ready (reasoning reconstructable)</option>
<option value="review_required">Needs work (partly reconstructable)</option>
<option value="gap_identified">Gap (not reconstructable)</option>
</select>
</div>
</div>
<details style="margin:2px 0 4px;border:1px solid var(--rule);background:var(--surface2)">
<summary style="cursor:pointer;padding:10px 13px;font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--accent)">How to choose your read · the five JRS conditions</summary>
<div style="padding:0 14px 13px;font-size:12.5px;color:var(--muted);line-height:1.55">
<p style="margin:6px 0 8px">Ask one question: could a later reviewer reconstruct the reasoning from the record alone? Check these five, then pick the read that fits.</p>
<ol style="margin:0 0 9px 18px;padding:0">
<li style="margin-bottom:5px"><b style="color:var(--text)">Basis identification.</b> Does the record state the basis for its conclusions?</li>
<li style="margin-bottom:5px"><b style="color:var(--text)">Reasoning traceability.</b> Can you trace the reasoning from evidence to conclusion?</li>
<li style="margin-bottom:5px"><b style="color:var(--text)">Cold-reviewer clarity.</b> Would someone with no prior knowledge understand it from the record alone?</li>
<li style="margin-bottom:5px"><b style="color:var(--text)">Accountability support.</b> Are the decision-makers and reviewers identifiable?</li>
<li style="margin-bottom:5px"><b style="color:var(--text)">Temporal reconstructability.</b> Does it hold up read cold years later (dates, sequence, sources)?</li>
</ol>
<p style="margin:0"><b style="color:var(--ready-text)">Ready</b> if essentially all five hold · <b style="color:var(--review-text)">Needs work</b> if some hold but gaps remain · <b style="color:var(--stop-text)">Gap</b> if the reasoning cannot be reconstructed. Judge the record only, not whether the decision was right. Full detail: <a href="codebook.html" style="color:var(--accent)">the JRS Codebook</a>.</p>
</div>
</details>
<div class="row2">
<div>
<label class="f">Real-world outcome</label>
<select id="outcome">
<option value="">Select…</option>
<option value="held_up">Held up (record stood)</option>
<option value="challenged">Challenged but stood</option>
<option value="failed_appeal">Overturned / lost on appeal</option>
<option value="failed_audit">Failed audit / cited as a finding</option>
</select>
</div>
<div>
<label class="f">Your contributor code (required)</label>
<input id="code" placeholder="e.g. E-08">
</div>
</div>
<label class="f">Public source / citation (required)</label>
<input id="source" placeholder="e.g. NY COOG FOIL-AO-19xxx, or court/arbitration cite, with a link if available">
<div class="hint">A verifiable public reference for the outcome. This is what makes it validation rather than anecdote.</div>
<label class="f">Notes (optional, no identifiers)</label>
<textarea id="notes" style="min-height:80px" placeholder="What about the documentation decided the outcome? Keep it de-identified."></textarea>
<div style="margin-top:18px"><button class="btn solid" onclick="submitCase()">Submit case</button><span class="status" id="st" role="status" aria-live="polite"></span></div>
<div class="note">Submitted cases arrive as pending entries for de-identification review before they count toward Rung 3. Validation is domain-specific: a FOIL outcome speaks to records-access decisions, an HR outcome to employment records. Nothing here is published as proof until reviewed.</div>
</div></main>
<footer class="ft"><div class="wrap" style="padding:0">© 2026 Phillip Wikes · JRS™ · <a href="privacy.html" style="color:inherit">Privacy</a> · confidential · not indexed</div></footer>
<script>
var U='https://pjzxkeviouofdseagvpf.supabase.co', K='sb_publishable_mkdtg6-NgJ44_JVr9vZf6Q_30BVgY4e', HDR={'apikey':K,'Authorization':'Bearer '+K};
function val(id){var e=document.getElementById(id);return e?(e.value||'').trim():'';}
function jrsSanitizeCheck(text){
var patterns=[
{re:/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g, label:'email address'},
{re:/\b\d{3}[-.\s]?\d{3}[-.\s]?\d{4}\b/g, label:'phone number'},
{re:/\b\d{3}-\d{2}-\d{4}\b/g, label:'SSN'},
{re:/\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g, label:'card number'}
];
var found=[];
patterns.forEach(function(p){ if(p.re.test(text)) found.push(p.label); });
if(found.length){
return confirm('Potential sensitive identifier detected ('+found.join(', ')+'). Confirm all personally identifiable information has been redacted before submission to preserve work-product privileges.');
}
return true;
}
function submitCase(){
var st=document.getElementById('st');
var record=val('record'), domain=val('domain'), jrs=val('jrs'), outcome=val('outcome'), code=val('code'), source=val('source'), notes=val('notes');
if(record.length<20||record.length>8000){ st.textContent='Record must be 20 to 8000 characters.'; st.style.color='var(--stop-text)'; return; }
if(!outcome){ st.textContent='Select the real-world outcome.'; st.style.color='var(--stop-text)'; return; }
if(!source){ st.textContent='A public source/citation is required.'; st.style.color='var(--stop-text)'; return; }
if(!code){ st.textContent='Your contributor code is required. Use the personalized link you were sent, or contact info@jrsstandard.com.'; st.style.color='var(--stop-text)'; return; }
if(!studyOpenFor(code)){ st.textContent='This study closed on '+CLOSED_AT+' and is no longer accepting cases. Nothing was submitted. Please contact info@jrsstandard.com.'; st.style.color='var(--review-text)'; return; }
if(!jrsSanitizeCheck(record+' '+notes)) return;
st.textContent='Submitting…'; st.style.color='var(--muted-soft)';
var btn=document.querySelector('.btn.solid'); btn.disabled=true;
// Self-contained: the full case (record + paired outcome + source) is stored in one row.
var payload={record:record, domain:domain, jrs_read:jrs, outcome:outcome, source:source, contributor:code, note:notes, status:'pending_deid_review'};
fetch(U+'/rest/v1/bench_outcomes',{method:'POST',headers:Object.assign({'Content-Type':'application/json','Prefer':'return=minimal'},HDR),
body:JSON.stringify(payload)})
.then(function(r){ if(!r.ok) throw 0;
st.textContent='Recorded. Thank you, this case is pending de-identification review.'; st.style.color='var(--ready-text)';
['record','source','notes'].forEach(function(id){document.getElementById(id).value='';});
btn.disabled=false;
})
.catch(function(){
// Fail-safe: never lose the submitter's work if the server is unreachable.
var obj={type:'jrs-validation-case', record:record, domain:domain, jrs_read:jrs, outcome:outcome, source:source, contributor:code, notes:notes, timestamp:new Date().toISOString()};
try{
var blob=new Blob([JSON.stringify(obj,null,2)],{type:'application/json'});
var u=URL.createObjectURL(blob); var a=document.createElement('a'); a.href=u; a.download='jrs-validation-'+Date.now()+'.json';
document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(u);
st.textContent='Server unavailable. Case downloaded for manual submission to info@jrsstandard.com.';
}catch(e){ st.textContent='Server unavailable. Contact info@jrsstandard.com to submit your case.'; }
st.style.color='var(--review-text)'; btn.disabled=false;
});
}
// Pre-fill the domain and contributor code from the link (e.g. ?domain=hr&code=TP) for one-click setup.
(function(){
var q=new URLSearchParams(location.search);
var c=(q.get('code')||'').trim();
if(c){ var ce=document.getElementById('code'); if(ce) ce.value=c; }
// Show the closure notice unless this link belongs to a study still open.
if(!studyOpenFor(c)){
var nb=document.getElementById('studies-closed'); if(nb) nb.style.display='block';
var sb=document.querySelector('.btn.solid');
if(sb){ sb.disabled=true; sb.style.opacity='.45'; sb.style.cursor='not-allowed'; }
}
var p=(q.get('domain')||'').toLowerCase();
var map={foil:'Public records / FOIL','public-records':'Public records / FOIL',records:'Public records / FOIL',hr:'HR / Employment',employment:'HR / Employment',ir:'Industrial Relations / Labor',labor:'Industrial Relations / Labor','industrial-relations':'Industrial Relations / Labor',compliance:'Compliance / Audit',audit:'Compliance / Audit',investigations:'Investigations',legal:'Legal / Litigation'};
var v=map[p]; if(!v) return;
var s=document.getElementById('domain');
for(var i=0;i<s.options.length;i++){ if(s.options[i].text===v){ s.selectedIndex=i; break; } }
})();
</script>
<script>
/* JRS LINK-CLICK TELEMETRY. Added 2026-08-13. Token-less, no dependencies.
Posts to /api/telemetry, which is a real endpoint in this repository. */
/**
* Zero-Drift Telemetry Dispatcher
* Guarantees event delivery without delaying navigation or blocking the main thread.
*/
function trackClickAndNavigate(event, targetUrl, eventMetaData) {
eventMetaData = eventMetaData || {};
// 1. Prevent default immediate navigation
if (event && typeof event.preventDefault === 'function') {
event.preventDefault();
}
// 2. Construct immutable telemetry payload
var payload = JSON.stringify({
timestamp: new Date().toISOString(),
origin_url: window.location.href,
target_url: targetUrl,
meta: eventMetaData
});
// 3. Primary Dispatch: Non-blocking navigator.sendBeacon
var isDispatched = false;
if (typeof navigator !== 'undefined' && navigator.sendBeacon) {
var blob = new Blob([payload], { type: 'application/json' });
isDispatched = navigator.sendBeacon('/api/telemetry', blob);
}
// 4. Secondary Dispatch: Fetch API with keepalive flag
if (!isDispatched && typeof fetch === 'function') {
fetch('/api/telemetry', {
method: 'POST',
body: payload,
headers: { 'Content-Type': 'application/json' },
keepalive: true
}).catch(function() {
/* Swallowing non-critical network drops to prioritize UX */
});
}
// 5. Deterministic Fail-safe Navigation Fallback (150ms timeout)
setTimeout(function() {
window.location.href = targetUrl;
}, 150);
}
/* DELEGATION LAYER.
One document-level listener, so links rendered by JavaScript after load are
captured too and no per-link handler is needed anywhere.
It decides WHEN to call the dispatcher. It does not alter it.
Three classes of link are deliberately NOT routed through the dispatcher:
- /api/dl and /api/support already count inside their own 302. A redirect
cannot be blocked or raced, so it is strictly stronger than a beacon and
routing them here would double-count.
- mailto, tel, in-page anchors and downloads are not navigations to count.
- modifier and middle clicks. preventDefault on those would break "open in
new tab", so the beacon is sent WITHOUT preventDefault and the browser is
left to do what the reader asked for. */
(function(){
var COUNTED_SERVER_SIDE = /^\/api\/(dl|support)\b/;
function beacon(target, meta){
try {
var payload = JSON.stringify({
timestamp: new Date().toISOString(),
origin_url: window.location.href,
target_url: target,
meta: meta || {}
});
var sent = false;
if (navigator.sendBeacon) {
sent = navigator.sendBeacon('/api/telemetry', new Blob([payload], { type: 'application/json' }));
}
if (!sent && typeof fetch === 'function') {
fetch('/api/telemetry', { method: 'POST', body: payload,
headers: { 'Content-Type': 'application/json' }, keepalive: true }).catch(function(){});
}
} catch (e) { /* never let telemetry break a click */ }
}
document.addEventListener('click', function(ev){
try {
var a = ev.target && ev.target.closest ? ev.target.closest('a[href]') : null;
if (!a) return;
var href = a.getAttribute('href') || '';
if (!href || href.charAt(0) === '#') return;
if (/^(mailto:|tel:|javascript:)/i.test(href)) return;
if (a.hasAttribute('download')) return;
if (COUNTED_SERVER_SIDE.test(href)) return;
var label = (a.textContent || '').replace(/\s+/g, ' ').trim().slice(0, 80);
var meta = { label: label, src: 'link' };
// Modifier or middle click: the reader wants a new tab. Record it, do not
// hijack it.
if (ev.metaKey || ev.ctrlKey || ev.shiftKey || ev.altKey || ev.button !== 0) {
beacon(a.href, meta);
return;
}
if (a.target && a.target !== '_self') { beacon(a.href, meta); return; }
trackClickAndNavigate(ev, a.href, meta);
} catch (e) { /* a telemetry fault must never block navigation */ }
}, true);
})();
</script>
</body>
</html>