feat(review): mark unauthored mini-requirements as non-compliant in the plan section

Stage-3 Lever C (Stage-1): the composer already returns plan.concise.text === null
iff the mini-requirements are not authored. The SliceReviewTab plan section now
names that non-compliance honestly — a static, non-interactive attention marker
(testid plan-mini-reqs-noncompliant, copy "Not compliant · mini-requirements not
authored", the existing amber attention styling) — in place of the terse
"— not planned yet" dash, in the SAME text===null branch.

Presentation-only: renders in every phase (no phase gate), suppresses no sibling
(media / locked set / plan-lock all render as before), adds no state/fetch/control/
abstraction, and changes no composer or data contract. "Visible does not block."

Tests (flagship-review-polish.test.tsx): the marker renders for post-intent and
intent-phase null-text (the no-phase-gate pin), stays absent for authored text
(Markdown renders), and — with media + locked siblings — renders alongside both
while the marker element itself carries no interactive descendants (scoped to the
marker; locked-set EvidenceOpeners remain valid controls).

Carried caveat (pre-existing, unrelated, NOT touched): the mission-status-reconcile
"named RED at base" failure (partitionProjectMissions bucketing) is independent of
this review-plan-section change.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
v-openrig-buildandClaude Opus 4.8 committed 2026-07-23 03:24:44 +00:00
1 parent c42c587914
commit 1a8e56edbe
2 files changed
+68 -1

No files matched your search

@@ -297,7 +297,13 @@ export function SliceReviewTab({
{data.plan.concise.text ? (
<MarkdownViewer content={data.plan.concise.text} hideFrontmatter hideRawToggle />
) : (
<p className="font-mono text-[11px] text-on-surface-variant">— not planned yet</p>
// Stage-3 Lever C (Stage-1): the composer already returned text===null iff the
// mini-requirements are not authored — name that non-compliance honestly (a
// static, non-interactive attention marker) instead of the terse dash. Renders
// in every phase; presentation-only, suppresses no sibling.
<p data-testid="plan-mini-reqs-noncompliant" className="font-mono text-[11px] text-amber-700 dark:text-amber-400">
Not compliant · mini-requirements not authored
</p>
)}
{data.plan.concise.media.length > 0 ? (
<div className="flex flex-wrap gap-3">
@@ -274,4 +274,65 @@ describe("flagship attempt-0003 Review polish", () => {
expect(header.textContent).toContain("completion ledger");
expect(within(header).getByTestId("cut-complete").textContent).toContain("cut-gating COMPLETE");
});
// ===================================================================
// STAGE-3 LEVER C (Stage-1) — "not compliant: mini-reqs" render marker.
// REV3 d9fa8a2e §5. TEST-ONLY: RED-1/RED-2/RED-3 fail because the marker
// element (testid plan-mini-reqs-noncompliant) does not exist yet; the
// compliant companion is GREEN today. The marker renders whenever
// data.plan.concise.text === null, in EVERY phase (D1: NO phase gate),
// presentation-only; copy is FROZEN (D2). They become regression pins when
// the marker lands (a SEPARATE Guard-gated GREEN dispatch on SliceReviewTab).
// ===================================================================
const MARKER_TID = "plan-mini-reqs-noncompliant";
const MARKER_COPY = "Not compliant · mini-requirements not authored";
const planNull = { concise: { text: null, media: [] }, lockedArtifacts: [], lock: null, ssotPath: null };
const renderSlice = () => render(withQuery(<SliceReviewTab sliceName="04-review-tab-observability" slicePath={null} />));
it("LeverC RED-1 (post-intent non-compliance): phase=spec + plan.concise.text===null renders the frozen marker with exact copy", () => {
sliceState.data = sliceReview({ phase: "spec", plan: planNull } as Partial<ComposedSliceReview>);
renderSlice();
const marker = screen.getByTestId(MARKER_TID); // <-- RED: marker element absent (writer unbuilt)
expect(marker.textContent).toBe(MARKER_COPY);
});
it("LeverC RED-2 (intent no-gate PIN, D1): phase=intent + text===null renders the SAME marker — no phase gate suppresses it", () => {
sliceState.data = sliceReview({ phase: "intent", plan: planNull } as Partial<ComposedSliceReview>);
renderSlice();
const marker = screen.getByTestId(MARKER_TID); // <-- RED: marker element absent
expect(marker.textContent).toBe(MARKER_COPY);
});
it("LeverC GREEN companion (compliant): authored plan text renders Markdown and NO marker", () => {
sliceState.data = sliceReview({
phase: "spec",
plan: { concise: { text: "1. Author the mini-requirements", media: [] }, lockedArtifacts: [], lock: null, ssotPath: null },
} as Partial<ComposedSliceReview>);
renderSlice();
const planSection = screen.getByTestId("plan-section");
expect(within(planSection).queryByTestId(MARKER_TID)).toBeNull(); // compliant -> no marker
expect(within(planSection).getByTestId("markdown-viewer")).toBeTruthy(); // the authored plan renders
});
it("LeverC RED-3 (preservation + MARKER-SCOPED non-interactive): text===null WITH media + locked siblings renders the marker AND both siblings; the marker element itself is non-interactive", () => {
sliceState.data = sliceReview({
plan: {
concise: { text: null, media: [{ kind: "video", src: "data:video/mp4;base64,AAAA", caption: "plan clip" }] },
lockedArtifacts: [{ name: "Implementation PRD", path: "IMPLEMENTATION-PRD.md", kind: "spec" }],
lock: null,
ssotPath: null,
},
} as Partial<ComposedSliceReview>);
renderSlice();
const marker = screen.getByTestId(MARKER_TID); // <-- RED: marker element absent
expect(marker.textContent).toBe(MARKER_COPY);
// both plan-section siblings still render (the marker suppresses nothing).
expect(screen.getByTestId("review-inline-video")).toBeTruthy(); // media sibling
expect(screen.getByTestId("plan-locked-set")).toBeTruthy(); // locked-set sibling
// non-interactive oracle SCOPED TO THE MARKER ELEMENT ONLY (locked-set EvidenceOpeners are valid controls).
expect(["A", "BUTTON"]).not.toContain(marker.tagName);
expect(marker.getAttribute("role")).not.toBe("button");
expect(marker.getAttribute("role")).not.toBe("link");
expect(marker.querySelectorAll("a, button, input, select, textarea, [role='button'], [role='link']").length).toBe(0);
});
});