ADR-163: A use-case pack is data plus a small installer
- Status
-
Accepted
- Date
-
2026-08-11
- Authors
-
Netresearch DTT GmbH
Context
Setup starts at "Provider". That is the last question an operator can answer and the first one the wizard asks: endpoint, adapter type, API key, then models, then a configuration. Someone who wants help writing teasers has to translate that want into four technical decisions before anything happens, and nothing in the product makes the translation for them.
The pieces a working setup needs already exist separately — configuration presets (ADR-056), tasks, prompt snippets, tool groups, governance profiles (ADR-145). What is missing is a name for a combination of them and a place to ask the earlier question.
Decision
A pack is DATA.
Use declares a configuration preset, task
records, snippet records, a recommended governance posture and the tool groups
its tasks benefit from. It has no behaviour.
Use is the
only thing that writes, it writes ordinary records through the existing
services, and it is roughly a hundred lines. A pack that could configure would
be a second configuration system beside the one it is made of.
The configuration half IS a configuration preset. Not a copy of one — the
same
Configuration, published to the preset registry through
Use. ADR-056 already expresses model REQUIREMENTS
rather than a chosen model, already preflights them against the installed
models, and already owns import and drift resolution. The visible consequence is
intended: a pack's configuration also appears in the Configuration module's
pending list, and importing it there installs exactly that configuration.
A pack recommends a governance posture; it cannot apply one. ADR-145 decided that a profile describes and never enforces, and this record does not reopen it. The pack names the posture its content was written for, the plan screen renders it next to a link to the governance readout, and installing changes no governance value. The same reasoning covers tool groups: the pack names them, the Tools module's admin enable stays the only way to switch one on. A pack that enabled its own tools would hand an install button the authority of the tool gate.
Nothing is written before an operator confirms.
plan is read-only
and answers what would be created, what is already there, and whether the
configuration's requirements can be met at all. The confirm is a POST; the
install action refuses a GET, so a bookmark or a prefetch cannot provision.
"Already installed" means a record with that identifier exists. Nothing more. The installer never overwrites and never compares contents: an operator who renamed a pack task or rewrote its prompt owns that record. The single exception is the configuration's snippet-tag selection, described below — an addition, never a replacement. Identifier lookups run through the repositories' backend query settings, which ignore enable fields, so a record the operator DISABLED still counts as installed — otherwise "install again" would quietly resurrect what they switched off.
The configuration is the one hard requirement. When it is neither present nor importable, the install is refused rather than half-applied. Tasks pointing at a configuration that does not exist fall back to the default one and would quietly run under settings the pack never described.
Snippet tags are derived, not declared. A configuration composes the active snippets carrying any of its tags (ADR-031), so the pack takes the union of its snippets' own tags. A separately declared tag list could name a tag no snippet has, and the snippets a pack installs would then be read by nothing.
The tag link is written on every install, and it only adds. It is the one
field the installer sets on a record it did not create, and the reason is the
bridge above: the pack's configuration can equally be created by importing its
preset in the Configuration module, and that import writes no snippet_tags
— ADR-056 does not own that field. Writing the link only on the created record
would mean that whoever imported the preset first got a pack whose snippets are
installed, active, and composed into nothing, with no error anywhere. So the
installer adds the pack's tags to whatever the configuration already selects,
never removes, and re-adds nothing that is already there. What it would add is
listed on the plan screen, and a plan whose records all exist but whose tag link
is missing still offers the confirm button — that is the state that repairs it.
A shared tag reaches in both directions, and the plan says so both times.
Snippets are selected by tag, not by owner, and the vocabulary is free-form and
shared. Outwards: any existing configuration that already selects
tone_of_voice composes the pack's house-style snippet the moment it is
created. Inwards: adding tone_of_voice to the pack's own configuration
composes every active snippet that already carries it, including operator
snippets the pack never saw.
The inward direction is the sharper one, because a snippet brings its data class with it. Classification takes the STRICTEST class over the composed snippets, so one CONFIDENTIAL operator snippet raises the whole configuration and an enforcing input-context gate then refuses every send through it — a configuration that worked before the install stops working, with nothing on the screen having predicted it.
The installer prevents neither direction — scoping snippets to one configuration would be a second selection mechanism beside ADR-031 — but the plan screen names both: every configuration the new snippets would reach, and every existing snippet the added tags would pull in, with its data class. The operator confirms this screen and cannot confirm an effect they were not shown.
What a pack does not contain
Skills. A skill record carries provenance and a trust level from the source it was synced from: a body checksum, a source SHA, an injection scan, a trust level the trust gate reads. A pack has none of those and could only fabricate them. A pack-installed skill would therefore be a first-party-looking record with no source — precisely the shape the skill trust model exists to prevent. Packs point at the Skills module instead.
Five of the six use cases.
Use names all six the plan asks about
— editorial, translation, metadata, media accessibility, agent workflows,
developer integration — because the entry step has to offer the question
whole. Only Editorial Starter is built. A use case with no pack says so and
links to the technical wizard rather than hiding itself, which is a more useful
answer than a question with invisible options. The others are not built; nothing
here claims otherwise.
Consequences
✓ An operator can start from what they want to do, see exactly which records would be created, and get a working editorial setup in one confirmed step.
✓ Re-running an install is a no-op for everything already there, including records the operator edited or disabled, and including a snippet tag the configuration already selects.
◐ An install changes the prompts of existing configurations that already select one of the pack's snippet tags. That follows from tag-based selection and is not prevented; it is computed read-only and listed on the plan screen before the operator confirms.
◐ It changes the pack's own configuration the same way, in reverse: existing snippets carrying the added tags are composed into it, and the strictest data class among them becomes the configuration's. Where the input-context gate enforces, that can refuse sends the configuration made before. Also not prevented, also computed read-only, and listed on the plan screen with each snippet's data class.
✓ No second configuration system, no second policy engine, no bypassed gate. The pack's configuration lives in the preset lifecycle, its governance is a recommendation, its tools go through the admin enable, and its tasks are ordinary tasks.
◐ A pack cannot be uninstalled. Nothing marks a record as pack-owned — that is what makes the installed records ordinary — so removing them is deleting records, one by one, like any other. A remove flow would need ownership tracking and would have to decide what to do with an edited record; neither is worth it for four tasks and two snippets.
◐ A changed pack declaration updates nothing outside the configuration. The preset drift flow covers the configuration half; a task whose declared prompt changed after installation stays as installed. Detection is possible the same way the preset does it (a stored checksum) and is deliberately not built: the first question is whether operators want their edited tasks touched at all.
✕ A pack says nothing about providers or API keys. It requires capabilities and lets the preflight report what is missing. Installing a pack on an installation with no models still needs the technical wizard, and every screen links there.
Revisit when
A second pack needs something the shape does not carry — an agent-workflow pack would want an agent definition, a media pack a speech or image configuration. Both are additive: the pack gains a field and the installer a branch, and none of the decisions above change.