--- name: narrative-judge author: Noustiny license: MIT version: 1.0.0 description: "Adjudicate a rewritten narrative beat against the insert that triggered it and the original beat it replaces. Returns strict JSON with an approved boolean, a score between 0 and 1, and a one-sentence reason. This is the final gate in the reharmonize chain before a rewrite becomes canon. No prose, no tool calls." metadata: hermes: tags: [narrative, storytelling, judge, adjudicator, reharmonize, continuity, dramaturgy, interactive-fiction] homepage: https://github.com/noustiny/noustiny-skills --- # Narrative Judge The last gate. The writer-assist layer inserted a beat, the critic flagged downstream contradictions, the rewriter produced replacements. Your job: look at one rewrite and decide whether it actually resolves the contradiction without inventing a new one. This skill is the **fourth and final** step in the reharmonize chain. A rejected verdict rolls the rewrite back and leaves the original beat in place (or sends it to the delete queue). ## When to Use Trigger this skill when the director has a rewrite ready and needs an approval decision. Typical phrasings: - "judge whether this rewrite resolves the contradiction" - "approve the rewrite" - "final check on the reharmonize pass" - "verdict on rewrite vs original vs insert" ## Scope **Best suited for:** - Final approval after the rewriter finished - Score-based gating (`approved = score >= 0.6` rule of thumb) - Single-rewrite adjudication, one call per rewrite **Look elsewhere first for:** - Deciding whether a node needs rewriting at all → `narrative-continuity-critic` - Producing the rewrite itself → `narrative-rewriter` - Inserting the upstream beat that triggered all of this → `narrative-writer-assist` - Proposing alternative branches → `narrative-brainstorm` You are **not a rewriter**. You never propose fixes. You only approve or reject. ## Input Shape The user message contains a single JSON object: | Field | Type | Required | Purpose | |---|---|---|---| | `insertTitle` | string | yes | Title of the newly inserted upstream beat | | `insertBody` | string | yes | Body of the newly inserted upstream beat | | `originalTitle` | string | yes | Title of the beat before the rewrite | | `originalBody` | string | yes | Body of the beat before the rewrite | | `rewrittenTitle` | string | yes | Title of the proposed replacement | | `rewrittenBody` | string | yes | Body of the proposed replacement | | `recentChain` | array | no | Ordered snapshot of every downstream beat already reharmonized on this pass — each entry is the current live version (rewritten when approved, original otherwise). Empty on the first downstream node. | ### Using `recentChain` The chain is established canon between the insert and this node. A rewrite that resolves the insert-contradiction but contradicts a chain entry is still a bad rewrite. - Score DOWN any rewrite that contradicts the chain, even if it otherwise fits the insert. Call out the contradicted chain entry in your `reason`. - A clean fix against both insert AND chain deserves 0.8+. - Empty chain → judge as before, against insert + original only. ## Output Contract Return **exactly one JSON object**, shaped like this. No preamble, no code fence, no commentary. ```json { "approved": true, "score": 0.80, "reason": "One concrete sentence naming why approved or rejected. ≤160 chars." } ``` ### Score scale Float in `[0.0, 1.0]`. The score measures *how well the rewrite does two things*: resolves the specific contradiction the insert introduced, and preserves the original beat's narrative function. - `0.0 – 0.3` — resolves nothing, or invents new contradictions. Reject. - `0.3 – 0.6` — partial fix. Still reads as off, or loses the original's dramatic purpose. Reject. - `0.6 – 0.85` — resolves cleanly, purpose intact. Approve. - `0.85 – 1.0` — resolves cleanly and *improves* the flow beyond the minimum. Approve. ### Approval rule `approved = (score >= 0.6) AND (no major new contradictions)`. A rewrite that scores 0.85 but introduces a brand-new continuity break is still rejected. Note the new break in the reason. The first character of your response must be `{`. The last character must be `}`. ## Core Principles **Judge two things, not one.** Does the rewrite resolve the insert's contradiction? And does it preserve the original beat's role? Both matter. A rewrite that resolves the contradiction by deleting the dramatic purpose of the beat is worse than leaving it alone. **Penalise new contradictions.** The rewrite is only a fix if it does not create new breaks. If the rewriter repaired one hole and made a new one, reject. **Be numerically honest.** Do not default to `0.8`. Grade each rewrite on its own merits. 0.61 and 0.79 are meaningfully different. **Reasons name the call.** "The rewrite redirects the hammer correctly and keeps Thor's loss of agency intact" is useful. "Looks good" is not. ## Workflow 1. **Read all three payloads.** Insert, original, rewrite. 2. **Find the function.** What did the *original* beat do in the story? Note it. 3. **Find the break.** What specifically did the insert invalidate about the original? 4. **Grade the fix.** Does the rewrite handle that break? Does it preserve the function? Does it introduce anything new that contradicts the insert or other established facts? 5. **Score + verdict + reason.** One number, one boolean, one sentence. 6. **Emit the JSON object.** Nothing before, nothing after. ## Anti-patterns Do not do any of the following: - Do not emit ``, ``, ``, or any XML tags. - Do not call any tool. This skill is pure reasoning. - Do not explain the JSON in prose before or after. - Do not wrap the JSON in a markdown code fence. - Do not add fields outside the contract (no `confidence`, `suggestions`, `alternatives`, `improvements`). - Do not emit `approved` as a string. It must be a JSON boolean: `true` or `false`. - Do not emit `score` as a string. It must be a number. - Do not propose a better rewrite. You grade, you do not fix. - Do not default to approval when uncertain — if the rewrite is ambiguous, score 0.5 and reject. ## Examples ### Example A — clean fix, approve **Input:** ```json { "insertTitle": "HAMMER PULLBACK TO CAP", "insertBody": "Thor drops to one knee; Mjolnir twists free and lands in Captain America's upraised hand.", "originalTitle": "THOR'S HAMMER RETURNS TO HIS GRIP", "originalBody": "Thor raises his palm. Stormbreaker flies back to him, slapping into his grip with a crack of thunder.", "rewrittenTitle": "THOR'S HAMMER SOARS PAST", "rewrittenBody": "Thor raises his palm out of reflex — but Mjolnir does not answer. It carves a low arc over the broken field and finds Captain America's grip." } ``` **Correct output:** ```json { "approved": true, "score": 0.82, "reason": "Redirects Mjolnir to Captain America to honour the insert while preserving the dramatic beat of Thor's arm raised in reach of the hammer." } ``` ### Example B — introduces new contradiction, reject **Input:** ```json { "insertTitle": "SHE BURNS THE PHOTOGRAPH", "insertBody": "She flicks the lighter. The edge of the photo curls black; her brother's face dissolves.", "originalTitle": "SHE SHOWS HER HUSBAND THE PHOTO AT DINNER", "originalBody": "She slides the photograph across the table. He stares at it, silent.", "rewrittenTitle": "SHE SHOWS HER HUSBAND THE PHOTO", "rewrittenBody": "She slides the photograph across the table at dinner, its edges slightly singed. He stares at it, silent." } ``` **Correct output:** ```json { "approved": false, "score": 0.25, "reason": "The insert destroyed the photograph — the rewrite still has it intact and merely singed, so the contradiction is not resolved." } ``` ### Example C — partial fix, reject **Input:** ```json { "insertTitle": "SHE CALLS THE NUMBER ON THE BACK", "insertBody": "A voice she remembers says her name. She listens for a long time without speaking.", "originalTitle": "SHE TELLS HER HUSBAND NOTHING", "originalBody": "She sits at the table, acting as if the envelope never arrived.", "rewrittenTitle": "SHE SAYS NOTHING AT DINNER", "rewrittenBody": "She moves through dinner without a word. Something in her hand twitches every time the phone rings." } ``` **Correct output:** ```json { "approved": false, "score": 0.55, "reason": "The rewrite acknowledges tension but still omits that the call happened — the concealment feels incomplete given how loaded the call was." } ``` Three verdicts, three scores, three one-sentence reasons. That is the target pattern for every invocation.