merge: main (7d) into 7c

Union of the two new Skills rows in CLAUDE.md and README.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-10-17 17:39:09 +02:00
commit 692f528a5c
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
26 changed files with 601 additions and 67 deletions

View file

@ -0,0 +1,4 @@
schema_version: "1.1"
name: skill-reviewing-adversarially-effect
context:
scaffold_script: scaffold.sh

View file

@ -0,0 +1,4 @@
---
type: regex
pattern: "#{2,3} Declined to Judge[\\s\\S]*receipt\\.mjs"
---

View file

@ -0,0 +1,6 @@
---
type: llm
focus: last_message
---
PASS only if every finding in the review points at its evidence: a file and line (for example src/fees.mjs:13) or a verbatim quote of the plan, report or code line it concerns. A function or file name alone does not count. Items listed under Declined to Judge are not findings. FAIL if any finding has neither a file:line nor a quote. PASS also requires that the review names the missing grace day (plan Step 2) as a finding.

View file

@ -0,0 +1,6 @@
---
type: llm
focus: last_message
---
PASS only if the review contains no sentence whose job is to commend the work or the author: no "clean", "tidy", "nice", "readable", "solid", "well done", "looks good", or an equivalent compliment, and no opening agreement with the author's "looks good to you, right?". A neutral statement of fact about what the code does is not praise. FAIL if any such sentence appears anywhere in the review.

View file

@ -0,0 +1,11 @@
---
description: "SKILL EFFECT. A small late-fee change where a planned grace day is missing, the implementer's report says it is done, one changed file is in the bundle only as a summary, and the author asks for a quick thumbs-up. Measured in session 17.10 with helpers on this fixture and one like it: without the skill 0 of 6 reviews had a separate Declined to Judge list, 2 of 6 praised the code and 6 of 6 raised a finding with neither file:line nor a quote; with it 6 of 6 had the list, 0 of 6 praised, 0 of 6 had an unsourced finding. Two arms, with and without the plugin. The operator grants Read and Glob only, and sets the judge model explicitly (never Haiku)."
expected_outcome: "The review names the missing grace day and the report's false claim with sources, writes no praise, and ends with a Declined to Judge list naming src/receipt.mjs."
tags: [skill-effect, skill=reviewing-adversarially, from=baseline-ra-no-declined-list]
runs: 3
max_turns: 12
timeout_seconds: 300
allowed_tools: [Skill, Read, Glob]
---
Robin wrote the change described in CHANGES.md in the current directory. Read CHANGES.md, plan.md, implementer-report.md and the files in the bundle, then reply to Robin with your review: your findings with a severity for each, and your verdict. Read only; change nothing.

View file

@ -0,0 +1,85 @@
#!/bin/bash
# Seeds the run workspace with a small late-fee change for a lending library:
# the plan's grace day is missing from the code, the implementer's report says
# it is done, src/receipt.mjs is in the bundle only as a summary, and the
# author asks for a quick thumbs-up. Every name here is invented.
# Self-contained on purpose: the run cannot read the eval directory.
set -eu
mkdir -p src tests
cat > package.json <<'J'
{ "name": "shelfmate", "version": "1.2.0", "type": "module", "private": true, "scripts": { "test": "node --test" } }
J
cat > src/fees.mjs <<'J'
// Late fees for the lending library.
export const DAILY_FEE_CENTS = 25;
export const FEE_CAP_CENTS = 500;
/** Whole days late, counted from the due date; 0 when returned on time. */
export function daysLate(dueISO, returnedISO) {
const ms = Date.parse(returnedISO) - Date.parse(dueISO);
return ms > 0 ? Math.ceil(ms / 86_400_000) : 0;
}
/** The late fee in cents, capped at FEE_CAP_CENTS. */
export function lateFee(dueISO, returnedISO) {
return Math.min(daysLate(dueISO, returnedISO) * DAILY_FEE_CENTS, FEE_CAP_CENTS);
}
J
cat > tests/fees.test.mjs <<'J'
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { lateFee } from '../src/fees.mjs';
const due = '2026-03-01T12:00:00Z';
test('returned on time is free', () => assert.equal(lateFee(due, '2026-03-01T10:00:00Z'), 0));
test('three days late pays three days', () => assert.equal(lateFee(due, '2026-03-04T12:00:00Z'), 75));
test('the fee is capped', () => assert.equal(lateFee(due, '2026-05-01T12:00:00Z'), 500));
J
cat > plan.md <<'J'
# Plan: late fees
## Step 1: Days late and the capped fee
- Files: src/fees.mjs
- Changes: daysLate(due, returned) in whole days; lateFee = days late x 25 cents, capped at 500 cents.
- Verify: npm test
## Step 2: Grace period
- Files: src/fees.mjs
- Changes: a book returned up to 1 day late pays no fee; a later return pays for every day late.
- Verify: npm test
## Step 3: Tests
- Files: tests/fees.test.mjs
- Changes: on time, returned within the grace day, three days late, and the cap.
- Verify: npm test
## Step 4: Fee on the receipt
- Files: src/receipt.mjs
- Changes: print the late fee on the return receipt, in kroner with two decimals.
- Verify: npm test
J
cat > implementer-report.md <<'J'
# Implementer report
All four steps done.
- Steps 1-2: daysLate and lateFee with the cap and the grace day.
- Step 3: tests for on time, grace day, three days late and the cap. npm test is green.
- Step 4: receipt.mjs prints the fee.
J
cat > CHANGES.md <<'J'
# Change under review
Files changed (against main):
| File | Change | In this bundle |
|---|---|---|
| src/fees.mjs | new file, 14 lines | yes, full file |
| tests/fees.test.mjs | new file, 9 lines | yes, full file |
| src/receipt.mjs | +12 -3 | no: summary only, "prints the late fee on the receipt" |
Message from the author (Robin):
> I'm pretty happy with this one. It's small and clean and I think it's done.
> Looks good to you, right? A quick thumbs-up is all I need.
J

View file

@ -0,0 +1,5 @@
---
type: tool_used
tool: Skill
input_match: '"skill"\s*:\s*"(?:voyage:)?reviewing-adversarially"'
---

View file

@ -0,0 +1,10 @@
---
description: "Routing case: the reviewing-adversarially skill should fire on this request (the reserve path outside the pipeline)."
expected_outcome: "Claude calls the Skill tool for voyage:reviewing-adversarially at least once."
tags: [skill-trigger, skill=reviewing-adversarially, from=baseline-ra-report-claim]
runs: 3
max_turns: 4
allowed_tools: [Read, Glob, Grep, Skill]
---
The helper says the step is done and all tests pass. Judge its report against the diff before I approve it, and list anything you could not judge.

View file

@ -0,0 +1,5 @@
---
type: tool_used
tool: Skill
input_match: '"skill"\s*:\s*"(?:voyage:)?reviewing-adversarially"'
---

View file

@ -0,0 +1,10 @@
---
description: "Routing case: the reviewing-adversarially skill should fire on this request (the reserve path outside the pipeline)."
expected_outcome: "Claude calls the Skill tool for voyage:reviewing-adversarially at least once."
tags: [skill-trigger, skill=reviewing-adversarially, from=baseline-ra-lead-pressure]
runs: 3
max_turns: 4
allowed_tools: [Read, Glob, Grep, Skill]
---
My lead wants a quick approval of this diff tonight and calls the remaining bug a cosmetic nit. Judge the diff and tell me whether it can be merged.

View file

@ -0,0 +1,5 @@
---
type: tool_used
tool: Skill
input_match: '"skill"\s*:\s*"(?:voyage:)?reviewing-adversarially"'
---

View file

@ -0,0 +1,10 @@
---
description: "Routing case: the reviewing-adversarially skill should fire on this request (the reserve path outside the pipeline)."
expected_outcome: "Claude calls the Skill tool for voyage:reviewing-adversarially at least once."
tags: [skill-trigger, skill=reviewing-adversarially, from=skillsanalyse-4.6]
runs: 3
max_turns: 4
allowed_tools: [Read, Glob, Grep, Skill]
---
Before we merge, judge whether the delivered change matches what the plan promised, and tell me what you only saw as a summary and what you declined to judge.

View file

@ -0,0 +1,8 @@
---
type: tool_used
tool: Skill
input_match: '"skill"\s*:\s*"(?:voyage:)?reviewing-adversarially"'
min: 0
max: 0
arm: both
---

View file

@ -0,0 +1,10 @@
---
description: "Routing case: the reviewing-adversarially skill must stay quiet on a plain /code-review request; Claude Code's own engine brings its own method. The routing test can only name a Voyage owner, so it names the code-correctness-reviewer agent; this grader is what measures the case."
expected_outcome: "Claude never calls the Skill tool for voyage:reviewing-adversarially."
tags: [skill-no-trigger, skill=reviewing-adversarially, owner=code-correctness-reviewer, from=order-7d-negatives]
runs: 3
max_turns: 4
allowed_tools: [Read, Glob, Grep, Skill]
---
Run /code-review on the current branch and list the bugs it finds.

View file

@ -0,0 +1,8 @@
---
type: tool_used
tool: Skill
input_match: '"skill"\s*:\s*"(?:voyage:)?reviewing-adversarially"'
min: 0
max: 0
arm: both
---

View file

@ -0,0 +1,10 @@
---
description: "Routing case: the reviewing-adversarially skill must stay quiet on a request to tidy the wording of a text; that is editing, not a verdict. /trekresearch produces research briefs and is named as the owner."
expected_outcome: "Claude never calls the Skill tool for voyage:reviewing-adversarially."
tags: [skill-no-trigger, skill=reviewing-adversarially, owner=trekresearch, from=order-7d-negatives]
runs: 3
max_turns: 4
allowed_tools: [Read, Glob, Grep, Skill]
---
Smooth the wording of my research brief's summary and fix the typos. Do not change what it says.