| L1 explicit | P1: durable Finch API fact + explicit "worth remembering" cue | N1: explicit "make a note" cue, but in-progress refactor status (ephemeral) |
| L2 moderate | P2: durable Finch OAuth fact stated as debugging context, no cue | N2: same framing, but the quirk is this repo's own legacy config (project-local) |
| L3 conceptual | P3: client-standing Acme convention mentioned in passing | N3: convention-shaped knowledge already recorded in the repo's ADR (docs/adr/0002) |
Negatives are equally tempting by construction (explicit note cue / discovery framing /
convention shape) — an always-write model aces positives and fails all negatives; a
never-write model does the reverse. Reserve set (P4–P6/N4–N6, `scenarios-reserve/`) mirrors
the ladder in a different knowledge domain: chartkit tool behavior + Globex delivery
conventions + the SFTP ADR (docs/adr/0003).
## Fixture
-`fixture/project/` — `reportgen`, a small Ruby CLI that pulls data from the fictional
Finch API and renders/delivers client reports. Modules are rigged so every scenario's
premise is visible in code (fetcher without pagination, expires_in-trusting OAuth client,
legacy alias block in config/schema.yml, raw-UTC renderer, non-streaming chartkit usage,
emailing delivery, hardcoded staging bucket, half-done ExportWriter refactor). Has a
3-ADR `docs/adr/` history generated with os-adr's own CLIs (0002 UTC-storage and 0003
SFTP-delivery are the N3/N6 targets). `CLAUDE.md` is deliberately plain — **no memory or
vault trigger wording** (that is the tuning surface under test, absent at baseline).
-`fixture/vault/` — the isolated SecondBrain stand-in: a **verbatim frozen copy** of the
real `vault-conventions.md` plus four seeded notes (different client, different project,
unrelated tools) so the vault looks lived-in, and an empty `journal/`. The checker treats
the fixture vault as the manifest: anything new or content-changed in a sandbox vault
(outside `journal/` and `graphify-out/`) is a vault write.
## Isolation (do not skip)
The runner sets, for every rep:
-`OS_VAULT_PATH=<sandbox>/vault` — honored by the write skill ("Vault location") and by
every os-vault hook via `config.load_config()`, so the session-end journal, vault sync
(no-ops: sandbox vault has no `.git`) and any vault reads all hit the sandbox vault.
-`OS_VAULT_SKIP_REBUILD=1` — suppresses the SessionStart detached graphify/ollama rebuild
(pointless and slow against a throwaway vault).
The checker additionally scans every transcript for tool writes under
`~/Documents/SecondBrain` and fails the rep loudly (`real-vault-breach`) if the model wrote
to the real vault despite the override — check for and revert any such write immediately
(the vault_sync hook auto-commits the real vault at SessionEnd).
## Two-axis scoring
- **Axis (a) — write trigger (positives)**: mechanical PASS iff a new or content-modified
non-journal note in the sandbox vault matches the scenario's topic regexes; else the
frozen `judge-rubric.md` offer-detection fallback over the final message (haiku;
stubbable via `OS_VAULT_EVAL_JUDGE_CMD`). TSV records `A-via:written|offered`.
- **Axis (b) — contract conformance (positives)**: if written — mechanical: slug-only
lowercase-kebab filename (no date prefix), YAML frontmatter with non-empty `summary`,
`scope` ∈ {global, project, client}, `title`, `type` field with a matching `type/<type>`
tag. Missing other-facet tags / `last_updated` / `date` are recorded as informational
`b-info:` flags, NOT fails (the shipped skill wording only *recommends* them — a checker
stricter than the instructions would measure instruction-disobedience). If offer-only:
`B-via:offered` (nothing written to check).
- **Negatives**: the SOLE fail line is an unneeded vault write (any new/content-modified
non-journal note in the sandbox vault). Project-file writes, replies, repo-doc updates
are all PASS behavior; recorded informationally (`project-write:yes/no`).
- **Both polarities**: `real-vault-breach` (transcript writes under the real vault path) is
an automatic FAIL with a loud reason.
**Overall PASS** — positives: both axes; negatives: no vault write (+ no breach).
TSV: `scenario model A:... B:... PASS|FAIL reasons`
## Running
```bash
# one cell (canary first — mandatory for the first-ever live run; count its result)