Skip to content

F2: blocking gate — cited key in BOTH citations.bibtex AND papers/#43

Open
frastlin wants to merge 3 commits into
masterfrom
feat/f2-presence-gate
Open

F2: blocking gate — cited key in BOTH citations.bibtex AND papers/#43
frastlin wants to merge 3 commits into
masterfrom
feat/f2-presence-gate

Conversation

@frastlin

Copy link
Copy Markdown
Collaborator

Resolves #36.

What & why

Two scripts each covered one edge of the triangle and neither enforced the full invariant: lit_review.py verify checked draft ↔ citations.bibtex symmetry (exit 2) but never that a key resolves to a paper; verify_citations.py resolve resolved @key → dir but always exited 0 and ignored the bibtex. So a hallucinated key could pass verify, sit in the bibtex, and still have no paper behind it. This adds one forceful gate that blocks (exit 2) when any cited key is missing from the bibtex or from papers/.

Changes

  • scripts/lit_review.py — new gate subcommand. For the cited-key set C:
    • MISSING_FROM_BIBTEX = C \ bibtex_keys
    • MISSING_FROM_PAPERS = { k ∈ C : keymap.resolve(k) is None OR its dir fails F3 }
    • prints each offending key with its citing sentence (reusing verify_citations.extract_citations); exits 2 if any bucket is non-empty.
    • "Present in papers/" follows the 2026-06-30 decision: the key must resolve and the directory must pass the F3 completeness gate. The F3 check is delegated to lint_paper_schema via a lazy import, so verify/build keep their stdlib-only footprint; PEP 723 gains pyyaml only for the gate path.
  • skills/verify-citations/SKILL.md — documents the gate as a REQUIRED Step 0, run before faithfulness grading; adds a lit_review.py launcher so the documented command is runnable.

Tests (TDD)

test_presence_gate.py: missing_from_papers (names the key and its citing sentence), missing_from_bibtex, clean_draft_exit_zero, and resolves_but_fails_f3 (key resolves to a dir whose abstract.md was removed → still blocked).

Full suite green: 181 passed, 56 subtests.

Dependencies

Third in build order. Depends on #34 (identity resolution) and #35 (the F3 gate this delegates to). Required by F5 (post-draft step) and F6 (pipeline gate).

🤖 Generated with Claude Code

frastlin and others added 3 commits June 30, 2026 13:55
Overturns the B5 dir/cite_key decoupling (signed off 2026-06-30): a paper's
directory name must now equal its cite_key.

- lint_paper_schema.py: new DIR_KEY_MISMATCH violation (exit 2) when a paper
  dir name != its derived cite_key.
- rename_to_cite_key.py: dry-run-by-default migration that renames mismatched
  dirs to their cite_key and rewrites every reference (index.md, _reader_done.tsv,
  keymap.tsv, ../<dir>/notes.md links and [[dir]] wikilinks in sibling files).
- paper-reader/SKILL.md: name new paper dirs from the cite_key so they are born
  compliant; metadata rule now requires dir == cite_key.
- build_keymap.py: docstring records the new invariant; keymap.tsv is now an
  identity cache.
- README: document rename_to_cite_key.py.

Tests: DirKeyMismatchTests (mismatch reported, match passes, year-differs-but-
key-matches, main() exits 2) + test_rename_to_cite_key.py (plan, dry-run touches
nothing, write renames + rewrites refs with no dangling links, idempotent).

Closes #34

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012MKtQ1Dfg5qYWhobNKk7jP
lint_paper_schema.py already implemented the substance (required files,
abstract.md verbatim+interpretation sections, exit 2). This is the hardening +
wiring the feature asked for.

- lint_paper_schema.py: add a PEP 723 block (pyyaml) so it is uv-runnable as a
  gate; docstring states it is the single source of truth for completeness (F3).
- Reconcile skills/lint-paper/SKILL.md: abstract.md and citations.md are now
  REQUIRED (not "recommended"), abstract.md must carry both sections, and a new
  Step 3 runs the mechanical linter as the authoritative, exit-2 gate so the two
  linters can never drift.
- Wire the gate as a mandatory final step in process-new-papers, ingest-new-papers,
  and ingest-collection: a non-zero exit hard-blocks the wave before drafting.
- sync_skill_launchers.py: add lint_paper_schema.py launchers for those four
  skills; regenerated (drift test green).

Tests: focused ABSTRACT_MISSING, CITATIONS_MISSING, ABSTRACT_SECTIONS
(missing-interpretation), and main()-exits-2-on-incomplete coverage.

Closes #35. Depends on #34 (F4 DIR_KEY_MISMATCH ships in the same gate).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012MKtQ1Dfg5qYWhobNKk7jP
…apers/

Two scripts each covered one edge (lit_review.py verify = draft<->bibtex symmetry;
verify_citations.py resolve = @key->dir but always exit 0). Neither enforced the
full invariant, so a key could pass verify, sit in the bibtex, and still have no
paper behind it.

- lit_review.py: new `gate` subcommand. For the cited-key set it computes
  MISSING_FROM_BIBTEX (cited but not declared) and MISSING_FROM_PAPERS (does not
  resolve to a dir, OR the dir fails the F3 completeness gate), prints each
  offending key with its citing sentence, and exits 2 if any bucket is non-empty.
  "Present in papers/" = resolves AND passes F3 (2026-06-30 decision); the F3
  check is delegated to lint_paper_schema (lazy import keeps verify/build
  stdlib-only). PEP 723 gains pyyaml for the gate path.
- verify-citations/SKILL.md: document the gate as a REQUIRED pre-ship Step 0,
  run before faithfulness grading; add a lit_review.py launcher so it is runnable.

Tests: test_presence_gate.py — missing-from-papers (names key + citing sentence),
missing-from-bibtex, clean-draft-exit-0, resolves-but-fails-F3 (missing abstract).

Closes #36. Depends on #34 (identity) and #35 (the F3 gate it delegates to).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012MKtQ1Dfg5qYWhobNKk7jP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

F2: Blocking gate — every cited key present in BOTH citations.bibtex AND papers/

1 participant