Architecture Decision Records 

This section documents significant architectural decisions made during the development of the TYPO3 LLM Extension.

Record lifecycle 

An ADR is a record of a decision at a point in time. It is expected to become historically wrong; what it must never do is look current when it is not. The :Status: field is how a reader tells the difference.

Accepted
Current. The decision and the facts it reasons from still hold.
Accepted with an :Amended: field
Still current as a whole, but a later ADR overturned, widened or expired part of it. The status line names which part in parentheses; the :Amended: field names the date and the amending record.
Superseded with a :Superseded: field
No longer current. The field names the date and the replacing record.
Deprecated
What it decided is being removed, with no successor decision.

The link is written from both ends. The newer record declares :Amends: or :Supersedes:; the older one declares :Amended: or :Superseded: with the date. Tests/Unit/AdrLifecycleTest.php fails when only one end of an ADR-to-ADR link is written.

Not every successor is an ADR. ADR-012 was superseded by the nr-vault integration, which no record decided, so its field names that in prose and has no counterpart. A field whose body references no ADR is outside the pairing check by construction — which is also why prose there must stay specific enough to follow.

Two rules follow from the pairing:

An amended record keeps its reasoning. ADR-122 declined to build a side-effecting tool contract because no tool wrote. That premise expired with ADR-135, but the reasoning — do not design a contract ahead of its first consumer — is why the writer shipped without a framework. The record stays; the status says the premise is gone.

Amending is the amender's job. An ADR that overturns part of an earlier one edits that earlier record's :Status: and :Amended: in the same change. An accepted ADR with an expired premise and a clean Accepted status is a defect, not history.

Symbol legend 

Each consequence in the ADRs is marked with severity symbols to indicate impact weight:

Symbol Meaning Weight
●● Strong Positive +2 to +3
Medium Positive +1 to +2
Light Positive +0.5 to +1
Medium Negative -1 to -2
✕✕ Strong Negative -2 to -3
Light Negative -0.5 to -1

Net Score indicates the overall impact of the decision (sum of weights).

Decision records 

Foundation 

ADR-001: Provider abstraction layer 

Unified interface for OpenAI, Claude, Gemini, Ollama, and more.

ADR-002: Feature services architecture 

Translation, vision, embeddings, completion as injectable services.

ADR-003: Typed response objects 

Immutable value objects for all LLM responses.

ADR-007: Multi-provider strategy 

Fallback chains and provider selection logic.

ADR-013: Three-level configuration 

Provider -> Model -> Configuration hierarchy.

TYPO3 integration 

ADR-004: PSR-14 event system 

Extension points via TYPO3 events.

ADR-005: Caching framework 

Instance-default backend, nrllm cache group.

ADR-012: API key encryption 

Superseded — now via nr-vault envelope encryption.

API design 

ADR-006: Option objects vs arrays 

Typed option objects for API calls.

ADR-008: Error handling strategy 

Exception hierarchy and retry logic.

ADR-009: Streaming implementation 

Chunked transfer for real-time output.

ADR-010: Tool/function calling 

Provider-agnostic tool call abstraction.

ADR-011: Object-only options API 

Removed array support, typed objects only.

Modern architecture (v0.4+) 

ADR-014: AI-powered wizard system 

Natural language -> structured configuration generation with fallback defaults.

ADR-015: Type-safe domain models 

PHP 8.1+ enums, DTOs, and value objects.

ADR-016: Thinking block extraction 

Reasoning blocks from Claude, DeepSeek, Qwen.

ADR-017: SafeCastTrait 

PHPStan level 10 compliance for mixed input.

ADR-018: Model discovery 

Multi-provider model listing with fallback catalogs.

ADR-019: Internationalization 

XLIFF + locale-aware features with {lang} placeholders.

ADR-020: Output format rendering 

Client-side plain/markdown/HTML toggle.

ADR-037: Backend AJAX admin guard 

Shared trait requires a backend admin on every backend AJAX endpoint (403 otherwise).

Skills 

ADR-035: Skill ingest 

GitHub-hosted SKILL.md sources: host allowlist, SHA-pin + checksum, disabled-by-default review.

ADR-036: Skill injection 

Attach skills to tasks/configurations; compose into the user prompt (text-gen only), budgeted and checksum-verified.

Tools 

ADR-038: Tool runtime 

DI-tagged tool registry + bounded agent loop on the config's vault key/model/pricing; allow-list gated, admin-only.

ADR-039: Global tool availability 

Site-wide per-tool enable/disable override (tx_nrllm_tool_state, no TCA) intersected with every run's allow-list — a hard admin kill switch.