Skip to content

Commit 6937984

Browse files
committed
Refactor documentation for consistency and clarity
1 parent dc06e29 commit 6937984

19 files changed

+119
-114
lines changed

docs/.vitepress/build-meta.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"contractVersion": "1.0.2",
33
"schemaHash": "sha256-07239d0e1a46c781c78b3ae70db52acceeb8dc17e431cd64858e23ad0e61020d",
4-
"buildTime": "2026-02-24T21:38:31.100Z"
4+
"buildTime": "2026-02-24T22:35:08.063Z"
55
}

docs/.vitepress/config.mts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ if (base !== '/' && !base.endsWith('/')) base += '/';
77

88
export default defineConfig({
99
title: 'Majestic Core',
10-
description: 'Technical documentation architecture, API contracts, invariants',
10+
description: 'Technical documentation: architecture, API contracts, invariants',
1111
base,
1212
lang: 'en-US',
1313

1414
head: [
1515
['link', { rel: 'icon', href: `${base === '/' ? '/' : base}logo.svg`, type: 'image/svg+xml' }],
1616
],
1717

18-
appearance: 'force-dark', // Match Svelte app dark only, no toggle
18+
appearance: 'force-dark', // Match Svelte app (dark only, no toggle)
1919

2020
themeConfig: {
2121
logo: '/logo.svg',

docs/.vitepress/theme/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import DefaultTheme from 'vitepress/theme';
22
import { h } from 'vue';
33
import './majestic.css';
44

5-
// Build meta written by prepare.mjs import path relative to theme
5+
// Build meta written by prepare.mjs (import path relative to theme)
66
// @ts-expect-error JSON import
77
import buildMeta from '../build-meta.json';
88

@@ -20,7 +20,7 @@ export default {
2020
},
2121
innerHTML: `
2222
<p style="font-size: 0.75rem; color: var(--vp-c-text-3); margin: 0;">
23-
Contract: ${(buildMeta as { contractVersion?: string }).contractVersion || ''} · Hash: ${(buildMeta as { schemaHash?: string }).schemaHash || ''} · Built: ${(buildMeta as { buildTime?: string }).buildTime || ''}
23+
Contract: ${(buildMeta as { contractVersion?: string }).contractVersion || '-'} · Hash: ${(buildMeta as { schemaHash?: string }).schemaHash || '-'} · Built: ${(buildMeta as { buildTime?: string }).buildTime || '-'}
2424
</p>
2525
`,
2626
}),

docs/.vitepress/theme/majestic.css

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
11
/**
2-
* Majestic brand palette matches Svelte app (majestic-server app.css, tailwind)
2+
* Majestic brand palette: matches Svelte app (majestic-server app.css, tailwind)
33
* Dark theme only. Spec site, not marketing.
44
*/
55
:root,
66
.dark {
7-
/* Backgrounds brand-void, charcoal, ash */
7+
/* Backgrounds: brand-void, charcoal, ash */
88
--vp-c-bg: #0f0d0b;
99
--vp-c-bg-alt: #1a1814;
1010
--vp-c-bg-elv: #252219;
1111
--vp-c-bg-soft: #252219;
1212

13-
/* Text brand-bone, muted, subtle */
13+
/* Text: brand-bone, muted, subtle */
1414
--vp-c-text-1: #e8e2d8;
1515
--vp-c-text-2: #b8b0a4;
1616
--vp-c-text-3: #8a8378;
1717

18-
/* Brand accent espresso gold */
18+
/* Brand accent: espresso gold */
1919
--vp-c-brand-1: #a67b4a;
2020
--vp-c-brand-2: #c9a065;
2121
--vp-c-brand-3: #8e6b3a;
2222
--vp-c-brand-soft: rgba(166, 123, 74, 0.15);
2323

24-
/* Borders subtle bone tint */
24+
/* Borders: subtle bone tint */
2525
--vp-c-border: rgba(232, 226, 216, 0.12);
2626
--vp-c-divider: rgba(232, 226, 216, 0.08);
2727
--vp-c-gutter: rgba(0, 0, 0, 0.4);
2828

29-
/* Default/gray warm neutrals */
29+
/* Default/gray: warm neutrals */
3030
--vp-c-default-1: #8a8378;
3131
--vp-c-default-2: #6a6358;
3232
--vp-c-default-3: #4a4338;

docs/architecture/capability-modeling.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
# Capability Modeling Design Blueprint
1+
# Capability Modeling - Design Blueprint
22

33
**Principle:** Store facts. Compute opinions.
44

55
---
66

7-
## Layer 1 Media Capability Profile (Database)
7+
## Layer 1 - Media Capability Profile (Database)
88

9-
Store normalized fields only. Do NOT store `direct_play_compatible` or `compatibility_reason` those are computed.
9+
Store normalized fields only. Do NOT store `direct_play_compatible` or `compatibility_reason` - those are computed.
1010

1111
### Video
1212
- `video_codec` (h264, hevc, vp9, av1)
@@ -30,11 +30,11 @@ Store normalized fields only. Do NOT store `direct_play_compatible` or `compatib
3030
- `probe_state` (`ok` | `failed` | `unknown`)
3131
- `probe_error` (short string when failed)
3232
- `probe_version` (optional, for invalidation)
33-
- `probe_last_run_at` (when probe last ran observability for "why is this unknown?")
33+
- `probe_last_run_at` (when probe last ran - observability for "why is this unknown?")
3434

3535
---
3636

37-
## Step 1 Probe Module
37+
## Step 1 - Probe Module
3838

3939
**Location:** `src/lib/server/probe/ffprobe.ts`
4040

@@ -69,7 +69,7 @@ Store normalized fields only. Do NOT store `direct_play_compatible` or `compatib
6969

7070
---
7171

72-
## Step 2 When to Probe
72+
## Step 2 - When to Probe
7373

7474
On scan:
7575
- **New file** → probe
@@ -84,7 +84,7 @@ If probe fails:
8484

8585
---
8686

87-
## Step 3 Device Profile (Apple TV)
87+
## Step 3 - Device Profile (Apple TV)
8888

8989
Static object, versioned:
9090

@@ -114,7 +114,7 @@ type DeviceProfile = {
114114
115115
---
116116
117-
## Step 4 Evaluate Function
117+
## Step 4 - Evaluate Function
118118
119119
Pure function:
120120
```ts

docs/architecture/curated-api.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
# Majestic Curated API Cloudflare Shared Data Layer
1+
# Majestic Curated API - Cloudflare Shared Data Layer
22

33
> **DEPRECATED.** The metadata/enrichment layer described here is superseded by [majestic-canon](../strategy/authoritative-data-distribution-dissection.md#15-canon-architecture--three-layers). Canon uses authoritative data distribution (signed patch packs) instead of live API. This document is retained for historical context and optional live-assist fallback design. **See majestic-canon for the canonical dataset source.**
44
55
---
66

77
**Purpose (historical):** Centralize movie, edition, person, and studio data for all paid Majestic server installs. Prior matched movies and editions become available to every paid instance, reducing TMDB/OMDb lookups and improving edition matching accuracy.
88

9-
**Context:** TMDB models Movie as atomic. Multi-version (theatrical vs director's cut, etc.) has been in their backlog since 2019it requires a parent/child ontology they don't have. Majestic designed Movie → Edition from day one. The Curated API was the interim design. **majestic-canon** is the target: patch-based distribution, not live API.
9+
**Context:** TMDB models Movie as atomic. Multi-version (theatrical vs director's cut, etc.) has been in their backlog since 2019 - it requires a parent/child ontology they don't have. Majestic designed Movie → Edition from day one. The Curated API was the interim design. **majestic-canon** is the target: patch-based distribution, not live API.
1010

1111
**Status:** Deprecated. Superseded by majestic-canon. Optional live-assist fallback only (under 5% of lookups).
1212

@@ -312,12 +312,12 @@ Not required at launch. Build when telemetry schema exists and installs are live
312312
## 11. Implementation Order
313313

314314
1. **Design doc** (this document) ✓
315-
2. **Roadmap phase** Add Phase 1.5 to ROADMAP
316-
3. **curatedApiClient** Minimal client: `lookupByTitleYear`, `lookupByUpc`. No-op when unconfigured.
317-
4. **Scanner integration** Call client before local DB when parsing filename/folder. Fallback unchanged.
318-
5. **Cloudflare Workers** Deploy read-only API. D1 or R2 backend. Auth middleware.
319-
6. **Edition Validation 100** Seed dataset. Verify matching correctness.
320-
7. **Barcode integration** Call `GET /editions/upc/:upc` in barcodeService before UPCMDB.
315+
2. **Roadmap phase** - Add Phase 1.5 to ROADMAP
316+
3. **curatedApiClient** - Minimal client: `lookupByTitleYear`, `lookupByUpc`. No-op when unconfigured.
317+
4. **Scanner integration** - Call client before local DB when parsing filename/folder. Fallback unchanged.
318+
5. **Cloudflare Workers** - Deploy read-only API. D1 or R2 backend. Auth middleware.
319+
6. **Edition Validation 100** - Seed dataset. Verify matching correctness.
320+
7. **Barcode integration** - Call `GET /editions/upc/:upc` in barcodeService before UPCMDB.
321321

322322
---
323323

@@ -343,4 +343,4 @@ Curated API does not compromise foundational principles. Keep it boring. Keep it
343343
| **Dataset corrections retroactively alter identity** | Never silently mutate identity_hash or UPC normalization. Dataset improvements must be additive, not destructive. Version-signal any logic change. |
344344
| **Latency creep** | 500ms is hard. Not advisory. If lookup drifts to 900ms, 1.2s, 2s, scanner UX degrades. Enforce at client. |
345345
| **Curated API becomes "better TMDB"** | Stay narrow. Store identity-critical edition data, canonical film linkage, deterministic match keys. Do not become a general-purpose metadata mirror, popularity engine, or review aggregation system. Let TMDB chase popularity. Majestic chases correctness. |
346-
| **Identity vs engagement data mixing** | Alternate overviews, cut-specific runtime, cast differencesfine if identity-critical. Do not store user taste signals, popularity adjustments, ranking hints, or behavioral metadata. The moment you mix identity with engagement, you blur the contract. Curated layer = edition correctness. Nothing else. |
346+
| **Identity vs engagement data mixing** | Alternate overviews, cut-specific runtime, cast differences - fine if identity-critical. Do not store user taste signals, popularity adjustments, ranking hints, or behavioral metadata. The moment you mix identity with engagement, you blur the contract. Curated layer = edition correctness. Nothing else. |

docs/architecture/edition-grouping.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Edition Grouping Design
1+
# Edition Grouping - Design
22

33
**Principle:** Server owns truth. Client renders it.
44

@@ -8,7 +8,7 @@ Edition grouping is the first feature that makes someone say: "Wait… this actu
88

99
## What It Must Do
1010

11-
1. **Group by `movie_id`** Multiple media files for the same movie become one row with multiple editions.
11+
1. **Group by `movie_id`** - Multiple media files for the same movie become one row with multiple editions.
1212

1313
2. **Editions listed with:**
1414
- Edition label (override > computed > canonical)
@@ -81,14 +81,14 @@ Priority: override > computed > canonical (when variants exist) > format.
8181

8282
Reuse `resolveEditionLabelForPoster` logic where applicable.
8383

84-
**Critical:** Edition labels must be **deterministic, cached, and not re-derived on every scan** from heuristics. If filename/folder parsing is used, it must produce a **normalized, stored label** not a live guess. You're building a library, not a regex experiment.
84+
**Critical:** Edition labels must be **deterministic, cached, and not re-derived on every scan** from heuristics. If filename/folder parsing is used, it must produce a **normalized, stored label** - not a live guess. You're building a library, not a regex experiment.
8585

8686
**Label survival:** Labels must survive file deletion and re-add. If a file is removed and later re-imported with the same fingerprint → same edition → same label. Label storage must be anchored to **media_file identity** (fingerprint or media_file_id), not to path. If labels depend on current folder path and get regenerated on re-import, you introduce drift.
8787

8888
For media files without disc_edition linkage:
8989

9090
- Store derived label (e.g. in media_file or a join table) at scan/match time
91-
- Anchor to fingerprint or media_file_id not path
91+
- Anchor to fingerprint or media_file_id - not path
9292
- Fallback: "Edition 1", "Edition 2" (deterministic by media_file_id)
9393

9494
---
@@ -103,7 +103,7 @@ Criteria (in order):
103103
2. Resolution descending (4K before 1080p)
104104
3. media_file_id ascending (tie-breaker)
105105

106-
**What we avoid:** Bitrate comparisons, "best HDR wins," audio heuristics, device-dependent reordering. If ordering depends on device, the UI feels unstable the same movie reorders when device changes. Canonical first. Always.
106+
**What we avoid:** Bitrate comparisons, "best HDR wins," audio heuristics, device-dependent reordering. If ordering depends on device, the UI feels unstable - the same movie reorders when device changes. Canonical first. Always.
107107

108108
---
109109

@@ -138,9 +138,9 @@ You do not want a movie to show "Playable" while one edition is flagged as corru
138138

139139
```
140140
Editions
141-
• Theatrical 4K HDR10 · Direct Play Ready
142-
• Director's Cut 1080p SDR · Direct Play Ready
143-
• Steelbook DV P7 · Not Supported on Apple TV
141+
• Theatrical - 4K HDR10 · Direct Play Ready
142+
• Director's Cut - 1080p SDR · Direct Play Ready
143+
• Steelbook - DV P7 · Not Supported on Apple TV
144144
```
145145

146146
Each selectable. Each with capability summary + compatibility status.
@@ -154,10 +154,10 @@ Default selection = first (canonical). User can change. Play uses selected editi
154154
## What Not to Do
155155

156156
- **No silent auto-picking** when multiple editions exist
157-
- **No client-side grouping** server aggregates
158-
- **No grid performance degradation** aggregation is a server concern
159-
- **No guessing** explicit selection required
160-
- **No "best available" collapse** never auto-play or auto-select "best edition on this device." That is how you become Plex again. Majestic does not optimize away choice. It exposes it.
157+
- **No client-side grouping** - server aggregates
158+
- **No grid performance degradation** - aggregation is a server concern
159+
- **No guessing** - explicit selection required
160+
- **No "best available" collapse** - never auto-play or auto-select "best edition on this device." That is how you become Plex again. Majestic does not optimize away choice. It exposes it.
161161

162162
---
163163

@@ -169,11 +169,11 @@ Default selection = first (canonical). User can change. Play uses selected editi
169169

170170
## Implementation Order
171171

172-
1. **Schema (if needed):** Edition label storage ensure derived labels are cached, not recomputed per request
172+
1. **Schema (if needed):** Edition label storage - ensure derived labels are cached, not recomputed per request
173173
2. **API:** New `/library` response shape with `editions` array, `default_edition_index`
174-
3. **API:** Aggregation logic group media_files by movie_id, build editions array
174+
3. **API:** Aggregation logic - group media_files by movie_id, build editions array
175175
4. **API:** Edition label resolution (from stored/cached source), canonical ordering
176-
5. **API:** Badge priority worst status across editions
176+
5. **API:** Badge priority - worst status across editions
177177
6. **Apple TV:** Update model for new response shape
178178
7. **Apple TV:** Grid uses movie-level items (one poster per movie)
179179
8. **Apple TV:** Detail page shows Editions section when count > 1

docs/architecture/identity-layer.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Identity Layer
22

3-
The identity layer defines how Majestic models ownership and edition truth. Edition identity is derived from content-derived inputsnever from paths, filenames, or mutable metadata.
3+
The identity layer defines how Majestic models ownership and edition truth. Edition identity is derived from content-derived inputs - never from paths, filenames, or mutable metadata.
44

55
## Principles
66

docs/architecture/identity-matching.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ Majestic matches media files to movies using a deterministic priority order. The
44

55
## Resolution Order
66

7-
1. **Per-file `.majestic.json`** `{filename}.majestic.json` in the same directory (e.g. `A New Standard.mkv.majestic.json`). Overrides directory-level for this file only. Use when a shared extras folder contains files from different movies.
7+
1. **Per-file `.majestic.json`** - `{filename}.majestic.json` in the same directory (e.g. `A New Standard.mkv.majestic.json`). Overrides directory-level for this file only. Use when a shared extras folder contains files from different movies.
88

9-
2. **Directory-level `.majestic.json`** `.majestic.json` in the file's directory. Applies to all files in that folder. Written automatically when you resolve or re-match in the UI.
9+
2. **Directory-level `.majestic.json`** - `.majestic.json` in the file's directory. Applies to all files in that folder. Written automatically when you resolve or re-match in the UI.
1010

11-
3. **Filename parsing** `Title (Year).mkv`, `Title (Year) [Steelbook].mkv`, etc.
11+
3. **Filename parsing** - `Title (Year).mkv`, `Title (Year) [Steelbook].mkv`, etc.
1212

13-
4. **Folder name parsing** Parent directory name.
13+
4. **Folder name parsing** - Parent directory name.
1414

15-
5. **User confirmation** Unresolved or ambiguous matches appear in Settings → Unresolved.
15+
5. **User confirmation** - Unresolved or ambiguous matches appear in Settings → Unresolved.
1616

1717
## What `.majestic.json` Contains
1818

@@ -47,10 +47,10 @@ The matcher still **reads** `.majestic.json` if present; it just **skips writing
4747

4848
## Why This Design
4949

50-
- **DB is source of truth** Survives rescans, renames, restarts. Scanner respects existing `media_file.movie_id`.
51-
- **Per-file override** Shared extras folders (e.g. `Extras/` with files from multiple movies) can use per-file `.majestic.json` to avoid directory-level overreach.
52-
- **No file mutation** We never modify the media file itself. Only metadata.
53-
- **Transparent** A visible JSON file in the folder. Users who organize by folder can inspect or edit it.
50+
- **DB is source of truth** - Survives rescans, renames, restarts. Scanner respects existing `media_file.movie_id`.
51+
- **Per-file override** - Shared extras folders (e.g. `Extras/` with files from multiple movies) can use per-file `.majestic.json` to avoid directory-level overreach.
52+
- **No file mutation** - We never modify the media file itself. Only metadata.
53+
- **Transparent** - A visible JSON file in the folder. Users who organize by folder can inspect or edit it.
5454

5555
## Target Audience
5656

0 commit comments

Comments
 (0)