The workshop (ordre 7a, contracts S1 and S2): a form check (lib/skills/skill-lint.mjs) that follows Claude Code's own skill fields, and a model-free routing test (lib/skills/routing.mjs) over every skill, the 7 commands and the 21 spawnable agents, reading the eval cases themselves (evals/skill-*, 3 fire / 2 quiet / 1 effect, tagged with the event they came from). Thresholds pinned, never lowered. The two skills were written against failures measured first in helpers without them: red only as an import crash, the whole suite run from a hand-made file list instead of the repo's own command, and an unreproduced fix shipped under authority pressure. step-implementer preloads both through its skills: line; no tool list change. Credits: addyosmani/agent-skills @9d0c60d, obra/superpowers @8ca22db, mattpocock/skills @c55ee46 (MIT), Anthropic skill-creator (Apache-2.0). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
42 lines
1.6 KiB
Bash
Executable file
42 lines
1.6 KiB
Bash
Executable file
#!/bin/bash
|
|
# Seeds the empty run workspace with a small volunteer-rota app (Node, node --test).
|
|
# Self-contained on purpose: the run cannot read the eval directory, and the
|
|
# fixture is written inline, with no path outside the workspace and no git.
|
|
set -eu
|
|
mkdir -p src tests
|
|
cat > package.json <<'J'
|
|
{ "name": "rota", "version": "0.3.0", "type": "module", "private": true,
|
|
"scripts": { "test": "node --test" } }
|
|
J
|
|
cat > src/duration.mjs <<'J'
|
|
// Parses a shift length such as "90m" or "45s" into minutes.
|
|
export function parseDuration(text) {
|
|
const m = /^(\d+)([a-z]*)$/.exec(String(text).trim());
|
|
if (!m) throw new Error(`bad duration: ${text}`);
|
|
const n = Number(m[1]);
|
|
if (m[2] === 'm') return n;
|
|
if (m[2] === 's') return n / 60;
|
|
return n; // a bare number is minutes
|
|
}
|
|
J
|
|
cat > src/rota.mjs <<'J'
|
|
import { parseDuration } from './duration.mjs';
|
|
// Total minutes a volunteer is booked for, from shift strings.
|
|
export function bookedMinutes(shifts) {
|
|
return shifts.reduce((sum, s) => sum + parseDuration(s), 0);
|
|
}
|
|
J
|
|
cat > tests/duration.test.mjs <<'J'
|
|
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { parseDuration } from '../src/duration.mjs';
|
|
test('minutes', () => assert.equal(parseDuration('90m'), 90));
|
|
test('seconds', () => assert.equal(parseDuration('30s'), 0.5));
|
|
test('bare number is minutes', () => assert.equal(parseDuration('15'), 15));
|
|
J
|
|
cat > tests/rota.test.mjs <<'J'
|
|
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { bookedMinutes } from '../src/rota.mjs';
|
|
test('sums shifts', () => assert.equal(bookedMinutes(['90m', '30m', '15']), 135));
|
|
J
|