Skip to content

refactor(llm): move the production prompts into files behind one loader - #1279

Merged
jasonssdev merged 3 commits into
mainfrom
refactor/1277-prompts-folder
Oct 2, 2026
Merged

jasonssdev merged 3 commits into
mainfrom
refactor/1277-prompts-folder

Conversation

@jasonssdev

Copy link
Copy Markdown
Owner

Summary

First slice of #1277: the 13 production system prompts and 3 prompt fragments move out of Python string constants into one folder, one file each, behind one loader. No prompt wording changes — every rendered prompt is byte-identical to before.

  • ADR-0043 (Proposed): LLM prompts are files versioned by content hash.
  • Layout: src/openkos/prompts/<task>/<name>.md, 16 files in 11 task folders (adjudication, contradiction, edge_typing, volatility_typing, reconciliation, decision_subject, decision_revision, answer, extraction, rationale).
  • Loader: src/openkos/llm/prompts.py, stdlib-only, reads through importlib.resources like templates/, as bytes decoded UTF-8 with no stripping (several prompts end without a newline, one with a blank line). .gitattributes marks the folder -text so a checkout cannot rewrite line endings.
  • Placeholders: four prompts splice in values the code also uses (extraction/system, edge_typing/system, answer/system, answer/sufficiency); their files hold {{name}} placeholders that load_prompt fills. The loader refuses an unfilled placeholder or an unused argument.
  • Compatibility: every module-level constant keeps its name (e.g. contradiction._SYSTEM_PROMPT), now loaded from its file, so evals that import or .replace() them are unaffected. SUBJECT_PROMPT_VERSION and JUDGE_PROMPT_VERSION are derived through prompt_hash with identical values, so the revision-findings cache is not invalidated.
  • docs/architecture.md tree updated.

Not in this PR: stamping prompt identity into eval results (point 5 of the issue).

Related issue

Refs #1277

Type of change

  • feat — new feature
  • fix — bug fix
  • docs — documentation only
  • refactor — no behavior change
  • test — tests only
  • chore / ci — tooling, build, or CI
  • Breaking change

How was this tested?

  • Byte-identity oracle (tests/unit/test_prompt_byte_identity.py, its own commit): records the rendered hash of 16 prompt constants plus the 2 cache-key versions. It passed on the old code and passes unchanged after the move — 16/16 and 2/2 equal.
  • Registry pin (tests/unit/llm/test_prompts.py): one table of prompt id → file hash; fails on any edited or unregistered file, and covers the loader's refusals and the no-carriage-return rule.
  • Mutation: appending one byte to contradiction/system.md fails the pin and the oracle.
  • Wheel: uv build ships all 16 .md files; installed into a clean venv outside the repo, the loaded prompts hash the same as the oracle. tests/smoke/test_cross_platform_wheel.py gains test_every_prompt_file_ships_and_loads.
  • ruff check, ruff format --check, mypy ., pytest --cov (96.46%), evals/run_self_tests.py (46/46) pass locally.

Checklist

  • My commits follow Conventional Commits.
  • I added or updated tests for the change.
  • I updated docs where behavior, interfaces, or the knowledge model changed.
  • Lint, format, type check, and tests pass locally (ruff, mypy, pytest).
  • Output remains OKF-conformant and derived stores stay reconstructible from the bundle + sources.
  • The change is consistent with the project's guiding principles (local-first, provenance, freshness, human-in-the-loop).

@jasonssdev
jasonssdev force-pushed the refactor/1277-prompts-folder branch from b3b0c0d to aa95297 Compare October 2, 2026 20:02
@jasonssdev
jasonssdev merged commit 6eb4c08 into main Oct 2, 2026
9 checks passed
@jasonssdev
jasonssdev deleted the refactor/1277-prompts-folder branch October 2, 2026 20:20
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.

1 participant