Skip to content

fix: #5 — feat(claude): Claude Code adapter (Mode A + Mode B + skill)#15

Merged
MiaoDX merged 1 commit into
mainfrom
claude-issue-5
May 2, 2026
Merged

fix: #5 — feat(claude): Claude Code adapter (Mode A + Mode B + skill)#15
MiaoDX merged 1 commit into
mainfrom
claude-issue-5

Conversation

@MiaoDX

@MiaoDX MiaoDX commented May 2, 2026

Copy link
Copy Markdown
Owner

Closes #5.

Ships the two static assets the Claude Code adapter needs on top of the
settings.json snippet that scripture-mcp init --target=claude-code
already installs (landed in #4 / PR #14).

What's in this PR

  • adapters/claude-code/output-styles/scripture-recap.md — style
    only, matches plan.md §5.1 verbatim. Sets
    keep-coding-instructions: true and instructs the model to treat
    <scripture_card> as a one-turn reflective frame. Contains no
    scripture text
    and names no specific tradition, per the
    issue's requirement.
  • adapters/claude-code/skills/verse-inject/SKILL.md — the manual
    fallback skill for the slash-marker flow. Sets
    disable-model-invocation: true so the model never auto-triggers
    it. Body is 56 lines (< 60 per the issue), contains no scripture
    text, and instructs the agent to call mcp__scripture__lookup for
    every verse fetch — the preview shows display_ref, attribution,
    and checksum_sha256, then the user explicitly confirms before any
    injection happens.
  • adapters/adapters.go — a tiny package that embeds the two
    static files via embed.FS. The package exists primarily so the
    test suite can assert structural properties of the assets without
    duplicating their content; the Claude*Path constants also
    document the canonical in-FS paths for the eventual installer in
    feat(install): one-line install.sh #7.
  • internal/injector/envelope.go — the §6.3 envelope now carries
    a checksum: sha256:<hex> line so the Mode A preview surfaces all
    three integrity fields the issue requires: verse text + source +
    checksum. The model is instructed (in the envelope's leading
    paragraph) not to act on the checksum beyond reproducing it
    verbatim if asked.
  • README.md — documents the symlink/copy install path for the
    two adapter assets. They're deliberately not auto-materialized
    by init: init's only acceptance criterion for feat(claude): Claude Code adapter (Mode A + Mode B + skill) #5 is recap on/off
    toggling, which feat(core): stdio MCP server + CLI subcommands #4 already met, and extending init to write files
    outside its existing splice surface would expand scope.

Acceptance-criteria mapping

Mode A — UserPromptExpansion hook:

  • /bible John 3:16 shows a preview card with verse text + source + checksum (envelope now carries the checksum line)
  • User must explicitly confirm before the model sees the verse (UserPromptExpansion shows the expanded prompt to the user before submission; the user hits Enter to confirm)
  • On confirm, the next coding request is wrapped with the temporary envelope from plan.md §6.3
  • keep-coding-instructions: true set on the active output style
  • Works for all 4 marker traditions: bible, dao, sutra, quran (covered by feat(core): stdio MCP server + CLI subcommands #4's lookup-from-prompt regex)
  • Hook exits silently if the prompt has no marker (covered by feat(core): stdio MCP server + CLI subcommands #4)

Mode A — verse-inject skill:

  • adapters/claude-code/skills/verse-inject/SKILL.md exists and is 56 lines (< 60)
  • disable-model-invocation: true in frontmatter
  • Skill body contains no scripture text — calls mcp__scripture__lookup via MCP (asserted by TestVerseInjectSkillIsManualOnlyAndShortAndScriptureFree, which substring-scans the body against every bundled verse > 12 bytes)
  • Manually invoking the skill triggers the same preview/confirm/inject flow (skill body steps 1–5)

Mode B — output style + Stop hook:

  • adapters/claude-code/output-styles/scripture-recap.md defines style only — no scripture text or specific traditions (asserted by TestClaudeOutputStyleHasRequiredFrontmatter)
  • Stop hook calls scripture-mcp recap --terminal (covered by feat(core): stdio MCP server + CLI subcommands #4 via init --target=claude-code --recap=on)
  • Mode B toggleable via scripture-mcp init --target=claude-code --recap=on|off (covered by feat(core): stdio MCP server + CLI subcommands #4)
  • Recap text does NOT appear in the next prompt's input — architectural property: Stop-hook stdout flows to the terminal, not into model_call. Rigorous end-to-end verification of this invariant is the explicit gate of test(critical): injection lifecycle + coding-quality regression #8 (test(critical): injection lifecycle); this issue treats it as a smoke-tested architectural guarantee.

Tests

  • adapters/adapters_test.go — embedded-asset frontmatter assertions,
    line-count check on SKILL.md, no-scripture-text scan against every
    bundled verse, no-tradition-leak check on the style file.
  • internal/injector/envelope_test.go — added the
    checksum: sha256:<hex> line to the envelope assertion list.

Verification

  • make build clean
  • staticcheck ./... clean
  • go test ./... — green across all 7 packages
  • python3 scripts/verify_quotes.py — 31,183 verses, 0 mismatches
  • Smoke: echo '/bible John 3:16 Refactor X.' | ./bin/scripture-mcp lookup-from-prompt emits an additionalContext envelope containing the verse, the John 3:16 display ref, the KJV attribution, and checksum: sha256:8473c0b1c7664945528317faf77351258eb79f8b11ba821ef76d7e916cde711a.

Generated by Claude Code

… skill

Closes #5.

Ships the two static assets the Claude adapter needs on top of the
settings.json snippet that `init --target=claude-code` already installs
(landed in #4):

- adapters/claude-code/output-styles/scripture-recap.md — style only,
  matches plan.md §5.1 verbatim. Sets `keep-coding-instructions: true`
  and instructs the model to treat <scripture_card> as a one-turn
  reflective frame. Contains no scripture text and names no specific
  tradition.
- adapters/claude-code/skills/verse-inject/SKILL.md — manual fallback
  for the slash-marker flow. Sets `disable-model-invocation: true` so
  the model never auto-triggers it. Body is 56 lines, contains no
  scripture text, and instructs the agent to call mcp__scripture__lookup
  for every verse fetch (preview includes display_ref + attribution +
  checksum, then the user explicitly confirms before injection).

Both files are bundled via a tiny `adapters` package that embeds them
through `embed.FS`, which lets the test suite assert structural
properties (frontmatter fields, line count, no-scripture-text, no
tradition leakage in the style file) without duplicating the content.

Also extends the §6.3 envelope with a `checksum: sha256:<hex>` line so
the Mode A preview surfaces all three integrity fields the issue
requires (verse text + source + checksum). The model is instructed not
to act on the checksum beyond reproducing it verbatim if asked.

README documents the symlink-based install path for the two assets;
they're deliberately not auto-materialized by `init` (init's only
acceptance criterion for #5 is recap on/off, which #4 already met).

Acceptance-criteria mapping (Mode A, Mode B, skill all from #5):

- [x] `/bible|/dao|/sutra|/quran <ref>` shows preview card with verse
      text + source + checksum (envelope now carries the checksum)
- [x] User explicitly confirms (UserPromptExpansion shows the expanded
      prompt before submission; user hits Enter to confirm)
- [x] On confirm, the next coding request is wrapped with the §6.3
      envelope
- [x] `keep-coding-instructions: true` set on the active output style
- [x] Hook exits silently if no marker present (covered by #4)
- [x] verse-inject SKILL.md exists, < 60 lines (56), has
      `disable-model-invocation: true`, no scripture text, calls
      `mcp__scripture__lookup`
- [x] scripture-recap.md style-only, names no tradition, no scripture
      text
- [x] Stop hook calls `scripture-mcp recap --terminal` (covered by #4
      via `init --target=claude-code --recap=on`)
- [x] Recap text never enters next prompt input (architectural —
      Stop hook stdout flows to terminal, not model_call; rigorous
      end-to-end verification gated by #8)

Tests:

- adapters/adapters_test.go — frontmatter assertions, line count,
  scripture-text leak check (substring scan against every bundled
  verse > 12 bytes), tradition-leak check on the style file
- internal/injector/envelope_test.go — new checksum line assertion

Verification:
- `make build` clean
- `staticcheck ./...` clean
- `go test ./...` green across all 7 packages
- `python3 scripts/verify_quotes.py` — 31,183 verses, 0 mismatches
- Smoke: `./bin/scripture-mcp lookup-from-prompt` for `/bible John 3:16`
  emits an additionalContext envelope containing display_ref,
  attribution, and the matching sha256 checksum.

https://claude.ai/code/session_01GwZwT41Z5H6TBSoaKuFcBM
@MiaoDX MiaoDX marked this pull request as ready for review May 2, 2026 01:30
@MiaoDX MiaoDX merged commit c821ff0 into main May 2, 2026
1 check passed
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.

feat(claude): Claude Code adapter (Mode A + Mode B + skill)

2 participants