From aa3f850ad89cff76e05959cd674a979eba2be190 Mon Sep 17 00:00:00 2001
From: anthonybyrnes <150540200+AJBcoding@users.noreply.github.com>
Date: Tue, 5 May 2026 00:14:19 -0700
Subject: [PATCH 01/12] =?UTF-8?q?acceptance:=20add=20English=20MA=20(CIP?=
=?UTF-8?q?=2023.01,=20n=3D29,=20-4.97%)=20=E2=80=94=20REV-2=20third=20CSU?=
=?UTF-8?q?LB=20direct-fail=20(cp-j0gw.1)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Per REV-2 narrative correction (cp-fiq8.2.2, 2026-05-03), AHEAD's
published per-cell flag override surfaces English MA as the third
CSULB direct-fail beyond Music MM and Art MFA. Fixture data was
already present (rows 1380-1398); test now asserts:
- verdict = FAIL (PPD-published, agrees with tool re-derivation)
- cohort_count = 29
- ep_gap_pct = -0.0497 (inside ±15% R19 noise band)
- R08 (graduate lowest-of-three) fires
- R18 (graduate loan-cap advisory) fires
- R19 (noise band) fires with gap_tool_derived provenance
Source: analyses/csulb-impact-passes/narrative.md REV-2;
senate-distribution-2026-05-04 packet.
11/11 acceptance tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
tests/acceptance.test.ts | 33 +++++++++++++++++++++++++++++++--
1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/tests/acceptance.test.ts b/tests/acceptance.test.ts
index 7431c22..85213c9 100644
--- a/tests/acceptance.test.ts
+++ b/tests/acceptance.test.ts
@@ -1,9 +1,12 @@
// Acceptance — reproduces dean memo v10 §1 numbers from the CSULB fixture.
//
// Source: briefs/2026-04-23-dean-royce-OBBBA-EP-synthesis.v10.md §1 bottom-line.
+// Extension (cp-j0gw.1): English MA per REV-2 narrative correction (cp-fiq8.2.2,
+// 2026-05-03) — third CSULB direct-fail surfaced after AHEAD-flag-override fix.
//
-// Music MM (5009/Master's): FAIL @ -32.65%, n=28
-// Art MFA (5007/Master's): FAIL @ -20.40%, n=23
+// Music MM (5009/Master's): FAIL @ -32.65%, n=28
+// Art MFA (5007/Master's): FAIL @ -20.40%, n=23
+// English MA (2301/Master's): FAIL @ -4.97%, n=29 (cp-j0gw.1, REV-2)
// Theatre BA (5005/Bachelor): PASS @ +6.06%, n=81 — within R19 noise band
// Cinematic Arts BA (5006/Bach): NOT MEASURED (B16 invisibility — absent from PPD)
@@ -47,6 +50,32 @@ describe('Acceptance — dean memo v10 §1', () => {
expect(v?.rules_fired.map((r) => r.id)).toContain('R17');
});
+ it('English MA (2301/Master\'s) — FAIL at -4.97%, n=29 (REV-2 cp-j0gw.1)', () => {
+ // REV-2 narrative correction (cp-fiq8.2.2, 2026-05-03): the AHEAD-published
+ // per-cell flag override surfaces this as the third CSULB direct-fail. Gap
+ // is small (-4.97%) but PPD-published verdict is authoritative — falls
+ // OUTSIDE the noise band trigger range only because PPD asserts FAIL.
+ // Source: analyses/csulb-impact-passes/narrative.md REV-2; senate packet
+ // briefs/senate-distribution-2026-05-04/.
+ const v = find('2301', "Master's");
+ expect(v).toBeDefined();
+ expect(v?.verdict).toBe('FAIL');
+ expect(v?.cohort_count).toBe(29);
+ expect(v?.median_earn_p4).toBe(47026.0);
+ expect(v?.benchmark).toBe(49483.0);
+ expect(v?.ep_gap_pct).toBeCloseTo(-0.0497, 4);
+ // PPD-published agrees with tool re-derivation (both FAIL).
+ expect(v?.cross_validation.status).toBe('agree');
+ // R08 fires — graduate lowest-of-three benchmark route.
+ expect(v?.rules_fired.map((r) => r.id)).toContain('R08');
+ // R18 fires — graduate loan-cap advisory.
+ expect(v?.rules_fired.map((r) => r.id)).toContain('R18');
+ // R19 fires — gap is INSIDE ±15% noise band; verdict could read other way
+ // on the same data with privacy noise.
+ expect(v?.noise_band.fired).toBe(true);
+ expect(v?.noise_band.provenance).toBe('gap_tool_derived');
+ });
+
it('Theatre BA (5005/Bachelor) — PASS at +6.06%, n=81, in R19 noise band', () => {
const v = find('5005', 'Bachelor');
expect(v).toBeDefined();
From 6d9a478fcba8ce085898162fa39879e16291e8a8 Mon Sep 17 00:00:00 2001
From: anthonybyrnes <150540200+AJBcoding@users.noreply.github.com>
Date: Tue, 5 May 2026 00:18:02 -0700
Subject: [PATCH 02/12] disclaimers: forward-simulation framing + 'not
attorneys/legislative analysts' (cp-j0gw.3 + cp-j0gw.6)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Two new IntegrityEnvelope fields surface as load-bearing context:
1. simulation_framing (cp-j0gw.3, per cp-dw65) — every verdict is a
FORWARD SIMULATION on AHEAD's PPD:2026 negotiator analytic file,
not an observation of the implemented rule. First STATS release
scheduled for 2027-07-01.
2. expertise_disclaimer (cp-j0gw.6) — explicit 'not attorneys, not
legislative analysts' framing with 'Independently verify all
numbers and citations against primary sources' instruction.
Surfaced via:
- src/citations.ts: SIMULATION_FRAMING + EXPERTISE_DISCLAIMER constants
- src/types.ts: IntegrityEnvelope.simulation_framing + .expertise_disclaimer
- src/engine.ts: populated in buildIntegrityEnvelope
- src/api/schema.ts: required JSON-schema fields
- web/index.html, persona-a.html, persona-b.html: new top-disclaimer
aside above main content (yellow callout, dark-mode adapted)
- web/css/main.css: .top-disclaimer styling
Recipe block (per-finding 'How to reproduce' — second half of D6) lands
in a follow-up commit. 200/200 tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
src/api/schema.ts | 4 ++++
src/citations.ts | 17 +++++++++++++++++
src/engine.ts | 8 +++++++-
src/types.ts | 12 ++++++++++++
tests/acceptance.test.ts | 12 ++++++++++++
web/css/main.css | 28 ++++++++++++++++++++++++++++
web/index.html | 12 ++++++++++++
web/persona-a.html | 11 +++++++++++
web/persona-b.html | 11 +++++++++++
9 files changed, 114 insertions(+), 1 deletion(-)
diff --git a/src/api/schema.ts b/src/api/schema.ts
index 8f370ba..0f2c25b 100644
--- a/src/api/schema.ts
+++ b/src/api/schema.ts
@@ -191,6 +191,8 @@ const $defs = {
'cross_validation_disagreements',
'data_status_summary',
'primary_source_reminder',
+ 'simulation_framing',
+ 'expertise_disclaimer',
],
additionalProperties: false,
properties: {
@@ -217,6 +219,8 @@ const $defs = {
},
},
primary_source_reminder: { type: 'string' },
+ simulation_framing: { type: 'string' },
+ expertise_disclaimer: { type: 'string' },
},
},
AnalysisResultBase: {
diff --git a/src/citations.ts b/src/citations.ts
index 5e8a73c..c736c5a 100644
--- a/src/citations.ts
+++ b/src/citations.ts
@@ -99,3 +99,20 @@ export const M_DOCS = {
/** Footer reminder rendered on every result page per spec §1.4. */
export const PRIMARY_SOURCE_REMINDER =
'Re-derive against primary sources before any external submission.';
+
+/**
+ * Forward-simulation framing per cp-dw65 (cp-j0gw.3). Every EP-test verdict
+ * surfaced by this tool is a SIMULATION run against AHEAD's negotiator
+ * analytic file (PPD:2026), not an observation of the implemented rule. The
+ * first official STATS earnings-premium release is scheduled for 2027-07-01.
+ */
+export const SIMULATION_FRAMING =
+ 'FORWARD SIMULATION — verdicts shown here are computed on the PPD:2026 negotiator analytic file. The first official STATS earnings-premium release is scheduled for 2027-07-01. Conditional on AHEAD-published projections holding.';
+
+/**
+ * Expertise disclaimer per cp-j0gw.6. We are not attorneys and not legislative
+ * analysts. Findings derive from publicly available data; verify against
+ * primary sources before any external use.
+ */
+export const EXPERTISE_DISCLAIMER =
+ 'This tool is built by educators, not attorneys or legislative analysts. Every finding is derived from publicly available federal data using the rules engine documented in this repo. Independently verify all numbers and citations against the primary sources before any external submission, public comment, or institutional decision.';
diff --git a/src/engine.ts b/src/engine.ts
index 40c72cd..1e6f872 100644
--- a/src/engine.ts
+++ b/src/engine.ts
@@ -16,7 +16,11 @@ import type {
VerdictWord,
} from './types.js';
import { CITATIONS, M_DOCS } from './citations.js';
-import { PRIMARY_SOURCE_REMINDER } from './citations.js';
+import {
+ EXPERTISE_DISCLAIMER,
+ PRIMARY_SOURCE_REMINDER,
+ SIMULATION_FRAMING,
+} from './citations.js';
import {
RULES,
RULE_ORDER,
@@ -163,6 +167,8 @@ function buildIntegrityEnvelope(
out_of_scope,
},
primary_source_reminder: PRIMARY_SOURCE_REMINDER,
+ simulation_framing: SIMULATION_FRAMING,
+ expertise_disclaimer: EXPERTISE_DISCLAIMER,
};
}
diff --git a/src/types.ts b/src/types.ts
index 825e0c4..22dd40e 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -206,6 +206,18 @@ export interface IntegrityEnvelope {
out_of_scope: number;
};
primary_source_reminder: string;
+ /**
+ * "Forward simulation" framing per cp-dw65 (cp-j0gw.3). All EP-test verdicts
+ * here are SIMULATIONS run on AHEAD's negotiator analytic file (PPD:2026),
+ * not observations of an implemented rule. The first official STATS earnings-
+ * premium release is scheduled for 2027-07-01.
+ */
+ simulation_framing: string;
+ /**
+ * "Not attorneys / not legislative analysts" disclaimer per cp-j0gw.6.
+ * Surfaced on every result page in addition to the primary-source reminder.
+ */
+ expertise_disclaimer: string;
}
export interface PanelDescriptor {
diff --git a/tests/acceptance.test.ts b/tests/acceptance.test.ts
index 85213c9..5a9482d 100644
--- a/tests/acceptance.test.ts
+++ b/tests/acceptance.test.ts
@@ -144,6 +144,18 @@ describe('Acceptance — dean memo v10 §1', () => {
expect(result.integrity_envelope.cross_validation_disagreements).toBe(0);
});
+ it('integrity envelope surfaces simulation framing (cp-j0gw.3)', () => {
+ expect(result.integrity_envelope.simulation_framing).toMatch(/FORWARD SIMULATION/);
+ expect(result.integrity_envelope.simulation_framing).toMatch(/PPD:2026/);
+ expect(result.integrity_envelope.simulation_framing).toMatch(/2027-07-01/);
+ });
+
+ it('integrity envelope surfaces expertise disclaimer (cp-j0gw.6)', () => {
+ expect(result.integrity_envelope.expertise_disclaimer).toMatch(/not attorneys/i);
+ expect(result.integrity_envelope.expertise_disclaimer).toMatch(/not.*legislative analysts/i);
+ expect(result.integrity_envelope.expertise_disclaimer).toMatch(/Independently verify/i);
+ });
+
it('footer reminder is present on every result page', () => {
expect(result.footer_reminder).toBe(
'Re-derive against primary sources before any external submission.',
diff --git a/web/css/main.css b/web/css/main.css
index 193d0f8..9463e84 100644
--- a/web/css/main.css
+++ b/web/css/main.css
@@ -161,6 +161,34 @@ main {
margin: 0;
}
+/* ─── Top disclaimer (cp-j0gw.6) ─────────────────────────────────────── */
+
+.top-disclaimer {
+ background: #fff8e6;
+ border-left: 4px solid #c08a00;
+ padding: var(--space-sm) var(--space-md);
+ margin: 0 var(--space-md) var(--space-md);
+ border-radius: 4px;
+ font-size: 0.95rem;
+ line-height: 1.45;
+}
+
+.top-disclaimer p {
+ margin: 0;
+}
+
+.top-disclaimer strong {
+ font-weight: 700;
+}
+
+@media (prefers-color-scheme: dark) {
+ .top-disclaimer {
+ background: #2a2410;
+ border-left-color: #d6a400;
+ color: #f4e8c2;
+ }
+}
+
/* ─── Landing page ───────────────────────────────────────────────────── */
.persona-card {
diff --git a/web/index.html b/web/index.html
index a1f6dac..8c1ef80 100644
--- a/web/index.html
+++ b/web/index.html
@@ -19,6 +19,18 @@ CSU Deans EP Tool
+
+
Which view do you need?
diff --git a/web/persona-a.html b/web/persona-a.html
index 2a71a34..532b93e 100644
--- a/web/persona-a.html
+++ b/web/persona-a.html
@@ -12,6 +12,17 @@
Check specific programs
+
+