# Changelog

All notable changes to anthroposophy.ai are documented in this file.

The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.1.2] - 2026-05-23

### Research workflows

The Sources corpus is curated by Steiner-engagement, not by canon — these are the foundational texts the GA itself takes up. A few workflows it makes practical:

- **From a Steiner lecture to its source text.** `find_source_chapters_for_ga_locus("GA 142, 1912-12-28")` returns the Sources chapters the curator has linked to that lecture (Bhagavad Gita Discourses, Mahabharata Parvas, the Pauline epistles as the GA 142 counterpart text). `fetch_source_chapter` then quotes the verses verbatim.

- **From a foundational text to Steiner's treatment of it.** `fetch_source_summary` on (say) the Kaṭha Upanishad or *De Anima* Book II names the verified GA loci where Steiner engages it; `fetch_passage` returns his actual words.

- **Cross-corpus surveys in a single call.** `search_anthroposophy(query=..., corpus="all")` fans GA + Free Man Creator (FMC) + Sources together, distinguishing hits by `[ga] / [fmc] / [sources]` tags with per-corpus totals.

- **Honest gap-detection.** When the curator has examined a chapter and Steiner did *not* engage it, `steiner_status: "not_engaged"` is the explicit sentinel — the data says so rather than inviting a fabricated bridge. Aristotle's *De Anima*, for example, carries this flag despite the structural temptations to read his hylomorphic soul-account into the threefold-body schema.

- **Stream-filtered comparative work.** `search_sources(stream="indian")` scopes to Vedic / Upanishadic / Gita / Mahabharata material; `stream="greco-christian"` to Patrologia + Aristotle + Aquinas + Hermetic Corpus; `stream="western-european"` to the Beguine + Rhineland + Theosophical + Goethean strands.

- **Curator's cross-tradition congruences as named syntheses.** Each summary surfaces the FMC curator's explicit cross-tradition observations (e.g. *De Anima*'s tripartite soul ↔ Vedanta's *pancha-kosha* ↔ Plotinus's nous-triad ↔ Kabbalah's *nefesh / ruach / neshamah*) as paraphrase the curator owns, never as quotes from those traditions.

Discipline reminder: only `fetch_source_chapter` is quote-safe (`quote_safe=true`). `fetch_source_summary`, `find_source_chapters_for_ga_locus`, and every `steiner_loci.statement` field are FMC-curatorial paraphrase (`quote_safe=false`) — they capture the verified loci but they never go inside quotation marks.

### Added

- `/sources/` corpus integration — Sacred, Inspired and Foundational Texts across 5 wisdom-streams (Indian, Persian, Egyptian-Hebrew, Greco-Christian, Western-European). Vedic scripture, the Greek-philosophical tradition (Aristotle, Plato, Plotinus), Patrologia (Church Fathers), Aquinas (Summa Theologiae + Summa Contra Gentiles), Beguine + Rhineland mysticism, Hermetic Corpus, Rosicrucian Manifestos, Theosophical inheritance (Isis Unveiled, Secret Doctrine, Mahatma Letters), Goethean works.

- Tool `search_sources`: full-text search over /sources/ chapters. Filters: `work`, `lang`, `edition`, `stream`, `tradition`, `form`, `year_from`, `year_to`. Returns ranked chapter hits with `chapter_locus`, snippet, curatorial blurb, and `summary_url` (when present) pointing at the FMC-curatorial paraphrase block.

- Tool `fetch_source_chapter`: retrieve verbatim chapter text by `chapter_locus` (`<work>[/<subwork>...]/<chapter>`). Returns `text_trust='verbatim'`, `quote_safe=true`, parent breadcrumbs, descriptor subtitle + blurb, and `available_versions[]`. Use to obtain quote-safe text from /sources/.

- Tool `fetch_source_summary`: retrieve the FMC-curatorial paraphrase block for a chapter or work — theme, soul-faculty, Steiner engagement (paraphrase + verified GA loci, or the honesty-gap sentinel "not engaged in the GA corpus"), cross-tradition congruences. `text_trust='paraphrase'`, `quote_safe=false`. The structural verbatim-vs-paraphrase split that prevents accidental quotation of curator-summary content.

- Tool `list_source_works`: discovery — enumerate /sources/ works by `stream`, `tradition`, `form`, `parent_locus`, `top_level_only`, `has_summary`. Returns work_locus, name, tradition, year_approx, chapter_count, word_count, landing_url, summary_url.

- Tool `find_source_chapters_for_ga_locus`: reverse cross-reference (sources → GA). Given a GA locus (`GA 142, 1912-12-28`) or volume (`142`), returns which /sources/ chapters cite that lecture, with paraphrase statements. Driven by the `sources_ga_xref` bridge, populated from chapter and work summaries.

- `search_anthroposophy` umbrella extended with `corpus='sources'` and `corpus='all'`. `'all'` fans GA + FMC + sources in a single call with round-robin interleave; `'both'` remains the back-compat default (GA + FMC). Response carries `sources_total` alongside `ga_total` and `fmc_total`.

- Tool `fetch_fmc_schema_image`: returns inline ImageContent for FMC schemas, mirror-first with upstream fallback. Resolves the image-fetch gap where MCP clients could not follow MediaWiki redirects to the upstream JPEGs.

### Changed

- Top-of-document **Quotation discipline (read first)** block in server `instructions` extended with a /sources/ paragraph. `fetch_source_chapter` returns quote-safe text (`text_trust='verbatim'`); `fetch_source_summary` returns FMC-curatorial paraphrase (`text_trust='paraphrase'`, `quote_safe=false`) — never quote, even when paraphrasing is tight. Each `steiner_loci` entry inside a summary names a verified GA locus retrievable via `fetch_passage`; the surrounding statement is the curator's paraphrase, not Steiner's words. `find_source_chapters_for_ga_locus` returns paraphrase as well.

- `search_anthroposophy.corpus` enum: `['ga','fmc','both']` → `['ga','fmc','sources','both','all']`. Tool description acknowledges sources as a third corpus alongside GA and FMC.

- MCP `tools/list` returns 14 tools (4 GA + 5 FMC + 5 sources).

- MCP server `version` and `SERVER_VERSION` bumped to `1.1.2`. Both were stale prior to this release (`1.1.0` and `1.0.0` respectively).

### Fixed

- `scripts/deploy_site.sh` parity probe: added retry/backoff (8 attempts, 0.5s × attempt#) to tolerate uvicorn's multi-worker spawn window. `systemctl is-active` returned `active` before all workers had bound to port 8044, causing a false rollback on the 2026-05-22 deploy.

- `v2/server/main.py`: removed a stale `import sources_shared` that crashed all 4 anthro-api workers with `ModuleNotFoundError` on startup (the module is on the MCP service's path, not the API service's). The /sources/ REST endpoints remain deferred per the MCP-first pattern; the import was dead code.

- `find_fmc_pages_for_ga_locus.inputSchema`: removed the top-level `anyOf` that required either `ga_locus` or `ga_volume`. Anthropic's `custom` tool API rejects top-level `anyOf` / `oneOf` / `allOf` in input_schema; any agent call that included this tool in its toolset was failing with `400 tools.N.custom.input_schema: input_schema does not support oneOf, allOf, or anyOf at the top level`. The field-presence constraint is now enforced in the dispatch handler instead (which already validated the same rule and returned `error_code: "missing_argument"`). A regression test (`test_no_top_level_schema_combinators`) sweeps every FMC tool schema for top-level combinators.

## [1.1.1] - 2026-05-18

### Research workflows

This release is the discipline layer that makes corpus citations trustworthy. With 1.1.1 in place:

- **Anything inside quotation marks must be byte-for-byte from a corpus retrieval.** `fetch_passage`, `fetch_source_chapter`, or a `quoted_span` record with `status=stored` — minor trimming, smoothing, or dropping a single word counts as paraphrase, even when self-labelled as quoting.
- **0-hit responses carry an authoritative "do not quote" signal.** `search_steiner` / `search_anthroposophy` / `search_sources` return `corpus_verdict: "NO_MATCH — ..."` in the response payload when `total == 0`. A researcher receiving a NO_MATCH answer can trust that the topic is genuinely not in the corpus rather than worry the agent gave up too early.
- **Bare GA-volume-and-year citations are rejected as unverified.** A claim like "GA 26, 1924" without a specific lecture-date or passage-number does not survive the discipline check.
- **Reverse-lookup questions get the dedicated tool.** "Which FMC pages cite GA 146, 1913-06-02?" routes to `find_fmc_pages_for_ga_locus`, not generic FTS — exact-locus questions answered by an exact-locus tool.

For research this means citations in an agent's output reflect retrieval rather than training memory or hallucination, and a "not in corpus" answer can be trusted as authoritative.

### Added

- `corpus_verdict` field on `search_steiner` and `search_anthroposophy` responses when `total == 0`. Carries an authoritative "do not quote" signal in the response payload, so the agent reads it directly rather than relying only on session-level instructions.

### Changed

- New top-of-document **Quotation discipline (read first)** block in server `instructions`. Requires `search_steiner` → `fetch_passage` before opening quotation marks. 0-hit corpus results are authoritative. Bare GA-number-plus-year citations (e.g. "GA 26, 1924") rejected as unverified. **Byte-for-byte means byte-for-byte**: dropping a single word ('thus', 'then', 'also') or trimming for slide-readability breaks verbatim status; self-labeling a paraphrase doesn't exempt it.

- Additional agent-discipline blocks in server `instructions`: inline citation rendering at parity with web-source linking; section references must use `<page_slug>#<section_anchor>` form; reverse cross-reference questions must use `find_fmc_pages_for_ga_locus`; stay inside the corpus when `verify_locus` returns true; citation follow-ups must verify both page and section anchor before answering.

- Tool `find_fmc_pages_for_ga_locus`: description lead rewritten around the question pattern it handles ("which FMC pages cite this lecture?"); routes away from `search_anthroposophy` for reverse-lookup queries.

- Tool `search_anthroposophy`: closing "When NOT to use this tool" block redirects exact-locus reverse lookups to `find_fmc_pages_for_ga_locus`.

- Shared FMC source-discipline contract (in `search_anthroposophy` + `fetch_fmc_page` descriptions): closing **Quotation-marks discipline** sentence reserves quotation marks for `quoted_span` records with `status='stored'` or verbatim Steiner passages from `fetch_passage`.

### Fixed

- `find_fmc_pages_for_ga_locus.inputSchema` now declares `anyOf` requiring `ga_locus` or `ga_volume`. Was permissive on `{}`.

- Removed dead `corpus` argument from `search_steiner` / `fetch_passage` / `fetch_parallel` dispatch. Handlers pass `corpus="steiner"` as a literal. `fetch_parallel.inputSchema` no longer advertises the single-value `corpus` enum.

## [1.1.0] - 2026-05-14

### Research workflows

This release brings the Free Man Creator (FMC) curatorial layer ([anthroposophy.eu](https://anthroposophy.eu) — pages, schemas, structured quoted-span records, and GA cross-references) onto the same MCP surface as the GA. Workflows it makes practical:

- **Which FMC pages cite this lecture?** `find_fmc_pages_for_ga_locus("1913-06-02-GA146")` returns the reverse cross-reference with attribution class (`adjacent` / `section-inferred` / `main-body-reference`).
- **What does the FMC curator say about X?** `fetch_fmc_page("Krishna_impulse")` returns ordered curatorial chunks (lead, sections, subsections, discussion notes) plus `quoted_span` records with provenance.
- **Show me schema FMC00.NNN.** `fetch_fmc_schema("FMC00.389A")` returns description, image URL, linked pages, and cited GA loci.
- **What's the link-graph around a page?** `traverse_anthroposophy_links` runs BFS over the FMC cross-link graph (depth 1-3, configurable max-nodes).

FMC content is CC-BY-SA paraphrase; `quoted_span` records carry the curator's structured provenance (`status=stored` for inline verbatim, `status=referenced` for GA pointers that resolve via `fetch_passage`). The unified `search_anthroposophy` umbrella ranks GA + FMC hits together for queries spanning both.

### Added

- FMC ([anthroposophy.eu](https://anthroposophy.eu)) corpus integration. The curatorial wiki at [anthroposophy.eu](https://anthroposophy.eu) is now retrievable through the MCP connector alongside the Gesamtausgabe. License: CC-BY-SA.

- Tool `search_anthroposophy`: unified full-text search across the GA and FMC corpora. Filters: `corpus`, `chunk_class`, `target_corpus`, `status`, `page_slug`. Inherits GA filters (`lang`, `edition`, `ga`, `ga_range`, `from_date`, `to_date`). Detects ranking mode from query content (`primary_seeking`, `comparative`, `curatorial`, `default`) and adjusts interleave order accordingly.

- Tool `fetch_fmc_page`: retrieve an FMC page by slug. Returns ordered curatorial chunks (lead, sections, subsections, discussion notes), `quoted_span` records with provenance, and the page's GA cross-references.

- Tool `fetch_fmc_schema`: retrieve a schema by `FMC00.NNN` id. Returns description, image URL, linked pages, and cited GA loci.

- Tool `traverse_anthroposophy_links`: BFS over the FMC link graph from a root page slug. Depth clamped to [1, 3]; configurable `max_nodes`.

- Tool `find_fmc_pages_for_ga_locus`: reverse cross-reference. Given a GA locus (`1913-06-02-GA146`) or volume (`146`), return all FMC pages that cite it with attribution class (`adjacent`, `section-inferred`, `main-body-reference`).

- Source-discipline contract enforced in tool response structure. `quoted_span` records with `status=referenced` carry no verbatim text; agents follow `target_locus` to the primary corpus. Records with `status=stored` carry the full `embedded_attribution` chain. All FMC retrieval results carry `primary_anchor` (corpus, page_url, curator, license) and `content_hash` for citation stability.

### Changed

- MCP `tools/list` returns 9 tools (4 GA + 5 FMC).

## [1.0.0] - 2026-05-07

### Research workflows

The initial release puts the complete Gesamtausgabe (GA 1 through GA 354, public domain) behind a single MCP surface. Workflows it makes practical:

- **Search the full corpus by keyword.** `search_steiner` runs FTS5 with Porter stemmer + diacritic normalization. Filters: `lang`, `edition`, `ga`, `ga_range`, `from_date`, `to_date`.
- **Verify a GA reference exists before citing.** `verify_locus` confirms `(ga, lecture_date)` is in the corpus — useful as a citation gate before publishing or quoting.
- **Retrieve any passage verbatim.** `fetch_passage(ga, lecture, passage_number, lang, edition)` returns text + stable citation URL in either German original or available English translation.
- **View parallel translations side-by-side.** `fetch_parallel` returns multiple editions of the same locus; per-edition translator + year + basis are surfaced, and an `alignment_confidence` flag warns when paragraph counts diverge between source and translation.

Multilingual support means a researcher reading the German can cross-check the English, and vice versa. Browseable HTML lives at `/v1/steiner/<lang>/ga/<vol>/<date>/p<NNN>` with content-negotiated JSON via the `.json` suffix. The MCP surface is anonymous and per-IP rate-limited at the edge — no account, no signup.

### Added

- Initial public release.

- Gesamtausgabe corpus (GA 1 through GA 354). Rudolf Steiner's books, lectures, and lecture cycles. Public domain.

- Multilingual retrieval. English translations alongside German originals. Per-edition tracking (translator, year, basis). `alignment_confidence` flag marks paragraph-count divergence between source and translation.

- MCP server at <https://anthroposophy.ai/mcp>. Streamable HTTP transport per MCP spec 2025-03-26. Anonymous access; per-IP rate limiting at the edge.

- Tool `search_steiner`: FTS5 search over the Gesamtausgabe. Porter stemmer with diacritic normalization. Filters: `lang`, `edition`, `ga`, `ga_range`, `from_date`, `to_date`, `corpus`.

- Tool `verify_locus`: confirm a GA reference exists in the indexed corpus before citing.

- Tool `fetch_passage`: retrieve a verbatim Steiner passage by `(ga, lecture, passage_number, lang, edition)`. Returns text and a stable citation URL.

- Tool `fetch_parallel`: retrieve the same passage across multiple translation editions side-by-side.

- REST API at <https://anthroposophy.ai/v1/>.

- Browseable passages at `/v1/steiner/<lang>/ga/<ga_volume>/<lecture_date>/p<NNN>`. Content negotiation returns HTML to browsers, JSON to agents via the `.json` suffix.

[1.1.2]: https://anthroposophy.ai/changelog#112---2026-05-23
[1.1.1]: https://anthroposophy.ai/changelog#111---2026-05-18
[1.1.0]: https://anthroposophy.ai/changelog#110---2026-05-14
[1.0.0]: https://anthroposophy.ai/changelog#100---2026-05-07
