Phase-4 candidate compositions — the filled, scored architectures. A solutions file is EITHER a bare array of solution objects (e.g. skischule's solutions-platform.json) OR an object wrapping them under `system` (demo/template/ehimare). Both shapes are blessed; pick whichever the instance ships. The per-solution shape is $defs/solution. Instance extensions narrow via allOf + $ref to this $id and add their own keys with unevaluatedProperties:false.
data/solutions.json), built from this.
data/solutions/<key>.yaml
One file per solution — a single system[] record. This is where an individual solution is authored.
data/solutions/_index.yaml
Manifest — the wrapper keys (e.g. _comment) plus the solution order, for deterministic reassembly.
solution recordThe fields of a single solution — one per authored file.
solutions.schema.json — change the schema, and this page changes.| Field | Type | Description |
|---|---|---|
key required
|
string | Stable selector for this solution (a `key`, not an `id` — see naming grammar D7). |
name required
|
string | Display name of the solution. |
kind
|
string | OPTIONAL coarse label on the buy↔build spectrum. RENDER-ONLY (no kernel logic branches on it) — any non-empty string an instance's KIND_LABEL maps is valid (buy|rent|build, rent|build, saas|chatwoot|eigenbau, …); no enforced enum. NOT required: a render-only tag must never be mandatory, and its absence is itself meaningful to some instances (skischule marks matrix-only landscape rows by leaving kind off). Architecture — not kind — is the structural truth; kind is a coarse projection of it for display. |
architecture required
|
string | REQUIRED. The architectures.json `key` this solution fills; the board groups by it — architecture is the structural truth, so no solution may omit it (a missing key fails the shape tier, a dangling key fails the semantic tier). `kind` is a coarse render-only projection of this. Resolution checked semantically. |
shortlist
|
number,null | Curation/ranking index, or null when rank is derived by the kernel. |
status
|
enum |
Board pill. Derived when absent (gate-fail→raus, all-offen→neu, else live). status:raus is also legal with no gate-0 (a decision-elimination).live · offen · neu · raus |
scores
|
map<scoreEntry> | criterionId → scoreEntry. Gate = '0'/'1'; Fit/Risk = '1'–'5' (floats allowed). Each value is the bare score string OR an object co-locating the value with its note/confidence/provenance facts (Plan 20). Key-resolution + range checked semantically. |
[each value]
|
→ scoreEntry | How this solution scores on one criterion — EITHER the bare score string (legacy/terse form: gate '0'/'1', fit/risk '1'–'5'), OR an object that CO-LOCATES the value with its gloss + confidence + the research facts that establish it (Plan 20). The exact tier-up mirror of coverageEntry: the criterion id appears once (as the scores map key) so value and provenance cannot drift. The `facts[]` ids resolve into research-index.json `facts` in the semantic tier. Facts attach to this VALUE cell; the derived aggregates (verdict %, weighted Fit, composite Risk) stay fact-free — their provenance is transitive through the cells they roll up. |
val required
|
string | The score value as a string (gate '0'/'1', fit/risk '1'–'5'). Same grammar as the bare form. |
note
|
string | One-line gloss on why this score. |
confidence
|
→ knowledgeState |
Confidence in THIS score value (per-cell; finer than the solution-level knowledge grid).offen · geschätzt · bekannt |
facts
|
array<string> | research-index.json `facts` ids that establish this value — the provenance refs (Plan 20). Resolved in the semantic tier. |
reasoning
|
map<string> | criterionId → 2–4 sentence note. A scored cell with no reasoning is flagged semantically. |
riskScores
|
map<number> | Hand-scored risk dims not derivable from criteria (e.g. abhaengigkeit, terminSicherheit) → 1–5. |
coverage
|
map<coverageEntry> | Fit-criterion id → coverageEntry. The composition, keyed by use case. Each value is the bare coverageCode string OR an object co-locating the code with its note/confidence/provenance facts (Plan 19). |
[each value]
|
→ coverageEntry | How this solution covers one use case — EITHER the bare coverageCode string (legacy/terse form), OR an object that CO-LOCATES the code with its gloss + confidence + the research facts that establish it (Plan 19). Co-located, not a sidecar: the criterion id appears once (as the coverage map key) so the value and its provenance cannot drift apart. The `facts[]` ids resolve into research-index.json `facts` in the semantic tier. |
cov required
|
→ coverageCode | The coverage code (in|part|aug:<filler>|proj|build|none). |
note
|
string | One-line gloss on how this use case is covered. |
confidence
|
→ knowledgeState |
Confidence in THIS coverage value (per-cell; finer than the solution-level knowledge grid).offen · geschätzt · bekannt |
facts
|
array<string> | research-index.json `facts` ids that establish this value — the provenance refs (Plan 19). Resolved in the semantic tier. |
knowledge
|
→ knowledge | The per-facet confidence grid for this solution (spezif/kosten/effort/risiko/fit). |
spezif
|
→ knowledgeFacet | Confidence that the solution is properly DEFINED — e.g. that its filler set is pinned. Distinct from fit: a solution can be under-defined precisely when you don't yet know which fillers it needs. |
level required
|
→ knowledgeState |
The confidence level (offen|geschätzt|bekannt). Same grammar as the bare form.offen · geschätzt · bekannt |
note
|
string | One-line gloss on why this confidence. |
facts
|
array<string> | research-index.json `facts` ids that justify this confidence — the provenance refs (Plan 23). Resolved in the semantic tier. |
kosten
|
→ knowledgeFacet | Confidence in the cost estimate. |
level required
|
→ knowledgeState |
The confidence level (offen|geschätzt|bekannt). Same grammar as the bare form.offen · geschätzt · bekannt |
note
|
string | One-line gloss on why this confidence. |
facts
|
array<string> | research-index.json `facts` ids that justify this confidence — the provenance refs (Plan 23). Resolved in the semantic tier. |
effort
|
→ knowledgeFacet | Confidence in the build + maintenance effort estimate (Plan 15 MR-2: renamed from the former `build`). |
level required
|
→ knowledgeState |
The confidence level (offen|geschätzt|bekannt). Same grammar as the bare form.offen · geschätzt · bekannt |
note
|
string | One-line gloss on why this confidence. |
facts
|
array<string> | research-index.json `facts` ids that justify this confidence — the provenance refs (Plan 23). Resolved in the semantic tier. |
risiko
|
→ knowledgeFacet | Confidence in the risk assessment. |
level required
|
→ knowledgeState |
The confidence level (offen|geschätzt|bekannt). Same grammar as the bare form.offen · geschätzt · bekannt |
note
|
string | One-line gloss on why this confidence. |
facts
|
array<string> | research-index.json `facts` ids that justify this confidence — the provenance refs (Plan 23). Resolved in the semantic tier. |
fit
|
→ knowledgeFacet | Confidence in the fit scoring. |
level required
|
→ knowledgeState |
The confidence level (offen|geschätzt|bekannt). Same grammar as the bare form.offen · geschätzt · bekannt |
note
|
string | One-line gloss on why this confidence. |
facts
|
array<string> | research-index.json `facts` ids that justify this confidence — the provenance refs (Plan 23). Resolved in the semantic tier. |
planGating
|
→ planGating | Edition/add-on gating of required capabilities (Plan 20) — fact-bearing observations the TCO surfaces as plan-threshold/add-on lines. |
axis required
|
string | The criterion/use-case id this gating applies to (resolved semantically against criteria). |
availability required
|
enum |
How the capability is reached: mid-tier=needs a higher (mid) edition · enterprise-only=top edition only · paid-addon=separately priced add-on.mid-tier · enterprise-only · paid-addon |
detail
|
string | The priced/edition detail in prose (e.g. '~55 €/month add-on'). The same content should live in the linked fact's claim; carried here for render. |
facts
|
array<string> | research-index.json `facts` ids establishing this gating (the R8 source URL → fact links). Resolved semantically. |
deployment
|
object | How the solution's core can be RUN — a descriptive solution PROPERTY (not a scored criterion, not a knowledge facet). `saas` = a vendor-hosted subscription offering; `selfHost` = an on-prem / OSS / self-run offering. NOT mutually exclusive (many offer both). Each mode is a deploymentMode tri-state with optional provenance. A generic property-filter (decisions.json filter `target:'property'`, `prop:'deployment.saas'`) narrows the board on it; `unknown` modes surface as research gaps in the Gaps view and are NEVER eliminated by a select-filter (don't eliminate on uncertainty). |
saas
|
→ deploymentMode | Is there a vendor-hosted SaaS/cloud offering (rent, no own server)? |
avail required
|
enum |
Is this mode available? yes|no|unknown — unknown is an open research gap, not a default.yes · no · unknown |
note
|
string | One-line gloss — the concrete offering name / hosting region that establishes the value. |
confidence
|
→ knowledgeState |
Confidence in THIS deployment fact (per-mode).offen · geschätzt · bekannt |
facts
|
array<string> | research-index.json `facts` ids that establish this value — the provenance refs (Plan 19). Resolved in the semantic tier. |
selfHost
|
→ deploymentMode | Is there a self-hosted offering (on-prem / OSS on own server / self-run license)? |
avail required
|
enum |
Is this mode available? yes|no|unknown — unknown is an open research gap, not a default.yes · no · unknown |
note
|
string | One-line gloss — the concrete offering name / hosting region that establishes the value. |
confidence
|
→ knowledgeState |
Confidence in THIS deployment fact (per-mode).offen · geschätzt · bekannt |
facts
|
array<string> | research-index.json `facts` ids that establish this value — the provenance refs (Plan 19). Resolved in the semantic tier. |
costInputs
|
object | Generic cost inputs (setup, recurringYr, basis?, draftToVerify?, …) priced under the Scenario. Instances with a richer cost engine (skischule's typed costModel) carry it in their extension schema instead. PROVENANCE (Plan 23 §G1): the €-figures may carry an optional `facts[]` (vendor pricing-page refs into research-index.json) + `confidence` ('offen'|'geschätzt'|'bekannt') alongside the prose `basis`. With no facts[] the cost renders the honest `unsourced` chip — a draftToVerify estimate, not a sourced price. |
workPackages
|
array<object> | Build/integration packages. Count each once per solution; never sum across solutions. |
name required
|
string | Name of the work package. |
covers
|
array<string> | Use-case/criterion ids this package delivers; resolved semantically. |
effort required
|
→ effortBand | The optimistic/expected/pessimistic person-day band for this package. |
opt required
|
number | Optimistic person-day estimate (best case). |
exp required
|
number | Expected person-day estimate (most likely). |
pess required
|
number | Pessimistic person-day estimate (worst case). |
maintHrsMo
|
number | Maintenance hours/month → Cost bucket ②. |
recommended
|
boolean | The AUTHORED verdict — is this the favoured solution. Register-1/2, never encoded in shell copy. |
verdictNote
|
string | One-line why, shown as the lead. Pairs with recommended. |
tradeoff
|
string | What you give up — one line. |
narrative
|
string | How the solution actually works — descriptive prose (register-2). |
revisedIn
|
string | Round marker (e.g. 'R2') of this solution's last material change — feeds staleness(). |
qualitative
|
object | PERMISSIVE per-project container (Plan 15, Decision 2). Any instance-specific qualitative block lives here — skischule's {verdict,strengths,weaknesses,risks,fit}, ehimare's redTeam[], etc. The base asserts only 'it is an object'; an instance extension MAY pin its keys. Solution-level prose that is genuinely common (narrative/tradeoff/verdictNote) stays as named fields above; everything bespoke goes in here rather than breeding half-used named slots. |